create-principles-disciple 1.133.13 → 1.134.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/codex-adapter/package.json +3 -2
- package/console/dist/server/routes/update.js +181 -34
- package/console/dist/server/update/legacy-mutation-journal.d.ts +118 -0
- package/console/dist/server/update/legacy-mutation-journal.js +220 -0
- package/console/dist/server/utils/cli-smoke.d.ts +19 -0
- package/console/dist/server/utils/cli-smoke.js +60 -0
- package/console/dist/server/utils/installed-layout.d.ts +8 -0
- package/console/dist/server/utils/installed-layout.js +4 -0
- package/console/dist/ui/i18n/en.json +2 -2
- package/console/dist/ui/i18n/zh-CN.json +2 -2
- package/console/dist/web/assets/app.js +85 -15
- package/console/package.json +2 -2
- package/core/dist/runtime-v2/__tests__/recovery-sweep-service.test.js +130 -0
- package/core/dist/runtime-v2/__tests__/recovery-sweep-service.test.js.map +1 -1
- package/core/dist/runtime-v2/recovery-sweep-service.d.ts +9 -0
- package/core/dist/runtime-v2/recovery-sweep-service.d.ts.map +1 -1
- package/core/dist/runtime-v2/recovery-sweep-service.js +7 -2
- package/core/dist/runtime-v2/recovery-sweep-service.js.map +1 -1
- package/core/package.json +1 -1
- package/dist/installer.d.ts +69 -0
- package/dist/installer.d.ts.map +1 -1
- package/dist/installer.js +200 -14
- package/dist/installer.js.map +1 -1
- package/dist/uninstaller.d.ts.map +1 -1
- package/dist/uninstaller.js +7 -3
- package/dist/uninstaller.js.map +1 -1
- package/dist/update/install-layout.d.ts +39 -2
- package/dist/update/install-layout.d.ts.map +1 -1
- package/dist/update/install-layout.js +69 -3
- package/dist/update/install-layout.js.map +1 -1
- package/dist/update/release-manager-authority.d.ts +8 -0
- package/dist/update/release-manager-authority.d.ts.map +1 -1
- package/dist/update/release-manager-authority.js +26 -4
- package/dist/update/release-manager-authority.js.map +1 -1
- package/dist/update/release-metadata-source.d.ts +85 -0
- package/dist/update/release-metadata-source.d.ts.map +1 -0
- package/dist/update/release-metadata-source.js +102 -0
- package/dist/update/release-metadata-source.js.map +1 -0
- package/install-layout/dist/index.d.ts +8 -0
- package/install-layout/dist/index.js +1 -0
- package/install-layout/package.json +1 -1
- package/package.json +2 -2
- package/pd-cli/dist/commands/runtime-recovery-failed-tasks.d.ts.map +1 -1
- package/pd-cli/dist/commands/runtime-recovery-failed-tasks.js +82 -6
- package/pd-cli/dist/commands/runtime-recovery-failed-tasks.js.map +1 -1
- package/pd-cli/dist/index.js +6 -3
- package/pd-cli/dist/index.js.map +1 -1
- package/pd-cli/package.json +1 -1
- package/plugin/dist/bundle.js +44 -44
- package/plugin/dist/governance-audit.js +139 -139
- package/plugin/dist/rulehost-evidence.js +144 -144
- package/release-manager/dist/installer.d.ts +69 -0
- package/release-manager/dist/installer.d.ts.map +1 -1
- package/release-manager/dist/installer.js +200 -14
- package/release-manager/dist/installer.js.map +1 -1
- package/release-manager/dist/uninstaller.d.ts.map +1 -1
- package/release-manager/dist/uninstaller.js +7 -3
- package/release-manager/dist/uninstaller.js.map +1 -1
- package/release-manager/dist/update/install-layout.d.ts +39 -2
- package/release-manager/dist/update/install-layout.d.ts.map +1 -1
- package/release-manager/dist/update/install-layout.js +69 -3
- package/release-manager/dist/update/install-layout.js.map +1 -1
- package/release-manager/dist/update/release-manager-authority.d.ts +8 -0
- package/release-manager/dist/update/release-manager-authority.d.ts.map +1 -1
- package/release-manager/dist/update/release-manager-authority.js +26 -4
- package/release-manager/dist/update/release-manager-authority.js.map +1 -1
- package/release-manager/dist/update/release-metadata-source.d.ts +85 -0
- package/release-manager/dist/update/release-metadata-source.d.ts.map +1 -0
- package/release-manager/dist/update/release-metadata-source.js +102 -0
- package/release-manager/dist/update/release-metadata-source.js.map +1 -0
- package/release-manager/package.json +2 -2
|
@@ -17,6 +17,54 @@ export declare const CONVERSATION_ACCESS_CONFIG_KEY: 'allowConversationAccess';
|
|
|
17
17
|
export declare function ensureConversationAccess(config: Record<string, unknown>): Record<string, unknown>;
|
|
18
18
|
export declare function resolveConsolePortBase(): number;
|
|
19
19
|
export declare function mergeInstallManifestHosts(current: unknown, host: HostTarget): ('codex' | 'openclaw')[];
|
|
20
|
+
/**
|
|
21
|
+
* PRI-709 P0-2 — active record commit point (ADR-0024 D-2).
|
|
22
|
+
*
|
|
23
|
+
* `~/.pd/active.json` is the deployment identity source: it records WHAT is
|
|
24
|
+
* actually deployed, keyed to the transaction that deployed it. Before PRI-709
|
|
25
|
+
* the installer never wrote it (the only writer was legacy-migration.ts), so
|
|
26
|
+
* every real install and every ReleaseManager apply left active.json absent or
|
|
27
|
+
* stale — the PRI-698 audit finding F-2.
|
|
28
|
+
*
|
|
29
|
+
* Identity is taken from the transaction, never recomputed here: the journal
|
|
30
|
+
* was opened with the payload's own identity (`_release/manifest.json` digest
|
|
31
|
+
* when the self-contained asset ships one), and active.json must agree with
|
|
32
|
+
* the journal of the transaction that produced it. A divergent second
|
|
33
|
+
* computation would break the audit trail.
|
|
34
|
+
*
|
|
35
|
+
* Ordering: journal-first. The caller appends `confirmed` and only then calls
|
|
36
|
+
* this, so a crash between the two is recoverable from the journal (the
|
|
37
|
+
* reverse order would leave an unjournaled active.json).
|
|
38
|
+
*
|
|
39
|
+
* Failure policy — Tier 2: this runs AFTER the backup was discarded, so the
|
|
40
|
+
* install is already committed and must not be failed here. A write failure is
|
|
41
|
+
* reported loud (rc-9) and returned to the caller; it never bricks the
|
|
42
|
+
* installation.
|
|
43
|
+
*/
|
|
44
|
+
export interface ActiveRecordCommitResult {
|
|
45
|
+
readonly written: boolean;
|
|
46
|
+
readonly activeRecordPath: string;
|
|
47
|
+
readonly generation: number;
|
|
48
|
+
readonly previousReleaseId: string | null;
|
|
49
|
+
/** Set when the record could not be written or the previous one was unreadable. */
|
|
50
|
+
readonly reason?: string;
|
|
51
|
+
}
|
|
52
|
+
export declare function commitInstallerActiveRecord(journal: InstallerJournal): ActiveRecordCommitResult;
|
|
53
|
+
/**
|
|
54
|
+
* PRI-709 P0-1 — installer supply path for the release metadata source.
|
|
55
|
+
*
|
|
56
|
+
* The installer is the only component that legitimately knows the metadata
|
|
57
|
+
* repository at install time, so it persists `PD_RELEASE_METADATA_URL` into
|
|
58
|
+
* `~/.pd/install.json` (the durable `install_config` tier). Without this the
|
|
59
|
+
* variable had to be exported in every shell that wanted a governed update
|
|
60
|
+
* check (PRI-698 audit F-4).
|
|
61
|
+
*
|
|
62
|
+
* Absent env is a no-op — an install with no metadata source stays
|
|
63
|
+
* unconfigured rather than persisting a guessed URL. A malformed env value is
|
|
64
|
+
* reported and skipped: it must never be written into install.json, where the
|
|
65
|
+
* strict reader would then fail loud and mark the install corrupt.
|
|
66
|
+
*/
|
|
67
|
+
export declare function persistReleaseMetadataSource(): void;
|
|
20
68
|
/**
|
|
21
69
|
* 验证原生模块:better-sqlite3 随发布资产携带 prebuilt 二进制
|
|
22
70
|
* (prebuilds/*.node),node-gyp-build 在 require 时解析——无需(也没有)
|
|
@@ -161,6 +209,27 @@ export declare function ensureBundledPdCliResolution(pdCliRoot: string): void;
|
|
|
161
209
|
export declare function runLegacyRuleContractPreflight(pluginDir: string, workspaceDir: string, runScan?: LegacyRulePreflightRunner): Promise<LegacyRulePreflightOutcome>;
|
|
162
210
|
export declare function checkBuiltPlugin(pluginDir: string): Promise<void>;
|
|
163
211
|
export declare function installPluginToStaging(pluginDir: string, language: SkillLanguage): Promise<void>;
|
|
212
|
+
/**
|
|
213
|
+
* PRI-711: materialize node_modules links for the INSTALLED codex-adapter so
|
|
214
|
+
* its declared `file:../<component>` dependencies resolve under ESM realpath
|
|
215
|
+
* rules. The adapter's dist imports @principles/host-runtime and
|
|
216
|
+
* @principles/core, and pd-cli's eager import graph (health-codex) statically
|
|
217
|
+
* imports the adapter — without these links every pd command dies with
|
|
218
|
+
* ERR_MODULE_NOT_FOUND at startup (observed 2026-09-09: the 1.231.2 full
|
|
219
|
+
* update swapped in Slice-D pd-cli while the deployed adapter, laid down by
|
|
220
|
+
* older installers, had no node_modules at all).
|
|
221
|
+
*
|
|
222
|
+
* Data-driven from the deployed adapter manifest: every dependency whose ref
|
|
223
|
+
* starts with `file:../` names a sibling runtime component directory. An
|
|
224
|
+
* existing correct link is kept; a stale physical copy (self-contained
|
|
225
|
+
* payloads ship materialized node_modules) or a wrong-target link is
|
|
226
|
+
* replaced with the canonical junction/symlink, mirroring syncPdCli.
|
|
227
|
+
* Idempotent. MUST run after installBundledCodexAdapter AND the
|
|
228
|
+
* core/host-runtime/install-layout installs — the manifest declares all
|
|
229
|
+
* three as file:../ siblings, and a missing sibling means a corrupted
|
|
230
|
+
* payload or a call-order regression, which fails the install loudly.
|
|
231
|
+
*/
|
|
232
|
+
export declare function ensureCodexAdapterResolution(): void;
|
|
164
233
|
export interface InstallResult {
|
|
165
234
|
success: boolean;
|
|
166
235
|
workspaceDir: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAmBL,KAAK,eAAe,EACpB,KAAK,kBAAkB,EAExB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAqB,KAAK,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,KAAK,EAAsB,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAGnF,OAAO,EAA+B,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, readdirSync, statSync, readFileSync, writeFileSync, mkdirSync, rmSync, copyFileSync, cpSync, renameSync, chmodSync, symlinkSync } from 'fs';
|
|
1
|
+
import { existsSync, lstatSync, readdirSync, realpathSync, statSync, readFileSync, writeFileSync, mkdirSync, rmSync, copyFileSync, cpSync, renameSync, chmodSync, symlinkSync } from 'fs';
|
|
2
2
|
import { createHash, randomUUID } from 'node:crypto';
|
|
3
3
|
import { pathToFileURL } from 'node:url';
|
|
4
4
|
import fse from 'fs-extra';
|
|
@@ -16,7 +16,9 @@ import { mergeInstallManifestWorkspaces, parseInstallManifest } from '@principle
|
|
|
16
16
|
import { detectOpenClawMainWorkspaceDivergence } from './utils/workspace-divergence.js';
|
|
17
17
|
import { applySkillLanguageSelection } from './skill-language.js';
|
|
18
18
|
import { parseReleaseAssetIdentity, parseReleaseAssetManifest, ReleaseAssetManifestError, verifyReleaseAssetManifestAsync, verifyReleaseAssetTarget, } from './update/release-asset-manifest.js';
|
|
19
|
-
import {
|
|
19
|
+
import { mergeIntoInstallJson, readInstallJsonRecord, resolvePdHomePaths, } from './update/install-layout.js';
|
|
20
|
+
import { RELEASE_METADATA_URL_ENV, normalizeReleaseMetadataUrl } from './update/release-metadata-source.js';
|
|
21
|
+
import { appendJournalTransition, readActiveRecord, writeActiveRecord, } from './update/transaction-journal.js';
|
|
20
22
|
/** PRI-343: Keep in sync with @principles/core CONVERSATION_ACCESS_CONFIG_KEY */
|
|
21
23
|
export const CONVERSATION_ACCESS_CONFIG_KEY = 'allowConversationAccess';
|
|
22
24
|
function isRecord(value) {
|
|
@@ -155,7 +157,90 @@ function resolveInstallManifestWorkspaces(workspaceDir) {
|
|
|
155
157
|
}
|
|
156
158
|
function writeInstallManifest(hosts, workspaces) {
|
|
157
159
|
mkdirSync(getPdDir(), { recursive: true });
|
|
158
|
-
|
|
160
|
+
// PRI-709 P0-1: merge into the existing record. This file has more than one
|
|
161
|
+
// writer (the update side owns `channel` / `autoCheck` / `releaseMetadataUrl`);
|
|
162
|
+
// a wholesale replace silently deleted those fields.
|
|
163
|
+
const existing = readInstallJsonRecord(getInstallManifestPath());
|
|
164
|
+
const payload = {
|
|
165
|
+
...(existing ?? {}),
|
|
166
|
+
layoutVersion: 1,
|
|
167
|
+
mode: 'canonical',
|
|
168
|
+
hosts,
|
|
169
|
+
workspaces,
|
|
170
|
+
};
|
|
171
|
+
writeFileSync(getInstallManifestPath(), JSON.stringify(payload, null, 2) + '\n', 'utf8');
|
|
172
|
+
}
|
|
173
|
+
export function commitInstallerActiveRecord(journal) {
|
|
174
|
+
const paths = resolvePdHomePaths(getPdDir());
|
|
175
|
+
let previous = null;
|
|
176
|
+
let previousWarning = null;
|
|
177
|
+
try {
|
|
178
|
+
previous = readActiveRecord(paths.activeRecordPath);
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
// A corrupt previous record must not block committing the new identity —
|
|
182
|
+
// overwriting it with a valid record is strictly an improvement.
|
|
183
|
+
previousWarning = error instanceof Error ? error.message : String(error);
|
|
184
|
+
logger.warn(`active.json was unreadable and is being replaced (${paths.activeRecordPath}): ${previousWarning}`);
|
|
185
|
+
}
|
|
186
|
+
// Generation continuity: never move backwards. A standalone install already
|
|
187
|
+
// carries generation 1, but re-installing over an existing deployment must
|
|
188
|
+
// advance past it — otherwise the deployment identity source would regress.
|
|
189
|
+
const generation = Math.max(journal.generation, previous === null ? 1 : previous.generation + 1);
|
|
190
|
+
try {
|
|
191
|
+
writeActiveRecord(paths.activeRecordPath, {
|
|
192
|
+
generation,
|
|
193
|
+
releaseId: journal.releaseId,
|
|
194
|
+
releaseMetadataDigest: journal.releaseMetadataDigest,
|
|
195
|
+
previousReleaseId: previous?.releaseId ?? null,
|
|
196
|
+
transactionId: journal.transactionId,
|
|
197
|
+
productVersion: journal.productVersion,
|
|
198
|
+
});
|
|
199
|
+
return {
|
|
200
|
+
written: true,
|
|
201
|
+
activeRecordPath: paths.activeRecordPath,
|
|
202
|
+
generation,
|
|
203
|
+
previousReleaseId: previous?.releaseId ?? null,
|
|
204
|
+
...(previousWarning !== null ? { reason: `previous_record_unreadable: ${previousWarning}` } : {}),
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
catch (error) {
|
|
208
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
209
|
+
logger.error(`active.json could not be written after a committed install (${paths.activeRecordPath}): ${reason}. `
|
|
210
|
+
+ `Deployment identity is out of sync with the transaction ${journal.transactionId}; re-run the installer to repair it.`);
|
|
211
|
+
return {
|
|
212
|
+
written: false,
|
|
213
|
+
activeRecordPath: paths.activeRecordPath,
|
|
214
|
+
generation,
|
|
215
|
+
previousReleaseId: previous?.releaseId ?? null,
|
|
216
|
+
reason,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* PRI-709 P0-1 — installer supply path for the release metadata source.
|
|
222
|
+
*
|
|
223
|
+
* The installer is the only component that legitimately knows the metadata
|
|
224
|
+
* repository at install time, so it persists `PD_RELEASE_METADATA_URL` into
|
|
225
|
+
* `~/.pd/install.json` (the durable `install_config` tier). Without this the
|
|
226
|
+
* variable had to be exported in every shell that wanted a governed update
|
|
227
|
+
* check (PRI-698 audit F-4).
|
|
228
|
+
*
|
|
229
|
+
* Absent env is a no-op — an install with no metadata source stays
|
|
230
|
+
* unconfigured rather than persisting a guessed URL. A malformed env value is
|
|
231
|
+
* reported and skipped: it must never be written into install.json, where the
|
|
232
|
+
* strict reader would then fail loud and mark the install corrupt.
|
|
233
|
+
*/
|
|
234
|
+
export function persistReleaseMetadataSource() {
|
|
235
|
+
const raw = process.env[RELEASE_METADATA_URL_ENV];
|
|
236
|
+
if (raw === undefined || raw.trim().length === 0)
|
|
237
|
+
return;
|
|
238
|
+
const normalized = normalizeReleaseMetadataUrl(raw);
|
|
239
|
+
if (normalized === null) {
|
|
240
|
+
logger.warn(`${RELEASE_METADATA_URL_ENV} is not a valid http(s) URL and was not persisted to install.json: ${JSON.stringify(raw)}. Release metadata source stays unconfigured.`);
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
mergeIntoInstallJson(getInstallManifestPath(), { releaseMetadataUrl: normalized });
|
|
159
244
|
}
|
|
160
245
|
function installBundledLayoutPackage(pluginDir) {
|
|
161
246
|
const source = path.join(pluginDir, 'install-layout');
|
|
@@ -1444,6 +1529,85 @@ function installBundledCodexAdapter(pluginDir) {
|
|
|
1444
1529
|
rmSync(codexAdapterDest, { recursive: true, force: true });
|
|
1445
1530
|
cpSync(codexAdapterSrc, codexAdapterDest, { recursive: true });
|
|
1446
1531
|
}
|
|
1532
|
+
/**
|
|
1533
|
+
* PRI-711: materialize node_modules links for the INSTALLED codex-adapter so
|
|
1534
|
+
* its declared `file:../<component>` dependencies resolve under ESM realpath
|
|
1535
|
+
* rules. The adapter's dist imports @principles/host-runtime and
|
|
1536
|
+
* @principles/core, and pd-cli's eager import graph (health-codex) statically
|
|
1537
|
+
* imports the adapter — without these links every pd command dies with
|
|
1538
|
+
* ERR_MODULE_NOT_FOUND at startup (observed 2026-09-09: the 1.231.2 full
|
|
1539
|
+
* update swapped in Slice-D pd-cli while the deployed adapter, laid down by
|
|
1540
|
+
* older installers, had no node_modules at all).
|
|
1541
|
+
*
|
|
1542
|
+
* Data-driven from the deployed adapter manifest: every dependency whose ref
|
|
1543
|
+
* starts with `file:../` names a sibling runtime component directory. An
|
|
1544
|
+
* existing correct link is kept; a stale physical copy (self-contained
|
|
1545
|
+
* payloads ship materialized node_modules) or a wrong-target link is
|
|
1546
|
+
* replaced with the canonical junction/symlink, mirroring syncPdCli.
|
|
1547
|
+
* Idempotent. MUST run after installBundledCodexAdapter AND the
|
|
1548
|
+
* core/host-runtime/install-layout installs — the manifest declares all
|
|
1549
|
+
* three as file:../ siblings, and a missing sibling means a corrupted
|
|
1550
|
+
* payload or a call-order regression, which fails the install loudly.
|
|
1551
|
+
*/
|
|
1552
|
+
export function ensureCodexAdapterResolution() {
|
|
1553
|
+
const codexAdapterDir = getInstalledCodexAdapterDir();
|
|
1554
|
+
const manifestPath = path.join(codexAdapterDir, 'package.json');
|
|
1555
|
+
let manifest;
|
|
1556
|
+
try {
|
|
1557
|
+
manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
|
|
1558
|
+
}
|
|
1559
|
+
catch (error) {
|
|
1560
|
+
throw new Error(`Installed @principles/codex-adapter package.json is missing or malformed (${manifestPath}): ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
1561
|
+
}
|
|
1562
|
+
if (!isRecord(manifest)) {
|
|
1563
|
+
throw new Error(`Installed @principles/codex-adapter package.json must contain an object (${manifestPath}).`);
|
|
1564
|
+
}
|
|
1565
|
+
if (manifest.dependencies !== undefined && !isRecord(manifest.dependencies)) {
|
|
1566
|
+
throw new Error(`Installed @principles/codex-adapter package.json dependencies must be an object (${manifestPath}).`);
|
|
1567
|
+
}
|
|
1568
|
+
const runtimeDir = getPdRuntimeDir();
|
|
1569
|
+
for (const [name, ref] of Object.entries(manifest.dependencies ?? {})) {
|
|
1570
|
+
if (typeof ref !== 'string' || !ref.startsWith('file:../'))
|
|
1571
|
+
continue;
|
|
1572
|
+
const siblingName = ref.slice('file:../'.length);
|
|
1573
|
+
// rc-1: the manifest is untrusted input — only accept single-path segment
|
|
1574
|
+
// siblings so a crafted ref cannot escape the runtime dir.
|
|
1575
|
+
if (!/^[A-Za-z0-9._-]+$/.test(siblingName) || siblingName === '.' || siblingName === '..') {
|
|
1576
|
+
throw new Error(`Installed @principles/codex-adapter declares an unsupported file dependency ref "${ref}" for ${name}.`);
|
|
1577
|
+
}
|
|
1578
|
+
const siblingDir = path.join(runtimeDir, siblingName);
|
|
1579
|
+
if (!existsSync(siblingDir)) {
|
|
1580
|
+
throw new Error(`@principles/codex-adapter depends on ${ref} but the sibling runtime component is missing: ${siblingDir}`);
|
|
1581
|
+
}
|
|
1582
|
+
const linkPath = path.join(codexAdapterDir, 'node_modules', name);
|
|
1583
|
+
let stat;
|
|
1584
|
+
try {
|
|
1585
|
+
stat = lstatSync(linkPath);
|
|
1586
|
+
}
|
|
1587
|
+
catch {
|
|
1588
|
+
stat = undefined; // ENOENT — create below
|
|
1589
|
+
}
|
|
1590
|
+
if (stat !== undefined) {
|
|
1591
|
+
if (stat.isSymbolicLink()) {
|
|
1592
|
+
try {
|
|
1593
|
+
if (realpathSync(linkPath) === realpathSync(siblingDir))
|
|
1594
|
+
continue;
|
|
1595
|
+
}
|
|
1596
|
+
catch {
|
|
1597
|
+
// Unreadable link target — fall through to replace.
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
rmSync(linkPath, { recursive: stat.isDirectory() && !stat.isSymbolicLink(), force: true });
|
|
1601
|
+
}
|
|
1602
|
+
mkdirSync(path.dirname(linkPath), { recursive: true });
|
|
1603
|
+
if (isWindows()) {
|
|
1604
|
+
symlinkSync(siblingDir, linkPath, 'junction');
|
|
1605
|
+
}
|
|
1606
|
+
else {
|
|
1607
|
+
symlinkSync(path.relative(path.dirname(linkPath), siblingDir), linkPath, 'dir');
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1447
1611
|
function ensureCoreDependency(_targetDir) {
|
|
1448
1612
|
const coreDir = getInstalledCoreDir();
|
|
1449
1613
|
if (!existsSync(coreDir)) {
|
|
@@ -1888,6 +2052,18 @@ async function runHostInstallers(host, ctx) {
|
|
|
1888
2052
|
function sha256File(filePath) {
|
|
1889
2053
|
return createHash('sha256').update(readFileSync(filePath)).digest('hex');
|
|
1890
2054
|
}
|
|
2055
|
+
function readPackageVersion(pkgPath) {
|
|
2056
|
+
if (!existsSync(pkgPath))
|
|
2057
|
+
return null;
|
|
2058
|
+
try {
|
|
2059
|
+
const parsed = JSON.parse(readFileSync(pkgPath, 'utf8'));
|
|
2060
|
+
return typeof parsed.version === 'string' && parsed.version.length > 0 ? parsed.version : null;
|
|
2061
|
+
}
|
|
2062
|
+
catch {
|
|
2063
|
+
// Identity falls back; journaling must not brick install.
|
|
2064
|
+
return null;
|
|
2065
|
+
}
|
|
2066
|
+
}
|
|
1891
2067
|
/**
|
|
1892
2068
|
* Identity of the payload being installed. Prefers the self-contained asset
|
|
1893
2069
|
* manifest (covers the whole payload); falls back to the bundled pd-cli
|
|
@@ -1896,20 +2072,19 @@ function sha256File(filePath) {
|
|
|
1896
2072
|
* legacy-migration.ts). The last-resort fallback hashes the literal reason
|
|
1897
2073
|
* string only to satisfy the journal's 64-hex format requirement; it is not
|
|
1898
2074
|
* part of any release-metadata identity chain.
|
|
2075
|
+
*
|
|
2076
|
+
* PRI-709 P0-2 (PRI-698 audit F-1): `productVersion` is the PRODUCT version —
|
|
2077
|
+
* the plugin package manifest. It previously read `pd-cli/package.json`, but
|
|
2078
|
+
* the two packages version independently (on the Owner machine: plugin
|
|
2079
|
+
* 1.230.2 vs pd-cli 1.147.5), so every confirmed journal recorded a version
|
|
2080
|
+
* that no runtime state could ever match. That is why active.json could not
|
|
2081
|
+
* serve as the deployment identity source.
|
|
1899
2082
|
*/
|
|
1900
2083
|
function resolveInstallerPayloadIdentity(pluginDir) {
|
|
1901
|
-
|
|
2084
|
+
const productVersion = readPackageVersion(path.join(pluginDir, 'package.json'))
|
|
2085
|
+
?? readPackageVersion(path.join(pluginDir, 'pd-cli', 'package.json'))
|
|
2086
|
+
?? 'unknown';
|
|
1902
2087
|
const pdCliPkgPath = path.join(pluginDir, 'pd-cli', 'package.json');
|
|
1903
|
-
if (existsSync(pdCliPkgPath)) {
|
|
1904
|
-
try {
|
|
1905
|
-
const parsed = JSON.parse(readFileSync(pdCliPkgPath, 'utf8'));
|
|
1906
|
-
if (typeof parsed.version === 'string' && parsed.version.length > 0)
|
|
1907
|
-
productVersion = parsed.version;
|
|
1908
|
-
}
|
|
1909
|
-
catch {
|
|
1910
|
-
// Identity falls back to 'unknown'; journaling must not brick install.
|
|
1911
|
-
}
|
|
1912
|
-
}
|
|
1913
2088
|
const assetManifestPath = path.join(pluginDir, '_release', 'manifest.json');
|
|
1914
2089
|
let releaseMetadataDigest;
|
|
1915
2090
|
let releaseMetadataDigestSource;
|
|
@@ -2213,6 +2388,11 @@ transaction) {
|
|
|
2213
2388
|
installBundledCodexAdapter(pluginDir);
|
|
2214
2389
|
stepIndex++;
|
|
2215
2390
|
installBundledLayoutPackage(pluginDir);
|
|
2391
|
+
// PRI-711: the adapter's own file: deps must resolve or pd-cli's eager
|
|
2392
|
+
// import graph crashes on every command. Runs only once ALL adapter
|
|
2393
|
+
// siblings exist — the manifest declares file:../core, file:../host-runtime
|
|
2394
|
+
// AND file:../install-layout, and install-layout lands just above.
|
|
2395
|
+
ensureCodexAdapterResolution();
|
|
2216
2396
|
if (spinner)
|
|
2217
2397
|
updateProgress(spinner, stepIndex, 'Installing release-manager authority module...');
|
|
2218
2398
|
installBundledReleaseManagerPackage(pluginDir);
|
|
@@ -2405,6 +2585,9 @@ transaction) {
|
|
|
2405
2585
|
throw new Error(`Host installation failed: ${hostFailures.join(' | ')}`);
|
|
2406
2586
|
}
|
|
2407
2587
|
writeInstallManifest(installManifestHosts, resolveInstallManifestWorkspaces(options.workspaceDir));
|
|
2588
|
+
// PRI-709 P0-1: persist the metadata source after the manifest write, so
|
|
2589
|
+
// the durable tier cannot be clobbered by the same install.
|
|
2590
|
+
persistReleaseMetadataSource();
|
|
2408
2591
|
// ADR-0024 D-2: host installers completed and the install manifest is
|
|
2409
2592
|
// written — the new installation is fully activated (backups not yet
|
|
2410
2593
|
// discarded, so a crash here still recovers via the backup).
|
|
@@ -2412,6 +2595,9 @@ transaction) {
|
|
|
2412
2595
|
cleanupBackup(backupDir, runtimeBackupDir);
|
|
2413
2596
|
// ADR-0024 D-2: backup cleanup is the commit point of the transaction.
|
|
2414
2597
|
journalInstallerTransitionDegrading(journal, journal.lastState, 'confirmed', 'backup cleaned up; install complete');
|
|
2598
|
+
// PRI-709 P0-2: active.json is the deployment identity source, written
|
|
2599
|
+
// journal-first — after `confirmed`, never before it.
|
|
2600
|
+
commitInstallerActiveRecord(journal);
|
|
2415
2601
|
if (spinner) {
|
|
2416
2602
|
spinner.succeed('Install complete!');
|
|
2417
2603
|
}
|