gentle-pi 2.1.2 → 2.2.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 +70 -12
- package/assets/agents/gentle-ai-worker.md +7 -3
- package/assets/agents/jd-fix-agent.md +1 -1
- package/assets/agents/jd-judge-a.md +3 -1
- package/assets/agents/jd-judge-b.md +3 -1
- package/assets/agents/review-readability.md +4 -1
- package/assets/agents/review-reliability.md +4 -1
- package/assets/agents/review-resilience.md +4 -1
- package/assets/agents/review-risk.md +4 -1
- package/assets/agents/sdd-apply.md +6 -1
- package/assets/agents/sdd-archive.md +6 -1
- package/assets/agents/sdd-design.md +6 -1
- package/assets/agents/sdd-explore.md +6 -2
- package/assets/agents/sdd-init.md +10 -2
- package/assets/agents/sdd-onboard.md +6 -1
- package/assets/agents/sdd-proposal.md +6 -1
- package/assets/agents/sdd-spec.md +6 -1
- package/assets/agents/sdd-status.md +6 -1
- package/assets/agents/sdd-sync.md +6 -1
- package/assets/agents/sdd-tasks.md +6 -1
- package/assets/agents/sdd-verify.md +6 -1
- package/assets/chains/4r-review.chain.md +2 -0
- package/assets/chains/sdd-full.chain.md +1 -1
- package/assets/chains/sdd-plan.chain.md +1 -1
- package/assets/chains/sdd-verify.chain.md +1 -1
- package/assets/orchestrator-delegation.md +246 -67
- package/assets/orchestrator.md +7 -14
- package/assets/sdd-orchestrator-workflow.md +154 -9
- package/assets/support/sdd-status-contract.md +19 -1
- package/contracts/review-integration/v1/fixtures/consent.fixture.json +3 -3
- package/contracts/review-integration/v1/fixtures/start-v2.fixture.json +19 -28
- package/contracts/review-integration/v1/fixtures/start.fixture.json +1 -10
- package/contracts/review-integration/v1/fixtures/status-v2.fixture.json +12 -21
- package/contracts/review-integration/v1/schemas/correction-plan-request.schema.json +49 -0
- package/contracts/review-integration/v1/schemas/operation.schema.json +76 -0
- package/contracts/review-integration/v1/schemas/repair.schema.json +39 -0
- package/contracts/review-integration/v1/schemas/status-v2.schema.json +4 -2
- package/contracts/review-integration/v1/schemas/status.schema.json +4 -2
- package/contracts/review-integration/v2/fixtures/consent.fixture.json +1 -1
- package/contracts/review-integration/v2/fixtures/start.fixture.json +1 -10
- package/contracts/review-integration/v2/fixtures/status.fixture.json +1 -10
- package/contracts/review-integration/v2/schemas/failure.schema.json +5 -1
- package/contracts/review-integration/v2/schemas/operation.schema.json +6 -1
- package/contracts/review-integration/v2/schemas/repair.schema.json +4 -2
- package/contracts/review-integration/v2/schemas/start.schema.json +5 -2
- package/contracts/review-integration/v2/schemas/status.schema.json +4 -2
- package/contracts/review-provider-contract-mirror/provider-contract.lock.json +30 -0
- package/contracts/review-provider-contract-mirror/v1.1.0/bundle/README.md +12 -0
- package/contracts/review-provider-contract-mirror/v1.1.0/bundle/manifest.json +65 -0
- package/contracts/review-provider-contract-mirror/v1.1.0/bundle/schemas/lens.schema.json +16 -0
- package/contracts/review-provider-contract-mirror/v1.1.0/bundle/schemas/refuter.schema.json +1 -0
- package/contracts/review-provider-contract-mirror/v1.1.0/bundle/schemas/targeted-validator.schema.json +1 -0
- package/contracts/review-provider-contract-mirror/v1.1.0/bundle/vectors/lens.json +1 -0
- package/contracts/review-provider-contract-mirror/v1.1.0/bundle/vectors/refuter.json +1 -0
- package/contracts/review-provider-contract-mirror/v1.1.0/bundle/vectors/targeted-validator.json +1 -0
- package/contracts/review-provider-contract-mirror/v1.1.0/generated/provider-capabilities.baseline.json +15 -0
- package/contracts/review-provider-contract-mirror/v1.1.0/generated/provider-roles.baseline.json +42 -0
- package/docs/native-authority-architecture.md +5 -5
- package/docs/review-integration.md +22 -2
- package/extensions/gentle-ai.ts +1595 -201
- package/extensions/sdd-init.ts +19 -6
- package/extensions/skill-registry.ts +10 -2
- package/extensions/startup-banner.ts +10 -4
- package/lib/gentle-ai-binary.ts +173 -2
- package/lib/git-commit-transaction.ts +77 -17
- package/lib/native-review-cli.ts +528 -65
- package/lib/provider-contract-bundle.ts +704 -0
- package/lib/review-candidate-view.ts +527 -18
- package/lib/review-compact-contract.ts +59 -248
- package/lib/review-host-relay.ts +436 -0
- package/lib/review-integration-v2.ts +537 -36
- package/lib/review-relay-contract.ts +16 -0
- package/lib/sdd-preflight.ts +53 -1
- package/package.json +5 -2
- package/runtime/gentle-ai-binary.mjs +173 -2
- package/runtime/git-commit-transaction.mjs +75 -15
- package/runtime/native-review-cli.mjs +524 -61
- package/runtime/review-integration-v2.mjs +536 -35
- package/runtime/review-relay-contract.mjs +17 -0
- package/scripts/build-git-commit-transaction-runner.mjs +1 -0
- package/scripts/check-provider-contract.mjs +138 -0
- package/scripts/gentle-ai-installer.mjs +23 -13
- package/scripts/maintainer/provider-relay-matrix.mjs +219 -0
- package/scripts/mirror-provider-contract.mjs +143 -0
- package/scripts/test-packed-runner.mjs +16 -2
- package/scripts/verify-package-files.mjs +110 -33
- package/skills/_shared/review-ledger-contract.md +4 -6
- package/skills/gentle-ai/SKILL.md +4 -4
- package/skills/issue-creation/SKILL.md +94 -168
- package/skills/judgment-day/SKILL.md +7 -1
- package/skills/judgment-day/references/prompts-and-formats.md +2 -0
- package/skills/rdd-defect-workflow/SKILL.md +54 -0
- package/tests/background-subagents.test.ts +771 -0
- package/tests/crosslane/cross-lane.mjs +1169 -0
- package/tests/delegated-key-learnings-contract.test.ts +238 -0
- package/tests/fixtures/devbinary/capabilities-v2.1.derived.json +331 -0
- package/tests/fixtures/devbinary/capabilities-v2.2.captured.json +340 -0
- package/tests/fixtures/devbinary/consent-v3.captured.json +37 -0
- package/tests/fixtures/devbinary/failure-v2-capture-evidence.captured.json +16 -0
- package/tests/fixtures/devbinary/result-artifact-v2-path.captured.json +12 -0
- package/tests/fixtures/devbinary/result-artifact-v2.captured.json +12 -0
- package/tests/fixtures/devbinary/start-v3-consent-declined.captured.json +19 -0
- package/tests/fixtures/devbinary/start-v3-consent-granted.captured.json +109 -0
- package/tests/fixtures/devbinary/status-v5-capture-result-submission.captured.json +184 -0
- package/tests/fixtures/devbinary/status-v5-repository-context.captured.json +138 -0
- package/tests/fixtures/devbinary/status-v5.captured.json +88 -0
- package/tests/fixtures/provider-contract-bundle/v1.1.0/README.md +12 -0
- package/tests/fixtures/provider-contract-bundle/v1.1.0/manifest.json +65 -0
- package/tests/fixtures/provider-contract-bundle/v1.1.0/schemas/lens.schema.json +16 -0
- package/tests/fixtures/provider-contract-bundle/v1.1.0/schemas/refuter.schema.json +1 -0
- package/tests/fixtures/provider-contract-bundle/v1.1.0/schemas/targeted-validator.schema.json +1 -0
- package/tests/fixtures/provider-contract-bundle/v1.1.0/vectors/lens.json +1 -0
- package/tests/fixtures/provider-contract-bundle/v1.1.0/vectors/refuter.json +1 -0
- package/tests/fixtures/provider-contract-bundle/v1.1.0/vectors/targeted-validator.json +1 -0
- package/tests/gentle-ai-binary.test.ts +1 -1
- package/tests/gentle-ai-dev-binary-surfacing.test.ts +195 -0
- package/tests/gentle-ai-dev-binary.test.ts +336 -0
- package/tests/gentle-ai-installer.test.ts +46 -46
- package/tests/git-commit-transaction.test.ts +229 -1
- package/tests/maintainer/provider-relay.maintest.ts +265 -0
- package/tests/native-review-capability-contract.test.ts +48 -2
- package/tests/native-review-cli.test.ts +56 -0
- package/tests/native-review-consent.test.ts +164 -3
- package/tests/native-review-parity-runtime.test.ts +37 -0
- package/tests/native-review-parity.test.ts +218 -15
- package/tests/native-sdd-attempt-authority.test.ts +235 -0
- package/tests/orchestrator-budget.test.ts +30 -5
- package/tests/package-manifest.test.ts +98 -72
- package/tests/provider-contract-bundle.test.ts +385 -0
- package/tests/provider-contract-mirror.test.ts +206 -0
- package/tests/provider-defect-handoff.test.ts +355 -0
- package/tests/review-actor-tool-deny.test.ts +12 -13
- package/tests/review-candidate-view.test.ts +489 -9
- package/tests/review-compact-contract.test.ts +52 -119
- package/tests/review-controller-native-recovery.test.ts +643 -47
- package/tests/review-controller-native-routing.test.ts +1667 -222
- package/tests/review-controller-workspace-root.test.ts +17 -2
- package/tests/review-corrected-finalize-binding.test.ts +175 -0
- package/tests/review-dispatch-hydration-gap.test.ts +197 -0
- package/tests/review-host-relay-routing.test.ts +317 -0
- package/tests/review-host-relay.test.ts +520 -0
- package/tests/review-integration-v2-forward.test.ts +631 -0
- package/tests/review-integration-v2.test.ts +114 -0
- package/tests/review-ledger-contract.test.ts +12 -28
- package/tests/review-recovered-lineage-routing.test.ts +246 -0
- package/tests/review-relay-transport-agent.test.ts +249 -0
- package/tests/runtime-harness.mjs +242 -14
- package/tests/sdd-agent-tools.test.ts +18 -33
- package/tests/skill-collision-prefixes.test.ts +1 -0
- package/tests/skill-registry.test.ts +50 -1
- package/tests/verify-package-files.test.ts +62 -0
- package/assets/agents/review-refuter.md +0 -40
- package/assets/agents/review-validator.md +0 -23
- package/lib/native-review-remediation.ts +0 -49
- package/lib/review-compact.ts +0 -947
- package/lib/review-refuter-adapter.ts +0 -129
- package/lib/review-runtime-contract.ts +0 -68
- package/prompts/gcl.md +0 -54
- package/prompts/gis.md +0 -25
- package/prompts/gpr.md +0 -41
- package/prompts/gwr.md +0 -31
- package/tests/fixtures/native-review-cli/v2.1.2/bind-sdd.json +0 -25
- package/tests/fixtures/native-review-cli/v2.1.2/finalize.json +0 -8
- package/tests/fixtures/native-review-cli/v2.1.2/sdd-status-engram.json +0 -139
- package/tests/fixtures/native-review-cli/v2.1.2/sdd-status.json +0 -200
- package/tests/fixtures/native-review-cli/v2.1.2/start.json +0 -12
- package/tests/fixtures/native-review-cli/v2.1.2/validate-allow.json +0 -24
- package/tests/fixtures/native-review-cli/v2.1.2/validate-deny-empty-context.json +0 -20
- package/tests/fixtures/native-review-cli/v2.1.2/validate-deny.json +0 -28
- package/tests/review-compact.test.ts +0 -243
- package/tests/review-refuter-adapter.test.ts +0 -89
|
@@ -158,13 +158,29 @@ const DISPOSITION_MAP: DispositionRange[] = [
|
|
|
158
158
|
{ lines: [25, 29], target: "delegation", label: "Language Boundary LB5 (exceptions)" },
|
|
159
159
|
{ lines: [31, 40], target: "core", label: "Mental Model" },
|
|
160
160
|
{ lines: [42, 42], target: "core", label: "Work Routing Ladder heading" },
|
|
161
|
-
{ lines: [44,
|
|
161
|
+
{ lines: [44, 97], target: "delegation", label: "Work Routing Ladder body + Pi Subagent Model Routing" },
|
|
162
|
+
{
|
|
163
|
+
lines: [98, 107],
|
|
164
|
+
target: "obsolete",
|
|
165
|
+
label: "Size/risk-selected SDD tier replaced by explicit-request/accepted-proposal selection (#312)",
|
|
166
|
+
},
|
|
167
|
+
{ lines: [108, 108], target: "delegation", label: "SDD explicit-request trigger" },
|
|
168
|
+
{
|
|
169
|
+
lines: [109, 110],
|
|
170
|
+
target: "obsolete",
|
|
171
|
+
label: "Size-gated SDD entry replaced by explicit-selection gating (#312)",
|
|
172
|
+
},
|
|
162
173
|
{ lines: [112, 112], target: "core", label: "Delegation Rules heading" },
|
|
163
174
|
{ lines: [114, 114], target: "core", label: "Delegation Rules core question" },
|
|
164
175
|
{
|
|
165
|
-
lines: [116,
|
|
176
|
+
lines: [116, 126],
|
|
177
|
+
target: "obsolete",
|
|
178
|
+
label: "Pre-canon delegation table replaced by the mirrored gentle-ai canon table (#312)",
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
lines: [128, 132],
|
|
166
182
|
target: "delegation",
|
|
167
|
-
label: "
|
|
183
|
+
label: "Mandatory Triggers heading + Pi trigger preamble + 4-file binding",
|
|
168
184
|
},
|
|
169
185
|
{
|
|
170
186
|
lines: [133, 133],
|
|
@@ -172,9 +188,14 @@ const DISPOSITION_MAP: DispositionRange[] = [
|
|
|
172
188
|
label: "Superseded no-runtime inline exception",
|
|
173
189
|
},
|
|
174
190
|
{
|
|
175
|
-
lines: [134,
|
|
191
|
+
lines: [134, 167],
|
|
176
192
|
target: "delegation",
|
|
177
|
-
label: "Mandatory Triggers remainder + Cost/Context Balance + Canonical Workflows
|
|
193
|
+
label: "Mandatory Triggers remainder + Cost/Context Balance + Canonical Workflows",
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
lines: [169, 181],
|
|
197
|
+
target: "obsolete",
|
|
198
|
+
label: "Parent-selected review lens table replaced by native RAR lens ownership (#312)",
|
|
178
199
|
},
|
|
179
200
|
{ lines: [183, 191], target: "core", label: "SDD Workflow pointer" },
|
|
180
201
|
{ lines: [193, 193], target: "core", label: "Memory Contract heading" },
|
|
@@ -200,7 +221,11 @@ function isNormativeLine(line: string): boolean {
|
|
|
200
221
|
const fixtureLines = readFileSync(FIXTURE_PATH, "utf8").split("\n");
|
|
201
222
|
const SUPERSEDED_LIFECYCLE_REVIEW_LINES = new Set([
|
|
202
223
|
70,
|
|
224
|
+
// 74/77: the loose mode-choice background lines were replaced by the
|
|
225
|
+
// marked gentle-pi:background-subagents policy block (issue #256).
|
|
226
|
+
74,
|
|
203
227
|
76,
|
|
228
|
+
77,
|
|
204
229
|
92,
|
|
205
230
|
125,
|
|
206
231
|
126,
|
|
@@ -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
|
|
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
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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;
|
|
@@ -270,20 +266,20 @@ test("package manifest installs pi-pretty through a wrapper without bundling nat
|
|
|
270
266
|
);
|
|
271
267
|
});
|
|
272
268
|
|
|
273
|
-
test("package verification binds the published Gentle AI v2.
|
|
269
|
+
test("package verification binds the published Gentle AI v2.4.0 runtime pin", () => {
|
|
274
270
|
const installer = readFileSync(join(PACKAGE_ROOT, "scripts", "gentle-ai-installer.mjs"), "utf8");
|
|
275
271
|
const binary = readFileSync(join(PACKAGE_ROOT, "lib", "gentle-ai-binary.ts"), "utf8");
|
|
276
272
|
const verifier = readFileSync(join(PACKAGE_ROOT, "scripts", "verify-package-files.mjs"), "utf8");
|
|
277
273
|
|
|
278
|
-
assert.match(installer, /INSTALLER_VERSION = "2\.
|
|
274
|
+
assert.match(installer, /INSTALLER_VERSION = "2\.4\.0"/);
|
|
279
275
|
assert.match(installer, /GENTLE_AI_WINDOWS_SOURCE_PACKAGE.*GENTLE_AI_WINDOWS_SOURCE_MODULE/);
|
|
280
|
-
assert.match(installer, /GENTLE_AI_WINDOWS_SOURCE_MODULE_CHECKSUM = "h1:
|
|
276
|
+
assert.match(installer, /GENTLE_AI_WINDOWS_SOURCE_MODULE_CHECKSUM = "h1:XKkcy\+t76cyUKQnRwL1UnqHbhh8o416I8HQ1UsdvWSI="/);
|
|
281
277
|
assert.match(installer, /GOTOOLCHAIN: "local"/);
|
|
282
278
|
assert.match(installer, /GOSUMDB: "sum\.golang\.org"/);
|
|
283
|
-
assert.match(binary, /GENTLE_AI_VERSION =
|
|
279
|
+
assert.match(binary, /GENTLE_AI_VERSION = INSTALLER_VERSION/);
|
|
284
280
|
assert.match(binary, /GO_SUMDB_SOURCE_BUILD/);
|
|
285
281
|
assert.match(binary, /GENTLE_AI_WINDOWS_SOURCE_MODULE_CHECKSUM/);
|
|
286
|
-
assert.match(verifier, /v2\.
|
|
282
|
+
assert.match(verifier, /v2\.4\.0/);
|
|
287
283
|
});
|
|
288
284
|
|
|
289
285
|
|
|
@@ -439,25 +435,52 @@ test("packaged agents use YAML list syntax for tool allowlists", () => {
|
|
|
439
435
|
}
|
|
440
436
|
});
|
|
441
437
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
438
|
+
// The Pi child-session tool registry exposes `find` for filesystem discovery
|
|
439
|
+
// and has no `glob` or `webfetch` builtin (see tests/runtime-harness.mjs and
|
|
440
|
+
// the working builtin `reviewer` canary in issue #62). A packaged agent that
|
|
441
|
+
// declares a name the runtime cannot resolve does not fail loudly: the SDK
|
|
442
|
+
// silently drops it and the child starts with a reduced allowlist, so the
|
|
443
|
+
// agent reports itself blocked instead of naming the missing tool.
|
|
444
|
+
const UNSUPPORTED_CHILD_SESSION_TOOLS = ["glob", "webfetch"];
|
|
445
445
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
446
|
+
test("packaged agents declare only tool names a Pi child session can resolve", () => {
|
|
447
|
+
const agentsDir = join(PACKAGE_ROOT, "assets", "agents");
|
|
448
|
+
const agentFiles = readdirSync(agentsDir).flatMap((entry) =>
|
|
449
|
+
entry.endsWith(".md") ? [join(agentsDir, entry)] : [],
|
|
450
|
+
);
|
|
451
|
+
|
|
452
|
+
assert.ok(agentFiles.length > 0, "gentle-pi must ship packaged agents");
|
|
453
|
+
|
|
454
|
+
for (const file of agentFiles) {
|
|
455
|
+
const { tools } = readAgentDefinition(file);
|
|
456
|
+
for (const unsupported of UNSUPPORTED_CHILD_SESSION_TOOLS) {
|
|
457
|
+
assert.ok(
|
|
458
|
+
!tools.includes(unsupported),
|
|
459
|
+
`${file} declares ${unsupported}, which no Pi child session exposes; use find for discovery`,
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
test("the retired Pi adversarial role agents are not packaged", () => {
|
|
466
|
+
// gentle-pi#311 P5: the refuter and targeted validator verdicts execute
|
|
467
|
+
// through Go-owned pi processes via provider-rendered self-contained
|
|
468
|
+
// vectors; the Pi-authored agent definitions must stay deleted.
|
|
469
|
+
for (const retired of RETIRED_ADVERSARIAL_AGENTS) {
|
|
470
|
+
assert.ok(!existsSync(join(PACKAGE_ROOT, "assets", "agents", retired)), `${retired} must stay deleted`);
|
|
451
471
|
}
|
|
452
472
|
});
|
|
453
473
|
|
|
454
|
-
test("forced package installation preserves same-path user-authored agents and separate shadows", () => {
|
|
474
|
+
test("forced package installation preserves same-path user-authored agents and separate shadows, including on retired asset paths", () => {
|
|
475
|
+
// The user-authored file below sits on the RETIRED review-refuter.md path:
|
|
476
|
+
// this also pins that gentle-pi#311 P5 asset retirement deletes only
|
|
477
|
+
// hash-proven package-managed copies, never user content.
|
|
455
478
|
const temporaryAgentHome = mkdtempSync(join(tmpdir(), "gentle-pi-refuter-home-"));
|
|
456
479
|
const temporaryProject = mkdtempSync(join(tmpdir(), "gentle-pi-refuter-project-"));
|
|
457
480
|
const previousAgentHome = process.env.GENTLE_PI_AGENT_HOME;
|
|
458
|
-
const samePathUserAgent = join(temporaryAgentHome, "agents",
|
|
459
|
-
const userShadow = join(temporaryAgentHome, "subagents",
|
|
460
|
-
const projectOverride = join(temporaryProject, ".pi", "agents",
|
|
481
|
+
const samePathUserAgent = join(temporaryAgentHome, "agents", RETIRED_REFUTER_FILE);
|
|
482
|
+
const userShadow = join(temporaryAgentHome, "subagents", RETIRED_REFUTER_FILE);
|
|
483
|
+
const projectOverride = join(temporaryProject, ".pi", "agents", RETIRED_REFUTER_FILE);
|
|
461
484
|
const userAgentSource = [
|
|
462
485
|
"---",
|
|
463
486
|
"name: review-refuter",
|
|
@@ -538,7 +561,7 @@ test("first forced sync migrates untouched v0.13 assets, preserves routing, and
|
|
|
538
561
|
const temporaryAgentHome = mkdtempSync(join(tmpdir(), "gentle-pi-v013-upgrade-"));
|
|
539
562
|
const previousAgentHome = process.env.GENTLE_PI_AGENT_HOME;
|
|
540
563
|
const installedReviewRisk = join(temporaryAgentHome, "agents", REVIEW_RISK_FILE);
|
|
541
|
-
const
|
|
564
|
+
const installedExemplar = join(temporaryAgentHome, "agents", MANAGED_EXEMPLAR_FILE);
|
|
542
565
|
const managedAssetsManifest = join(
|
|
543
566
|
temporaryAgentHome,
|
|
544
567
|
"gentle-ai",
|
|
@@ -572,8 +595,8 @@ test("first forced sync migrates untouched v0.13 assets, preserves routing, and
|
|
|
572
595
|
"migration must update the package body without losing user routing",
|
|
573
596
|
);
|
|
574
597
|
assert.equal(
|
|
575
|
-
readFileSync(
|
|
576
|
-
readFileSync(join(PACKAGE_ROOT, "assets", "agents",
|
|
598
|
+
readFileSync(installedExemplar, "utf8"),
|
|
599
|
+
readFileSync(join(PACKAGE_ROOT, "assets", "agents", MANAGED_EXEMPLAR_FILE), "utf8"),
|
|
577
600
|
"an asset missing from v0.13 must install normally",
|
|
578
601
|
);
|
|
579
602
|
|
|
@@ -582,8 +605,8 @@ test("first forced sync migrates untouched v0.13 assets, preserves routing, and
|
|
|
582
605
|
) as ManagedAssetsManifest;
|
|
583
606
|
assert.equal(manifest.assets[`agents/${REVIEW_RISK_FILE}`], sha256(migrated));
|
|
584
607
|
assert.equal(
|
|
585
|
-
manifest.assets[`agents/${
|
|
586
|
-
sha256(readFileSync(
|
|
608
|
+
manifest.assets[`agents/${MANAGED_EXEMPLAR_FILE}`],
|
|
609
|
+
sha256(readFileSync(installedExemplar, "utf8")),
|
|
587
610
|
);
|
|
588
611
|
|
|
589
612
|
const userEditedMigration = migrated.replace(
|
|
@@ -684,23 +707,23 @@ test("first forced sync preserves a body-edited v0.13 asset byte-for-byte", () =
|
|
|
684
707
|
test("forced package installation refreshes an asset recorded as package-managed", () => {
|
|
685
708
|
const temporaryAgentHome = mkdtempSync(join(tmpdir(), "gentle-pi-malformed-refuter-"));
|
|
686
709
|
const previousAgentHome = process.env.GENTLE_PI_AGENT_HOME;
|
|
687
|
-
const
|
|
710
|
+
const installedExemplar = join(temporaryAgentHome, "agents", MANAGED_EXEMPLAR_FILE);
|
|
688
711
|
const managedAssetsManifest = join(
|
|
689
712
|
temporaryAgentHome,
|
|
690
713
|
"gentle-ai",
|
|
691
714
|
"managed-assets.json",
|
|
692
715
|
);
|
|
693
716
|
const previousPackageSource =
|
|
694
|
-
"---\nname:
|
|
717
|
+
"---\nname: gentle-ai-explore\ntools:\n - read\n - bash\n---\nprevious package version\n";
|
|
695
718
|
const routedPreviousPackageSource = previousPackageSource.replace(
|
|
696
|
-
"name:
|
|
697
|
-
"name:
|
|
719
|
+
"name: gentle-ai-explore\n",
|
|
720
|
+
"name: gentle-ai-explore\nmodel: openai/previous-package\nthinking: high\n",
|
|
698
721
|
);
|
|
699
722
|
|
|
700
723
|
try {
|
|
701
724
|
process.env.GENTLE_PI_AGENT_HOME = temporaryAgentHome;
|
|
702
725
|
installSddAssets(PACKAGE_ROOT, true);
|
|
703
|
-
assert.ok(existsSync(
|
|
726
|
+
assert.ok(existsSync(installedExemplar), "a missing package asset must install");
|
|
704
727
|
assert.ok(
|
|
705
728
|
existsSync(managedAssetsManifest),
|
|
706
729
|
"the installer must record ownership independently from the filename",
|
|
@@ -709,16 +732,16 @@ test("forced package installation refreshes an asset recorded as package-managed
|
|
|
709
732
|
const manifest = JSON.parse(
|
|
710
733
|
readFileSync(managedAssetsManifest, "utf8"),
|
|
711
734
|
) as ManagedAssetsManifest;
|
|
712
|
-
writeFileSync(
|
|
713
|
-
manifest.assets[`agents/${
|
|
735
|
+
writeFileSync(installedExemplar, routedPreviousPackageSource);
|
|
736
|
+
manifest.assets[`agents/${MANAGED_EXEMPLAR_FILE}`] = sha256(
|
|
714
737
|
routedPreviousPackageSource,
|
|
715
738
|
);
|
|
716
739
|
writeFileSync(managedAssetsManifest, JSON.stringify(manifest, null, 2));
|
|
717
740
|
|
|
718
741
|
installSddAssets(PACKAGE_ROOT, true);
|
|
719
742
|
|
|
720
|
-
const refreshed = readAgentDefinition(
|
|
721
|
-
assert.deepEqual(refreshed.tools,
|
|
743
|
+
const refreshed = readAgentDefinition(installedExemplar);
|
|
744
|
+
assert.deepEqual(refreshed.tools, MANAGED_EXEMPLAR_TOOLS);
|
|
722
745
|
assert.doesNotMatch(refreshed.source, /^ - bash$/m);
|
|
723
746
|
} finally {
|
|
724
747
|
if (previousAgentHome === undefined) {
|
|
@@ -736,7 +759,7 @@ function assertManagedAgentUserEditIsPreserved(
|
|
|
736
759
|
): void {
|
|
737
760
|
const temporaryAgentHome = mkdtempSync(join(tmpdir(), "gentle-pi-managed-edit-"));
|
|
738
761
|
const previousAgentHome = process.env.GENTLE_PI_AGENT_HOME;
|
|
739
|
-
const
|
|
762
|
+
const installedExemplar = join(temporaryAgentHome, "agents", MANAGED_EXEMPLAR_FILE);
|
|
740
763
|
const managedAssetsManifest = join(
|
|
741
764
|
temporaryAgentHome,
|
|
742
765
|
"gentle-ai",
|
|
@@ -746,15 +769,15 @@ function assertManagedAgentUserEditIsPreserved(
|
|
|
746
769
|
try {
|
|
747
770
|
process.env.GENTLE_PI_AGENT_HOME = temporaryAgentHome;
|
|
748
771
|
installSddAssets(PACKAGE_ROOT, true);
|
|
749
|
-
const installedSource = readFileSync(
|
|
772
|
+
const installedSource = readFileSync(installedExemplar, "utf8");
|
|
750
773
|
const userEditedSource = editSource(installedSource);
|
|
751
774
|
assert.notEqual(userEditedSource, installedSource, `${editLabel} must alter the asset`);
|
|
752
|
-
writeFileSync(
|
|
775
|
+
writeFileSync(installedExemplar, userEditedSource);
|
|
753
776
|
|
|
754
777
|
installSddAssets(PACKAGE_ROOT, true);
|
|
755
778
|
|
|
756
779
|
assert.deepEqual(
|
|
757
|
-
readFileSync(
|
|
780
|
+
readFileSync(installedExemplar),
|
|
758
781
|
Buffer.from(userEditedSource),
|
|
759
782
|
`${editLabel} must invalidate ownership and survive force refresh byte-for-byte`,
|
|
760
783
|
);
|
|
@@ -762,7 +785,7 @@ function assertManagedAgentUserEditIsPreserved(
|
|
|
762
785
|
readFileSync(managedAssetsManifest, "utf8"),
|
|
763
786
|
) as ManagedAssetsManifest;
|
|
764
787
|
assert.equal(
|
|
765
|
-
manifest.assets[`agents/${
|
|
788
|
+
manifest.assets[`agents/${MANAGED_EXEMPLAR_FILE}`],
|
|
766
789
|
undefined,
|
|
767
790
|
`${editLabel} must remove package ownership`,
|
|
768
791
|
);
|
|
@@ -779,8 +802,8 @@ function assertManagedAgentUserEditIsPreserved(
|
|
|
779
802
|
test("forced package installation preserves a model-only edit to a managed agent", () => {
|
|
780
803
|
assertManagedAgentUserEditIsPreserved("a model-only user edit", (source) =>
|
|
781
804
|
source.replace(
|
|
782
|
-
"name:
|
|
783
|
-
"name:
|
|
805
|
+
"name: gentle-ai-explore\n",
|
|
806
|
+
"name: gentle-ai-explore\nmodel: private/user-model\n",
|
|
784
807
|
),
|
|
785
808
|
);
|
|
786
809
|
});
|
|
@@ -788,8 +811,8 @@ test("forced package installation preserves a model-only edit to a managed agent
|
|
|
788
811
|
test("forced package installation preserves a thinking-only edit to a managed agent", () => {
|
|
789
812
|
assertManagedAgentUserEditIsPreserved("a thinking-only user edit", (source) =>
|
|
790
813
|
source.replace(
|
|
791
|
-
"name:
|
|
792
|
-
"name:
|
|
814
|
+
"name: gentle-ai-explore\n",
|
|
815
|
+
"name: gentle-ai-explore\nthinking: xhigh\n",
|
|
793
816
|
),
|
|
794
817
|
);
|
|
795
818
|
});
|
|
@@ -797,8 +820,8 @@ test("forced package installation preserves a thinking-only edit to a managed ag
|
|
|
797
820
|
test("forced package installation preserves an ordinary body edit to a managed agent", () => {
|
|
798
821
|
assertManagedAgentUserEditIsPreserved("an ordinary body edit", (source) =>
|
|
799
822
|
source.replace(
|
|
800
|
-
"
|
|
801
|
-
"Preserve this user-authored body change
|
|
823
|
+
"You are the read-only explorer for generic non-SDD work.",
|
|
824
|
+
"Preserve this user-authored body change. You are the read-only explorer for generic non-SDD work.",
|
|
802
825
|
),
|
|
803
826
|
);
|
|
804
827
|
});
|
|
@@ -806,7 +829,7 @@ test("forced package installation preserves an ordinary body edit to a managed a
|
|
|
806
829
|
test("package model assignment keeps only package-managed agents owned", () => {
|
|
807
830
|
const temporaryAgentHome = mkdtempSync(join(tmpdir(), "gentle-pi-model-ownership-"));
|
|
808
831
|
const previousAgentHome = process.env.GENTLE_PI_AGENT_HOME;
|
|
809
|
-
const
|
|
832
|
+
const installedExemplar = join(temporaryAgentHome, "agents", MANAGED_EXEMPLAR_FILE);
|
|
810
833
|
const userAgent = join(temporaryAgentHome, "agents", "user-router.md");
|
|
811
834
|
const managedAssetsManifest = join(
|
|
812
835
|
temporaryAgentHome,
|
|
@@ -821,14 +844,14 @@ test("package model assignment keeps only package-managed agents owned", () => {
|
|
|
821
844
|
writeFileSync(userAgent, userAgentSource);
|
|
822
845
|
|
|
823
846
|
applyModelConfig(PACKAGE_ROOT, {
|
|
824
|
-
"
|
|
847
|
+
"gentle-ai-explore": { model: "package/selected-model", thinking: "high" },
|
|
825
848
|
"user-router": { model: "user/selected-model", thinking: "low" },
|
|
826
849
|
});
|
|
827
850
|
|
|
828
|
-
const
|
|
851
|
+
const routedExemplar = readFileSync(installedExemplar, "utf8");
|
|
829
852
|
const routedUserAgent = readFileSync(userAgent, "utf8");
|
|
830
|
-
assert.match(
|
|
831
|
-
assert.match(
|
|
853
|
+
assert.match(routedExemplar, /^model: package\/selected-model$/m);
|
|
854
|
+
assert.match(routedExemplar, /^thinking: high$/m);
|
|
832
855
|
assert.match(routedUserAgent, /^model: user\/selected-model$/m);
|
|
833
856
|
assert.match(routedUserAgent, /^thinking: low$/m);
|
|
834
857
|
|
|
@@ -836,8 +859,8 @@ test("package model assignment keeps only package-managed agents owned", () => {
|
|
|
836
859
|
readFileSync(managedAssetsManifest, "utf8"),
|
|
837
860
|
) as ManagedAssetsManifest;
|
|
838
861
|
assert.equal(
|
|
839
|
-
manifest.assets[`agents/${
|
|
840
|
-
sha256(
|
|
862
|
+
manifest.assets[`agents/${MANAGED_EXEMPLAR_FILE}`],
|
|
863
|
+
sha256(routedExemplar),
|
|
841
864
|
"package-controlled routing must update the managed asset hash coherently",
|
|
842
865
|
);
|
|
843
866
|
assert.equal(
|
|
@@ -848,8 +871,8 @@ test("package model assignment keeps only package-managed agents owned", () => {
|
|
|
848
871
|
|
|
849
872
|
installSddAssets(PACKAGE_ROOT, true);
|
|
850
873
|
assert.equal(
|
|
851
|
-
readFileSync(
|
|
852
|
-
readFileSync(join(PACKAGE_ROOT, "assets", "agents",
|
|
874
|
+
readFileSync(installedExemplar, "utf8"),
|
|
875
|
+
readFileSync(join(PACKAGE_ROOT, "assets", "agents", MANAGED_EXEMPLAR_FILE), "utf8"),
|
|
853
876
|
"a routed package-managed agent must remain eligible for package refresh",
|
|
854
877
|
);
|
|
855
878
|
assert.equal(
|
|
@@ -1137,18 +1160,21 @@ test("pi-pretty wrapper uses real package path resolution for pnpm symlink insta
|
|
|
1137
1160
|
assert.match(wrapper, /quietToolsEnabled/);
|
|
1138
1161
|
});
|
|
1139
1162
|
|
|
1140
|
-
test("v2.
|
|
1163
|
+
test("v2.2.0 release package and runtime stop before publication", () => {
|
|
1141
1164
|
const packageJson = readPackageJson();
|
|
1142
|
-
assert.equal(packageJson.version, "2.
|
|
1165
|
+
assert.equal(packageJson.version, "2.2.0", "the release manifest must remain explicitly pinned to v2.2.0");
|
|
1143
1166
|
assert.equal(
|
|
1144
1167
|
packageJson.scripts?.test,
|
|
1145
|
-
"node --experimental-strip-types --test tests/*.test.ts && pnpm run test:harness",
|
|
1168
|
+
"node --experimental-strip-types --test tests/*.test.ts && pnpm run check:provider-contract && pnpm run test:harness",
|
|
1146
1169
|
);
|
|
1147
1170
|
assert.ok(packageJson.files?.includes("assets/"));
|
|
1148
1171
|
assert.ok(packageJson.files?.includes("contracts/"));
|
|
1149
1172
|
|
|
1150
1173
|
const verifier = readFileSync(join(PACKAGE_ROOT, "scripts", "verify-package-files.mjs"), "utf8");
|
|
1151
|
-
|
|
1174
|
+
// gentle-pi#311 P5: the retired adversarial role agents must not be pinned
|
|
1175
|
+
// as required package files, while the append-only migration history stays.
|
|
1176
|
+
assert.doesNotMatch(verifier, /assets\/agents\/review-refuter\.md/);
|
|
1177
|
+
assert.doesNotMatch(verifier, /assets\/agents\/review-validator\.md/);
|
|
1152
1178
|
assert.match(verifier, /assets\/migrations\/managed-assets-v0\.13\.json/);
|
|
1153
1179
|
assert.match(verifier, /assets\/migrations\/managed-assets-v0\.14\.json/);
|
|
1154
1180
|
|
|
@@ -1157,13 +1183,13 @@ test("v2.1.2 release package and runtime stop before publication", () => {
|
|
|
1157
1183
|
assert.doesNotMatch(runtime, /execFileSync\("(?:npm|pnpm)", \["publish"/);
|
|
1158
1184
|
});
|
|
1159
1185
|
|
|
1160
|
-
test("bounded review keeps the Judgment Day skill contract at metadata version 1.
|
|
1186
|
+
test("bounded review keeps the Judgment Day skill contract at canon metadata version 1.7", () => {
|
|
1161
1187
|
const frontmatter = readAgentFrontmatter(
|
|
1162
1188
|
join(PACKAGE_ROOT, "skills", "judgment-day", "SKILL.md"),
|
|
1163
1189
|
);
|
|
1164
1190
|
|
|
1165
|
-
assert.match(frontmatter, /^ version: "1\.
|
|
1166
|
-
assert.doesNotMatch(frontmatter, /^ version: "1\.
|
|
1191
|
+
assert.match(frontmatter, /^ version: "1\.7"$/m);
|
|
1192
|
+
assert.doesNotMatch(frontmatter, /^ version: "1\.4"$/m);
|
|
1167
1193
|
});
|
|
1168
1194
|
|
|
1169
1195
|
test("README documents bounded review transactions and the honest installed permission boundary", () => {
|
|
@@ -1173,9 +1199,9 @@ test("README documents bounded review transactions and the honest installed perm
|
|
|
1173
1199
|
"Native compact gate validation is read-only.",
|
|
1174
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.",
|
|
1175
1201
|
"Dangerous-command safety remains independent and authoritative.",
|
|
1176
|
-
"
|
|
1202
|
+
"Adversarial review roles (the refuter and the targeted validator) are never Pi-authored",
|
|
1177
1203
|
"package-managed isolated installation",
|
|
1178
|
-
"Project and user overrides may shadow
|
|
1204
|
+
"Project and user overrides may shadow a package asset",
|
|
1179
1205
|
]) {
|
|
1180
1206
|
assert.ok(readme.includes(clause), `README missing review v2 clause: ${clause}`);
|
|
1181
1207
|
}
|