@agentsfleet/orly 0.10.14 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/.githooks/pre-push +2 -1
  2. package/AGENTS.md +21 -31
  3. package/README.md +94 -28
  4. package/SOUL.md +13 -23
  5. package/audits/agents-md.md +67 -57
  6. package/audits/deinit-pairs.sh +13 -18
  7. package/audits/design-tokens.sh +9 -23
  8. package/audits/doc-read.sh +10 -33
  9. package/audits/doc-reads.ts +41 -0
  10. package/audits/error-codes.sh +18 -25
  11. package/audits/logging-rust.awk +145 -0
  12. package/audits/logging.sh +10 -166
  13. package/audits/msid-ui.sh +45 -18
  14. package/audits/rule-ledger-lib.sh +9 -6
  15. package/audits/rust-error.sh +20 -15
  16. package/audits/scope.sh +88 -0
  17. package/audits/spec-template.sh +2 -2
  18. package/audits/spec-template.ts +1 -1
  19. package/audits/sql-mod.sh +11 -14
  20. package/audits/ufs-strings.awk +164 -0
  21. package/audits/ufs.sh +10 -188
  22. package/core/operating-model.md +8 -8
  23. package/dispatch/edit_rules.md +8 -6
  24. package/dispatch/lib.sh +41 -26
  25. package/dispatch/lifecycle.md +12 -5
  26. package/dispatch/name_architecture.md +8 -3
  27. package/dispatch/verify.md +1 -1
  28. package/dispatch/write_any.md +10 -3
  29. package/dispatch/write_changelog.md +7 -4
  30. package/dispatch/write_go.md +1 -1
  31. package/dispatch/write_http.md +5 -7
  32. package/dispatch/write_python.md +1 -1
  33. package/dispatch/write_rust.md +17 -1
  34. package/dispatch/write_shell.md +1 -1
  35. package/dispatch/write_spec.md +3 -1
  36. package/dispatch/write_sql.md +28 -6
  37. package/dispatch/write_ts_adhere_bun.md +11 -0
  38. package/dispatch/write_zig.md +53 -21
  39. package/docs/CHANGELOG.md +10 -0
  40. package/docs/CHANGELOG_VOICE.md +11 -2
  41. package/docs/EXECUTE_DOC_READS.md +10 -10
  42. package/docs/HARNESS_VERIFY_OUTPUT.md +6 -3
  43. package/docs/JUDGMENTS.md +156 -0
  44. package/docs/LIFECYCLE_PATTERNS.md +26 -16
  45. package/docs/LOGGING_STANDARD.md +39 -19
  46. package/docs/ORLY_ARCHITECTURE.md +77 -6
  47. package/docs/RELEASE_TEMPLATE.md +21 -5
  48. package/docs/REST_API_DESIGN_GUIDELINES.md +86 -21
  49. package/docs/RULE_ENFORCEMENT.md +6 -6
  50. package/docs/SCHEMA_CONVENTIONS.md +24 -3
  51. package/docs/TEMPLATE.md +4 -4
  52. package/docs/VERIFY_TIERS.md +2 -2
  53. package/docs/greptile-learnings/RULES.md +81 -26
  54. package/llms.txt +46 -34
  55. package/package.json +6 -1
  56. package/packs/language/go/rules.md +1 -1
  57. package/packs/language/python/rules.md +1 -1
  58. package/packs/language/rust/rules.md +17 -1
  59. package/packs/language/shell/rules.md +1 -1
  60. package/registry.json +22 -7
  61. package/schemas/profile.schema.json +48 -5
  62. package/skills/orly-babysit-prs/SKILL.md +87 -34
  63. package/skills/orly-spec-new/SKILL.md +19 -6
  64. package/skills/orly-write-integration-test/SKILL.md +4 -4
  65. package/skills/orly-write-unit-test/SKILL.md +10 -1
  66. package/src/cli.test.ts +2 -2
  67. package/src/cli.ts +19 -75
  68. package/src/cli_help.ts +69 -0
  69. package/src/command_limits.ts +20 -0
  70. package/src/command_process.test.ts +109 -0
  71. package/src/command_process.ts +88 -0
  72. package/src/command_runner.test.ts +88 -0
  73. package/src/command_runner.ts +33 -0
  74. package/src/comprehension_cache.test.ts +123 -0
  75. package/src/config.test.ts +5 -4
  76. package/src/config.ts +26 -164
  77. package/src/config_discovery.ts +159 -0
  78. package/src/config_validation.test.ts +56 -0
  79. package/src/config_validation.ts +25 -0
  80. package/src/criteria.test.ts +1 -1
  81. package/src/criteria.ts +10 -26
  82. package/src/criteria_spec.ts +12 -20
  83. package/src/criteria_support.ts +2 -19
  84. package/src/doc_reads.test.ts +42 -0
  85. package/src/doc_rules.ts +2 -2
  86. package/src/evaluation_resources.test.ts +64 -0
  87. package/src/execution/config.ts +22 -0
  88. package/src/execution/plan.test.ts +65 -0
  89. package/src/execution/plan.ts +51 -0
  90. package/src/gates.ts +9 -6
  91. package/src/gates_spec.test.ts +52 -6
  92. package/src/gates_test_support.ts +9 -7
  93. package/src/install.test.ts +38 -222
  94. package/src/install.ts +117 -308
  95. package/src/install_loaders.test.ts +203 -0
  96. package/src/install_nested.test.ts +2 -2
  97. package/src/install_packs.test.ts +66 -6
  98. package/src/installation/hooks.ts +63 -0
  99. package/src/installation/lock.test.ts +97 -0
  100. package/src/installation/lock.ts +56 -0
  101. package/src/installation/migration.test.ts +212 -0
  102. package/src/installation/migration.ts +65 -0
  103. package/src/installation/plan.ts +96 -0
  104. package/src/installation/transaction.ts +126 -0
  105. package/src/installation_preservation.test.ts +48 -0
  106. package/src/judgments/advice.test.ts +38 -0
  107. package/src/judgments/advice.ts +32 -0
  108. package/src/judgments/command.integration.test.ts +47 -0
  109. package/src/judgments/command.ts +90 -0
  110. package/src/judgments/constants.ts +55 -0
  111. package/src/judgments/evidence.test.ts +48 -0
  112. package/src/judgments/evidence.ts +34 -0
  113. package/src/judgments/files.test.ts +62 -0
  114. package/src/judgments/files.ts +73 -0
  115. package/src/judgments/questions.test.ts +19 -0
  116. package/src/judgments/questions.ts +85 -0
  117. package/src/judgments/replay.test.ts +43 -0
  118. package/src/judgments/replay.ts +66 -0
  119. package/src/judgments/runner.integration.test.ts +165 -0
  120. package/src/judgments/runner.ts +97 -0
  121. package/src/judgments/scan.test.ts +19 -0
  122. package/src/judgments/scan.ts +40 -0
  123. package/src/judgments/syntax.test.ts +115 -0
  124. package/src/judgments/syntax.ts +71 -0
  125. package/src/judgments/syntax_worker.ts +70 -0
  126. package/src/judgments/test_support.ts +60 -0
  127. package/src/judgments/transport.integration.test.ts +63 -0
  128. package/src/judgments/transport.ts +35 -0
  129. package/src/judgments/types.test.ts +43 -0
  130. package/src/judgments/types.ts +66 -0
  131. package/src/judgments/wire.test.ts +48 -0
  132. package/src/judgments/wire.ts +40 -0
  133. package/src/loaders.test.ts +13 -16
  134. package/src/loaders.ts +28 -10
  135. package/src/model.test.ts +20 -3
  136. package/src/model.ts +7 -18
  137. package/src/pack_hygiene.test.ts +42 -1
  138. package/src/pack_hygiene.ts +18 -8
  139. package/src/references.ts +15 -7
  140. package/src/release_inventory.test.ts +80 -0
  141. package/src/render.test.ts +1 -1
  142. package/src/render.ts +3 -8
  143. package/src/required_scanner.test.ts +36 -0
  144. package/src/review_poll.test.ts +158 -0
  145. package/src/scanner_scope.test.ts +202 -0
  146. package/src/setup.test.ts +9 -6
  147. package/src/spec_baseline.test.ts +1 -1
  148. package/src/spec_completion.test.ts +74 -0
  149. package/src/spec_obligations.ts +64 -0
  150. package/src/spec_rehearsal.test.ts +182 -0
  151. package/src/spec_template_io.test.ts +11 -9
  152. package/src/surfaces.test.ts +2 -0
  153. package/src/surfaces.ts +1 -1
  154. package/src/validation.ts +7 -4
  155. package/src/verify.test.ts +18 -2
  156. package/src/verify.ts +7 -3
