Skip to content

refactor(tests): one invariant namespace — every catalog entry resolves, the canary mapping is guarded, and journey families are runnable (#2337) - #2740

Merged
vybe merged 1 commit into
devfrom
feature/2337-journey-invariants
Sep 13, 2026
Merged

vybe merged 1 commit into
devfrom
feature/2337-journey-invariants

Conversation

@webmixgamer

@webmixgamer webmixgamer commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Summary

  • The defect was resolution, not authoring. test_2338_journey_catalog.py resolved journey invariants: ids from the catalog's one markdown table, so 11 of 71 defined invariants were citable; citing P-02 (a real §7 entry — J10's own permission promise) failed as "coverage theatre". One stdlib parser (tests/unit/_invariant_catalog.py) now resolves every **X-NN** … *(Tier definition through the same code path for both validators; a summary table is never a definition.
  • E-06 collision removed, not documented again. Catalog E-06 (the unimplemented Active watchdog: remediate stuck executions detected by monitoring #129 orphan check) shared its id with registry E-06 ("no overdue next_run_at", bug: enabled schedule shows "Next: 1d ago" — stale next_run_at, cron fires silently skipped with no execution record #1472). The Active watchdog: remediate stuck executions detected by monitoring #129 entry is re-homed to E-09AC4 relaxed for this one id by operator ruling (recorded on the issue). Zero references break: catalog E-06 was uncitable before this change.
  • Canary mapping + guard. A three-column table (module → registry id → catalog id; the first cell is the module, so a table-parsing regex can never read the join as definitions) documents live vs journey-only. tests/unit/test_2337_invariant_namespace.py asserts INVARIANTS == every module's INVARIANT_ID == the table, every catalog id resolves, and no row's two ids differ; exact per-family pins; Signal: mandatory on new families with a frozen, shrink-only allowlist for the 60 legacy entries lacking the line (registered as debt); synthetic-markdown self-tests in both directions.
  • Journey-level families, scoped to what is runnable today (AC2): SK- skills (SQL), RD- repo-bound deployment (SQL), PLG- plugins (file/HTTP, journey-only), IA- inter-agent (one-hop permission edge, fan-out batch bound MAX_TASKS, dead callee fails fast — measured 0.16 s live). Recursion depth has no product guard to predicate on → Gaps to fill next. J01/J06/J07/J08/J09/J10 records gain ids; JOURNEYS.md regenerated.

Changes

  • docs/testing/orchestration-invariant-catalog.md — E-06→E-09 + shipped E-06 entry; §16–§19; Canary mapping; L-03 list re-synced to snapshot.ORPHAN_SCAN_TABLES (six tables were missing); Gaps; status line
  • tests/unit/_invariant_catalog.py (new), tests/unit/test_2337_invariant_namespace.py (new, 16 tests), tests/unit/test_2338_journey_catalog.py (resolver via the parser; list-shape check)
  • tests/journeys/catalog.yaml, docs/testing/JOURNEYS.md (regenerated), tests/registry.json (additive)
  • docs/memory/requirements/infrastructure.md, src/backend/services/canary_alerts.py (comment only) — the two places that stated the collision as current
  • docs/memory/learnings.md (+1 entry), docs/security-reports/cso-diff-2026-09-12-2337-journey-invariants.{json,md}

Test Plan

  • cd tests && ../.venv/bin/python -m pytest unit/test_2337_invariant_namespace.py unit/test_2338_journey_catalog.py unit/test_1880_canary_alert_parity.py -q83 passed; randomized run green; 381 passed across the seven neighbouring tests that read the touched files; 15,338 tests collect
  • Mutation battery (restore from scratch copies, cmp-verified): delete cited SK-02 → pin + J07 unresolved; drop E-03 from INVARIANTS → three-way equality (and test_1880) red; drift a mapping row to SCH-03 → drift test red; add SK-04 without Signal: → pin + no-Signal red
  • Live oracle: POST /api/canary/run-cycle enumerates exactly the 16 ids the mapping table lists (422 names them for anything else)
  • /review: 0 critical, 3 informational applied · /cso --diff: clean in scope; one out-of-scope VERIFIED finding routed privately as abilityai/trinity-enterprise#614

Deviations from the ACs, on record

  • AC2 — every new entry is a runnable predicate; the 60 legacy prose-only entries are ratcheted, not retro-fitted (debt inbox).
  • AC4 — one id renumbered (E-06E-09) by operator ruling; the alternative was documenting the collision a fifth time.

Fixes #2337

🤖 Generated with Claude Code

…es, the canary mapping is guarded, and journey families are runnable (#2337)

The journey validator resolved `invariants:` ids from the catalog's one markdown
table (the 12-row "Recommended starting subset"), so 11 of the 71 defined
invariants were citable and citing P-02 — a real §7 entry, J10's own permission
promise — failed as "coverage theatre". One stdlib parser
(tests/unit/_invariant_catalog.py) now resolves every `**X-NN** … *(Tier`
definition; a table is never a definition.

Catalog E-06 (the unimplemented #129 orphan check) shared its id with the
registry's E-06 ("no overdue next_run_at", #1472). The #129 entry is re-homed to
E-09 — AC4 relaxed for this one id by operator ruling — so the id means the same
thing in the catalog and in canary/invariants/e06_no_overdue_next_run.py. A
Canary mapping table (module → registry id → catalog id) documents live vs
journey-only, and tests/unit/test_2337_invariant_namespace.py asserts INVARIANTS
== every module's INVARIANT_ID == the table, every catalog id resolves, and no
row's two ids differ. Exact per-family pins; `Signal:` mandatory on new
families with a shrink-only allowlist for the 60 legacy entries without the
line; synthetic-markdown self-tests prove a bold mention, a dagger row and a
table row are not definitions. Mutation-verified: deleting a cited entry,
unregistering E-03, drifting a mapping row and adding a Signal-less entry each
turn exactly the intended tests red.

New families scoped to runnable predicates: SK- (skills), RD- (repo-bound
deployment), PLG- (plugins, file/HTTP), IA- (one-hop permission edge, fan-out
batch bound, dead callee fails fast). Inter-agent recursion depth has no product
guard to predicate on and is recorded in Gaps. L-03's documented cascade list is
re-synced to snapshot.ORPHAN_SCAN_TABLES. J01/J06/J07/J08/J09/J10 records gain
ids; JOURNEYS.md regenerated; the two docs that stated the collision as current
(requirements/infrastructure.md, a canary_alerts.py comment) updated. CSO diff
report: clean in scope; one out-of-scope finding routed privately (ent#614).

Fixes #2337

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

@vybe vybe left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merge-train: batch validated on train/20260913-0705 (#2745) — lane B, /validate-pr + /review clean; refactored tests proven not weakened by mutation; closing keyword normalised to Fixes #2337 so the promotion workflow fires.

@vybe
vybe merged commit 38d7544 into dev Sep 13, 2026
29 checks passed
@webmixgamer
webmixgamer deleted the feature/2337-journey-invariants branch September 13, 2026 11:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants