gentle-pi 2.0.0 → 2.1.1
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 +3 -12
- package/extensions/gentle-ai.ts +362 -123
- package/lib/gentle-ai-binary.ts +64 -17
- package/lib/native-review-cli.ts +207 -27
- package/lib/review-candidate-view.ts +9 -5
- package/lib/review-integration-v2.ts +5 -1
- package/package.json +1 -1
- package/runtime/gentle-ai-binary.mjs +64 -17
- package/runtime/native-review-cli.mjs +206 -26
- package/runtime/review-integration-v2.mjs +5 -1
- package/scripts/gentle-ai-installer.mjs +454 -71
- package/scripts/test-packed-runner.mjs +1 -1
- package/skills/_shared/review-ledger-contract.md +3 -1
- package/tests/gentle-ai-binary.test.ts +70 -3
- package/tests/gentle-ai-installer.test.ts +543 -7
- package/tests/gentle-ai.test.ts +2 -2
- package/tests/native-review-consent.test.ts +205 -0
- package/tests/native-review-parity-runtime.test.ts +15 -6
- package/tests/native-review-parity.test.ts +228 -53
- package/tests/package-manifest.test.ts +10 -3
- package/tests/review-candidate-view.test.ts +43 -0
- package/tests/review-controller-lock-status.test.ts +25 -7
- package/tests/review-controller-native-routing.test.ts +419 -20
- package/tests/review-controller-workspace-root.test.ts +40 -10
- package/tests/review-controller.test.ts +1 -1
- package/tests/review-integration-v2.test.ts +10 -1
- package/tests/runtime-harness.mjs +24 -12
|
@@ -212,7 +212,8 @@ test("installed commit transaction runner loads JavaScript only and has determin
|
|
|
212
212
|
assert.equal(packageJson.scripts?.["test:packed-runner"], "node scripts/test-packed-runner.mjs");
|
|
213
213
|
assert.match(packageJson.scripts?.prepublishOnly ?? "", /pnpm run test:packed-runner/);
|
|
214
214
|
assert.match(ci, /pnpm run test:packed-runner/);
|
|
215
|
-
assert.
|
|
215
|
+
assert.match(packedRunner, /\["install"[^\]]*"--ignore-scripts=false"/s, "packed install must explicitly enable postinstall");
|
|
216
|
+
assert.doesNotMatch(packedRunner, /\["install"[^\]]*"--ignore-scripts"(?!\=false)/s);
|
|
216
217
|
assert.match(packedRunner, /execFileSync\("where\.exe", \["npm"\]/);
|
|
217
218
|
assert.match(packedRunner, /could not resolve npm-cli\.js without a command shell/);
|
|
218
219
|
assert.doesNotMatch(packedRunner, /ComSpec|cmd\.exe/);
|
|
@@ -275,7 +276,13 @@ test("package verification binds the published Gentle AI v2.2.2 runtime pin", ()
|
|
|
275
276
|
const verifier = readFileSync(join(PACKAGE_ROOT, "scripts", "verify-package-files.mjs"), "utf8");
|
|
276
277
|
|
|
277
278
|
assert.match(installer, /INSTALLER_VERSION = "2\.2\.2"/);
|
|
279
|
+
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="/);
|
|
281
|
+
assert.match(installer, /GOTOOLCHAIN: "local"/);
|
|
282
|
+
assert.match(installer, /GOSUMDB: "sum\.golang\.org"/);
|
|
278
283
|
assert.match(binary, /GENTLE_AI_VERSION = "2\.2\.2"/);
|
|
284
|
+
assert.match(binary, /GO_SUMDB_SOURCE_BUILD/);
|
|
285
|
+
assert.match(binary, /GENTLE_AI_WINDOWS_SOURCE_MODULE_CHECKSUM/);
|
|
279
286
|
assert.match(verifier, /v2\.2\.2/);
|
|
280
287
|
});
|
|
281
288
|
|
|
@@ -1130,9 +1137,9 @@ test("pi-pretty wrapper uses real package path resolution for pnpm symlink insta
|
|
|
1130
1137
|
assert.match(wrapper, /quietToolsEnabled/);
|
|
1131
1138
|
});
|
|
1132
1139
|
|
|
1133
|
-
test("v2.
|
|
1140
|
+
test("v2.1.1 release package and runtime stop before publication", () => {
|
|
1134
1141
|
const packageJson = readPackageJson();
|
|
1135
|
-
assert.equal(packageJson.version, "2.
|
|
1142
|
+
assert.equal(packageJson.version, "2.1.1", "the release manifest must remain explicitly pinned to v2.1.1");
|
|
1136
1143
|
assert.equal(
|
|
1137
1144
|
packageJson.scripts?.test,
|
|
1138
1145
|
"node --experimental-strip-types --test tests/*.test.ts && pnpm run test:harness",
|
|
@@ -584,6 +584,49 @@ test("native projections reconstruct symlink, intended-untracked, and gitlink id
|
|
|
584
584
|
assert.deepEqual(projection.gitlinks, { "vendor/dependency": gitlinkCommit });
|
|
585
585
|
});
|
|
586
586
|
|
|
587
|
+
test("native staged projections restore the exact current index over HEAD", (t) => {
|
|
588
|
+
const contributorRoot = repository(t);
|
|
589
|
+
const baseTree = git(contributorRoot, "rev-parse", "HEAD^{tree}");
|
|
590
|
+
writeFileSync(join(contributorRoot, "tracked.txt"), "staged candidate\n");
|
|
591
|
+
git(contributorRoot, "add", "tracked.txt");
|
|
592
|
+
const candidateTree = git(contributorRoot, "write-tree");
|
|
593
|
+
const registry = new CandidateViewRegistry();
|
|
594
|
+
|
|
595
|
+
registry.restoreProjectionFromNative("staged-index-projection", contributorRoot, {
|
|
596
|
+
baseTree,
|
|
597
|
+
currentCandidateTree: candidateTree,
|
|
598
|
+
paths: ["tracked.txt"],
|
|
599
|
+
intendedUntracked: [],
|
|
600
|
+
projection: "staged",
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
const projection = registry.resolveProjection("staged-index-projection", contributorRoot);
|
|
604
|
+
assert.equal(projection.baseTree, baseTree);
|
|
605
|
+
assert.equal(projection.candidateTree, candidateTree);
|
|
606
|
+
assert.equal(projection.committedOnly, false);
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
test("native staged projections reject a workspace snapshot that differs from the current index", (t) => {
|
|
610
|
+
const contributorRoot = repository(t);
|
|
611
|
+
const baseTree = git(contributorRoot, "rev-parse", "HEAD^{tree}");
|
|
612
|
+
writeFileSync(join(contributorRoot, "tracked.txt"), "workspace candidate\n");
|
|
613
|
+
const workspace = new CandidateViewRegistry().create({ contributorRoot });
|
|
614
|
+
try {
|
|
615
|
+
assert.throws(
|
|
616
|
+
() => new CandidateViewRegistry().restoreProjectionFromNative("workspace-as-staged", contributorRoot, {
|
|
617
|
+
baseTree,
|
|
618
|
+
currentCandidateTree: workspace.candidateTree,
|
|
619
|
+
paths: ["tracked.txt"],
|
|
620
|
+
intendedUntracked: [],
|
|
621
|
+
projection: "staged",
|
|
622
|
+
}),
|
|
623
|
+
(error: unknown) => error instanceof CandidateViewError && error.reason === "projection-kind-drift",
|
|
624
|
+
);
|
|
625
|
+
} finally {
|
|
626
|
+
workspace.cleanup();
|
|
627
|
+
}
|
|
628
|
+
});
|
|
629
|
+
|
|
587
630
|
test("native projections recover a committed range base from its frozen tree", (t) => {
|
|
588
631
|
const contributorRoot = repository(t);
|
|
589
632
|
const baseCommit = git(contributorRoot, "rev-parse", "HEAD");
|
|
@@ -75,11 +75,27 @@ function nativeStatus(cwd: string, status: string, locks: readonly unknown[]): N
|
|
|
75
75
|
} as NativeReviewStatusResult;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
function fakeNative(status: NativeReviewStatusResult, onStart?: () => void): NativeReviewCli {
|
|
78
|
+
function fakeNative(status: NativeReviewStatusResult, onStart?: (request: Parameters<NativeReviewCli["start"]>[0]) => void): NativeReviewCli {
|
|
79
79
|
const blocking = status.locks.some((lock) => (lock as { status?: string }).status !== "released");
|
|
80
|
+
const tree = execFileSync("git", ["rev-parse", "HEAD^{tree}"], { cwd: status.repository, encoding: "utf8" }).trim();
|
|
81
|
+
const targetIdentity = `sha256:${"a".repeat(64)}`;
|
|
82
|
+
const projection = {
|
|
83
|
+
schema: "gentle-ai.review-integration.projection/v1",
|
|
84
|
+
kind: "current-changes",
|
|
85
|
+
projection: "workspace",
|
|
86
|
+
baseTree: tree,
|
|
87
|
+
initialReviewTree: tree,
|
|
88
|
+
currentCandidateTree: tree,
|
|
89
|
+
pathsDigest: targetIdentity,
|
|
90
|
+
paths: [],
|
|
91
|
+
intendedUntracked: [],
|
|
92
|
+
intendedUntrackedProof: targetIdentity,
|
|
93
|
+
initialSnapshotIdentity: targetIdentity,
|
|
94
|
+
currentSnapshotIdentity: targetIdentity,
|
|
95
|
+
};
|
|
80
96
|
return {
|
|
81
|
-
start: async () => {
|
|
82
|
-
onStart?.();
|
|
97
|
+
start: async (request) => {
|
|
98
|
+
onStart?.(request);
|
|
83
99
|
return { lineageId: "native-lineage", state: "reviewing", riskLevel: "medium", selectedLenses: ["review-reliability"], changedFiles: 1, changedLines: 2, correctionBudget: 1, action: "created", lensesRequired: true };
|
|
84
100
|
},
|
|
85
101
|
finalize: async () => { throw new Error("finalize must not run"); },
|
|
@@ -90,7 +106,9 @@ function fakeNative(status: NativeReviewStatusResult, onStart?: () => void): Nat
|
|
|
90
106
|
targetStatus: async () => ({
|
|
91
107
|
applicability: blocking ? "corrupted" : "unrelated",
|
|
92
108
|
action: blocking ? "repair_authority" : "start",
|
|
93
|
-
|
|
109
|
+
targetIdentity,
|
|
110
|
+
projection,
|
|
111
|
+
raw: { action: blocking ? "repair_authority" : "start", locks: status.locks, target_identity: targetIdentity, projection: { projection: "workspace" } },
|
|
94
112
|
}),
|
|
95
113
|
} as unknown as NativeReviewCli;
|
|
96
114
|
}
|
|
@@ -121,11 +139,11 @@ test("INSPECT treats released lock residue as non-blocking and still blocks on l
|
|
|
121
139
|
test("START precondition ignores released lock residue and still blocks on live lock claims", async (t) => {
|
|
122
140
|
const cwd = repository(t);
|
|
123
141
|
|
|
124
|
-
|
|
125
|
-
const proceeded = await runtime(fakeNative(nativeStatus(cwd, "clean", [RELEASED_LOCK]), () => {
|
|
142
|
+
const startRequests: Parameters<NativeReviewCli["start"]>[0][] = [];
|
|
143
|
+
const proceeded = await runtime(fakeNative(nativeStatus(cwd, "clean", [RELEASED_LOCK]), (request) => { startRequests.push(request); }))
|
|
126
144
|
.execute("start-released", { operation: "start", input: JSON.stringify({ mode: "ordinary" }) }, undefined, undefined, context(cwd));
|
|
127
145
|
const proceededDetails = proceeded.details as Record<string, unknown>;
|
|
128
|
-
assert.
|
|
146
|
+
assert.deepEqual(startRequests, [{ cwd, targetIdentity: `sha256:${"a".repeat(64)}`, projection: "workspace" }]);
|
|
129
147
|
assert.equal((proceededDetails.result as Record<string, unknown>).lineage_id, "native-lineage");
|
|
130
148
|
assert.notEqual(proceededDetails.outcome, "native-authority-lock-present");
|
|
131
149
|
|