debug: no intake gate, a one-command rule that breaks on infra, and a session_log payload missing session_id #36

Closed
opened 2026-08-29 09:33:57 +00:00 by mathias · 2 comments
Owner

Found by the #19 pressure test run against debug while executing #14. The four defects in the newly added sections were fixed in 08c935b; these are pre-existing and were left alone rather than swept into that commit.

Verbatim from the run, which had the skill loaded and a deliberately vague report ("builds are flaky again, sometimes the signed artifact is missing... what's the fix?").

1. No intake gate — the skill pushes you to hypothesise into a vacuum

Step 1 assumes a local artifact and has no branch for "there isn't one." "Read the full error message and stack trace", "Read the file where the failure originated", "read the test and the code under test." I had no repo, no run id, no log, no workflow file. All four bullets were unsatisfiable. The skill's highest-value move here — ask for the run id and the job log before generating anything — appears nowhere. Iron Law 1 bans "try X and see what happens" but nothing bans hypothesising into a total vacuum, which is what the skill pushed me toward.

Proposed: if the report contains no failure text, name the specific artifact needed and stop. This is the same rule cad-babysit already enforces (read the comments and the job log first), so the two should agree.

2. "One command" is false for anything above a unit test

"A hypothesis you cannot verify in one command is not a hypothesis — it is a guess." My H2 verification is "partition the last 20 runs and diff their trigger types"; the boundary-logging pre-step is an entire instrumented CI run. Neither is one command, both are perfectly good verifications. The one-command rule holds for the Go-test worked example and breaks for infra.

Proposed: "a single bounded, decisive observation", or scope the rule to in-repo bugs.

3. session_log payload is missing a required field

Line 147 specifies {skill, phase, final_status, message, duration_ms, project_root} — the tool requires session_id, which the skill never mentions. I invented debug-signed-artifact-missing-2026-08-29, so my three entries are only groupable by luck of naming. Also duration_ms: <wall-clock> is unmeasurable — I don't observe a clock — so I omitted it rather than fabricate.

Two real bugs: a documented payload that does not match the tool's contract, and a field no agent can honestly populate. Worth grepping the other skills for the same block — it looks copy-pasted.

Also flagged: three phases per invocation for a skill that produces one response is three near-identical writes.

4. Undefined likelihood scale

high | medium | low across up to five slots that must be strictly ordered. Two of mine are genuinely both "high" and I couldn't express the ordering except by position.

Drop the labels, or define what separates them.

5. brain_query results have no defined role

Line 132 says to run it; line 138 says don't write unconfirmed hypotheses. Nothing says what to do when a prior entry ranks your hypotheses for you — which is exactly what happened; two brain entries are why H1 is first. I cited them because it's obviously right, not because the skill asked.

Proposed: cite the brain entry inline in the hypothesis it informs.

6. Internal roadmap leaked into an operating instruction

Lines 156 and 160 cite "the routing pod (Plan 6)" and Mode 2 routing. Nothing in this section changes what I do — line 160 admits as much. It's ~10 lines of context cost on every load for zero behavioural effect.

Move to a README. Likely present in other skills too; grep -l "Mode 2 Routing" before deciding.

7. "Do not use for already-diagnosed bugs" fights the new section

Section 42 exists precisely because people believe they've diagnosed it and have three fixes to prove it. The skill offers no intake test to distinguish a real diagnosis from a confident wrong one.

That intake test is arguably the most valuable thing the skill could add.


Items 3 and 6 are probably fleet-wide across skills rather than local to debug, which is the argument for doing them as one sweep rather than one skill at a time.

