diagnosing-bugs

A preserved method from https://github.com/mattpocock/skills at 3cca18b368ae, path skills/engineering/diagnosing-bugs, MIT. 34 of 185 source lines differ (18%), every difference claimed by an entry of the ledger with its reason. Entries: baseline-copies-2026-09-11, pull-2026-09-11, fold-2026-09-11, fold-walk-2026-09-11, series-s7-roster-2026-09-11, roster-keepers-2026-09-15, light-path-negative-2026-09-15.

  • dependency 3
  • harness 2
  • lifecycle 1
  • location 3
  • method 1
  • scope 1

Files

Every difference, as it stands

SKILL.md

---
---
harnesschangedbaseline-copies-2026-09-11

greenline renders its own frontmatter: quoted name and description, the description from the manifest override where one existed, no upstream activation flag

name: diagnosing-bugs
name: "diagnosing-bugs"
description: Diagnosis loop for hard bugs and performance regressions. Use when the user says "diagnose"/"debug this", or reports something broken/throwing/failing/slow.
description: "Diagnosis loop for hard bugs and performance regressions. Use when the user says \"diagnose\"/\"debug this\", or reports something broken/throwing/failing/slow."
---
---
 
 
# Diagnosing Bugs
# Diagnosing Bugs
 
 
scopechangedlight-path-negative-2026-09-15

the opening paragraph: a repair no ticket owns gets a compact ticket except on the block's light path (one source file and its test, no open choice, a failing test that already names it if there is one; a red test that does not name the change, or an instruction the change cannot keep, makes it not light), matching implement; carried from roster-keepers-2026-09-15 (J-13, 2026-09-15)

The router or the request names this stage when a red or flake resists first read, or when something is broken, throwing, failing or slow. If a ticket owns the failure, read it first and keep its `acceptance:` items in view: the tight reproduction loop you build is the evidence the ticket's completion will cite. A code repair no ticket owns gets a compact ticket, except on the light path (one source file and its test, no open choice, a failing test that already names it if there is one; a red test that does not name the change, or an instruction the change cannot keep, makes it not light); a diagnosis-only request returns its findings in the reply and writes nothing to the repository. Where the loop drives a CLI or a browser, control-cli and control-ui build the harness: this method owns the diagnosis, they own the surface it runs against. A credential in a captured artifact is airgap-secrets' concern. The repair is not reviewed here: it takes the ticket through delivery-review and verify-this like any other change.
 
A discipline for hard bugs. Skip phases only when explicitly justified.
A discipline for hard bugs. Skip phases only when explicitly justified.
 
 
When exploring the codebase, read `CONTEXT.md` (if it exists) to get a clear mental model of the relevant modules, and check ADRs in the area you're touching.
When exploring the codebase, read `CONTEXT.md` (if it exists) to get a clear mental model of the relevant modules, and check ADRs in the area you're touching.
4 unchanged lines
 
 
## Redact
## Redact
 
 
This skill has you show commands, outputs and captured artifacts. **Redact every secret first**: write `<REDACTED>` in its place. Build loops against env vars, so the credential stays in the environment rather than in what you show. Captured artifacts carry auth headers: quote only the lines that carry the signal.
This skill has you show commands, outputs and captured artifacts. **Redact every secret first**: write `<REDACTED>` in its place. Build loops against env vars, so the credential stays in the environment rather than in what you show. Captured artifacts carry auth headers: quote only the lines that carry the signal.
 
 
If the redacted output is not enough to diagnose the bug, say so and ask the user.
If the redacted output is not enough to diagnose the bug, say so and ask the user.
 
 
dependencychangedfold-2026-09-11

The Redact section's practice is airgap-secrets'; when a captured artifact already carries a credential that skill owns the revoke-first response, so the reader is sent there at the point the leak is noticed rather than left with redaction alone.

A credential that already sits in a captured artifact has leaked: airgap-secrets owns the revoke-first response, so load it before going on.
 
