task: the tier floor announces WHY it fired, and a design decision can appeal it on the record (DIVE-2089) - #252
Merged
Conversation
…l it on the record (DIVE-2089) The T2 category floor reads SUBJECT MATTER as risk and picks the gate's audience from it. dev3's tier-1 sizing gate — "should an agent's right to act derive from the credentials it holds, or from a declared clearance level?" — was forced hard-human because the ask contains "credentials" and "privileged". It discusses credential handling as a design question and performs no credential operation. Two things made that worse than a mis-tier. It was SILENT: dev3 found out by re-reading their own filed gate. And the workaround was to re-file with neutral wording, which works, teaches the fleet to launder vocabulary to reach the right audience, and leaves no trace of having been done. - The floor now names the matched term, on the result and on stderr at file time. For a decision gate it states the sanctioned appeal and says not to reword the ask. - --discusses="<why>" appeals a floor that fired on subject matter. A DECLARATION, not a sixth guesser: no phrasing reliably separates "discussing X" from "doing X". Unlike a reworded ask it is attributable, shown to the reviewer, and audited applied OR refused. - Four guards: --type=decision only; only on an actual over-fire; never for money / outbound comms / irreversible infra; downgrades only to a LEAD-routed tier 1. An explicit --tier=2 vetoes it; refusals are loud. Not a keyword class, deliberately — DIVE-2099 note 1: inferring this from more vocabulary reproduces the bug with the polarity reversed, where a false negative routes a real secret gate away from the human. No existing gate changes tier: nothing moves without the new flag, which discharges the DIVE-2146 precondition by construction. Measured while checking it — the DIVE-2146 self-restart gate never tripped the floor; it reached the human via an explicit --tier=2 re-file. Kept as a live assertion so a future widening of the floor goes red there first. tests/gate_floor_declared_discussion_unit.sh — 36 assertions, every arm on the ask axis AND the TITLE axis (DIVE-1957). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…reads (DIVE-2089)
olivia's iteration-1 reject, and it was right. The floor announces on two
surfaces — the stderr warn at file time, and the `ok ... ${floor_note}`
result line — and all 36 assertions called cmd_task_need with stdout
suppressed, grepping only stderr. The result line had ZERO assertions.
Proved by mutation: stripping ${floor_term:+: matched '$floor_term'} out
of floor_note left 36 passed, 0 failed.
That is the wrong surface to leave unguarded. It is the one defect 2's own
discovery story runs through — dev3 found the escalation by RE-READING
their filed gate, not by catching a warn that had already scrolled past —
and the iteration-1 build note quoted this very line as its before/after
evidence.
There were TWO reasons it was unasserted, and the second is the one that
bites. The suite sets JSON_MODE=1 globally, under which ok() emits the jq
payload and never renders the prose at all. So the obvious repair — stop
discarding stdout — would ALSO have stayed green under olivia's mutation:
the surface is not merely uncaptured, it is unreachable. The arm has to
flip the mode, and the negative control needs a liveness assertion or it
passes vacuously on an empty string.
- 9 new assertions (36 -> 45): the result line states the floor fired and
names the matched term, on the ask axis AND the TITLE axis (DIVE-1957);
a negative control that an unfloored gate claims no floor; a liveness
arm that the prose rendered at all.
- floor_term now rides the --json payload (null when nothing floored). An
agent filing with --json got tier_floored:true and no way to learn which
word did it, which leaves the machine reader in exactly the state this
ticket exists to fix.
Mutation-graded, each red predicted before running: olivia's exact mutation
-> 2 red; ${floor_note} dropped from the result line -> 4 red; floor_term
dropped from the JSON payload -> 1 red; ok()'s prose branch blanked -> 5
red, including the liveness arm.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes DIVE-2089. Merges BEFORE DIVE-2099 (PR #225) — 2099 ships inert if it lands first, because engineering gates keep arriving pinned at tier-2 where its new authority cannot reach them.
The defect
The T2 keyword floor reads SUBJECT MATTER as RISK and picks the audience from it. A gate asking "how should we model capability vs clearance" was routed as though it HANDLED a secret. Talking about credentials is not handling credentials. It fired silently, and the discovered workaround — reword until it routes correctly — teaches the fleet to launder vocabulary, which erodes the exact signal the floor exists to protect.
What this ships
--discusses="<why>"ontask need— a DECLARED appeal of a floor that fired on subject matter. Deliberately not a sixth keyword class. Four guards:--type=decisiononly (approval/manual/secret/access declare an ACTION, so the flag is REFUSED, not ignored); only on an actual over-fire; a non-appealable core (money / outbound comms / irreversible infra) re-tested on the residual; downgrade only to a LEAD-ROUTED tier 1.--tier=2vetoes it. Every refusal is loud, the declaration is written into the ask the reviewer grades, and the outcome is audited applied OR refused.How it was checked
tests/gate_floor_declared_discussion_unit.sh, 45 assertions. Every arm exercised on the ask axis AND the TITLE axis — a suite varying only the ask passes vacuously (DIVE-1957), and the title is the axis a filer cannot reword.Graded by mutation, not by greenness. The verifier re-derived four load-bearing mutants independently: neutralising the downgrade → 8 red; neutralising the non-appealable core → 4 red; neutralising the decision-only guard → 5 red; blanking
ok()'s prose branch → 5 red including liveness. The suite cannot pass by having disabled the floor.Arm 7 keeps a refutation LIVE rather than in prose: if the floor is ever widened to match
restart/session, it goes red.Regression: 25/26
gate_*_unit.shharnesses green, 392 assertions.gate_verifier_route_unit.shexits rc=5 identically on basedfd3d30and on this head — pre-existing, measured on both sides rather than taken on report.Rebase note
Rebased onto
dfd3d30. The generated bundle was REBUILT at each step, never hand-resolved —build.shitself changed on main (DIVE-2102 registerssrc/lib/capability.sh), so a rebuild with the stale script emits 47,779 lines instead of 48,024 withcapability_declare()absent, and still passes the sha check. Verified by arithmetic: bundle delta vs base == src delta vs base == 218.The recursion, left standing on purpose
Pushing this branch required a human-only tier-2 approval because this ticket's own TITLE contains "credentials" and the floor matches over ask + title. Unclearable by the org lead, unfixable by rewording. Left as-is rather than reworded: laundering it is the behaviour this PR exists to stop.
🤖 Generated with Claude Code