Make one command check a library entry, and open the watchdog category - #18
Conversation
|
Rebased the branch to drop the pure Two lines still overlap because both PRs genuinely rewrite them — the README's browse-links row and the library README's contribute-links row, where this PR adds the |
369a028 to
4d7ab2f
Compare
…atchdog category A first-time contributor could compile a rule but could not tell whether it was shaped like the rest of the library, because two of the library's four conventions were enforced by review attention alone. The drift that produced this was already in the tree. Six risk/ entries shipped with the compiler's default JSON indentation rather than the library's one-node- per-line format, because CONTRIBUTING said "keep it formatted like neighboring entries" and offered no tool to do it. Every entry carries a REGIME/CONDITIONS/ INVALIDATION/SHAPE/CALIBRATED ON header and a NOT line; nothing documented that, so a newcomer would have discovered it in review. - scripts/check_contribution.py checks one entry or the whole library: compilation, IR agreement, house formatting, the comment header, signal documentation, StrategyGraph round trip, replay determinism, and the effects boundary. `--write` generates or repairs the _ir.json partner in library format, so nobody hand-reflows JSON again. Reads utf-8-sig, so a BOM is not a first-contribution error. - CI runs it over the whole library on every pull request. - The six drifted risk/ fixtures are reformatted. No semantic change; the suite compares parsed JSON. - docs/first-contribution.md walks the path once with a real rule, and its example compiles under tests/test_docs.py rather than being prose. - nano/library/README.md documents the header convention, the SOURCE: provenance field, and the checker. CONTRIBUTING.md gains the checker command and an attribution section. The watchdog category opens the use case the README has advertised since v0.1.0 with nowhere in the library to put it. Two entries - one PAUSE, one OBSERVE - establish the shape: host-measured system and policy state, the same nonnegative rises-as-it-worsens direction convention as risk/, and no direction ever proposed, which tests/test_library.py now enforces for the whole category. CLI: `nano check` on a file saved with a UTF-8 BOM reported `Unexpected character` at 1:1, naming an invisible character in a correct program. Reading as utf-8-sig fixes it without touching the grammar. Stale claims pinned rather than only corrected: the library README said 26 strategies while shipping 32, so the count, the category list, and the root README's per-category table all get drift guards. .gitignore now covers the .venv that CONTRIBUTING tells a newcomer to create. New links added here use the AetherAI3 namespace, but the existing DBarr3 links are deliberately left alone; PR #16 owns that change, and duplicating it would only conflict. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
PR #17 landed nano/watchdog/, the runtime profile that admits a rule under a narrower contract; this branch adds nano/library/watchdog/, the corpus written for it. They arrived from separate changes with nothing connecting them, so a reader met two things called "watchdog" and no statement of how they relate. Both library entries are admissible under the profile as written. A test pins that for the whole category, synthesising each rule's signal specs from what it actually reads, so the assertion is about admissibility - opcodes, tier, effects, intents, cadence - and not about any one host feed. The corpus and the runtime can no longer drift apart silently. The library README, CONTRIBUTING, and the first-contribution walkthrough now say which is which, and say plainly that contributing an entry asks nothing extra: a rule following the two category conventions already qualifies, and the signal contract belongs to the host deploying it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
4d7ab2f to
20d5167
Compare
|
Rebased onto #17 landing changed something worth acting on: it added Both library entries turn out to be admissible under the profile as written — verified, not assumed: A new test pins that for the whole category, synthesising each rule's signal specs from what it actually reads, so the assertion is about admissibility — opcodes, tier, effects, intents, cadence — and not about any one host's feed. The corpus and the runtime can no longer drift apart silently. The library README, CONTRIBUTING, and the walkthrough now say which is which, and say plainly that contributing an entry asks nothing extra of a contributor. Suite is 457 passed, 2 skipped; One note for whoever picks up #15 (SuperTrend): I checked it against the checks this PR adds and it passes both — its IR is already in library format and its header carries all five required fields plus a |
#18 landed the contribution checker, the watchdog library category, and drift guards on the library counts, which conflicted with this branch's own count updates. Both conflicts were the same class: a strategy total that each side had bumped independently. Resolved to main's table shape with trend/ at 4 to include supertrend_flip_long, and the library README total at 35. The entry itself needed no changes. It already passes the checks #18 added: its _ir.json was written in the library's one-node-per-line house format, and its comment header carries all five required fields plus a NOT line. The full suite is 471 passed, 2 skipped and check_contribution.py --all reports 35 entries ready for review. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Why does this change belong in Nano?
A first-time contributor could compile a rule but could not tell whether it was shaped like the rest of the library. The suite proves an entry compiles to its pinned IR and replays deterministically. It says nothing about two conventions every entry actually follows, and both were held up by review attention alone.
The drift was already in the tree:
risk/entries ship withjson.dumps(indent=2)output instead of the library's one-node-per-line format.CONTRIBUTING.mdsaid "keep it formatted like neighboring entries" and offered no tool that produces that format —nano compileemits correct IR in the wrong shape.REGIME:/CONDITIONS:/INVALIDATION:/SHAPE:/CALIBRATED ON:header plus aNOT <neighbour>:line. Nothing documented that anywhere, so a newcomer would have found out in review.What changed?
Contributor tooling
scripts/check_contribution.pychecks one entry or the whole library — compilation, IR agreement, house formatting, the comment header, signal documentation,StrategyGraphround trip, replay determinism, and the effects boundary:--writegenerates or repairs the_ir.jsonpartner in library format, so nobody hand-reflows JSON again. It readsutf-8-sig, so a BOM is not a first-contribution error. CI runs--allon every PR.The six drifted
risk/fixtures are reformatted — no semantic change, the suite compares parsed JSON.Documentation
docs/first-contribution.mdwalks the path once with a real rule: idea →.nano→ generated IR → deterministic replay → CI → PR. Its example is compiled bytests/test_docs.pyrather than being prose.nano/library/README.mddocuments the header convention and the optionalSOURCE:provenance field;CONTRIBUTING.mdgains the checker command, the watchdog path, and an attribution section.The
watchdog/categoryThe README has advertised deterministic watchdogs since v0.1.0 with nowhere in the library to put one. Two entries —
trusted_route_guard(PAUSE) andcredential_age_alert(OBSERVE) — establish the shape: host-measured system and policy state, the same nonnegative rises-as-it-worsens direction convention asrisk/, and never a proposed direction, whichtests/test_library.pynow enforces across the whole category. The category is deliberately thin; the rest are seeded as issues.CLI
nano checkon a file saved with a UTF-8 BOM reportedUnexpected character ''at 1:1 — naming an invisible character in a correct program, on the first command a Windows contributor runs. Reading asutf-8-sigfixes it without touching the grammar; a BOM carries no meaning inside a program and every other byte still has to be valid UTF-8.Stale claims, pinned rather than only corrected
The library count, the category list, and the root README's per-category table all get drift guards, in the same spirit as the existing
test_docs.pytest-count guard. Repository links across README, CONTRIBUTING, SECURITY,pyproject.toml, and the issue-template config still pointed at the pre-renameDBarr3namespace..gitignorenow covers the.venvthat CONTRIBUTING tells a newcomer to create.Validation
python -m pytest -qpassed — 415 passed, 2 skipped (was 401 passed, 2 skipped).python scripts/check_contribution.py --allpassed —34 entries ready for review.The checker was tested in both directions rather than only written. Against the library as it stood it reported the six formatting-drifted
risk/fixtures. Against a deliberately incomplete probe rule — saved with a BOM, missing every header field, using an undocumented signal, with no IR partner — it reported all seven problems and named the fix for each. The BOM itself passed through both the checker andnano checkwithout complaint, which is the point.Boundary check
DecisionGateor add external actuation to Nano source/runtime..nanoand_ir.jsonfiles plus documented host signal conventions.pause/observeonly and its signals are nonnegative and rise as the situation worsens.Nothing here weakens a boundary; the checker adds one that was previously only implied, refusing any entry declaring effects beyond
intent.emitandlog.append. The watchdog entries propose intents like every other entry — Nano does not inspect a network, read a key store, or enforce anything.🤖 Generated with Claude Code