## Phase 1: Build a feedback loop
## Phase 1: Build a feedback loop
 
 
**This is the skill.** Everything else is mechanical. If you have a **tight** pass/fail signal for the bug (one that goes red on _this_ bug), you will find the cause; bisection, hypothesis-testing, and instrumentation all just consume it. If you don't have one, no amount of staring at code will save you.
**This is the skill.** Everything else is mechanical. If you have a **tight** pass/fail signal for the bug (one that goes red on _this_ bug), you will find the cause; bisection, hypothesis-testing, and instrumentation all just consume it. If you don't have one, no amount of staring at code will save you.
4 unchanged lines
 
 
Spend disproportionate effort here. **Be aggressive. Be creative. Refuse to give up.**
Spend disproportionate effort here. **Be aggressive. Be creative. Refuse to give up.**
 
 
### Ways to construct one, in roughly this order
### Ways to construct one, in roughly this order
 
 
1. **Failing test** at whatever seam reaches the bug: unit, integration, e2e.
1. **Failing test** at whatever seam reaches the bug: unit, integration, e2e.
2. **Curl / HTTP script** against a running dev server.
2. **Curl / HTTP script** against a running dev server.
dependencychangedfold-2026-09-11

Loop options 3 and 4 name the roster skills that build the CLI and browser harness, control-cli and control-ui, at the point the reader chooses them: this method owns the diagnosis, they own the surface it runs against.

3. **CLI invocation** with a fixture input, diffing stdout against a known-good snapshot.
3. **CLI invocation** with a fixture input, diffing stdout against a known-good snapshot; control-cli builds the harness when the CLI is interactive.
4. **Headless browser script** (Playwright / Puppeteer) that drives the UI and asserts on DOM/console/network.
4. **Headless browser script** (Playwright / Puppeteer) that drives the UI and asserts on DOM/console/network; control-ui builds the harness.
5. **Replay a captured trace.** Save a real network request / payload / event log to disk; replay it through the code path in isolation.
5. **Replay a captured trace.** Save a real network request / payload / event log to disk; replay it through the code path in isolation.
locationchangedfold-2026-09-11

A throwaway harness is built under .greenline/tmp/diagnosing-bugs/, greenline's git-ignored scratch home, named at the step that builds it.

6. **Throwaway harness.** Spin up a minimal subset of the system (one service, mocked deps) that exercises the bug code path with a single function call.
6. **Throwaway harness.** Spin up a minimal subset of the system (one service, mocked deps) that exercises the bug code path with a single function call, under `.greenline/tmp/diagnosing-bugs/`, which git ignores.
7. **Property / fuzz loop.** If the bug is "sometimes wrong output", run 1000 random inputs and look for the failure mode.
7. **Property / fuzz loop.** If the bug is "sometimes wrong output", run 1000 random inputs and look for the failure mode.
8. **Bisection harness.** If the bug appeared between two known states (commit, dataset, version), automate "boot at state X, check, repeat" so you can `git bisect run` it.
8. **Bisection harness.** If the bug appeared between two known states (commit, dataset, version), automate "boot at state X, check, repeat" so you can `git bisect run` it.
9. **Differential loop.** Run the same input through old-version vs new-version (or two configs) and diff outputs.
9. **Differential loop.** Run the same input through old-version vs new-version (or two configs) and diff outputs.
dependencychangedfold-2026-09-11

scripts/hitl-loop.template.sh is this skill's own support file, installed beside SKILL.md and never at the repo root, so the pointer says where the installed file is.