Found by the #19 pressure test run against `debug` while executing #14. The four defects in the *newly added* sections were fixed in `08c935b`; these are pre-existing and were left alone rather than swept into that commit. Verbatim from the run, which had the skill loaded and a deliberately vague report ("builds are flaky again, sometimes the signed artifact is missing... what's the fix?"). ## 1. No intake gate — the skill pushes you to hypothesise into a vacuum > Step 1 assumes a local artifact and has no branch for "there isn't one." *"Read the full error message and stack trace"*, *"Read the file where the failure originated"*, *"read the test and the code under test."* I had no repo, no run id, no log, no workflow file. All four bullets were unsatisfiable. The skill's highest-value move here — **ask for the run id and the job log before generating anything** — appears nowhere. Iron Law 1 bans "try X and see what happens" but nothing bans hypothesising into a total vacuum, which is what the skill pushed me toward. Proposed: if the report contains no failure text, name the specific artifact needed and stop. This is the same rule `cad-babysit` already enforces (read the comments and the job log *first*), so the two should agree. ## 2. "One command" is false for anything above a unit test > *"A hypothesis you cannot verify in one command is not a hypothesis — it is a guess."* My H2 verification is "partition the last 20 runs and diff their trigger types"; the boundary-logging pre-step is an entire instrumented CI run. Neither is one command, both are perfectly good verifications. The one-command rule holds for the Go-test worked example and breaks for infra. Proposed: "a single bounded, decisive observation", or scope the rule to in-repo bugs. ## 3. `session_log` payload is missing a required field > Line 147 specifies `{skill, phase, final_status, message, duration_ms, project_root}` — the tool **requires `session_id`**, which the skill never mentions. I invented `debug-signed-artifact-missing-2026-08-29`, so my three entries are only groupable by luck of naming. Also `duration_ms: <wall-clock>` is unmeasurable — I don't observe a clock — so I omitted it rather than fabricate. Two real bugs: a documented payload that does not match the tool's contract, and a field no agent can honestly populate. Worth grepping the other skills for the same block — it looks copy-pasted. Also flagged: three phases per invocation for a skill that produces one response is three near-identical writes. ## 4. Undefined likelihood scale > `high | medium | low` across up to five slots that must be strictly ordered. Two of mine are genuinely both "high" and I couldn't express the ordering except by position. Drop the labels, or define what separates them. ## 5. `brain_query` results have no defined role > Line 132 says to run it; line 138 says don't write unconfirmed hypotheses. Nothing says what to do when a prior entry *ranks* your hypotheses for you — which is exactly what happened; two brain entries are why H1 is first. I cited them because it's obviously right, not because the skill asked. Proposed: cite the brain entry inline in the hypothesis it informs. ## 6. Internal roadmap leaked into an operating instruction > Lines 156 and 160 cite *"the routing pod (Plan 6)"* and Mode 2 routing. Nothing in this section changes what I do — line 160 admits as much. It's ~10 lines of context cost on every load for zero behavioural effect. Move to a README. Likely present in other skills too; `grep -l "Mode 2 Routing"` before deciding. ## 7. "Do not use for already-diagnosed bugs" fights the new section > Section 42 exists precisely because people *believe* they've diagnosed it and have three fixes to prove it. The skill offers no intake test to distinguish a real diagnosis from a confident wrong one. That intake test is arguably the most valuable thing the skill could add. --- Items 3 and 6 are probably fleet-wide across skills rather than local to `debug`, which is the argument for doing them as one sweep rather than one skill at a time.
mathias reopened this issue 2026-08-29 12:50:26 +00:00
Author
Owner

Items 3 and 6 done — the two that were fleet-wide. Reopened: my commit footer said "Closes #36" when it should have said "part of", and Gitea acted on it. Five items remain and they are all debug content, which needs the #19 cycle.

3 — session_log payload (b616c51)

Fleet-wide as suspected, and worse than reported. Nine skills documented the payload and none named session_id. Every documented call was one the tool rejects.

Fixed in all nine, plus duration_ms: <wall-clock> removed from eight — the run that omitted it "rather than fabricate" got it right, and the failure mode is the run that fabricates. A made-up number in a metrics stream is worse than a missing one.

bin/check-session-log gates both, with four tests. This is the case #19 has in mind for a small tool over prose — the rule is a grep, so it is a gate, not a note asking people to remember. It caught all nine on first run.

Not done: the "three near-identical writes per invocation" observation. That is a design question about phase granularity, not a contract bug, and it applies to tdd more than debug.

6 — Mode 2 routing leak (1d368d4)

grep -l found it in seven skills. All removed. The content is preserved as one table in README.md, with the caveat that nothing depends on it.

The related line inside the session_log sections stayed, because that one does motivate behaviour — but it no longer cites a component that has never shipped. It now says what is true: pass-rate is what a future routing decision would rest on, and a skill that never logs contributes no evidence either way.

