@event4u/agent-config 9.6.0 → 9.8.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 (204) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +207 -942
  3. package/README.md +21 -21
  4. package/dist/agent-src/README.md +2 -2
  5. package/dist/agent-src/commands/commit/in-chunks.md +8 -0
  6. package/dist/agent-src/commands/commit.md +17 -0
  7. package/dist/agent-src/commands/pr/create.md +4 -0
  8. package/dist/agent-src/contexts/override-system.md +75 -5
  9. package/dist/agent-src/rules/context-hygiene.md +2 -0
  10. package/dist/agent-src/rules/doc-screenshot-hygiene.md +97 -0
  11. package/dist/agent-src/rules/domain-safety-pii.md +1 -0
  12. package/dist/agent-src/rules/downstream-changes.md +31 -1
  13. package/dist/agent-src/rules/external-code-graph-interop.md +13 -3
  14. package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +2 -0
  15. package/dist/agent-src/rules/git-history-discipline.md +2 -0
  16. package/dist/agent-src/rules/language-and-tone.md +2 -0
  17. package/dist/agent-src/rules/lethal-trifecta-guard.md +3 -0
  18. package/dist/agent-src/rules/media-governance-routing.md +2 -0
  19. package/dist/agent-src/rules/minimal-safe-diff.md +2 -0
  20. package/dist/agent-src/rules/no-roadmap-references.md +3 -0
  21. package/dist/agent-src/rules/non-destructive-by-default.md +20 -0
  22. package/dist/agent-src/rules/onboarding-gate.md +2 -0
  23. package/dist/agent-src/rules/output-discipline.md +2 -0
  24. package/dist/agent-src/rules/persona-governance.md +2 -0
  25. package/dist/agent-src/rules/preservation-guard.md +3 -0
  26. package/dist/agent-src/rules/roadmap-progress-sync.md +2 -0
  27. package/dist/agent-src/rules/secret-vcs-guard.md +106 -0
  28. package/dist/agent-src/rules/security-sensitive-stop.md +1 -1
  29. package/dist/agent-src/rules/skill-quality.md +2 -0
  30. package/dist/agent-src/rules/source-confidentiality.md +2 -0
  31. package/dist/agent-src/rules/source-of-truth.md +2 -0
  32. package/dist/agent-src/rules/telegraph-speak.md +2 -0
  33. package/dist/agent-src/rules/token-optimizer-maintenance.md +2 -0
  34. package/dist/agent-src/rules/tool-safety.md +1 -0
  35. package/dist/agent-src/rules/verify-before-complete.md +2 -0
  36. package/dist/agent-src/skills/adr-create/SKILL.md +17 -1
  37. package/dist/agent-src/skills/agent-docs-writing/SKILL.md +34 -16
  38. package/dist/agent-src/skills/agents-md-thin-root/SKILL.md +9 -9
  39. package/dist/agent-src/skills/code-intelligence/SKILL.md +94 -0
  40. package/dist/agent-src/skills/gated-reach/SKILL.md +185 -0
  41. package/dist/agent-src/skills/gated-reach/evals/triggers.json +72 -0
  42. package/dist/agent-src/skills/image-analyser/SKILL.md +14 -12
  43. package/dist/agent-src/skills/image-editing/SKILL.md +1 -0
  44. package/dist/agent-src/skills/readme-writing/SKILL.md +6 -1
  45. package/dist/agent-src/skills/screenshot-hygiene/SKILL.md +171 -0
  46. package/dist/agent-src/skills/secrets-management/SKILL.md +44 -1
  47. package/dist/agent-src/skills/subagent-orchestration/prompts/adversarial-verification-council.md +29 -0
  48. package/dist/agent-src/skills/subagent-orchestration/prompts/do-and-judge-two-stage.md +29 -0
  49. package/dist/agent-src/skills/subagent-orchestration/prompts/do-and-judge.md +29 -0
  50. package/dist/agent-src/skills/subagent-orchestration/prompts/do-competitively.md +29 -0
  51. package/dist/agent-src/skills/subagent-orchestration/prompts/do-in-parallel.md +29 -0
  52. package/dist/agent-src/skills/subagent-orchestration/prompts/do-in-steps.md +29 -0
  53. package/dist/agent-src/skills/subagent-orchestration/prompts/do-in-worktrees.md +29 -0
  54. package/dist/agent-src/skills/subagent-orchestration/prompts/judge-with-debate.md +29 -0
  55. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +4 -0
  56. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  57. package/dist/agent-src/templates/github-workflows/doc-impact.yml +101 -0
  58. package/dist/agent-src/templates/github-workflows/secret-scan.yml +65 -0
  59. package/dist/cli/configRoot.js +112 -0
  60. package/dist/cli/configRoot.js.map +1 -0
  61. package/dist/cli/configRoot.test.js +97 -0
  62. package/dist/cli/configRoot.test.js.map +1 -0
  63. package/dist/cli/help.js +4 -1
  64. package/dist/cli/help.js.map +1 -1
  65. package/dist/cli/main.js +19 -2
  66. package/dist/cli/main.js.map +1 -1
  67. package/dist/cli/registry.js +1 -0
  68. package/dist/cli/registry.js.map +1 -1
  69. package/dist/discovery/deprecation-report.md +1 -1
  70. package/dist/discovery/discovery-manifest.json +164 -47
  71. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  72. package/dist/discovery/discovery-manifest.summary.md +4 -4
  73. package/dist/discovery/orphan-report.md +1 -1
  74. package/dist/discovery/packs.json +13 -8
  75. package/dist/discovery/trust-report.md +11 -11
  76. package/dist/discovery/workspaces.json +11 -6
  77. package/dist/install/install.mjs +16 -0
  78. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  79. package/dist/mcp/mcp-cloudflare-catalogue.json +1 -1
  80. package/dist/mcp/registry-manifest.json +4 -4
  81. package/dist/router.json +1 -1
  82. package/dist/server/app.js +10 -0
  83. package/dist/server/app.js.map +1 -1
  84. package/dist/server/routes/ping.js +18 -0
  85. package/dist/server/routes/ping.js.map +1 -1
  86. package/dist/server/schemas/settings.js +8 -0
  87. package/dist/server/schemas/settings.js.map +1 -1
  88. package/dist/server/serverInfo.js +6 -2
  89. package/dist/server/serverInfo.js.map +1 -1
  90. package/dist/server/token.js +11 -4
  91. package/dist/server/token.js.map +1 -1
  92. package/dist/server/writeRoot.js +15 -1
  93. package/dist/server/writeRoot.js.map +1 -1
  94. package/dist/shared/capabilities.js +33 -0
  95. package/dist/shared/capabilities.js.map +1 -0
  96. package/dist/shared/capabilities.test.js +39 -0
  97. package/dist/shared/capabilities.test.js.map +1 -0
  98. package/dist/ui/assets/{index-BiEZiZ31.js → index-CrmZ34Rg.js} +16 -16
  99. package/dist/ui/assets/index-CrmZ34Rg.js.map +1 -0
  100. package/dist/ui/index.html +14 -5
  101. package/docs/CLAIMS.md +64 -38
  102. package/docs/architecture.md +2 -2
  103. package/docs/archive/CHANGELOG-6.0.0-overview.md +953 -0
  104. package/docs/benchmark.md +170 -9
  105. package/docs/catalog.md +8 -3
  106. package/docs/comparison.yaml +44 -2
  107. package/docs/contracts/local-server-ports.md +53 -0
  108. package/docs/contracts/no-runtime-boundary.md +1 -1
  109. package/docs/contracts/subagent-boundary.md +15 -0
  110. package/docs/customization.md +14 -3
  111. package/docs/decisions/ADR-016-installer-architecture.md +2 -0
  112. package/docs/decisions/ADR-088-no-external-runtime-federation.md +1 -1
  113. package/docs/decisions/ADR-094-agent-memory-layer-removal.md +1 -1
  114. package/docs/decisions/ADR-109-subagent-v1-contract.md +2 -0
  115. package/docs/decisions/ADR-110-discipline-profile-resolution-locus.md +2 -0
  116. package/docs/decisions/ADR-113-ci-native-release-label-trigger.md +11 -3
  117. package/docs/decisions/ADR-122-adversarial-verification-council.md +30 -0
  118. package/docs/decisions/ADR-123-runtime-security-scope-and-spawn-hardening.md +31 -0
  119. package/docs/decisions/ADR-124-embedded-engine-doctrine.md +255 -0
  120. package/docs/decisions/ADR-125-doc-screenshot-anonymization.md +131 -0
  121. package/docs/decisions/ADR-126-internet-reach-operator-tooling.md +254 -0
  122. package/docs/decisions/ADR-127-enforcement-claims-must-resolve.md +150 -0
  123. package/docs/decisions/ADR-128-executable-evidence-and-measured-escalation.md +201 -0
  124. package/docs/decisions/INDEX.md +21 -0
  125. package/docs/decisions/engine-reclassification-2026-07.md +104 -0
  126. package/docs/distribution/awesome-list-submission.md +1 -1
  127. package/docs/distribution/registries.md +36 -27
  128. package/docs/enforcement-by-host.md +7 -0
  129. package/docs/featured-skills.md +2 -2
  130. package/docs/getting-started-by-role.md +1 -1
  131. package/docs/getting-started.md +1 -1
  132. package/docs/governance-advantage.md +1 -1
  133. package/docs/guides/gated-platform-reads.md +221 -0
  134. package/docs/positioning-evidence.md +1 -1
  135. package/docs/proof.md +92 -16
  136. package/docs/spawn-site-policy.md +72 -0
  137. package/docs/threat-model.md +2 -1
  138. package/package.json +6 -3
  139. package/src/agent-src/README.md +2 -2
  140. package/src/config/agent-settings.template.yml +43 -0
  141. package/src/config/reach-channels.yml +217 -0
  142. package/src/config/reach-prescriptions-intake.yml +200 -0
  143. package/src/scripts/_dispatch.bash +15 -0
  144. package/src/scripts/_lib/adversarial_bench_score.ts +106 -0
  145. package/src/scripts/_lib/exec_evidence.ts +251 -0
  146. package/src/scripts/_lib/fixtures/secret-detector/negatives.txt +10 -0
  147. package/src/scripts/_lib/fixtures/secret-detector/positives.txt +11 -0
  148. package/src/scripts/_lib/kernel_rules.ts +46 -0
  149. package/src/scripts/_lib/reddit_thread_parse.ts +598 -0
  150. package/src/scripts/_lib/risk_paths.ts +160 -0
  151. package/src/scripts/_lib/secret_detector.test.ts +103 -0
  152. package/src/scripts/_lib/secret_detector.ts +319 -0
  153. package/src/scripts/_lib/spawn_env.ts +24 -4
  154. package/src/scripts/_lib/tool_probe.ts +359 -0
  155. package/src/scripts/adr/regenerate_index.ts +81 -6
  156. package/src/scripts/audit_adr_coverage.ts +33 -0
  157. package/src/scripts/bench_adversarial_council.ts +292 -0
  158. package/src/scripts/build_proof.ts +162 -0
  159. package/src/scripts/check_adr_frontmatter.ts +195 -0
  160. package/src/scripts/check_artefact_count_messaging.ts +4 -0
  161. package/src/scripts/check_backstop_debt.ts +200 -0
  162. package/src/scripts/check_claims.ts +188 -8
  163. package/src/scripts/check_comparison.ts +12 -0
  164. package/src/scripts/check_enforcement_coverage.ts +592 -0
  165. package/src/scripts/check_kernel_rule_bundle.ts +16 -12
  166. package/src/scripts/check_no_new_legacy_path.ts +2 -0
  167. package/src/scripts/check_reach_channels.ts +407 -0
  168. package/src/scripts/check_reach_staleness.ts +364 -0
  169. package/src/scripts/check_secret_leak.test.ts +47 -0
  170. package/src/scripts/check_secret_leak.ts +290 -0
  171. package/src/scripts/check_source_pointer_freshness.ts +165 -0
  172. package/src/scripts/code_graph/build.ts +0 -0
  173. package/src/scripts/code_graph/cli.ts +207 -0
  174. package/src/scripts/code_graph/detect.ts +134 -0
  175. package/src/scripts/code_graph/extract.ts +386 -0
  176. package/src/scripts/code_graph/loader.ts +123 -0
  177. package/src/scripts/code_graph/query.ts +176 -0
  178. package/src/scripts/code_graph/sanitize.ts +30 -0
  179. package/src/scripts/code_graph/types.ts +83 -0
  180. package/src/scripts/code_graph/validate.ts +63 -0
  181. package/src/scripts/external_sources_denylist.json +3 -1
  182. package/src/scripts/generate_subagent_floor.ts +194 -0
  183. package/src/scripts/hook_manifest.yaml +13 -3
  184. package/src/scripts/hooks/code_graph_nudge_hook.ts +184 -0
  185. package/src/scripts/hooks/dispatch_hook.ts +5 -1
  186. package/src/scripts/iron_law_sha.ts +3 -12
  187. package/src/scripts/lint_override_kernel_guard.ts +219 -0
  188. package/src/scripts/lint_readme_serial_comma.ts +169 -0
  189. package/src/scripts/measure_rule_budget.ts +3 -12
  190. package/src/scripts/postinstall_gui.ts +129 -0
  191. package/src/scripts/reach_doctor.ts +1651 -0
  192. package/src/scripts/release.ts +24 -3
  193. package/src/scripts/risk_escalation_shadow.ts +160 -0
  194. package/src/scripts/schemas/agent-settings.schema.json +23 -0
  195. package/src/scripts/schemas/reach-channels.schema.json +134 -0
  196. package/src/scripts/schemas/reach-doctor-payload.schema.json +220 -0
  197. package/src/scripts/schemas/rule.schema.json +10 -0
  198. package/src/scripts/skill_linter.ts +55 -0
  199. package/src/scripts/validate_reach_prescriptions.ts +751 -0
  200. package/src/server/schemas/settings.ts +16 -0
  201. package/src/shared/capabilities.test.ts +43 -0
  202. package/src/shared/capabilities.ts +75 -0
  203. package/src/templates/minimal/agents-overrides-readme.md +20 -0
  204. package/dist/ui/assets/index-BiEZiZ31.js.map +0 -1
