create-principles-disciple 1.132.1 → 1.132.3
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/console/dist/server/routes/update.js +187 -19
- package/console/dist/server/update/mutation-controller.d.ts +18 -0
- package/console/dist/server/update/mutation-controller.js +29 -0
- package/console/dist/server/utils/installed-layout.d.ts +1 -0
- package/console/dist/server/utils/installed-layout.js +2 -0
- package/console/package.json +1 -0
- package/core/dist/runtime-v2/__tests__/architecture-regression.test.js +15 -0
- package/core/dist/runtime-v2/__tests__/architecture-regression.test.js.map +1 -1
- package/core/dist/runtime-v2/adapter/__tests__/pd-stream-simple.test.d.ts +2 -0
- package/core/dist/runtime-v2/adapter/__tests__/pd-stream-simple.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/adapter/__tests__/pd-stream-simple.test.js +71 -0
- package/core/dist/runtime-v2/adapter/__tests__/pd-stream-simple.test.js.map +1 -0
- package/core/dist/runtime-v2/adapter/__tests__/pi-ai-http-transport.test.d.ts +2 -0
- package/core/dist/runtime-v2/adapter/__tests__/pi-ai-http-transport.test.d.ts.map +1 -0
- package/core/dist/runtime-v2/adapter/__tests__/pi-ai-http-transport.test.js +219 -0
- package/core/dist/runtime-v2/adapter/__tests__/pi-ai-http-transport.test.js.map +1 -0
- package/core/dist/runtime-v2/adapter/artificer-l2-adapter.d.ts.map +1 -1
- package/core/dist/runtime-v2/adapter/artificer-l2-adapter.js +2 -3
- package/core/dist/runtime-v2/adapter/artificer-l2-adapter.js.map +1 -1
- package/core/dist/runtime-v2/adapter/l2-agent-loop-adapter.d.ts +12 -1
- package/core/dist/runtime-v2/adapter/l2-agent-loop-adapter.d.ts.map +1 -1
- package/core/dist/runtime-v2/adapter/l2-agent-loop-adapter.js +15 -2
- package/core/dist/runtime-v2/adapter/l2-agent-loop-adapter.js.map +1 -1
- package/core/dist/runtime-v2/adapter/pi-ai-http-transport.d.ts +50 -0
- package/core/dist/runtime-v2/adapter/pi-ai-http-transport.d.ts.map +1 -0
- package/core/dist/runtime-v2/adapter/pi-ai-http-transport.js +93 -0
- package/core/dist/runtime-v2/adapter/pi-ai-http-transport.js.map +1 -0
- package/core/dist/runtime-v2/adapter/pi-ai-runtime-adapter.d.ts.map +1 -1
- package/core/dist/runtime-v2/adapter/pi-ai-runtime-adapter.js +5 -0
- package/core/dist/runtime-v2/adapter/pi-ai-runtime-adapter.js.map +1 -1
- package/core/dist/runtime-v2/internalization/__tests__/diag-router-runner.test.js +43 -0
- package/core/dist/runtime-v2/internalization/__tests__/diag-router-runner.test.js.map +1 -1
- package/core/dist/runtime-v2/internalization/__tests__/mvp-core-loop-journeys.test.js +55 -0
- package/core/dist/runtime-v2/internalization/__tests__/mvp-core-loop-journeys.test.js.map +1 -1
- package/core/dist/runtime-v2/internalization/__tests__/owner-decision.test.js +152 -0
- package/core/dist/runtime-v2/internalization/__tests__/owner-decision.test.js.map +1 -1
- package/core/dist/runtime-v2/internalization/__tests__/rule-code-dialect.test.js +30 -9
- package/core/dist/runtime-v2/internalization/__tests__/rule-code-dialect.test.js.map +1 -1
- package/core/dist/runtime-v2/internalization/__tests__/shared-information-plane-runner.test.js +131 -0
- package/core/dist/runtime-v2/internalization/__tests__/shared-information-plane-runner.test.js.map +1 -1
- package/core/dist/runtime-v2/internalization/diag-router-runner.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/diag-router-runner.js +35 -0
- package/core/dist/runtime-v2/internalization/diag-router-runner.js.map +1 -1
- package/core/dist/runtime-v2/internalization/internalization-orchestrator.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/internalization-orchestrator.js +23 -0
- package/core/dist/runtime-v2/internalization/internalization-orchestrator.js.map +1 -1
- package/core/dist/runtime-v2/internalization/legacy-rule-contract-scanner.d.ts +11 -0
- package/core/dist/runtime-v2/internalization/legacy-rule-contract-scanner.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/legacy-rule-contract-scanner.js +11 -1
- package/core/dist/runtime-v2/internalization/legacy-rule-contract-scanner.js.map +1 -1
- package/core/dist/runtime-v2/internalization/owner-review.d.ts +7 -1
- package/core/dist/runtime-v2/internalization/owner-review.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/owner-review.js +22 -3
- package/core/dist/runtime-v2/internalization/owner-review.js.map +1 -1
- package/core/dist/runtime-v2/internalization/rule-code-validator.d.ts +7 -4
- package/core/dist/runtime-v2/internalization/rule-code-validator.d.ts.map +1 -1
- package/core/dist/runtime-v2/internalization/rule-code-validator.js +25 -2
- package/core/dist/runtime-v2/internalization/rule-code-validator.js.map +1 -1
- package/core/package.json +3 -2
- package/dist/installer.d.ts.map +1 -1
- package/dist/installer.js +50 -0
- package/dist/installer.js.map +1 -1
- package/dist/update/release-manager-authority.d.ts +69 -0
- package/dist/update/release-manager-authority.d.ts.map +1 -0
- package/dist/update/release-manager-authority.js +125 -0
- package/dist/update/release-manager-authority.js.map +1 -0
- package/dist/utils/workspace-divergence.d.ts +36 -0
- package/dist/utils/workspace-divergence.d.ts.map +1 -0
- package/dist/utils/workspace-divergence.js +87 -0
- package/dist/utils/workspace-divergence.js.map +1 -0
- package/host-runtime/dist/internalization-consumer-cycle.js +12 -1
- package/host-runtime/package.json +1 -1
- package/install-layout/dist/index.d.ts +5 -0
- package/install-layout/dist/index.js +1 -0
- package/install-layout/package.json +1 -1
- package/package.json +3 -2
- package/pd-cli/dist/commands/codex-worker.d.ts.map +1 -1
- package/pd-cli/dist/commands/codex-worker.js +14 -2
- package/pd-cli/dist/commands/codex-worker.js.map +1 -1
- package/pd-cli/dist/commands/runtime-internalization-run-once.d.ts.map +1 -1
- package/pd-cli/dist/commands/runtime-internalization-run-once.js +19 -3
- package/pd-cli/dist/commands/runtime-internalization-run-once.js.map +1 -1
- package/pd-cli/package.json +1 -1
- package/plugin/dist/bundle.js +871 -735
- package/plugin/dist/governance-audit.js +381 -247
- package/plugin/dist/openclaw-sdk.d.ts +3 -0
- package/plugin/dist/rulehost-evidence.js +420 -286
- package/plugin/dist/service/subagent-workflow/types.d.ts +2 -2
- package/plugin/dist/utils/retry.d.ts +1 -1
- package/plugin/dist/utils/workspace-resolver.d.ts +35 -4
- package/plugin/openclaw.plugin.json +1 -1
- package/plugin/package.json +1 -1
- package/release-manager/dist/i18n.d.ts +6 -0
- package/release-manager/dist/i18n.d.ts.map +1 -0
- package/release-manager/dist/i18n.js +234 -0
- package/release-manager/dist/i18n.js.map +1 -0
- package/release-manager/dist/index.d.ts +7 -0
- package/release-manager/dist/index.d.ts.map +1 -0
- package/release-manager/dist/index.js +474 -0
- package/release-manager/dist/index.js.map +1 -0
- package/release-manager/dist/installer.d.ts +185 -0
- package/release-manager/dist/installer.d.ts.map +1 -0
- package/release-manager/dist/installer.js +2305 -0
- package/release-manager/dist/installer.js.map +1 -0
- package/release-manager/dist/installers/codex-host-installer.d.ts +29 -0
- package/release-manager/dist/installers/codex-host-installer.d.ts.map +1 -0
- package/release-manager/dist/installers/codex-host-installer.js +494 -0
- package/release-manager/dist/installers/codex-host-installer.js.map +1 -0
- package/release-manager/dist/installers/index.d.ts +40 -0
- package/release-manager/dist/installers/index.d.ts.map +1 -0
- package/release-manager/dist/installers/index.js +35 -0
- package/release-manager/dist/installers/index.js.map +1 -0
- package/release-manager/dist/installers/openclaw-host-installer.d.ts +18 -0
- package/release-manager/dist/installers/openclaw-host-installer.d.ts.map +1 -0
- package/release-manager/dist/installers/openclaw-host-installer.js +414 -0
- package/release-manager/dist/installers/openclaw-host-installer.js.map +1 -0
- package/release-manager/dist/mvp-config.d.ts +197 -0
- package/release-manager/dist/mvp-config.d.ts.map +1 -0
- package/release-manager/dist/mvp-config.js +509 -0
- package/release-manager/dist/mvp-config.js.map +1 -0
- package/release-manager/dist/prompts.d.ts +30 -0
- package/release-manager/dist/prompts.d.ts.map +1 -0
- package/release-manager/dist/prompts.js +231 -0
- package/release-manager/dist/prompts.js.map +1 -0
- package/release-manager/dist/skill-language.d.ts +32 -0
- package/release-manager/dist/skill-language.d.ts.map +1 -0
- package/release-manager/dist/skill-language.js +107 -0
- package/release-manager/dist/skill-language.js.map +1 -0
- package/release-manager/dist/uninstaller.d.ts +55 -0
- package/release-manager/dist/uninstaller.d.ts.map +1 -0
- package/release-manager/dist/uninstaller.js +409 -0
- package/release-manager/dist/uninstaller.js.map +1 -0
- package/release-manager/dist/update/atomic-file.d.ts +35 -0
- package/release-manager/dist/update/atomic-file.d.ts.map +1 -0
- package/release-manager/dist/update/atomic-file.js +120 -0
- package/release-manager/dist/update/atomic-file.js.map +1 -0
- package/release-manager/dist/update/bootstrap-protocol.d.ts +55 -0
- package/release-manager/dist/update/bootstrap-protocol.d.ts.map +1 -0
- package/release-manager/dist/update/bootstrap-protocol.js +132 -0
- package/release-manager/dist/update/bootstrap-protocol.js.map +1 -0
- package/release-manager/dist/update/channel-metadata.d.ts +28 -0
- package/release-manager/dist/update/channel-metadata.d.ts.map +1 -0
- package/release-manager/dist/update/channel-metadata.js +90 -0
- package/release-manager/dist/update/channel-metadata.js.map +1 -0
- package/release-manager/dist/update/channel-promotion.d.ts +39 -0
- package/release-manager/dist/update/channel-promotion.d.ts.map +1 -0
- package/release-manager/dist/update/channel-promotion.js +55 -0
- package/release-manager/dist/update/channel-promotion.js.map +1 -0
- package/release-manager/dist/update/data-compatibility.d.ts +35 -0
- package/release-manager/dist/update/data-compatibility.d.ts.map +1 -0
- package/release-manager/dist/update/data-compatibility.js +45 -0
- package/release-manager/dist/update/data-compatibility.js.map +1 -0
- package/release-manager/dist/update/install-layout.d.ts +59 -0
- package/release-manager/dist/update/install-layout.d.ts.map +1 -0
- package/release-manager/dist/update/install-layout.js +127 -0
- package/release-manager/dist/update/install-layout.js.map +1 -0
- package/release-manager/dist/update/legacy-migration.d.ts +56 -0
- package/release-manager/dist/update/legacy-migration.d.ts.map +1 -0
- package/release-manager/dist/update/legacy-migration.js +254 -0
- package/release-manager/dist/update/legacy-migration.js.map +1 -0
- package/release-manager/dist/update/product-identity.d.ts +50 -0
- package/release-manager/dist/update/product-identity.d.ts.map +1 -0
- package/release-manager/dist/update/product-identity.js +63 -0
- package/release-manager/dist/update/product-identity.js.map +1 -0
- package/release-manager/dist/update/release-asset-manifest.d.ts +31 -0
- package/release-manager/dist/update/release-asset-manifest.d.ts.map +1 -0
- package/release-manager/dist/update/release-asset-manifest.js +161 -0
- package/release-manager/dist/update/release-asset-manifest.js.map +1 -0
- package/release-manager/dist/update/release-identity.d.ts +33 -0
- package/release-manager/dist/update/release-identity.d.ts.map +1 -0
- package/release-manager/dist/update/release-identity.js +108 -0
- package/release-manager/dist/update/release-identity.js.map +1 -0
- package/release-manager/dist/update/release-manager-authority.d.ts +69 -0
- package/release-manager/dist/update/release-manager-authority.d.ts.map +1 -0
- package/release-manager/dist/update/release-manager-authority.js +125 -0
- package/release-manager/dist/update/release-manager-authority.js.map +1 -0
- package/release-manager/dist/update/release-manager.d.ts +96 -0
- package/release-manager/dist/update/release-manager.d.ts.map +1 -0
- package/release-manager/dist/update/release-manager.js +253 -0
- package/release-manager/dist/update/release-manager.js.map +1 -0
- package/release-manager/dist/update/release-metadata.d.ts +57 -0
- package/release-manager/dist/update/release-metadata.d.ts.map +1 -0
- package/release-manager/dist/update/release-metadata.js +200 -0
- package/release-manager/dist/update/release-metadata.js.map +1 -0
- package/release-manager/dist/update/release-policy.d.ts +51 -0
- package/release-manager/dist/update/release-policy.d.ts.map +1 -0
- package/release-manager/dist/update/release-policy.js +103 -0
- package/release-manager/dist/update/release-policy.js.map +1 -0
- package/release-manager/dist/update/rollback-policy.d.ts +56 -0
- package/release-manager/dist/update/rollback-policy.d.ts.map +1 -0
- package/release-manager/dist/update/rollback-policy.js +61 -0
- package/release-manager/dist/update/rollback-policy.js.map +1 -0
- package/release-manager/dist/update/transaction-journal.d.ts +131 -0
- package/release-manager/dist/update/transaction-journal.d.ts.map +1 -0
- package/release-manager/dist/update/transaction-journal.js +346 -0
- package/release-manager/dist/update/transaction-journal.js.map +1 -0
- package/release-manager/dist/update/trust-metadata.d.ts +55 -0
- package/release-manager/dist/update/trust-metadata.d.ts.map +1 -0
- package/release-manager/dist/update/trust-metadata.js +170 -0
- package/release-manager/dist/update/trust-metadata.js.map +1 -0
- package/release-manager/dist/update/update-history.d.ts +46 -0
- package/release-manager/dist/update/update-history.d.ts.map +1 -0
- package/release-manager/dist/update/update-history.js +123 -0
- package/release-manager/dist/update/update-history.js.map +1 -0
- package/release-manager/dist/utils/config-file-io.d.ts +26 -0
- package/release-manager/dist/utils/config-file-io.d.ts.map +1 -0
- package/release-manager/dist/utils/config-file-io.js +128 -0
- package/release-manager/dist/utils/config-file-io.js.map +1 -0
- package/release-manager/dist/utils/env.d.ts +60 -0
- package/release-manager/dist/utils/env.d.ts.map +1 -0
- package/release-manager/dist/utils/env.js +308 -0
- package/release-manager/dist/utils/env.js.map +1 -0
- package/release-manager/dist/utils/logger.d.ts +15 -0
- package/release-manager/dist/utils/logger.d.ts.map +1 -0
- package/release-manager/dist/utils/logger.js +30 -0
- package/release-manager/dist/utils/logger.js.map +1 -0
- package/release-manager/dist/utils/workspace-divergence.d.ts +36 -0
- package/release-manager/dist/utils/workspace-divergence.d.ts.map +1 -0
- package/release-manager/dist/utils/workspace-divergence.js +87 -0
- package/release-manager/dist/utils/workspace-divergence.js.map +1 -0
- package/release-manager/package.json +78 -0
|
@@ -8,9 +8,10 @@ import { appendUpdateHistory } from './update-history.js';
|
|
|
8
8
|
import { checkOpenClawGateway, stopOpenClawGateway, restartOpenClawGateway, } from '../utils/gateway.js';
|
|
9
9
|
import { migrateLegacyExtensionBackups, reservePdBackupDestination, resolvePdBackupsRoot, } from '../utils/pd-backups.js';
|
|
10
10
|
import { resolveExtensionsDir, resolveUpdateLayout, resolvePluginDir, readCurrentVersion, } from '../utils/installed-layout.js';
|
|
11
|
-
import { ActivationCompatibilityReadModel } from '@principles/core/runtime-v2';
|
|
11
|
+
import { ActivationCompatibilityReadModel, isFeatureEnabled } from '@principles/core/runtime-v2';
|
|
12
12
|
import { collectFileDepLinkSpecs } from '../utils/update-links.js';
|
|
13
|
-
import { updateMutationController, LEGACY_MUTATION_AUTHORITY, } from '../update/mutation-controller.js';
|
|
13
|
+
import { updateMutationController, LEGACY_MUTATION_AUTHORITY, RELEASE_MANAGER_AUTHORITY, MUTATION_KINDS, } from '../update/mutation-controller.js';
|
|
14
|
+
import { loadPdConfig, computeFlagsFromLoadResult } from '../config/pd-config-store.js';
|
|
14
15
|
/**
|
|
15
16
|
* Legacy rule contract preflight (2026-08-19): refuse to swap the runtime
|
|
16
17
|
* while an ACTIVE owner-approved rule still depends on a RuleHost contract
|
|
@@ -904,6 +905,11 @@ function ensureRuntimeResolutionLinks(layout, tempDir) {
|
|
|
904
905
|
{ manifestDir: path.join(tempDir, 'install-layout'), deployedDir: layout.installLayoutDir },
|
|
905
906
|
{ manifestDir: path.join(tempDir, 'core'), deployedDir: layout.coreDir },
|
|
906
907
|
{ manifestDir: path.join(tempDir, 'plugin'), deployedDir: layout.pluginDir },
|
|
908
|
+
// PRI-672: staged release-manager component (npm name
|
|
909
|
+
// create-principles-disciple). Its staged manifest carries the
|
|
910
|
+
// file:../install-layout ref, and the staged console's manifest carries
|
|
911
|
+
// file:../release-manager — both derive their resolution links here.
|
|
912
|
+
{ manifestDir: path.join(tempDir, 'release-manager'), deployedDir: layout.releaseManagerDir },
|
|
907
913
|
];
|
|
908
914
|
const readStagedDependencies = (manifestDir) => {
|
|
909
915
|
try {
|
|
@@ -1152,6 +1158,18 @@ async function doInlineFullUpdate(workspaceDir) {
|
|
|
1152
1158
|
if (fs.existsSync(path.join(installLayoutSrc, 'package.json')) && fs.existsSync(path.join(installLayoutSrc, 'dist'))) {
|
|
1153
1159
|
copyDirRecursive(installLayoutSrc, layout.installLayoutDir, SKIP_DIRS);
|
|
1154
1160
|
}
|
|
1161
|
+
// PRI-672: the release-manager component (npm name
|
|
1162
|
+
// create-principles-disciple — the ReleaseManager authority module the
|
|
1163
|
+
// updated console imports) must land BEFORE the swap and its resolution
|
|
1164
|
+
// link, same PRI-561 ordering as host-runtime/install-layout. Conditioned
|
|
1165
|
+
// on the staged component so updates from tarballs published before this
|
|
1166
|
+
// component existed simply skip it (their console does not import it).
|
|
1167
|
+
const releaseManagerSrc = path.join(tempDir, 'release-manager');
|
|
1168
|
+
if (fs.existsSync(releaseManagerSrc) &&
|
|
1169
|
+
fs.existsSync(path.join(releaseManagerSrc, 'package.json')) &&
|
|
1170
|
+
fs.existsSync(path.join(releaseManagerSrc, 'dist'))) {
|
|
1171
|
+
copyDirRecursive(releaseManagerSrc, layout.releaseManagerDir, SKIP_DIRS);
|
|
1172
|
+
}
|
|
1155
1173
|
const { error: linkError, quarantined } = ensureRuntimeResolutionLinks(layout, tempDir);
|
|
1156
1174
|
reconciledQuarantine = quarantined;
|
|
1157
1175
|
if (linkError) {
|
|
@@ -1321,6 +1339,33 @@ async function doInlineFullUpdate(workspaceDir) {
|
|
|
1321
1339
|
* registers under `release-manager` for the same kinds and this route layer
|
|
1322
1340
|
* needs no further change.
|
|
1323
1341
|
*/
|
|
1342
|
+
/**
|
|
1343
|
+
* Compute the legacy update-check response body (PRI-659 handler body, split
|
|
1344
|
+
* out in PRI-672 so the ReleaseManager-governed check can serve the exact
|
|
1345
|
+
* same wire contract). Behavior is unchanged: degraded ERR-002 shape when the
|
|
1346
|
+
* current version cannot be determined, network checks otherwise.
|
|
1347
|
+
*/
|
|
1348
|
+
async function computeLegacyUpdateCheck(pluginDir) {
|
|
1349
|
+
// ERR-002 / Runtime Contract Rule 9: 当无法确定当前版本时(如插件未安装),
|
|
1350
|
+
// 返回 degraded 状态 + reason,而非 500。前端 validateUpdateStatus 要求
|
|
1351
|
+
// currentVersion/latestVersion 为 string,hasUpdate 为 boolean。
|
|
1352
|
+
const currentVersion = readCurrentVersion(pluginDir);
|
|
1353
|
+
const codexInstalled = detectCodexInstall();
|
|
1354
|
+
if (!currentVersion) {
|
|
1355
|
+
return {
|
|
1356
|
+
currentVersion: undefined,
|
|
1357
|
+
body: {
|
|
1358
|
+
hasUpdate: false,
|
|
1359
|
+
currentVersion: 'unknown',
|
|
1360
|
+
latestVersion: '',
|
|
1361
|
+
codexInstalled,
|
|
1362
|
+
error: 'Could not determine current version (plugin not installed)',
|
|
1363
|
+
},
|
|
1364
|
+
};
|
|
1365
|
+
}
|
|
1366
|
+
const result = await doCheckForUpdates(currentVersion);
|
|
1367
|
+
return { currentVersion, body: { ...result, codexInstalled } };
|
|
1368
|
+
}
|
|
1324
1369
|
function legacyCheckMutation(req, res, ctx) {
|
|
1325
1370
|
return (async () => {
|
|
1326
1371
|
const pluginDir = resolvePluginDir(ctx.workspaceDir);
|
|
@@ -1329,23 +1374,8 @@ function legacyCheckMutation(req, res, ctx) {
|
|
|
1329
1374
|
return;
|
|
1330
1375
|
}
|
|
1331
1376
|
try {
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
// currentVersion/latestVersion 为 string,hasUpdate 为 boolean。
|
|
1335
|
-
const currentVersion = readCurrentVersion(pluginDir);
|
|
1336
|
-
const codexInstalled = detectCodexInstall();
|
|
1337
|
-
if (!currentVersion) {
|
|
1338
|
-
sendSuccess(res, {
|
|
1339
|
-
hasUpdate: false,
|
|
1340
|
-
currentVersion: 'unknown',
|
|
1341
|
-
latestVersion: '',
|
|
1342
|
-
codexInstalled,
|
|
1343
|
-
error: 'Could not determine current version (plugin not installed)',
|
|
1344
|
-
});
|
|
1345
|
-
return;
|
|
1346
|
-
}
|
|
1347
|
-
const result = await doCheckForUpdates(currentVersion);
|
|
1348
|
-
sendSuccess(res, { ...result, codexInstalled });
|
|
1377
|
+
const { body } = await computeLegacyUpdateCheck(pluginDir);
|
|
1378
|
+
sendSuccess(res, body);
|
|
1349
1379
|
}
|
|
1350
1380
|
catch (err) {
|
|
1351
1381
|
sendError(res, 500, 'update_check_error', err instanceof Error ? err.message : 'Unknown error');
|
|
@@ -1473,6 +1503,140 @@ updateMutationController.register('check', { name: LEGACY_MUTATION_AUTHORITY, ha
|
|
|
1473
1503
|
updateMutationController.register('apply', { name: LEGACY_MUTATION_AUTHORITY, handler: legacyApplyMutation });
|
|
1474
1504
|
updateMutationController.register('apply-full', { name: LEGACY_MUTATION_AUTHORITY, handler: legacyApplyFullMutation });
|
|
1475
1505
|
updateMutationController.register('rollback', { name: LEGACY_MUTATION_AUTHORITY, handler: legacyRollbackMutation });
|
|
1506
|
+
let releaseManagerModuleState = { state: 'unattempted' };
|
|
1507
|
+
function releaseManagerFlagEnabled(workspaceDir) {
|
|
1508
|
+
const flags = computeFlagsFromLoadResult(loadPdConfig(workspaceDir));
|
|
1509
|
+
return isFeatureEnabled(flags, 'release_manager_shadow');
|
|
1510
|
+
}
|
|
1511
|
+
function fallbackToLegacyForAllKinds(reason) {
|
|
1512
|
+
for (const kind of MUTATION_KINDS) {
|
|
1513
|
+
updateMutationController.unregister(kind, RELEASE_MANAGER_AUTHORITY);
|
|
1514
|
+
updateMutationController.setFallbackReason(kind, reason);
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
/**
|
|
1518
|
+
* Governed check dispatch (kind `check` only, flag on, readiness ready at
|
|
1519
|
+
* registration time). Runs the ReleaseManager shadow check for governance and
|
|
1520
|
+
* parity evidence, then serves the legacy-computed response body — byte-for-
|
|
1521
|
+
* byte the legacy contract. On a ReleaseManager refusal the response headers
|
|
1522
|
+
* are re-annotated to the explicit fallback and the legacy body is served
|
|
1523
|
+
* anyway: check is read-only, so the fallback cannot leave partial state.
|
|
1524
|
+
*/
|
|
1525
|
+
async function runReleaseManagerCheckDispatch(mod, req, res, ctx) {
|
|
1526
|
+
if (req.method !== 'GET') {
|
|
1527
|
+
sendMethodNotAllowed(res);
|
|
1528
|
+
return;
|
|
1529
|
+
}
|
|
1530
|
+
const pluginDir = resolvePluginDir(ctx.workspaceDir);
|
|
1531
|
+
// One legacy computation feeds BOTH the shadow comparison (via legacyCheck)
|
|
1532
|
+
// and the response body — a governed check never doubles network cost.
|
|
1533
|
+
let legacyOnce = null;
|
|
1534
|
+
const legacyComputed = () => {
|
|
1535
|
+
legacyOnce ??= () => computeLegacyUpdateCheck(pluginDir);
|
|
1536
|
+
return legacyOnce();
|
|
1537
|
+
};
|
|
1538
|
+
let decisionSource = null;
|
|
1539
|
+
const authority = mod.createReleaseManagerAuthority({
|
|
1540
|
+
pdHome: path.join(os.homedir(), '.pd'),
|
|
1541
|
+
metadataBaseUrl: process.env.PD_RELEASE_METADATA_URL,
|
|
1542
|
+
legacyCheck: async (currentVersion) => {
|
|
1543
|
+
if (decisionSource === null)
|
|
1544
|
+
return null;
|
|
1545
|
+
return decisionSource(currentVersion);
|
|
1546
|
+
},
|
|
1547
|
+
});
|
|
1548
|
+
decisionSource = async () => {
|
|
1549
|
+
const computed = await legacyComputed();
|
|
1550
|
+
if (computed.currentVersion === undefined)
|
|
1551
|
+
return null;
|
|
1552
|
+
const raw = computed.body;
|
|
1553
|
+
return {
|
|
1554
|
+
source: 'legacy-updater',
|
|
1555
|
+
latestVersion: typeof raw.latestVersion === 'string' && raw.latestVersion.length > 0 ? raw.latestVersion : null,
|
|
1556
|
+
updateAvailable: raw.hasUpdate === true,
|
|
1557
|
+
};
|
|
1558
|
+
};
|
|
1559
|
+
if (authority.installStatus === null || !authority.kinds.check.ready) {
|
|
1560
|
+
// Readiness flipped between registration sync and dispatch — explicit
|
|
1561
|
+
// fallback, never a half-governed check.
|
|
1562
|
+
const reasons = authority.installStatus === null
|
|
1563
|
+
? 'install_state_corrupt'
|
|
1564
|
+
: authority.kinds.check.reasons.join(',');
|
|
1565
|
+
res.setHeader('X-PD-Mutation-Authority', `${LEGACY_MUTATION_AUTHORITY} (preferred: ${RELEASE_MANAGER_AUTHORITY} unavailable)`);
|
|
1566
|
+
res.setHeader('X-PD-Mutation-Fallback-Reason', `release_manager_unavailable:${reasons}`);
|
|
1567
|
+
await legacyCheckMutation(req, res, ctx);
|
|
1568
|
+
return;
|
|
1569
|
+
}
|
|
1570
|
+
try {
|
|
1571
|
+
const check = await authority.manager.check(authority.installStatus.channel);
|
|
1572
|
+
const comparison = check.shadowComparison;
|
|
1573
|
+
const agrees = comparison.agrees === null ? 'unknown' : String(comparison.agrees);
|
|
1574
|
+
console.log(`[release-manager] governed update check served (channel=${check.channel}, agrees=${agrees}${comparison.note ? `, note: ${comparison.note}` : ''})`);
|
|
1575
|
+
}
|
|
1576
|
+
catch (error) {
|
|
1577
|
+
const mapped = mod.mapReleaseManagerErrorToFallback(error);
|
|
1578
|
+
console.log(`[release-manager] governed update check refused (${mapped.reason}) — explicit fallback to ${LEGACY_MUTATION_AUTHORITY}`);
|
|
1579
|
+
res.setHeader('X-PD-Mutation-Authority', `${LEGACY_MUTATION_AUTHORITY} (preferred: ${RELEASE_MANAGER_AUTHORITY} unavailable: ${mapped.reason})`);
|
|
1580
|
+
res.setHeader('X-PD-Mutation-Fallback-Reason', `release_manager_unavailable:${mapped.reason}`);
|
|
1581
|
+
}
|
|
1582
|
+
try {
|
|
1583
|
+
const { body } = await legacyComputed();
|
|
1584
|
+
sendSuccess(res, body);
|
|
1585
|
+
}
|
|
1586
|
+
catch (err) {
|
|
1587
|
+
sendError(res, 500, 'update_check_error', err instanceof Error ? err.message : 'Unknown error');
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
/**
|
|
1591
|
+
* Bring the authority registration in line with current flag + readiness
|
|
1592
|
+
* state, then dispatch happens through the controller as usual. Idempotent;
|
|
1593
|
+
* the dynamic import is attempted once per server run.
|
|
1594
|
+
*/
|
|
1595
|
+
async function syncReleaseManagerAuthority(workspaceDir) {
|
|
1596
|
+
if (!releaseManagerFlagEnabled(workspaceDir)) {
|
|
1597
|
+
fallbackToLegacyForAllKinds('release_manager_shadow_disabled');
|
|
1598
|
+
return;
|
|
1599
|
+
}
|
|
1600
|
+
if (releaseManagerModuleState.state === 'unattempted') {
|
|
1601
|
+
try {
|
|
1602
|
+
const module = await import('create-principles-disciple/dist/update/release-manager-authority.js');
|
|
1603
|
+
releaseManagerModuleState = { state: 'loaded', module };
|
|
1604
|
+
}
|
|
1605
|
+
catch (error) {
|
|
1606
|
+
releaseManagerModuleState = { state: 'missing', detail: error instanceof Error ? error.message : String(error) };
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
if (releaseManagerModuleState.state === 'missing') {
|
|
1610
|
+
fallbackToLegacyForAllKinds('installer_missing');
|
|
1611
|
+
return;
|
|
1612
|
+
}
|
|
1613
|
+
const mod = releaseManagerModuleState.module;
|
|
1614
|
+
let authority;
|
|
1615
|
+
try {
|
|
1616
|
+
authority = mod.createReleaseManagerAuthority({
|
|
1617
|
+
pdHome: path.join(os.homedir(), '.pd'),
|
|
1618
|
+
metadataBaseUrl: process.env.PD_RELEASE_METADATA_URL,
|
|
1619
|
+
});
|
|
1620
|
+
}
|
|
1621
|
+
catch {
|
|
1622
|
+
fallbackToLegacyForAllKinds('authority_module_unavailable');
|
|
1623
|
+
return;
|
|
1624
|
+
}
|
|
1625
|
+
for (const rmKind of mod.RELEASE_MANAGER_AUTHORITY_KINDS) {
|
|
1626
|
+
const readiness = authority.kinds[rmKind];
|
|
1627
|
+
if (readiness.ready && rmKind === 'check') {
|
|
1628
|
+
updateMutationController.register('check', {
|
|
1629
|
+
name: RELEASE_MANAGER_AUTHORITY,
|
|
1630
|
+
handler: (req, res, ctx) => runReleaseManagerCheckDispatch(mod, req, res, ctx),
|
|
1631
|
+
});
|
|
1632
|
+
updateMutationController.setFallbackReason('check', null);
|
|
1633
|
+
}
|
|
1634
|
+
else {
|
|
1635
|
+
updateMutationController.unregister(rmKind, RELEASE_MANAGER_AUTHORITY);
|
|
1636
|
+
updateMutationController.setFallbackReason(rmKind, `release_manager_unavailable:${readiness.reasons.join(',')}`);
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1476
1640
|
const UPDATE_MUTATION_KINDS = new Map([
|
|
1477
1641
|
['/check', 'check'],
|
|
1478
1642
|
['/apply', 'apply'],
|
|
@@ -1485,5 +1649,9 @@ export async function handleUpdateRoute(req, res, workspaceDir, subPath) {
|
|
|
1485
1649
|
sendNotFound(res, `Update route not found: ${subPath}`);
|
|
1486
1650
|
return;
|
|
1487
1651
|
}
|
|
1652
|
+
// PRI-672: align the authority registration with the current flag +
|
|
1653
|
+
// readiness state before the controller resolves the authority. Pure
|
|
1654
|
+
// routing/decision work — no runtime mutation happens here.
|
|
1655
|
+
await syncReleaseManagerAuthority(workspaceDir);
|
|
1488
1656
|
await updateMutationController.dispatch(req, res, { workspaceDir }, kind);
|
|
1489
1657
|
}
|
|
@@ -57,6 +57,13 @@ export interface MutationGovernanceInfo {
|
|
|
57
57
|
readonly preferred: string;
|
|
58
58
|
readonly fallback: boolean;
|
|
59
59
|
readonly available: readonly string[];
|
|
60
|
+
/**
|
|
61
|
+
* PRI-672: why the fallback authority is serving (set by the wiring when the
|
|
62
|
+
* preferred authority is unregistered/unavailable). Omitted when the wiring
|
|
63
|
+
* has no reason to report — e.g. before any dispatch, or while the preferred
|
|
64
|
+
* authority serves.
|
|
65
|
+
*/
|
|
66
|
+
readonly fallbackReason?: string;
|
|
60
67
|
}
|
|
61
68
|
export interface ResolvedAuthority {
|
|
62
69
|
readonly authority: MutationAuthority;
|
|
@@ -64,6 +71,17 @@ export interface ResolvedAuthority {
|
|
|
64
71
|
}
|
|
65
72
|
export declare class MutationController {
|
|
66
73
|
private readonly authorities;
|
|
74
|
+
/** PRI-672: per-kind reason the fallback is serving (machine-readable, rc-9). */
|
|
75
|
+
private readonly fallbackReasons;
|
|
76
|
+
/**
|
|
77
|
+
* Record why the fallback authority is currently serving `kind` (e.g.
|
|
78
|
+
* `release_manager_shadow_disabled` or `release_manager_unavailable:…`).
|
|
79
|
+
* Emitted as the `X-PD-Mutation-Fallback-Reason` header whenever a dispatch
|
|
80
|
+
* actually resolves to the fallback, and surfaced by describeGovernance().
|
|
81
|
+
* Pass null to clear.
|
|
82
|
+
*/
|
|
83
|
+
setFallbackReason(kind: MutationKind, reason: string | null): void;
|
|
84
|
+
getFallbackReason(kind: MutationKind): string | undefined;
|
|
67
85
|
register(kind: MutationKind, authority: MutationAuthority): void;
|
|
68
86
|
unregister(kind: MutationKind, name: string): boolean;
|
|
69
87
|
hasAuthority(kind: MutationKind, name: string): boolean;
|
|
@@ -13,6 +13,26 @@ export const PREFERRED_MUTATION_AUTHORITY = RELEASE_MANAGER_AUTHORITY;
|
|
|
13
13
|
export const MUTATION_KINDS = ['check', 'apply', 'apply-full', 'rollback'];
|
|
14
14
|
export class MutationController {
|
|
15
15
|
authorities = new Map();
|
|
16
|
+
/** PRI-672: per-kind reason the fallback is serving (machine-readable, rc-9). */
|
|
17
|
+
fallbackReasons = new Map();
|
|
18
|
+
/**
|
|
19
|
+
* Record why the fallback authority is currently serving `kind` (e.g.
|
|
20
|
+
* `release_manager_shadow_disabled` or `release_manager_unavailable:…`).
|
|
21
|
+
* Emitted as the `X-PD-Mutation-Fallback-Reason` header whenever a dispatch
|
|
22
|
+
* actually resolves to the fallback, and surfaced by describeGovernance().
|
|
23
|
+
* Pass null to clear.
|
|
24
|
+
*/
|
|
25
|
+
setFallbackReason(kind, reason) {
|
|
26
|
+
if (reason === null) {
|
|
27
|
+
this.fallbackReasons.delete(kind);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
this.fallbackReasons.set(kind, reason);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
getFallbackReason(kind) {
|
|
34
|
+
return this.fallbackReasons.get(kind);
|
|
35
|
+
}
|
|
16
36
|
register(kind, authority) {
|
|
17
37
|
let table = this.authorities.get(kind);
|
|
18
38
|
if (table === undefined) {
|
|
@@ -61,6 +81,10 @@ export class MutationController {
|
|
|
61
81
|
? `${authority.name} (preferred: ${PREFERRED_MUTATION_AUTHORITY} not yet available)`
|
|
62
82
|
: authority.name;
|
|
63
83
|
res.setHeader('X-PD-Mutation-Authority', headerValue);
|
|
84
|
+
const fallbackReason = fallback ? this.fallbackReasons.get(kind) : undefined;
|
|
85
|
+
if (fallbackReason !== undefined) {
|
|
86
|
+
res.setHeader('X-PD-Mutation-Fallback-Reason', fallbackReason);
|
|
87
|
+
}
|
|
64
88
|
await authority.handler(req, res, ctx);
|
|
65
89
|
}
|
|
66
90
|
/** Governance snapshot for observability and migration tests. */
|
|
@@ -77,6 +101,11 @@ export class MutationController {
|
|
|
77
101
|
const { authority, fallback } = this.resolveAuthority(kind);
|
|
78
102
|
info = { active: authority.name, preferred: PREFERRED_MUTATION_AUTHORITY, fallback, available };
|
|
79
103
|
}
|
|
104
|
+
if (info.fallback) {
|
|
105
|
+
const fallbackReason = this.fallbackReasons.get(kind);
|
|
106
|
+
if (fallbackReason !== undefined)
|
|
107
|
+
info = { ...info, fallbackReason };
|
|
108
|
+
}
|
|
80
109
|
snapshot[kind] = info;
|
|
81
110
|
}
|
|
82
111
|
return snapshot;
|
|
@@ -45,6 +45,7 @@ export function resolveUpdateLayout() {
|
|
|
45
45
|
hostRuntimeDir: paths.hostRuntimeDir,
|
|
46
46
|
pdCliDir: paths.pdCliDir,
|
|
47
47
|
installLayoutDir: paths.installLayoutDir,
|
|
48
|
+
releaseManagerDir: paths.releaseManagerDir,
|
|
48
49
|
hosts: resolution.manifest?.hosts ?? [],
|
|
49
50
|
};
|
|
50
51
|
}
|
|
@@ -55,6 +56,7 @@ export function resolveUpdateLayout() {
|
|
|
55
56
|
hostRuntimeDir: path.join(legacyPluginDir, 'host-runtime'),
|
|
56
57
|
pdCliDir: path.join(legacyPluginDir, 'pd-cli'),
|
|
57
58
|
installLayoutDir: path.join(legacyPluginDir, 'install-layout'),
|
|
59
|
+
releaseManagerDir: path.join(legacyPluginDir, 'release-manager'),
|
|
58
60
|
hosts: ['openclaw'],
|
|
59
61
|
};
|
|
60
62
|
}
|
package/console/package.json
CHANGED
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"@principles/core": "file:../core",
|
|
24
24
|
"@principles/host-runtime": "file:../host-runtime",
|
|
25
25
|
"@principles/install-layout": "file:../install-layout",
|
|
26
|
+
"create-principles-disciple": "file:../release-manager",
|
|
26
27
|
"principles-disciple": "file:../plugin",
|
|
27
28
|
"@radix-ui/react-alert-dialog": "^1.1.15",
|
|
28
29
|
"@radix-ui/react-dialog": "^1.1.15",
|
|
@@ -3722,6 +3722,16 @@ describe('SEC-BASE-4: log secret redaction & SQL injection guards', () => {
|
|
|
3722
3722
|
describe('SEC-BASE-5: network & config isolation guards', () => {
|
|
3723
3723
|
const REPO_ROOT = pathSync.resolve(__dirname, '../../../../..');
|
|
3724
3724
|
it('core does not import node:http / node:https / undici / fetch for business', () => {
|
|
3725
|
+
// PRI-683: pi-ai-http-transport.ts is the registered exception
|
|
3726
|
+
// (io-seam-registry.json `pi-ai-http-transport` seam). It owns the LLM
|
|
3727
|
+
// transport's undici Agent config; requests still originate from pi-ai.
|
|
3728
|
+
const registryPath = pathSync.join(REPO_ROOT, 'packages', 'principles-core', 'io-seam-registry.json');
|
|
3729
|
+
const registry = JSON.parse(fsSync.readFileSync(registryPath, 'utf8'));
|
|
3730
|
+
const registeredFiles = new Set();
|
|
3731
|
+
for (const seam of registry.seams) {
|
|
3732
|
+
for (const file of seam.files)
|
|
3733
|
+
registeredFiles.add(file);
|
|
3734
|
+
}
|
|
3725
3735
|
const coreDir = pathSync.join(REPO_ROOT, 'packages', 'principles-core', 'src');
|
|
3726
3736
|
const files = fsSync.readdirSync(coreDir, { recursive: true, encoding: 'utf8' })
|
|
3727
3737
|
.filter((f) => typeof f === 'string' && f.endsWith('.ts') && !f.includes('__tests__'));
|
|
@@ -3729,14 +3739,19 @@ describe('SEC-BASE-5: network & config isolation guards', () => {
|
|
|
3729
3739
|
for (const f of files) {
|
|
3730
3740
|
const content = fsSync.readFileSync(pathSync.join(coreDir, f), 'utf8');
|
|
3731
3741
|
const lines = content.split('\n');
|
|
3742
|
+
const isRegisteredSeam = registeredFiles.has(f.replace(/\\/g, '/'));
|
|
3732
3743
|
lines.forEach((line, idx) => {
|
|
3733
3744
|
if (/^import\s+type/.test(line.trim()))
|
|
3734
3745
|
return;
|
|
3735
3746
|
if (/from\s+['"]node:http['"]/.test(line) || /from\s+['"]node:https['"]/.test(line)
|
|
3736
3747
|
|| /from\s+['"]undici['"]/.test(line) || /from\s+['"]node-fetch['"]/.test(line)) {
|
|
3748
|
+
if (isRegisteredSeam)
|
|
3749
|
+
return;
|
|
3737
3750
|
violations.push(`${f}:${idx + 1}: ${line.trim()}`);
|
|
3738
3751
|
}
|
|
3739
3752
|
if (!/^\s*(\/\/|\/\*|\*)/.test(line) && /\bfetch\s*\(/.test(line) && !/import/.test(line)) {
|
|
3753
|
+
if (isRegisteredSeam)
|
|
3754
|
+
return;
|
|
3740
3755
|
violations.push(`${f}:${idx + 1}: ${line.trim()}`);
|
|
3741
3756
|
}
|
|
3742
3757
|
});
|