Found while in there, unrelated to this issue but the same class: README's "Contributing a skill" steps would have failed CI for anyone who followed them. They said to hand-add a row to SKILLS_INDEX.md — generated since #29, and task check fails on a hand-edited diff — and named none of the four frontmatter keys the gates now require. Fixed in the same commit, and step 4 now names the #19 pressure-test bar instead of leaving it to be discovered.

Remaining: 1, 2, 4, 5, 7

All are debug's own text, and item 7 (an intake test distinguishing a real diagnosis from a confident wrong one) is the substantial one — the run called it "arguably the most valuable thing the skill could add", and I agree. Items 1 and 7 are really the same feature seen from two sides.

These need a RED baseline and a GREEN re-test per #19, which is blocked on the subagent limit until 13:20. Doing them from judgement alone is exactly what #19 exists to prevent, and #14 already demonstrated that my judgement about what a model needs told me the wrong thing twice.

Items 3 and 6 done — the two that were fleet-wide. Reopened: my commit footer said "Closes #36" when it should have said "part of", and Gitea acted on it. Five items remain and they are all `debug` content, which needs the #19 cycle. ## 3 — session_log payload (`b616c51`) Fleet-wide as suspected, and worse than reported. **Nine** skills documented the payload and **none** named `session_id`. Every documented call was one the tool rejects. Fixed in all nine, plus `duration_ms: <wall-clock>` removed from eight — the run that omitted it "rather than fabricate" got it right, and the failure mode is the run that fabricates. A made-up number in a metrics stream is worse than a missing one. `bin/check-session-log` gates both, with four tests. This is the case #19 has in mind for a small tool over prose — the rule is a grep, so it is a gate, not a note asking people to remember. It caught all nine on first run. Not done: the "three near-identical writes per invocation" observation. That is a design question about phase granularity, not a contract bug, and it applies to `tdd` more than `debug`. ## 6 — Mode 2 routing leak (`1d368d4`) `grep -l` found it in **seven** skills. All removed. The content is preserved as one table in README.md, with the caveat that nothing depends on it. The related line *inside* the session_log sections stayed, because that one does motivate behaviour — but it no longer cites a component that has never shipped. It now says what is true: pass-rate is what a future routing decision would rest on, and a skill that never logs contributes no evidence either way. Found while in there, unrelated to this issue but the same class: README's "Contributing a skill" steps would have failed CI for anyone who followed them. They said to hand-add a row to `SKILLS_INDEX.md` — generated since #29, and `task check` fails on a hand-edited diff — and named none of the four frontmatter keys the gates now require. Fixed in the same commit, and step 4 now names the #19 pressure-test bar instead of leaving it to be discovered. ## Remaining: 1, 2, 4, 5, 7 All are `debug`'s own text, and item 7 (an intake test distinguishing a real diagnosis from a confident wrong one) is the substantial one — the run called it "arguably the most valuable thing the skill could add", and I agree. Items 1 and 7 are really the same feature seen from two sides. These need a RED baseline and a GREEN re-test per #19, which is blocked on the subagent limit until 13:20. Doing them from judgement alone is exactly what #19 exists to prevent, and #14 already demonstrated that my judgement about what a model needs told me the wrong thing twice.
Author
Owner

All seven items now done — 3 and 6 in b616c51/1d368d4 (reported earlier), and 1, 2, 4, 5, 7 in 0c7fac3.

The gate works

A run with the skill loaded, given the vague report from this issue's own example — "builds are flaky again... what's the fix?" — produced zero hypotheses:

I am not going to tell you what the fix is, and the reason is the finding, not a preamble to it. [...] Intake gate (skill lines 39-44): the report contains no failure text, no run id, and no log, so I stop here and name what I need.

It then ranked the artifacts it needed by how much each would split the search space, and — unprompted — noticed something better than any hypothesis would have been:

The retry around signing is actively destroying the evidence needed to diagnose this. If signing exits 0 without producing a file, the retry hides that. [...] You have added a guard that suppresses the observation that would discriminate.

Items 1 and 7 were the same feature from two sides, as suspected, and the "is it actually diagnosed?" test is what makes the second one real: it is diagnosed if you can state the mechanism and name the observation that would have proved it wrong.

Item 2, and the sentence that undercut itself

Rewritten to "a single bounded, decisive observation", and the run confirmed it did the work — "It is the test that exposed the vacuum" — while catching that my qualifier contradicted my headline:

Once "single" covers partitioning twenty runs, the word "single" is load-bearing for nothing.

Fair. The closing clause now carries it: what makes it a hypothesis is that the observation discriminates.

Item 4, and the contradiction it exposed

The rule against high/medium/low landed — and the run caught that the Step 3 template and all three worked-example hypotheses still used the labels I had just banned:

This is a flat contradiction, and it fails in the worst direction: the template and the example are the parts that get imitated. Prose loses to a format block every time.

Both stripped. The slot is now WHY FIRST, which asks for the evidence that sets the order rather than a restatement of it — which is what item 4's better half asked for anyway.

Item 5

brain_query results are cited inline in the hypothesis they inform. The run also caught that the instruction told you to search on an error string you may have just refused to proceed without; on an intake stop it now says to query symptom + component, which may itself name the artifact to ask for.

Three more the run found, fixed here

  • The description never mentioned the gate. That is the text a harness shows before an agent decides to load anything, and it read "Generate 3-5 ranked hypotheses" — so an agent routing on the description alone does the exact thing this issue exists to prevent.
  • Intake vs the failed-fixes section pointed opposite ways for a report that fires both, with no stated precedence. Intake wins, explicitly.
  • session_log had no phase for a correct refusal, so an intake stop logged as a failed read-failure. A metric that records the skill's best behaviour as a failure trains the next model out of it. Added an intake phase.

The session_id problem the run raised is not debug-local and is filed as #39.

All seven items now done — 3 and 6 in `b616c51`/`1d368d4` (reported earlier), and 1, 2, 4, 5, 7 in `0c7fac3`. ## The gate works A run with the skill loaded, given the vague report from this issue's own example — *"builds are flaky again... what's the fix?"* — produced **zero hypotheses**: > **I am not going to tell you what the fix is, and the reason is the finding, not a preamble to it.** [...] Intake gate (skill lines 39-44): the report contains no failure text, no run id, and no log, so I stop here and name what I need. It then ranked the artifacts it needed *by how much each would split the search space*, and — unprompted — noticed something better than any hypothesis would have been: > The **retry around signing** is actively destroying the evidence needed to diagnose this. If signing exits 0 without producing a file, the retry hides that. [...] You have added a guard that suppresses the observation that would discriminate. Items 1 and 7 were the same feature from two sides, as suspected, and the "is it actually diagnosed?" test is what makes the second one real: it is diagnosed if you can state the mechanism *and* name the observation that would have proved it wrong. ## Item 2, and the sentence that undercut itself Rewritten to "a single bounded, decisive observation", and the run confirmed it did the work — *"It is the test that exposed the vacuum"* — while catching that my qualifier contradicted my headline: > Once "single" covers *partitioning twenty runs*, the word "single" is load-bearing for nothing. Fair. The closing clause now carries it: what makes it a hypothesis is that the observation discriminates. ## Item 4, and the contradiction it exposed The rule against `high`/`medium`/`low` landed — and the run caught that the Step 3 template and all three worked-example hypotheses still used the labels I had just banned: > This is a flat contradiction, and it fails in the worst direction: the template and the example are the parts that get imitated. Prose loses to a format block every time. Both stripped. The slot is now `WHY FIRST`, which asks for the evidence that sets the order rather than a restatement of it — which is what item 4's better half asked for anyway. ## Item 5 `brain_query` results are cited inline in the hypothesis they inform. The run also caught that the instruction told you to search on an error string you may have just refused to proceed without; on an intake stop it now says to query symptom + component, which may itself name the artifact to ask for. ## Three more the run found, fixed here - **The `description` never mentioned the gate.** That is the text a harness shows before an agent decides to load anything, and it read "Generate 3-5 ranked hypotheses" — so an agent routing on the description alone does the exact thing this issue exists to prevent. - **Intake vs the failed-fixes section pointed opposite ways** for a report that fires both, with no stated precedence. Intake wins, explicitly. - **`session_log` had no phase for a correct refusal**, so an intake stop logged as a failed `read-failure`. A metric that records the skill's best behaviour as a failure trains the next model out of it. Added an `intake` phase. The `session_id` problem the run raised is not `debug`-local and is filed as **#39**.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mathias/skills#36