What Studio needs
A per run record of what lint found, so Studio's third proof rung can read a fact instead of matching a phrase.
Today
project-bin/lint-gate.sh persists only .claude/lint-baseline.json under --update-baseline. The run output lives in $TMPDIR and the verdicts go to stdout. Nothing survives the run.
Studio therefore greps docs/BUILD-LOG.md for lint ... (ok|clean|0 findings). That is phrase matching, and it is one rewording away from silently going red.
Blast radius
Rating: safe additive as a new file. Needs care as a BUILD-LOG row.
Write a new file, for example .claude/loop/lint-last.json next to the baseline, or an append only docs/LINT-LOG.md. Declare it in bin/lib/artifact-manifest.tsv. Studio adds a reader.
Do not put it in the exec table in docs/BUILD-LOG.md. That table is parsed by three consumers with different rules:
- Studio
daemon/src/runtime/proof.ts parseExecRows: rungs 1 and 2 read the last row, so a trailing lint row becomes "the exec".
bin/status.sh treats column 3 as a script name and column 4 as a gate, so a lint row appears under "last gate FAILED for" or "pass but not done-renamed".
project-bin/done-drift-check.sh greps the last row per backticked filename.
No obligation change is needed: bin/lib/obligation-check.sh already lists lint-gate under NOROUTE as landing in the build gate rather than a per module review artifact.
Decision needed
None. Ready to implement, provided it never writes to the exec table.
What Studio needs
A per run record of what lint found, so Studio's third proof rung can read a fact instead of matching a phrase.
Today
project-bin/lint-gate.shpersists only.claude/lint-baseline.jsonunder--update-baseline. The run output lives in$TMPDIRand the verdicts go to stdout. Nothing survives the run.Studio therefore greps
docs/BUILD-LOG.mdforlint ... (ok|clean|0 findings). That is phrase matching, and it is one rewording away from silently going red.Blast radius
Rating: safe additive as a new file. Needs care as a BUILD-LOG row.
Write a new file, for example
.claude/loop/lint-last.jsonnext to the baseline, or an append onlydocs/LINT-LOG.md. Declare it inbin/lib/artifact-manifest.tsv. Studio adds a reader.Do not put it in the exec table in
docs/BUILD-LOG.md.That table is parsed by three consumers with different rules:daemon/src/runtime/proof.tsparseExecRows: rungs 1 and 2 read the last row, so a trailing lint row becomes "the exec".bin/status.shtreats column 3 as a script name and column 4 as a gate, so a lint row appears under "last gate FAILED for" or "pass but not done-renamed".project-bin/done-drift-check.shgreps the last row per backticked filename.No obligation change is needed:
bin/lib/obligation-check.shalready lists lint-gate under NOROUTE as landing in the build gate rather than a per module review artifact.Decision needed
None. Ready to implement, provided it never writes to the exec table.