gentle-pi 2.1.2 → 2.3.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 (228) hide show
  1. package/README.md +108 -79
  2. package/assets/agents/gentle-ai-worker.md +7 -3
  3. package/assets/agents/jd-fix-agent.md +1 -1
  4. package/assets/agents/jd-judge-a.md +3 -1
  5. package/assets/agents/jd-judge-b.md +3 -1
  6. package/assets/agents/review-readability.md +4 -3
  7. package/assets/agents/review-reliability.md +4 -3
  8. package/assets/agents/review-resilience.md +4 -3
  9. package/assets/agents/review-risk.md +4 -3
  10. package/assets/agents/sdd-apply.md +11 -4
  11. package/assets/agents/sdd-archive.md +6 -1
  12. package/assets/agents/sdd-design.md +6 -1
  13. package/assets/agents/sdd-explore.md +6 -2
  14. package/assets/agents/sdd-init.md +10 -2
  15. package/assets/agents/sdd-onboard.md +6 -1
  16. package/assets/agents/sdd-proposal.md +8 -1
  17. package/assets/agents/sdd-research.md +54 -0
  18. package/assets/agents/sdd-spec.md +6 -1
  19. package/assets/agents/sdd-status.md +10 -5
  20. package/assets/agents/sdd-sync.md +6 -1
  21. package/assets/agents/sdd-tasks.md +8 -4
  22. package/assets/agents/sdd-verify.md +27 -2
  23. package/assets/chains/4r-review.chain.md +2 -0
  24. package/assets/chains/sdd-full.chain.md +2 -2
  25. package/assets/chains/sdd-plan.chain.md +1 -1
  26. package/assets/chains/sdd-verify.chain.md +2 -2
  27. package/assets/orchestrator-delegation.md +145 -160
  28. package/assets/orchestrator-memory.md +2 -0
  29. package/assets/orchestrator.md +25 -48
  30. package/assets/sdd-orchestrator-workflow.md +163 -25
  31. package/assets/support/sdd-status-contract.md +24 -6
  32. package/contracts/review-integration/v1/fixtures/consent.fixture.json +3 -3
  33. package/contracts/review-integration/v1/fixtures/start-v2.fixture.json +19 -28
  34. package/contracts/review-integration/v1/fixtures/start.fixture.json +1 -10
  35. package/contracts/review-integration/v1/fixtures/status-v2.fixture.json +12 -21
  36. package/contracts/review-integration/v1/schemas/correction-plan-request.schema.json +49 -0
  37. package/contracts/review-integration/v1/schemas/operation.schema.json +76 -0
  38. package/contracts/review-integration/v1/schemas/repair.schema.json +39 -0
  39. package/contracts/review-integration/v1/schemas/status-v2.schema.json +4 -2
  40. package/contracts/review-integration/v1/schemas/status.schema.json +4 -2
  41. package/contracts/review-integration/v1/schemas/transition-execution.schema.json +42 -0
  42. package/contracts/review-integration/v2/fixtures/consent.fixture.json +1 -1
  43. package/contracts/review-integration/v2/fixtures/start.fixture.json +1 -10
  44. package/contracts/review-integration/v2/fixtures/status.fixture.json +1 -10
  45. package/contracts/review-integration/v2/schemas/failure.schema.json +5 -1
  46. package/contracts/review-integration/v2/schemas/last-event-closure.schema.json +66 -0
  47. package/contracts/review-integration/v2/schemas/opencode-provider-role.schema.json +14 -0
  48. package/contracts/review-integration/v2/schemas/operation.schema.json +6 -1
  49. package/contracts/review-integration/v2/schemas/repair.schema.json +4 -2
  50. package/contracts/review-integration/v2/schemas/start.schema.json +5 -2
  51. package/contracts/review-integration/v2/schemas/status.schema.json +4 -2
  52. package/contracts/review-provider-contract-mirror/provider-contract.lock.json +30 -0
  53. package/contracts/review-provider-contract-mirror/v1.1.0/bundle/README.md +12 -0
  54. package/contracts/review-provider-contract-mirror/v1.1.0/bundle/manifest.json +65 -0
  55. package/contracts/review-provider-contract-mirror/v1.1.0/bundle/schemas/lens.schema.json +16 -0
  56. package/contracts/review-provider-contract-mirror/v1.1.0/bundle/schemas/refuter.schema.json +1 -0
  57. package/contracts/review-provider-contract-mirror/v1.1.0/bundle/schemas/targeted-validator.schema.json +1 -0
  58. package/contracts/review-provider-contract-mirror/v1.1.0/bundle/vectors/lens.json +1 -0
  59. package/contracts/review-provider-contract-mirror/v1.1.0/bundle/vectors/refuter.json +1 -0
  60. package/contracts/review-provider-contract-mirror/v1.1.0/bundle/vectors/targeted-validator.json +1 -0
  61. package/contracts/review-provider-contract-mirror/v1.1.0/generated/provider-capabilities.baseline.json +15 -0
  62. package/contracts/review-provider-contract-mirror/v1.1.0/generated/provider-roles.baseline.json +42 -0
  63. package/docs/native-authority-architecture.md +14 -16
  64. package/docs/review-integration.md +27 -353
  65. package/extensions/ask-user-choice.ts +151 -0
  66. package/extensions/gentle-ai.ts +2710 -3211
  67. package/extensions/quiet-tools.ts +515 -32
  68. package/extensions/sdd-init.ts +21 -12
  69. package/extensions/skill-registry.ts +10 -2
  70. package/extensions/startup-banner.ts +10 -4
  71. package/lib/gentle-ai-binary.ts +173 -2
  72. package/lib/gentle-ai-renderer.ts +70 -0
  73. package/lib/model-routing-authority.ts +133 -0
  74. package/lib/native-review-cli.ts +676 -781
  75. package/lib/opaque-pi-reviewer-adapter.ts +284 -0
  76. package/lib/provider-contract-bundle.ts +704 -0
  77. package/lib/review-candidate-view.ts +836 -118
  78. package/lib/review-compact-contract.ts +59 -248
  79. package/lib/review-host-relay.ts +578 -0
  80. package/lib/review-integration-v2.ts +1254 -221
  81. package/lib/review-last-event-controller.ts +35 -0
  82. package/lib/review-relay-contract.ts +16 -0
  83. package/lib/sdd-preflight.ts +230 -67
  84. package/lib/sdd-status.ts +66 -111
  85. package/lib/terminal-theme.ts +1 -1
  86. package/package.json +83 -79
  87. package/runtime/gentle-ai-binary.mjs +174 -3
  88. package/runtime/native-review-cli.mjs +610 -715
  89. package/runtime/review-integration-v2.mjs +1223 -190
  90. package/runtime/review-relay-contract.mjs +17 -0
  91. package/scripts/{build-git-commit-transaction-runner.mjs → build-runtime-modules.mjs} +5 -5
  92. package/scripts/check-provider-contract.mjs +138 -0
  93. package/scripts/gentle-ai-installer.mjs +85 -22
  94. package/scripts/maintainer/provider-relay-matrix.mjs +403 -0
  95. package/scripts/mirror-provider-contract.mjs +143 -0
  96. package/scripts/test-packed-runner.mjs +20 -9
  97. package/scripts/verify-package-files.mjs +119 -43
  98. package/skills/_shared/review-ledger-contract.md +11 -19
  99. package/skills/chained-pr/SKILL.md +3 -0
  100. package/skills/cognitive-doc-design/SKILL.md +1 -1
  101. package/skills/comment-writer/SKILL.md +1 -1
  102. package/skills/gentle-ai/SKILL.md +7 -74
  103. package/skills/issue-creation/SKILL.md +94 -168
  104. package/skills/judgment-day/SKILL.md +9 -5
  105. package/skills/judgment-day/references/prompts-and-formats.md +2 -0
  106. package/skills/rdd-defect-workflow/SKILL.md +54 -0
  107. package/skills/release/SKILL.md +3 -3
  108. package/skills/skill-registry/SKILL.md +1 -1
  109. package/skills/work-unit-commits/SKILL.md +3 -1
  110. package/tests/artifact-language.test.ts +24 -11
  111. package/tests/ask-user-choice.test.ts +264 -0
  112. package/tests/background-subagents.test.ts +771 -0
  113. package/tests/codegraph-tools.test.ts +3 -3
  114. package/tests/crosslane/cross-lane.mjs +16 -0
  115. package/tests/delegated-key-learnings-contract.test.ts +240 -0
  116. package/tests/devbinary/native-review-parity.devtest.ts +167 -250
  117. package/tests/devbinary/pi-host-relay.devtest.ts +867 -0
  118. package/tests/fixtures/devbinary/capabilities-v2.1.derived.json +331 -0
  119. package/tests/fixtures/devbinary/capabilities-v2.2.captured.json +340 -0
  120. package/tests/fixtures/devbinary/consent-v3.captured.json +37 -0
  121. package/tests/fixtures/devbinary/failure-v2-capture-evidence.captured.json +16 -0
  122. package/tests/fixtures/devbinary/last-event-capture-correction-plan.captured.json +10 -0
  123. package/tests/fixtures/devbinary/last-event-capture-refuter-approved.captured.json +20 -0
  124. package/tests/fixtures/devbinary/last-event-capture-refuter-correction-required.captured.json +26 -0
  125. package/tests/fixtures/devbinary/last-event-capture-result-approved.captured.json +8 -0
  126. package/tests/fixtures/devbinary/last-event-capture-result-correction-required.captured.json +26 -0
  127. package/tests/fixtures/devbinary/last-event-capture-validation-approved.captured.json +8 -0
  128. package/tests/fixtures/devbinary/last-event-closure.provenance.md +13 -0
  129. package/tests/fixtures/devbinary/result-artifact-v2-path.captured.json +12 -0
  130. package/tests/fixtures/devbinary/result-artifact-v2.captured.json +12 -0
  131. package/tests/fixtures/devbinary/review-acknowledged-v1.captured.json +9 -0
  132. package/tests/fixtures/devbinary/review-acknowledged.provenance.md +31 -0
  133. package/tests/fixtures/devbinary/start-v3-consent-declined.captured.json +19 -0
  134. package/tests/fixtures/devbinary/start-v3-consent-granted.captured.json +109 -0
  135. package/tests/fixtures/devbinary/start-v3-zero-lens-closed.captured.json +21 -0
  136. package/tests/fixtures/devbinary/status-v5-capture-result-submission.captured.json +184 -0
  137. package/tests/fixtures/devbinary/status-v5-repository-context.captured.json +138 -0
  138. package/tests/fixtures/devbinary/status-v5.captured.json +88 -0
  139. package/tests/fixtures/native-review-cli/v2.5.0-rc.1/PROVENANCE.txt +15 -0
  140. package/tests/fixtures/provider-contract-bundle/v1.1.0/README.md +12 -0
  141. package/tests/fixtures/provider-contract-bundle/v1.1.0/manifest.json +65 -0
  142. package/tests/fixtures/provider-contract-bundle/v1.1.0/schemas/lens.schema.json +16 -0
  143. package/tests/fixtures/provider-contract-bundle/v1.1.0/schemas/refuter.schema.json +1 -0
  144. package/tests/fixtures/provider-contract-bundle/v1.1.0/schemas/targeted-validator.schema.json +1 -0
  145. package/tests/fixtures/provider-contract-bundle/v1.1.0/vectors/lens.json +1 -0
  146. package/tests/fixtures/provider-contract-bundle/v1.1.0/vectors/refuter.json +1 -0
  147. package/tests/fixtures/provider-contract-bundle/v1.1.0/vectors/targeted-validator.json +1 -0
  148. package/tests/gentle-ai-binary.test.ts +83 -13
  149. package/tests/gentle-ai-dev-binary-surfacing.test.ts +195 -0
  150. package/tests/gentle-ai-dev-binary.test.ts +159 -0
  151. package/tests/gentle-ai-installer.test.ts +138 -48
  152. package/tests/gentle-ai.test.ts +820 -131
  153. package/tests/gentle-theme.test.ts +133 -0
  154. package/tests/maintainer/provider-relay.maintest.ts +601 -0
  155. package/tests/model-routing-authority.test.ts +257 -0
  156. package/tests/native-review-capability-contract.test.ts +75 -2
  157. package/tests/native-review-cli.test.ts +588 -908
  158. package/tests/native-review-consent.test.ts +283 -38
  159. package/tests/native-review-parity-runtime.test.ts +108 -350
  160. package/tests/native-review-parity.test.ts +684 -732
  161. package/tests/native-sdd-attempt-authority.test.ts +235 -0
  162. package/tests/opaque-pi-reviewer-adapter.test.ts +266 -0
  163. package/tests/orchestrator-budget.test.ts +158 -89
  164. package/tests/orchestrator-rdd-ownership.test.ts +103 -0
  165. package/tests/package-manifest.test.ts +128 -100
  166. package/tests/provider-contract-bundle.test.ts +385 -0
  167. package/tests/provider-contract-mirror.test.ts +206 -0
  168. package/tests/provider-defect-handoff.test.ts +252 -0
  169. package/tests/quiet-tool-rendering.test.ts +1055 -28
  170. package/tests/review-actor-tool-deny.test.ts +12 -13
  171. package/tests/review-authority-recovery-docs.test.ts +1 -2
  172. package/tests/review-candidate-view.test.ts +898 -12
  173. package/tests/review-compact-contract.test.ts +29 -122
  174. package/tests/review-controller-lock-status.test.ts +2 -2
  175. package/tests/review-controller-native-recovery.test.ts +366 -857
  176. package/tests/review-controller-native-routing.test.ts +1253 -4199
  177. package/tests/review-controller-retired-ops.test.ts +1 -1
  178. package/tests/review-controller-workspace-root.test.ts +236 -70
  179. package/tests/review-controller.test.ts +26 -816
  180. package/tests/review-corrected-finalize-binding.test.ts +134 -0
  181. package/tests/review-dispatch-hydration-gap.test.ts +145 -0
  182. package/tests/review-gate.test.ts +0 -45
  183. package/tests/review-host-relay-restart-parity.test.ts +360 -0
  184. package/tests/review-host-relay-routing.test.ts +352 -0
  185. package/tests/review-host-relay.test.ts +754 -0
  186. package/tests/review-integration-v2-forward.test.ts +654 -0
  187. package/tests/review-integration-v2.test.ts +317 -129
  188. package/tests/review-last-event-closure.test.ts +408 -0
  189. package/tests/review-ledger-contract.test.ts +106 -60
  190. package/tests/review-recovered-lineage-routing.test.ts +199 -0
  191. package/tests/review-relay-transport-agent.test.ts +322 -0
  192. package/tests/review-snapshot.test.ts +3 -2
  193. package/tests/runtime-harness.mjs +573 -180
  194. package/tests/sdd-agent-tools.test.ts +53 -32
  195. package/tests/sdd-preflight.test.ts +81 -15
  196. package/tests/sdd-status.test.ts +109 -110
  197. package/tests/skill-collision-prefixes.test.ts +6 -8
  198. package/tests/skill-registry.test.ts +50 -1
  199. package/tests/verify-package-files.test.ts +62 -0
  200. package/tests/writer-edit-surface-scope.test.ts +230 -0
  201. package/themes/Gentleman-Cute.json +94 -0
  202. package/themes/Gentleman-Sexy.json +92 -0
  203. package/assets/agents/review-refuter.md +0 -40
  204. package/assets/agents/review-validator.md +0 -23
  205. package/lib/git-commit-transaction.ts +0 -801
  206. package/lib/native-review-remediation.ts +0 -49
  207. package/lib/review-compact.ts +0 -947
  208. package/lib/review-refuter-adapter.ts +0 -129
  209. package/lib/review-runtime-contract.ts +0 -68
  210. package/prompts/gcl.md +0 -54
  211. package/prompts/gis.md +0 -25
  212. package/prompts/gpr.md +0 -41
  213. package/prompts/gwr.md +0 -31
  214. package/runtime/git-commit-transaction.mjs +0 -802
  215. package/scripts/run-git-commit-transaction.mjs +0 -35
  216. package/tests/fixtures/native-review-cli/v2.1.2/bind-sdd.json +0 -25
  217. package/tests/fixtures/native-review-cli/v2.1.2/finalize.json +0 -8
  218. package/tests/fixtures/native-review-cli/v2.1.2/sdd-status-engram.json +0 -139
  219. package/tests/fixtures/native-review-cli/v2.1.2/sdd-status.json +0 -200
  220. package/tests/fixtures/native-review-cli/v2.1.2/start.json +0 -12
  221. package/tests/fixtures/native-review-cli/v2.1.2/validate-allow.json +0 -24
  222. package/tests/fixtures/native-review-cli/v2.1.2/validate-deny-empty-context.json +0 -20
  223. package/tests/fixtures/native-review-cli/v2.1.2/validate-deny.json +0 -28
  224. package/tests/fixtures/native-review-cli/v2.1.3/sdd-status-engram.json +0 -139
  225. package/tests/fixtures/native-review-cli/v2.1.3/sdd-status.json +0 -200
  226. package/tests/git-commit-transaction.test.ts +0 -302
  227. package/tests/review-compact.test.ts +0 -243
  228. package/tests/review-refuter-adapter.test.ts +0 -89