@@ -2,9 +2,9 @@
2
2
 
3
3
  A three-part proof that generated `AGENTS.md` still holds the line after edits:
4
4
 
5
- 1. **Deterministic layer** — `audits/agents-md.sh` (mechanical, fast, runs in `pre-commit`).
5
+ 1. **Deterministic layer** — `audits/agents-md.sh` (mechanical, fast; declared conformance and the governance pre-push audit run it).
6
6
  2. **Prompt-invariance layer** — this file. A Large Language Model (LLM) agent reads `AGENTS.md` and answers every question below. Every answer must be **YES**. A NO means the ruleset regressed.
7
- 3. **Evidence layer** — `orly verify --write-evidence` records the source commit, registry digest, profile checks, and prompt result.
7
+ 3. **Evidence layer** — `orly verify --write-evidence` records checkout HEAD, profile checks, and the declared prompt result. It records no registry digest.
8
8
 
9
9
  Run this suite before and after an operating-model change. Both runs must produce the same all-YES result. A pass that flips to NO is a broken invariant.
10
10
 
@@ -35,6 +35,7 @@ The questionnaire is organised by scenario. Each scenario corresponds to a momen
35
35
  | 1.3 | Must `orly-spec-new` be invoked rather than hand-rolling the spec file? | YES |
36
36
  | 1.4 | Is the agent forbidden from writing code before CHORE(open) completes its 4 steps? | YES |
37
37
  | 1.5 | When a spec contradicts a rule, must the spec be amended (not the rule weakened)? | YES |
38
+ | 1.6 | Does authoring copy only the template's executable body, commit a new milestone on the detected default branch, and keep updates to an existing stream on its active branch? | YES |
38
39
 
39
40
  ### Scenario 2 — Brainstorming leads to a new spec
40
41
 
@@ -59,10 +60,10 @@ The questionnaire is organised by scenario. Each scenario corresponds to a momen
59
60
 
60
61
  | # | Question | Expected |
61
62
  |---|---|---|
62
- | 4.1 (UI) | For every `*.tsx`/`*.jsx` under `ui/packages/app/`, must raw HTML be substituted with a design-system primitive when one exists? | YES |
63
- | 4.1a (UI) | For every `*.tsx`/`*.jsx` under `ui/packages/{app,website}/`, does DESIGN TOKEN GATE block arbitrary `*-[...]` Tailwind classes (`text-[Npx]`, `leading-[...]`, `tracking-[...]`, `max-w-[Npx|Nch]`, `text-[clamp(...)]`, raw palette colours) when an equivalent token utility exists in `ui/packages/design-system/src/theme.css`? | YES |
63
+ | 4.1 (UI) | For production `*.tsx`/`*.jsx` under `ui/packages/{app,website}/`, excluding the documented test files and browser-test specs, must raw HTML use a design-system primitive when one exists? | YES |
64
+ | 4.1a (UI) | For production `*.tsx`/`*.jsx` under `ui/packages/{app,website}/`, excluding the documented test files and browser-test specs, does DESIGN TOKEN GATE block arbitrary Tailwind values when an equivalent token utility exists in `ui/packages/design-system/src/theme.css`? | YES |
64
65
  | 4.1b (UI) | Is the DESIGN TOKEN GATE override `// DESIGN TOKEN: SKIPPED per user override (reason: ...)` user-only — i.e. auto-mode does NOT cover it, and reasons must cite a concrete external constraint (not "looks the same" / "shorter to write")? | YES |
65
- | 4.1c (UI) | Does the project-side `audits/design-tokens.sh` audit run as part of `make lint` (`_website_lint` + `_app_lint`) and block on any arbitrary that has a token equivalent? (Default scope: full ui/packages working tree via `git ls-files`; the diff-scoped mode is retired.) | YES |
66
+ | 4.1c (UI) | Does the design-token façade require a clean project-side `audits/design-tokens.sh` run before CONFORM and delegate its `make lint` integration to the consumer repository, with full tracked working-tree scope and the retired diff mode rejected? | YES |
66
67
  | 4.2 (Zig) | For every `*.zig` Edit/Write outside `vendor/`/`third_party/`/`.zig-cache/`, does ZIG GATE fire? | YES |
67
68
  | 4.3 (Zig) | Must FILE SHAPE DECISION print before the first Write to a new `*.zig` under `src/` — and is that override **not** covered by auto-mode? | YES |
68
69
  | 4.4 (Zig) | Does PUB GATE delegate mechanical consumer-grep to `zlint`'s `unused-decls: error` rule (run by `make lint`), leaving the gate body to enforce shape verdict + no-inheritance + per-edit proof? | YES |
@@ -73,22 +74,23 @@ The questionnaire is organised by scenario. Each scenario corresponds to a momen
73
74
  | 4.6 (TS/JS) | Are milestone IDs (`M{N}_{NNN}`, `§X.Y`, `T7`, `dim 5.8.15`) banned in source files (incl. tests)? | YES |
74
75
  | 4.7 (TS/JS) | Does RULE UFS require string literals used in ≥2 sites to become a named constant? | YES |
75
76
  | 4.7a (TS/JS/Zig) | Does RULE UFS extend to numeric literals carrying semantic meaning (conversion factors, thresholds, sub-cent rates) — required to become a named constant even at the first use site, with a pin-test carve-out? | YES |
76
- | 4.7b (cross-runtime) | Must cross-runtime constants share an identical SCREAMING_SNAKE name across Zig + TS + JS (e.g. `NANOS_PER_USD` everywhere, never `NANOS_PER_DOLLAR` in one and `NANOS_PER_USD` in another)? | YES |
77
- | 4.7c (test fixtures) | Are test fixtures, mock returns, and assertion arguments **not** RULE UFS exceptions — i.e. wire-format strings and semantic numerics in test code must use the named constant just like production code does? | YES |
77
+ | 4.7b (cross-runtime) | Must cross-runtime constants preserve the same semantic name across languages, allowing only the case changes a language requires? | YES |
78
+ | 4.7c (test fixtures) | Outside the Rust test exemptions in `dispatch/write_rust.md`, must wire-format strings and semantic numerics in fixtures, mock returns, and assertions use the named constants required for production code? | YES |
78
79
  | 4.8 (Shell) | Are shell scripts subject to the File & Function Length Gate (≤350 / ≤50 / ≤70)? | YES |
79
80
  | 4.8a (Length) | Is 350 a **ceiling rather than a budget** — must a source file be split below the cap whenever the agent's own rubric (test coverage, simplicity, optimisation, performance, concurrency, adversarial review) says two files beat one, with two ~150-line files a good outcome rather than an over-split, and is a file with no headroom left for its own tests already too long? | YES |
80
81
  | 4.8b (Length scope) | Does the File & Function Length Gate cover **test files and extensionless executables** too — no `.test.`/`_test`/`/tests/` carve-out anywhere, and an extensionless staged file carrying a shebang gated by `dispatch_add_shebang_files` because an ambiguous extension makes the gate fire by default? | YES |
81
82
  | 4.9 (Shell) | Must `gitleaks` pass before any commit/push? | YES |
