create-principles-disciple 1.147.7 → 1.147.8

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.
Files changed (84) hide show
  1. package/_release/product-identity.json +1 -1
  2. package/core/dist/host/host-installer.d.ts +15 -0
  3. package/core/dist/host/host-installer.d.ts.map +1 -1
  4. package/core/dist/host/host-installer.js.map +1 -1
  5. package/core/dist/runtime-v2/feature-flags/feature-flag-contract.js +1 -1
  6. package/core/dist/runtime-v2/feature-flags/feature-flag-contract.js.map +1 -1
  7. package/core/dist/runtime-v2/feature-flags/feature-flag-lifecycle.js +2 -2
  8. package/core/dist/runtime-v2/feature-flags/feature-flag-lifecycle.js.map +1 -1
  9. package/core/dist/runtime-v2/pain-recall-capability.d.ts.map +1 -1
  10. package/core/dist/runtime-v2/pain-recall-capability.js +53 -2
  11. package/core/dist/runtime-v2/pain-recall-capability.js.map +1 -1
  12. package/core/dist/runtime-v2/pain-recall-read-model.d.ts.map +1 -1
  13. package/core/dist/runtime-v2/pain-recall-read-model.js +60 -5
  14. package/core/dist/runtime-v2/pain-recall-read-model.js.map +1 -1
  15. package/core/dist/runtime-v2/signal-collector/keyword-stage.d.ts.map +1 -1
  16. package/core/dist/runtime-v2/signal-collector/keyword-stage.js +35 -0
  17. package/core/dist/runtime-v2/signal-collector/keyword-stage.js.map +1 -1
  18. package/core/package.json +1 -1
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +6 -29
  21. package/dist/index.js.map +1 -1
  22. package/dist/install-summary.d.ts +38 -0
  23. package/dist/install-summary.d.ts.map +1 -0
  24. package/dist/install-summary.js +115 -0
  25. package/dist/install-summary.js.map +1 -0
  26. package/dist/installer.d.ts +36 -0
  27. package/dist/installer.d.ts.map +1 -1
  28. package/dist/installer.js +120 -26
  29. package/dist/installer.js.map +1 -1
  30. package/dist/installers/workbuddy-host-installer.d.ts +51 -17
  31. package/dist/installers/workbuddy-host-installer.d.ts.map +1 -1
  32. package/dist/installers/workbuddy-host-installer.js +510 -186
  33. package/dist/installers/workbuddy-host-installer.js.map +1 -1
  34. package/dist/prompts.js +1 -1
  35. package/dist/prompts.js.map +1 -1
  36. package/host-runtime/dist/governance-signal-admission.d.ts +2 -2
  37. package/host-runtime/dist/governance-signal-admission.js +2 -6
  38. package/host-runtime/package.json +1 -1
  39. package/package.json +3 -3
  40. package/pd-cli/dist/commands/health-mcp.d.ts +19 -0
  41. package/pd-cli/dist/commands/health-mcp.d.ts.map +1 -1
  42. package/pd-cli/dist/commands/health-mcp.js +226 -0
  43. package/pd-cli/dist/commands/health-mcp.js.map +1 -1
  44. package/pd-cli/dist/commands/health.d.ts.map +1 -1
  45. package/pd-cli/dist/commands/health.js +18 -1
  46. package/pd-cli/dist/commands/health.js.map +1 -1
  47. package/pd-cli/dist/commands/mcp-logs-export.d.ts +7 -0
  48. package/pd-cli/dist/commands/mcp-logs-export.d.ts.map +1 -0
  49. package/pd-cli/dist/commands/mcp-logs-export.js +267 -0
  50. package/pd-cli/dist/commands/mcp-logs-export.js.map +1 -0
  51. package/pd-cli/dist/commands/workbuddy-worker.d.ts.map +1 -1
  52. package/pd-cli/dist/commands/workbuddy-worker.js +2 -1
  53. package/pd-cli/dist/commands/workbuddy-worker.js.map +1 -1
  54. package/pd-cli/dist/index.js +35 -0
  55. package/pd-cli/dist/index.js.map +1 -1
  56. package/pd-cli/dist/services/zip-writer.d.ts +6 -0
  57. package/pd-cli/dist/services/zip-writer.d.ts.map +1 -0
  58. package/pd-cli/dist/services/zip-writer.js +97 -0
  59. package/pd-cli/dist/services/zip-writer.js.map +1 -0
  60. package/pd-mcp-server/dist/index.d.ts +1 -0
  61. package/pd-mcp-server/dist/index.js +167 -10
  62. package/pd-mcp-server/dist/log-file.d.ts +26 -0
  63. package/pd-mcp-server/dist/log-file.js +312 -0
  64. package/pd-mcp-server/dist/logging.d.ts +2 -1
  65. package/pd-mcp-server/dist/logging.js +25 -14
  66. package/pd-mcp-server/dist/server.js +78 -24
  67. package/pd-mcp-server/dist/version.d.ts +1 -1
  68. package/pd-mcp-server/dist/version.js +1 -1
  69. package/pd-mcp-server/dist/workspace.d.ts +3 -0
  70. package/pd-mcp-server/dist/workspace.js +5 -0
  71. package/pd-mcp-server/package.json +1 -1
  72. package/plugin/dist/bundle.js +274 -273
  73. package/plugin/dist/openclaw.plugin.json +1 -1
  74. package/plugin/mcp/launcher.cjs +561 -0
  75. package/plugin/openclaw.plugin.json +1 -1
  76. package/plugin/package.json +1 -1
  77. package/release-manager/dist/installer.js +120 -26
  78. package/release-manager/dist/installers/workbuddy-host-installer.js +510 -186
  79. package/release-manager/package.json +1 -1
  80. package/workbuddy-adapter/dist/pd-hook.js +3 -2
  81. package/workbuddy-adapter/package.json +1 -1
  82. package/workbuddy-adapter/plugin/.codebuddy-plugin/plugin.json +1 -1
  83. package/workbuddy-adapter/plugin/mcp/launcher.cjs +215 -1
  84. package/workbuddy-adapter/plugin/skills/pd-pain-signal/SKILL.md +4 -0
