gentle-pi 2.2.0 → 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.
- package/README.md +51 -80
- package/assets/agents/review-readability.md +0 -2
- package/assets/agents/review-reliability.md +0 -2
- package/assets/agents/review-resilience.md +0 -2
- package/assets/agents/review-risk.md +0 -2
- package/assets/agents/sdd-apply.md +5 -3
- package/assets/agents/sdd-proposal.md +2 -0
- package/assets/agents/sdd-research.md +54 -0
- package/assets/agents/sdd-status.md +4 -4
- package/assets/agents/sdd-tasks.md +2 -3
- package/assets/agents/sdd-verify.md +21 -1
- package/assets/chains/sdd-full.chain.md +1 -1
- package/assets/chains/sdd-verify.chain.md +1 -1
- package/assets/orchestrator-delegation.md +54 -248
- package/assets/orchestrator-memory.md +2 -0
- package/assets/orchestrator.md +22 -38
- package/assets/sdd-orchestrator-workflow.md +30 -37
- package/assets/support/sdd-status-contract.md +7 -7
- package/contracts/review-integration/v1/schemas/transition-execution.schema.json +42 -0
- package/contracts/review-integration/v2/schemas/last-event-closure.schema.json +66 -0
- package/contracts/review-integration/v2/schemas/opencode-provider-role.schema.json +14 -0
- package/docs/native-authority-architecture.md +9 -11
- package/docs/review-integration.md +27 -373
- package/extensions/ask-user-choice.ts +151 -0
- package/extensions/gentle-ai.ts +1778 -3673
- package/extensions/quiet-tools.ts +515 -32
- package/extensions/sdd-init.ts +4 -8
- package/lib/gentle-ai-renderer.ts +70 -0
- package/lib/model-routing-authority.ts +133 -0
- package/lib/native-review-cli.ts +372 -940
- package/lib/opaque-pi-reviewer-adapter.ts +284 -0
- package/lib/review-candidate-view.ts +341 -132
- package/lib/review-host-relay.ts +210 -68
- package/lib/review-integration-v2.ts +839 -307
- package/lib/review-last-event-controller.ts +35 -0
- package/lib/sdd-preflight.ts +177 -66
- package/lib/sdd-status.ts +66 -111
- package/lib/terminal-theme.ts +1 -1
- package/package.json +83 -82
- package/runtime/gentle-ai-binary.mjs +1 -1
- package/runtime/native-review-cli.mjs +322 -890
- package/runtime/review-integration-v2.mjs +789 -257
- package/runtime/review-relay-contract.mjs +1 -1
- package/scripts/{build-git-commit-transaction-runner.mjs → build-runtime-modules.mjs} +4 -5
- package/scripts/gentle-ai-installer.mjs +75 -22
- package/scripts/maintainer/provider-relay-matrix.mjs +195 -11
- package/scripts/test-packed-runner.mjs +4 -7
- package/scripts/verify-package-files.mjs +12 -13
- package/skills/_shared/review-ledger-contract.md +8 -14
- package/skills/chained-pr/SKILL.md +3 -0
- package/skills/cognitive-doc-design/SKILL.md +1 -1
- package/skills/comment-writer/SKILL.md +1 -1
- package/skills/gentle-ai/SKILL.md +7 -74
- package/skills/judgment-day/SKILL.md +5 -7
- package/skills/rdd-defect-workflow/SKILL.md +3 -3
- package/skills/release/SKILL.md +3 -3
- package/skills/skill-registry/SKILL.md +1 -1
- package/skills/work-unit-commits/SKILL.md +3 -1
- package/tests/artifact-language.test.ts +24 -11
- package/tests/ask-user-choice.test.ts +264 -0
- package/tests/codegraph-tools.test.ts +3 -3
- package/tests/crosslane/cross-lane.mjs +15 -1168
- package/tests/delegated-key-learnings-contract.test.ts +8 -6
- package/tests/devbinary/native-review-parity.devtest.ts +167 -250
- package/tests/devbinary/pi-host-relay.devtest.ts +867 -0
- package/tests/fixtures/devbinary/last-event-capture-correction-plan.captured.json +10 -0
- package/tests/fixtures/devbinary/last-event-capture-refuter-approved.captured.json +20 -0
- package/tests/fixtures/devbinary/last-event-capture-refuter-correction-required.captured.json +26 -0
- package/tests/fixtures/devbinary/last-event-capture-result-approved.captured.json +8 -0
- package/tests/fixtures/devbinary/last-event-capture-result-correction-required.captured.json +26 -0
- package/tests/fixtures/devbinary/last-event-capture-validation-approved.captured.json +8 -0
- package/tests/fixtures/devbinary/last-event-closure.provenance.md +13 -0
- package/tests/fixtures/devbinary/review-acknowledged-v1.captured.json +9 -0
- package/tests/fixtures/devbinary/review-acknowledged.provenance.md +31 -0
- package/tests/fixtures/devbinary/start-v3-zero-lens-closed.captured.json +21 -0
- package/tests/fixtures/native-review-cli/v2.5.0-rc.1/PROVENANCE.txt +15 -0
- package/tests/gentle-ai-binary.test.ts +83 -13
- package/tests/gentle-ai-dev-binary.test.ts +51 -228
- package/tests/gentle-ai-installer.test.ts +137 -47
- package/tests/gentle-ai.test.ts +820 -131
- package/tests/gentle-theme.test.ts +133 -0
- package/tests/maintainer/provider-relay.maintest.ts +340 -4
- package/tests/model-routing-authority.test.ts +257 -0
- package/tests/native-review-capability-contract.test.ts +28 -1
- package/tests/native-review-cli.test.ts +586 -962
- package/tests/native-review-consent.test.ts +150 -66
- package/tests/native-review-parity-runtime.test.ts +80 -359
- package/tests/native-review-parity.test.ts +674 -925
- package/tests/opaque-pi-reviewer-adapter.test.ts +266 -0
- package/tests/orchestrator-budget.test.ts +132 -88
- package/tests/orchestrator-rdd-ownership.test.ts +103 -0
- package/tests/package-manifest.test.ts +37 -35
- package/tests/provider-defect-handoff.test.ts +15 -118
- package/tests/quiet-tool-rendering.test.ts +1055 -28
- package/tests/review-authority-recovery-docs.test.ts +1 -2
- package/tests/review-candidate-view.test.ts +409 -3
- package/tests/review-compact-contract.test.ts +4 -30
- package/tests/review-controller-lock-status.test.ts +2 -2
- package/tests/review-controller-native-recovery.test.ts +363 -1450
- package/tests/review-controller-native-routing.test.ts +1251 -5642
- package/tests/review-controller-retired-ops.test.ts +1 -1
- package/tests/review-controller-workspace-root.test.ts +222 -71
- package/tests/review-controller.test.ts +26 -816
- package/tests/review-corrected-finalize-binding.test.ts +112 -153
- package/tests/review-dispatch-hydration-gap.test.ts +1 -53
- package/tests/review-gate.test.ts +0 -45
- package/tests/review-host-relay-restart-parity.test.ts +360 -0
- package/tests/review-host-relay-routing.test.ts +117 -82
- package/tests/review-host-relay.test.ts +242 -8
- package/tests/review-integration-v2-forward.test.ts +576 -553
- package/tests/review-integration-v2.test.ts +239 -165
- package/tests/review-last-event-closure.test.ts +408 -0
- package/tests/review-ledger-contract.test.ts +97 -35
- package/tests/review-recovered-lineage-routing.test.ts +0 -47
- package/tests/review-relay-transport-agent.test.ts +119 -46
- package/tests/review-snapshot.test.ts +3 -2
- package/tests/runtime-harness.mjs +361 -196
- package/tests/sdd-agent-tools.test.ts +36 -0
- package/tests/sdd-preflight.test.ts +81 -15
- package/tests/sdd-status.test.ts +109 -110
- package/tests/skill-collision-prefixes.test.ts +5 -8
- package/tests/writer-edit-surface-scope.test.ts +230 -0
- package/themes/Gentleman-Cute.json +94 -0
- package/themes/Gentleman-Sexy.json +92 -0
- package/lib/git-commit-transaction.ts +0 -861
- package/runtime/git-commit-transaction.mjs +0 -862
- package/scripts/run-git-commit-transaction.mjs +0 -35
- package/tests/fixtures/native-review-cli/v2.1.3/sdd-status-engram.json +0 -139
- package/tests/fixtures/native-review-cli/v2.1.3/sdd-status.json +0 -200
- package/tests/git-commit-transaction.test.ts +0 -530
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import test from "node:test";
|
|
5
|
+
|
|
6
|
+
const ROOT = join(import.meta.dirname, "..");
|
|
7
|
+
const ASSETS = join(ROOT, "assets");
|
|
8
|
+
const BOUNDARY =
|
|
9
|
+
"Gentle AI dynamically supplies runtime-specific RDD instructions via generated Pi APPEND_SYSTEM composition. Follow only those exact native instructions; if absent or unsupported, this package does not invent or fall back.";
|
|
10
|
+
|
|
11
|
+
function read(relativePath: string): string {
|
|
12
|
+
return readFileSync(join(ROOT, relativePath), "utf8");
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const core = read("assets/orchestrator.md");
|
|
16
|
+
const delegation = read("assets/orchestrator-delegation.md");
|
|
17
|
+
const staticPrompts = `${core}\n${delegation}`;
|
|
18
|
+
|
|
19
|
+
test("static prompts omit stale native RDD lifecycle mirrors", () => {
|
|
20
|
+
for (const marker of [
|
|
21
|
+
"Authority-First Terminal Procedure",
|
|
22
|
+
"reconcile-terminal-mirrors",
|
|
23
|
+
"Native Bounded Review Orchestration",
|
|
24
|
+
"Continue after a stop reason code",
|
|
25
|
+
"gentle-ai review status",
|
|
26
|
+
"next_transition",
|
|
27
|
+
"start -> finalize -> validate",
|
|
28
|
+
"review.capture-result",
|
|
29
|
+
"review.validate",
|
|
30
|
+
"reviewGate.result",
|
|
31
|
+
]) {
|
|
32
|
+
assert.ok(!staticPrompts.includes(marker), `stale RDD marker remains: ${marker}`);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test("lossless blocking prompts route every closed single-select envelope through the native closed tool", () => {
|
|
37
|
+
for (const clause of [
|
|
38
|
+
"For every strictly closed single-select envelope",
|
|
39
|
+
"ask_user_choice",
|
|
40
|
+
"envelope-owned canonical option token as opaque `value`",
|
|
41
|
+
"returns exactly one `value`",
|
|
42
|
+
"externally owned open/free-text questionnaire",
|
|
43
|
+
"never for a closed domain",
|
|
44
|
+
"exact captured provider-owned choice invocation",
|
|
45
|
+
]) {
|
|
46
|
+
assert.ok(delegation.includes(clause), `lossless prompt is missing: ${clause}`);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("static prompts declare one dynamic Gentle AI RDD ownership boundary", () => {
|
|
51
|
+
assert.equal(staticPrompts.split(BOUNDARY).length - 1, 1, "expected one dynamic RDD ownership boundary");
|
|
52
|
+
assert.ok(core.includes(BOUNDARY), "the Pi parent prompt owns the single boundary");
|
|
53
|
+
assert.ok(!delegation.includes(BOUNDARY), "generic delegation detail must not gain RDD text");
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test("rendered parent prompt keeps the RDD boundary while omitting lifecycle mirrors", async () => {
|
|
57
|
+
const { __testing } = await import("../extensions/gentle-ai.ts");
|
|
58
|
+
const rendered = __testing.getOrchestratorPrompt();
|
|
59
|
+
assert.ok(rendered.includes(BOUNDARY));
|
|
60
|
+
for (const marker of ["Authority-First Terminal Procedure", "reconcile-terminal-mirrors", "next_transition"]) {
|
|
61
|
+
assert.ok(!rendered.includes(marker), `rendered parent prompt leaked: ${marker}`);
|
|
62
|
+
}
|
|
63
|
+
assert.ok(Buffer.byteLength(rendered, "utf8") <= 8192, "the rendered parent prompt must stay below the reduced 8 KiB budget");
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test("static prompts retain normal SDD and delegated-work guidance", () => {
|
|
67
|
+
for (const heading of ["## SDD Workflow (lazy-loaded)", "## Memory Contract"]) {
|
|
68
|
+
assert.ok(core.includes(heading), `core lost ${heading}`);
|
|
69
|
+
}
|
|
70
|
+
for (const heading of [
|
|
71
|
+
"### Delegation Rules",
|
|
72
|
+
"#### Background Subagent Policy",
|
|
73
|
+
"#### Allowed edit surfaces (MANDATORY)",
|
|
74
|
+
"### 3. SDD (optional)",
|
|
75
|
+
]) {
|
|
76
|
+
assert.ok(delegation.includes(heading), `delegation lost ${heading}`);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test("always-on parent prompt requires a narrow writer edit surface before launch", () => {
|
|
81
|
+
assert.match(core, /Before launching (?:a )?bounded writer/i);
|
|
82
|
+
assert.match(core, /`gentle-ai-worker`/);
|
|
83
|
+
assert.match(core, /`worker`/);
|
|
84
|
+
assert.match(core, /## Allowed edit surfaces/);
|
|
85
|
+
assert.match(core, /repository-relative/i);
|
|
86
|
+
assert.match(core, /never `\.`|never a bare repository root/i);
|
|
87
|
+
assert.match(core, /do not ask the human to author paths or globs/i);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test("review integration documents the opaque Pi adapter and Go-owned authority boundary", () => {
|
|
91
|
+
const docs = read("docs/review-integration.md");
|
|
92
|
+
for (const marker of [
|
|
93
|
+
"Buffer → Buffer/error",
|
|
94
|
+
"exact Go-issued materialize/submission tokens",
|
|
95
|
+
"typed Pi transport refusal fails closed",
|
|
96
|
+
"Go owns worktree, lineage, candidate freeze, lens selection, correction, validator, approval burn, and review semantics",
|
|
97
|
+
"Delivery commands remain ordinary repository-policy operations.",
|
|
98
|
+
"package has no durable receipt or policy authority",
|
|
99
|
+
"static assets intentionally omit lifecycle instructions",
|
|
100
|
+
]) {
|
|
101
|
+
assert.ok(docs.includes(marker), `review integration doc is missing: ${marker}`);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
@@ -114,10 +114,10 @@ test("package verification names the native review runtime boundary and packaged
|
|
|
114
114
|
const manifest = readPackageJson();
|
|
115
115
|
|
|
116
116
|
assert.ok(manifest.files?.includes("lib/"), "the published package must include the native review runtime module directory");
|
|
117
|
-
assert.ok(manifest.files?.includes("runtime/"), "the published package must include
|
|
117
|
+
assert.ok(manifest.files?.includes("runtime/"), "the published package must include generated JavaScript runtime modules");
|
|
118
118
|
assert.match(verifier, /"lib\/native-review-cli\.ts"/, "package verification must require the native review adapter from the packaged runtime");
|
|
119
|
-
assert.match(verifier, /"runtime\/
|
|
120
|
-
assert.match(verifier, /build-
|
|
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");
|
|
121
121
|
assert.match(verifier, /"tests\/fixtures\/native-review-cli\/v2\.1\.3\/start\.json"/, "package verification must retain the pinned native decoder fixture");
|
|
122
122
|
assert.match(
|
|
123
123
|
readFileSync(join(PACKAGE_ROOT, "extensions", "gentle-ai.ts"), "utf8"),
|
|
@@ -187,36 +187,31 @@ test("npm publication is bound to the exact package tag and triggering commit",
|
|
|
187
187
|
assert.doesNotMatch(releaseSkill, /--ref "\$\{tag\}"|-f dist-tag=/);
|
|
188
188
|
});
|
|
189
189
|
|
|
190
|
-
test("
|
|
190
|
+
test("Pi delivery relay is absent from the packaged extension", () => {
|
|
191
191
|
const extension = readFileSync(join(PACKAGE_ROOT, "extensions", "gentle-ai.ts"), "utf8");
|
|
192
|
-
const gate = readFileSync(join(PACKAGE_ROOT, "lib", "review-publication-gate.ts"), "utf8");
|
|
193
|
-
const transaction = readFileSync(join(PACKAGE_ROOT, "lib", "review-transaction.ts"), "utf8");
|
|
194
192
|
|
|
195
|
-
assert.
|
|
196
|
-
assert.match(transaction, /from "\.\/review-publication-gate\.ts"/);
|
|
197
|
-
assert.doesNotMatch(gate, /review-(?:transaction|object-store|graph-schema|lock|snapshot)/);
|
|
198
|
-
assert.doesNotMatch(transaction, /export function evaluateReleaseFastPathV1|export function resolveConfiguredPushDestinationV1/);
|
|
193
|
+
assert.doesNotMatch(extension, /review-publication-gate/);
|
|
199
194
|
});
|
|
200
195
|
|
|
201
|
-
test("
|
|
196
|
+
test("generated runtime modules and packed-package checks are deterministic", () => {
|
|
202
197
|
const packageJson = readPackageJson();
|
|
203
|
-
const
|
|
198
|
+
const generator = readFileSync(join(PACKAGE_ROOT, "scripts", "build-runtime-modules.mjs"), "utf8");
|
|
204
199
|
const packedRunner = readFileSync(join(PACKAGE_ROOT, "scripts", "test-packed-runner.mjs"), "utf8");
|
|
205
200
|
const ci = readFileSync(join(PACKAGE_ROOT, ".github", "workflows", "ci.yml"), "utf8");
|
|
206
|
-
assert.equal(packageJson.scripts?.["build:
|
|
207
|
-
assert.equal(packageJson.scripts?.["check:
|
|
208
|
-
assert.equal(packageJson.scripts?.["test:packed-
|
|
209
|
-
assert.match(packageJson.scripts?.prepublishOnly ?? "", /pnpm run test:packed-
|
|
210
|
-
assert.match(ci, /pnpm run
|
|
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/);
|
|
211
208
|
assert.match(packedRunner, /\["install"[^\]]*"--ignore-scripts=false"/s, "packed install must explicitly enable postinstall");
|
|
212
209
|
assert.doesNotMatch(packedRunner, /\["install"[^\]]*"--ignore-scripts"(?!\=false)/s);
|
|
213
210
|
assert.match(packedRunner, /execFileSync\("where\.exe", \["npm"\]/);
|
|
214
211
|
assert.match(packedRunner, /could not resolve npm-cli\.js without a command shell/);
|
|
215
212
|
assert.doesNotMatch(packedRunner, /ComSpec|cmd\.exe/);
|
|
216
213
|
assert.match(packedRunner, /review", "capabilities", "--contract", "gentle-ai\.review-integration\/v2"/);
|
|
217
|
-
assert.
|
|
218
|
-
assert.doesNotMatch(runner, /\.ts["']/);
|
|
219
|
-
assert.doesNotMatch(runner, /experimental-strip-types/);
|
|
214
|
+
assert.doesNotMatch(packedRunner, /git-commit-transaction|transaction runner/i);
|
|
220
215
|
});
|
|
221
216
|
|
|
222
217
|
test("package manifest ships and runs the checked-in package-local Gentle AI installer", () => {
|
|
@@ -266,20 +261,20 @@ test("package manifest installs pi-pretty through a wrapper without bundling nat
|
|
|
266
261
|
);
|
|
267
262
|
});
|
|
268
263
|
|
|
269
|
-
test("package verification binds the published Gentle AI v2.
|
|
264
|
+
test("package verification binds the published Gentle AI v2.5.0 runtime pin", () => {
|
|
270
265
|
const installer = readFileSync(join(PACKAGE_ROOT, "scripts", "gentle-ai-installer.mjs"), "utf8");
|
|
271
266
|
const binary = readFileSync(join(PACKAGE_ROOT, "lib", "gentle-ai-binary.ts"), "utf8");
|
|
272
267
|
const verifier = readFileSync(join(PACKAGE_ROOT, "scripts", "verify-package-files.mjs"), "utf8");
|
|
273
268
|
|
|
274
|
-
assert.match(installer, /INSTALLER_VERSION = "2\.
|
|
269
|
+
assert.match(installer, /INSTALLER_VERSION = "2\.5\.0"/);
|
|
275
270
|
assert.match(installer, /GENTLE_AI_WINDOWS_SOURCE_PACKAGE.*GENTLE_AI_WINDOWS_SOURCE_MODULE/);
|
|
276
|
-
assert.match(installer, /GENTLE_AI_WINDOWS_SOURCE_MODULE_CHECKSUM = "h1:
|
|
271
|
+
assert.match(installer, /GENTLE_AI_WINDOWS_SOURCE_MODULE_CHECKSUM = "h1:0nvTLJFAf9ruBDwTvi\+aDrWt\/dt\/GKvUP2cFVB6c2DI="/);
|
|
277
272
|
assert.match(installer, /GOTOOLCHAIN: "local"/);
|
|
278
273
|
assert.match(installer, /GOSUMDB: "sum\.golang\.org"/);
|
|
279
274
|
assert.match(binary, /GENTLE_AI_VERSION = INSTALLER_VERSION/);
|
|
280
275
|
assert.match(binary, /GO_SUMDB_SOURCE_BUILD/);
|
|
281
276
|
assert.match(binary, /GENTLE_AI_WINDOWS_SOURCE_MODULE_CHECKSUM/);
|
|
282
|
-
assert.match(verifier, /v2\.
|
|
277
|
+
assert.match(verifier, /v2\.5\.0/);
|
|
283
278
|
});
|
|
284
279
|
|
|
285
280
|
|
|
@@ -981,6 +976,10 @@ test("gentle-ai-worker packages the exact scoped writer contract", () => {
|
|
|
981
976
|
const contextContract = readMarkdownSection(source, "Context contract");
|
|
982
977
|
assert.match(contextContract, /pre-existing untracked targets explicitly listed by the parent/);
|
|
983
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/);
|
|
984
983
|
|
|
985
984
|
const implementationRules = readMarkdownSection(source, "Implementation rules");
|
|
986
985
|
assert.match(implementationRules, /`blocked` only for a non-human technical blocker/);
|
|
@@ -1129,7 +1128,7 @@ test("bounded implementation routing uses the same explicit fallback in both pol
|
|
|
1129
1128
|
);
|
|
1130
1129
|
});
|
|
1131
1130
|
|
|
1132
|
-
test("orchestrator routes generic roles without
|
|
1131
|
+
test("orchestrator routes generic roles without static RDD lens routing", () => {
|
|
1133
1132
|
for (const file of ["orchestrator.md", "orchestrator-delegation.md"]) {
|
|
1134
1133
|
const routing = readFileSync(join(PACKAGE_ROOT, "assets", file), "utf8");
|
|
1135
1134
|
assert.match(routing, /generic non-SDD exploration[\s\S]*`gentle-ai-explore`/);
|
|
@@ -1139,12 +1138,16 @@ test("orchestrator routes generic roles without reusing SDD or review agents", (
|
|
|
1139
1138
|
);
|
|
1140
1139
|
assert.match(routing, /generic non-SDD (?:technical )?verification[\s\S]*`gentle-ai-verify`/);
|
|
1141
1140
|
assert.match(routing, /SDD roles stay inside SDD|Use `sdd-explore` and `sdd-verify` only inside SDD/);
|
|
1142
|
-
assert.match(routing, /
|
|
1143
|
-
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/);
|
|
1144
1142
|
assert.match(routing, /(?:verification that |verification commands →).*executes? or delegates?|executing\/delegating verification commands/);
|
|
1145
1143
|
assert.match(routing, /missing(?: or |\/)unusable[\s\S]*native `Agent`[\s\S]*(?:the )?same read-only/);
|
|
1146
1144
|
assert.match(routing, /report (?:the )?fallback/);
|
|
1145
|
+
assert.doesNotMatch(routing, /review lenses? (?:inside|only inside)|review lens routing/i);
|
|
1147
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/);
|
|
1148
1151
|
});
|
|
1149
1152
|
|
|
1150
1153
|
test("pi-pretty wrapper uses real package path resolution for pnpm symlink installs", () => {
|
|
@@ -1160,9 +1163,9 @@ test("pi-pretty wrapper uses real package path resolution for pnpm symlink insta
|
|
|
1160
1163
|
assert.match(wrapper, /quietToolsEnabled/);
|
|
1161
1164
|
});
|
|
1162
1165
|
|
|
1163
|
-
test("v2.
|
|
1166
|
+
test("v2.3.0 release package and runtime stop before publication", () => {
|
|
1164
1167
|
const packageJson = readPackageJson();
|
|
1165
|
-
assert.equal(packageJson.version, "2.
|
|
1168
|
+
assert.equal(packageJson.version, "2.3.0", "the release manifest must remain explicitly pinned to v2.3.0");
|
|
1166
1169
|
assert.equal(
|
|
1167
1170
|
packageJson.scripts?.test,
|
|
1168
1171
|
"node --experimental-strip-types --test tests/*.test.ts && pnpm run check:provider-contract && pnpm run test:harness",
|
|
@@ -1192,17 +1195,16 @@ test("bounded review keeps the Judgment Day skill contract at canon metadata ver
|
|
|
1192
1195
|
assert.doesNotMatch(frontmatter, /^ version: "1\.4"$/m);
|
|
1193
1196
|
});
|
|
1194
1197
|
|
|
1195
|
-
test("README documents
|
|
1198
|
+
test("README documents dynamic Gentle AI RDD ownership and the installed permission boundary", () => {
|
|
1196
1199
|
const readme = readFileSync(join(PACKAGE_ROOT, "README.md"), "utf8");
|
|
1197
1200
|
for (const clause of [
|
|
1198
|
-
"
|
|
1199
|
-
"
|
|
1200
|
-
"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",
|
|
1201
1203
|
"Dangerous-command safety remains independent and authoritative.",
|
|
1202
|
-
"Adversarial review roles (the refuter and the targeted validator) are never Pi-authored",
|
|
1203
1204
|
"package-managed isolated installation",
|
|
1204
1205
|
"Project and user overrides may shadow a package asset",
|
|
1205
1206
|
]) {
|
|
1206
|
-
assert.ok(readme.includes(clause), `README missing
|
|
1207
|
+
assert.ok(readme.includes(clause), `README missing dynamic RDD clause: ${clause}`);
|
|
1207
1208
|
}
|
|
1209
|
+
assert.doesNotMatch(readme, /New ordinary review uses compact `gentle_review` `start -> finalize -> validate`\./);
|
|
1208
1210
|
});
|
|
@@ -46,13 +46,6 @@ const DELEGATION_CHOICE1_ORDER = [
|
|
|
46
46
|
"execute the shared candidate-scoped continuation below",
|
|
47
47
|
] as const;
|
|
48
48
|
|
|
49
|
-
const SDD_CHOICE1_ORDER = [
|
|
50
|
-
"Complete a definitive lookup across open and closed issues",
|
|
51
|
-
"Derive the evidence channel only from the installed build string",
|
|
52
|
-
"If the installed build predates the relevant published fix",
|
|
53
|
-
"perform no further GitHub mutation and no blind retry",
|
|
54
|
-
] as const;
|
|
55
|
-
|
|
56
49
|
// ---------------------------------------------------------------------------
|
|
57
50
|
// 1 — assets/orchestrator-delegation.md structural presence
|
|
58
51
|
// ---------------------------------------------------------------------------
|
|
@@ -101,6 +94,12 @@ test("orchestrator-delegation.md states the admissibility-before-relay rule", ()
|
|
|
101
94
|
assert.match(DELEGATION, /The test is what produced the failure, not what the work was doing when it happened/i);
|
|
102
95
|
});
|
|
103
96
|
|
|
97
|
+
test("orchestrator-delegation.md excludes local consent lifecycle outcomes from provider-defect reporting", () => {
|
|
98
|
+
assert.match(DELEGATION, /`consent-binding-expired` and `consent-binding-already-consumed` are local lifecycle outcomes, not Gentle AI provider defects/i);
|
|
99
|
+
assert.match(DELEGATION, /An unknown consent binding is reportable only when independent evidence proves a fresh, same-session, unconsumed binding was lost/i);
|
|
100
|
+
assert.match(DELEGATION, /Never infer that evidence from the old combined stale-binding message/i);
|
|
101
|
+
});
|
|
102
|
+
|
|
104
103
|
test("orchestrator-delegation.md states the never-offer-to-repair rule", () => {
|
|
105
104
|
assert.match(
|
|
106
105
|
DELEGATION,
|
|
@@ -231,125 +230,23 @@ test("orchestrator-delegation.md does NOT reference the rc.3 canon", () => {
|
|
|
231
230
|
});
|
|
232
231
|
|
|
233
232
|
// ---------------------------------------------------------------------------
|
|
234
|
-
// 3 —
|
|
233
|
+
// 3 — SDD points to the single complete handoff contract
|
|
235
234
|
// ---------------------------------------------------------------------------
|
|
236
235
|
|
|
237
|
-
test("sdd-orchestrator-workflow.md
|
|
236
|
+
test("sdd-orchestrator-workflow.md points provider defects to the complete delegation contract", () => {
|
|
238
237
|
assert.match(SDD_WORKFLOW, /## Provider Defect Handoff/);
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
test("sdd-orchestrator-workflow.md references v2.4.0-rc.8 and the consent/v3 envelope", () => {
|
|
242
|
-
assert.match(SDD_WORKFLOW, /v2\.4\.0-rc\.8/);
|
|
243
|
-
assert.match(SDD_WORKFLOW, /gentle-ai\.review-integration\.consent\/v3/);
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
test("sdd-orchestrator-workflow.md lists all three semantic choice tokens in order", () => {
|
|
247
|
-
for (const token of CHOICE_TOKENS) {
|
|
248
|
-
assert.ok(
|
|
249
|
-
SDD_WORKFLOW.includes(`\`${token}\``),
|
|
250
|
-
`sdd-orchestrator-workflow.md missing semantic choice token: ${token}`,
|
|
251
|
-
);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
const positions = CHOICE_TOKENS.map((token) => SDD_WORKFLOW.indexOf(`\`${token}\``));
|
|
255
|
-
for (const pos of positions) {
|
|
256
|
-
assert.notEqual(pos, -1, "a choice token is missing; ordering assertion is meaningless");
|
|
257
|
-
}
|
|
258
|
-
assert.ok(
|
|
259
|
-
positions[0] < positions[1],
|
|
260
|
-
`report_and_continue must appear before continue_without_reporting in sdd-orchestrator-workflow.md; got positions ${positions}`,
|
|
261
|
-
);
|
|
262
|
-
assert.ok(
|
|
263
|
-
positions[1] < positions[2],
|
|
264
|
-
`continue_without_reporting must appear before stop_here in sdd-orchestrator-workflow.md; got positions ${positions}`,
|
|
265
|
-
);
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
test("sdd-orchestrator-workflow.md preserves the rc.8 choice-1 ordering on the concise surface", () => {
|
|
269
|
-
assertChoice1Order(SDD_WORKFLOW, SDD_CHOICE1_ORDER, "sdd-orchestrator-workflow.md");
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
test("sdd-orchestrator-workflow.md references the full contract in orchestrator-delegation.md", () => {
|
|
273
238
|
assert.match(
|
|
274
239
|
SDD_WORKFLOW,
|
|
275
240
|
/The full contract lives in `assets\/orchestrator-delegation\.md` under `#### Gentle AI Provider Defect Handoff \(MANDATORY\)`/i,
|
|
276
241
|
);
|
|
277
|
-
// The pointer must resolve: the named heading has to exist on the delegation surface.
|
|
278
242
|
assert.match(DELEGATION, /^#### Gentle AI Provider Defect Handoff \(MANDATORY\)$/m);
|
|
243
|
+
assert.doesNotMatch(SDD_WORKFLOW, /`report_and_continue`|`continue_without_reporting`|`stop_here`/);
|
|
279
244
|
});
|
|
280
245
|
|
|
281
|
-
test("
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
assert.
|
|
286
|
-
|
|
287
|
-
/Never offer to switch to, inspect, modify, or directly repair the Gentle AI repository/i,
|
|
288
|
-
);
|
|
289
|
-
// consent
|
|
290
|
-
assert.match(SDD_WORKFLOW, /Ask the user first, in the active conversation language, for explicit consent to report the apparent defect/i);
|
|
291
|
-
// privacy
|
|
292
|
-
assert.match(SDD_WORKFLOW, /Privacy scrub immediately before the first GitHub operation/i);
|
|
293
|
-
// definitive lookup
|
|
294
|
-
assert.match(SDD_WORKFLOW, /Complete a definitive lookup across open and closed issues in `Gentleman-Programming\/gentle-ai`/i);
|
|
295
|
-
// evidence channel
|
|
296
|
-
assert.match(SDD_WORKFLOW, /recognized prerelease tags are `-rc\.` and `-main\.`; every other build is stable/i);
|
|
297
|
-
assert.match(SDD_WORKFLOW, /never recommend switching channels/i);
|
|
298
|
-
// outdated + regression
|
|
299
|
-
assert.match(SDD_WORKFLOW, /If the installed build predates the relevant published fix, recommend installing it and reproducing/i);
|
|
300
|
-
assert.match(SDD_WORKFLOW, /treat it as a possible regression/i);
|
|
301
|
-
assert.match(SDD_WORKFLOW, /never reopen automatically/i);
|
|
302
|
-
// confirmed creation
|
|
303
|
-
assert.match(SDD_WORKFLOW, /Confirmed creation requires the GitHub create operation to confirm a newly-created issue identity\/URL/i);
|
|
304
|
-
// uncertainty continuation
|
|
305
|
-
assert.match(SDD_WORKFLOW, /perform no further GitHub mutation and no blind retry/i);
|
|
306
|
-
assert.match(SDD_WORKFLOW, /execute the exact captured provider-owned decline invocation exactly once, validate it, re-enter native negotiated STATUS, and resume the already-held consumer continuation/i);
|
|
307
|
-
// exact decline
|
|
308
|
-
assert.match(SDD_WORKFLOW, /Both continue choices execute that exact captured decline invocation exactly once/i);
|
|
309
|
-
assert.match(SDD_WORKFLOW, /never synthesize the decline command, target, token, or consumer continuation from prose/i);
|
|
310
|
-
// scope/mode
|
|
311
|
-
assert.match(SDD_WORKFLOW, /Do not invoke `gentle-ai review mode disable` at clone or global scope within this handoff/i);
|
|
312
|
-
assert.match(SDD_WORKFLOW, /Do not turn RDD off or on within this handoff/i);
|
|
313
|
-
// resume
|
|
314
|
-
assert.match(SDD_WORKFLOW, /Resume after an installed published fix or an explicit maintainer-authorized, documented native recovery or reset/i);
|
|
315
|
-
assert.match(SDD_WORKFLOW, /Never resume against unpublished code/i);
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
test("sdd-orchestrator-workflow.md does NOT carry the gentle-report label discipline", () => {
|
|
319
|
-
assert.equal(
|
|
320
|
-
SDD_WORKFLOW.includes("gentle-report"),
|
|
321
|
-
false,
|
|
322
|
-
"sdd-orchestrator-workflow.md must not reference the removed gentle-report label",
|
|
323
|
-
);
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
test("sdd-orchestrator-workflow.md does NOT make published fixes the sole resumption route", () => {
|
|
327
|
-
assert.equal(
|
|
328
|
-
SDD_WORKFLOW.includes("Resume only after an installed published fix"),
|
|
329
|
-
false,
|
|
330
|
-
"sdd-orchestrator-workflow.md must not state the prohibited sole-resumption route",
|
|
331
|
-
);
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
test("sdd-orchestrator-workflow.md does NOT retain the rc.3 hard-stop that withholds the decline invocation", () => {
|
|
335
|
-
assert.equal(
|
|
336
|
-
SDD_WORKFLOW.includes("Any report ambiguity or failure is a hard stop: preserve all consumer state and do not execute the decline invocation"),
|
|
337
|
-
false,
|
|
338
|
-
"sdd-orchestrator-workflow.md must not retain the rc.3 hard-stop wedge",
|
|
339
|
-
);
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
test("both handoff surfaces invoke `gentle-ai review mode disable` exactly once", () => {
|
|
343
|
-
// The delegation surface carries the contract inside the canon block, so its
|
|
344
|
-
// section is bounded by the following `####` canon heading, not by `## `.
|
|
345
|
-
const surfaces = [
|
|
346
|
-
["orchestrator-delegation.md", DELEGATION, /#### Gentle AI Provider Defect Handoff[\s\S]*?(?=\n#### SDD Edit-Authority|$)/],
|
|
347
|
-
["sdd-orchestrator-workflow.md", SDD_WORKFLOW, /## Provider Defect Handoff[\s\S]*?(?=\n## |$)/],
|
|
348
|
-
] as const;
|
|
349
|
-
for (const [name, asset, sectionPattern] of surfaces) {
|
|
350
|
-
const section = asset.match(sectionPattern)?.[0] ?? "";
|
|
351
|
-
assert.ok(section.length > 0, `${name}: provider defect handoff section not found`);
|
|
352
|
-
const n = countOccurrences(section, "gentle-ai review mode disable");
|
|
353
|
-
assert.equal(n, 1, `${name} must invoke "gentle-ai review mode disable" exactly once; got ${n}`);
|
|
354
|
-
}
|
|
246
|
+
test("the complete delegation handoff invokes `gentle-ai review mode disable` exactly once", () => {
|
|
247
|
+
const section = DELEGATION.match(
|
|
248
|
+
/#### Gentle AI Provider Defect Handoff[\s\S]*?(?=\n#### SDD Edit-Authority|$)/,
|
|
249
|
+
)?.[0] ?? "";
|
|
250
|
+
assert.ok(section.length > 0, "orchestrator-delegation.md: provider defect handoff section not found");
|
|
251
|
+
assert.equal(countOccurrences(section, "gentle-ai review mode disable"), 1);
|
|
355
252
|
});
|