Skip to content

[contract] Tiered execution — TierDefinition + TierSelector + DegradationPolicy #201

@stackbilt-admin

Description

@stackbilt-admin

Summary

Charter has accumulated 6 independent tiered execution systems with no unified contract, no shared invariants, and no governance for declaring a new tier system. Two external repos (colonyos, llm-providers) independently arrived at the same structural pattern — confirming this is a load-bearing architectural primitive, not an implementation detail.

Charter's Internal Fragmentation (Primary Case)

Six independent tier systems exist today with no shared shape:

System Tiers Location
OntologySensitivityTier 6 (public → secrets) validate/ontology.ts:19–25
AppMode 5 (GOVERNANCE → BRIEF) types/index.ts:13
ChangeClass 3 (SURFACE → CROSS_CUTTING) classify/index.ts:45–105
CommitRiskLevel 3 (LOW → HIGH) git/risk.ts:47–78
Urgency 4 (LOW → CRITICAL) types/index.ts:25
Complexity 5 (TRIVIAL → EPIC) types/index.ts:26

Charter has ceiling/pass-warn-fail logic (validator.ts:93–97) but no unified tier schema, no shared constraint rule shape, no transition/recovery policies.

External Corroboration

colonyos (sha:a13570c3) — tarot/cognitive-law.ts

Zero-inference, pure deterministic signal counting:

Property Detail
Trigger conditions deck_fatigue, circuit_open, consecutive_defer (persistent); high_shadow_density, evaluation_failure, facts_malformed (ephemeral)
Named tiers NORMAL (0 signals), ALTERNATE1 (1), ALTERNATE2 (2), DIRECT (3+)
What's constrained Autonomy ceiling (each tier reduces ceiling by 0/1/2/3 rungs)
Selection if (n===0) NORMAL; if (n===1) ALT1; if (n===2) ALT2; return DIRECT
Hysteresis Degrade immediately; recover one step per COGNITIVE_LAW_RECOVERY_TICKS stable ticks
Transitions logged Yes, bounded to 10 entries

Airbus-style degradation: immediate on signal count, asymmetric recovery, ceiling bounded by Commander at all times.

llm-providers (sha:fb20e0ea) — src/model-catalog.ts + src/factory.ts

Pure deterministic request inspection + static scoring weights:

Property Detail
Trigger conditions Request shape (vision → tools → token count → default); caller hint via request.metadata.useCase
Named tiers COST_EFFECTIVE, HIGH_PERFORMANCE, BALANCED, TOOL_CALLING, LONG_CONTEXT, VISION
What's constrained Model ranking in fallback chain
Selection inferUseCaseFromRequest() + rankModels() weight matrix; caller override takes precedence
Hysteresis None — each request is independent

Structural comparison

Property colonyos llm-providers charter (6 systems)
Selection mechanism Deterministic (signal count) Deterministic (request shape) Deterministic (various)
What is constrained Autonomy ceiling Model ranking Governance routing
Named tiers Yes (4) Yes (6) Yes (3–6 each)
Caller override No (bounded by Commander) Yes (metadata hint) Varies
Hysteresis/recovery Yes (asymmetric) None None
Transitions logged Yes (bounded) No No
Unified contract No No No

Proposed 3-Contract Set

1. TierDefinition — declares a tier system

interface TierDefinition<T extends string> {
  name: string;                          // e.g. 'CommitRiskLevel'
  tiers: readonly T[];                   // ordered, finite union — no dead tiers allowed
  descriptions: Record<T, string>;       // semantic per-tier description
  constraints: Record<T, TierConstraint>; // what is constrained and by how much
  mode: 'additive' | 'absolute';         // whether tiers stack or override
}

2. TierSelector — how tier selection must work

interface TierSelector<T extends string, Input> {
  // Deterministic: same input → same tier. No randomness, no inference.
  select(input: Input, hint?: T): T;

  // Tier selection occurs before constraint application — never post-hoc.
  // Transitions must emit an observable event.
  onTransition?: (from: T, to: T, reason: string) => void;
}

Invariants:

  • Deterministic given same inputs (no randomness, no inference)
  • Caller-overridable via explicit hint (hint takes precedence over inferred)
  • Tier selection occurs before constraint application
  • Transitions are observable (event emitted on tier change)
  • All declared tiers are reachable (no dead tiers)

3. DegradationPolicy — extension for health-signal-driven systems

interface DegradationPolicy<T extends string> extends TierSelector<T, number> {
  // Degradation is immediate: signal detected → tier applied same tick
  degrade(signalCount: number): T;

  // Recovery is asymmetric: one step at a time, N consecutive stable ticks required
  recoveryTicks: number;

  // Ceiling bounded by external config — never self-granted
  ceiling: T;

  // Floor — minimum tier regardless of signals
  floor: T;
}

Invariants:

  • Degradation is immediate (signal detected → tier applied same tick)
  • Recovery is asymmetric: one step at a time, requires N consecutive stable ticks
  • Floor bounded by system minimum; ceiling bounded by external config — not self-granted
  • Transition log retained (bounded size acceptable)

Required Work

  1. Extract shared TierDefinition shape — charter's 6 existing systems each declare one
  2. Enforce TierSelector invariants at the contract layer (deterministic, no post-hoc, observable)
  3. DegradationPolicy is opt-in — only tier systems driven by health signals need it (colonyos cognitive-law.ts is the reference implementation)
  4. Refactor charter's 6 internal tier systems to use the unified shape — no behavior change, interface alignment only

Why P2

  • Not a blocker — charter functions today — but the fragmentation compounds: each new governance feature adds a 7th independent system
  • colonyos and llm-providers already comply structurally; making the contract explicit lets new implementations be verified at type-check time
  • DegradationPolicy in particular is valuable for any charter mode that needs circuit-breaker / autonomy-ceiling behavior (see [contract] Authority-gated governance — propose→gate→commit invariant #200)

Source

Convergence Evidence — 2026-W21 (convergence-evidence-2026-W21-colonyos-llm-providers, F2, high confidence). Verified by 3 Haiku subagent deep reads on 2026-05-23. Post-fire eval confirmed structural match is real despite domain difference (autonomy vs model selection vs governance routing).

Related: #200 (authority-gated governance)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestpriority:p2Nice to have this cycletype:featureNew capability or extension point

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions