gentle-pi 2.6.1 → 2.6.2
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 +183 -943
- package/contracts/review-provider-contract-mirror/provider-contract.lock.json +9 -8
- package/contracts/review-provider-contract-mirror/v1.2.0/bundle/manifest.json +3 -3
- package/contracts/review-provider-contract-mirror/v1.2.0/bundle/orchestration/pi.md +7 -2
- package/contracts/review-provider-contract-mirror/v1.2.0/bundle/schemas/lens.schema.json +2 -2
- package/contracts/review-provider-contract-mirror/v1.2.0/bundle/schemas/targeted-validator.schema.json +1 -1
- package/contracts/review-provider-contract-mirror/v1.2.0/generated/provider-capabilities.baseline.json +1 -1
- package/contracts/review-provider-contract-mirror/v1.2.0/generated/provider-roles.baseline.json +2 -2
- package/docs/assets/brand/gentle-pi-banner.png +0 -0
- package/docs/assets/brand/gentle-pi-banner.svg +33 -0
- package/docs/assets/brand/terminal-divider.svg +17 -0
- package/docs/assets/diagrams/agent-orchestration.svg +19 -0
- package/docs/assets/diagrams/gentleman-workflow.svg +15 -0
- package/docs/assets/diagrams/native-review.svg +16 -0
- package/docs/assets/diagrams/sdd-cycle.svg +14 -0
- package/docs/assets/features/gentle-shell.png +0 -0
- package/docs/gentle-shell.md +151 -0
- package/docs/readme-reference.md +868 -0
- package/extensions/gentle-agents.ts +4 -1
- package/extensions/gentle-ai.ts +65 -22
- package/lib/agents-history.ts +7 -1
- package/lib/native-review-cli.ts +9 -0
- package/package.json +1 -1
- package/runtime/native-review-cli.mjs +9 -0
- package/scripts/gentle-ai-installer.mjs +10 -10
- package/scripts/verify-package-files.mjs +2 -2
- package/tests/gentle-agents.test.ts +22 -0
- package/tests/gentle-ai-binary.test.ts +1 -1
- package/tests/gentle-ai-installer.test.ts +47 -47
- package/tests/gentle-ai.test.ts +3 -2
- package/tests/native-review-capability-contract.test.ts +13 -1
- package/tests/package-manifest.test.ts +19 -18
- package/tests/review-authority-recovery-docs.test.ts +13 -13
- package/tests/review-controller-native-routing.test.ts +49 -0
- package/tests/review-ledger-contract.test.ts +7 -5
- package/tests/sdd-managed-runtime-settlement.test.ts +37 -0
- package/tests/sdd-selection-transport.test.ts +57 -0
- package/tests/skill-collision-prefixes.test.ts +2 -2
|
@@ -197,9 +197,12 @@ export async function admitManagedRemediation(request: TaskRequest, input: unkno
|
|
|
197
197
|
task.error = "Managed remediation lacks complete passing planned-command evidence";
|
|
198
198
|
}
|
|
199
199
|
if (payload.outcome === "passed" && state.settlement && state.settlement.state !== "blocked") task.status = TASK_STATUS.COMPLETED;
|
|
200
|
-
if (!state.settlement
|
|
200
|
+
if (!state.settlement) {
|
|
201
201
|
task.status = TASK_STATUS.FAILED;
|
|
202
202
|
task.error = "Native remediation settlement unresolved; retain exact history for reconciliation";
|
|
203
|
+
} else if (state.settlement.state === "blocked") {
|
|
204
|
+
task.status = TASK_STATUS.FAILED;
|
|
205
|
+
task.error = `Native remediation settlement blocked(${state.settlement.reason ?? "unspecified"}); current native admission decides any later attempt`;
|
|
203
206
|
}
|
|
204
207
|
await persist(task);
|
|
205
208
|
},
|
package/extensions/gentle-ai.ts
CHANGED
|
@@ -1839,7 +1839,15 @@ async function resolveSelectedNativeSddChangeStartup(
|
|
|
1839
1839
|
}
|
|
1840
1840
|
if (selection.phase === "remediate") {
|
|
1841
1841
|
if (status.nextRecommended !== "remediate" || status.remediationState?.failedEvidenceRevision !== selection.failedEvidenceRevision) throw new Error("Stale remediation selection");
|
|
1842
|
-
} else if (status.nextRecommended !== selection.phase || status.dependencies[selection.phase] !== "ready" || status.blockedReasons.length > 0) {
|
|
1842
|
+
} else if (status.nextRecommended !== selection.phase || status.dependencies[selection.phase] !== "ready" || (status.blockedReasons.length > 0 && selection.phase !== "verify")) {
|
|
1843
|
+
// Native's contract gates terminal, archive, and apply work on a
|
|
1844
|
+
// non-empty `blockedReasons`, and it deliberately keeps the `verify`
|
|
1845
|
+
// route runnable, because the blocker can name the evidence refresh
|
|
1846
|
+
// that is its own remedy ("failed verification evidence is incomplete;
|
|
1847
|
+
// rerun SDD verification", gentle-ai#3538). Vetoing that route made the
|
|
1848
|
+
// native-recommended phase unreachable (gentle-pi#972). The other
|
|
1849
|
+
// phases still fail closed, and every blocker stays in the injected
|
|
1850
|
+
// status for reporting.
|
|
1843
1851
|
throw new Error(`SDD selection native status blocks phase ${selection.phase}; it cannot execute.`);
|
|
1844
1852
|
}
|
|
1845
1853
|
return { selection, status };
|
|
@@ -5601,6 +5609,33 @@ function completeNativeStart(
|
|
|
5601
5609
|
};
|
|
5602
5610
|
}
|
|
5603
5611
|
|
|
5612
|
+
// gentle-ai#4003: every Pi-side teardown step that fails after the native
|
|
5613
|
+
// burn is deferred cleanup, not a failed acknowledgement. Only the
|
|
5614
|
+
// already-sanitized CandidateViewError surface is relayed; anything else is
|
|
5615
|
+
// reduced to the step's fixed code so no path or command text reaches the
|
|
5616
|
+
// caller. The candidate-view hint is out-of-band on purpose: no controller
|
|
5617
|
+
// operation exposes a cleanup-only retry, and replaying acknowledge-approved
|
|
5618
|
+
// would hit the already-burned lineage.
|
|
5619
|
+
const POST_BURN_CLEANUP = {
|
|
5620
|
+
candidateView: { code: "candidate-view-cleanup-failed", nextAction: "retry-candidate-view-cleanup-or-remove-the-view-out-of-band" },
|
|
5621
|
+
retainedSelection: { code: "retained-selection-cleanup-failed", nextAction: "retained-selection-clears-on-the-next-terminal-status" },
|
|
5622
|
+
} as const;
|
|
5623
|
+
|
|
5624
|
+
function deferredPostBurnCleanup(step: (typeof POST_BURN_CLEANUP)[keyof typeof POST_BURN_CLEANUP], cleanup: () => void): Record<string, unknown> | undefined {
|
|
5625
|
+
try {
|
|
5626
|
+
cleanup();
|
|
5627
|
+
return undefined;
|
|
5628
|
+
} catch (error) {
|
|
5629
|
+
return {
|
|
5630
|
+
status: "deferred",
|
|
5631
|
+
diagnostics: error instanceof CandidateViewError
|
|
5632
|
+
? { code: error.reason, message: error.message }
|
|
5633
|
+
: { code: step.code },
|
|
5634
|
+
next_action: step.nextAction,
|
|
5635
|
+
};
|
|
5636
|
+
}
|
|
5637
|
+
}
|
|
5638
|
+
|
|
5604
5639
|
function nativeOperationFailure(operation: ReviewControllerOperation | "gentle_review_capture", error: unknown): Record<string, unknown> {
|
|
5605
5640
|
const value = error as { mutationOutcome?: unknown; nextAction?: unknown; diagnostics?: unknown; auditRecord?: unknown; launchAttempted?: unknown; candidateViewPreNative?: unknown; failureEnvelope?: { raw?: unknown; mutationOutcome?: unknown; replayability?: unknown; nextAction?: unknown; code?: unknown; continuation?: { command?: unknown } } };
|
|
5606
5641
|
if (isRecord(value.failureEnvelope) && isRecord(value.failureEnvelope.raw)) {
|
|
@@ -7335,42 +7370,50 @@ async function executeReviewControllerOperation(
|
|
|
7335
7370
|
} catch (error) {
|
|
7336
7371
|
return nativeOperationFailure(parameters.operation, error);
|
|
7337
7372
|
}
|
|
7373
|
+
let acknowledged: NativeReviewAcknowledgeApprovedOutcome | void;
|
|
7338
7374
|
try {
|
|
7339
7375
|
// gentle-ai #3947: the burn answers with one review-acknowledged/v1
|
|
7340
7376
|
// envelope bound to exactly this lineage, target, and revision, and
|
|
7341
7377
|
// the burn is reported from that envelope, never from a later
|
|
7342
7378
|
// STATUS. Every published release up to v2.5.0-rc.3 still burns in
|
|
7343
7379
|
// silence, and that result stays byte-identical.
|
|
7344
|
-
|
|
7380
|
+
acknowledged = await acknowledgementCli.acknowledgeApproved({
|
|
7345
7381
|
argumentTokens,
|
|
7346
7382
|
cwd: defaultCwd,
|
|
7347
7383
|
binding: { lineageId: parameters.lineageId, targetIdentity: status.targetIdentity, revision: status.authority.revision },
|
|
7348
7384
|
...(signal === undefined ? {} : { signal }),
|
|
7349
7385
|
});
|
|
7350
|
-
clearRetainedNativeUntrackedSelection(retainedUntrackedSelections, defaultCwd, parameters.lineageId);
|
|
7351
|
-
// The registry owns restoring writability of its 0555 views before
|
|
7352
|
-
// removal; a terminal approved cleanup keeps the lineage projection.
|
|
7353
|
-
candidateViews?.cleanupTerminal(parameters.lineageId, "approved", defaultCwd);
|
|
7354
|
-
// gentle-pi#668: `closed` is never auto-derived or recorded here --
|
|
7355
|
-
// a parent that wants the on-path passes nativeReviewOutcome:
|
|
7356
|
-
// "closed" explicitly on its next assess call for this candidate.
|
|
7357
|
-
return {
|
|
7358
|
-
operation: parameters.operation,
|
|
7359
|
-
status: "closed",
|
|
7360
|
-
outcome: "native-approved-acknowledgement-completed",
|
|
7361
|
-
lineage_id: parameters.lineageId,
|
|
7362
|
-
target_identity: status.targetIdentity,
|
|
7363
|
-
...(acknowledged === undefined ? {} : { consumed_revision: acknowledged.consumedRevision }),
|
|
7364
|
-
authority: "burned",
|
|
7365
|
-
...(acknowledged === undefined ? {} : { burn_evidence: acknowledged.schema }),
|
|
7366
|
-
delivery: "ordinary-repository-policy",
|
|
7367
|
-
mutation_performed: true,
|
|
7368
|
-
mutation_outcome: "committed",
|
|
7369
|
-
};
|
|
7370
7386
|
} catch (error) {
|
|
7371
7387
|
if (!nativeMutationRequiresStatus(error)) return nativeOperationFailure(parameters.operation, error);
|
|
7372
7388
|
return await reconcileNativeMutationFailure(parameters.operation, error, acknowledgementCli, target, retainedUntrackedSelections);
|
|
7373
7389
|
}
|
|
7390
|
+
// gentle-ai#4003: from here the native burn is the committed authority
|
|
7391
|
+
// outcome. Both Pi-side teardown steps run outside the mutation-result
|
|
7392
|
+
// try/catch and each one is guarded on its own, so a cleanup failure is
|
|
7393
|
+
// reported as deferred cleanup and never as a failed acknowledgement
|
|
7394
|
+
// that would invite a replay of a burned operation.
|
|
7395
|
+
const retainedSelectionCleanup = deferredPostBurnCleanup(POST_BURN_CLEANUP.retainedSelection, () => clearRetainedNativeUntrackedSelection(retainedUntrackedSelections, defaultCwd, parameters.lineageId));
|
|
7396
|
+
// The registry owns restoring writability of its 0555 views before
|
|
7397
|
+
// removal; a terminal approved cleanup keeps the lineage projection.
|
|
7398
|
+
const candidateViewCleanup = deferredPostBurnCleanup(POST_BURN_CLEANUP.candidateView, () => candidateViews?.cleanupTerminal(parameters.lineageId, "approved", defaultCwd));
|
|
7399
|
+
// gentle-pi#668: `closed` is never auto-derived or recorded here --
|
|
7400
|
+
// a parent that wants the on-path passes nativeReviewOutcome:
|
|
7401
|
+
// "closed" explicitly on its next assess call for this candidate.
|
|
7402
|
+
return {
|
|
7403
|
+
operation: parameters.operation,
|
|
7404
|
+
status: "closed",
|
|
7405
|
+
outcome: "native-approved-acknowledgement-completed",
|
|
7406
|
+
lineage_id: parameters.lineageId,
|
|
7407
|
+
target_identity: status.targetIdentity,
|
|
7408
|
+
...(acknowledged === undefined ? {} : { consumed_revision: acknowledged.consumedRevision }),
|
|
7409
|
+
authority: "burned",
|
|
7410
|
+
...(acknowledged === undefined ? {} : { burn_evidence: acknowledged.schema }),
|
|
7411
|
+
delivery: "ordinary-repository-policy",
|
|
7412
|
+
mutation_performed: true,
|
|
7413
|
+
mutation_outcome: "committed",
|
|
7414
|
+
...(retainedSelectionCleanup === undefined ? {} : { retained_selection_cleanup: retainedSelectionCleanup }),
|
|
7415
|
+
...(candidateViewCleanup === undefined ? {} : { candidate_view_cleanup: candidateViewCleanup }),
|
|
7416
|
+
};
|
|
7374
7417
|
}
|
|
7375
7418
|
if (parameters.operation === REVIEW_CONTROLLER_OPERATION.ANSWER_CONSENT) {
|
|
7376
7419
|
const input = parseControllerJson(requiredControllerString(parameters, "input"), parameters.operation);
|
package/lib/agents-history.ts
CHANGED
|
@@ -16,7 +16,13 @@ export function remediationUnresolved(task: TaskRecord): boolean {
|
|
|
16
16
|
const state = task.sddRemediation;
|
|
17
17
|
if (!state) return false;
|
|
18
18
|
if (state.acquireUncertain || state.settlementUncertain) return true;
|
|
19
|
-
|
|
19
|
+
// A received settlement is a definite native outcome, whatever its state
|
|
20
|
+
// (including "blocked"): it is terminal task history, never local
|
|
21
|
+
// ambiguity. Native admission is the sole authority over any later
|
|
22
|
+
// attempt for the same cwd/change; only genuinely uncertain outcomes, or
|
|
23
|
+
// no settlement at all with a still-retained token/claimed actor, are
|
|
24
|
+
// unresolved.
|
|
25
|
+
if (state.settlement) return false;
|
|
20
26
|
return !!state.token || !!state.actorClaimed || !["blocked", "complete"].includes(state.acquireResult?.state ?? "");
|
|
21
27
|
}
|
|
22
28
|
|
package/lib/native-review-cli.ts
CHANGED
|
@@ -971,6 +971,15 @@ export const NATIVE_CLI_CONTRACTS = Object.freeze({
|
|
|
971
971
|
// this row repeats 2.8.0 exactly. riskEvidence and hint remain dark
|
|
972
972
|
// because neither is proven to reach the negotiated START path Pi consumes.
|
|
973
973
|
"2.8.1": Object.freeze({ start: true, finalize: true, validate: true, bindSdd: true, status: true, inventory: true, reclaim: true, recover: true, abandon: true, quarantineLegacy: true, reconcileAuthority: true, repairLegacyAlias: true, mode: true, riskEvidence: false, hint: false, delivery: true }),
|
|
974
|
+
// v2.8.2 shipped OpenCode SDD preflight plugin fixes, community-tools RTK
|
|
975
|
+
// acquisition, and Claude Code Stop telemetry. The provider contract semver
|
|
976
|
+
// stays 1.2.0; the same pin re-mirrors bundle bytes that had drifted under
|
|
977
|
+
// that semver (lens inspection.status "unavailable", targeted-validator
|
|
978
|
+
// regressions/inspection members, seven Pi stop reason codes). None of
|
|
979
|
+
// those touch the closed START/STATUS fields this row negotiates, so it
|
|
980
|
+
// repeats 2.8.1 exactly. riskEvidence and hint remain dark because neither
|
|
981
|
+
// is proven to reach the negotiated START path Pi consumes.
|
|
982
|
+
"2.8.2": Object.freeze({ start: true, finalize: true, validate: true, bindSdd: true, status: true, inventory: true, reclaim: true, recover: true, abandon: true, quarantineLegacy: true, reconcileAuthority: true, repairLegacyAlias: true, mode: true, riskEvidence: false, hint: false, delivery: true }),
|
|
974
983
|
});
|
|
975
984
|
|
|
976
985
|
export interface NativeReviewProcessDiagnostics {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gentle-pi",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.2",
|
|
4
4
|
"description": "Turn Pi into el Gentleman: a senior-architect development harness with SDD/OpenSpec, subagents, strict TDD evidence, review guardrails, and skill discovery.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -972,6 +972,15 @@ export const NATIVE_CLI_CONTRACTS = Object.freeze({
|
|
|
972
972
|
// this row repeats 2.8.0 exactly. riskEvidence and hint remain dark
|
|
973
973
|
// because neither is proven to reach the negotiated START path Pi consumes.
|
|
974
974
|
"2.8.1": Object.freeze({ start: true, finalize: true, validate: true, bindSdd: true, status: true, inventory: true, reclaim: true, recover: true, abandon: true, quarantineLegacy: true, reconcileAuthority: true, repairLegacyAlias: true, mode: true, riskEvidence: false, hint: false, delivery: true }),
|
|
975
|
+
// v2.8.2 shipped OpenCode SDD preflight plugin fixes, community-tools RTK
|
|
976
|
+
// acquisition, and Claude Code Stop telemetry. The provider contract semver
|
|
977
|
+
// stays 1.2.0; the same pin re-mirrors bundle bytes that had drifted under
|
|
978
|
+
// that semver (lens inspection.status "unavailable", targeted-validator
|
|
979
|
+
// regressions/inspection members, seven Pi stop reason codes). None of
|
|
980
|
+
// those touch the closed START/STATUS fields this row negotiates, so it
|
|
981
|
+
// repeats 2.8.1 exactly. riskEvidence and hint remain dark because neither
|
|
982
|
+
// is proven to reach the negotiated START path Pi consumes.
|
|
983
|
+
"2.8.2": Object.freeze({ start: true, finalize: true, validate: true, bindSdd: true, status: true, inventory: true, reclaim: true, recover: true, abandon: true, quarantineLegacy: true, reconcileAuthority: true, repairLegacyAlias: true, mode: true, riskEvidence: false, hint: false, delivery: true }),
|
|
975
984
|
});
|
|
976
985
|
|
|
977
986
|
|
|
@@ -36,7 +36,7 @@ const WINDOWS_SYSTEM_ROOT = "C:\\Windows";
|
|
|
36
36
|
// version check below) derives from this constant instead of repeating the
|
|
37
37
|
// literal, so a pin bump cannot leave a stale copy behind. See
|
|
38
38
|
// scripts/install-gentle-ai.mjs for the incident that motivated this.
|
|
39
|
-
export const INSTALLER_VERSION = "2.8.
|
|
39
|
+
export const INSTALLER_VERSION = "2.8.2";
|
|
40
40
|
export const RELEASE_BASE_URL = `https://github.com/Gentleman-Programming/gentle-ai/releases/download/v${INSTALLER_VERSION}/`;
|
|
41
41
|
export const GENTLE_AI_INSTALL_METHOD = Object.freeze({
|
|
42
42
|
SIGNED_RELEASE_ASSET: "signed-release-asset",
|
|
@@ -45,10 +45,10 @@ export const GENTLE_AI_INSTALL_METHOD = Object.freeze({
|
|
|
45
45
|
export const GENTLE_AI_WINDOWS_SOURCE_PACKAGE_PATH = "github.com/gentleman-programming/gentle-ai/v2/cmd/gentle-ai";
|
|
46
46
|
export const GENTLE_AI_WINDOWS_SOURCE_MODULE = "github.com/gentleman-programming/gentle-ai/v2";
|
|
47
47
|
export const GENTLE_AI_WINDOWS_SOURCE_TAG = `v${INSTALLER_VERSION}`;
|
|
48
|
-
// `go mod download -json github.com/gentleman-programming/gentle-ai/v2@v2.8.
|
|
48
|
+
// `go mod download -json github.com/gentleman-programming/gentle-ai/v2@v2.8.2`
|
|
49
49
|
// with GOSUMDB=sum.golang.org reports this exact module SumDB checksum, and the
|
|
50
|
-
// tag resolves to commit
|
|
51
|
-
export const GENTLE_AI_WINDOWS_SOURCE_MODULE_CHECKSUM = "h1:
|
|
50
|
+
// tag resolves to commit e3f53de6, the published v2.8.2 release head.
|
|
51
|
+
export const GENTLE_AI_WINDOWS_SOURCE_MODULE_CHECKSUM = "h1:54VJ0ruRiPc6MbNw4iFmlcBkQFOyF5D8iHY0A54Ivug=";
|
|
52
52
|
export const GENTLE_AI_WINDOWS_SOURCE_PACKAGE = `${GENTLE_AI_WINDOWS_SOURCE_PACKAGE_PATH}@${GENTLE_AI_WINDOWS_SOURCE_TAG}`;
|
|
53
53
|
export const GENTLE_AI_WINDOWS_MINIMUM_GO_VERSION = "1.25.10";
|
|
54
54
|
export const GENTLE_AI_GO_TOOLCHAIN_UNAVAILABLE_CODE = "GENTLE_AI_GO_TOOLCHAIN_UNAVAILABLE";
|
|
@@ -67,7 +67,7 @@ export class GentleAiInstallerError extends Error {
|
|
|
67
67
|
// Sentinel used while a re-pinned gentle-ai release is not yet published. A
|
|
68
68
|
// sentinel digest can never match a real SHA-256, so installation fails closed,
|
|
69
69
|
// and verify-package-files.mjs refuses to pack/publish while any digest below
|
|
70
|
-
// still holds it. The v2.8.
|
|
70
|
+
// still holds it. The v2.8.2 digests are pinned from the published release:
|
|
71
71
|
// archive sha256 values verified against the minisign-signed checksums.txt and
|
|
72
72
|
// freshly computed hashes; binary sha256 values computed from the extracted
|
|
73
73
|
// executables.
|
|
@@ -109,15 +109,15 @@ async function downloadPinnedGentleAiAsset(asset, destination, options) {
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
// Windows is absent from signed release archives on purpose. gentle-ai stopped
|
|
112
|
-
// distributing unsigned Windows builds in c4b764d0, so v2.8.
|
|
112
|
+
// distributing unsigned Windows builds in c4b764d0, so v2.8.2 publishes signed
|
|
113
113
|
// Darwin/Linux archives only. Windows x64/arm64 uses the separately verified
|
|
114
114
|
// exact-tag Go SumDB source-build path below; restore archive rows only when
|
|
115
115
|
// upstream ships signed Windows assets.
|
|
116
116
|
export const GENTLE_AI_RELEASE_ASSETS = Object.freeze({
|
|
117
|
-
"darwin/amd64": asset("gentle-ai_2.8.
|
|
118
|
-
"darwin/arm64": asset("gentle-ai_2.8.
|
|
119
|
-
"linux/amd64": asset("gentle-ai_2.8.
|
|
120
|
-
"linux/arm64": asset("gentle-ai_2.8.
|
|
117
|
+
"darwin/amd64": asset("gentle-ai_2.8.2_darwin_amd64.tar.gz", "0daa28897e6e54ce584f12ccefebf0d0df84e4ea8fbbd3a07e596ca82b079fa2", "17069156869ceda8e23eaa4fe5d7565cd57c1d78528f121dabba7301b82a0c14", "gentle-ai"),
|
|
118
|
+
"darwin/arm64": asset("gentle-ai_2.8.2_darwin_arm64.tar.gz", "12265017e0fb6d5dd1ddb1751f188fa8c47d95a95d7c7515ae174394da5f6e97", "491542e4b60e432048d4074f21c1b04417b980cf77eb34cd0a2e7447ca57dd77", "gentle-ai"),
|
|
119
|
+
"linux/amd64": asset("gentle-ai_2.8.2_linux_amd64.tar.gz", "5b95b184606168685a4ff576c103b051ceb23346a7f81ba557e047fa4d744146", "a55f4d2e114128866810c25195e5efecdded4502660e9a9c35c0b7a41c909dd8", "gentle-ai"),
|
|
120
|
+
"linux/arm64": asset("gentle-ai_2.8.2_linux_arm64.tar.gz", "a33c91ca0f5c5c85a4fd69f5169138089eb53e0a92c6ab80de5094d0688debb7", "e2759aca09ffe97638e984491319e43c9477d1ae117726ecbdf20d29d44c8950", "gentle-ai"),
|
|
121
121
|
});
|
|
122
122
|
|
|
123
123
|
// A pinned asset is either a signed archive or, for a prerelease pin only,
|
|
@@ -340,7 +340,7 @@ async function main() {
|
|
|
340
340
|
});
|
|
341
341
|
|
|
342
342
|
if (driftedContracts.length > 0) {
|
|
343
|
-
console.error("gentle-pi packaged review-integration/v1 and review-integration/v2 contract bytes drifted from the pinned v2.8.
|
|
343
|
+
console.error("gentle-pi packaged review-integration/v1 and review-integration/v2 contract bytes drifted from the pinned v2.8.2 runtime's vendored Gentle AI contract artifacts:");
|
|
344
344
|
for (const drift of driftedContracts) console.error(`- ${drift.relativePath}: expected ${drift.expected}, got ${drift.actual}`);
|
|
345
345
|
process.exit(1);
|
|
346
346
|
}
|
|
@@ -385,7 +385,7 @@ async function main() {
|
|
|
385
385
|
process.exit(1);
|
|
386
386
|
}
|
|
387
387
|
|
|
388
|
-
console.log(`gentle-pi package resource check passed (${requiredPaths.length} files; ${Object.keys(contractHashes).length} exact byte-pinned contract artifacts for the v2.8.
|
|
388
|
+
console.log(`gentle-pi package resource check passed (${requiredPaths.length} files; ${Object.keys(contractHashes).length} exact byte-pinned contract artifacts for the v2.8.2 runtime).`);
|
|
389
389
|
}
|
|
390
390
|
|
|
391
391
|
const isMainModule = process.argv[1] !== undefined && import.meta.url === pathToFileURL(process.argv[1]).href;
|
|
@@ -2160,3 +2160,25 @@ test("R3/R4 host reload refuses retained acquire/actor uncertainty without anoth
|
|
|
2160
2160
|
await h.fire("session_shutdown", ctx);
|
|
2161
2161
|
}
|
|
2162
2162
|
});
|
|
2163
|
+
|
|
2164
|
+
test("R3/R4 a known native-blocked settlement lets native admission decide the next attempt; an uncertain one still refuses locally", async () => {
|
|
2165
|
+
for (const uncertain of [false, true]) {
|
|
2166
|
+
const h = fakePi(), runtime = deps(), fixtureHome = join(root, `remediation-settlement-${uncertain}`);
|
|
2167
|
+
mkdirSync(join(fixtureHome, ".pi", "agent", "agents"), { recursive: true });
|
|
2168
|
+
writeFileSync(join(fixtureHome, ".pi", "agent", "agents", "sdd-remediate.md"), readFileSync("assets/agents/sdd-remediate.md"));
|
|
2169
|
+
const revision = `sha256:${"a".repeat(64)}`;
|
|
2170
|
+
const acquire = { workspaceRoot: cwd, changeName: "alpha", requestId: "retained", workUnit: "correct", evidenceGoal: "Observed correction", remediatesEvidenceRevision: revision };
|
|
2171
|
+
await saveTask(historyDir(fixtureHome), { id: "retained", agent: "sdd-remediate", cwd, status: "failed", createdAt: 1, sddRemediation: uncertain
|
|
2172
|
+
? { acquire, settlementUncertain: true, settle: { requestId: "exact" } }
|
|
2173
|
+
: { acquire, settlement: { state: "blocked", reason: "maintainer_decision" } } } as never, emptyThread());
|
|
2174
|
+
let acquisitions = 0, confirmations = 0;
|
|
2175
|
+
gentleAgents(h.pi, {}, { ...runtime.deps, home: fixtureHome, nativeSdd: { sddStatus: async () => ({ schemaName: "gentle-ai.sdd-status", schemaVersion: 2, changeName: "alpha", artifactStore: "openspec", planningHome: { mode: "repo-local", path: join(cwd, "openspec") }, changeRoot: join(cwd, "openspec/changes/alpha"), actionContext: { mode: "repo-local", workspaceRoot: cwd, allowedEditRoots: [cwd] }, dependencies: Object.fromEntries(["proposal", "specs", "design", "tasks", "apply", "verify", "archive"].map(key => [key, "ready"])), phaseInstructions: { apply: [], verify: [], remediate: ["Correct evidence"], archive: [] }, blockedReasons: [], nextRecommended: "remediate", remediationState: { required: true, complete: false, failedEvidenceRevision: revision } }), sddAttemptSettle: async () => ({ state: "proceed" as const }), sddAttemptAcquire: async () => { acquisitions++; return { state: "blocked" }; } } as unknown as NativeReviewCli });
|
|
2176
|
+
const { ctx } = fakeContext(fakeTui, async () => { confirmations++; return true; });
|
|
2177
|
+
await h.fire("session_start", ctx);
|
|
2178
|
+
await assert.rejects(h.tools.get("subagent_run").execute("again", { agent: "sdd-remediate", task: "Correct alpha", context: PARENT_CONFIRMED_SDD_CONTEXT, mode: "background", sdd_change: { changeName: "alpha", workspaceRoot: cwd, phase: "remediate", failedEvidenceRevision: revision }, remediation: { attempt: { ...acquire, requestId: "different" }, plan: { cwd, commands: ["pnpm test"], runtimeHarness: { naReason: "Not applicable because this fixture has no runtime boundary." }, rollback: { boundary: "Revert fixture", command: "git diff --check" } } } }, undefined, undefined, ctx), uncertain ? /reconcile exact history without actor replay/ : /no actor started/);
|
|
2179
|
+
assert.equal(acquisitions, uncertain ? 0 : 1, "native admission is consulted once local unresolved history is not uncertain");
|
|
2180
|
+
assert.equal(confirmations, uncertain ? 0 : 1);
|
|
2181
|
+
assert.equal(runtime.spawned.length, 0);
|
|
2182
|
+
await h.fire("session_shutdown", ctx);
|
|
2183
|
+
}
|
|
2184
|
+
});
|
|
@@ -97,7 +97,7 @@ async function writeWindowsSourceBinary(packageRoot: string): Promise<{ binaryPa
|
|
|
97
97
|
method: "go-sumdb-source-build",
|
|
98
98
|
package: "github.com/gentleman-programming/gentle-ai/v2/cmd/gentle-ai",
|
|
99
99
|
module: "github.com/gentleman-programming/gentle-ai/v2",
|
|
100
|
-
tag: "v2.8.
|
|
100
|
+
tag: "v2.8.2",
|
|
101
101
|
architecture: process.arch === "x64" ? "x64" : "arm64",
|
|
102
102
|
binarySha256: createHash("sha256").update(binary).digest("hex"),
|
|
103
103
|
moduleChecksum: GENTLE_AI_WINDOWS_SOURCE_MODULE_CHECKSUM,
|