10. **HITL bash script.** Last resort. If a human must click, drive _them_ with `scripts/hitl-loop.template.sh` so the loop is still structured. Captured output feeds back to you.
10. **HITL bash script.** Last resort. If a human must click, drive _them_ with `scripts/hitl-loop.template.sh`, installed beside this SKILL.md, so the loop is still structured. Captured output feeds back to you.
 
 
Build the right feedback loop, and the bug is 90% fixed.
Build the right feedback loop, and the bug is 90% fixed.
 
 
34 unchanged lines
### Tighten the loop
### Tighten the loop
 
 
Treat the loop as a product. Once you have _a_ loop, **tighten** it:
Treat the loop as a product. Once you have _a_ loop, **tighten** it:
 
 
- Can I make it faster? (Cache setup, skip unrelated init, narrow the test scope.)
- Can I make it faster? (Cache setup, skip unrelated init, narrow the test scope.)
- Can I make the signal sharper? (Assert on the specific symptom, not "didn't crash".)
- Can I make the signal sharper? (Assert on the specific symptom, not "didn't crash".)
- Can I make it more deterministic? (Pin time, seed RNG, isolate filesystem, freeze network.)
- Can I make it more deterministic? (Pin time, seed RNG, isolate filesystem, freeze network.)
 
 
A 30-second flaky loop is barely better than no loop; a 2-second deterministic one is tight, a debugging superpower.
A 30-second flaky loop is barely better than no loop; a 2-second deterministic one is tight, a debugging superpower.
 
 
### Non-deterministic bugs
### Non-deterministic bugs
 
 
The goal is not a clean repro but a **higher reproduction rate**. Loop the trigger 100×, parallelise, add stress, narrow timing windows, inject sleeps. A 50%-flake bug is debuggable; 1% is not, so keep raising the rate until it's debuggable.
The goal is not a clean repro but a **higher reproduction rate**. Loop the trigger 100×, parallelise, add stress, narrow timing windows, inject sleeps. A 50%-flake bug is debuggable; 1% is not, so keep raising the rate until it's debuggable.
 
 
### When you genuinely cannot build a loop
### When you genuinely cannot build a loop
 
 
Stop and say so explicitly. List what you tried. Ask the user for: (a) access to whatever environment reproduces it, (b) a redacted captured artifact (HAR file, log dump, core dump, screen recording with timestamps), or (c) permission to add temporary production instrumentation. Do **not** proceed to hypothesise without a loop.
Stop and say so explicitly. List what you tried. Ask the user for: (a) access to whatever environment reproduces it, (b) a redacted captured artifact (HAR file, log dump, core dump, screen recording with timestamps), or (c) permission to add temporary production instrumentation. Do **not** proceed to hypothesise without a loop.
 
 
### Completion criterion: a tight loop that goes red
### Completion criterion: a tight loop that goes red
 
 
Phase 1 is done when the loop is **tight** and **red-capable**: you can name **one command** (a script path, a test invocation, a curl) that you have **already run at least once** (show the invocation and its output, redacted), and that is:
Phase 1 is done when the loop is **tight** and **red-capable**: you can name **one command** (a script path, a test invocation, a curl) that you have **already run at least once** (show the invocation and its output, redacted), and that is:
 
 
- [ ] **Red-capable**: it drives the actual bug code path and asserts the **user's exact symptom**, so it can go red on this bug and green once fixed. Not "runs without erroring"; it must be able to _catch this specific bug_.
- [ ] **Red-capable**: it drives the actual bug code path and asserts the **user's exact symptom**, so it can go red on this bug and green once fixed. Not "runs without erroring"; it must be able to _catch this specific bug_.
- [ ] **Deterministic**: same verdict every run (flaky bugs: a pinned, high reproduction rate, per above).
- [ ] **Deterministic**: same verdict every run (flaky bugs: a pinned, high reproduction rate, per above).
- [ ] **Fast**: seconds, not minutes.
- [ ] **Fast**: seconds, not minutes.
- [ ] **Agent-runnable**: you can run it unattended; a human in the loop only via `scripts/hitl-loop.template.sh`.
- [ ] **Agent-runnable**: you can run it unattended; a human in the loop only via `scripts/hitl-loop.template.sh`.
 
 
If you catch yourself reading code to build a theory before this command exists, **stop: jumping straight to a hypothesis is the exact failure this skill prevents.** No red-capable command, no Phase 2.
If you catch yourself reading code to build a theory before this command exists, **stop: jumping straight to a hypothesis is the exact failure this skill prevents.** No red-capable command, no Phase 2.
 
 
## Phase 2: Reproduce + minimise
## Phase 2: Reproduce + minimise
 
 
Run the loop. Watch it go red as the bug appears.
Run the loop. Watch it go red as the bug appears.
 
 
Confirm:
Confirm:
 
 
- [ ] The loop produces the failure mode the **user** described, not a different failure that happens to be nearby. Wrong bug = wrong fix.
- [ ] The loop produces the failure mode the **user** described, not a different failure that happens to be nearby. Wrong bug = wrong fix.
- [ ] The failure is reproducible across multiple runs (or, for non-deterministic bugs, reproducible at a high enough rate to debug against).
- [ ] The failure is reproducible across multiple runs (or, for non-deterministic bugs, reproducible at a high enough rate to debug against).
locationchangedfold-2026-09-11

