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
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRI-709 P0-3 — journal coverage for the legacy console updater (ADR-0024 D-2).
|
|
3
|
+
*
|
|
4
|
+
* PRI-698 Phase 0 Audit finding F-3: the console updater performed runtime
|
|
5
|
+
* mutations with **zero** journal writes. Under ADR-0024 D-2 an unjournaled
|
|
6
|
+
* runtime mutation is the one thing that must never happen, so the legacy
|
|
7
|
+
* updater had to be brought under the SAME journal as the installer and the
|
|
8
|
+
* ReleaseManager before the legacy path can be retired.
|
|
9
|
+
*
|
|
10
|
+
* Design rules (all load-bearing):
|
|
11
|
+
*
|
|
12
|
+
* - **No new journal implementation.** This module reuses
|
|
13
|
+
* `create-principles-disciple`'s `transaction-journal` — one JSONL file per
|
|
14
|
+
* transaction under `~/.pd/transactions/`, append + fsync, strict reader.
|
|
15
|
+
* Nothing here parses, formats or rotates journals.
|
|
16
|
+
* - **The ReleaseManager path is never double-journaled.** ReleaseManager
|
|
17
|
+
* `apply-full` orchestrates the installer, which journals the whole
|
|
18
|
+
* lifecycle; the console dispatch for that path never reaches the legacy
|
|
19
|
+
* handlers this module wraps. When the ReleaseManager explicitly falls back
|
|
20
|
+
* to legacy, the legacy handler is the ONLY writer — one transaction per
|
|
21
|
+
* mutation, whichever authority served it.
|
|
22
|
+
* - **Explicit degradation, never a blocked mutation.** The journal module is
|
|
23
|
+
* loaded dynamically: the console runs in installations where the
|
|
24
|
+
* create-principles-disciple dist may be absent (the same delivery-surface
|
|
25
|
+
* gap the ReleaseManager authority loader already handles). A missing module
|
|
26
|
+
* is reported and the mutation proceeds unjournaled — refusing the Owner's
|
|
27
|
+
* update would be worse than an unaudited one, and the gap is observable.
|
|
28
|
+
* - **No fabricated digests.** The legacy updater does not verify signed
|
|
29
|
+
* release metadata, so its digest provenance is `fallback`: a synthetic
|
|
30
|
+
* sha256 over a literal marker, readable but explicitly NOT verifiable. It
|
|
31
|
+
* never claims `manifest` / `signed_channel` it cannot back.
|
|
32
|
+
*
|
|
33
|
+
* Transition strategy for legacy kinds:
|
|
34
|
+
*
|
|
35
|
+
* apply / apply-full / rollback: `planned` → `confirmed` | `failed`
|
|
36
|
+
*
|
|
37
|
+
* `planned` is appended immediately before the mutation (after all request
|
|
38
|
+
* validation, so rejected requests leave no transaction); `confirmed` or
|
|
39
|
+
* `failed` after it. `rolled_back` is NOT used for the rollback kind — a
|
|
40
|
+
* rollback restores a previous deployment and is itself a forward transition
|
|
41
|
+
* to a known-good state, whereas `rolled_back` means "this transaction was
|
|
42
|
+
* undone".
|
|
43
|
+
*
|
|
44
|
+
* Two documented trade-offs (PRI-709 review, deliberate):
|
|
45
|
+
*
|
|
46
|
+
* - **`generation` stays at the standalone default `1`.** Legacy console
|
|
47
|
+
* transactions do not participate in the dual-slot generation lineage — they
|
|
48
|
+
* never move the active record — so recording a real `active.json.generation
|
|
49
|
+
* + 1` would CLAIM a lineage the console does not actually advance. Recovery
|
|
50
|
+
* is unaffected either way: `recoverUnfinishedTransaction` keys on
|
|
51
|
+
* `activeRecord.transactionId`, which a console transaction never matches, so
|
|
52
|
+
* it resolves to "the previously confirmed release stands".
|
|
53
|
+
* - **The legacy path leaves `active.json` untouched.** The legacy updater
|
|
54
|
+
* replaces the runtime without the installer's dual-slot swap, so after a
|
|
55
|
+
* legacy `apply-full` the active record describes the PREVIOUS deployment.
|
|
56
|
+
* Making the console a second writer of the deployment identity would be a
|
|
57
|
+
* worse violation (one source of truth); the honest fix is retiring the
|
|
58
|
+
* legacy path (ADR-0024 D-1), which is exactly what this journal coverage
|
|
59
|
+
* unblocks.
|
|
60
|
+
*/
|
|
61
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
62
|
+
import * as fs from 'node:fs';
|
|
63
|
+
import * as path from 'node:path';
|
|
64
|
+
/** Load the shared journal; `null` when the delivery surface lacks the module. */
|
|
65
|
+
async function loadJournalPort() {
|
|
66
|
+
try {
|
|
67
|
+
const module = await import('create-principles-disciple/dist/update/transaction-journal.js');
|
|
68
|
+
return { appendJournalTransition: module.appendJournalTransition };
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Product version of the currently installed runtime.
|
|
76
|
+
*
|
|
77
|
+
* Same rule as the installer (PRI-709 P0-2): the PRODUCT manifest is
|
|
78
|
+
* `pluginDir/package.json`; `pd-cli` versions independently and is only a
|
|
79
|
+
* fallback.
|
|
80
|
+
*/
|
|
81
|
+
function resolveInstalledProductVersion(pluginDir) {
|
|
82
|
+
for (const candidate of [path.join(pluginDir, 'package.json'), path.join(pluginDir, 'pd-cli', 'package.json')]) {
|
|
83
|
+
try {
|
|
84
|
+
const parsed = JSON.parse(fs.readFileSync(candidate, 'utf8'));
|
|
85
|
+
if (typeof parsed.version === 'string' && parsed.version.length > 0)
|
|
86
|
+
return parsed.version;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// Identity falls back; an unjournaled-able version must not block a mutation.
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return 'unknown';
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Open one legacy transaction and append `planned` before the mutation runs.
|
|
96
|
+
*/
|
|
97
|
+
export async function openLegacyMutationJournal(options) {
|
|
98
|
+
const port = options.journal ?? await loadJournalPort();
|
|
99
|
+
if (port === null) {
|
|
100
|
+
return { journaled: false, reason: 'journal_module_unavailable' };
|
|
101
|
+
}
|
|
102
|
+
const productVersion = resolveInstalledProductVersion(options.pluginDir);
|
|
103
|
+
// Unverifiable by construction: the legacy updater never sees signed release
|
|
104
|
+
// metadata, so the digest is a marker hash labelled `fallback`.
|
|
105
|
+
const releaseMetadataDigest = createHash('sha256')
|
|
106
|
+
.update(`legacy-console-updater-unverified:${options.kind}`)
|
|
107
|
+
.digest('hex');
|
|
108
|
+
const transactionId = `console-${options.kind}-${Date.now()}-${randomUUID().slice(0, 8)}`;
|
|
109
|
+
const releaseId = `console-${options.kind}-${productVersion}-${releaseMetadataDigest.slice(0, 12)}`;
|
|
110
|
+
const journal = {
|
|
111
|
+
transactionId,
|
|
112
|
+
journalPath: path.join(options.pdHome, 'transactions', `${transactionId}.jsonl`),
|
|
113
|
+
releaseId,
|
|
114
|
+
productVersion,
|
|
115
|
+
releaseMetadataDigest,
|
|
116
|
+
};
|
|
117
|
+
try {
|
|
118
|
+
port.appendJournalTransition(journal.journalPath, {
|
|
119
|
+
at: (options.now ?? (() => new Date))().toISOString(),
|
|
120
|
+
from: null,
|
|
121
|
+
to: 'planned',
|
|
122
|
+
transactionId,
|
|
123
|
+
releaseId,
|
|
124
|
+
productVersion,
|
|
125
|
+
releaseMetadataDigest,
|
|
126
|
+
releaseMetadataDigestSource: 'fallback',
|
|
127
|
+
generation: 1,
|
|
128
|
+
detail: `actor=console-updater kind=${options.kind}`,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
return {
|
|
133
|
+
journaled: false,
|
|
134
|
+
reason: `journal_write_failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
return { journaled: true, journal };
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Maps a mutation's RESULT to its journal terminal state.
|
|
141
|
+
*
|
|
142
|
+
* PRI-709 review: the legacy updater reports failure as a VALUE —
|
|
143
|
+
* `doApplyUpdate` / `doRollbackUpdate` / `doInlineFullUpdate` return
|
|
144
|
+
* `{ success: false, message }` for ~30 distinct failure modes and only throw
|
|
145
|
+
* for infrastructure errors. Terminal state decided on "did it throw" alone
|
|
146
|
+
* would journal confirmed for most real failures. So: `success === true` is
|
|
147
|
+
* `confirmed`, `success === false` is `failed` (with the reported message as
|
|
148
|
+
* detail), and a non-object result (no contract) is treated as completed.
|
|
149
|
+
* The HTTP response contract is untouched either way — this only decides what
|
|
150
|
+
* the journal records.
|
|
151
|
+
*/
|
|
152
|
+
function toLegacyMutationOutcome(result) {
|
|
153
|
+
if (typeof result !== 'object' || result === null) {
|
|
154
|
+
return { to: 'confirmed', detail: 'completed' };
|
|
155
|
+
}
|
|
156
|
+
const record = result;
|
|
157
|
+
if (!Object.hasOwn(record, 'success')) {
|
|
158
|
+
return { to: 'confirmed', detail: 'completed' };
|
|
159
|
+
}
|
|
160
|
+
const detailParts = [record.message, record.reason]
|
|
161
|
+
.filter((part) => typeof part === 'string' && part.length > 0);
|
|
162
|
+
const detail = detailParts.length > 0 ? detailParts.join('; ') : 'no detail reported';
|
|
163
|
+
return { to: record.success === true ? 'confirmed' : 'failed', detail };
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Writes the terminal transition for an opened legacy transaction and reports
|
|
167
|
+
* loud when it cannot land: the journal would then hold an unfinished
|
|
168
|
+
* transaction, which is a governance gap (rc-9) even though the mutation's
|
|
169
|
+
* real outcome must not be masked.
|
|
170
|
+
*/
|
|
171
|
+
async function appendLegacyOutcome(options, status, outcome) {
|
|
172
|
+
if (!status.journaled)
|
|
173
|
+
return;
|
|
174
|
+
const port = options.journal ?? await loadJournalPort();
|
|
175
|
+
if (port === null)
|
|
176
|
+
return;
|
|
177
|
+
try {
|
|
178
|
+
port.appendJournalTransition(status.journal.journalPath, {
|
|
179
|
+
at: (options.now ?? (() => new Date))().toISOString(),
|
|
180
|
+
from: 'planned',
|
|
181
|
+
to: outcome.to,
|
|
182
|
+
transactionId: status.journal.transactionId,
|
|
183
|
+
releaseId: status.journal.releaseId,
|
|
184
|
+
productVersion: status.journal.productVersion,
|
|
185
|
+
releaseMetadataDigest: status.journal.releaseMetadataDigest,
|
|
186
|
+
releaseMetadataDigestSource: 'fallback',
|
|
187
|
+
generation: 1,
|
|
188
|
+
detail: `actor=console-updater kind=${options.kind} ${outcome.detail}`,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
console.warn(`[update] Legacy mutation "${options.kind}" finished as "${outcome.to}" but its terminal journal transition `
|
|
193
|
+
+ `could not be written (${error instanceof Error ? error.message : String(error)}). `
|
|
194
|
+
+ `Transaction ${status.journal.transactionId} stays unfinished and must be reconciled.`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Runs a legacy mutation under one journal transaction.
|
|
199
|
+
*
|
|
200
|
+
* `planned` is written before `run()`; `confirmed` / `failed` after — decided
|
|
201
|
+
* by BOTH the thrown/not-thrown boundary and the updater's `success` result
|
|
202
|
+
* shape (see `toLegacyMutationOutcome`). A journal failure never changes the
|
|
203
|
+
* mutation's outcome — it is reported alongside it.
|
|
204
|
+
*/
|
|
205
|
+
export async function runLegacyJournaledMutation(options, run) {
|
|
206
|
+
const opened = await openLegacyMutationJournal(options);
|
|
207
|
+
try {
|
|
208
|
+
const result = await run();
|
|
209
|
+
const outcome = toLegacyMutationOutcome(result);
|
|
210
|
+
await appendLegacyOutcome(options, opened, { to: outcome.to, detail: `${options.kind}: ${outcome.detail}` });
|
|
211
|
+
return { result, journal: opened };
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
await appendLegacyOutcome(options, opened, {
|
|
215
|
+
to: 'failed',
|
|
216
|
+
detail: `${options.kind}: ${error instanceof Error ? error.message : String(error)}`,
|
|
217
|
+
});
|
|
218
|
+
throw error;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type CliSmokeResult = {
|
|
2
|
+
ok: true;
|
|
3
|
+
version: string;
|
|
4
|
+
} | {
|
|
5
|
+
ok: false;
|
|
6
|
+
error: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Spawn the pd CLI entry and require exit 0.
|
|
10
|
+
*
|
|
11
|
+
* Resolves `node` from PATH — the same resolution the installed bin/pd.cmd
|
|
12
|
+
* shim already depends on, so any environment that can run `pd` at all can
|
|
13
|
+
* run this probe. The entry path is boundary-checked to stay inside the
|
|
14
|
+
* pd-cli component dir (same guard shape as the legacy-rule preflight's
|
|
15
|
+
* subprocess target), and the subprocess is invoked with an argv array —
|
|
16
|
+
* never a shell string (ERR-045). Bounded stderr extract on failure (rc-8);
|
|
17
|
+
* never throws.
|
|
18
|
+
*/
|
|
19
|
+
export declare function runPostUpdateCliSmoke(pdCliDir: string): CliSmokeResult;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRI-711: post-apply CLI smoke for the full-update pipeline.
|
|
3
|
+
*
|
|
4
|
+
* The full update swaps component dists without running npm install, and
|
|
5
|
+
* resolution gaps of one class have now shipped three times — each discovered
|
|
6
|
+
* only as a bricked CLI at the next console launch (PRI-561 host-runtime
|
|
7
|
+
* links, the 2026-08-29 install-layout component gap, PRI-711 codex-adapter).
|
|
8
|
+
* Spawning the pd CLI once with `--version` loads its entire eager import
|
|
9
|
+
* graph (health-codex → @principles/codex-adapter →
|
|
10
|
+
* @principles/host-runtime → @principles/core) and exits without touching
|
|
11
|
+
* workspace state, so a gap anywhere in that graph surfaces before the update
|
|
12
|
+
* is recorded as a success.
|
|
13
|
+
*/
|
|
14
|
+
import { execFileSync } from 'child_process';
|
|
15
|
+
import * as fs from 'fs';
|
|
16
|
+
import * as path from 'path';
|
|
17
|
+
/**
|
|
18
|
+
* Spawn the pd CLI entry and require exit 0.
|
|
19
|
+
*
|
|
20
|
+
* Resolves `node` from PATH — the same resolution the installed bin/pd.cmd
|
|
21
|
+
* shim already depends on, so any environment that can run `pd` at all can
|
|
22
|
+
* run this probe. The entry path is boundary-checked to stay inside the
|
|
23
|
+
* pd-cli component dir (same guard shape as the legacy-rule preflight's
|
|
24
|
+
* subprocess target), and the subprocess is invoked with an argv array —
|
|
25
|
+
* never a shell string (ERR-045). Bounded stderr extract on failure (rc-8);
|
|
26
|
+
* never throws.
|
|
27
|
+
*/
|
|
28
|
+
export function runPostUpdateCliSmoke(pdCliDir) {
|
|
29
|
+
const resolvedRoot = path.resolve(pdCliDir);
|
|
30
|
+
const pdCliEntry = path.join(resolvedRoot, 'dist', 'index.js');
|
|
31
|
+
if (!pdCliEntry.startsWith(resolvedRoot + path.sep)) {
|
|
32
|
+
return { ok: false, error: `pd CLI entry ${pdCliEntry} is outside the pd-cli component dir ${resolvedRoot}` };
|
|
33
|
+
}
|
|
34
|
+
if (!fs.existsSync(pdCliEntry)) {
|
|
35
|
+
return { ok: false, error: `pd CLI entry not found at ${pdCliEntry}` };
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const stdout = execFileSync('node', [pdCliEntry, '--version'], {
|
|
39
|
+
timeout: 60_000,
|
|
40
|
+
encoding: 'utf8',
|
|
41
|
+
windowsHide: true,
|
|
42
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
43
|
+
});
|
|
44
|
+
const version = (stdout.trim().split(/\r?\n/, 1)[0] ?? '').trim();
|
|
45
|
+
return { ok: true, version };
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
// rc-1/rc-2: the child failure shape is unknown — guard every read.
|
|
49
|
+
// Node prints the error MESSAGE first and stack frames after, so the
|
|
50
|
+
// operator-facing extract is the bounded HEAD of stderr (a tail would
|
|
51
|
+
// carry only stack noise — observed in the PRI-711 test fixture).
|
|
52
|
+
let reason = error instanceof Error ? error.message : String(error);
|
|
53
|
+
if (typeof error === 'object' && error !== null && Object.hasOwn(error, 'stderr')) {
|
|
54
|
+
const { stderr } = error;
|
|
55
|
+
if (typeof stderr === 'string' && stderr.trim().length > 0)
|
|
56
|
+
reason = stderr;
|
|
57
|
+
}
|
|
58
|
+
return { ok: false, error: reason.trim().slice(0, 400) };
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -8,6 +8,14 @@ export interface UpdateLayout {
|
|
|
8
8
|
pdCliDir: string;
|
|
9
9
|
installLayoutDir: string;
|
|
10
10
|
releaseManagerDir: string;
|
|
11
|
+
/**
|
|
12
|
+
* PRI-711: codex-adapter is a runtime-layout component pd-cli resolves
|
|
13
|
+
* eagerly. Undefined when the DEPLOYED @principles/install-layout is one
|
|
14
|
+
* generation old (this update runs inside the currently-running console,
|
|
15
|
+
* which resolves the layout helper installed by the PREVIOUS update) —
|
|
16
|
+
* consumers must degrade to skipping the adapter, never assume it.
|
|
17
|
+
*/
|
|
18
|
+
codexAdapterDir: string | undefined;
|
|
11
19
|
hosts: InstallHost[];
|
|
12
20
|
}
|
|
13
21
|
export declare function resolveUpdateLayout(): UpdateLayout | undefined;
|
|
@@ -46,6 +46,9 @@ export function resolveUpdateLayout() {
|
|
|
46
46
|
pdCliDir: paths.pdCliDir,
|
|
47
47
|
installLayoutDir: paths.installLayoutDir,
|
|
48
48
|
releaseManagerDir: paths.releaseManagerDir,
|
|
49
|
+
// rc-1: the deployed install-layout may predate the codexAdapterDir
|
|
50
|
+
// field — guard instead of trusting the shape.
|
|
51
|
+
codexAdapterDir: typeof paths.codexAdapterDir === 'string' ? paths.codexAdapterDir : undefined,
|
|
49
52
|
hosts: resolution.manifest?.hosts ?? [],
|
|
50
53
|
};
|
|
51
54
|
}
|
|
@@ -57,6 +60,7 @@ export function resolveUpdateLayout() {
|
|
|
57
60
|
pdCliDir: path.join(legacyPluginDir, 'pd-cli'),
|
|
58
61
|
installLayoutDir: path.join(legacyPluginDir, 'install-layout'),
|
|
59
62
|
releaseManagerDir: path.join(legacyPluginDir, 'release-manager'),
|
|
63
|
+
codexAdapterDir: path.join(legacyPluginDir, 'codex-adapter'),
|
|
60
64
|
hosts: ['openclaw'],
|
|
61
65
|
};
|
|
62
66
|
}
|
|
@@ -1355,8 +1355,8 @@
|
|
|
1355
1355
|
"filesUpdated": "Updated {{count}} files",
|
|
1356
1356
|
"networkErrorHint": "Please check your network connection and try again.",
|
|
1357
1357
|
"retry": "Retry",
|
|
1358
|
-
"codexWarning": "Codex Host detected.
|
|
1359
|
-
"partialUpdateHint": "Plugin code updated.
|
|
1358
|
+
"codexWarning": "Codex Host detected. The full update also refreshes the Codex adapter (@principles/codex-adapter) in the runtime layout. To re-register Codex hooks or repair the Codex host install, run the installer.",
|
|
1359
|
+
"partialUpdateHint": "Plugin code updated. If components ever look out of sync, refresh the full runtime with: npx create-principles-disciple",
|
|
1360
1360
|
"applyFullUpdate": "Full Update",
|
|
1361
1361
|
"fullUpdating": "Full update in progress…",
|
|
1362
1362
|
"fullUpdateSuccess": "Full update completed.",
|
|
@@ -1355,8 +1355,8 @@
|
|
|
1355
1355
|
"filesUpdated": "更新了 {{count}} 个文件",
|
|
1356
1356
|
"networkErrorHint": "请检查网络连接后重试。",
|
|
1357
1357
|
"retry": "重试",
|
|
1358
|
-
"codexWarning": "检测到 Codex Host
|
|
1359
|
-
"partialUpdateHint": "
|
|
1358
|
+
"codexWarning": "检测到 Codex Host 已安装。全量更新现在会同步刷新运行时布局中的 Codex 适配器(@principles/codex-adapter)。如需重新注册 Codex hooks 或修复 Codex 宿主安装,请运行安装器。",
|
|
1359
|
+
"partialUpdateHint": "插件代码已更新。如发现组件版本不同步,请运行以下命令刷新完整运行时:npx create-principles-disciple",
|
|
1360
1360
|
"applyFullUpdate": "全量更新",
|
|
1361
1361
|
"fullUpdating": "全量更新中…",
|
|
1362
1362
|
"fullUpdateSuccess": "全量更新完成。",
|