@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,251 @@
1
+ /**
2
+ * `exec:` evidence — the ledger form that re-derives its own claim.
3
+ *
4
+ * The other three evidence forms are existence checks: a file is present, a
5
+ * substring is present, a URL carries a date. None of them can tell a live
6
+ * claim from a stale one. A ledger entry reading "the suite is green" whose
7
+ * pointer resolves to a report nobody regenerated stays `backed` forever.
8
+ *
9
+ * `exec:<command> -> 0` closes that: the command runs again and its exit code
10
+ * carries the verdict. Three properties make it safe enough to run in CI, and
11
+ * all three are the parts that get dropped when this is rebuilt from memory:
12
+ *
13
+ * 1. The allowlist is a set of **argv prefix tuples**, never a regex over a
14
+ * command string. A regex over shell text is the classic bypass; a tuple
15
+ * compared against parsed argv has nothing to hide behind.
16
+ * 2. Every argument *after* the matched prefix is re-checked — for shell
17
+ * metacharacters and for repo escape — including the right-hand side of
18
+ * `--flag=value`. Without that split, `--rootdir=/etc` clears an allowlist
19
+ * that only ever looked at the flag name.
20
+ * 3. Execution is `spawnSync` with an argv array and no shell, confined to the
21
+ * repo root, and gated to CI. Locally the caller reports UNVERIFIED rather
22
+ * than running anything — see `exec_allowed_here()`.
23
+ *
24
+ * Scope limit, stated rather than discovered later: this form only covers
25
+ * claims whose exit code *is* the verdict. A claim resting on a paid model run,
26
+ * a stochastic benchmark, or a prose contract cannot use it, and is recorded as
27
+ * unfalsifiable-by-machine instead of quietly omitted.
28
+ */
29
+
30
+ import { spawnSync } from 'node:child_process';
31
+ import path from 'node:path';
32
+
33
+ /** Marker that opens the fourth evidence form. */
34
+ export const EXEC_PREFIX = 'exec:';
35
+
36
+ /**
37
+ * Allowlisted argv prefixes. Each entry is matched element-by-element against
38
+ * the parsed argv — `["skill_eval_coverage"]` admits
39
+ * `skill_eval_coverage --check` but not `skill_eval_coverage; rm -rf /`,
40
+ * because the latter never parses into that shape.
41
+ *
42
+ * All but one are this repo's own scripts, run through `scripts-run`. That is a
43
+ * deliberately narrower surface than a general test-runner allowlist: these are
44
+ * deterministic, model-free, and already run in CI for other reasons.
45
+ */
46
+ export const ALLOWLIST_PREFIXES: readonly (readonly string[])[] = [
47
+ ['skill_eval_coverage'],
48
+ ['domain_soundness_status'],
49
+ ['check_artefact_count_messaging'],
50
+ ['check_enforcement_coverage'],
51
+ ['check_token_regression'],
52
+ ['lint_agent_security'],
53
+ ['measure_lexical_ranking'],
54
+ ['vitest', 'run'],
55
+ ];
56
+
57
+ /** Shell metacharacters plus the control bytes used to smuggle a second command. */
58
+ const UNSAFE_CHARS = new Set(['&', ';', '|', '>', '<', '`', '$', '\n', '\r', '\0']);
59
+
60
+ const WINDOWS_ABSOLUTE = /^[A-Za-z]:[\\/]/;
61
+
62
+ /** Commands that are not repo scripts and must not be routed through scripts-run. */
63
+ const NON_SCRIPT_PREFIXES = new Set(['vitest']);
64
+
65
+ export interface ExecPointer {
66
+ /** The command as written in the ledger, e.g. `skill_eval_coverage --check`. */
67
+ command: string;
68
+ /** The exit code the claim asserts. */
69
+ expected: number;
70
+ }
71
+
72
+ export interface ExecOutcome {
73
+ /** `true` only when the command ran AND matched the asserted exit code. */
74
+ verified: boolean;
75
+ /** `true` when the command ran and disagreed — a real finding, not a skip. */
76
+ mismatch: boolean;
77
+ /** Human-readable verdict for the report. */
78
+ reason: string;
79
+ }
80
+
81
+ /**
82
+ * Parse `exec:<command> -> <code>`. Accepts `->` and the `→` the docs render.
83
+ * Returns null when `raw` is not an exec pointer at all, so callers can fall
84
+ * through to the path/URL forms.
85
+ */
86
+ export function parse_exec_pointer(raw: string): ExecPointer | { error: string } | null {
87
+ const ev = raw.trim();
88
+ if (!ev.startsWith(EXEC_PREFIX)) return null;
89
+
90
+ const body = ev.slice(EXEC_PREFIX.length).trim();
91
+ const arrow = body.match(/\s*(?:->|→)\s*(\d+)\s*$/);
92
+ if (!arrow) return { error: 'exec pointer missing the `-> <exit-code>` suffix' };
93
+
94
+ const command = body.slice(0, arrow.index).trim();
95
+ if (!command) return { error: 'exec pointer has an empty command' };
96
+
97
+ return { command, expected: Number(arrow[1]) };
98
+ }
99
+
100
+ /**
101
+ * Split a command into argv without invoking a shell. Deliberately minimal: no
102
+ * quote handling, no expansion, no substitution. Anything that would *need*
103
+ * those is rejected by `args_are_safe` anyway, so supporting them would only
104
+ * widen the surface.
105
+ */
106
+ export function split_argv(command: string): string[] {
107
+ return command.split(/\s+/).filter((t) => t.length > 0);
108
+ }
109
+
110
+ /** Does argv start with an allowlisted prefix? */
111
+ export function command_is_allowlisted(argv: string[]): boolean {
112
+ return ALLOWLIST_PREFIXES.some(
113
+ (prefix) => argv.length >= prefix.length && prefix.every((tok, i) => argv[i] === tok),
114
+ );
115
+ }
116
+
117
+ /** Would this argument reach outside the repo? */
118
+ function targets_outside_repo(candidate: string): boolean {
119
+ if (candidate.startsWith('/')) return true;
120
+ if (WINDOWS_ABSOLUTE.test(candidate)) return true;
121
+ if (candidate === '..' || candidate.startsWith('../')) return true;
122
+ return candidate.includes('/../');
123
+ }
124
+
125
+ /**
126
+ * Re-check every argument after the allowlisted prefix.
127
+ *
128
+ * The `--flag=value` split is the part worth keeping: an allowlist that only
129
+ * inspects the token as written treats `--rootdir=/etc` as a flag and lets the
130
+ * path through. Here the right-hand side is extracted and checked on its own.
131
+ */
132
+ export function args_are_safe(argv: string[]): boolean {
133
+ for (const arg of argv.slice(1)) {
134
+ for (const ch of arg) {
135
+ if (UNSAFE_CHARS.has(ch)) return false;
136
+ }
137
+ const eq = arg.indexOf('=');
138
+ const candidate = arg.startsWith('-') && eq !== -1 ? arg.slice(eq + 1) : arg;
139
+ if (candidate && targets_outside_repo(candidate)) return false;
140
+ }
141
+ return true;
142
+ }
143
+
144
+ /**
145
+ * Static validation — everything checkable without running anything.
146
+ *
147
+ * Split out from `run_exec_evidence` on purpose: a malformed or non-allowlisted
148
+ * command is a defect in the *ledger*, so it must fail on a laptop too. Only
149
+ * the re-execution half is environment-dependent. Returns null when the pointer
150
+ * is well-formed and admissible, else the reason.
151
+ */
152
+ export function exec_static_error(pointer: ExecPointer): string | null {
153
+ const argv = split_argv(pointer.command);
154
+ if (argv.length === 0) return 'exec pointer has an empty command';
155
+ if (!command_is_allowlisted(argv)) {
156
+ return `exec command \`${pointer.command}\` is not in the deterministic allowlist`;
157
+ }
158
+ if (!args_are_safe(argv)) {
159
+ return `exec command \`${pointer.command}\` carries a suspicious argument`;
160
+ }
161
+ return null;
162
+ }
163
+
164
+ /**
165
+ * May this environment execute evidence commands?
166
+ *
167
+ * CI only. A consumer's checkout never re-runs a claim's command — the upstream
168
+ * package's ledger is not the consumer's business, and "runs in the repository
169
+ * root with full filesystem access" is a property to confine, not to trust.
170
+ */
171
+ export function exec_allowed_here(env: NodeJS.ProcessEnv = process.env): boolean {
172
+ if (env.AGENT_CONFIG_EXEC_EVIDENCE === '1') return true; // maintainer opt-in, one run
173
+ return env.CI === 'true' || env.CI === '1';
174
+ }
175
+
176
+ /** Build the real argv: repo scripts go through `scripts-run`, others run directly. */
177
+ function resolve_runner(argv: string[], repo: string): { file: string; args: string[] } {
178
+ const head = argv[0] as string;
179
+ if (NON_SCRIPT_PREFIXES.has(head)) {
180
+ return { file: path.join(repo, 'node_modules', '.bin', head), args: argv.slice(1) };
181
+ }
182
+ return {
183
+ file: path.join(repo, 'scripts-run'),
184
+ args: [`src/scripts/${head}`, ...argv.slice(1)],
185
+ };
186
+ }
187
+
188
+ /**
189
+ * Run an allowlisted evidence command and compare its exit code to the claim.
190
+ *
191
+ * Never throws: every failure path returns an `ExecOutcome` so one bad pointer
192
+ * cannot take down the whole ledger check. `mismatch` distinguishes "ran and
193
+ * disagreed" (a finding) from "could not run" (a skip) — collapsing those two
194
+ * is how a verifier turns into a rubber stamp.
195
+ */
196
+ export function run_exec_evidence(pointer: ExecPointer, repo: string, timeoutMs = 300_000): ExecOutcome {
197
+ const argv = split_argv(pointer.command);
198
+
199
+ if (argv.length === 0) {
200
+ return { verified: false, mismatch: false, reason: 'UNVERIFIED: empty command' };
201
+ }
202
+ if (!command_is_allowlisted(argv)) {
203
+ return {
204
+ verified: false,
205
+ mismatch: false,
206
+ reason: `UNVERIFIED: \`${pointer.command}\` is not in the deterministic allowlist`,
207
+ };
208
+ }
209
+ if (!args_are_safe(argv)) {
210
+ return {
211
+ verified: false,
212
+ mismatch: false,
213
+ reason: `UNVERIFIED: \`${pointer.command}\` carries a suspicious argument`,
214
+ };
215
+ }
216
+
217
+ const { file, args } = resolve_runner(argv, repo);
218
+ const result = spawnSync(file, args, {
219
+ cwd: repo,
220
+ encoding: 'utf-8',
221
+ timeout: timeoutMs,
222
+ shell: false,
223
+ });
224
+
225
+ if (result.error) {
226
+ return {
227
+ verified: false,
228
+ mismatch: false,
229
+ reason: `UNVERIFIED: could not execute \`${pointer.command}\` (${result.error.message})`,
230
+ };
231
+ }
232
+ if (result.status === null) {
233
+ return {
234
+ verified: false,
235
+ mismatch: false,
236
+ reason: `UNVERIFIED: \`${pointer.command}\` was killed (timeout or signal)`,
237
+ };
238
+ }
239
+ if (result.status !== pointer.expected) {
240
+ return {
241
+ verified: false,
242
+ mismatch: true,
243
+ reason: `evidence mismatch — claim asserts exit ${pointer.expected}, \`${pointer.command}\` exited ${result.status}`,
244
+ };
245
+ }
246
+ return {
247
+ verified: true,
248
+ mismatch: false,
249
+ reason: `verified \`${pointer.command}\` (exit ${result.status})`,
250
+ };
251
+ }
@@ -0,0 +1,10 @@
1
+ # secret-detector negative fixtures — all benign, must not flag high/medium.
2
+ api_key = "changeme"
3
+ api_key = "xxxxxxxxxxxxxxxx"
4
+ password = "your-password-here"
5
+ build commit d41d8cd98f00b204e9800998ecf8427e5f1a2b3c
6
+ request id 550e8400-e29b-41d4-a716-446655440000
7
+ bundle integrity 3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b
8
+ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAElFTkSuQmCC
9
+ API_KEY=your-key-here
10
+ aws_key = "AKIAZ4Q7WXYT2H9RVBKL" # secret-allow
@@ -0,0 +1,11 @@
1
+ # secret-detector positive fixtures — every value below is FAKE, do not use.
2
+ # Line format: <kind-label>|<fake-secret>
3
+ aws|AKIA1234567890ABCDEF
4
+ github|ghp_0123456789abcdefghijklmnopqrstuvwxyz
5
+ stripe|sk_live_0123456789abcdefABCDEF
6
+ google|AIza0123456789abcdefghijklmnopqrstuvwxy
7
+ slack|xoxb-0123456789-abcdefABCDEF
8
+ pem|-----BEGIN RSA PRIVATE KEY-----
9
+ jwt|eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
10
+ dburl|postgres://dbuser:s3cr3tpass@db.internal:5432/app
11
+ assignment|api_key = "s3cr3tV4lu3Abc123"
@@ -0,0 +1,46 @@
1
+ /**
2
+ * The locked kernel set — one definition, imported everywhere.
3
+ *
4
+ * These nine rules are the Iron-Law floor (`docs/contracts/kernel-membership.md`
5
+ * § 4). Before this module the list existed three times — in
6
+ * `check_kernel_rule_bundle.ts`, `iron_law_sha.ts`, and `measure_rule_budget.ts`
7
+ * — two of them carrying a "kept in sync with …" comment, which is the standard
8
+ * way a list drifts: the comment records an intention, nothing enforces it.
9
+ *
10
+ * Membership is a governance decision, not a convenience. Adding or removing an
11
+ * entry changes what may never be overridden, what the prefix-stability snapshot
12
+ * covers, and what the one-kernel-rule-per-PR gate applies to. Change it here,
13
+ * once, and let every consumer follow.
14
+ */
15
+
16
+ /** Kernel rule ids, stem form (no extension), in stable sorted order. */
17
+ export const KERNEL_RULE_IDS: readonly string[] = [
18
+ 'agent-authority',
19
+ 'ask-when-uncertain',
20
+ 'commit-policy',
21
+ 'direct-answers',
22
+ 'language-and-tone',
23
+ 'no-cheap-questions',
24
+ 'non-destructive-by-default',
25
+ 'scope-control',
26
+ 'verify-before-complete',
27
+ ] as const;
28
+
29
+ /** Same set, `.md` filename form — what path-matching consumers compare against. */
30
+ export const KERNEL_RULE_FILENAMES: ReadonlySet<string> = new Set(
31
+ KERNEL_RULE_IDS.map((id) => `${id}.md`),
32
+ );
33
+
34
+ /** Set form of the stems, for membership tests that key on the id. */
35
+ export const KERNEL_RULE_ID_SET: ReadonlySet<string> = new Set(KERNEL_RULE_IDS);
36
+
37
+ /**
38
+ * True when `name` names a kernel rule, in either stem or `.md` form.
39
+ *
40
+ * Accepts a bare id, a filename, or a path ending in either — callers hold the
41
+ * name in all three shapes and should not each re-derive the normalisation.
42
+ */
43
+ export function is_kernel_rule(name: string): boolean {
44
+ const base = name.replace(/\\/g, '/').split('/').pop() ?? name;
45
+ return KERNEL_RULE_ID_SET.has(base.replace(/\.md$/, ''));
46
+ }