package/dist/installer.js CHANGED
@@ -3444,40 +3444,124 @@ function assertUsableWorkspaceDir(workspaceDir) {
3444
3444
  'Re-run with the path quoted, so the shell cannot strip its separators:\n' +
3445
3445
  ' --workspace "D:\\.openclaw\\workspace"');
3446
3446
  }
3447
- async function createConfigFile(workspaceDir, channels) {
3448
- const configDir = getOpenClawDir();
3449
- const configPath = path.join(configDir, 'principles-disciple.json');
3447
+ /**
3448
+ * Where the OpenClaw plugin (and therefore the MCP launcher) reads the
3449
+ * Owner-declared governance workspace. The gateway process, hook processes and
3450
+ * MCP children all run with different environments, and the MCP child has its
3451
+ * environment sanitized by the host (PD_WORKSPACE_DIR / HOME are stripped), so
3452
+ * this FILE is the only signal every one of them can see.
3453
+ */
3454
+ const OPENCLAW_PD_CONFIG_FILENAME = 'principles-disciple.json';
3455
+ function describeError(error) {
3456
+ return error instanceof Error ? error.message : String(error);
3457
+ }
3458
+ /** Same-directory identity for a workspace pointer (Windows is case-insensitive). */
3459
+ function sameWorkspaceTarget(left, right) {
3460
+ const normalize = (value) => {
3461
+ const resolved = path.resolve(value);
3462
+ const trimmed = resolved.length > 1 ? resolved.replace(/[\\/]+$/, '') : resolved;
3463
+ return process.platform === 'win32' ? trimmed.toLowerCase() : trimmed;
3464
+ };
3465
+ return normalize(left) === normalize(right);
3466
+ }
3467
+ /**
3468
+ * Read the existing declaration as UNTRUSTED input (it is a plain file on disk)
3469
+ * and classify it. Never overwrites and never silently repairs anything.
3470
+ */
3471
+ export function inspectOpenClawWorkspaceDeclaration(workspaceDir) {
3472
+ const configPath = path.join(getOpenClawDir(), OPENCLAW_PD_CONFIG_FILENAME);
3473
+ if (!existsSync(configPath))
3474
+ return { configPath, state: 'absent' };
3475
+ let raw;
3476
+ try {
3477
+ raw = readFileSync(configPath, 'utf-8');
3478
+ }
3479
+ catch (e) {
3480
+ return { configPath, state: 'unreadable', reason: describeError(e) };
3481
+ }
3482
+ let parsed;
3483
+ try {
3484
+ parsed = JSON.parse(raw);
3485
+ }
3486
+ catch (e) {
3487
+ return { configPath, state: 'invalid', reason: `it is not valid JSON (${describeError(e)})` };
3488
+ }
3489
+ if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
3490
+ return { configPath, state: 'invalid', reason: 'the root value is not a JSON object' };
3491
+ }
3492
+ const declaredRaw = Object.hasOwn(parsed, 'workspace') ? Reflect.get(parsed, 'workspace') : undefined;
3493
+ if (typeof declaredRaw !== 'string' || declaredRaw.trim().length === 0) {
3494
+ return { configPath, state: 'invalid', reason: 'it has no non-empty string "workspace" field' };
3495
+ }
3496
+ const declared = declaredRaw.trim();
3497
+ if (!isUsableWorkspacePointer(declared)) {
3498
+ return {
3499
+ configPath,
3500
+ state: 'invalid',
3501
+ declaredWorkspace: declared,
3502
+ reason: 'the "workspace" value does not name one fixed absolute directory',
3503
+ };
3504
+ }
3505
+ if (!sameWorkspaceTarget(declared, workspaceDir)) {
3506
+ return { configPath, state: 'conflict', declaredWorkspace: declared };
3507
+ }
3508
+ return { configPath, state: 'compatible', declaredWorkspace: declared };
3509
+ }
3510
+ function throwOnIncompatibleDeclaration(inspection, workspaceDir) {
3511
+ if (inspection.state === 'absent' || inspection.state === 'compatible')
3512
+ return;
3513
+ if (inspection.state === 'conflict') {
3514
+ throw new Error('An existing OpenClaw PD config declares a DIFFERENT workspace; it was left unchanged.\n' +
3515
+ ` Config: ${inspection.configPath}\n` +
3516
+ ` Declared: ${JSON.stringify(inspection.declaredWorkspace)}\n` +
3517
+ ` Requested: ${JSON.stringify(path.resolve(workspaceDir))}\n` +
3518
+ 'The pd-recall MCP server can only serve the workspace declared in this file, so the installer\n' +
3519
+ 'never overwrites it. Otherwise the host would report a successful install while recall served\n' +
3520
+ 'another workspace.\n' +
3521
+ ` To keep the existing workspace, re-run with --workspace ${JSON.stringify(inspection.declaredWorkspace)}.\n` +
3522
+ ` To switch deliberately, back up ${inspection.configPath}, remove it, then re-run for the new workspace.`);
3523
+ }
3524
+ throw new Error(`The existing OpenClaw PD config cannot be verified and was left unchanged (${inspection.reason}).\n` +
3525
+ ` Config: ${inspection.configPath}\n` +
3526
+ 'Expected a JSON object with an absolute "workspace" string.\n' +
3527
+ ' Fix it manually, or back it up and remove it, then re-run the installer.');
3528
+ }
3529
+ /**
3530
+ * Read-only preflight: refuse BEFORE any runtime mutation when the existing
3531
+ * declaration points somewhere else (or cannot be trusted). This is the check
3532
+ * that keeps an install from "succeeding" while pd-recall serves a different
3533
+ * workspace.
3534
+ */
3535
+ export function assertOpenClawWorkspaceDeclarationCompatible(workspaceDir) {
3536
+ throwOnIncompatibleDeclaration(inspectOpenClawWorkspaceDeclaration(workspaceDir), workspaceDir);
3537
+ }
3538
+ /**
3539
+ * Ensure the OpenClaw plugin can locate the governance workspace through the
3540
+ * file declaration. Idempotent: a compatible existing declaration is left
3541
+ * byte-identical (no rewrite, no installedAt churn). A conflicting/invalid one
3542
+ * fails loud and is never overwritten.
3543
+ */
3544
+ export async function ensureOpenClawWorkspaceDeclaration(workspaceDir, channels) {
3450
3545
  // Defense in depth: the same refusal the install entry makes, kept here
3451
3546
  // because this is the only writer of the pointer the plugin reads on every
3452
3547
  // hook, and other callers reach it without passing through install().
3453
3548
  assertUsableWorkspaceDir(workspaceDir);
3454
- let existingChannels = null;
3455
- let existingFeatures = null;
3456
- if (existsSync(configPath)) {
3457
- const existingRaw = readFileSync(configPath, 'utf-8');
3458
- const existing = JSON.parse(existingRaw);
3459
- if (existing !== null && typeof existing === 'object' && !Array.isArray(existing)) {
3460
- const existingObj = existing;
3461
- if (Object.hasOwn(existingObj, 'channels') && Array.isArray(existingObj.channels)) {
3462
- existingChannels = existingObj.channels.filter((c) => typeof c === 'string');
3463
- }
3464
- if (Object.hasOwn(existingObj, 'features') && Array.isArray(existingObj.features)) {
3465
- existingFeatures = existingObj.features.filter((f) => typeof f === 'string');
3466
- }
3467
- }
3549
+ const inspection = inspectOpenClawWorkspaceDeclaration(workspaceDir);
3550
+ throwOnIncompatibleDeclaration(inspection, workspaceDir);
3551
+ if (inspection.state === 'compatible') {
3552
+ return { configPath: inspection.configPath, action: 'unchanged' };
3468
3553
  }
3554
+ const resolvedWorkspace = path.resolve(workspaceDir);
3469
3555
  const config = {
3470
- workspace: workspaceDir,
3471
- state: path.join(workspaceDir, '.state'),
3472
- channels: existingChannels ?? channels,
3556
+ workspace: resolvedWorkspace,
3557
+ state: path.join(resolvedWorkspace, '.state'),
3558
+ channels,
3473
3559
  installedAt: new Date().toISOString(),
3474
3560
  mvpFirst: true,
3475
3561
  };
3476
- if (existingFeatures) {
3477
- config.features = existingFeatures;
3478
- }
3479
- await fse.ensureDir(configDir);
3480
- await fse.writeJson(configPath, config, { spaces: 2 });
3562
+ await fse.ensureDir(path.dirname(inspection.configPath));
3563
+ await fse.writeJson(inspection.configPath, config, { spaces: 2 });
3564
+ return { configPath: inspection.configPath, action: 'created' };
3481
3565
  }
3482
3566
  /**
3483
3567
  * ADR-0020 §2.3: Run host installers for the selected HostTarget.
@@ -3872,6 +3956,14 @@ transaction) {
3872
3956
  // (permissions / invalid path) flows into the unified failure result
3873
3957
  // below instead of rejecting the install() promise (P1 review finding).
3874
3958
  await fse.ensureDir(path.resolve(options.workspaceDir));
3959
+ // OpenClaw only: the MCP launcher re-derives the governance workspace from
3960
+ // this PD-owned file, because the host strips PD_WORKSPACE_DIR / HOME from
3961
+ // MCP children. An existing declaration for a DIFFERENT workspace must
3962
+ // refuse the install BEFORE any runtime mutation — otherwise the install
3963
+ // would report success while pd-recall served another workspace.
3964
+ if (installsOpenClaw(options.host)) {
3965
+ assertOpenClawWorkspaceDeclarationCompatible(options.workspaceDir);
3966
+ }
3875
3967
  if (spinner)
3876
3968
  updateProgress(spinner, stepIndex, 'Checking built plugin...');
3877
3969
  await checkBuiltPlugin(pluginDir);
@@ -4116,7 +4208,9 @@ transaction) {
4116
4208
  stepIndex++;
4117
4209
  if (spinner)
4118
4210
  updateProgress(spinner, stepIndex, 'Creating config...');
4119
- await createConfigFile(options.workspaceDir, options.channels);
4211
+ if (installsOpenClaw(options.host)) {
4212
+ await ensureOpenClawWorkspaceDeclaration(options.workspaceDir, options.channels);
4213
+ }
4120
4214
  stepIndex++;
4121
4215
  // PRI-686 Fix C: after pinning PD canonical, check OpenClaw's resolved
4122
4216
  // main-agent workspace against it. Read-only; a divergence means PD