Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .verify-floor.json

Large diffs are not rendered by default.

77 changes: 62 additions & 15 deletions ADDING_CAPABILITIES.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,12 @@ Enforced by `capability_admission.py` + `test_capability_admission.py`. Run **be
python3 capability_admission.py --preflight '{"capability_id":"capability:my-thing", ...}'
```

`preflight` answers the five declarable requirements immediately and returns the other three as
explicit **obligations** rather than silently skipping them — because silently skipping is how they
got skipped.
`preflight` answers the six declarable requirements immediately — including findability, which is the
one most worth learning before the code exists — and returns the other three (caller, heartbeat,
fixture) as explicit **obligations** rather than silently skipping them, because silently skipping is
how they got skipped.

### The eight parts
### The nine parts

| # | Requirement | The failure it prevents |
|---|---|---|
Expand All @@ -57,23 +58,68 @@ got skipped.
| 6 | **A kill switch** | An undeclared switch cannot be found in an emergency. |
| 7 | **A rollback path** | — |
| 8 | **An expiry or a cadence** | Nothing may sit unexamined forever; that is how dormancy survives two audits. |
| 9 | **A surface that can OFFER it** (`findable`) | FM10 — 22 of 43 capabilities were bound to no surface at all, so nothing could offer them and no amount of running could produce evidence for them. All 43 had passed admission. The rule existed — as prose, in this file. |

Enforcement binds on capabilities registered from 2026-08-21. The 36 pre-gate capabilities are
reported as **legacy debt on every run** and do not fail the suite — a gate that is red on arrival
gets switched off, and then it protects nothing. Legacy rows still print exactly what they are
missing; the exemption lives on the row, never inside the predicates, so debt can never read as
compliance.
Enforcement binds on capabilities registered from 2026-08-21, and **each requirement carries its own
date**: findability binds from 2026-08-23 (`capability_admission.REQUIREMENT_ENFORCED_FROM`). The
pre-gate capabilities are reported as **legacy debt on every run** and do not fail the suite — a gate
that is red on arrival gets switched off, and then it protects nothing. The same reasoning applies to
a requirement added later, which is why the date is per-requirement rather than one global cutoff.
Legacy and pre-cutoff rows still print exactly what they are missing; the exemption lives on the row,
never inside the predicates, so debt can never read as compliance.

### Say which surfaces bind it (or why none does)
### Requirement 9 in detail: which surface can OFFER it (or why none can)

The eight parts make a capability *invocable and observable*. They do not make it *findable*. A
capability nothing binds is offered from a 40-plus catalogue queried generically, which is the
The first eight parts make a capability *invocable and observable*. None of them makes it *findable*.
A capability nothing binds is offered from a 40-plus catalogue queried generically, which is the
measured 13.62% selection condition — built, admitted, and still not chosen.

**This was prose in this file until 2026-08-23, and the measurement is what a prose rule is worth
here: 37 of 43 capabilities had no usefulness evidence, and 22 of those were bound to no surface at
all.** It is now the ninth predicate in `capability_admission.REQUIREMENTS`, and
`test_capability_admission.py` fails on it.

So when adding or reviving one, name its surfaces in `capability_advisor.SURFACE_BINDINGS` — the
skills or automations for which it should be in the small declared set — with a one-line reason each,
or state that no surface binds it yet and what would change that. Keep a bound set to 3–7 entries;
past ~10 it reintroduces the problem the binding removes, and a selftest enforces the ceiling.
skills or automations for which it should be in the small declared set — with a one-line reason each.
Keep a bound set to 3–7 entries; past ~10 it reintroduces the problem the binding removes, and a
selftest enforces the ceiling. Run `--preflight` first: findability is **declarable**, so the answer
arrives before the code is written rather than after.

**Three sub-causes, because the fixes differ.** The predicate names which one applies:

| cause | what it means | the fix |
|---|---|---|
| `bound_nowhere` | no surface declares it | add one entry to a surface's 3–7, with its reason |
| `bound_to_unconsulted_surface` | every binding names a surface no caller ever consults | bind a surface listed in `capability_advisor.CONSULT_SITES`, or make that surface consult |
| *(invoked without attribution)* | a surface runs the entrypoint directly and the invocation is credited to nobody | **not checked** — see below |

`CONSULT_SITES` is the other half of a binding, and until 2026-08-23 nothing declared it: `ci` bound
two capabilities and no caller anywhere consults a `ci` surface, while `opener-lane` and `closer-lane`
bind ten between them and both lane prompts consult with **no `--surface` at all**, so the declared
set never reaches the caller it was written for. A declared consult site is a falsifiable claim about
a file — the selftest opens it. Absent on this machine means *unverified*, never refuted; present and
no longer naming its surface is DRIFT and fails.

**A surface has exactly three honest states, and the selftest enforces it**: a caller consults it
(`CONSULT_SITES`), it deliberately binds nothing (`NO_BINDING` with the reason), or it holds bindings
nothing can reach and that is *recorded* (`KNOWN_UNCONSULTED`, with the reason AND the fix). A fourth
state — bindings nothing can reach and nobody wrote down — is what `ci` was, and it is invisible until
a capability is stranded on it, so it now fails `capability_advisor._selftest_findability` naming the
SURFACE rather than only the capability. `KNOWN_UNCONSULTED` is a record, not a waiver: capabilities
bound only there still fail requirement 9. And a fixed entry may not linger — the same selftest fails
on a stale one, because a cached reason that outlives its evidence is this workspace's named defect.

**What requirement 9 deliberately does NOT check**, stated here because a gate that cannot say what
it skipped is the same defect as one that cannot say what would clear it: a surface that invokes the
entrypoint *directly* without surface attribution. The `orchestrate` skill already runs `capacity.py`
while `windowed-capacity-policy`'s heartbeat sits behind `ORCH_CAPABILITY_HEARTBEATS`, which only a
live tick sets — so it is used and entirely uncredited.
`capability_activation_audit.heartbeat_reachable` was checked first and answers a different question:
it reports that row `reachable` via `orchestrate.sh (CLI)`, because it asks whether *some* driver
reaches the heartbeat, not whether *this surface's* invocation is attributed to the surface. Deciding
that needs the surface's own prompt, which lives outside this repository. Likewise
`repo-audit:fix` is *named* by its skill and never *entered* by a run; only trial records can show
that, never a table of files.

Binding is prioritisation, not concealment: an unbound capability is still returned, ranked after the
bound ones. That is deliberate — a capability that could never be selected could never earn the
Expand Down Expand Up @@ -122,3 +168,4 @@ write it down with the criterion that would change it.
| FM7 circular measurement | the activation/recurrence split |
| FM8 tests asserting bugs | fixture-must-not-error assertion; synthetic-fixture rule |
| FM9 wrong tree | mirror re-run after every sync |
| FM10 admitted but unofferable | `capability_admission.req_findable` (requirement 9), plus `capability_advisor.consulting_surfaces()` for the surfaces that strand a binding |
59 changes: 56 additions & 3 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,9 @@ the two axes as one. They are orthogonal:
capability routinely spans both (`adversarial-review` is role judgment, invoked by a rail gate,
recorded over a deterministic acceptance edge).

The eight admission parts (`ADDING_CAPABILITIES.md`) are **not** the definition of a capability. They
are what must be present for one to work with this system — invocable, observable, improvable.
The nine admission parts (`ADDING_CAPABILITIES.md`) are **not** the definition of a capability. They
are what must be present for one to work with this system — invocable, observable, findable,
improvable.

**Two kinds, and their measurement stories differ.** *Workflow* capabilities run implementation code
and have a definable success condition, so effectiveness is a pass/fail rate. *Sub-agent* capabilities
Expand All @@ -167,7 +168,7 @@ are ordered by when each starts working:

| Layer | Mechanism | Works from |
|---|---|---|
| 1 | `capability_advisor.SURFACE_BINDINGS` — declared, per surface, 3–7 entries, each with its reason; plus `CAPABILITY_PRECONDITIONS`, which explains an offer without changing it | day one; no classifier, no history |
| 1 | `capability_advisor.SURFACE_BINDINGS` — declared, per surface, 3–7 entries, each with its reason; `CONSULT_SITES`, which declares who actually ASKS at each surface; plus `CAPABILITY_PRECONDITIONS`, which explains an offer without changing it | day one; no classifier, no history |
| 2 | `capability_propensity.rank` — orders *within* the bound set by measured usefulness | first resolved trials |
| 3 | `capability_advisor.learned_associations` — corrects the table from what a surface actually reaches for | once observations accumulate |

Expand All @@ -178,6 +179,58 @@ committed table is the seed (tool); instance promotions live in the ledger (evid
bound set and flagged `bound: false`. A concealed capability could never be selected, so it could
never earn the evidence that would bind it — the gate would starve its own drain.

**And a binding is only half of layer 1: `CONSULT_SITES` is the other half, and nothing declared it
until 2026-08-23.** `SURFACE_BINDINGS` says which capabilities a surface should be offered; nothing
said which surfaces are ever ASKED, and the two are independent — from a capability's point of view,
a binding to a surface no caller consults is indistinguishable from no binding at all. Measured over
the 43-row ledger: `ci` bound two capabilities and no caller anywhere consults a `ci` surface;
`opener-lane` and `closer-lane` bind ten between them and both lane prompts consult the advisor with
**no `--surface`**, so `binding_for("")` returns `{}` and the declared set never reaches the caller it
was written for. `repo-audit` is the control case — never consulted under its bare name, and
correctly so, because every consult happens at a phase key whose resolution merges the parent's
entries. So "not consulted" is a defect only for a key that is not a PREFIX of a consulted key.
A consult site is a **falsifiable claim about a file**: the selftest opens it. Present-and-no-longer-
naming-its-surface is DRIFT and fails; absent on this machine is *unverified*, never refuted — the
same "no ledger, no verdict" rule `capability_admission.commitments()` uses, because treating absence
as refutation would strand every skill-bound capability on a fresh clone.

**A surface therefore has exactly three declared states, and a fourth is a selftest failure.** It is
consulted (`CONSULT_SITES`), it deliberately binds nothing (`NO_BINDING` with the reason), or it holds
bindings nothing can reach and that is recorded with the reason and the fix (`KNOWN_UNCONSULTED` —
currently `opener-lane` and `closer-lane`, whose fix is a `--surface` flag in a lane TOML outside this
repository). Bindings nothing can reach that nobody wrote down is the fourth state, it is what `ci`
was, and it is invisible until a capability is stranded on it — so it now fails naming the SURFACE,
not just the capability. `KNOWN_UNCONSULTED` is a record and not a waiver: a capability bound only
there still fails requirement 9. A fixed entry may not linger either; a stale one fails, because a
cached reason outliving its evidence is the prose-cache defect under a different hat.

**Findability is the ninth admission requirement (2026-08-23), because the eight before it make a
capability invocable and observable and none of them makes it findable.** 37 of 43 capabilities had
no usefulness evidence and 22 of those were bound to no surface, so nothing could offer them and no
amount of running could produce evidence for them — every one had passed admission, and the rule
against it existed as prose in the document that argues prose does not survive the next session.
`capability_admission.req_findable` consumes `capability_advisor.surfaces_binding` (the inverse of
`binding_for`, so ONE resolver) and `consulting_surfaces()`, and it distinguishes `bound_nowhere` from
`bound_to_unconsulted_surface` because the fixes differ: declare a surface, versus bind a consulted
one or make the surface consult. A capability a rail invokes UNCONDITIONALLY rather than offers is
exempt by declaration — `findability_category: no_surface` plus a rationale in
`capabilities.KNOWN_DECLARATIONS`, both halves required, which is where `capability-admission-gate`
and `docs-drift-fix-agent` now sit instead of on a `ci` surface nothing consults.

Two things it deliberately does **not** decide, named rather than omitted. A surface that invokes the
entrypoint DIRECTLY without surface attribution: the `orchestrate` skill already runs `capacity.py`
while `windowed-capacity-policy`'s heartbeat sits behind `ORCH_CAPABILITY_HEARTBEATS`, which only a
live tick sets, so the capability is used and entirely uncredited.
`capability_activation_audit.heartbeat_reachable` answers a different question — it calls that row
`reachable` via `orchestrate.sh (CLI)`, because it asks whether *some* driver reaches the heartbeat,
not whether *this surface's* invocation is attributed to the surface — and deciding it needs the
surface's own prompt, which lives outside this repository. And a surface that is NAMED but never
ENTERED (`repo-audit:fix`, which the skill's table lists and no audit run reaches, since an audit ends
at phase 5 and hands implementation to the lanes): only trial records can show that, never a table of
files. Enforcement is per-requirement dated (`REQUIREMENT_ENFORCED_FROM`) so the 43 pre-existing rows
are reported as drainable debt instead of failing the suite; the report prints the debt, its causes,
the surfaces that strand a binding, and the drainable count beside it.

**And a fourth input, orthogonal to all three: the per-repo contraindication.** The three layers above
rank a capability by how well it fits the SURFACE. None of them can say *this tool does not work
against this particular repository* — a fact that lives in the repo's own record, not in the ledger.
Expand Down
28 changes: 20 additions & 8 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ gates / feedback surfaces — and "capability" is a different axis entirely.
is FOR. One capability routinely spans both (`adversarial-review` is role judgment invoked by a
rail gate and recorded over a rail acceptance edge).
- **The admission parts are not the definition of a capability.** A caller, heartbeat, outcome path,
fixture, kill switch, rollback, expiry and dedup finding are the components that must be present
for a capability to WORK WITH THIS SYSTEM — to be invocable, observable and improvable. Do not
describe a capability by its admission parts; describe it by what it does, then check the parts.
fixture, kill switch, rollback, expiry, dedup finding and a surface that can offer it are the
components that must be present for a capability to WORK WITH THIS SYSTEM — to be invocable,
observable, findable and improvable. Do not describe a capability by its admission parts; describe
it by what it does, then check the parts.

**Two kinds of capability, and their measurement stories differ — do not average across them:**

Expand All @@ -68,7 +69,12 @@ Three layers, ordered by when each starts working — see `ARCHITECTURE.md` for

1. **`capability_advisor.SURFACE_BINDINGS`** — declared per surface, 3–7 entries, each carrying its
reason. Works on day one with no classifier and no history. When adding or reviving a capability,
say which surfaces bind it, or say why none does.
say which surfaces bind it, or say why none does — **and this is now the ninth admission
requirement, not advice**: `capability_admission.req_findable` fails a new capability that no
surface can offer, distinguishing `bound_nowhere` from `bound_to_unconsulted_surface`, because the
fixes differ. A binding is only half of it; `capability_advisor.CONSULT_SITES` declares which
surfaces a caller actually NAMES, and a binding to a surface nobody consults is indistinguishable
from no binding at all.
2. **`capability_propensity.rank`** — orders *within* the bound set by measured usefulness.
3. **`capability_advisor.learned_associations`** — corrects the table from observed use.

Expand Down Expand Up @@ -169,10 +175,16 @@ after it was written.
**`ADDING_CAPABILITIES.md` is the procedure, and it is ENFORCED.** Run
`python3 capability_admission.py --preflight '<spec json>'` before writing code: a capability must
arrive with a dedup finding, a caller, a heartbeat, a recurrence fixture, an outcome path, a kill
switch, a rollback and an expiry-or-cadence. `test_capability_admission.py` fails the suite
otherwise, and also fails on a citation to a dated record that does not exist or a deadline that
passed with no record. That doc lists the nine failure modes behind those eight requirements; read
it before adding or reviving a capability.
switch, a rollback, an expiry-or-cadence, **and a surface that can offer it**.
`test_capability_admission.py` fails the suite otherwise, and also fails on a citation to a dated
record that does not exist or a deadline that passed with no record. That doc lists the failure modes
behind those nine requirements; read it before adding or reviving a capability.

The ninth is the newest and the one `--preflight` exists for: findability is **declarable**, so a
capability no surface will ever offer is a design answer you get before writing code rather than a
second project afterwards. Each requirement carries its own enforcement date
(`capability_admission.REQUIREMENT_ENFORCED_FROM`), because a rule added later is red on arrival for
everything that predates it, and a gate red on arrival gets switched off.

For model/profile or compiler work, also inspect `execution_profiles.py`,
`completion_event_adapter.py`, `pattern_miner.py`, `capability_compiler.py`, `evidence_schema.py`,
Expand Down
Loading
Loading