82
83
  | 4.10 (CI) | Are CI/CD edits (`.github/workflows/**`, deploy configs) **forbidden without explicit user approval** even in auto mode? | YES |
83
84
  | 4.11 (Bun) | For `*.ts`/`*.tsx`/`*.js`/`*.jsx` edits, does AGENTS.md route to `dispatch/write_ts_adhere_bun.md` (TS FILE SHAPE DECISION at PLAN, const/import/Bun-primitive discipline)? | YES |
84
- | 4.12 (Logging) | For every Edit/Write that adds/removes/changes a log emit (Zig `std.log.*`/`std.debug.print`/`obs.scoped`, Rust `tracing::*`/print macros under `rustd/`, TS/JS `console.*`/custom logger, shell `echo` to `&2`), does LOGGING GATE require reading `docs/LOGGING_STANDARD.md` and printing the per-edit gate block citing §3 (wire format) / §4 (severity) / §5 (error codes) / §6 (PII) / §7, §8, or §8A (language binding) / §10A (tightenings)? | YES |
85
- | 4.13 (Logging) | Are `std.debug.print`, Rust `println!`/`eprintln!`/`dbg!`, Rust tracing without `event` or with positional formatting, and `console.log` in their non-test production scopes automatic blocking violations, with no "temporary" carve-out? | YES |
85
+ | 4.12 (Logging) | When an edit changes a log emit in the façade's production scopes, must the agent read `docs/LOGGING_STANDARD.md` and print the one-line gate result, using the full section-citing block on a violation? | YES |
86
+ | 4.13 (Logging) | Do direct diagnostic print macros, Rust tracing without `event` or with positional formatting, and `console.log` block in their production scopes, while intentional program-interface stream output requires a non-empty `// logging: <reason>` annotation and has no temporary carve-out? | YES |
86
87
  | 4.14 (Logging) | Must a new registry-scheme `error_code` reference (agentsfleet: `UZ-XXX-NNN`) land in the same commit as its registry entry (used-but-undeclared = blocking)? | YES |
87
88
  | 4.15 (Lifecycle) | For every Edit/Write that adds/reshapes a lifecycle method in `*.zig` (`pub fn init|deinit|close|release|destroy|shutdown|dispose|free`) or an `errdefer`/`defer` adjacent to allocation, does LIFECYCLE GATE require reading `docs/LIFECYCLE_PATTERNS.md` and printing the per-edit gate block? | YES |
88
89
  | 4.16 (Lifecycle) | Is `defer X.free(Y)` + `errdefer X.free(Y)` on the same allocation in the same scope a blocking violation? | YES |
89
- | 4.17 (Lifecycle) | Must the LAST `errdefer` in init lexically precede the LAST allocation it protects (no batched-at-bottom errdefer)? | YES |
90
- | 4.18 (Spec template) | For every Edit/Write to a spec under `docs/v*/{pending,active,done}/` or to `docs/TEMPLATE.md`, does SPEC TEMPLATE GATE forbid time/effort estimates, complexity ratings, percentage-complete fields, owners, and dates (per `TEMPLATE.md` "Prohibited" section)? | YES |
91
- | 4.19 (Spec template) | Does `spec-template.sh` run as part of `make lint` and block on prohibited-section regex matches? | YES |
90
+ | 4.17 (Lifecycle) | Must each fallible acquisition in a multi-step init be followed immediately by its `errdefer`, with no batched cleanup at the bottom? | YES |
91
+ | 4.17a (Reviewer duties) | Do the façades accurately limit machine claims to implemented checks, while requiring review of cross-module strings, empty cleanup pairs, arena lifetime, cleanup repeatability and log message/field size? | YES |
92
+ | 4.18 (Spec template) | For every Edit/Write to a spec under `docs/v*/{pending,active,done}/` or to `docs/TEMPLATE.md`, does SPEC TEMPLATE GATE forbid time/effort estimates, complexity ratings, percentage-complete fields, assigned owners, and implementation dates (per `TEMPLATE.md` "Prohibited" section)? | YES |
93
+ | 4.19 (Spec template) | Does `audits/spec-template.sh` reject prohibited sections, with `orly gate pr` invoking it through the `spec.gate` criterion? | YES |
92
94
  | 4.20 (Doc read) | For every Edit/Write whose file pattern matches a row in the EXECUTE doc-reads table, does DOC READ GATE require a `📖 DOC READ: <path>` proof-line — either citing §N applied OR the cited-skip variant — before the turn's first triggering edit? | YES |
93
95
  | 4.21 (Doc read) | Is the `📖 DOC READ:` proof-line required **per triggered document per turn** (not once per session — every new turn that edits the trigger surface needs a fresh line)? | YES |
94
96
  | 4.22 (Doc read) | Are auto-mode and "I read this earlier" both invalid grounds to skip the per-turn proof-line — already-loaded sections are cited rather than re-read, but the line itself is never skipped? | YES |
@@ -106,7 +108,7 @@ The questionnaire is organised by scenario. Each scenario corresponds to a momen
106
108
  | # | Question | Expected |
107
109
  |---|---|---|
108
110
  | 5.1 | Is the agent required to verify CWD is inside the active worktree before resuming (`pwd` + `git worktree list`)? | YES |
109
- | 5.2 | Must the agent re-read RULES.md when sub-task shape changes (new layer/language/resume after break)? | YES |
111
+ | 5.2 | Must the agent section-scan and re-read the relevant `docs/greptile-learnings/RULES.md` sections when the sub-task shape changes, such as a new layer or language? | YES |
110
112
  | 5.3 | If the spec is in `active/`, does CHORE(close) follow the final implementation commit or an explicit request to park, while Section commits continue implementation? | YES |
111
113
  | 5.4 | If unexpected changes appear in files the agent is editing, must the agent stop and ask (not overwrite as stale)? | YES |
112
114
 
@@ -117,16 +119,16 @@ The questionnaire is organised by scenario. Each scenario corresponds to a momen
117
119
  | 6.1 | Does CONFORM enumerate every gate as a row in its verdict block and invoke the active profile's `conform` commands? | YES |
118
120
  | 6.2 | Does any remaining violation in CONFORM return the lifecycle to EXECUTE without advancing? | YES |
119
121
  | 6.3 | Is `/orly-write-unit-test` the FIRST verify action, with skipping = CHORE(close) violation? | YES |
120
- | 6.4 | Are `make lint` + `make test` always required (tier 1)? | YES |
122
+ | 6.4 | Must verification run the repository-declared commands, with narrower package checks unable to replace the full boundary? | YES |
121
123
  | 6.5 | Is the repository's declared `verify.integration` required when the diff touches HTTP/schema/DB/Redis or integration-test surfaces? | YES |
122
- | 6.6 | Is at least one declared `verify.integration` run from clean state required per branch before ship-ready (where the repository declares one)? | YES |
124
+ | 6.6 | Before the Pull Request, must a code-changing branch run the full declared integration suite where one exists, following the repository's declared command and applicable reset recipe, while a branch with no code skips integration? | YES |
123
125
  | 6.7 | Are package-scoped runners (`bun run test`, `vitest <file>`, `zig build test` w/o integration) explicitly **not** verification? | YES |
124
- | 6.8 | Must memleak evidence (last 3 lines verbatim) appear in PR Session Notes when touching `src/http/**` / `src/cmd/serve.zig` / allocator wiring? | YES |
126
+ | 6.8 | Must memory-leak evidence be pasted into Pull Request Session Notes, or its Continuous Integration (CI) URL cited? | YES |
125
127
  | 6.9 | Does CHORE(open) DECLARE the `Test Baseline:` line in the spec header while measuring nothing, with the counts from the repository's declared `verify.*` commands landing before the Pull Request (a product pack may name a dedicated counter)? | YES |
126
128
  | 6.9a | Does the baseline identify the full comparison commit, with matching run evidence or an isolated checkout, declared unit and integration counts, and a report reference? | YES |
