feat(tri): tri now check -- ask the blocking gate its own question locally - #3013
Merged
Conversation
…cally Five local instruments read docs/now/ and every one checks FRESHNESS (an entry exists, dated in the window) while the required `check` context checks SHAPE. Measured on one malformed entry dated today: the gate reported three complaints and three of the five local readers went green -- scripts/pre-commit went green BECAUSE of that file, since its freshness loop found the entry the gate rejects and stopped looking. The command delegates to tools/check_now_entry_shape.py --check-files rather than deciding, so the local answer IS the gate's answer. A sixth reader written in Rust would answer the question and then drift from it. Wired into `tri hooks pre-commit` and scripts/verify.sh's gate preview. Refs #2994 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ved the process 437: docs/now/ is read by five local instruments and every one checks freshness while the required context checks shape. One malformed entry dated today: the gate had three complaints, three local readers went green, and scripts/pre-commit went green BECAUSE of that file. The repair is delegation, not a sixth reader. 438: the suite for that went green at 3 of 3 with one vacuous pass. A sibling test called set_current_dir, which is process-global, so the shape test took its silent early return -- hiding that its planted filenames could never have passed the gate's own filename rule. Refs #2994 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
Contributor
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
gHashTag
added a commit
that referenced
this pull request
Sep 3, 2026
…stion (#3015) * feat(tri): tri gates preview -- ask each blocking context its own question Four contexts can block a merge here. One of them, `check`, gained a local preview last pass. Measured for the other three: * `validate` had NO local reader of any kind. A broken tracked JSON turns it red while verify.sh, scripts/pre-commit and tri hooks pre-commit say nothing about JSON. * `check-linked-issue` reads the PULL REQUEST title and body. The only local stand-in, tri hooks l1-check, reads the last COMMIT -- a different subject. On #3013 the PR body carried the reference and the squashed commit did not. * And the vocabularies disagreed. Both CI gates run (Closes?|Fixes?|Resolves?|Refs?|Updates?)\s*#[0-9]+; the local check ran (Closes|Fixes|Resolves|Reference)\s+#(\d+) -- missing Refs, which Law L1 names and this repository writes, and inventing Reference, which neither gate accepts. Over the last 20 commits on master: 4 matches against 33. The command delegates every row and reads the issue pattern OUT of issue-gate.yml rather than transcribing it, so a fifth vocabulary cannot appear. PROXY and UNAVAILABLE are printed and are never counted as passes. Refs #2994 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(ci): the NOW freshness gate could not run on macOS at all date -u -d yesterday is GNU-only; on BSD it prints 'illegal option -- d' and under set -e the gate exits 1. A contributor on a Mac could not ask this gate its question, and the failure was indistinguishable from a refusal -- which is how tri gates preview first reported a false FAIL for this context. scripts/pre-commit and scripts/verify.sh already carry the two-form lookup; this is the same one. CI is Linux, so the first form still decides there. Refs #2994 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * docs(skill): 439-440 -- the other three blocking contexts, and a mutation run over an empty set 439: validate had NO local reader; check-linked-issue reads the PR body while the local stand-in reads the last commit; and the vocabularies disagreed 4 against 33 over the last 20 master commits. Plus: the freshness gate itself could not run on macOS, and that failure is indistinguishable from a refusal. 440: cargo test takes a substring, so 'preview_tests|l1_' matched nothing and four mutation kills were scored over an empty sample, every line reading ok. The guard must sum passed AND failed. Refs #2994 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- 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.
The measurement
docs/now/is read by five instruments before a push. Every one of them checks freshness — an entry exists, dated inside the window. The requiredcheckcontext checks shape. Same directory, same label, a different question.Planted one malformed entry dated today:
tools/check_now_entry_shape.py(required)scripts/pre-committri hooks now-gatetri hooks pre-commitscripts/verify.shThe second row is the finding:
scripts/pre-commitwent green because of the malformed file. Its freshness loop found the entry the gate rejects, stopped looking, and reported health. A preview the offending artefact satisfies is worse than no preview.This is #2994, and it has now cost a full CI round at least three times — #2991, the pass that filed it, and the pass that wrote this.
The repair is delegation, not a sixth reader
A local re-implementation answers the question once and then drifts, invisibly, because both sides stay green until the day they disagree. So:
tools/check_now_entry_shape.pygrows one flag,--check-files <path>…, sharing the existing per-entry loop (lifted intoreport()); the PR path is untouched.tri now check [paths…] [--staged] [--base <rev>]computes the file set and shells out to that script. The local answer is the gate's answer; there is nothing to keep in sync.tri hooks pre-commit(staged entries) and intoscripts/verify.sh's gate preview, the file whose own docs claimed it previewed "the same three conditions" while never opening an entry.Two refusals it needs, and both are the honest kind:
python3→ exit non-zero saying nothing was checked. The interpreter is probed by asking the OS (python3 -c ""), not by matching an error string.tri hooks now-gate, which asks the other question.Controls
cargo test -p tri--check-files→--self-checkOkREADME.md/.mdfilterentry_paths; while inline, no test reached it)scripts/verify.sh, malformed entrynow-shape:MALFORMEDscripts/verify.sh, well-formed entrynow-shape:okWhat went wrong on the way, and is in the skill
The suite went green at 3 of 3 with one vacuous pass. A sibling test called
std::env::set_current_dir— process-global — so the shape test'sErr(_) => returnguard fired and it never ran. That hid a second defect: the planted filenames werezz-check-test-<date>-…, which the gate's own filename rule rejects, sowell formedcould never have passed. Both repaired structurally: the refusal is nowgate_script(&Path)and takes a scratch directory instead of moving the process, and the silent guards areexpect(...).And the probe that found all this destroyed the work it was measuring.
git add -Aplusgit reset --hard HEAD~1in a loop swept the implementation into a probe commit and deleted it; recovered whole from the reflog. Probes now run on a throwaway branch with explicit paths staged.Skill §437–438.
Refs #2994
🤖 Generated with Claude Code