gentle-pi 2.2.0 → 2.4.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 +76 -79
- 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-explore.md +1 -0
- 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 +56 -249
- package/assets/orchestrator-memory.md +2 -0
- package/assets/orchestrator.md +20 -40
- 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/contracts/review-provider-contract-mirror/provider-contract.lock.json +8 -7
- package/contracts/review-provider-contract-mirror/{v1.1.0 → v1.2.0}/bundle/README.md +10 -0
- package/contracts/review-provider-contract-mirror/v1.2.0/bundle/manifest.json +74 -0
- package/contracts/review-provider-contract-mirror/v1.2.0/bundle/orchestration/pi.md +53 -0
- package/contracts/review-provider-contract-mirror/v1.2.0/bundle/schemas/targeted-validator.schema.json +1 -0
- package/contracts/review-provider-contract-mirror/{v1.1.0 → v1.2.0}/generated/provider-capabilities.baseline.json +9 -2
- package/contracts/review-provider-contract-mirror/{v1.1.0 → v1.2.0}/generated/provider-roles.baseline.json +2 -2
- 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 +2349 -3785
- package/extensions/quiet-tools.ts +515 -32
- package/extensions/sdd-init.ts +4 -8
- package/lib/agent-home.ts +8 -0
- package/lib/gentle-ai-renderer.ts +70 -0
- package/lib/model-routing-authority.ts +133 -0
- package/lib/native-review-cli.ts +387 -940
- package/lib/opaque-pi-reviewer-adapter.ts +284 -0
- package/lib/provider-contract-bundle.ts +88 -6
- package/lib/review-candidate-view.ts +341 -132
- package/lib/review-host-relay.ts +324 -96
- package/lib/review-integration-v2.ts +868 -307
- package/lib/review-last-event-controller.ts +35 -0
- package/lib/sdd-preflight.ts +179 -68
- 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 +337 -890
- package/runtime/review-integration-v2.mjs +816 -255
- 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 +23 -23
- package/skills/_shared/review-ledger-contract.md +14 -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/issue-creation/SKILL.md +53 -93
- 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/fixtures/provider-contract-bundle/v1.2.0/README.md +22 -0
- package/{contracts/review-provider-contract-mirror/v1.1.0/bundle → tests/fixtures/provider-contract-bundle/v1.2.0}/manifest.json +11 -2
- package/tests/fixtures/provider-contract-bundle/v1.2.0/orchestration/pi.md +97 -0
- package/tests/fixtures/provider-contract-bundle/v1.2.0/schemas/lens.schema.json +16 -0
- package/tests/fixtures/provider-contract-bundle/v1.2.0/schemas/refuter.schema.json +1 -0
- package/tests/fixtures/provider-contract-bundle/v1.2.0/vectors/lens.json +1 -0
- package/tests/fixtures/provider-contract-bundle/v1.2.0/vectors/refuter.json +1 -0
- package/tests/fixtures/provider-contract-bundle/v1.2.0/vectors/targeted-validator.json +1 -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 +821 -131
- package/tests/gentle-theme.test.ts +133 -0
- package/tests/issue-creation-skill.test.ts +103 -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 +45 -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 +152 -36
- package/tests/provider-contract-bundle.test.ts +76 -0
- package/tests/provider-contract-mirror.test.ts +19 -0
- package/tests/provider-defect-handoff.test.ts +15 -118
- package/tests/quiet-tool-rendering.test.ts +1055 -28
- package/tests/review-agent-end-preflight.test.ts +408 -0
- 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-contract-prompt.test.ts +139 -0
- 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 +328 -91
- package/tests/review-host-relay.test.ts +436 -14
- package/tests/review-integration-v2-forward.test.ts +623 -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 +362 -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 +366 -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
- /package/contracts/review-provider-contract-mirror/{v1.1.0 → v1.2.0}/bundle/schemas/lens.schema.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.1.0 → v1.2.0}/bundle/schemas/refuter.schema.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.1.0 → v1.2.0}/bundle/vectors/lens.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.1.0 → v1.2.0}/bundle/vectors/refuter.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.1.0 → v1.2.0}/bundle/vectors/targeted-validator.json +0 -0
- /package/{contracts/review-provider-contract-mirror/v1.1.0/bundle → tests/fixtures/provider-contract-bundle/v1.2.0}/schemas/targeted-validator.schema.json +0 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import test from "node:test";
|
|
7
|
+
import { pathToFileURL } from "node:url";
|
|
8
|
+
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
9
|
+
import { createGentleAiExtension } from "../extensions/gentle-ai.ts";
|
|
10
|
+
import type { NativeReviewCli } from "../lib/native-review-cli.ts";
|
|
11
|
+
|
|
12
|
+
// gentle-pi#560 / gentle-ai#4056, #4057: since 2026-08-01 Gentle AI stopped
|
|
13
|
+
// writing a runtime-specific review execution contract into Pi's generated
|
|
14
|
+
// APPEND_SYSTEM composition. This package now injects the mirrored provider
|
|
15
|
+
// contract bundle's own `orchestration/pi.md` text at session start instead.
|
|
16
|
+
// These tests exercise the real committed mirror (contracts/review-provider-contract-mirror/)
|
|
17
|
+
// rather than a fake one: the mirror IS the package under test.
|
|
18
|
+
|
|
19
|
+
type BeforeAgentStartResult = { systemPrompt: string };
|
|
20
|
+
type BeforeAgentStartHandler = (event: unknown, ctx: ExtensionContext) => Promise<BeforeAgentStartResult>;
|
|
21
|
+
|
|
22
|
+
const REPO_ROOT = join(import.meta.dirname, "..");
|
|
23
|
+
const MIRROR_LOCK_PATH = join(REPO_ROOT, "contracts", "review-provider-contract-mirror", "provider-contract.lock.json");
|
|
24
|
+
|
|
25
|
+
function mirroredPiOrchestrationText(): string {
|
|
26
|
+
const lock = JSON.parse(readFileSync(MIRROR_LOCK_PATH, "utf8")) as { contract_semver: string };
|
|
27
|
+
return readFileSync(
|
|
28
|
+
join(REPO_ROOT, "contracts", "review-provider-contract-mirror", `v${lock.contract_semver}`, "bundle", "orchestration", "pi.md"),
|
|
29
|
+
"utf8",
|
|
30
|
+
).trim();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function harness(nativeReviewCli: NativeReviewCli | null): { beforeAgentStart: BeforeAgentStartHandler } {
|
|
34
|
+
const handlers = new Map<string, BeforeAgentStartHandler>();
|
|
35
|
+
const pi = {
|
|
36
|
+
on(name: string, handler: BeforeAgentStartHandler) {
|
|
37
|
+
handlers.set(name, handler);
|
|
38
|
+
},
|
|
39
|
+
events: { emit() {} },
|
|
40
|
+
registerCommand() {},
|
|
41
|
+
registerTool() {},
|
|
42
|
+
} as unknown as ExtensionAPI;
|
|
43
|
+
createGentleAiExtension({ nativeReviewCli })(pi);
|
|
44
|
+
const beforeAgentStart = handlers.get("before_agent_start");
|
|
45
|
+
assert.equal(typeof beforeAgentStart, "function");
|
|
46
|
+
return { beforeAgentStart: beforeAgentStart as BeforeAgentStartHandler };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function ctx(overrides: Record<string, unknown> = {}): ExtensionContext {
|
|
50
|
+
return {
|
|
51
|
+
cwd: process.cwd(),
|
|
52
|
+
hasUI: true,
|
|
53
|
+
ui: { notify() {} },
|
|
54
|
+
sessionManager: { getSessionId: () => "review-contract-prompt-session" },
|
|
55
|
+
...overrides,
|
|
56
|
+
} as unknown as ExtensionContext;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const primaryEvent = { systemPrompt: "base" };
|
|
60
|
+
|
|
61
|
+
test("before_agent_start injects the mirrored review execution contract for the primary session", async () => {
|
|
62
|
+
const { beforeAgentStart } = harness({} as NativeReviewCli);
|
|
63
|
+
const result = await beforeAgentStart(primaryEvent, ctx());
|
|
64
|
+
const expected = mirroredPiOrchestrationText();
|
|
65
|
+
assert.match(result.systemPrompt, /## Gentle AI review execution contract \(mirrored provider bundle 1\.2\.0\)/);
|
|
66
|
+
assert.ok(result.systemPrompt.includes(expected), "the mirrored orchestration/pi.md text must appear verbatim");
|
|
67
|
+
assert.match(result.systemPrompt, /call `gentle_review` with {"operation":"inspect"}/);
|
|
68
|
+
assert.match(result.systemPrompt, /call `gentle_review` with operation `status`, the exact retained `lineageId`, and `workspaceRoot`/);
|
|
69
|
+
assert.match(result.systemPrompt, /Use `gentle_review_capture` for one current returned slot or `gentle_review_capture_group` for the complete current reviewer group/);
|
|
70
|
+
assert.match(result.systemPrompt, /An approved capture awaits acknowledgement; it is not burned\. On `approved`, use bound facade STATUS to obtain or replay the exact provider-issued `acknowledge-approved` continuation, then execute it unchanged\. Only its successful returned envelope burns authority; do not issue STATUS after that burn\./);
|
|
71
|
+
let previousLifecycleIndex = result.systemPrompt.indexOf("## Gentle AI review execution contract");
|
|
72
|
+
for (const marker of [
|
|
73
|
+
'call `gentle_review` with {"operation":"inspect"}',
|
|
74
|
+
"2. **Freeze once.**",
|
|
75
|
+
"call `gentle_review` with operation `status`",
|
|
76
|
+
"Use `gentle_review_capture` for one current returned slot",
|
|
77
|
+
"5. **Acknowledge exactly.**",
|
|
78
|
+
]) {
|
|
79
|
+
const markerIndex = result.systemPrompt.indexOf(marker, previousLifecycleIndex + 1);
|
|
80
|
+
assert.ok(markerIndex > previousLifecycleIndex, `${marker} must follow the previous lifecycle step`);
|
|
81
|
+
previousLifecycleIndex = markerIndex;
|
|
82
|
+
}
|
|
83
|
+
assert.doesNotMatch(result.systemPrompt, /authority is already burned/);
|
|
84
|
+
assert.doesNotMatch(result.systemPrompt, /gentle-ai review status\b.*--agent pi/);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test("before_agent_start does not inject the review execution contract for a named agent session", async () => {
|
|
88
|
+
const { beforeAgentStart } = harness({} as NativeReviewCli);
|
|
89
|
+
const result = await beforeAgentStart({ agentName: "review-readability", systemPrompt: "base" }, ctx());
|
|
90
|
+
assert.doesNotMatch(result.systemPrompt, /Gentle AI review execution contract/);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test("before_agent_start does not inject the review execution contract for an SDD executor session", async () => {
|
|
94
|
+
const { beforeAgentStart } = harness({} as NativeReviewCli);
|
|
95
|
+
const result = await beforeAgentStart({ systemPrompt: "SDD apply executor body" }, ctx());
|
|
96
|
+
assert.doesNotMatch(result.systemPrompt, /Gentle AI review execution contract/);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test("before_agent_start injects nothing when nativeReviewCli is null", async () => {
|
|
100
|
+
const { beforeAgentStart } = harness(null);
|
|
101
|
+
const result = await beforeAgentStart(primaryEvent, ctx());
|
|
102
|
+
assert.doesNotMatch(result.systemPrompt, /Gentle AI review execution contract/);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// gentle-ai R1/R3: a tampered mirrored orchestration/pi.md must never be spliced into the system prompt.
|
|
106
|
+
function tempMirror(text: string, entrySha256: string): string {
|
|
107
|
+
const root = mkdtempSync(join(tmpdir(), "gentle-pi-mirror-"));
|
|
108
|
+
const bundleDir = join(root, "v9.9.9", "bundle", "orchestration");
|
|
109
|
+
mkdirSync(bundleDir, { recursive: true });
|
|
110
|
+
writeFileSync(join(bundleDir, "pi.md"), text, "utf8");
|
|
111
|
+
const lock = JSON.stringify({ contract_semver: "9.9.9", entries: { "orchestration/pi.md": entrySha256 } });
|
|
112
|
+
writeFileSync(join(root, "provider-contract.lock.json"), lock, "utf8");
|
|
113
|
+
return root;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
test("rejects a tampered mirror, accepts a matching one, and warns once", async () => {
|
|
117
|
+
const tampered = tempMirror("tampered contract text", "0".repeat(64));
|
|
118
|
+
const matchingText = "matching contract text";
|
|
119
|
+
const matching = tempMirror(matchingText, createHash("sha256").update(Buffer.from(matchingText, "utf8")).digest("hex"));
|
|
120
|
+
try {
|
|
121
|
+
// Cache-bust: isolate this module's fragment cache from the real-mirror tests above.
|
|
122
|
+
const cacheBustedUrl = `${pathToFileURL(join(import.meta.dirname, "..", "extensions", "gentle-ai.ts")).href}?tamper=${Math.random()}`;
|
|
123
|
+
type Testing = {
|
|
124
|
+
readMirroredReviewContractFragment: (mirrorRoot?: string) => string | null;
|
|
125
|
+
loadReviewContractPromptFragment: (ctx: ExtensionContext, mirrorRoot?: string) => string | null;
|
|
126
|
+
};
|
|
127
|
+
const fresh = (await import(cacheBustedUrl)) as { __testing: Testing };
|
|
128
|
+
assert.equal(fresh.__testing.readMirroredReviewContractFragment(tampered), null);
|
|
129
|
+
assert.ok(fresh.__testing.readMirroredReviewContractFragment(matching)?.includes(matchingText));
|
|
130
|
+
let notifyCount = 0;
|
|
131
|
+
const spyCtx = { hasUI: true, ui: { notify: () => { notifyCount += 1; } } } as unknown as ExtensionContext;
|
|
132
|
+
fresh.__testing.loadReviewContractPromptFragment(spyCtx, tampered);
|
|
133
|
+
fresh.__testing.loadReviewContractPromptFragment(spyCtx, tampered);
|
|
134
|
+
assert.equal(notifyCount, 1);
|
|
135
|
+
} finally {
|
|
136
|
+
rmSync(tampered, { recursive: true, force: true });
|
|
137
|
+
rmSync(matching, { recursive: true, force: true });
|
|
138
|
+
}
|
|
139
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import { execFileSync } from "node:child_process";
|
|
3
|
-
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { mkdtempSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { tmpdir } from "node:os";
|
|
5
5
|
import { join } from "node:path";
|
|
6
6
|
import test from "node:test";
|
|
@@ -47,7 +47,7 @@ function context(cwd: string): ExtensionContext {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
function repository(t: test.TestContext): string {
|
|
50
|
-
const cwd = mkdtempSync(join(tmpdir(), "gentle-pi-lock-status-"));
|
|
50
|
+
const cwd = realpathSync(mkdtempSync(join(tmpdir(), "gentle-pi-lock-status-")));
|
|
51
51
|
t.after(() => rmSync(cwd, { recursive: true, force: true }));
|
|
52
52
|
execFileSync("git", ["init", "-b", "main"], { cwd });
|
|
53
53
|
writeFileSync(join(cwd, "app.ts"), "export const value = 1;\n");
|