127
129
  | 6.9b | Does `orly gate pr` reject missing declared baseline counts, allow reasoned `n/a` only without code or baseline lanes, and run all declared verification commands independently of custom hooks? | YES |
128
130
  | 6.9c | Does setup require `conform` and a named `verify.*` command, allowing `verify.docs` without application test suites while reporting incomplete configuration? | YES |
129
- | 6.10 | Does VERIFY end with a Test Delta row (growth vs the branch point's baseline) plus a lacking-areas verdict, with zero/negative unit delta on a code-adding diff requiring justification or a return to EXECUTE? | YES |
131
+ | 6.10 | Does VERIFY end with a Test Delta row against the recorded comparison revision, with zero or negative unit growth on a code-adding diff requiring justification or a return to EXECUTE? | YES |
130
132
  | 6.11 | Do the lifecycle stage runbooks (CHORE(open/close) checklists, PLAN expansions, deferral quote format, pre-PR gates, LAND) resolve from `dispatch/lifecycle.md`, with AGENTS.md keeping each stage's binding essence? | YES |
131
133
 
132
134
  ### Scenario 7 — Review discipline before merge
@@ -138,7 +140,9 @@ The questionnaire is organised by scenario. Each scenario corresponds to a momen
138
140
  | 7.3 | Is gstack `/review` the single review route for every runtime (Claude, Codex, OpenCode, Amp) — local and pre-commit, distinct from post-push reviewer triage? | YES |
139
141
  | 7.4 | Does `orly-babysit-prs` run after every push and stop only on two consecutive empty polls? | YES |
140
142
  | 7.5 | Is using `gh pr checks --watch` for greptile explicitly disallowed? | YES |
141
- | 7.6 | If an MCP-backed skill is unavailable, must PR Session Notes record the skip + a "rerun before merge" note? | YES |
143
+ | 7.11 | Must every review poll fetch all review, line-comment and summary pages, keep failed or empty check discovery incomplete, and bind both quiet polls to the same pushed revision? | YES |
144
+ | 7.12 | Does a disputed finding require the owner's item-specific decision, with historical false-positive labels providing context rather than automatic suppression? | YES |
145
+ | 7.6 | If the required reviewer is unavailable, must Pull Request Session Notes record the reason, timestamp, and rerun-before-merge requirement, while the required unit-test skill is never skipped or deferred? | YES |
142
146
  | 7.7 | Is merging/closing/ready-from-draft of another user's PR forbidden without explicit approval? | YES |
143
147
  | 7.8 | Does AGENTS.md require an Indy-acked verbatim quote (in PR Session Notes or the spec's Discovery section, format `> Indy (YYYY-MM-DD HH:MM): "<quote>"`) for any claim that a spec Section/Dimension was "deferred to follow-up" — and does an agent-unilateral deferral count as incomplete scope (not deferral), blocking CHORE(close) until either the item lands or the quote is captured? | YES |
144
148
  | 7.9 | Does AGENTS.md treat `HANDOFF.md` (or `HANDOFF_*.md` at any depth) as a faithful state report — i.e. must a pickup agent reading a HANDOFF that claims items were deferred without ack-quotes treat those items as in-scope and surface the contradiction to Kishore before continuing? | YES |
@@ -175,7 +179,7 @@ The questionnaire is organised by scenario. Each scenario corresponds to a momen
175
179
 
176
180
  | # | Question | Expected |
177
181
  |---|---|---|
178
- | 11.1 | Pre-v0.30.0, is the table-removal flow rm-file + rm-embed + rm-migration-array (no `ALTER TABLE`/`DROP TABLE`/`SELECT 1;` markers)? | YES |
182
+ | 11.1 | Only under the explicit `product.agentsfleet` pack, is its pre-v0.30.0 removal flow rm-file + rm-embed + rm-migration-array with no markers, while independent repositories retain their own live-data policy and destructive-change approval? | YES |
179
183
  | 11.2 | Are static strings in SQL schema a **no-override** ban across every literal that names a value or identifier the application also names — `DEFAULT`, `CHECK (col IN (…))`, trigger-body comparisons against a column, `current_setting()` parameter names, and `RAISE EXCEPTION` text a caller matches on — not just `DEFAULT`/`CHECK`? | YES |
180
184
 
181
185
  ### Scenario 12 — Auto-mode boundary (added)
@@ -184,16 +188,16 @@ The questionnaire is organised by scenario. Each scenario corresponds to a momen
184
188
  |---|---|---|
185
189
  | 12.1 | Does auto-mode autonomy require BOTH auto-mode-active AND (active spec OR forward-looking start instruction) before commit/push/PR proceed without re-asking? | YES |
186
190
  | 12.2 | Do action-triggered guards still block under auto mode (autonomy bypasses none)? | YES |
187
- | 12.3 | Under standing authorization, does `gh pr create` default to `--draft`, requiring the user to explicitly ask for a ready PR? | NO |
191
+ | 12.3 | Under standing authorization, does `gh pr create` omit `--draft` unless the user asks for a draft? | YES |
188
192
 
189
193
  ### Scenario 13 — Ruleset changes (Invariance Suite meta-gate)
190
194
 
191
195
  | # | Question | Expected |
192
196
  |---|---|---|
193
197
  | 13.1 | When the agent edits `core/**`, `packs/**`, `schemas/**`, `src/**`, `registry.json`, generated `AGENTS.md`, `audits/agents-md.md`, governance hooks, or any dispatch entry, does `edit_rules` require the audit and questionnaire before declaring done? | YES |
194
- | 13.2 | Is the agent forbidden from self-overriding the Invariance Suite Gate? (Only the user may bypass at push time via `SKIP_INVARIANCE_PUSH=1`.) | YES |
195
- | 13.3 | Does generated evidence bind the source commit, registry digest, profile results, and prompt-comprehension result? | YES |
196
- | 13.4 | Does the pre-push hook run the deterministic chain and regenerate evidence against the pushed commit, with live prompt evaluation deliberately off the push path (the hook records `--llm-result not-required` with its rationale; `make llmevals` is the manual matrix)? | YES |
198
+ | 13.2 | Is the agent forbidden from self-overriding the Invariance Suite Gate, with governance pushes running the required audit? | YES |
199
+ | 13.3 | Does generated evidence record checkout HEAD, profile-check results, and the declared prompt result, without recording a registry digest? | YES |
200
+ | 13.4 | Does pre-push run the deterministic chain and regenerate evidence for checkout HEAD, without forwarding pushed revisions to the verifier, and record `--llm-result not-required` while live comprehension runs manually? | YES |
197
201
 
198
202
  ### Scenario 14 — Communication discipline
199
203
 
@@ -204,7 +208,7 @@ The questionnaire is organised by scenario. Each scenario corresponds to a momen
204
208
  | 14.3 | Does AGENTS.md require a pre-send self-check scanning outgoing text for unexpanded acronyms (regex `\b[A-Z][A-Z0-9]{1,5}\b`), treating skip as on par with skipping a gate (`ACRONYM CHECK: SKIPPED per user override (reason: ...)`)? | YES |
205
209
  | 14.4 | Does the tone rule permit dry humour and swear words, while requiring that technical clarity is never traded for it? | YES |
206
210
  | 14.5 | Does the verification done-message use ✅ / 🔴 / 🟠 glyphs and the explicit format defined in `dispatch/verify.md`? | YES |
207
- | 14.6 | Does AGENTS.md identify the human as Kishore (casual handle Indy) and the agent as Oracle (casual handle Orly), with address tags 🤠 Indy / 🦉 Orly so addressing resolves unambiguously? | YES |
211
+ | 14.6 | Does AGENTS.md identify the human as Kishore (casual handle Indy) and the agent as Oracle (casual handle Aiwa), with address tags 🤠 Indy / 🦉 Aiwa so addressing resolves unambiguously? | YES |
208
212
 
209
213
  ### Scenario 15 — Architecture-edit ordering
210
214
 
@@ -226,7 +230,7 @@ The questionnaire is organised by scenario. Each scenario corresponds to a momen
226
230
 
227
231
  | # | Question | Expected |
228
232
  |---|---|---|
229
- | 17.1 | Does `conn.query()` require `.drain()` in the same function before `deinit()`, with the repository's own convention gate verifying it? | YES |
233
+ | 17.1 | Must query results drain before their connection is released, including early exits, using wrapper-owned cleanup where provided and reviewing cleanup alongside any declared check? | YES |
230
234
  | 17.2 | Is `conn.exec()` the prescribed alternative when no rows are needed? | YES |
231
235
 
232
236
  ### Scenario 18 — Commit/push hygiene & worktree isolation
@@ -242,7 +246,7 @@ The questionnaire is organised by scenario. Each scenario corresponds to a momen
242
246
 
243
247
  | # | Question | Expected |
244
248
  |---|---|---|
245
- | 19.1 | Does CONFORM include a combined awk pass over `git diff -U0 HEAD` that emits `MS-ID:`, `PUB:`, and `UI:` hits? | YES |
249
+ | 19.1 | Does CONFORM include `audits/msid-ui.sh`, whose default staged diff emits milestone-identifier and interface-substitution hits, with public-declaration checks handled separately? | YES |
246
250
  | 19.2 | Is non-empty awk output a violation that must be addressed before CONFORM passes? | YES |
247
251
 
248
252
  ### Scenario 20 — Rule extension protocol
@@ -265,10 +269,10 @@ The questionnaire is organised by scenario. Each scenario corresponds to a momen
265
269
 
266
270
  | # | Question | Expected |
267
271
  |---|---|---|
268
- | 22.1 | When `make harness-verify` (the pre-commit ceremony) invokes `ufs.sh`, `design-tokens.sh`, `deinit-pairs.sh`, `error-codes.sh`, `logging.sh`, or `spec-template.sh`, do those scripts default to scanning the full working tree via `git ls-files` — so staged-but-not-yet-committed content is in scope? | YES |
272
+ | 22.1 | Must each audit use its documented scope: source audits select their full source trees by default, while spec bulk scans use pending/active working files for prohibited patterns and `--staged` checks full readiness from index bytes? | YES |
269
273
  | 22.2 | Is the `--diff` (BASE...HEAD) mode of `ufs.sh` and `design-tokens.sh` retired — explicitly rejected with exit 2 and a pointer to the gate body? | YES |
270
274
  | 22.3 | Does `msid-ui.sh` (renamed from `combined.sh` after the PUB clause moved to zlint + agent chat-output discipline) remain the lone diff-shaped audit (still default `--staged`) — because its sub-checks (MS-ID / UI substitution) assert on *added* lines, not file state, and `git diff --cached` reads the index? | YES |
271
- | 22.4 | Does every dispatch façade that absorbed a converted full-codebase leaf audit (`dispatch/write_any.md` ← logging/error-registry/UFS, `dispatch/write_ts_adhere_bun.md` ← design-token, `dispatch/write_zig.md` ← lifecycle/deinit, `dispatch/write_spec.md` ← spec-template) carry a "Scope" section documenting full-codebase semantics and the staged-content forcing function? | YES |
275
+ | 22.4 | Do the relevant dispatch scope sections describe each source audit and its staged mode, while `dispatch/write_spec.md` distinguishes index readiness, single-file working-copy readiness, and prohibited-only bulk scans? | YES |
272
276
 
273
277
  ### Scenario 23 — Agent comprehension robustness
274
278
 
@@ -280,9 +284,9 @@ The questions force *proof of reading* over *recall*.
280
284
 
281
285
  | # | Question | Expected |
282
286
  |---|---|---|
283
- | 23.1 | When answering a rule-specific question, must the agent quote the dispatch **façade** (`dispatch/<entry>.md`), not the one-line dispatch-index summary — because the index is explicitly "a floor, not a ceiling" and paraphrasing the façade is a hallucination risk? | YES |
284
- | 23.2 | When a recalled memory, `CLAUDE.md` snippet, or prior-session note conflicts with the current `AGENTS.md`/gate body, must the agent defer to the file-on-disk and surface the conflict (recall is stale-by-default)? | YES |
285
- | 23.3 | Must override strings be reproduced **verbatim** (`<GATE>: SKIPPED per user override (reason: ...)`) and never paraphrased, since the harness matches the literal string? | YES |
287
+ | 23.1 | Must the agent section-scan the triggered dispatch façade and read the sections the change touches, instead of treating the dispatch-index summary as the full rule? | YES |
288
+ | 23.2 | Must the agent read the current triggered rules and surface a mid-task conflict before continuing, with a contradicting spec amended to match the rule? | YES |
289
+ | 23.3 | Must a user-invoked action-guard override use the specified `<GATE>: SKIPPED per user override (reason: ...)` form immediately before the edit? | YES |
286
290
  | 23.4 | When two rules fire on the same edit (e.g. PUB + LIFECYCLE on `pub fn init`, or a spec that contradicts a rule), must the agent apply **both**/escalate rather than silently picking one? | YES |
287
291
  | 23.5 | For an auto-mode / override question, must the agent trace the full conditional chain (auto-mode AND (active-spec OR start-instruction); action-triggered guards still block) rather than collapsing it to "auto mode = yes"? | YES |
288
292
  | 23.6 | Is the negative-test harness (`evals/test-agents-md.sh`) required to pass — proving each deterministic check still *bites* — whenever `audits/agents-md.sh` itself changes? | YES |
@@ -301,7 +305,7 @@ memory file — the exact drift the `## Memory Discipline` section exists to pre
301
305
  |---|---|---|
302
306
  | 24.1 | Is writing to `**/memory/*.md` or any `MEMORY.md` forbidden, because the harness neither records nor recalls them under `autoMemoryEnabled: false`? | YES |
303
307
  | 24.2 | Does a rule that fires on a file-type / lifecycle trigger belong in `dispatch/<entry>.md` behind its gate, not in a memory note? | YES |
304
- | 24.3 | Does in-flight state (branch / PR / next steps) belong in a `HANDOFF_*.md` + PR Session Notes + the spec, surfaced by the `pickup` / `handoff` skills? | YES |
308
+ | 24.3 | Does in-flight state such as the branch, Pull Request, and next steps belong in `HANDOFF_*.md`, Pull Request Session Notes, and the spec? | YES |
305
309
  | 24.4 | Is a durable architecture fact homed in the product repo's `docs/architecture/*.md`, not memory? | YES |
306
310
  | 24.5 | If a fact has no firing gate and no doc home, is the correct move to add the rule (Rule extension protocol) or drop it — never to create a memory file? | YES |
307
311
 
@@ -309,7 +313,7 @@ memory file — the exact drift the `## Memory Discipline` section exists to pre
309
313
 
310
314
  The M126 adversarial review mined ghostty's Allocator and concurrency practice into eleven
311
315
  citable rules in `dispatch/write_zig.md`. These questions force *reading the façade rule
312
- bodies* (per 23.1 — quote the façade, not the index), because their failure mode is an
316
+ bodies* (per 23.1 — read the façade, not just the index), because their failure mode is an
313
317
  editing agent that omits the discipline the way the liveness sweeper diverged from its
314
318
  siblings.
315
319
 
@@ -319,9 +323,9 @@ siblings.
319
323
  | 25.2 (A2) | Does rule A2 require an `errdefer` immediately after each fallible acquisition in a multi-step init (never batched at the bottom), with `errdefer comptime unreachable` after the last fallible op? | YES |
320
324
  | 25.3 (A3) | Does rule A3 require leaf structures to take `alloc` per call and store nothing, reserving a stored `alloc` field for lifecycle roots only? | YES |
321
325
  | 25.4 (A4) | Does rule A4 make an arena the ownership unit (`_arena` per config/request object, scratch arena per transient op, arena-in-message across a thread boundary) and forbid using an arena to mask a missing free in a reusable helper? | YES |
322
- | 25.5 (A5) | Does rule A5 require ownership stated in the fixed phrases "caller must free" / "takes ownership" on every allocating public fn plus `self.* = undefined` poisoning in every deinit — with the phrase/poison checks blocking inside the discipline roster and advisory outside? | YES |
326
+ | 25.5 (A5) | Does rule A5 require ownership stated in the fixed phrases "caller must free" / "takes ownership" on every allocating public fn plus `self.* = undefined` poisoning in every deinit — with these requirements enforced by review rather than repository lint? | YES |
323
327
  | 25.6 (A6) | Does rule A6 require every multi-step init in the roster to carry comptime-erased tripwire fail points and a loop-all-failpoints test under `std.testing.allocator` asserting both that the errdefer chain freed everything and that state rolled back? | YES |
324
- | 25.7 (C1) | Does rule C1 require cross-thread channels to be Single-Producer Single-Consumer (SPSC), with the payload carrying its own allocator and the receiver freeing in a `defer` at the top of the handler? | YES |
328
+ | 25.7 (C1) | Does rule C1 require new cross-thread channels to be Single-Producer Single-Consumer (SPSC), with the payload carrying its own allocator and the receiver freeing in a `defer` at the top of the handler? | YES |
325
329
  | 25.8 (C2) | Does rule C2 define shutdown as stop-signal → join → deinit, explicitly forbidding freeing shared state on a drain timeout while a straggler thread can still touch it? | YES |
326
330
  | 25.9 (C3) | Does rule C3 forbid a blocking push/socket-write while holding a lock the consumer needs (try-instant, else notify + unlock + block + relock), with lock state an explicit parameter? | YES |
327
331
  | 25.10 (C4) | Does rule C4 require exactly one documented mutex per shared aggregate whose doc comment names precisely what it protects, with `lock(); defer unlock();` adjacent? | YES |
@@ -330,17 +334,20 @@ siblings.
330
334
 
331
335
  ### Scenario 26 — Rules propagation
332
336
 
337
+ Questions in this scenario describe the current source package's `.orly/`
338
+ consumer installation. Previous-layout recovery has separate migration proofs.
339
+
333
340
  | # | Question | Expected |
334
341
  |---|---|---|
335
- | 26.1 | Is `registry.json` the canonical profile and pack registry, with `core/operating-model.md` as the global operating-model source? | YES |
336
- | 26.2 | Is every repository's rule set carried by its own commit — `AGENTS.orly.md` beside the repository's own `AGENTS.md` — with **no** symlink from any agent home into this checkout, so a teammate's clone is governed without installing anything? | YES |
337
- | 26.3 | Do consumer repositories carry their orly-managed files as tracked, committed snapshots — rule pages, gate scripts, skills, hooks, and `.oracle/orly.json` — rather than resolving them from `ORLY_ROOT` or a symlink into dotfiles? | YES |
342
+ | 26.1 | Is `registry.json` the canonical registry of core documents, packs, and rules, with `core/operating-model.md` as the operating-model source and command configuration owned by each repository? | YES |
343
+ | 26.2 | Is every repository's rule set carried by its own commit — `.orly/AGENTS.md` reached from the repository's own `AGENTS.md` — without depending on agent-home symlinks into this checkout, while architecture names Kishore's machine-local exception? | YES |
344
+ | 26.3 | Do consumer repositories carry their orly-managed files as tracked, committed snapshots — rule pages, gate scripts, skills, hooks, and `.orly/orly.json` — rather than resolving them from `ORLY_ROOT` or a symlink into dotfiles? | YES |
338
345
  | 26.4 | Are `orly sync`, `orly render`, and `orly validate` gone — `orly update` covering this checkout because pack sources living inside the target are skipped, `orly init --dry-run` covering the preview, and `orly verify` validating the registry on its way through — with every verb run from inside the repository it acts on? | YES |
339
- | 26.5 | Does the `agentsfleet` profile map CONFORM to `make harness-verify` while VERIFY remains behavior proof? | YES |
340
- | 26.6 | Does `README.md` document initialization, explicit synchronization, status, and doctor commands for new repositories? | YES |
346
+ | 26.5 | Does the `agentsfleet` operating model name `make harness-verify` for CONFORM while VERIFY proves behavior, with each repository declaring its actual commands in `.orly/orly.json`? | YES |
347
+ | 26.6 | Does `README.md` document the released initialization, update, doctor, and gate commands for new repositories? | YES |
341
348
  | 26.7 | Does `orly gate pr` discover a spec closed to `done/` on the branch (its `Branch:` header names the branch) and run the spec criteria — including `spec.moved`, `spec.baseline`, `spec.ordering`, and `spec.deferrals` — instead of skip-passing as spec-less? | YES |
342
- | 26.8 | Does the install write one loader per runtime that has a deterministic way into context — a bare, unbackticked `@AGENTS.orly.md` import line inside the pointer block, a `CLAUDE.md` carrying `@AGENTS.md` where the repository has none, and both rule files in `opencode.json`'s `instructions` — so delivery never depends on an agent noticing a markdown link? | YES |
343
- | 26.9 | Are those loaders the repository's files rather than orly's — absent from `managed`, `CLAUDE.md` written only when missing (a symlink at the host counted as delivery, any other symlink left alone), `opencode.json` edited only by appending a missing `instructions` entry, and an unparseable one left byte for byte? | YES |
349
+ | 26.8 | Does the install write one loader per runtime that has a deterministic way into context — a bare, unbackticked `@.orly/AGENTS.md` import line inside the pointer block, a `CLAUDE.md` carrying `@AGENTS.md` where the repository has none, and both rule files in `opencode.json`'s `instructions` — so delivery never depends on an agent noticing a markdown link? | YES |
350
+ | 26.9 | Are loaders repository-owned and absent from `managed`, with foreign Claude content preserved, an older generated Claude loader refreshed, missing OpenCode instruction entries added through its parsed configuration, and an unparseable OpenCode file left byte for byte? | YES |
344
351
 
345
352
  ### Scenario 27 — Rule-path residence & reachability
346
353
 
@@ -354,8 +361,10 @@ both must hold in every session, in every worktree, after every restart.
354
361
  | # | Question | Expected |
355
362
  |---|---|---|
356
363
  | 27.1 | Does AGENTS.md state that every `dispatch/…`, `docs/…`, and `audits/…` rule path resolves inside **this** repository, materialised by `orly init`/`update` from the packs its own sources selected — so a path the repository lacks means its sources never selected that pack, not a broken reference? | YES |
357
- | 27.2 | Does every rule document an agent is told to read exist inside the repository it is working in — so no read depends on a permission prompt, a second checkout, or a path outside the work tree? | YES |
364
+ | 27.2 | Does every installed rule page live inside its repository, with external reference implementations and upstream guidelines separately identified as read-only sources? | YES |
358
365
  | 27.3 | Must rule docs be cited relative to the installing repository — never through the `~/Projects/dotfiles/` anchor — in dispatch façades, `docs/TEMPLATE.md`, `docs/EXECUTE_DOC_READS.md`, and spec Applicable-Rules lists, with `audits/rule-paths.sh` failing `make audit` on an **anchored** reference in any surface `orly init` materialises (engine-only files exempt)? | YES |
366
+ | 27.4 | Do reusable packs use the consumer's declared commands and policies, with product priming, datastore version boundaries, build graphs and sibling docs paths gated behind explicit product selection? | YES |
367
+ | 27.5 | Do migration registration, cleanup ownership, mounted authorization and structured logging pages agree, without requiring calls through freed pointers or duplicating mounted guards? | YES |
359
368
 
360
369
  ### Scenario 28 — Rule-enforcement ledger & recorded doc reads
361
370
 
@@ -368,7 +377,7 @@ than only the one with a Read hook.
368
377
 
369
378
  | # | Question | Expected |
370
379
  |---|---|---|
371
- | 28.1 | Is `docs/RULE_ENFORCEMENT.md` generated by `audits/rule-ledger.sh --write` and currency-checked by `make audit` (`--check` regenerates and byte-compares), so an edited rule doc reds the audit until the scoreboard is regenerated — and is the render a pure function of the tree, carrying no timestamp or commit hash? | YES |
380
+ | 28.1 | Is `docs/RULE_ENFORCEMENT.md` generated by `audits/rule-ledger.sh --write` and currency-checked by `make audit` (`--check` regenerates and byte-compares), so a rule edit that changes the rendered scoreboard reds the audit until it is regenerated — and is the render a pure function of the tree, carrying no timestamp or commit hash? | YES |
372
381
  | 28.2 | Do the ledger's clause counts INFORM only — never failing a build — with the reds reserved for structural conditions (a cited-but-unregistered doc, a registered path missing from disk, a façade `.sh` declaring no `dispatch_init` scope, a stale scoreboard)? | YES |
373
382
  | 28.3 | Does the DOC READ GATE require recording each triggered read with `bash audits/doc-read.sh log <path>` — runnable in every runtime, automatic in Claude Code via the `PostToolUse` Read hook — with `.githooks/pre-commit` comparing the record against the staged diff? | YES |
374
383
  | 28.4 | When no read record exists (a runtime without hook support, before the command is run), does `audits/doc-read.sh check` warn 🟠 and exit 0 rather than red — because a check that fires where it cannot work teaches people to ignore it? | YES |
@@ -408,23 +417,24 @@ comprehension layer closes that gap:
408
417
  non-compliant model. In the FULL graded run an absent or credit-blocked
409
418
  agent FAILS the gate — "every agent adheres" cannot be proven by an agent
410
419
  that never answered; smoke logs + excludes it, never silently.
411
- - **Evidence** — `orly verify --write-evidence` binds the result to the
412
- current source commit and registry digest; pre-push records the live result
413
- as `not-required` unless a manual `make llmevals` run supplied one.
420
+ - **Evidence** — `orly verify --write-evidence` records checkout HEAD, profile
421
+ checks, and the declared prompt result. It records no registry digest.
422
+ Pre-push always declares the live result `not-required`; a manual passing
423
+ run may separately write evidence with `--llm-result pass`.
414
424
 
415
425
  ---
416
426
 
417
427
  ## Step 3 — Generate evidence
418
428
 
419
- After all questions answer YES and the report below is complete, generate the
420
- machine-readable evidence file:
429
+ After all questions answer YES, the report below is complete, and live comprehension passes, generate the
430
+ machine-readable evidence file. An owner-approved live deferral remains `not-required`, never `pass`:
421
431
 
422
432
  ```bash
423
433
  orly verify --write-evidence --llm-result pass
424
434
  ```
425
435
 
426
436
  The evidence is local and ignored by Git. The pre-push hook regenerates it
427
- against the exact commit being pushed.
437
+ for checkout HEAD, which need not be the revision named by a push ref.
428
438
 
429
439
  ## Step 4 — Tabulated audit report
430
440
 
@@ -484,14 +494,14 @@ OVERALL: PASS | FAIL — <reason if fail>
484
494
 
485
495
  ---
486
496
 
487
- ## Wiring it into `pre-commit`
497
+ ## Commit and push enforcement
488
498
 
489
- The dotfiles `.githooks/pre-commit` runs `make audit` when generated rules,
490
- canonical sources, profiles, dispatch pages, audits, or governance hooks are
491
- staged. It is fast and deterministic.
499
+ This checkout's `.githooks/pre-commit` checks recorded document reads for staged
500
+ governance changes. `.githooks/pre-push` runs `make audit` when governance changed,
501
+ then writes evidence for checkout HEAD.
492
502
 
493
- The Step-2 questionnaire is read during the edit. A live smoke run is hooked
494
- only for semantic governance changes because:
503
+ The Step-2 questionnaire is read during the edit. Live comprehension remains a
504
+ manual requirement for semantic governance changes because:
495
505
 
496
506
  - It needs an LLM, which means latency, cost, and credentials in the hook environment.
497
507
  - It only adds value when operating-model semantics change.
@@ -502,7 +512,7 @@ Required workflow when you edit Oracle rules:
502
512
  1. Run Step 1 (`bash audits/agents-md.sh`).
503
513
  2. Answer every question in this file against the generated `AGENTS.md` and dispatch pages.
504
514
  3. Emit the report. All-YES permits commit; any NO returns to the edit.
505
- 4. Let pre-push run one fixture per installed agent and generate commit-bound evidence.
515
+ 4. For semantic changes, run the live comprehension matrix manually and record its result. Pre-push runs deterministic verification and generates commit-bound evidence.
506
516
 
507
517
  ---
508
518
 
@@ -46,6 +46,10 @@
46
46
 
47
47
  set -euo pipefail
48
48
 
49
+ source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/scope.sh"
50
+ audit_scope_init --all "$@"
51
+ audit_index_snapshot "$@"
52
+
49
53
  MODE="${1:-${SCOPE:-all}}"
50
54
  ROOT="$(git rev-parse --show-toplevel)"
51
55
  cd "$ROOT"
@@ -58,22 +62,13 @@ note() { printf "NOTE: %s\n" "$*"; }
58
62
  # ---------------------------------------------------------------------------
59
63
  # 1. Gather Zig files in scope. Tests INCLUDED — same lifecycle rules apply.
60
64
  # ---------------------------------------------------------------------------
61
- case "$MODE" in
62
- --staged|staged)
63
- # while read, not mapfile — bash-3.2 portability (see scripts/run-playbook-tests.sh).
64
- FILES=()
65
- while IFS= read -r f; do FILES+=("$f"); done < <(git diff --cached --name-only --diff-filter=ACMRT \
66
- | grep -E '^src/.*\.zig$' || true)
67
- ;;
68
- --all|all)
69
- FILES=()
70
- while IFS= read -r f; do FILES+=("$f"); done < <(find src -type f -name '*.zig' 2>/dev/null || true)
71
- ;;
72
- *)
73
- printf "usage: %s [--staged|--all]\n" "$0" >&2
74
- exit 64
75
- ;;
76
- esac
65
+ MODE="$AUDIT_MODE"
66
+ FILES=()
67
+ while IFS= read -r -d '' f; do
68
+ [ ! -f "$f" ] || FILES+=("$f")
69
+ done < <(audit_scope_paths '*.zig')
70
+ STAGED=0
71
+ [ "$MODE" != --staged ] || STAGED=1
77
72
 
