@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.
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +207 -942
- package/README.md +21 -21
- package/dist/agent-src/README.md +2 -2
- package/dist/agent-src/commands/commit/in-chunks.md +8 -0
- package/dist/agent-src/commands/commit.md +17 -0
- package/dist/agent-src/commands/pr/create.md +4 -0
- package/dist/agent-src/contexts/override-system.md +75 -5
- package/dist/agent-src/rules/context-hygiene.md +2 -0
- package/dist/agent-src/rules/doc-screenshot-hygiene.md +97 -0
- package/dist/agent-src/rules/domain-safety-pii.md +1 -0
- package/dist/agent-src/rules/downstream-changes.md +31 -1
- package/dist/agent-src/rules/external-code-graph-interop.md +13 -3
- package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +2 -0
- package/dist/agent-src/rules/git-history-discipline.md +2 -0
- package/dist/agent-src/rules/language-and-tone.md +2 -0
- package/dist/agent-src/rules/lethal-trifecta-guard.md +3 -0
- package/dist/agent-src/rules/media-governance-routing.md +2 -0
- package/dist/agent-src/rules/minimal-safe-diff.md +2 -0
- package/dist/agent-src/rules/no-roadmap-references.md +3 -0
- package/dist/agent-src/rules/non-destructive-by-default.md +20 -0
- package/dist/agent-src/rules/onboarding-gate.md +2 -0
- package/dist/agent-src/rules/output-discipline.md +2 -0
- package/dist/agent-src/rules/persona-governance.md +2 -0
- package/dist/agent-src/rules/preservation-guard.md +3 -0
- package/dist/agent-src/rules/roadmap-progress-sync.md +2 -0
- package/dist/agent-src/rules/secret-vcs-guard.md +106 -0
- package/dist/agent-src/rules/security-sensitive-stop.md +1 -1
- package/dist/agent-src/rules/skill-quality.md +2 -0
- package/dist/agent-src/rules/source-confidentiality.md +2 -0
- package/dist/agent-src/rules/source-of-truth.md +2 -0
- package/dist/agent-src/rules/telegraph-speak.md +2 -0
- package/dist/agent-src/rules/token-optimizer-maintenance.md +2 -0
- package/dist/agent-src/rules/tool-safety.md +1 -0
- package/dist/agent-src/rules/verify-before-complete.md +2 -0
- package/dist/agent-src/skills/adr-create/SKILL.md +17 -1
- package/dist/agent-src/skills/agent-docs-writing/SKILL.md +34 -16
- package/dist/agent-src/skills/agents-md-thin-root/SKILL.md +9 -9
- package/dist/agent-src/skills/code-intelligence/SKILL.md +94 -0
- package/dist/agent-src/skills/gated-reach/SKILL.md +185 -0
- package/dist/agent-src/skills/gated-reach/evals/triggers.json +72 -0
- package/dist/agent-src/skills/image-analyser/SKILL.md +14 -12
- package/dist/agent-src/skills/image-editing/SKILL.md +1 -0
- package/dist/agent-src/skills/readme-writing/SKILL.md +6 -1
- package/dist/agent-src/skills/screenshot-hygiene/SKILL.md +171 -0
- package/dist/agent-src/skills/secrets-management/SKILL.md +44 -1
- package/dist/agent-src/skills/subagent-orchestration/prompts/adversarial-verification-council.md +29 -0
- package/dist/agent-src/skills/subagent-orchestration/prompts/do-and-judge-two-stage.md +29 -0
- package/dist/agent-src/skills/subagent-orchestration/prompts/do-and-judge.md +29 -0
- package/dist/agent-src/skills/subagent-orchestration/prompts/do-competitively.md +29 -0
- package/dist/agent-src/skills/subagent-orchestration/prompts/do-in-parallel.md +29 -0
- package/dist/agent-src/skills/subagent-orchestration/prompts/do-in-steps.md +29 -0
- package/dist/agent-src/skills/subagent-orchestration/prompts/do-in-worktrees.md +29 -0
- package/dist/agent-src/skills/subagent-orchestration/prompts/judge-with-debate.md +29 -0
- package/dist/agent-src/skills/verify-repair-loop/SKILL.md +4 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/github-workflows/doc-impact.yml +101 -0
- package/dist/agent-src/templates/github-workflows/secret-scan.yml +65 -0
- package/dist/cli/configRoot.js +112 -0
- package/dist/cli/configRoot.js.map +1 -0
- package/dist/cli/configRoot.test.js +97 -0
- package/dist/cli/configRoot.test.js.map +1 -0
- package/dist/cli/help.js +4 -1
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/main.js +19 -2
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/registry.js +1 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +164 -47
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +4 -4
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +13 -8
- package/dist/discovery/trust-report.md +11 -11
- package/dist/discovery/workspaces.json +11 -6
- package/dist/install/install.mjs +16 -0
- package/dist/mcp/awesome-mcp-servers.row.md +1 -1
- package/dist/mcp/mcp-cloudflare-catalogue.json +1 -1
- package/dist/mcp/registry-manifest.json +4 -4
- package/dist/router.json +1 -1
- package/dist/server/app.js +10 -0
- package/dist/server/app.js.map +1 -1
- package/dist/server/routes/ping.js +18 -0
- package/dist/server/routes/ping.js.map +1 -1
- package/dist/server/schemas/settings.js +8 -0
- package/dist/server/schemas/settings.js.map +1 -1
- package/dist/server/serverInfo.js +6 -2
- package/dist/server/serverInfo.js.map +1 -1
- package/dist/server/token.js +11 -4
- package/dist/server/token.js.map +1 -1
- package/dist/server/writeRoot.js +15 -1
- package/dist/server/writeRoot.js.map +1 -1
- package/dist/shared/capabilities.js +33 -0
- package/dist/shared/capabilities.js.map +1 -0
- package/dist/shared/capabilities.test.js +39 -0
- package/dist/shared/capabilities.test.js.map +1 -0
- package/dist/ui/assets/{index-BiEZiZ31.js → index-CrmZ34Rg.js} +16 -16
- package/dist/ui/assets/index-CrmZ34Rg.js.map +1 -0
- package/dist/ui/index.html +14 -5
- package/docs/CLAIMS.md +64 -38
- package/docs/architecture.md +2 -2
- package/docs/archive/CHANGELOG-6.0.0-overview.md +953 -0
- package/docs/benchmark.md +170 -9
- package/docs/catalog.md +8 -3
- package/docs/comparison.yaml +44 -2
- package/docs/contracts/local-server-ports.md +53 -0
- package/docs/contracts/no-runtime-boundary.md +1 -1
- package/docs/contracts/subagent-boundary.md +15 -0
- package/docs/customization.md +14 -3
- package/docs/decisions/ADR-016-installer-architecture.md +2 -0
- package/docs/decisions/ADR-088-no-external-runtime-federation.md +1 -1
- package/docs/decisions/ADR-094-agent-memory-layer-removal.md +1 -1
- package/docs/decisions/ADR-109-subagent-v1-contract.md +2 -0
- package/docs/decisions/ADR-110-discipline-profile-resolution-locus.md +2 -0
- package/docs/decisions/ADR-113-ci-native-release-label-trigger.md +11 -3
- package/docs/decisions/ADR-122-adversarial-verification-council.md +30 -0
- package/docs/decisions/ADR-123-runtime-security-scope-and-spawn-hardening.md +31 -0
- package/docs/decisions/ADR-124-embedded-engine-doctrine.md +255 -0
- package/docs/decisions/ADR-125-doc-screenshot-anonymization.md +131 -0
- package/docs/decisions/ADR-126-internet-reach-operator-tooling.md +254 -0
- package/docs/decisions/ADR-127-enforcement-claims-must-resolve.md +150 -0
- package/docs/decisions/ADR-128-executable-evidence-and-measured-escalation.md +201 -0
- package/docs/decisions/INDEX.md +21 -0
- package/docs/decisions/engine-reclassification-2026-07.md +104 -0
- package/docs/distribution/awesome-list-submission.md +1 -1
- package/docs/distribution/registries.md +36 -27
- package/docs/enforcement-by-host.md +7 -0
- package/docs/featured-skills.md +2 -2
- package/docs/getting-started-by-role.md +1 -1
- package/docs/getting-started.md +1 -1
- package/docs/governance-advantage.md +1 -1
- package/docs/guides/gated-platform-reads.md +221 -0
- package/docs/positioning-evidence.md +1 -1
- package/docs/proof.md +92 -16
- package/docs/spawn-site-policy.md +72 -0
- package/docs/threat-model.md +2 -1
- package/package.json +6 -3
- package/src/agent-src/README.md +2 -2
- package/src/config/agent-settings.template.yml +43 -0
- package/src/config/reach-channels.yml +217 -0
- package/src/config/reach-prescriptions-intake.yml +200 -0
- package/src/scripts/_dispatch.bash +15 -0
- package/src/scripts/_lib/adversarial_bench_score.ts +106 -0
- package/src/scripts/_lib/exec_evidence.ts +251 -0
- package/src/scripts/_lib/fixtures/secret-detector/negatives.txt +10 -0
- package/src/scripts/_lib/fixtures/secret-detector/positives.txt +11 -0
- package/src/scripts/_lib/kernel_rules.ts +46 -0
- package/src/scripts/_lib/reddit_thread_parse.ts +598 -0
- package/src/scripts/_lib/risk_paths.ts +160 -0
- package/src/scripts/_lib/secret_detector.test.ts +103 -0
- package/src/scripts/_lib/secret_detector.ts +319 -0
- package/src/scripts/_lib/spawn_env.ts +24 -4
- package/src/scripts/_lib/tool_probe.ts +359 -0
- package/src/scripts/adr/regenerate_index.ts +81 -6
- package/src/scripts/audit_adr_coverage.ts +33 -0
- package/src/scripts/bench_adversarial_council.ts +292 -0
- package/src/scripts/build_proof.ts +162 -0
- package/src/scripts/check_adr_frontmatter.ts +195 -0
- package/src/scripts/check_artefact_count_messaging.ts +4 -0
- package/src/scripts/check_backstop_debt.ts +200 -0
- package/src/scripts/check_claims.ts +188 -8
- package/src/scripts/check_comparison.ts +12 -0
- package/src/scripts/check_enforcement_coverage.ts +592 -0
- package/src/scripts/check_kernel_rule_bundle.ts +16 -12
- package/src/scripts/check_no_new_legacy_path.ts +2 -0
- package/src/scripts/check_reach_channels.ts +407 -0
- package/src/scripts/check_reach_staleness.ts +364 -0
- package/src/scripts/check_secret_leak.test.ts +47 -0
- package/src/scripts/check_secret_leak.ts +290 -0
- package/src/scripts/check_source_pointer_freshness.ts +165 -0
- package/src/scripts/code_graph/build.ts +0 -0
- package/src/scripts/code_graph/cli.ts +207 -0
- package/src/scripts/code_graph/detect.ts +134 -0
- package/src/scripts/code_graph/extract.ts +386 -0
- package/src/scripts/code_graph/loader.ts +123 -0
- package/src/scripts/code_graph/query.ts +176 -0
- package/src/scripts/code_graph/sanitize.ts +30 -0
- package/src/scripts/code_graph/types.ts +83 -0
- package/src/scripts/code_graph/validate.ts +63 -0
- package/src/scripts/external_sources_denylist.json +3 -1
- package/src/scripts/generate_subagent_floor.ts +194 -0
- package/src/scripts/hook_manifest.yaml +13 -3
- package/src/scripts/hooks/code_graph_nudge_hook.ts +184 -0
- package/src/scripts/hooks/dispatch_hook.ts +5 -1
- package/src/scripts/iron_law_sha.ts +3 -12
- package/src/scripts/lint_override_kernel_guard.ts +219 -0
- package/src/scripts/lint_readme_serial_comma.ts +169 -0
- package/src/scripts/measure_rule_budget.ts +3 -12
- package/src/scripts/postinstall_gui.ts +129 -0
- package/src/scripts/reach_doctor.ts +1651 -0
- package/src/scripts/release.ts +24 -3
- package/src/scripts/risk_escalation_shadow.ts +160 -0
- package/src/scripts/schemas/agent-settings.schema.json +23 -0
- package/src/scripts/schemas/reach-channels.schema.json +134 -0
- package/src/scripts/schemas/reach-doctor-payload.schema.json +220 -0
- package/src/scripts/schemas/rule.schema.json +10 -0
- package/src/scripts/skill_linter.ts +55 -0
- package/src/scripts/validate_reach_prescriptions.ts +751 -0
- package/src/server/schemas/settings.ts +16 -0
- package/src/shared/capabilities.test.ts +43 -0
- package/src/shared/capabilities.ts +75 -0
- package/src/templates/minimal/agents-overrides-readme.md +20 -0
- 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.
|