@@ -17,7 +17,8 @@ import { applyModelConfig } from "../extensions/gentle-ai.ts";
17
17
  import { installSddAssets } from "../lib/sdd-preflight.ts";
18
18
 
19
19
  const PACKAGE_ROOT = dirname(dirname(fileURLToPath(import.meta.url)));
20
- const REVIEW_REFUTER_FILE = "review-refuter.md";
20
+ const MANAGED_EXEMPLAR_FILE = "gentle-ai-explore.md";
21
+ const RETIRED_REFUTER_FILE = "review-refuter.md";
21
22
  const REVIEW_RISK_FILE = "review-risk.md";
22
23
  const V013_REVIEW_RISK_FIXTURE = join(
23
24
  PACKAGE_ROOT,
@@ -49,17 +50,12 @@ const V014_MANAGED_ASSETS = join(
49
50
  "migrations",
50
51
  "managed-assets-v0.14.json",
51
52
  );
52
- const REVIEW_REFUTER_TOOLS = ["read", "grep", "find"];
53
- const FORBIDDEN_REFUTER_TOOLS = [
54
- "bash",
55
- "edit",
56
- "write",
57
- "task",
58
- "subagent",
59
- "subagent_run",
60
- "mem_save",
61
- "mem_update",
62
- ];
53
+ // gentle-pi#311 P5: the managed-asset installer mechanism tests use
54
+ // gentle-ai-explore.md as their exemplar (packaged, absent from the v0.13
55
+ // manifest) after review-refuter.md was retired together with every
56
+ // Pi-authored adversarial review verdict.
57
+ const MANAGED_EXEMPLAR_TOOLS = ["read", "grep", "find", "codegraph"];
58
+ const RETIRED_ADVERSARIAL_AGENTS = ["review-refuter.md", "review-validator.md"];
63
59
 
64
60
  interface ManagedAssetsManifest {
65
61
  schemaVersion: number;
@@ -118,10 +114,10 @@ test("package verification names the native review runtime boundary and packaged
118
114
  const manifest = readPackageJson();
119
115
 
120
116
  assert.ok(manifest.files?.includes("lib/"), "the published package must include the native review runtime module directory");
121
- assert.ok(manifest.files?.includes("runtime/"), "the published package must include the generated JavaScript transaction runtime");
117
+ assert.ok(manifest.files?.includes("runtime/"), "the published package must include generated JavaScript runtime modules");
122
118
  assert.match(verifier, /"lib\/native-review-cli\.ts"/, "package verification must require the native review adapter from the packaged runtime");
123
- assert.match(verifier, /"runtime\/git-commit-transaction\.mjs"/, "package verification must require the installed JavaScript transaction runtime");
124
- assert.match(verifier, /build-git-commit-transaction-runner\.mjs.*--check/s, "package verification must reject generated-runtime drift");
119
+ assert.match(verifier, /"runtime\/native-review-cli\.mjs"/, "package verification must require the generated native review adapter");
120
+ assert.match(verifier, /build-runtime-modules\.mjs.*--check/s, "package verification must reject generated-runtime drift");
125
121
  assert.match(verifier, /"tests\/fixtures\/native-review-cli\/v2\.1\.3\/start\.json"/, "package verification must retain the pinned native decoder fixture");
126
122
  assert.match(
127
123
  readFileSync(join(PACKAGE_ROOT, "extensions", "gentle-ai.ts"), "utf8"),
@@ -191,36 +187,31 @@ test("npm publication is bound to the exact package tag and triggering commit",
191
187
  assert.doesNotMatch(releaseSkill, /--ref "\$\{tag\}"|-f dist-tag=/);
192
188
  });
193
189
 
194
- test("publication gate is isolated from graph-v1 authority storage", () => {
190
+ test("Pi delivery relay is absent from the packaged extension", () => {
195
191
  const extension = readFileSync(join(PACKAGE_ROOT, "extensions", "gentle-ai.ts"), "utf8");
196
- const gate = readFileSync(join(PACKAGE_ROOT, "lib", "review-publication-gate.ts"), "utf8");
197
- const transaction = readFileSync(join(PACKAGE_ROOT, "lib", "review-transaction.ts"), "utf8");
198
192
 
199
- assert.match(extension, /from "\.\.\/lib\/review-publication-gate\.ts"/);
200
- assert.match(transaction, /from "\.\/review-publication-gate\.ts"/);
201
- assert.doesNotMatch(gate, /review-(?:transaction|object-store|graph-schema|lock|snapshot)/);
202
- assert.doesNotMatch(transaction, /export function evaluateReleaseFastPathV1|export function resolveConfiguredPushDestinationV1/);
193
+ assert.doesNotMatch(extension, /review-publication-gate/);
203
194
  });
204
195
 
205
- test("installed commit transaction runner loads JavaScript only and has deterministic build checks", () => {
196
+ test("generated runtime modules and packed-package checks are deterministic", () => {
206
197
  const packageJson = readPackageJson();
207
- const runner = readFileSync(join(PACKAGE_ROOT, "scripts", "run-git-commit-transaction.mjs"), "utf8");
198
+ const generator = readFileSync(join(PACKAGE_ROOT, "scripts", "build-runtime-modules.mjs"), "utf8");
208
199
  const packedRunner = readFileSync(join(PACKAGE_ROOT, "scripts", "test-packed-runner.mjs"), "utf8");
209
200
  const ci = readFileSync(join(PACKAGE_ROOT, ".github", "workflows", "ci.yml"), "utf8");
210
- assert.equal(packageJson.scripts?.["build:transaction-runner"], "node scripts/build-git-commit-transaction-runner.mjs --write");
211
- assert.equal(packageJson.scripts?.["check:transaction-runner"], "node scripts/build-git-commit-transaction-runner.mjs --check");
212
- assert.equal(packageJson.scripts?.["test:packed-runner"], "node scripts/test-packed-runner.mjs");
213
- assert.match(packageJson.scripts?.prepublishOnly ?? "", /pnpm run test:packed-runner/);
214
- assert.match(ci, /pnpm run test:packed-runner/);
201
+ assert.equal(packageJson.scripts?.["build:runtime-modules"], "node scripts/build-runtime-modules.mjs --write");
202
+ assert.equal(packageJson.scripts?.["check:runtime-modules"], "node scripts/build-runtime-modules.mjs --check");
203
+ assert.equal(packageJson.scripts?.["test:packed-package"], "node scripts/test-packed-runner.mjs");
204
+ assert.match(packageJson.scripts?.prepublishOnly ?? "", /pnpm run test:packed-package/);
205
+ assert.match(ci, /pnpm run check:runtime-modules/);
206
+ assert.match(ci, /pnpm run test:packed-package/);
207
+ assert.match(generator, /Generated by scripts\/build-runtime-modules\.mjs/);
215
208
  assert.match(packedRunner, /\["install"[^\]]*"--ignore-scripts=false"/s, "packed install must explicitly enable postinstall");
216
209
  assert.doesNotMatch(packedRunner, /\["install"[^\]]*"--ignore-scripts"(?!\=false)/s);
217
210
  assert.match(packedRunner, /execFileSync\("where\.exe", \["npm"\]/);
218
211
  assert.match(packedRunner, /could not resolve npm-cli\.js without a command shell/);
219
212
  assert.doesNotMatch(packedRunner, /ComSpec|cmd\.exe/);
220
213
  assert.match(packedRunner, /review", "capabilities", "--contract", "gentle-ai\.review-integration\/v2"/);
221
- assert.match(runner, /\.\.\/runtime\/git-commit-transaction\.mjs/);
222
- assert.doesNotMatch(runner, /\.ts["']/);
223
- assert.doesNotMatch(runner, /experimental-strip-types/);
214
+ assert.doesNotMatch(packedRunner, /git-commit-transaction|transaction runner/i);
224
215
  });
225
216
 
226
217
  test("package manifest ships and runs the checked-in package-local Gentle AI installer", () => {
@@ -270,20 +261,20 @@ test("package manifest installs pi-pretty through a wrapper without bundling nat
270
261
  );
271
262
  });
272
263
 
273
- test("package verification binds the published Gentle AI v2.2.2 runtime pin", () => {
264
+ test("package verification binds the published Gentle AI v2.5.0 runtime pin", () => {
274
265
  const installer = readFileSync(join(PACKAGE_ROOT, "scripts", "gentle-ai-installer.mjs"), "utf8");
275
266
  const binary = readFileSync(join(PACKAGE_ROOT, "lib", "gentle-ai-binary.ts"), "utf8");
276
267
  const verifier = readFileSync(join(PACKAGE_ROOT, "scripts", "verify-package-files.mjs"), "utf8");
277
268
 
278
- assert.match(installer, /INSTALLER_VERSION = "2\.2\.2"/);
269
+ assert.match(installer, /INSTALLER_VERSION = "2\.5\.0"/);
279
270
  assert.match(installer, /GENTLE_AI_WINDOWS_SOURCE_PACKAGE.*GENTLE_AI_WINDOWS_SOURCE_MODULE/);
280
- assert.match(installer, /GENTLE_AI_WINDOWS_SOURCE_MODULE_CHECKSUM = "h1:YZcI5dRvoHm82I2CULvgBkB2M3UQQGarYO\/u\/Nt5LSc="/);
271
+ assert.match(installer, /GENTLE_AI_WINDOWS_SOURCE_MODULE_CHECKSUM = "h1:0nvTLJFAf9ruBDwTvi\+aDrWt\/dt\/GKvUP2cFVB6c2DI="/);
281
272
  assert.match(installer, /GOTOOLCHAIN: "local"/);
282
273
  assert.match(installer, /GOSUMDB: "sum\.golang\.org"/);
283
- assert.match(binary, /GENTLE_AI_VERSION = "2\.2\.2"/);
274
+ assert.match(binary, /GENTLE_AI_VERSION = INSTALLER_VERSION/);
284
275
  assert.match(binary, /GO_SUMDB_SOURCE_BUILD/);
285
276
  assert.match(binary, /GENTLE_AI_WINDOWS_SOURCE_MODULE_CHECKSUM/);
286
- assert.match(verifier, /v2\.2\.2/);
277
+ assert.match(verifier, /v2\.5\.0/);
287
278
  });
288
279
 
289
280
 
@@ -439,25 +430,52 @@ test("packaged agents use YAML list syntax for tool allowlists", () => {
439
430
  }
440
431
  });
441
432
 
442
- test("package source defines review-refuter with the exact read-only boundary", () => {
443
- const refuterPath = join(PACKAGE_ROOT, "assets", "agents", REVIEW_REFUTER_FILE);
444
- assert.ok(existsSync(refuterPath), "gentle-pi must package review-refuter.md");
433
+ // The Pi child-session tool registry exposes `find` for filesystem discovery
434
+ // and has no `glob` or `webfetch` builtin (see tests/runtime-harness.mjs and
435
+ // the working builtin `reviewer` canary in issue #62). A packaged agent that
436
+ // declares a name the runtime cannot resolve does not fail loudly: the SDK
437
+ // silently drops it and the child starts with a reduced allowlist, so the
438
+ // agent reports itself blocked instead of naming the missing tool.
439
+ const UNSUPPORTED_CHILD_SESSION_TOOLS = ["glob", "webfetch"];
445
440
 
446
- const { name, tools } = readAgentDefinition(refuterPath);
447
- assert.equal(name, "review-refuter");
448
- assert.deepEqual(tools, REVIEW_REFUTER_TOOLS);
449
- for (const tool of FORBIDDEN_REFUTER_TOOLS) {
450
- assert.ok(!tools.includes(tool), `review-refuter must deny ${tool}`);
441
+ test("packaged agents declare only tool names a Pi child session can resolve", () => {
442
+ const agentsDir = join(PACKAGE_ROOT, "assets", "agents");
443
+ const agentFiles = readdirSync(agentsDir).flatMap((entry) =>
444
+ entry.endsWith(".md") ? [join(agentsDir, entry)] : [],
445
+ );
446
+
447
+ assert.ok(agentFiles.length > 0, "gentle-pi must ship packaged agents");
448
+
449
+ for (const file of agentFiles) {
450
+ const { tools } = readAgentDefinition(file);
451
+ for (const unsupported of UNSUPPORTED_CHILD_SESSION_TOOLS) {
452
+ assert.ok(
453
+ !tools.includes(unsupported),
454
+ `${file} declares ${unsupported}, which no Pi child session exposes; use find for discovery`,
455
+ );
456
+ }
451
457
  }
452
458
  });
453
459
 
454
- test("forced package installation preserves same-path user-authored agents and separate shadows", () => {
460
+ test("the retired Pi adversarial role agents are not packaged", () => {
461
+ // gentle-pi#311 P5: the refuter and targeted validator verdicts execute
462
+ // through Go-owned pi processes via provider-rendered self-contained
463
+ // vectors; the Pi-authored agent definitions must stay deleted.
464
+ for (const retired of RETIRED_ADVERSARIAL_AGENTS) {
465
+ assert.ok(!existsSync(join(PACKAGE_ROOT, "assets", "agents", retired)), `${retired} must stay deleted`);
466
+ }
467
+ });
468
+
469
+ test("forced package installation preserves same-path user-authored agents and separate shadows, including on retired asset paths", () => {
470
+ // The user-authored file below sits on the RETIRED review-refuter.md path:
471
+ // this also pins that gentle-pi#311 P5 asset retirement deletes only
472
+ // hash-proven package-managed copies, never user content.
455
473
  const temporaryAgentHome = mkdtempSync(join(tmpdir(), "gentle-pi-refuter-home-"));
456
474
  const temporaryProject = mkdtempSync(join(tmpdir(), "gentle-pi-refuter-project-"));
457
475
  const previousAgentHome = process.env.GENTLE_PI_AGENT_HOME;
458
- const samePathUserAgent = join(temporaryAgentHome, "agents", REVIEW_REFUTER_FILE);
459
- const userShadow = join(temporaryAgentHome, "subagents", REVIEW_REFUTER_FILE);
460
- const projectOverride = join(temporaryProject, ".pi", "agents", REVIEW_REFUTER_FILE);
476
+ const samePathUserAgent = join(temporaryAgentHome, "agents", RETIRED_REFUTER_FILE);
477
+ const userShadow = join(temporaryAgentHome, "subagents", RETIRED_REFUTER_FILE);
478
+ const projectOverride = join(temporaryProject, ".pi", "agents", RETIRED_REFUTER_FILE);
461
479
  const userAgentSource = [
462
480
  "---",
463
481
  "name: review-refuter",
@@ -538,7 +556,7 @@ test("first forced sync migrates untouched v0.13 assets, preserves routing, and
538
556
  const temporaryAgentHome = mkdtempSync(join(tmpdir(), "gentle-pi-v013-upgrade-"));
539
557
  const previousAgentHome = process.env.GENTLE_PI_AGENT_HOME;
540
558
  const installedReviewRisk = join(temporaryAgentHome, "agents", REVIEW_RISK_FILE);
541
- const installedRefuter = join(temporaryAgentHome, "agents", REVIEW_REFUTER_FILE);
559
+ const installedExemplar = join(temporaryAgentHome, "agents", MANAGED_EXEMPLAR_FILE);
542
560
  const managedAssetsManifest = join(
543
561
  temporaryAgentHome,
544
562
  "gentle-ai",
@@ -572,8 +590,8 @@ test("first forced sync migrates untouched v0.13 assets, preserves routing, and
572
590
  "migration must update the package body without losing user routing",
573
591
  );
574
592
  assert.equal(
575
- readFileSync(installedRefuter, "utf8"),
576
- readFileSync(join(PACKAGE_ROOT, "assets", "agents", REVIEW_REFUTER_FILE), "utf8"),
593
+ readFileSync(installedExemplar, "utf8"),
594
+ readFileSync(join(PACKAGE_ROOT, "assets", "agents", MANAGED_EXEMPLAR_FILE), "utf8"),
577
595
  "an asset missing from v0.13 must install normally",
578
596
  );
579
597
 
@@ -582,8 +600,8 @@ test("first forced sync migrates untouched v0.13 assets, preserves routing, and
582
600
  ) as ManagedAssetsManifest;
583
601
  assert.equal(manifest.assets[`agents/${REVIEW_RISK_FILE}`], sha256(migrated));
584
602
  assert.equal(
585
- manifest.assets[`agents/${REVIEW_REFUTER_FILE}`],
586
- sha256(readFileSync(installedRefuter, "utf8")),
603
+ manifest.assets[`agents/${MANAGED_EXEMPLAR_FILE}`],
604
+ sha256(readFileSync(installedExemplar, "utf8")),
587
605
  );
588
606
 
589
607
  const userEditedMigration = migrated.replace(
@@ -684,23 +702,23 @@ test("first forced sync preserves a body-edited v0.13 asset byte-for-byte", () =
684
702
  test("forced package installation refreshes an asset recorded as package-managed", () => {
685
703
  const temporaryAgentHome = mkdtempSync(join(tmpdir(), "gentle-pi-malformed-refuter-"));
686
704
  const previousAgentHome = process.env.GENTLE_PI_AGENT_HOME;
687
- const installedRefuter = join(temporaryAgentHome, "agents", REVIEW_REFUTER_FILE);
705
+ const installedExemplar = join(temporaryAgentHome, "agents", MANAGED_EXEMPLAR_FILE);
688
706
  const managedAssetsManifest = join(
689
707
  temporaryAgentHome,
690
708
  "gentle-ai",
691
709
  "managed-assets.json",
692
710
  );
693
711
  const previousPackageSource =
694
- "---\nname: review-refuter\ntools:\n - read\n - bash\n---\nprevious package version\n";
712
+ "---\nname: gentle-ai-explore\ntools:\n - read\n - bash\n---\nprevious package version\n";
695
713
  const routedPreviousPackageSource = previousPackageSource.replace(
696
- "name: review-refuter\n",
697
- "name: review-refuter\nmodel: openai/previous-package\nthinking: high\n",
714
+ "name: gentle-ai-explore\n",
715
+ "name: gentle-ai-explore\nmodel: openai/previous-package\nthinking: high\n",
698
716
  );
699
717
 
700
718
  try {
701
719
  process.env.GENTLE_PI_AGENT_HOME = temporaryAgentHome;
702
720
  installSddAssets(PACKAGE_ROOT, true);
703
- assert.ok(existsSync(installedRefuter), "a missing package asset must install");
721
+ assert.ok(existsSync(installedExemplar), "a missing package asset must install");
704
722
  assert.ok(
705
723
  existsSync(managedAssetsManifest),
706
724
  "the installer must record ownership independently from the filename",
@@ -709,16 +727,16 @@ test("forced package installation refreshes an asset recorded as package-managed
709
727
  const manifest = JSON.parse(
710
728
  readFileSync(managedAssetsManifest, "utf8"),
711
729
  ) as ManagedAssetsManifest;
712
- writeFileSync(installedRefuter, routedPreviousPackageSource);
713
- manifest.assets[`agents/${REVIEW_REFUTER_FILE}`] = sha256(
730
+ writeFileSync(installedExemplar, routedPreviousPackageSource);
731
+ manifest.assets[`agents/${MANAGED_EXEMPLAR_FILE}`] = sha256(
714
732
  routedPreviousPackageSource,
715
733
  );
716
734
  writeFileSync(managedAssetsManifest, JSON.stringify(manifest, null, 2));
717
735
 
718
736
  installSddAssets(PACKAGE_ROOT, true);
719
737
 
720
- const refreshed = readAgentDefinition(installedRefuter);
721
- assert.deepEqual(refreshed.tools, REVIEW_REFUTER_TOOLS);
738
+ const refreshed = readAgentDefinition(installedExemplar);
739
+ assert.deepEqual(refreshed.tools, MANAGED_EXEMPLAR_TOOLS);
722
740
  assert.doesNotMatch(refreshed.source, /^ - bash$/m);
723
741
  } finally {
724
742
  if (previousAgentHome === undefined) {
@@ -736,7 +754,7 @@ function assertManagedAgentUserEditIsPreserved(
736
754
  ): void {
737
755
  const temporaryAgentHome = mkdtempSync(join(tmpdir(), "gentle-pi-managed-edit-"));
738
756
  const previousAgentHome = process.env.GENTLE_PI_AGENT_HOME;
739
- const installedRefuter = join(temporaryAgentHome, "agents", REVIEW_REFUTER_FILE);
757
+ const installedExemplar = join(temporaryAgentHome, "agents", MANAGED_EXEMPLAR_FILE);
740
758
  const managedAssetsManifest = join(
741
759
  temporaryAgentHome,
742
760
  "gentle-ai",
@@ -746,15 +764,15 @@ function assertManagedAgentUserEditIsPreserved(
746
764
  try {
747
765
  process.env.GENTLE_PI_AGENT_HOME = temporaryAgentHome;
748
766
  installSddAssets(PACKAGE_ROOT, true);
749
- const installedSource = readFileSync(installedRefuter, "utf8");
767
+ const installedSource = readFileSync(installedExemplar, "utf8");
750
768
  const userEditedSource = editSource(installedSource);
751
769
  assert.notEqual(userEditedSource, installedSource, `${editLabel} must alter the asset`);
752
- writeFileSync(installedRefuter, userEditedSource);
770
+ writeFileSync(installedExemplar, userEditedSource);
753
771
 
754
772
  installSddAssets(PACKAGE_ROOT, true);
755
773
 
756
774
  assert.deepEqual(
757
- readFileSync(installedRefuter),
775
+ readFileSync(installedExemplar),
758
776
  Buffer.from(userEditedSource),
759
777
  `${editLabel} must invalidate ownership and survive force refresh byte-for-byte`,
760
778
  );
@@ -762,7 +780,7 @@ function assertManagedAgentUserEditIsPreserved(
762
780
  readFileSync(managedAssetsManifest, "utf8"),
763
781
  ) as ManagedAssetsManifest;
764
782
  assert.equal(
765
- manifest.assets[`agents/${REVIEW_REFUTER_FILE}`],
783
+ manifest.assets[`agents/${MANAGED_EXEMPLAR_FILE}`],
766
784
  undefined,
767
785
  `${editLabel} must remove package ownership`,
768
786
  );
@@ -779,8 +797,8 @@ function assertManagedAgentUserEditIsPreserved(
779
797
  test("forced package installation preserves a model-only edit to a managed agent", () => {
780
798
  assertManagedAgentUserEditIsPreserved("a model-only user edit", (source) =>
781
799
  source.replace(
782
- "name: review-refuter\n",
783
- "name: review-refuter\nmodel: private/user-model\n",
800
+ "name: gentle-ai-explore\n",
801
+ "name: gentle-ai-explore\nmodel: private/user-model\n",
784
802
  ),
785
803
  );
786
804
  });
@@ -788,8 +806,8 @@ test("forced package installation preserves a model-only edit to a managed agent
788
806
  test("forced package installation preserves a thinking-only edit to a managed agent", () => {
789
807
  assertManagedAgentUserEditIsPreserved("a thinking-only user edit", (source) =>
790
808
  source.replace(
791
- "name: review-refuter\n",
792
- "name: review-refuter\nthinking: xhigh\n",
809
+ "name: gentle-ai-explore\n",
810
+ "name: gentle-ai-explore\nthinking: xhigh\n",
793
811
  ),
794
812
  );
795
813
  });
@@ -797,8 +815,8 @@ test("forced package installation preserves a thinking-only edit to a managed ag
797
815
  test("forced package installation preserves an ordinary body edit to a managed agent", () => {
798
816
  assertManagedAgentUserEditIsPreserved("an ordinary body edit", (source) =>
799
817
  source.replace(
800
- "Challenge the supplied inferential claims",
801
- "Preserve this user-authored body change and challenge the supplied inferential claims",
818
+ "You are the read-only explorer for generic non-SDD work.",
819
+ "Preserve this user-authored body change. You are the read-only explorer for generic non-SDD work.",
802
820
  ),
803
821
  );
804
822
  });
@@ -806,7 +824,7 @@ test("forced package installation preserves an ordinary body edit to a managed a
806
824
  test("package model assignment keeps only package-managed agents owned", () => {
807
825
  const temporaryAgentHome = mkdtempSync(join(tmpdir(), "gentle-pi-model-ownership-"));
808
826
  const previousAgentHome = process.env.GENTLE_PI_AGENT_HOME;
809
- const installedRefuter = join(temporaryAgentHome, "agents", REVIEW_REFUTER_FILE);
827
+ const installedExemplar = join(temporaryAgentHome, "agents", MANAGED_EXEMPLAR_FILE);
810
828
  const userAgent = join(temporaryAgentHome, "agents", "user-router.md");
811
829
  const managedAssetsManifest = join(
812
830
  temporaryAgentHome,
@@ -821,14 +839,14 @@ test("package model assignment keeps only package-managed agents owned", () => {
821
839
  writeFileSync(userAgent, userAgentSource);
822
840
 
823
841
  applyModelConfig(PACKAGE_ROOT, {
824
- "review-refuter": { model: "package/selected-model", thinking: "high" },
842
+ "gentle-ai-explore": { model: "package/selected-model", thinking: "high" },
825
843
  "user-router": { model: "user/selected-model", thinking: "low" },
826
844
  });
827
845
 
828
- const routedRefuter = readFileSync(installedRefuter, "utf8");
846
+ const routedExemplar = readFileSync(installedExemplar, "utf8");
829
847
  const routedUserAgent = readFileSync(userAgent, "utf8");
830
- assert.match(routedRefuter, /^model: package\/selected-model$/m);
831
- assert.match(routedRefuter, /^thinking: high$/m);
848
+ assert.match(routedExemplar, /^model: package\/selected-model$/m);
849
+ assert.match(routedExemplar, /^thinking: high$/m);
832
850
  assert.match(routedUserAgent, /^model: user\/selected-model$/m);
833
851
  assert.match(routedUserAgent, /^thinking: low$/m);
834
852
 
@@ -836,8 +854,8 @@ test("package model assignment keeps only package-managed agents owned", () => {
836
854
  readFileSync(managedAssetsManifest, "utf8"),
837
855
  ) as ManagedAssetsManifest;
838
856
  assert.equal(
839
- manifest.assets[`agents/${REVIEW_REFUTER_FILE}`],
840
- sha256(routedRefuter),
857
+ manifest.assets[`agents/${MANAGED_EXEMPLAR_FILE}`],
858
+ sha256(routedExemplar),
841
859
  "package-controlled routing must update the managed asset hash coherently",
842
860
  );
843
861
  assert.equal(
@@ -848,8 +866,8 @@ test("package model assignment keeps only package-managed agents owned", () => {
848
866
 
849
867
  installSddAssets(PACKAGE_ROOT, true);
850
868
  assert.equal(
851
- readFileSync(installedRefuter, "utf8"),
852
- readFileSync(join(PACKAGE_ROOT, "assets", "agents", REVIEW_REFUTER_FILE), "utf8"),
869
+ readFileSync(installedExemplar, "utf8"),
870
+ readFileSync(join(PACKAGE_ROOT, "assets", "agents", MANAGED_EXEMPLAR_FILE), "utf8"),
853
871
  "a routed package-managed agent must remain eligible for package refresh",
854
872
  );
855
873
  assert.equal(
@@ -958,6 +976,10 @@ test("gentle-ai-worker packages the exact scoped writer contract", () => {
958
976
  const contextContract = readMarkdownSection(source, "Context contract");
959
977
  assert.match(contextContract, /pre-existing untracked targets explicitly listed by the parent/);
960
978
  assert.match(contextContract, /new files required by the delegated task/);
979
+ assert.match(contextContract, /derived candidate set the human can approve or narrow/);
980
+ assert.match(contextContract, /never an open request for the human to author paths or globs/);
981
+ assert.match(interactionContract, /closed set the human can approve, decline, or select from/);
982
+ assert.match(interactionContract, /never ask the human to author paths, globs, identifiers, or commands as free text/);
961
983
 
962
984
  const implementationRules = readMarkdownSection(source, "Implementation rules");
963
985
  assert.match(implementationRules, /`blocked` only for a non-human technical blocker/);
@@ -1106,7 +1128,7 @@ test("bounded implementation routing uses the same explicit fallback in both pol
1106
1128
  );
1107
1129
  });
1108
1130
 
1109
- test("orchestrator routes generic roles without reusing SDD or review agents", () => {
1131
+ test("orchestrator routes generic roles without static RDD lens routing", () => {
1110
1132
  for (const file of ["orchestrator.md", "orchestrator-delegation.md"]) {
1111
1133
  const routing = readFileSync(join(PACKAGE_ROOT, "assets", file), "utf8");
1112
1134
  assert.match(routing, /generic non-SDD exploration[\s\S]*`gentle-ai-explore`/);
@@ -1116,12 +1138,16 @@ test("orchestrator routes generic roles without reusing SDD or review agents", (
1116
1138
  );
1117
1139
  assert.match(routing, /generic non-SDD (?:technical )?verification[\s\S]*`gentle-ai-verify`/);
1118
1140
  assert.match(routing, /SDD roles stay inside SDD|Use `sdd-explore` and `sdd-verify` only inside SDD/);
1119
- assert.match(routing, /review lenses inside reviews|Use review lenses only inside explicit review transactions/);
1120
- assert.match(routing, /(?:truly local )?read-only check(?:ing)? of (?:known )?1-3 known files|1-3-file read-only check/);
1141
+ assert.match(routing, /(?:truly local )?read-only check(?:ing)? of (?:known )?1[-–]3 known files|1[-–]3-file read-only check/);
1121
1142
  assert.match(routing, /(?:verification that |verification commands →).*executes? or delegates?|executing\/delegating verification commands/);
1122
1143
  assert.match(routing, /missing(?: or |\/)unusable[\s\S]*native `Agent`[\s\S]*(?:the )?same read-only/);
1123
1144
  assert.match(routing, /report (?:the )?fallback/);
1145
+ assert.doesNotMatch(routing, /review lenses? (?:inside|only inside)|review lens routing/i);
1124
1146
  }
1147
+
1148
+ const core = readFileSync(join(PACKAGE_ROOT, "assets", "orchestrator.md"), "utf8");
1149
+ assert.match(core, /Gentle AI dynamically supplies runtime-specific RDD instructions/);
1150
+ assert.match(core, /this package does not invent or fall back/);
1125
1151
  });
1126
1152
 
1127
1153
  test("pi-pretty wrapper uses real package path resolution for pnpm symlink installs", () => {
@@ -1137,18 +1163,21 @@ test("pi-pretty wrapper uses real package path resolution for pnpm symlink insta
1137
1163
  assert.match(wrapper, /quietToolsEnabled/);
1138
1164
  });
1139
1165
 
1140
- test("v2.1.2 release package and runtime stop before publication", () => {
1166
+ test("v2.3.0 release package and runtime stop before publication", () => {
1141
1167
  const packageJson = readPackageJson();
1142
- assert.equal(packageJson.version, "2.1.2", "the release manifest must remain explicitly pinned to v2.1.2");
1168
+ assert.equal(packageJson.version, "2.3.0", "the release manifest must remain explicitly pinned to v2.3.0");
1143
1169
  assert.equal(
1144
1170
  packageJson.scripts?.test,
1145
- "node --experimental-strip-types --test tests/*.test.ts && pnpm run test:harness",
1171
+ "node --experimental-strip-types --test tests/*.test.ts && pnpm run check:provider-contract && pnpm run test:harness",
1146
1172
  );
1147
1173
  assert.ok(packageJson.files?.includes("assets/"));
1148
1174
  assert.ok(packageJson.files?.includes("contracts/"));
1149
1175
 
1150
1176
  const verifier = readFileSync(join(PACKAGE_ROOT, "scripts", "verify-package-files.mjs"), "utf8");
1151
- assert.match(verifier, /assets\/agents\/review-refuter\.md/);
1177
+ // gentle-pi#311 P5: the retired adversarial role agents must not be pinned
1178
+ // as required package files, while the append-only migration history stays.
1179
+ assert.doesNotMatch(verifier, /assets\/agents\/review-refuter\.md/);
1180
+ assert.doesNotMatch(verifier, /assets\/agents\/review-validator\.md/);
1152
1181
  assert.match(verifier, /assets\/migrations\/managed-assets-v0\.13\.json/);
1153
1182
  assert.match(verifier, /assets\/migrations\/managed-assets-v0\.14\.json/);
1154
1183
 
@@ -1157,26 +1186,25 @@ test("v2.1.2 release package and runtime stop before publication", () => {
1157
1186
  assert.doesNotMatch(runtime, /execFileSync\("(?:npm|pnpm)", \["publish"/);
1158
1187
  });
1159
1188
 
1160
- test("bounded review keeps the Judgment Day skill contract at metadata version 1.4", () => {
1189
+ test("bounded review keeps the Judgment Day skill contract at canon metadata version 1.7", () => {
1161
1190
  const frontmatter = readAgentFrontmatter(
1162
1191
  join(PACKAGE_ROOT, "skills", "judgment-day", "SKILL.md"),
1163
1192
  );
1164
1193
 
1165
- assert.match(frontmatter, /^ version: "1\.4"$/m);
1166
- assert.doesNotMatch(frontmatter, /^ version: "1\.5"$/m);
1194
+ assert.match(frontmatter, /^ version: "1\.7"$/m);
1195
+ assert.doesNotMatch(frontmatter, /^ version: "1\.4"$/m);
1167
1196
  });
1168
1197
 
1169
- test("README documents bounded review transactions and the honest installed permission boundary", () => {
1198
+ test("README documents dynamic Gentle AI RDD ownership and the installed permission boundary", () => {
1170
1199
  const readme = readFileSync(join(PACKAGE_ROOT, "README.md"), "utf8");
1171
1200
  for (const clause of [
1172
- "New ordinary review uses compact `gentle_review` `start -> finalize -> validate`.",
1173
- "Native compact gate validation is read-only.",
1174
- "Release from protected `main` may bypass receipt validation only when the tag targets the current immutable `origin/main` SHA, required CI for that exact SHA is successful, the remote head is rechecked before tag push, and no fresh risk evidence exists; otherwise release fails closed through native receipt validation.",
1201
+ "Gentle AI dynamically supplies runtime-specific RDD instructions",
1202
+ "does not define an RDD lifecycle",
1175
1203
  "Dangerous-command safety remains independent and authoritative.",
1176
- "`review-refuter` uses exactly `read`, `grep`, and `find`",
1177
1204
  "package-managed isolated installation",
1178
- "Project and user overrides may shadow the package asset",
1205
+ "Project and user overrides may shadow a package asset",
1179
1206
  ]) {
1180
- assert.ok(readme.includes(clause), `README missing review v2 clause: ${clause}`);
1207
+ assert.ok(readme.includes(clause), `README missing dynamic RDD clause: ${clause}`);
1181
1208
  }
1209
+ assert.doesNotMatch(readme, /New ordinary review uses compact `gentle_review` `start -> finalize -> validate`\./);
1182
1210
  });