78
73
  if [[ ${#FILES[@]} -eq 0 ]]; then
79
74
  ok "no zig source files in scope ($MODE)"
@@ -140,8 +135,8 @@ if [[ -n "$inits_list" ]]; then
140
135
 
141
136
  # Body window: from sig line to next pub-fn / fn / EOF, capped at +50.
142
137
  body=$(awk -v start="$ln" '
143
- NR <= start { next }
144
- /^[[:space:]]*(pub )?fn [a-zA-Z_]/ { exit }
138
+ NR < start { next }
139
+ NR > start && /^[[:space:]]*(pub )?fn [a-zA-Z_]/ { exit }
145
140
  NR > start + 50 { exit }
146
141
  { print }
147
142
  ' "$f")
@@ -37,7 +37,11 @@
37
37
 
38
38
  set -euo pipefail
39
39
 
40
- MODE="${1:---all}"
40
+ source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/scope.sh"
41
+ audit_scope_init --all "$@"
42
+ audit_index_snapshot "$@"
43
+
44
+ MODE="$AUDIT_MODE"
41
45
  ROOT="$(git rev-parse --show-toplevel)"
42
46
  cd "$ROOT"
43
47
 
@@ -102,35 +106,17 @@ in_gradient_scope() {
102
106
  esac
103
107
  }
104
108
 
105
- case "$MODE" in
106
- --staged|staged)
107
- FILES=$(git diff --cached --name-only --diff-filter=ACMRT 2>/dev/null || true)
108
- GRADIENT_CANDIDATES="$FILES"
109
- ;;
110
- --all|all)
111
- # `git ls-files` reports the index, which includes staged content —
112
- # so pre-commit-style invocations see staged-but-not-committed files
113
- # without needing a `--staged` flag.
114
- FILES=$(git ls-files -- 'ui/packages/app/*.tsx' 'ui/packages/app/*.jsx' 'ui/packages/website/*.tsx' 'ui/packages/website/*.jsx' 2>/dev/null || true)
115
- GRADIENT_CANDIDATES=$(git ls-files -- ui/packages/app ui/packages/website ui/packages/design-system 2>/dev/null || true)
116
- ;;
117
- *)
118
- echo "usage: $0 [--all|--staged]" >&2
119
- echo "note: --diff was retired in M70 — see dispatch/write_ts_adhere_bun.md (Design Tokens → Scope)." >&2
120
- exit 2 ;;
121
- esac
122
-
123
109
  FAIL=0
124
110
  SEEN_FILES_LIST=""
125
111
 
126
112
  # Pre-filter FILES list once (drop blanks, non-existent, out-of-scope).
127
113
  SCOPED_FILES=()
128
- while IFS= read -r f; do
114
+ while IFS= read -r -d '' f; do
129
115
  [ -z "$f" ] && continue
130
116
  [ ! -f "$f" ] && continue
131
117
  in_scope "$f" || continue
132
118
  SCOPED_FILES+=("$f")
133
- done <<< "$FILES"
119
+ done < <(audit_scope_paths '*.tsx' '*.jsx')
134
120
 
135
121
  if [ "${#SCOPED_FILES[@]}" -gt 0 ]; then
136
122
  for entry in "${PATTERNS[@]}"; do
@@ -156,7 +142,7 @@ if [ "${#SCOPED_FILES[@]}" -gt 0 ]; then
156
142
  fi
157
143
 
158
144
  GRADIENT_FILES=()
159
- while IFS= read -r f; do
145
+ while IFS= read -r -d '' f; do
160
146
  [ -z "$f" ] && continue
161
147
  [ ! -f "$f" ] && continue
162
148
  in_gradient_scope "$f" || continue
@@ -167,7 +153,7 @@ while IFS= read -r f; do
167
153
  SEEN_FILES_LIST="${SEEN_FILES_LIST}${f}"$'\n'
168
154
  FAIL=1
169
155
  done < <(check_font_ownership "$f")
170
- done <<< "$GRADIENT_CANDIDATES"
156
+ done < <(audit_scope_paths "ui/packages/app/*" "ui/packages/website/*" "ui/packages/design-system/*")
171
157
 
172
158
  if [ "${#GRADIENT_FILES[@]}" -gt 0 ]; then
173
159
  while IFS= read -r match; do
@@ -101,16 +101,13 @@ run_log() {
101
101
  # The section rides the SAME row rather than a second file: a citation that
102
102
  # could be written without a read beside it would be a third assertion to
103
103
  # reconcile, and the pair is what carries meaning.
104
- printf '{"ts":%s,"path":"%s","blob":"%s","section":"%s"}\n' \
105
- "$(date +%s)" "$(json_escape "$relative")" "$blob" "$(json_escape "$section")" >> "$log"
106
- return 0
104
+ bun "$HERE/doc-reads.ts" log "$(date +%s)" "$relative" "$blob" "$section" >> "$log"
107
105
  }
108
106
 
109
- # Backslash and double quote are legal in a POSIX filename and illegal raw in a
110
- # JSON string. Unescaped, `we"ird.md` writes a row no parser can read — and this
111
- # one mis-splits it, reporting a path that was never read.
107
+ # JSON encoding preserves quoted names, tabs, newlines and other controls.
108
+ # Fields are escaped while passing through the tab-delimited comparison file.
112
109
  json_escape() {
113
- printf '%s' "$1" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g'
110
+ bun "$HERE/doc-reads.ts" escape "$1"
114
111
  }
115
112
 
116
113
  # The content a read actually saw. Validity is keyed to this rather than to a
@@ -134,40 +131,20 @@ expected_facade_pages() {
134
131
  scope="$(ledger_facade_scope "$page")"
135
132
  [ -n "$scope" ] || continue
136
133
  stem="$(basename "$page" .md)"
137
- [ "$(ledger_match_count "$scope" < "$staged")" -gt 0 ] && printf 'dispatch/%s.md\n' "$stem"
134
+ [ "$(ledger_match_count "$scope" < "$staged")" -gt 0 ] && printf '%s\n' "${page#"$LEDGER_ROOT"/}"
138
135
  done < <(ledger_facade_pages)
139
136
  }
140
137
 
141
- json_unescape() {
142
- printf '%s' "$1" | sed -e 's/\\"/"/g' -e 's/\\\\/\\/g'
143
- }
144
-
145
138
  # Paths whose recorded read saw the content that is on disk now, one
146
139
  # `path<TAB>ts<TAB>section` row each. A row written against an older version of
147
140
  # the document proves the agent read something else, so it does not count — and
148
141
  # rows from before this milestone, which carry no blob, cannot prove anything
149
142
  # and are ignored.
150
143
  #
151
- # The path is cut at the first `","blob":"` rather than by stripping a fixed
152
- # tail: the row gained a trailing `section` field, and a suffix strip that
153
- # spelled the old shape would have silently yielded a path that matches nothing
154
- # — reading as "never read" for every document.
144
+ # The helper validates each JSON row, skips malformed records and compares the
145
+ # current file hash before emitting escaped fields for the shell comparison.
155
146
  current_reads() {
156
- local log="$1" line path blob ts section
157
- while IFS= read -r line; do
158
- case "$line" in *'"blob":"'*) ;; *) continue ;; esac
159
- blob="${line#*\"blob\":\"}"; blob="${blob%%\"*}"
160
- [ -n "$blob" ] || continue
161
- path="${line#*\"path\":\"}"; path="${path%%\",\"blob\":\"*}"
162
- path="$(json_unescape "$path")"
163
- ts="${line#*\"ts\":}"; ts="${ts%%,*}"
164
- section=""
165
- case "$line" in
166
- *'"section":"'*) section="${line#*\"section\":\"}"; section="${section%%\"*}" ;;
167
- esac
168
- [ "$blob" = "$(content_hash "$path")" ] &&
169
- printf '%s\t%s\t%s\n' "$path" "$ts" "$(json_unescape "$section")"
170
- done < "$log"
147
+ bun "$HERE/doc-reads.ts" current "$1" "$LEDGER_ROOT"
171
148
  }