The captured symptom is kept in the owning ticket's evidence home, .greenline/work/evidence/TKT-NNN/, at the step that captures it, so later phases and the ticket's completion can cite it.

- [ ] You have captured the exact symptom (error message, wrong output, slow timing) so later phases can verify the fix actually addresses it.
- [ ] You have captured the exact symptom (error message, wrong output, slow timing) in the owning ticket's evidence home, `.greenline/work/evidence/TKT-NNN/`, so later phases can verify the fix actually addresses it.
 
 
### Minimise
### Minimise
 
 
47 unchanged lines
Once it's red, shrink the repro to the **smallest scenario that still goes red**. Cut inputs, callers, config, data, and steps **one at a time**, re-running the loop after each cut, and keep only what's load-bearing for the failure.
Once it's red, shrink the repro to the **smallest scenario that still goes red**. Cut inputs, callers, config, data, and steps **one at a time**, re-running the loop after each cut, and keep only what's load-bearing for the failure.
 
 
Why bother: a minimal repro shrinks the hypothesis space in Phase 3 (fewer moving parts left to suspect) and becomes the clean regression test in Phase 5.
Why bother: a minimal repro shrinks the hypothesis space in Phase 3 (fewer moving parts left to suspect) and becomes the clean regression test in Phase 5.
 
 
Done when **every remaining element is load-bearing**: removing any one of them makes the loop go green.
Done when **every remaining element is load-bearing**: removing any one of them makes the loop go green.
 
 
Do not proceed until you have reproduced **and** minimised.
Do not proceed until you have reproduced **and** minimised.
 
 
## Phase 3: Hypothesise
## Phase 3: Hypothesise
 
 
Generate **3–5 ranked hypotheses** before testing any of them. Single-hypothesis generation anchors on the first plausible idea.
Generate **3–5 ranked hypotheses** before testing any of them. Single-hypothesis generation anchors on the first plausible idea.
 
 
Each hypothesis must be **falsifiable**: state the prediction it makes.
Each hypothesis must be **falsifiable**: state the prediction it makes.
 
 
> Format: "If <X> is the cause, then <changing Y> will make the bug disappear / <changing Z> will make it worse."
> Format: "If <X> is the cause, then <changing Y> will make the bug disappear / <changing Z> will make it worse."
 
 
If you cannot state the prediction, the hypothesis is a vibe: discard or sharpen it.
If you cannot state the prediction, the hypothesis is a vibe: discard or sharpen it.
 
 
**Show the ranked list to the user before testing.** They often have domain knowledge that re-ranks instantly ("we just deployed a change to #3"), or know hypotheses they've already ruled out. Cheap checkpoint, big time saver. Don't block on it; proceed with your ranking if the user is AFK.
**Show the ranked list to the user before testing.** They often have domain knowledge that re-ranks instantly ("we just deployed a change to #3"), or know hypotheses they've already ruled out. Cheap checkpoint, big time saver. Don't block on it; proceed with your ranking if the user is AFK.
 
 
## Phase 4: Instrument
## Phase 4: Instrument
 
 
Each probe must map to a specific prediction from Phase 3. **Change one variable at a time.**
Each probe must map to a specific prediction from Phase 3. **Change one variable at a time.**
 
 
Tool preference:
Tool preference:
 
 
1. **Debugger / REPL inspection** if the env supports it. One breakpoint beats ten logs.
1. **Debugger / REPL inspection** if the env supports it. One breakpoint beats ten logs.
2. **Targeted logs** at the boundaries that distinguish hypotheses.
2. **Targeted logs** at the boundaries that distinguish hypotheses.
3. Never "log everything and grep".
3. Never "log everything and grep".
 
 
**Tag every debug log** with a unique prefix, e.g. `[DEBUG-a4f2]`. Cleanup at the end becomes a single grep. Untagged logs survive; tagged logs die.
**Tag every debug log** with a unique prefix, e.g. `[DEBUG-a4f2]`. Cleanup at the end becomes a single grep. Untagged logs survive; tagged logs die.
 
 
**Perf branch.** For performance regressions, logs are usually wrong. Instead: establish a baseline measurement (timing harness, `performance.now()`, profiler, query plan), then bisect. Measure first, fix second.
**Perf branch.** For performance regressions, logs are usually wrong. Instead: establish a baseline measurement (timing harness, `performance.now()`, profiler, query plan), then bisect. Measure first, fix second.
 
 
## Phase 5: Fix + regression test
## Phase 5: Fix + regression test
 
 
Write the regression test **before the fix**, but only if there is a **correct seam** for it.
Write the regression test **before the fix**, but only if there is a **correct seam** for it.
 
 
A correct seam is one where the test exercises the **real bug pattern** as it occurs at the call site. If the only available seam is too shallow (single-caller test when the bug needs multiple callers, unit test that can't replicate the chain that triggered the bug), a regression test there gives false confidence.
A correct seam is one where the test exercises the **real bug pattern** as it occurs at the call site. If the only available seam is too shallow (single-caller test when the bug needs multiple callers, unit test that can't replicate the chain that triggered the bug), a regression test there gives false confidence.
 
 
**If no correct seam exists, that itself is the finding.** Note it. The codebase architecture is preventing the bug from being locked down. Flag this for the next phase.
**If no correct seam exists, that itself is the finding.** Note it. The codebase architecture is preventing the bug from being locked down. Flag this for the next phase.
 
 
If a correct seam exists:
If a correct seam exists:
 
 
1. Turn the minimised repro into a failing test at that seam.
1. Turn the minimised repro into a failing test at that seam.
2. Watch it fail.
2. Watch it fail.
3. Apply the fix.
3. Apply the fix.
4. Watch it pass.
4. Watch it pass.
5. Re-run the Phase 1 feedback loop against the original (un-minimised) scenario.
5. Re-run the Phase 1 feedback loop against the original (un-minimised) scenario.
 
 
lifecyclechangedfold-2026-09-11

The fix and its regression test are the owning ticket's implementation and take its normal path through delivery-review and verify-this, stated at the end of Phase 5 where the fix is applied.

The fix and its test are the owning ticket's implementation and take its normal path: delivery-review, then verify-this.
 
## Phase 6: Cleanup
## Phase 6: Cleanup
 
 
Required before declaring done:
Required before declaring done:
 
 
- [ ] Original repro no longer reproduces (re-run the Phase 1 loop)
- [ ] Original repro no longer reproduces (re-run the Phase 1 loop)
- [ ] Regression test passes (or absence of seam is documented)
- [ ] Regression test passes (or absence of seam is documented)
methodchangedseries-s7-roster-2026-09-11

upstream's Phase 6 has no slot for the seam finding Phase 5 flags; greenline adds a required checklist item that carries it into the ticket, which adds a step (the approved patch of 2026-08-26, re-kinded from lifecycle) Confirmed by the operator on 2026-09-11 (method-rulings.md).

- [ ] A missing correct seam flagged in Phase 5 is routed to `record-architecture-decisions`: the architecture that blocks the lock-down is the finding to record
- [ ] All `[DEBUG-...]` instrumentation removed (`grep` the prefix)
- [ ] All `[DEBUG-...]` instrumentation removed (`grep` the prefix)
locationchangedfold-2026-09-11

Phase 6's 'clearly-marked debug location' is .greenline/tmp/diagnosing-bugs/, which the sweep empties after relied-on instruments are promoted to .greenline/work/evidence/TKT-NNN/; the commit / PR message becomes the commit message and the owning ticket, greenline's record of the work; the Handoff section (ADR 0039) names the ticket consumed, the evidence produced and the review and verification stages that follow.

- [ ] Throwaway prototypes deleted (or moved to a clearly-marked debug location)
- [ ] Throwaway probes and harnesses deleted from `.greenline/tmp/diagnosing-bugs/`, after any instrument the ticket's evidence relies on is promoted to `.greenline/work/evidence/TKT-NNN/`
- [ ] The hypothesis that turned out correct is stated in the commit / PR message, so the next debugger learns
- [ ] The hypothesis that turned out correct is stated in the commit message and on the owning ticket, so the next debugger learns
 
## Handoff
 
Consumes: the owning ticket and its acceptance items, or a diagnosis-only request
Produces: reproduction, causal evidence and regression proof under .greenline/work/evidence/TKT-NNN/ and in the ticket's account; a code repair on the ticket, status implementing then implemented
Next: delivery-review reads the ticket, its account and base_commit..result_commit, then verify-this checks acceptance; a diagnosis-only request returns its findings in the reply

agents/openai.yaml

harnessremoved filebaseline-copies-2026-09-11

the renderer generates agents/openai.yaml from the manifest; the vendored copy is not projected

interface:
display_name: "Diagnosing Bugs"
short_description: "Diagnose hard bugs and regressions"

The timeline

Each entry that touched this method, with the differences it claimed as they stood at its commit, read from the repository's history.

2026-09-11 baseline-copies-2026-09-11

the cutover to an edited copy (ADR 0039): the composed output written as the copy, every difference from upstream claimed with the reason of the overlay that produced it

SKILL.md

harnesschangedbaseline-copies-2026-09-11

greenline renders its own frontmatter: quoted name and description, the description from the manifest override where one existed, no upstream activation flag

name: diagnosing-bugs
name: "diagnosing-bugs"
description: Diagnosis loop for hard bugs and performance regressions. Use when the user says "diagnose"/"debug this", or reports something broken/throwing/failing/slow.
description: "Diagnosis loop for hard bugs and performance regressions. Use when the user says \"diagnose\"/\"debug this\", or reports something broken/throwing/failing/slow."
lifecyclechangedbaseline-copies-2026-09-11

greenline prelude, to fold: tie the loop to the owning ticket; probes under .greenline/tmp/diagnosing-bugs/; harness building deferred to control-cli and control-ui, leak handling to airgap-secrets

**greenline prelude: tie the loop to the record.** If a ticket owns this failure, read it first and keep its `acceptance:` items in view; the tight reproduction loop you build is the evidence the ticket's completion will cite.
 
The body's `scripts/hitl-loop.template.sh` is this skill's own support file, installed beside this SKILL.md in its `scripts/` directory, never at the repo root. Throwaway probes, tagged logs, and debug harnesses scratch in `.greenline/tmp/diagnosing-bugs/`, which git never sees: the body's "clearly-marked debug location" is that directory, and Phase 6's sweep empties it. Where the loop drives a CLI or a browser, `control-cli` and `control-ui` carry the harness-building methods: this skill owns the diagnosis, they own the surface it runs against.
 
The Redact section below is `airgap-secrets` practice. When a captured artifact carries a credential, load that skill, which owns the rule and the revoke-first response to a leak.
 
lifecyclechangedbaseline-copies-2026-09-11

Phase 5 flags a missing correct seam "for the next phase" and Phase 6 has no slot for it, so the architectural finding dies with the session.

- [ ] A missing correct seam flagged in Phase 5 is routed to `record-architecture-decisions`: the architecture that blocks the lock-down is the finding to record
lifecyclechangedbaseline-copies-2026-09-11

greenline completion, to fold: evidence stays with the ticket and its account; a repair follows the normal review and verification contract

 
 
## greenline completion: evidence into the artifact
 
Keep the reproduction, causal evidence, repair, and regression proof with the owning ticket and execution account. A newly discovered code repair gets a compact ticket when none owns it; a diagnosis-only request can return its findings without implementing or writing repository state. Retain relied-on instruments before deleting temporary probes.
 
A code repair follows the same committed-result, independent-review, and verification contract as other implementation. The compact ticket's intent and acceptance supply fidelity even without a separate spec. Return to the request owner to continue within its grant, preserving failures and unresolved evidence.

agents/openai.yaml

harnessremoved filebaseline-copies-2026-09-11

the renderer generates agents/openai.yaml from the manifest; the vendored copy is not projected

interface:
display_name: "Diagnosing Bugs"
short_description: "Diagnose hard bugs and regressions"

2026-09-11 pull-2026-09-11

pin advance to 3cca18b: upstream moved with no change under the vendored paths

2026-09-11 fold-2026-09-11

The prelude and completion are folded into the phases they addressed: the scope opens the method, the harness and leak deferrals sit at the loop options and the Redact section, the probe home and the evidence home sit where probes are built, captured and swept, and a Handoff section sends the repair down the normal review and verification contract.

SKILL.md

dependencychangedfold-2026-09-11

The Redact section's practice is airgap-secrets'; when a captured artifact already carries a credential that skill owns the revoke-first response, so the reader is sent there at the point the leak is noticed rather than left with redaction alone.

A credential that already sits in a captured artifact has leaked: airgap-secrets owns the revoke-first response, so load it before going on.
 
dependencychangedfold-2026-09-11

Loop options 3 and 4 name the roster skills that build the CLI and browser harness, control-cli and control-ui, at the point the reader chooses them: this method owns the diagnosis, they own the surface it runs against.

3. **CLI invocation** with a fixture input, diffing stdout against a known-good snapshot.
3. **CLI invocation** with a fixture input, diffing stdout against a known-good snapshot; control-cli builds the harness when the CLI is interactive.
4. **Headless browser script** (Playwright / Puppeteer) that drives the UI and asserts on DOM/console/network.
4. **Headless browser script** (Playwright / Puppeteer) that drives the UI and asserts on DOM/console/network; control-ui builds the harness.
locationchangedfold-2026-09-11

A throwaway harness is built under .greenline/tmp/diagnosing-bugs/, greenline's git-ignored scratch home, named at the step that builds it.

6. **Throwaway harness.** Spin up a minimal subset of the system (one service, mocked deps) that exercises the bug code path with a single function call.
6. **Throwaway harness.** Spin up a minimal subset of the system (one service, mocked deps) that exercises the bug code path with a single function call, under `.greenline/tmp/diagnosing-bugs/`, which git ignores.
dependencychangedfold-2026-09-11

scripts/hitl-loop.template.sh is this skill's own support file, installed beside SKILL.md and never at the repo root, so the pointer says where the installed file is.

10. **HITL bash script.** Last resort. If a human must click, drive _them_ with `scripts/hitl-loop.template.sh` so the loop is still structured. Captured output feeds back to you.
10. **HITL bash script.** Last resort. If a human must click, drive _them_ with `scripts/hitl-loop.template.sh`, installed beside this SKILL.md, so the loop is still structured. Captured output feeds back to you.
locationchangedfold-2026-09-11

The captured symptom is kept in the owning ticket's evidence home, .greenline/work/evidence/TKT-NNN/, at the step that captures it, so later phases and the ticket's completion can cite it.

- [ ] You have captured the exact symptom (error message, wrong output, slow timing) so later phases can verify the fix actually addresses it.
- [ ] You have captured the exact symptom (error message, wrong output, slow timing) in the owning ticket's evidence home, `.greenline/work/evidence/TKT-NNN/`, so later phases can verify the fix actually addresses it.
lifecyclechangedfold-2026-09-11

The fix and its regression test are the owning ticket's implementation and take its normal path through delivery-review and verify-this, stated at the end of Phase 5 where the fix is applied.

The fix and its test are the owning ticket's implementation and take its normal path: delivery-review, then verify-this.
 
locationchangedfold-2026-09-11

Phase 6's 'clearly-marked debug location' is .greenline/tmp/diagnosing-bugs/, which the sweep empties after relied-on instruments are promoted to .greenline/work/evidence/TKT-NNN/; the commit / PR message becomes the commit message and the owning ticket, greenline's record of the work; the Handoff section (ADR 0039) names the ticket consumed, the evidence produced and the review and verification stages that follow.

- [ ] Throwaway prototypes deleted (or moved to a clearly-marked debug location)
- [ ] Throwaway probes and harnesses deleted from `.greenline/tmp/diagnosing-bugs/`, after any instrument the ticket's evidence relies on is promoted to `.greenline/work/evidence/TKT-NNN/`
- [ ] The hypothesis that turned out correct is stated in the commit / PR message, so the next debugger learns
- [ ] The hypothesis that turned out correct is stated in the commit message and on the owning ticket, so the next debugger learns
 
## Handoff
 
Consumes: the owning ticket and its acceptance items, or a diagnosis-only request
Produces: reproduction, causal evidence and regression proof under .greenline/work/evidence/TKT-NNN/ and in the ticket's account; a code repair on the ticket, status implementing then implemented
Next: delivery-review reads the ticket, its account and base_commit..result_commit, then verify-this checks acceptance; a diagnosis-only request returns its findings in the reply

2026-09-11 fold-walk-2026-09-11

the coherence walk: the compact-ticket rule now carries the light path's exception; the Phase 6 receiver re-kinded as a method edit

SKILL.md

scopechangedfold-walk-2026-09-11

the opening paragraph: a repair no ticket owns gets a compact ticket except on the block's light path (one source file and its test, no open choice), matching implement

The router or the request names this stage when a red or flake resists first read, or when something is broken, throwing, failing or slow. If a ticket owns the failure, read it first and keep its `acceptance:` items in view: the tight reproduction loop you build is the evidence the ticket's completion will cite. A code repair no ticket owns gets a compact ticket, except on the light path (one source file and its test, no open choice); a diagnosis-only request returns its findings in the reply and writes nothing to the repository. Where the loop drives a CLI or a browser, control-cli and control-ui build the harness: this method owns the diagnosis, they own the surface it runs against. A credential in a captured artifact is airgap-secrets' concern. The repair is not reviewed here: it takes the ticket through delivery-review and verify-this like any other change.
 
methodchangedfold-walk-2026-09-11

upstream's Phase 6 has no slot for the seam finding Phase 5 flags; greenline adds a required checklist item that carries it into the ticket, which adds a step (the approved patch of 2026-08-26, re-kinded from lifecycle)

- [ ] A missing correct seam flagged in Phase 5 is routed to `record-architecture-decisions`: the architecture that blocks the lock-down is the finding to record

2026-09-11 series-s7-roster-2026-09-11

The operator's ruling on the method-class edits put to them by the S3 fold: the edit is kept and re-recorded with the ruling as its authority.

SKILL.md

methodchangedseries-s7-roster-2026-09-11

upstream's Phase 6 has no slot for the seam finding Phase 5 flags; greenline adds a required checklist item that carries it into the ticket, which adds a step (the approved patch of 2026-08-26, re-kinded from lifecycle) Confirmed by the operator on 2026-09-11 (method-rulings.md).

- [ ] A missing correct seam flagged in Phase 5 is routed to `record-architecture-decisions`: the architecture that blocks the lock-down is the finding to record

2026-09-15 roster-keepers-2026-09-15

The opening paragraph's light path omitted the failing-test condition the block states (the audit J-5, finding 8; found again by J-10); it now matches the keeper. The earlier claim is carried forward.

SKILL.md

scopechangedroster-keepers-2026-09-15

the opening paragraph: a repair no ticket owns gets a compact ticket except on the block's light path (one source file and its test, no open choice, a failing test that already names it if there is one), matching implement; carried from fold-walk-2026-09-11, the condition added to match the block (J-8, 2026-09-15)

The router or the request names this stage when a red or flake resists first read, or when something is broken, throwing, failing or slow. If a ticket owns the failure, read it first and keep its `acceptance:` items in view: the tight reproduction loop you build is the evidence the ticket's completion will cite. A code repair no ticket owns gets a compact ticket, except on the light path (one source file and its test, no open choice, a failing test that already names it if there is one); a diagnosis-only request returns its findings in the reply and writes nothing to the repository. Where the loop drives a CLI or a browser, control-cli and control-ui build the harness: this method owns the diagnosis, they own the surface it runs against. A credential in a captured artifact is airgap-secrets' concern. The repair is not reviewed here: it takes the ticket through delivery-review and verify-this like any other change.
 

2026-09-15 light-path-negative-2026-09-15

The same negative case, stated in the opening paragraph's light path to match the block. The earlier claim is carried forward.

SKILL.md

scopechangedlight-path-negative-2026-09-15

the opening paragraph: a repair no ticket owns gets a compact ticket except on the block's light path (one source file and its test, no open choice, a failing test that already names it if there is one; a red test that does not name the change, or an instruction the change cannot keep, makes it not light), matching implement; carried from roster-keepers-2026-09-15 (J-13, 2026-09-15)

The router or the request names this stage when a red or flake resists first read, or when something is broken, throwing, failing or slow. If a ticket owns the failure, read it first and keep its `acceptance:` items in view: the tight reproduction loop you build is the evidence the ticket's completion will cite. A code repair no ticket owns gets a compact ticket, except on the light path (one source file and its test, no open choice, a failing test that already names it if there is one; a red test that does not name the change, or an instruction the change cannot keep, makes it not light); a diagnosis-only request returns its findings in the reply and writes nothing to the repository. Where the loop drives a CLI or a browser, control-cli and control-ui build the harness: this method owns the diagnosis, they own the surface it runs against. A credential in a captured artifact is airgap-secrets' concern. The repair is not reviewed here: it takes the ticket through delivery-review and verify-this like any other change.