gentle-pi 2.1.2 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +108 -79
- 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 -3
- package/assets/agents/review-reliability.md +4 -3
- package/assets/agents/review-resilience.md +4 -3
- package/assets/agents/review-risk.md +4 -3
- package/assets/agents/sdd-apply.md +11 -4
- 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 +8 -1
- package/assets/agents/sdd-research.md +54 -0
- package/assets/agents/sdd-spec.md +6 -1
- package/assets/agents/sdd-status.md +10 -5
- package/assets/agents/sdd-sync.md +6 -1
- package/assets/agents/sdd-tasks.md +8 -4
- package/assets/agents/sdd-verify.md +27 -2
- package/assets/chains/4r-review.chain.md +2 -0
- package/assets/chains/sdd-full.chain.md +2 -2
- package/assets/chains/sdd-plan.chain.md +1 -1
- package/assets/chains/sdd-verify.chain.md +2 -2
- package/assets/orchestrator-delegation.md +145 -160
- package/assets/orchestrator-memory.md +2 -0
- package/assets/orchestrator.md +25 -48
- package/assets/sdd-orchestrator-workflow.md +163 -25
- package/assets/support/sdd-status-contract.md +24 -6
- 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/v1/schemas/transition-execution.schema.json +42 -0
- 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/last-event-closure.schema.json +66 -0
- package/contracts/review-integration/v2/schemas/opencode-provider-role.schema.json +14 -0
- 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 +14 -16
- package/docs/review-integration.md +27 -353
- package/extensions/ask-user-choice.ts +151 -0
- package/extensions/gentle-ai.ts +2710 -3211
- package/extensions/quiet-tools.ts +515 -32
- package/extensions/sdd-init.ts +21 -12
- package/extensions/skill-registry.ts +10 -2
- package/extensions/startup-banner.ts +10 -4
- package/lib/gentle-ai-binary.ts +173 -2
- package/lib/gentle-ai-renderer.ts +70 -0
- package/lib/model-routing-authority.ts +133 -0
- package/lib/native-review-cli.ts +676 -781
- package/lib/opaque-pi-reviewer-adapter.ts +284 -0
- package/lib/provider-contract-bundle.ts +704 -0
- package/lib/review-candidate-view.ts +836 -118
- package/lib/review-compact-contract.ts +59 -248
- package/lib/review-host-relay.ts +578 -0
- package/lib/review-integration-v2.ts +1254 -221
- package/lib/review-last-event-controller.ts +35 -0
- package/lib/review-relay-contract.ts +16 -0
- package/lib/sdd-preflight.ts +230 -67
- package/lib/sdd-status.ts +66 -111
- package/lib/terminal-theme.ts +1 -1
- package/package.json +83 -79
- package/runtime/gentle-ai-binary.mjs +174 -3
- package/runtime/native-review-cli.mjs +610 -715
- package/runtime/review-integration-v2.mjs +1223 -190
- package/runtime/review-relay-contract.mjs +17 -0
- package/scripts/{build-git-commit-transaction-runner.mjs → build-runtime-modules.mjs} +5 -5
- package/scripts/check-provider-contract.mjs +138 -0
- package/scripts/gentle-ai-installer.mjs +85 -22
- package/scripts/maintainer/provider-relay-matrix.mjs +403 -0
- package/scripts/mirror-provider-contract.mjs +143 -0
- package/scripts/test-packed-runner.mjs +20 -9
- package/scripts/verify-package-files.mjs +119 -43
- package/skills/_shared/review-ledger-contract.md +11 -19
- 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 +94 -168
- package/skills/judgment-day/SKILL.md +9 -5
- package/skills/judgment-day/references/prompts-and-formats.md +2 -0
- package/skills/rdd-defect-workflow/SKILL.md +54 -0
- 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/background-subagents.test.ts +771 -0
- package/tests/codegraph-tools.test.ts +3 -3
- package/tests/crosslane/cross-lane.mjs +16 -0
- package/tests/delegated-key-learnings-contract.test.ts +240 -0
- package/tests/devbinary/native-review-parity.devtest.ts +167 -250
- package/tests/devbinary/pi-host-relay.devtest.ts +867 -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/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/result-artifact-v2-path.captured.json +12 -0
- package/tests/fixtures/devbinary/result-artifact-v2.captured.json +12 -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-consent-declined.captured.json +19 -0
- package/tests/fixtures/devbinary/start-v3-consent-granted.captured.json +109 -0
- package/tests/fixtures/devbinary/start-v3-zero-lens-closed.captured.json +21 -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/native-review-cli/v2.5.0-rc.1/PROVENANCE.txt +15 -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 +83 -13
- package/tests/gentle-ai-dev-binary-surfacing.test.ts +195 -0
- package/tests/gentle-ai-dev-binary.test.ts +159 -0
- package/tests/gentle-ai-installer.test.ts +138 -48
- package/tests/gentle-ai.test.ts +820 -131
- package/tests/gentle-theme.test.ts +133 -0
- package/tests/maintainer/provider-relay.maintest.ts +601 -0
- package/tests/model-routing-authority.test.ts +257 -0
- package/tests/native-review-capability-contract.test.ts +75 -2
- package/tests/native-review-cli.test.ts +588 -908
- package/tests/native-review-consent.test.ts +283 -38
- package/tests/native-review-parity-runtime.test.ts +108 -350
- package/tests/native-review-parity.test.ts +684 -732
- package/tests/native-sdd-attempt-authority.test.ts +235 -0
- package/tests/opaque-pi-reviewer-adapter.test.ts +266 -0
- package/tests/orchestrator-budget.test.ts +158 -89
- package/tests/orchestrator-rdd-ownership.test.ts +103 -0
- package/tests/package-manifest.test.ts +128 -100
- 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 +252 -0
- package/tests/quiet-tool-rendering.test.ts +1055 -28
- package/tests/review-actor-tool-deny.test.ts +12 -13
- package/tests/review-authority-recovery-docs.test.ts +1 -2
- package/tests/review-candidate-view.test.ts +898 -12
- package/tests/review-compact-contract.test.ts +29 -122
- package/tests/review-controller-lock-status.test.ts +2 -2
- package/tests/review-controller-native-recovery.test.ts +366 -857
- package/tests/review-controller-native-routing.test.ts +1253 -4199
- package/tests/review-controller-retired-ops.test.ts +1 -1
- package/tests/review-controller-workspace-root.test.ts +236 -70
- package/tests/review-controller.test.ts +26 -816
- package/tests/review-corrected-finalize-binding.test.ts +134 -0
- package/tests/review-dispatch-hydration-gap.test.ts +145 -0
- 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 +352 -0
- package/tests/review-host-relay.test.ts +754 -0
- package/tests/review-integration-v2-forward.test.ts +654 -0
- package/tests/review-integration-v2.test.ts +317 -129
- package/tests/review-last-event-closure.test.ts +408 -0
- package/tests/review-ledger-contract.test.ts +106 -60
- package/tests/review-recovered-lineage-routing.test.ts +199 -0
- package/tests/review-relay-transport-agent.test.ts +322 -0
- package/tests/review-snapshot.test.ts +3 -2
- package/tests/runtime-harness.mjs +573 -180
- package/tests/sdd-agent-tools.test.ts +53 -32
- package/tests/sdd-preflight.test.ts +81 -15
- package/tests/sdd-status.test.ts +109 -110
- package/tests/skill-collision-prefixes.test.ts +6 -8
- package/tests/skill-registry.test.ts +50 -1
- package/tests/verify-package-files.test.ts +62 -0
- package/tests/writer-edit-surface-scope.test.ts +230 -0
- package/themes/Gentleman-Cute.json +94 -0
- package/themes/Gentleman-Sexy.json +92 -0
- package/assets/agents/review-refuter.md +0 -40
- package/assets/agents/review-validator.md +0 -23
- package/lib/git-commit-transaction.ts +0 -801
- 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/runtime/git-commit-transaction.mjs +0 -802
- package/scripts/run-git-commit-transaction.mjs +0 -35
- 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/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 -302
- package/tests/review-compact.test.ts +0 -243
- package/tests/review-refuter-adapter.test.ts +0 -89
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
// Generated by scripts/build-
|
|
1
|
+
// Generated by scripts/build-runtime-modules.mjs. Do not edit.
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
|
-
import { existsSync, lstatSync, readFileSync } from "node:fs";
|
|
3
|
+
import { existsSync, lstatSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { homedir } from "node:os";
|
|
4
5
|
import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
5
6
|
import {
|
|
6
7
|
GENTLE_AI_INSTALL_METHOD,
|
|
@@ -8,6 +9,7 @@ import {
|
|
|
8
9
|
GENTLE_AI_WINDOWS_SOURCE_MODULE_CHECKSUM,
|
|
9
10
|
GENTLE_AI_WINDOWS_SOURCE_PACKAGE_PATH,
|
|
10
11
|
GENTLE_AI_WINDOWS_SOURCE_TAG,
|
|
12
|
+
INSTALLER_VERSION,
|
|
11
13
|
isGentleAiWindowsGoVersionSupported,
|
|
12
14
|
isWindowsGoSumdbSourceTarget,
|
|
13
15
|
resolveGentleAiReleaseAsset,
|
|
@@ -15,7 +17,10 @@ import {
|
|
|
15
17
|
import { fileURLToPath } from "node:url";
|
|
16
18
|
|
|
17
19
|
export const GENTLE_AI_BINARY_MISSING_CODE = "package-local-binary-missing";
|
|
18
|
-
|
|
20
|
+
// Derived from the one authoritative pinned version in
|
|
21
|
+
// scripts/gentle-ai-installer.mjs rather than repeating the literal here, so
|
|
22
|
+
// the two can never independently drift apart the way they once did.
|
|
23
|
+
export const GENTLE_AI_VERSION = INSTALLER_VERSION;
|
|
19
24
|
|
|
20
25
|
export class PackageLocalGentleAiBinaryMissingError extends Error {
|
|
21
26
|
code = GENTLE_AI_BINARY_MISSING_CODE;
|
|
@@ -43,6 +48,165 @@ function sha256(value ) {
|
|
|
43
48
|
return createHash("sha256").update(value).digest("hex");
|
|
44
49
|
}
|
|
45
50
|
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
// Dev-binary override — the maintainer field-test lane.
|
|
53
|
+
//
|
|
54
|
+
// Two explicit activation paths, in precedence order:
|
|
55
|
+
// 1. GENTLE_PI_GENTLE_AI_DEV_BINARY (session override, absolute path), then
|
|
56
|
+
// 2. the persistent registration file at
|
|
57
|
+
// <GENTLE_PI_CONFIG_HOME|~/.pi/gentle-ai>/dev-binary.json with the strict
|
|
58
|
+
// shape {"schema":"gentle-pi.dev-binary/v1","path":"<absolute path>"}.
|
|
59
|
+
//
|
|
60
|
+
// The registration deliberately pins no digest: it is the unpinned field-test
|
|
61
|
+
// mode, and the binary at that path changes on every rebuild. Every resolution
|
|
62
|
+
// re-validates the file and recomputes the sha256, so a rebuilt binary is
|
|
63
|
+
// followed automatically with a fresh digest and no re-registration.
|
|
64
|
+
//
|
|
65
|
+
// Guardrails per resolution: absolute path, regular non-symlink file, POSIX
|
|
66
|
+
// executable. Any failure — including a malformed registration document or a
|
|
67
|
+
// registered-but-missing binary — is a typed error naming its origin, never a
|
|
68
|
+
// silent fallback to the pinned binary: silently running the pin while the
|
|
69
|
+
// maintainer believes he is field-testing main is the worst possible outcome.
|
|
70
|
+
// With neither activation path present, the pinned supply-chain resolution
|
|
71
|
+
// below stays byte-identical.
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
|
|
74
|
+
export const GENTLE_AI_DEV_BINARY_ENV = "GENTLE_PI_GENTLE_AI_DEV_BINARY";
|
|
75
|
+
export const GENTLE_AI_DEV_BINARY_REGISTRATION_SCHEMA = "gentle-pi.dev-binary/v1";
|
|
76
|
+
export const GENTLE_AI_DEV_BINARY_OVERRIDE_INVALID_CODE = "dev-binary-override-invalid";
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
export class GentleAiDevBinaryOverrideError extends Error {
|
|
92
|
+
code = GENTLE_AI_DEV_BINARY_OVERRIDE_INVALID_CODE;
|
|
93
|
+
source ;
|
|
94
|
+
origin ;
|
|
95
|
+
constructor(source , origin , reason ) {
|
|
96
|
+
super(`${GENTLE_AI_DEV_BINARY_OVERRIDE_INVALID_CODE}: ${origin} ${reason}. Fix or remove the override; the pinned binary is never used silently while an override is declared.`);
|
|
97
|
+
this.name = "GentleAiDevBinaryOverrideError";
|
|
98
|
+
this.source = source;
|
|
99
|
+
this.origin = origin;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
let devBinaryEnvironmentTestingOverlay ;
|
|
104
|
+
|
|
105
|
+
/** Testing-only environment overlay; production code never calls this. */
|
|
106
|
+
export function setGentleAiDevBinaryEnvironmentForTesting(environment ) {
|
|
107
|
+
devBinaryEnvironmentTestingOverlay = environment;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function ambientDevBinaryEnvironment() {
|
|
111
|
+
return devBinaryEnvironmentTestingOverlay ?? { env: process.env, home: homedir() };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function gentleAiDevBinaryRegistrationPath(environment = ambientDevBinaryEnvironment()) {
|
|
115
|
+
const configHome = environment.env.GENTLE_PI_CONFIG_HOME ?? join(environment.home, ".pi", "gentle-ai");
|
|
116
|
+
return join(configHome, "dev-binary.json");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function validateDevBinary(source , origin , path , platform ) {
|
|
120
|
+
if (typeof path !== "string" || path.length === 0) throw new GentleAiDevBinaryOverrideError(source, origin, "declares an empty dev binary path");
|
|
121
|
+
if (!isAbsolute(path)) throw new GentleAiDevBinaryOverrideError(source, origin, `must name an absolute path, received "${path}"`);
|
|
122
|
+
let details ;
|
|
123
|
+
try {
|
|
124
|
+
details = lstatSync(path);
|
|
125
|
+
} catch {
|
|
126
|
+
throw new GentleAiDevBinaryOverrideError(source, origin, `names "${path}", which does not exist`);
|
|
127
|
+
}
|
|
128
|
+
if (!details.isFile() || details.isSymbolicLink()) throw new GentleAiDevBinaryOverrideError(source, origin, `names "${path}", which is not a regular non-symlink file`);
|
|
129
|
+
if (platform !== "win32" && (details.mode & 0o111) === 0) throw new GentleAiDevBinaryOverrideError(source, origin, `names "${path}", which is not a POSIX executable`);
|
|
130
|
+
let digest ;
|
|
131
|
+
try {
|
|
132
|
+
digest = sha256(readFileSync(path));
|
|
133
|
+
} catch {
|
|
134
|
+
throw new GentleAiDevBinaryOverrideError(source, origin, `names "${path}", which could not be read`);
|
|
135
|
+
}
|
|
136
|
+
return { source, origin, path, sha256: digest };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function readDevBinaryRegistration(registrationPath ) {
|
|
140
|
+
let contents ;
|
|
141
|
+
try {
|
|
142
|
+
contents = readFileSync(registrationPath, "utf8");
|
|
143
|
+
} catch {
|
|
144
|
+
throw new GentleAiDevBinaryOverrideError("registration", registrationPath, "could not be read");
|
|
145
|
+
}
|
|
146
|
+
let parsed ;
|
|
147
|
+
try {
|
|
148
|
+
parsed = JSON.parse(contents);
|
|
149
|
+
} catch {
|
|
150
|
+
throw new GentleAiDevBinaryOverrideError("registration", registrationPath, "is not valid JSON");
|
|
151
|
+
}
|
|
152
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) throw new GentleAiDevBinaryOverrideError("registration", registrationPath, "must be a JSON object");
|
|
153
|
+
const record = parsed ;
|
|
154
|
+
const keys = Object.keys(record).sort();
|
|
155
|
+
if (keys.length !== 2 || keys[0] !== "path" || keys[1] !== "schema") throw new GentleAiDevBinaryOverrideError("registration", registrationPath, `must carry exactly the keys "schema" and "path"`);
|
|
156
|
+
if (record.schema !== GENTLE_AI_DEV_BINARY_REGISTRATION_SCHEMA) throw new GentleAiDevBinaryOverrideError("registration", registrationPath, `must declare schema ${GENTLE_AI_DEV_BINARY_REGISTRATION_SCHEMA}`);
|
|
157
|
+
if (typeof record.path !== "string" || record.path.length === 0) throw new GentleAiDevBinaryOverrideError("registration", registrationPath, "must declare a non-empty string path");
|
|
158
|
+
return record.path;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Resolves the active dev-binary override, if any. Returns undefined only when
|
|
163
|
+
* neither activation path is present; a present-but-invalid override always
|
|
164
|
+
* throws a typed GentleAiDevBinaryOverrideError naming its origin.
|
|
165
|
+
*/
|
|
166
|
+
export function resolveGentleAiDevBinaryOverride(
|
|
167
|
+
environment = ambientDevBinaryEnvironment(),
|
|
168
|
+
platform = process.platform,
|
|
169
|
+
) {
|
|
170
|
+
const envValue = environment.env[GENTLE_AI_DEV_BINARY_ENV];
|
|
171
|
+
if (envValue !== undefined && envValue.length > 0) return validateDevBinary("env", GENTLE_AI_DEV_BINARY_ENV, envValue, platform);
|
|
172
|
+
const registrationPath = gentleAiDevBinaryRegistrationPath(environment);
|
|
173
|
+
if (!existsSync(registrationPath)) return undefined;
|
|
174
|
+
return validateDevBinary("registration", registrationPath, readDevBinaryRegistration(registrationPath), platform);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Cheap presence probe: is a dev-binary override declared at all? Used by the
|
|
179
|
+
* native CLI to select the unpinned version gate without hashing the binary.
|
|
180
|
+
* Declared-but-invalid still counts as configured — the resolution path will
|
|
181
|
+
* fail loudly with the typed error instead of quietly using the pin.
|
|
182
|
+
*/
|
|
183
|
+
export function gentleAiDevBinaryOverrideConfigured(environment = ambientDevBinaryEnvironment()) {
|
|
184
|
+
const envValue = environment.env[GENTLE_AI_DEV_BINARY_ENV];
|
|
185
|
+
if (envValue !== undefined && envValue.length > 0) return true;
|
|
186
|
+
return existsSync(gentleAiDevBinaryRegistrationPath(environment));
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** Validates and persistently registers a dev binary; returns the fresh override. */
|
|
190
|
+
export function registerGentleAiDevBinary(
|
|
191
|
+
path ,
|
|
192
|
+
environment = ambientDevBinaryEnvironment(),
|
|
193
|
+
platform = process.platform,
|
|
194
|
+
) {
|
|
195
|
+
const registrationPath = gentleAiDevBinaryRegistrationPath(environment);
|
|
196
|
+
const validated = validateDevBinary("registration", registrationPath, path, platform);
|
|
197
|
+
mkdirSync(dirname(registrationPath), { recursive: true });
|
|
198
|
+
writeFileSync(registrationPath, `${JSON.stringify({ schema: GENTLE_AI_DEV_BINARY_REGISTRATION_SCHEMA, path })}\n`);
|
|
199
|
+
return { registrationPath, override: validated };
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** Deletes the persistent registration; returns whether one existed. */
|
|
203
|
+
export function unregisterGentleAiDevBinary(environment = ambientDevBinaryEnvironment()) {
|
|
204
|
+
const registrationPath = gentleAiDevBinaryRegistrationPath(environment);
|
|
205
|
+
if (!existsSync(registrationPath)) return false;
|
|
206
|
+
rmSync(registrationPath);
|
|
207
|
+
return true;
|
|
208
|
+
}
|
|
209
|
+
|
|
46
210
|
function isConfined(path , directory ) {
|
|
47
211
|
const relativePath = relative(directory, path);
|
|
48
212
|
return relativePath !== "" && !relativePath.startsWith("..") && !isAbsolute(relativePath);
|
|
@@ -107,7 +271,14 @@ export function resolveGentleAiBinary(
|
|
|
107
271
|
packageRoot = dirname(dirname(fileURLToPath(import.meta.url))),
|
|
108
272
|
platform = process.platform,
|
|
109
273
|
readBinary = readFileSync,
|
|
274
|
+
environment = ambientDevBinaryEnvironment(),
|
|
110
275
|
) {
|
|
276
|
+
// The explicit dev-binary override wins over the pinned supply-chain path.
|
|
277
|
+
// Its typed errors propagate: a declared override never falls back to the
|
|
278
|
+
// pin. Without a declared override this call returns undefined and the
|
|
279
|
+
// pinned resolution below is byte-identical to the pre-override behavior.
|
|
280
|
+
const override = resolveGentleAiDevBinaryOverride(environment, platform);
|
|
281
|
+
if (override !== undefined) return override.path;
|
|
111
282
|
const binaryPath = gentleAiBinaryPath(packageRoot, platform);
|
|
112
283
|
const versionDirectory = dirname(binaryPath);
|
|
113
284
|
const manifestPath = join(versionDirectory, "integrity.json");
|