172
149
 
173
150
  # Timestamps carrying BULK_ASSERTION_THRESHOLD or more distinct façades, one
@@ -212,7 +189,7 @@ run_check() {
212
189
  current_reads "$log" | sort -u > "$recorded"
213
190
 
214
191
  while IFS= read -r page; do
215
- grep -qF "$(printf '%s\t' "$page")" "$recorded" && continue
192
+ grep -qF "$(printf '%s\t' "$(json_escape "$page")")" "$recorded" && continue
216
193
  printf ' %s🔴%s DOC READ: %s triggered by the staged diff, not read at its current content\n' "$R" "$X" "$page"
217
194
  unread=1
218
195
  done < "$expected"
@@ -229,7 +206,7 @@ report_citations() {
229
206
  local expected="$1" recorded="$2" page total=0 cited=0 section
230
207
  while IFS= read -r page; do
231
208
  total=$((total + 1))
232
- section="$(grep -F "$(printf '%s\t' "$page")" "$recorded" | cut -f3 | grep -c '[^[:space:]]')"
209
+ section="$(grep -F "$(printf '%s\t' "$(json_escape "$page")")" "$recorded" | cut -f3 | grep -c '[^[:space:]]')"
233
210
  [ "$section" -gt 0 ] && cited=$((cited + 1))
234
211
  done < "$expected"
235
212
  [ "$total" -eq 0 ] && return 0