@@ -0,0 +1,255 @@
1
+ ---
2
+ adr: 124
3
+ status: accepted
4
+ date: 2026-07-23
5
+ decision: embedded-engine-doctrine
6
+ supersedes: ADR-088 (engine-adoption interpretation only), ADR-094 (engine-adoption interpretation only)
7
+ superseded_by: —
8
+ phase: road-to-native-code-intelligence
9
+ type: structural
10
+ ---
11
+
12
+ # ADR-124 — Embedded-engine doctrine: this suite may own deterministic in-process engines; the service/daemon prohibition stands
13
+
14
+ ## Status
15
+
16
+ **Accepted** · 2026-07-23. **Maintainer-directed reversal** of the
17
+ engine-rejection *interpretation* accumulated across ADR-088, ADR-094 and the
18
+ archived harvest-cycle REJECT records of 2026-06/07. The council ratification
19
+ round reviewed the *boundary wording*, not the direction — the direction is a
20
+ maintainer product decision: the prior councils optimized for scope discipline
21
+ and, in doing so, systematically excluded a capability class (deterministic
22
+ code/corpus intelligence) that competing suites ship as their headline
23
+ feature. The ratification round ran 2026-07-23 (see References); its three
24
+ convergent wording patches — the tightened `--watch` termination clause, the
25
+ maintainer-approves-per-dep ladder note, and the "changes *what* the tool can
26
+ answer, not just *how fast*" state-store test in § 6 — are folded in, and the
27
+ ADR is accepted on that sealed wording.
28
+
29
+ ## Context
30
+
31
+ ### What the record actually prohibits (verified 2026-07-23)
32
+
33
+ The "no runtime" identity rests on instruments whose literal scope is narrower
34
+ than the posture they produced:
35
+
36
+ 1. **ADR-088** prohibits **cross-vendor runtime federation**: "agent-config
37
+ does not bridge to, or drive, external tool runtimes. It is a content suite
38
+ (skills, rules, commands) for AI coding tools — not a runtime coordinator."
39
+ It says nothing about whether this suite may run an in-process algorithm of
40
+ its own. The frequently-cited gloss "no runtime orchestration (work
41
+ stealing, load balancing)" is a harvest-cycle REJECT line (council,
42
+ 2026-07-07) that *cites* ADR-088 — it is not ADR-088's text.
43
+ 2. **ADR-094** removed one specific companion package (Layer 2:
44
+ PostgreSQL + pgvector + MCP memory server + decay engine) because "its
45
+ PostgreSQL + MCP runtime contradicted the suite's 'no app runtime'
46
+ positioning." It is a removal record, not a forward-looking ban list.
47
+ 3. **Archived REJECT records** (council convergences, 2026-06 → 2026-07,
48
+ quoted inline per the transient-reference rule): the MCP deferred-rule
49
+ retrieval **server** ("council REJECT, 2026-07-07", three re-open
50
+ conditions); "SQLite memory *service*, vector clocks, distributed memory —
51
+ the second-brain verdict and Layer-2 sunset stand"; a web console ("no
52
+ runtime to monitor"); a browser daemon + compiled runtime ("compiled
53
+ runtime betrays no-runtime identity" — routed to `agent-ide-plugin`); an
54
+ in-process swarm/topology engine ("an in-process actor runtime is
55
+ identity-rejected").
56
+ 4. **`src/rules/external-code-graph-interop.md`** codified the resulting
57
+ ceiling: "This suite is an **orchestrator, not a competitor**: query the
58
+ existing index first … NEVER REBUILD WHAT THE INDEX ALREADY ANSWERS." This
59
+ is the single most on-point prior commitment against a native code-graph
60
+ engine — an active tier-2a rule, and it is amended by this ADR (§ 2).
61
+
62
+ In practice these instruments were *interpreted* wider than written: a
63
+ 2026-07-23 inventory sweep across all roadmap dispositions (active, archive,
64
+ later, skipped, stubs) found **44 engine-shaped rejects across ~30 cycles** —
65
+ harvests of at least six external references (a code-graph suite, an
66
+ orchestration runtime, a control-plane/enforcement suite, and three memory
67
+ systems) adopted **protocol discipline only** and reflexively rejected every
68
+ **engine**, including engines that are neither services nor daemons.
69
+
70
+ ### The precedent — read honestly
71
+
72
+ **ADR-116** pre-decided SQLite FTS5 via `node:sqlite` — a persisted,
73
+ incrementally-updated engine, in-process — as compatible with the Layer-2
74
+ sunset: "no service, no always-on worker, zero npm dependency." Two facts keep
75
+ this precedent honest rather than convenient:
76
+
77
+ - **That engine was never built.** The activation path was re-resolved to a
78
+ hand-rolled stdlib BM25 + trigram prefilter (`_lib/lexical_index.ts`); only
79
+ the engine choice moved, per the ADR-116 amendment banner.
80
+ - **Its compatibility argument rested on being a zero-npm-dep Node built-in.**
81
+ ADR-116 explicitly rejected `better-sqlite3` and a minisearch dependency
82
+ *for being npm deps*. It is therefore precedent for "embedded engine ≠
83
+ runtime" **in principle**, and **counter-precedent on the dependency axis**.
84
+ This ADR does its own work on that axis (§ 1, Class A) instead of borrowing
85
+ authority ADR-116 does not carry.
86
+
87
+ ### Dependency reality
88
+
89
+ The package ships **13 runtime npm dependencies** today (fastify, commander,
90
+ execa, tsx, zod, js-yaml, the MCP SDK, …). No package-wide "zero
91
+ dependencies" commitment exists — the closest claim was a README bullet
92
+ deliberately dropped before 2.2.0. The zero-dep virtue in ADR-061/ADR-116 is a
93
+ *feature-level* stdlib preference, not a distribution-level promise. An engine
94
+ dependency is therefore a **cost to justify per adoption**, not a broken vow.
95
+
96
+ ### The product goal has changed
97
+
98
+ The maintainer directs: the suite should be able to natively own capability
99
+ classes (deterministic code intelligence first) when owning them makes the
100
+ package better, closes gaps and improves agent behavior — not merely defer to
101
+ whatever index a consumer happens to ship.
102
+
103
+ ## Decision
104
+
105
+ ### 1. Three engine classes; the boundary moves, it does not vanish
106
+
107
+ | Class | Definition | Verdict |
108
+ |---|---|---|
109
+ | **A — Embedded engine** | Deterministic, in-process, invoked-per-command, no resident process, no listening socket, no network in the build path; state only as gitignored, rebuildable build/index artifacts under the suite's own runtime dirs (`agents/runtime/state/`). **Termination clause (council patch, 2026-07-23): a Class-A engine terminates after command completion; in-memory state never spans CLI invocations** — a memory-only long-lived process that "never touches disk" is Class B regardless of its storage story. The sole exception is an explicit `--watch` flag on a stateless file-regeneration command where (a) the process lifecycle is bounded to file-system event observation, (b) **each regeneration cycle is a fresh Class-A invocation with no shared in-memory state between cycles**, and (c) the flag emits a first-launch notice that a long-running process started; any other persistent process (REPL, server, daemon, background worker) is Class B regardless of flag naming, and the `--watch` mode itself is a Class-B escalation under § 5. Implementation preference in order: Node built-ins / stdlib → exact-pinned pure-npm or WASM dependencies (admissible with a per-dependency justification in the adopting ADR — the justification states why a lighter dependency does not suffice, and the maintainer approves it in that ADR, not in a downstream feature PR) → native-compiled (node-gyp) deps only via an explicit per-dependency exception on the same terms. Every subprocess it spawns routes through `hardenedSpawnEnv()` per ADR-123 and `docs/spawn-site-policy.md`. | **ADOPTABLE.** This suite may build, fork, or vendor Class-A engines natively. |
110
+ | **B — Resident service / daemon** | Anything with a lifecycle beyond one command: DB servers, MCP *servers* run as memory/retrieval backends, watchers, browser daemons, background workers, web consoles. (In-process actor runtimes/swarms are equally out of scope, but by the ADR-109 identity floor preserved in § 3 — not by this lifecycle definition; they can terminate within one command and are still excluded.) | **PROHIBITED in core**, unchanged. Route to `agent-ide-plugin` or a sibling package where genuinely needed. ADR-088/094 remain authoritative here. |
111
+ | **C — Network/LLM-dependent build path** | Any index/graph/corpus *build* step that requires network or model calls (embedding pipelines included — ADR-061's "embeddings only on measured recall failure" remains the sole doorway). | **PROHIBITED by default**, unchanged. Query-time LLM use follows existing council/budget governance. |
112
+
113
+ ### 2. What is explicitly superseded
114
+
115
+ - The **blanket engine-rejection interpretation** of ADR-088 and ADR-094.
116
+ Their literal text (no cross-vendor federation; Layer-2 removal) stands; any
117
+ archived REJECT that cites them against a Class-A engine is void and must be
118
+ re-evaluated (§ 4).
119
+ - The **"orchestrator, not a competitor" ceiling** in
120
+ `external-code-graph-interop.md`. New wording: "orchestrator *first* —
121
+ query a consumer-shipped index when present and fresh; owner *where it
122
+ wins* — the suite's native engines cover the gap when none is shipped or
123
+ ours is measurably better." Interop behavior toward existing indexes is
124
+ unchanged.
125
+
126
+ ### 3. What is explicitly NOT superseded
127
+
128
+ - **Falsifiability-first.** Every native engine ships **default-off**,
129
+ activates via tripwire or explicit setting, and earns default-on only
130
+ through a pre-registered benchmark with an honest-null publication path.
131
+ The evidence gates now govern *defaults*, no longer *existence*.
132
+ - Claims Ledger, budget/spend gates, minimal-safe-diff, source
133
+ confidentiality, and the security posture (ADR-123 spawn hardening applies
134
+ to every engine subprocess; the no-network floor applies to every build
135
+ path).
136
+ - The `agent-ide-plugin` routing for genuinely runtime-shaped capability.
137
+ - ADR-109's no-runtime identity floor for subagent artifacts (no daemon, no
138
+ auto-write, no in-process swarm, no dispatch we enforce) — a command-invoked,
139
+ non-dispatching engine does not touch it.
140
+
141
+ ### 4. Mandatory re-evaluation sweep
142
+
143
+ Every engine-shaped REJECT recorded 2026-06-01 → 2026-07-22 is re-classified
144
+ A/B/C. Class-A rejects are re-opened as candidates (adoption still demand- and
145
+ benchmark-gated); Class-B/C rejects are re-affirmed with the class cited. The
146
+ population was inventoried on 2026-07-23 (44 entries); the classification
147
+ table is committed as `docs/decisions/engine-reclassification-2026-07.md` by
148
+ the implementing roadmap — no silent re-openings, no silent re-affirmations.
149
+
150
+ ### 5. Extension clause
151
+
152
+ Opening Class B (e.g., a resident index server for very large fleets) requires
153
+ its own ADR with: a named consumer demand signal, a measured Class-A failure
154
+ (the embedded engine demonstrably cannot serve the need), and a security
155
+ review under ADR-123. This clause exists so the next escalation is a decision,
156
+ not a drift.
157
+
158
+ ### 6. Contract reconciliation — obligations this ADR creates
159
+
160
+ The doctrine is not landed until the published claims agree with it. The
161
+ implementing roadmap carries, in the same change-set as the first engine:
162
+
163
+ - **`docs/contracts/no-runtime-boundary.md`** — the "Cross-session persistent
164
+ state stores" prohibition row gains an explicit carve-out: *gitignored,
165
+ deterministic, rebuildable build/index artifacts under
166
+ `agents/runtime/state/` are build outputs, not state stores* (they carry no
167
+ authority, are reproducible from the working tree, and are never
168
+ auto-written memory). One-shot subprocess spawning is already sanctioned by
169
+ the contract's Allowed table; daemons remain prohibited. **State-store test
170
+ (council ratification patch): if deleting the artifact changes *what* the
171
+ tool can answer rather than only *how fast* it answers, it is a state store,
172
+ not a build artifact — even if deterministically rebuildable.** A code-graph
173
+ cache passes the test (deleting it only slows the next query; the answer is
174
+ identical, recomputed from source); a learned index that enables query
175
+ semantics absent from the source tree (vector/embedding search) fails it and
176
+ stays Class C.
177
+ - **`docs/comparison.yaml` row 1** — "no state database" is reworded to "no
178
+ resident database or service; deterministic, rebuildable file indexes only",
179
+ so the machine-checked claim stays true rather than quietly weakening.
180
+ - **`src/rules/external-code-graph-interop.md`** — ceiling sentence amended
181
+ per § 2.
182
+ - **Config-surface guard alignment** — a planned no-runtime config-surface
183
+ guard (parked in a later-disposition roadmap) denylists `vector`/`daemon`/
184
+ `decay`/`pgvector` keys and `setInterval`/`setTimeout` outside dev tooling.
185
+ Its denylist must except Class-A engine surfaces when it lands, or Class-A
186
+ engines will fail CI after this doctrine flips; this ADR is the anchor that
187
+ guard must cite.
188
+
189
+ ## Consequences
190
+
191
+ - The suite may natively own: code-graph extraction/query (first instance —
192
+ WASM tree-sitter, Class A), lexical/FTS index engines (in-principle
193
+ precedent: ADR-116, with the honest reading above), deterministic
194
+ clustering/analysis over its own graph outputs, and comparable future
195
+ engines — each behind the § 3 gates.
196
+ - **Sequencing rule:** no second native engine starts before the first has a
197
+ published benchmark verdict. The § 4 table is the queue, not a starting gun.
198
+ - Positioning language changes from "no engines, governance only" to "no
199
+ *resident runtime*; deterministic embedded intelligence is in scope."
200
+ README/docs claims still bind to bench rows via the Claims Ledger.
201
+ - **Named cost:** the first engine introduces parser-class runtime
202
+ dependencies (exact-pinned WASM). That breaks the feature-level stdlib
203
+ pattern ADR-061/116 prize — accepted deliberately, justified per dependency
204
+ in the adopting artifact, never silently.
205
+ - **Named risk:** scope-dilution pressure on a single-maintainer package with
206
+ a live adoption gap. Mitigation is structural, not aspirational — the § 3
207
+ gates, the sequencing rule, and the § 4 table as the only intake path for
208
+ further engines.
209
+
210
+ ## Alternatives considered
211
+
212
+ - **Keep the orchestrator-only posture** — rejected by maintainer directive:
213
+ it structurally cedes the headline capability class to peer suites and makes
214
+ the interop rule a promise with no machine behind it when consumers ship no
215
+ index (the common case).
216
+ - **Repeal ADR-088/094 outright** — rejected: their literal scope
217
+ (cross-vendor federation; resident memory runtime) is correct and keeps the
218
+ differentiation that a reversal must not destroy.
219
+ - **Class-A via native node-gyp bindings** — rejected: perpetual
220
+ consumer-install failure tax on a solo-maintainer package; WASM carries the
221
+ same fidelity without the toolchain.
222
+
223
+ ## References
224
+
225
+ - ADR-061 (engine-fork ban; embeddings doorway) · ADR-088 (no external-runtime
226
+ federation) · ADR-094 (Layer-2 removal) · ADR-109 (subagent contract,
227
+ no-runtime identity floor) · ADR-116 (FTS5 pre-decision + amendment) ·
228
+ ADR-123 (spawn hardening).
229
+ - `docs/contracts/no-runtime-boundary.md` · `docs/comparison.yaml` ·
230
+ `docs/spawn-site-policy.md` · `src/rules/external-code-graph-interop.md`.
231
+ - Pre-landing adversarial council review: 2026-07-23, debate mode, 2 rounds,
232
+ members claude-sonnet-4-5 (Anthropic) + gpt-4o (OpenAI). Convergence:
233
+ A/B/C taxonomy well-drawn; the rebuildable-build-artifact carve-out judged
234
+ honest (deterministic from source, no runtime decisions recorded, byte-stable
235
+ rebuild) and categorically distinct from a state store; code-graph confirmed
236
+ as the correct first engine (retriever too incremental, policy evaluator
237
+ needs its predicate language designed first); benchmark thresholds sound.
238
+ Adopted patches: the Class-A termination clause (§ 1) and the benchmark
239
+ confound controls (implementing roadmap, Phase 5). A round-1 proposal to
240
+ block engine *construction* on an external adoption signal was rebutted by
241
+ both members in round 2 (capability-before-adoption causality; the engine is
242
+ the differentiation the launch story needs) — the adopted middle path is the
243
+ bench-as-launch-story inversion plus the existing default-off gates.
244
+ - Council ratification round on wording: 2026-07-23, debate mode, 1 round,
245
+ members claude-sonnet-4-5 (Anthropic, verdict FLAG-with-patches) + gpt-4o
246
+ (OpenAI, verdict RATIFY-with-patches). Both converged on three wording
247
+ patches, all folded in on acceptance: (1) the `--watch` termination clause
248
+ now requires each regeneration cycle to be a fresh Class-A invocation with
249
+ no shared in-memory state (§ 1); (2) the dependency ladder names the
250
+ maintainer as the per-dep approver in the adopting ADR, not a downstream PR
251
+ (§ 1); (3) the state-store test — "changes *what* the tool can answer, not
252
+ just *how fast*" — is added to the § 6 no-runtime-boundary carve-out, which
253
+ explicitly keeps vector/embedding indexes on the Class-C side. No member
254
+ flagged the direction; the round sealed the wording and the ADR is accepted
255
+ on it.
@@ -0,0 +1,131 @@
1
+ ---
2
+ adr: 125
3
+ status: accepted
4
+ date: 2026-07-23
5
+ decision: doc-screenshot-anonymization
6
+ supersedes: —
7
+ superseded_by: —
8
+ phase: road-to-doc-screenshot-anonymization
9
+ type: structural
10
+ ---
11
+
12
+ # ADR-125 — Doc-screenshot anonymization: human-gated, capture-delegated, detection-as-helper
13
+
14
+ - **Status:** Accepted (2026-07-23)
15
+ - **Closes:** `agents/roadmaps/road-to-doc-screenshot-anonymization.md`
16
+ - **Related:** `src/rules/doc-screenshot-hygiene.md`; `src/skills/screenshot-hygiene/SKILL.md`; `src/rules/non-destructive-by-default.md` (the egress Hard Floor this routes into); `src/rules/domain-safety-pii.md` (text-surface sibling); `src/rules/lethal-trifecta-guard.md`; `src/skills/image-analyser/SKILL.md` (detection helper); `src/skills/readme-writing/SKILL.md` (unrequested-screenshot check).
17
+
18
+ ## Context
19
+
20
+ The maintainer wants agents to create screenshots for documentation when
21
+ genuinely useful — e.g. when generating a Starlight docs site — and embed them,
22
+ with a hard requirement: **sensitive data visible on a screenshot must be
23
+ anonymized / pixelated before the screenshot ships.**
24
+
25
+ A code sweep established the gap: the package has image *generation* skills and a
26
+ Starlight docs path (`docs/media/` → `site/sync-docs.mjs` auto-copy/rewrite), but
27
+ **no screenshot-capture discipline and no anonymization of sensitive content
28
+ inside a captured screenshot.** `domain-safety-pii` scopes to text surfaces only
29
+ (drafts / logs / exports / legal privilege); media governance
30
+ (`media-governance-routing`, `image-likeness-and-rights`) scopes to *generated*-
31
+ image rights/likeness. Neither covers redacting sensitive data inside a captured
32
+ screenshot.
33
+
34
+ An AI council debate (2026-07-23, anthropic/claude-sonnet-4-5 + openai/gpt-4o,
35
+ 2 rounds) surfaced the load-bearing tension: agents creating screenshots
36
+ autonomously + a "must anonymize" security guarantee + imperfect detection are
37
+ mutually constraining. Automated detection (OCR + pattern-match + allowlist)
38
+ cannot *prove* a screenshot is safe — it misses semantic leaks (aggregate counts,
39
+ real-vs-fake data tells, re-identification via name structure), and an allowlist
40
+ of "known-fake data" degenerates into an unmaintainable cross-cultural dictionary
41
+ and an identity-resolution hazard.
42
+
43
+ ## Decision
44
+
45
+ Build the feature (the maintainer has decided *whether*; the council informed
46
+ *how*), with these locked choices:
47
+
48
+ 1. **Capture is delegated to the host** (`claude-in-chrome` / Playwright). The
49
+ package ships NO bundled capture engine — respects the no-runtime-floor
50
+ doctrine (ADR-109 §7). The package owns only the anonymization + embedding
51
+ discipline.
52
+
53
+ 2. **Standalone rule + skill, not a "Surface 5" on `domain-safety-pii`.**
54
+ Screenshots are opaque binary artifacts requiring OCR/vision, not the
55
+ text-pattern surfaces `domain-safety-pii` contracts around. Bolting them on
56
+ would break that rule's scope contract.
57
+
58
+ 3. **Detection is a HELPER, never a CLEARANCE.** The automated OCR + pattern
59
+ pass flags candidate regions and pre-redacts to make review cheap; it never
60
+ certifies a screenshot as safe. **The gate is human confirmation** for
61
+ data-bearing screenshots.
62
+
63
+ 4. **Egress teeth via the kernel, not a new kernel rule.** A data-bearing
64
+ screenshot embedded into shipped docs is an *irreversible published egress*.
65
+ The rule's Iron Law routes that embed INTO the existing kernel
66
+ `non-destructive-by-default` Hard Floor (publish/commit already require
67
+ this-turn confirmation). This gives the gate real teeth **without** adding a
68
+ new `always`/kernel rule — which would demand an ADR-gated kernel-membership
69
+ re-run + 24 h soak and would fail the kernel cross-cutting criterion (the
70
+ concern is docs/media-scoped, not cross-cutting across all work). The rule
71
+ ships as `auto` tier-2a; its severity is borrowed from the kernel Hard Floor
72
+ it routes into. ("Route, don't rebuild.")
73
+
74
+ 5. **Conservative default:** uncertain / unresolved / cannot-confirm-safe →
75
+ redact-or-refuse, never ship-and-hope.
76
+
77
+ 6. **Terminal / CLI / IDE screenshots are forbidden.** They are the highest leak
78
+ vector (absolute local paths, env tokens) and least reliably OCR-able. Steer
79
+ to text code blocks with text redaction — cheaper and safer.
80
+
81
+ 7. **Redaction is a deterministic opaque box/blur** over flagged regions; reject
82
+ lossy provider inpaint (docs need visual accuracy). The redaction tool is
83
+ **optional / tool-agnostic** — `sharp` is a `site` dependency only, not a
84
+ package dependency; mandating it breaks framework-neutrality + no-runtime-
85
+ floor. Missing tool → STOP and hand off to the maintainer; never silently
86
+ downgrade the guarantee.
87
+
88
+ 8. **The identity allowlist is the maintainer's OWN public handles + a small
89
+ fake-data seed** (`screenshots.identity_allowlist`, default `[]`) — NOT a
90
+ global fake-data dictionary and NOT identity-resolution. Default: everything
91
+ is treated as sensitive unless a human decides or it matches the allowlist. A
92
+ public handle co-located with a real name does not whitelist the name.
93
+
94
+ ## Consequences
95
+
96
+ - New `auto` tier-2a rule `doc-screenshot-hygiene` (obligation surface + taxonomy
97
+ + risk tiers) routing to a new `screenshot-hygiene` skill (the decide →
98
+ capture → detect → redact → audit → embed workflow + the human-gate checklist).
99
+ - New `screenshots.*` config keys (allowlist + terminal-forbid policy + gate)
100
+ with conservative defaults.
101
+ - `readme-writing` strengthens its unrequested-screenshot check for data-bearing
102
+ shots; illustrative/no-data docs screenshots are the reconciled exception.
103
+ - The "must anonymize" requirement is honored as a **human-gated** guarantee,
104
+ not a false-confidence automated one — the failure mode the council flagged
105
+ (agent ships PII because the automated audit "passed") is structurally avoided.
106
+ - Cost: agents cannot autonomously embed data-bearing screenshots; a human
107
+ confirmation is required. This friction is intentional and symmetric with the
108
+ irreversibility of the egress.
109
+
110
+ ## Alternatives considered
111
+
112
+ - **New `always`/kernel rule (Anthropic Round 1).** Rejected: fails the kernel
113
+ cross-cutting criterion, and the ADR+24 h-soak gate is disproportionate. The
114
+ route-into-Hard-Floor synthesis delivers the same teeth without kernel churn.
115
+ - **Fully automated redaction pipeline as the gate (OpenAI Round 1).** Rejected
116
+ as a *clearance*: detection can't prove safety; "audit passed" would license
117
+ agents to skip human review — the exact inversion the gate exists to prevent.
118
+ Kept only as a *helper* that flags + pre-redacts.
119
+ - **Extend `domain-safety-pii` with Surface 5.** Rejected: breaks the text-
120
+ surface scope contract of that rule.
121
+ - **Bundle a `sharp`-based capture+redaction engine.** Rejected: `sharp` is a
122
+ site-only dep; bundling breaks framework-neutrality + no-runtime-floor.
123
+ - **"Don't build it at all" (Anthropic Round 1 core).** Out of scope — the
124
+ maintainer decided to build; the ADR records the safe *how*.
125
+
126
+ ## References
127
+
128
+ - AI council debate 2026-07-23 (anthropic/claude-sonnet-4-5 + openai/gpt-4o,
129
+ 2 rounds), inlined in `agents/roadmaps/road-to-doc-screenshot-anonymization.md`.
130
+ - ADR-109 (no-runtime-floor doctrine); `src/rules/non-destructive-by-default.md`;
131
+ `docs/contracts/kernel-membership.md`; `docs/threat-model.md`.
@@ -0,0 +1,254 @@
1
+ ---
2
+ adr: 126
3
+ status: accepted
4
+ date: 2026-07-24
5
+ decision: internet-reach-operator-tooling
6
+ supersedes: —
7
+ superseded_by: —
8
+ phase: road-to-internet-reach
9
+ type: structural
10
+ ---
11
+
12
+ # ADR-126 — Internet reach: operator tooling shipped, router skill cancelled by its own gate
13
+
14
+ - **Status:** Accepted (2026-07-24)
15
+ - **Closes:** `agents/roadmaps/archive/road-to-internet-reach.md`
16
+ - **Related:** `docs/contracts/no-runtime-boundary.md` (Class A boundary); ADR-112 (read-only command discipline); ADR-123 (hardened spawn env); ADR-124 (embedded-engine doctrine / Class A–C); `src/rules/lethal-trifecta-guard.md`; `src/rules/source-confidentiality.md`; `src/skills/supply-chain-intake/SKILL.md`; `docs/benchmark.md` § internet-reach.
17
+
18
+ ## Context
19
+
20
+ The package had no coverage for internet reach: no web-research router, no
21
+ upstream-tool health check, no platform-access prescriptions. `CAPABILITIES.yaml`
22
+ listed 279 skills across 28 areas with `gaps: 0` — true for the areas the index
23
+ tracks, and internet reach was not one of them.
24
+
25
+ An external capability-layer reference (anonymized per `source-confidentiality`;
26
+ provenance retained as an `ENC1:` token in the roadmap) solves this with four
27
+ jobs — backend selection, installation, health checking, routing — while
28
+ explicitly not wrapping the upstream tools. Three of its mechanism shapes were
29
+ worth absorbing: ordered-backend channels (switching a backend is reordering a
30
+ list, not editing code), a five-state probe taxonomy with stale-shim detection,
31
+ and a tiered access model. Four of its practices were rejected outright:
32
+ auto-installation from an unpinned archive, browser-credential harvesting,
33
+ an agent-obligating update-check standing rule, and a "MUST USE" trigger with no
34
+ published evidence.
35
+
36
+ The open question was **not** whether those mechanisms are implementable — they
37
+ plainly are — but whether a reach layer earns its place next to the host's own
38
+ web-search and web-fetch tools. That question was made falsifiable before any
39
+ tracked code existed.
40
+
41
+ ## Decision
42
+
43
+ **1. The reach layer is Class A.** Deterministic, command-invoked probe /
44
+ doctor / validation scripts. No LLM call and no network access in the build
45
+ path, no resident process, no daemon, no wrapper CLI, no MCP reach server.
46
+ Reading and searching itself stays "the agent calls the upstream tool directly".
47
+ Every subprocess spawn routes through `hardenedSpawnEnv()` (ADR-123).
48
+
49
+ **2. Scope was decided by a pre-registered benchmark, before authoring.** 12
50
+ credential-free dev-research tasks × 2 arms (host-native tools vs. prototype
51
+ reach prescriptions), thresholds and three verdict bands committed before the
52
+ run, prescriptions prototyped in gitignored scratch first so both arms were real
53
+ at scoring time.
54
+
55
+ **3. The benchmark returned a null, and the null was honoured.** The native arm
56
+ passed 12/12; the reach arm scored **0 outright wins of 12** under the
57
+ pre-registered rule (reach wins only where native fails; ties are native wins) →
58
+ band `stop`. Therefore **no router skill ships.** The `internet-reach` skill,
59
+ its gated-platform prescription set, and the shipped-skill verdict run were
60
+ cancelled *pre-authoring* by the gate that was built to cancel them.
61
+
62
+ **4. The verdict-independent operator tooling ships anyway,** because it answers
63
+ a question that does not need a router: *is the upstream tool I already chose to
64
+ install healthy, and is its install command pinned?* Concretely: a
65
+ schema-validated channel registry, a five-state probe engine with stale-shim
66
+ detection, a read-only `reach:doctor`, and a CI gate that fails on any unpinned
67
+ install prescription.
68
+
69
+ **5. Supply chain is prescription-first, mechanized.** No automatic installation
70
+ of system packages, no piping a remote script into a shell. The doctor emits an
71
+ exact pinned command; a human runs it. "Every prescription passes the intake
72
+ gate" is enforced by `check_reach_channels` + `validate_reach_prescriptions` in
73
+ CI, not by an honour system — the failure mode the reference itself exhibits.
74
+
75
+ **6. Two capabilities are refused, not deferred-with-a-wink.** Browser-credential
76
+ extraction (a lethal-trifecta leg; the reference documents the account-ban risk
77
+ it creates) and CN-market channels (perpetual anti-bot maintenance, no demand
78
+ signal in this audience). Re-opening either requires a named demand signal and
79
+ its own roadmap.
80
+
81
+ **7. An adversarial security review ran pre-merge and found a real HIGH — it was
82
+ fixed, not documented-around.** The review (`agent-security-review` +
83
+ `threat-modeling` over the five reach scripts, the two schemas and the
84
+ registration) confirmed the design's strongest property: neither spawn site uses
85
+ a shell, no reach script contains a write primitive, no fetched byte reaches any
86
+ payload (both spawns discard stdout/stderr, so the only network-derived datum is
87
+ an exit code), the credential check stats and never reads, and all three gates are
88
+ fail-closed (13/13 negative fixtures non-zero, controls zero). It also found that
89
+ `reach:doctor` never validated the registry at runtime while the schema's
90
+ `probe_args` denylist leaked — a registry entry of `probe_cmd: sh` +
91
+ `probe_args: ["-c", "<payload>"]` passed all three gates with ✅ and was then
92
+ executed and reported as healthy under the innocuous backend label. The false
93
+ assurance was the defect: the schema asserted a probe "can never install, write,
94
+ or authenticate as a side effect", and that was not true. Fixed in the same
95
+ change: `collect()` now enforces the schema and refuses on any error-severity
96
+ finding (exit 2), `probe_args` became a flag-shaped **allowlist**, `probe_cmd` is
97
+ bound to equal its backend `id` (so a row can never label a different binary), the
98
+ prototype-chain lookup on the deep-probe table is guarded, the CI refusal moved
99
+ from the CLI layer into `collect()`, parse errors no longer echo file content, and
100
+ the read-only witness assertion was narrowed to what it actually measures. Two
101
+ permanent regression fixtures cover the hostile-registry shape. The schema comment
102
+ now states a bounded claim and explicitly declines to promise that every upstream
103
+ binary is side-effect-free under every flag — that judgement stays with the human
104
+ adding a backend.
105
+
106
+ **A second review round — an external bot gate plus a paid multi-model council —
107
+ found one more real primitive, and two of its HIGHs did not reproduce.** Recorded
108
+ because a review trail that only lists confirmed hits teaches the wrong lesson
109
+ about review. The bot gate's two HIGH findings were probed before being believed
110
+ and **neither reproduced as worded**: the deep-probe table was already
111
+ `Object.hasOwn`-guarded behind a `collect()` gate that validates before any load
112
+ or spawn, and a nine-way probe matrix over every entry point showed the parse
113
+ paths leaked nothing. Its `removal_after`-compared-lexicographically finding was a
114
+ false positive twice over (the code parses to epoch numbers, and the schema pins
115
+ both date fields to a fixed-width ISO pattern). Each is now documented at the site
116
+ so it cannot be re-raised without reading the refutation. What the round DID find:
117
+ (a) the grep gate echoed matched file lines verbatim, so `--registry <any file>`
118
+ printed that file's content back — closed at all **four** echo sites, the fourth
119
+ found only by re-running the probe against every entry point instead of assuming
120
+ three fixes had closed the class; and (b) via the council, `credential_path` was
121
+ an arbitrary-path oracle — a registry declaring
122
+ `credential_path: ../../../../etc/passwd` made the doctor report that path's
123
+ existence and permissions at exit 0 inside a normal-looking health row. Now
124
+ confined to the operator's home, this repo, or the temp dir, checked against both
125
+ the literal and realpath'd form of each (so a symlink cannot escape), refused
126
+ before any syscall, and reported as a refusal rather than a silent skip. Both fixes
127
+ are mutation-tested: forcing the confinement open turns six tests red, and deleting
128
+ the file-type check turns the directory case red.
129
+
130
+ ## Consequences
131
+
132
+ **Good.**
133
+
134
+ - The most expensive possible mistake — authoring, projecting, indexing and
135
+ publicly claiming a router skill that loses to tools the user already has —
136
+ was avoided by measurement rather than by taste.
137
+ - What shipped is small, deterministic and independently useful; it carries no
138
+ availability promise and no SLA.
139
+ - A published null strengthens the package's evidence posture: the benchmark
140
+ surface now contains a case where the package's own proposed feature lost.
141
+ - Pinning and lifecycle discipline are machine-checked, so the supply-chain
142
+ claim is falsifiable rather than aspirational.
143
+
144
+ **Bad / accepted costs.**
145
+
146
+ - The capability gap for **gated platforms stays open.** The credential-free
147
+ task set (needed for reproducibility) structurally excluded the two cases
148
+ where a reach advantage was hypothesized: video subtitles (backend absent →
149
+ `untested`) and authenticated / rate-limited access. The null is therefore
150
+ narrow: *on public, credential-free dev-research tasks*, a reach layer buys no
151
+ capability the host lacks. Anyone wanting the gated case measured must
152
+ pre-register a credentialed task set with its own thresholds.
153
+ - A **measured cost asymmetry is left on the table on purpose.** On all 8 tasks
154
+ both arms solved, the reach arm cost 0.46× the native arm's tokens (0.26× on
155
+ repository metadata, 0.31× on discussion search) — the native arm repeatedly
156
+ paid *discovery overhead* to find the machine-readable endpoint the
157
+ prescription already knows. This is recorded outside the decision: the token
158
+ threshold was authored as a ≤1.5× guardrail, never a win condition, and
159
+ promoting it to one after seeing the data would be precisely the post-hoc
160
+ rigging the bands exist to prevent. Acting on it requires a separate,
161
+ cost-primary pre-registration.
162
+ - **Both accepted costs now have a named re-entry point,** so neither stays a
163
+ footnote: the credential-gated case the keyless task set could not ask, and the
164
+ cost thesis (whose pre-registration must make token cost the primary metric and
165
+ must price the maintenance cost of the thing winning). Both are parked as
166
+ named plans in the roadmap layer with explicit resume triggers — a named demand
167
+ signal, a measured host-capability regression, or a maintainer decision. Paths
168
+ are deliberately not cited here: the roadmap layer is transient and a stable
169
+ artefact must not link into it (`no-roadmap-references`). The gated-platform one
170
+ has since fired and been executed — see § Amendment 2026-07-25. Neither may reuse this
171
+ roadmap's task set or thresholds: a capability-shaped corpus must not be
172
+ allowed to decide a cost question, and vice versa.
173
+ - The registry carries maintenance weight (upstream tools break at platform
174
+ cadence). Contained by `last_verified` + an offline staleness lint + an
175
+ append-only upstream-change log — not by a scheduled network job, which would
176
+ buy flaky CI and an implicit availability promise.
177
+
178
+ ## Alternatives considered
179
+
180
+ - **Ship the router anyway and measure later.** Rejected: re-benchmarking an
181
+ already merged, indexed and comparison-table-listed skill documents a decision
182
+ instead of gating it. The gate has to be able to say no.
183
+ - **Lower the win threshold until the reach arm passes.** Rejected as rigging.
184
+ Worth recording that the band is *defect-insensitive* here: two reach failures
185
+ were prescription bugs, but repairing them yields ties, and ties are native
186
+ wins — zero native failures means zero possible reach wins regardless of
187
+ prescription quality. There was nothing to salvage by re-running.
188
+ - **Promote the token-cost finding into the verdict.** Rejected for this
189
+ roadmap; see the accepted cost above. It is a genuine signal and it deserves
190
+ its own honest experiment, not a retrofitted one.
191
+ - **A weekly scheduled job probing every upstream backend.** Rejected: flaky CI
192
+ against third-party endpoints plus an availability promise the package does
193
+ not make. Replaced by staleness metadata + an operator-invoked deep check.
194
+ - **A credits/attribution entry naming the reference.** Rejected:
195
+ `source-confidentiality` forbids derivation-attribution in tracked artefacts,
196
+ and the license carve-out covers vendored code only — nothing is vendored.
197
+ Provenance lives anonymized in the roadmap with the link as an `ENC1:` token,
198
+ and the reference's identifying tokens were added to the CI denylist so a
199
+ future accidental attribution fails the build.
200
+
201
+ ## Amendment 2026-07-25 — the gated-platform gap, measured and partly closed
202
+
203
+ This ADR's null was scoped explicitly: *"It says nothing about gated-platform
204
+ access. Testing that needs a credentialed task set with its own
205
+ pre-registration."* That test has now run, and the first thing it found is that
206
+ the sentence's premise was wrong — **no credentials were needed**.
207
+
208
+ **Closed for three channels, credential-free.** Reddit thread text (Atom feeds),
209
+ Reddit comment **ranking and reply nesting** (server-rendered HTML), and a single
210
+ named tweet (the platform's own oEmbed endpoint) all reached 6/6 against a
211
+ pre-registered task set with a native control and thresholds frozen before the
212
+ run. The native arm scored 0/6 on both Reddit tiers, because the host's own tool
213
+ refuses the `reddit.com` domain outright. Evidence: `docs/benchmark.md`
214
+ § gated-reach; `internal/bench/gated-reach/{README,results,VERDICT}.md`.
215
+
216
+ **Still open, each with its re-entry trigger.**
217
+
218
+ | Surface | State | Re-entry trigger |
219
+ |---|---|---|
220
+ | YouTube transcripts | **parked, unexercised** | the backend is installed by a human and one real extraction is run |
221
+ | Reddit logged-in HTML (session cookie) | parked | an observed login wall on `old.reddit` **and** the maintainer choosing that successor |
222
+ | Reddit approved Data API | parked | the maintainer choosing the durable path — approval-only, weeks of latency, so it starts before it is needed or not at all |
223
+ | Twitter timelines / search | parked | a task that genuinely needs them; no credential-free path exists |
224
+ | Headless browser | parked | a measured need on a fourth platform |
225
+ | Audio transcription fallback | parked | a video task failing specifically because no caption track exists |
226
+
227
+ **The credential-free scope was a deliberate cut, not an oversight.** Adding a
228
+ credential to any of these channels would put a secret on the same autonomous
229
+ path as untrusted third-party content (Reddit comment bodies, tweet HTML) and an
230
+ outbound fetch — all three legs of the lethal trifecta at once, which
231
+ `lethal-trifecta-guard` exists to prevent. Keeping every prescription
232
+ credential-free keeps that leg broken **by construction** rather than by
233
+ discipline. It also removed the whole consent-gate / credential-file /
234
+ account-ban surface that the design council named as the sharpest risk in this
235
+ area. The cut cost real capability (no timelines, no search, no metrics) and
236
+ that cost is recorded rather than hidden.
237
+
238
+ **One bound this amendment does not soften.** Reddit tier 2 is on an announced
239
+ closing path (login requirement announced 2026-06-30, still not enforced on the
240
+ bench machine on 2026-07-25). It ships with a kill-switch keyed on an
241
+ **observed** login wall — never on the announcement — plus a reverse trigger that
242
+ keeps the tier alive while logged-out access still works. A press release is not
243
+ an outage.
244
+
245
+ ## References
246
+
247
+ - `internal/bench/reach-vs-native/README.md` — pre-registered tasks, thresholds, bands, run protocol.
248
+ - `internal/bench/reach-vs-native/VERDICT.md` — tally, per-channel S0a/S0b, `band: stop`, honest limitations.
249
+ - `docs/benchmark.md` § internet-reach — the published null.
250
+ - `internal/upstream-changes.md` — maintenance log for channel breakage.
251
+ - Council: anthropic/claude-sonnet-4-5 + openai/gpt-4o, 2026-07-24, 3 rounds — converged on the five structural defects of the first draft (impossible sequencing, rigged threshold, post-facto verdict, unfalsifiable acceptance criteria, unmechanized discipline claims); all five fixed before execution.
252
+ - `internal/bench/gated-reach/VERDICT.md` — per-channel verdicts + kill-switch criteria (Amendment 2026-07-25).
253
+ - `docs/guides/gated-platform-reads.md` — the shipped operator prescriptions.
254
+ - `src/skills/gated-reach/SKILL.md` — the ship-tier skill, triggers proven both directions.