create-principles-disciple 1.145.39 → 1.145.42

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 (53) hide show
  1. package/_release/product-identity.json +1 -1
  2. package/codex-adapter/dist/ingestion/catch-up.d.ts +1 -1
  3. package/codex-adapter/dist/ingestion/catch-up.js +10 -2
  4. package/codex-adapter/dist/pd-hook.js +6 -2
  5. package/codex-adapter/dist/worker/workspace-worker.js +2 -1
  6. package/codex-adapter/package.json +1 -1
  7. package/core/dist/host/host-installer.d.ts +13 -0
  8. package/core/dist/host/host-installer.d.ts.map +1 -1
  9. package/core/dist/host/host-installer.js.map +1 -1
  10. package/core/package.json +1 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +29 -0
  13. package/dist/index.js.map +1 -1
  14. package/dist/installer.d.ts.map +1 -1
  15. package/dist/installer.js +26 -1
  16. package/dist/installer.js.map +1 -1
  17. package/dist/installers/workbuddy-host-installer.d.ts +75 -0
  18. package/dist/installers/workbuddy-host-installer.d.ts.map +1 -1
  19. package/dist/installers/workbuddy-host-installer.js +178 -34
  20. package/dist/installers/workbuddy-host-installer.js.map +1 -1
  21. package/dist/utils/config-file-io.d.ts +10 -2
  22. package/dist/utils/config-file-io.d.ts.map +1 -1
  23. package/dist/utils/config-file-io.js +32 -9
  24. package/dist/utils/config-file-io.js.map +1 -1
  25. package/host-runtime/dist/workbuddy-worker-status.js +4 -1
  26. package/host-runtime/package.json +1 -1
  27. package/package.json +2 -2
  28. package/pd-cli/dist/services/pd-config-loader.d.ts +1 -1
  29. package/pd-cli/dist/services/pd-config-loader.d.ts.map +1 -1
  30. package/pd-cli/dist/services/pd-config-loader.js +9 -0
  31. package/pd-cli/dist/services/pd-config-loader.js.map +1 -1
  32. package/plugin/dist/bundle.js +1 -1
  33. package/plugin/dist/openclaw.plugin.json +1 -1
  34. package/plugin/openclaw.plugin.json +1 -1
  35. package/plugin/package.json +1 -1
  36. package/release-manager/dist/index.d.ts.map +1 -1
  37. package/release-manager/dist/index.js +29 -0
  38. package/release-manager/dist/index.js.map +1 -1
  39. package/release-manager/dist/installer.d.ts.map +1 -1
  40. package/release-manager/dist/installer.js +26 -1
  41. package/release-manager/dist/installer.js.map +1 -1
  42. package/release-manager/dist/installers/workbuddy-host-installer.d.ts +75 -0
  43. package/release-manager/dist/installers/workbuddy-host-installer.d.ts.map +1 -1
  44. package/release-manager/dist/installers/workbuddy-host-installer.js +178 -34
  45. package/release-manager/dist/installers/workbuddy-host-installer.js.map +1 -1
  46. package/release-manager/dist/utils/config-file-io.d.ts +10 -2
  47. package/release-manager/dist/utils/config-file-io.d.ts.map +1 -1
  48. package/release-manager/dist/utils/config-file-io.js +32 -9
  49. package/release-manager/dist/utils/config-file-io.js.map +1 -1
  50. package/release-manager/package.json +2 -2
  51. package/workbuddy-adapter/dist/pd-hook.js +5 -1
  52. package/workbuddy-adapter/dist/worker/workspace-worker.js +2 -1
  53. package/workbuddy-adapter/package.json +1 -1
@@ -151,6 +151,45 @@ export type FlagOverrideResult = {
151
151
  reason: string;
152
152
  nextAction: string;
153
153
  };
154
+ /**
155
+ * Enable/disable `features.host.workbuddy.enabled` in the GOVERNANCE
156
+ * workspace's .pd/config.yaml with a line-targeted edit (comments and unknown
157
+ * keys preserved), creating a loader-valid config from the installer template
158
+ * when absent. Atomic write; round-trip verified.
159
+ */
160
+ /**
161
+ * PRI-1064 (Owner directive 2026-10-31): governance is ON by default at
162
+ * install time. The only state preserved as OFF is an EXPLICIT opt-out
163
+ * (`enabled: false` the Owner wrote). A pre-existing config with sparse
164
+ * flags (e.g. left by a failed install round) no longer silently keeps
165
+ * governance off — the user saw "Install complete!" while every hook
166
+ * skipped with host.workbuddy_disabled.
167
+ * Both entries are validated and atomically committed in one file write;
168
+ * an already-correct config is left byte-identical (no rewrite).
169
+ */
170
+ export declare function ensureWorkbuddyGovernanceEnabled(governanceDir: string): FlagOverrideResult & {
171
+ hostExplicitOff: boolean;
172
+ keywordExplicitOff: boolean;
173
+ changed: boolean;
174
+ };
175
+ /**
176
+ * PRI-1064 review: the install summary must state BOTH gates.
177
+ *
178
+ * The first version derived the whole sentence from `hostExplicitOff` alone,
179
+ * so a config with `workbuddy_live_keyword_pain.enabled: false` was reported as
180
+ * "governance and four-term keyword Pain detection are ON" — a false summary
181
+ * of exactly the kind this change set out to remove. Each gate is now stated
182
+ * on its own, and an OFF state always names the flag the Owner wrote.
183
+ *
184
+ * Inherited verbatim by the PRI-1063 copy work, which keeps the flag ids
185
+ * dotted (they ARE the flat keys) but replaces the prose with paste-ready
186
+ * snippets.
187
+ */
188
+ export declare function describeGovernanceDefaults(state: {
189
+ hostExplicitOff: boolean;
190
+ keywordExplicitOff: boolean;
191
+ changed: boolean;
192
+ } | null, governanceDir: string): string;
154
193
  export declare function setWorkbuddyGovernanceFlag(governanceDir: string, enabled: boolean): FlagOverrideResult;
155
194
  /** Read the explicit host.workbuddy override state (null = no explicit override → registry default OFF). */
156
195
  export declare function readWorkbuddyGovernanceFlagOverride(governanceDir: string): boolean | null;
@@ -174,6 +213,42 @@ export interface WorkbuddyDetectDetails extends HostDetectResult {
174
213
  /** settings.json exists AND parsed (false also when unparsable — install fails loud there). */
175
214
  settingsExisted: boolean;
176
215
  }
216
+ export interface WorkbuddyEarlyPreflightDeps {
217
+ homeDir?: () => string;
218
+ /** Bash availability probe override (default: literal `bash -c "exit 0"`). */
219
+ probeBash?: () => {
220
+ ok: true;
221
+ } | {
222
+ ok: false;
223
+ detail: string;
224
+ };
225
+ /** Exclusive-open probe; returns the errno string when the file is held. */
226
+ probeHostFileLock?: (filePath: string) => string | undefined;
227
+ platform?: (typeof process)['platform'];
228
+ }
229
+ export type WorkbuddyEarlyPreflight = {
230
+ ok: true;
231
+ } | {
232
+ ok: false;
233
+ reason: string;
234
+ nextAction: string;
235
+ };
236
+ /**
237
+ * PRI-1062: hard preflights the main installer runs BEFORE any side effect.
238
+ *
239
+ * Call-site contract (enforced in installer.ts): this must run before the
240
+ * gateway pre-flight, because that block may STOP a running OpenClaw gateway.
241
+ * A refusal from here returns immediately and would otherwise leave the
242
+ * Owner's gateway down, since the restart is only honoured at the end of the
243
+ * install flow.
244
+ *
245
+ * A RUNNING WorkBuddy holds settings.json with exclusive sharing — the
246
+ * commit-stage atomic rename fails with EPERM after minutes of npm work and
247
+ * the whole install rolls back. Git Bash availability is equally knowable
248
+ * up front. Both checks are cheap (one bash spawn + two file opens) and
249
+ * fail with a nextAction naming the exact user action.
250
+ */
251
+ export declare function runWorkbuddyEarlyPreflight(deps?: WorkbuddyEarlyPreflightDeps): WorkbuddyEarlyPreflight;
177
252
  export declare class WorkBuddyHostInstaller implements HostInstaller {
178
253
  readonly hostId = "workbuddy";
179
254
  private readonly deps;
@@ -1 +1 @@
1
- {"version":3,"file":"workbuddy-host-installer.d.ts","sourceRoot":"","sources":["../../src/installers/workbuddy-host-installer.ts"],"names":[],"mappings":"AA2DA,OAAO,KAAK,EACV,aAAa,EACb,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,uBAAuB,CAAC;AAM/B,yFAAyF;AACzF,eAAO,MAAM,qBAAqB,wBAAwB,CAAC;AAC3D,qFAAqF;AACrF,eAAO,MAAM,0BAA0B,+BAA+B,CAAC;AACvE,+EAA+E;AAC/E,eAAO,MAAM,oBAAoB,mDAA2D,CAAC;AAiB7F,yEAAyE;AACzE,eAAO,MAAM,yBAAyB,UAA6E,CAAC;AA4DpH,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,0BAA0B;IACzC,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,MAAM,CAAC;IACvB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IACtC;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IACtC,gFAAgF;IAChF,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,uBAAuB,KAAK,sBAAsB,CAAC;CAChH;AAED,gGAAgG;AAChG,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,wFAAwF;IACxF,eAAe,EAAE,MAAM,CAAC;IACxB,8DAA8D;IAC9D,eAAe,EAAE,MAAM,CAAC;IACxB,8DAA8D;IAC9D,aAAa,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,0BAA0B;IAC1B,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAyBrE;AAoBD;;;;;;;;;GASG;AACH,wBAAgB,6BAA6B,CAC3C,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,EACrD,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,GACpC,MAAM,EAAE,CAkBV;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,GAAG,SAAS,CAU/D;AAID,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,OAAO,EAAE,IAAI,CAAA;CAAE,GAC3D;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,KAAK,CAAA;CAAE,GAC9C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpE,iFAAiF;AACjF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CAgC/D;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CA2C9I;AAID;;;;;;;;;GASG;AACH,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAG;IAAE,OAAO,CAAC,EAAE,sBAAsB,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CA4C9I;AAcD;;;;;;;GAOG;AACH,wBAAgB,iCAAiC,CAC/C,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,GACpB;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAmDlE;AA4CD,MAAM,MAAM,kBAAkB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AA6CxI,wBAAgB,0BAA0B,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,kBAAkB,CAqHtG;AAED,4GAA4G;AAC5G,wBAAgB,mCAAmC,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAYzF;AAmRD,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;IAC9D,qDAAqD;IACrD,SAAS,EAAE,OAAO,CAAC;IACnB,iCAAiC;IACjC,WAAW,EAAE,OAAO,CAAC;IACrB,uCAAuC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,UAAU,EAAE,OAAO,CAAC;IACpB,kDAAkD;IAClD,aAAa,EAAE,OAAO,CAAC;IACvB,sFAAsF;IACtF,YAAY,EAAE,OAAO,GAAG,IAAI,CAAC;IAC7B,qEAAqE;IACrE,gBAAgB,EAAE,OAAO,CAAC;IAC1B,4DAA4D;IAC5D,qBAAqB,EAAE,OAAO,CAAC;IAC/B,+FAA+F;IAC/F,eAAe,EAAE,OAAO,CAAC;CAC1B;AAmBD,qBAAa,sBAAuB,YAAW,aAAa;IAC1D,QAAQ,CAAC,MAAM,eAAe;IAE9B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAuC;IAE5D,YAAY,IAAI,GAAE,0BAA+B,EA0BhD;IAED,OAAO,CAAC,KAAK;IAIb;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,SAAS;IAejB,oGAAoG;IACpG,OAAO,CAAC,gBAAgB;IAwBlB,OAAO,CAAC,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAqKjE;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,OAAO,CAAC,6BAA6B;IAwDrC,OAAO,CAAC,cAAc;IA6EtB,OAAO,CAAC,yBAAyB;IAoBjC;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB;IAa9B;;;;;;OAMG;IACH,OAAO,CAAC,uBAAuB;IAoK/B,4FAA4F;IAC5F,wBAAwB,IAAI;QAAE,IAAI,EAAE,gBAAgB,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAQ9G;IAED,mEAAmE;IACnE,gBAAgB,IAAI,kBAAkB,CAGrC;IAED,oEAAoE;IACpE,iBAAiB,IAAI,kBAAkB,CAGtC;IAIK,SAAS,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA+KxE;IAED;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;IA8C1B,8EAA8E;IAC9E,OAAO,CAAC,mBAAmB;IAmB3B,MAAM,IAAI,gBAAgB,CAEzB;IAED,iHAAiH;IACjH,aAAa,IAAI,sBAAsB,CAyCtC;CACF"}
1
+ {"version":3,"file":"workbuddy-host-installer.d.ts","sourceRoot":"","sources":["../../src/installers/workbuddy-host-installer.ts"],"names":[],"mappings":"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"}
@@ -41,8 +41,8 @@
41
41
  * - rc-9-no-silent-fallback: engine-unreachable fallback is reported in the
42
42
  * result reason; every result carries reason + nextAction.
43
43
  */
44
- import { spawnSync } from 'node:child_process';
45
- import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, cpSync, writeFileSync } from 'node:fs';
44
+ import { spawnSync, execFileSync } from 'node:child_process';
45
+ import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, cpSync, writeFileSync, openSync, closeSync } from 'node:fs';
46
46
  import * as path from 'node:path';
47
47
  import * as yaml from 'js-yaml';
48
48
  import semver from 'semver';
@@ -487,44 +487,81 @@ function isEmptyFeaturesMapping(line) {
487
487
  * when absent. Atomic write; round-trip verified.
488
488
  */
489
489
  /**
490
- * On genuinely new WorkBuddy installations only, persist both gates in the
491
- * newly created governance workspace. Never change registry defaults: old
492
- * workspaces with sparse flags must NOT silently enable on upgrade.
493
- * Both entries are validated and atomically committed in one file write.
490
+ * PRI-1064 (Owner directive 2026-10-31): governance is ON by default at
491
+ * install time. The only state preserved as OFF is an EXPLICIT opt-out
492
+ * (`enabled: false` the Owner wrote). A pre-existing config with sparse
493
+ * flags (e.g. left by a failed install round) no longer silently keeps
494
+ * governance off — the user saw "Install complete!" while every hook
495
+ * skipped with host.workbuddy_disabled.
496
+ * Both entries are validated and atomically committed in one file write;
497
+ * an already-correct config is left byte-identical (no rewrite).
494
498
  */
495
- function enableFreshWorkbuddyKeywordPain(governanceDir) {
499
+ export function ensureWorkbuddyGovernanceEnabled(governanceDir) {
496
500
  const configPath = path.join(governanceDir, '.pd', 'config.yaml');
497
501
  let raw;
498
502
  try {
499
503
  raw = yaml.load(readFileSync(configPath, 'utf-8'));
500
504
  }
501
505
  catch {
502
- return { ok: false, reason: 'fresh_workbuddy_config_unreadable', nextAction: 'Repair governance config and retry.' };
506
+ return { ok: false, reason: 'fresh_workbuddy_config_unreadable', nextAction: 'Repair governance config and retry.', hostExplicitOff: false, keywordExplicitOff: false, changed: false };
503
507
  }
504
508
  if (!isRecord(raw) || !isRecord(raw.features)) {
505
- return { ok: false, reason: 'fresh_workbuddy_features_invalid', nextAction: 'Governance config needs a features mapping.' };
509
+ return { ok: false, reason: 'fresh_workbuddy_features_invalid', nextAction: 'Governance config needs a features mapping.', hostExplicitOff: false, keywordExplicitOff: false, changed: false };
506
510
  }
507
511
  const oldHost = raw.features['host.workbuddy'];
508
512
  const oldKeyword = raw.features.workbuddy_live_keyword_pain;
513
+ const hostExplicitOff = isRecord(oldHost) && oldHost.enabled === false;
514
+ const keywordExplicitOff = isRecord(oldKeyword) && oldKeyword.enabled === false;
509
515
  const features = {
510
516
  ...raw.features,
511
- 'host.workbuddy': { ...(isRecord(oldHost) ? oldHost : {}), enabled: true, category: WORKBUDDY_FLAG_CATEGORY },
512
- workbuddy_live_keyword_pain: { ...(isRecord(oldKeyword) ? oldKeyword : {}), enabled: true, category: WORKBUDDY_FLAG_CATEGORY },
517
+ 'host.workbuddy': { ...(isRecord(oldHost) ? oldHost : {}), enabled: !hostExplicitOff, category: WORKBUDDY_FLAG_CATEGORY },
518
+ workbuddy_live_keyword_pain: { ...(isRecord(oldKeyword) ? oldKeyword : {}), enabled: !keywordExplicitOff, category: WORKBUDDY_FLAG_CATEGORY },
513
519
  };
514
520
  const next = yaml.dump({ ...raw, features }, { lineWidth: -1, noRefs: true });
521
+ const alreadyCorrect = isRecord(oldHost) && oldHost.enabled === !hostExplicitOff && oldHost.category === WORKBUDDY_FLAG_CATEGORY
522
+ && isRecord(oldKeyword) && oldKeyword.enabled === !keywordExplicitOff && oldKeyword.category === WORKBUDDY_FLAG_CATEGORY;
523
+ if (alreadyCorrect) {
524
+ return { ok: true, configPath, enabled: !hostExplicitOff, hostExplicitOff, keywordExplicitOff, changed: false };
525
+ }
515
526
  try {
516
527
  const verify = yaml.load(next);
517
528
  if (!isRecord(verify) || !isRecord(verify.features) ||
518
- !isRecord(verify.features['host.workbuddy']) || verify.features['host.workbuddy'].enabled !== true ||
519
- !isRecord(verify.features.workbuddy_live_keyword_pain) || verify.features.workbuddy_live_keyword_pain.enabled !== true) {
520
- return { ok: false, reason: 'fresh_workbuddy_flags_verification_failed', nextAction: 'No changes written.' };
529
+ !isRecord(verify.features['host.workbuddy']) || verify.features['host.workbuddy'].enabled !== !hostExplicitOff ||
530
+ !isRecord(verify.features.workbuddy_live_keyword_pain) || verify.features.workbuddy_live_keyword_pain.enabled !== !keywordExplicitOff) {
531
+ return { ok: false, reason: 'fresh_workbuddy_flags_verification_failed', nextAction: 'No changes written.', hostExplicitOff, keywordExplicitOff, changed: false };
521
532
  }
522
533
  atomicReplaceTextFile(configPath, next);
523
534
  }
524
535
  catch {
525
- return { ok: false, reason: 'fresh_workbuddy_flag_write_failed', nextAction: 'Repair config storage and retry.' };
536
+ return { ok: false, reason: 'fresh_workbuddy_flag_write_failed', nextAction: 'Repair config storage and retry.', hostExplicitOff, keywordExplicitOff, changed: false };
526
537
  }
527
- return { ok: true, configPath, enabled: true };
538
+ return { ok: true, configPath, enabled: !hostExplicitOff, hostExplicitOff, keywordExplicitOff, changed: true };
539
+ }
540
+ /**
541
+ * PRI-1064 review: the install summary must state BOTH gates.
542
+ *
543
+ * The first version derived the whole sentence from `hostExplicitOff` alone,
544
+ * so a config with `workbuddy_live_keyword_pain.enabled: false` was reported as
545
+ * "governance and four-term keyword Pain detection are ON" — a false summary
546
+ * of exactly the kind this change set out to remove. Each gate is now stated
547
+ * on its own, and an OFF state always names the flag the Owner wrote.
548
+ *
549
+ * Inherited verbatim by the PRI-1063 copy work, which keeps the flag ids
550
+ * dotted (they ARE the flat keys) but replaces the prose with paste-ready
551
+ * snippets.
552
+ */
553
+ export function describeGovernanceDefaults(state, governanceDir) {
554
+ if (state === null) {
555
+ return ` Governance flag state is UNKNOWN — no governance config exists at ${governanceDir} (run "pd runtime init --workspace ${governanceDir}", then re-run the installer).`;
556
+ }
557
+ if (state.hostExplicitOff) {
558
+ return ' WorkBuddy governance is OFF — your explicit opt-out (features.host.workbuddy.enabled=false) was preserved; four-term keyword Pain detection is ON.';
559
+ }
560
+ const hostState = ` WorkBuddy governance is ON${state.changed ? ' (enabled by this install)' : ' (already enabled)'}`;
561
+ const keywordState = state.keywordExplicitOff
562
+ ? 'four-term keyword Pain detection is OFF — your explicit opt-out (features.workbuddy_live_keyword_pain.enabled=false) was preserved'
563
+ : 'four-term keyword Pain detection is ON';
564
+ return `${hostState}; ${keywordState}.`;
528
565
  }
529
566
  export function setWorkbuddyGovernanceFlag(governanceDir, enabled) {
530
567
  const configDir = path.join(governanceDir, '.pd');
@@ -937,6 +974,105 @@ function applyWorkbuddyGovernanceRuntimeProfile(governanceDir, profile) {
937
974
  return { ok: true, configPath, profileId: GOVERNANCE_PROFILE_ID, model, pendingAgents };
938
975
  }
939
976
  // ─── WorkBuddyHostInstaller ─────────────────────────────────────────────────
977
+ /** Shared Git Bash failure message (win32 hooks launch through bash). */
978
+ function gitBashUnavailableReason(detail) {
979
+ return {
980
+ reason: `git_bash_not_available: WorkBuddy executes command hooks through Git Bash on Windows, but "bash" is not resolvable (${detail}). Hooks would fail to launch.`,
981
+ nextAction: 'Install Git for Windows (or otherwise provide bash.exe on PATH), then re-run the installer.',
982
+ };
983
+ }
984
+ /** Default bash probe: literal program name + argv array, no shell. */
985
+ function defaultProbeBash() {
986
+ try {
987
+ execFileSync('bash', ['-c', 'exit 0'], { encoding: 'utf-8', timeout: 15_000, windowsHide: true });
988
+ return { ok: true };
989
+ }
990
+ catch (error) {
991
+ const err = error;
992
+ return { ok: false, detail: typeof err.status === 'number' ? `exit ${err.status}` : (err.message ?? 'unresolvable') };
993
+ }
994
+ }
995
+ /**
996
+ * Default lock probe: a read-WRITE open of the host JSON file.
997
+ *
998
+ * Why `r+` and not `r`: a plain read open succeeds whenever the holder shared
999
+ * FILE_SHARE_READ — the common case for a running editor-host — while the
1000
+ * commit-stage `rename` still fails. A write-intent open narrows that gap by
1001
+ * requiring write access on the shared handle.
1002
+ *
1003
+ * Known limit (documented, not guessed): the final `rename` to this path needs
1004
+ * DELETE sharing, which Node exposes no flag for, so a host that grants
1005
+ * read+write but not delete is NOT detectable here. That residual case is
1006
+ * covered by atomicReplaceTextFile's rename retry rather than by this probe.
1007
+ *
1008
+ * EPERM/EBUSY (sharing violation while WorkBuddy runs) and EACCES are lock
1009
+ * signals; anything else (incl. ENOENT) is not a lock verdict.
1010
+ */
1011
+ function defaultProbeHostFileLock(filePath) {
1012
+ let fd;
1013
+ try {
1014
+ fd = openSync(filePath, 'r+');
1015
+ closeSync(fd);
1016
+ fd = undefined;
1017
+ return undefined;
1018
+ }
1019
+ catch (error) {
1020
+ const code = error?.code;
1021
+ if (code === 'EPERM' || code === 'EBUSY' || code === 'EACCES')
1022
+ return String(code);
1023
+ return undefined;
1024
+ }
1025
+ finally {
1026
+ if (fd !== undefined) {
1027
+ try {
1028
+ closeSync(fd);
1029
+ }
1030
+ catch { /* already closed */ }
1031
+ }
1032
+ }
1033
+ }
1034
+ /**
1035
+ * PRI-1062: hard preflights the main installer runs BEFORE any side effect.
1036
+ *
1037
+ * Call-site contract (enforced in installer.ts): this must run before the
1038
+ * gateway pre-flight, because that block may STOP a running OpenClaw gateway.
1039
+ * A refusal from here returns immediately and would otherwise leave the
1040
+ * Owner's gateway down, since the restart is only honoured at the end of the
1041
+ * install flow.
1042
+ *
1043
+ * A RUNNING WorkBuddy holds settings.json with exclusive sharing — the
1044
+ * commit-stage atomic rename fails with EPERM after minutes of npm work and
1045
+ * the whole install rolls back. Git Bash availability is equally knowable
1046
+ * up front. Both checks are cheap (one bash spawn + two file opens) and
1047
+ * fail with a nextAction naming the exact user action.
1048
+ */
1049
+ export function runWorkbuddyEarlyPreflight(deps = {}) {
1050
+ const platform = deps.platform ?? process.platform;
1051
+ if (platform === 'win32') {
1052
+ const bash = (deps.probeBash ?? defaultProbeBash)();
1053
+ if (!bash.ok)
1054
+ return { ok: false, ...gitBashUnavailableReason(bash.detail) };
1055
+ }
1056
+ const paths = resolveWorkbuddyPaths((deps.homeDir ?? getHomeDir)());
1057
+ const probe = deps.probeHostFileLock ?? defaultProbeHostFileLock;
1058
+ const hostFiles = [
1059
+ ['settings.json', paths.settingsPath],
1060
+ ['installed_plugins.json', paths.registryPath],
1061
+ ];
1062
+ for (const [label, filePath] of hostFiles) {
1063
+ if (!existsSync(filePath))
1064
+ continue;
1065
+ const code = probe(filePath);
1066
+ if (code !== undefined) {
1067
+ return {
1068
+ ok: false,
1069
+ reason: `workbuddy_host_file_locked: ${label} is held with an exclusive handle (${code}) — WorkBuddy appears to be running. The registration commit would fail after minutes of work and roll the install back.`,
1070
+ nextAction: 'Fully exit WorkBuddy (tray icon → Quit, then confirm in Task Manager that no WorkBuddy process remains) and re-run the installer. This check ran before any installation work, so nothing needs recovering.',
1071
+ };
1072
+ }
1073
+ }
1074
+ return { ok: true };
1075
+ }
940
1076
  /** Materialize the PD-owned marketplace dir (source never escapes its root). */
941
1077
  function materializeMarketplace(marketplaceRoot, pluginDir) {
942
1078
  rmSync(marketplaceRoot, { recursive: true, force: true });
@@ -1024,11 +1160,7 @@ export class WorkBuddyHostInstaller {
1024
1160
  if (process.platform === 'win32') {
1025
1161
  const bashCheck = this.deps.runCommand('bash', ['-c', 'exit 0'], { timeoutMs: 15_000 });
1026
1162
  if (bashCheck.status !== 0) {
1027
- return {
1028
- ok: false,
1029
- reason: `git_bash_not_available: WorkBuddy executes command hooks through Git Bash on Windows, but "bash" is not resolvable (${bashCheck.error ?? `exit ${bashCheck.status}`}). Hooks would fail to launch.`,
1030
- nextAction: 'Install Git for Windows (or otherwise provide bash.exe on PATH), then re-run the installer.',
1031
- };
1163
+ return { ok: false, ...gitBashUnavailableReason(bashCheck.error ?? `exit ${bashCheck.status}`) };
1032
1164
  }
1033
1165
  }
1034
1166
  return { ok: true };
@@ -1037,7 +1169,6 @@ export class WorkBuddyHostInstaller {
1037
1169
  async install(ctx) {
1038
1170
  const p = this.paths();
1039
1171
  const details = this.detectDetails();
1040
- const freshKeywordInstall = !details.registered && !existsSync(path.join(p.governanceDir, '.pd', 'config.yaml'));
1041
1172
  // 1. Preflight: host presence + hook runtime prerequisites.
1042
1173
  if (!details.hostFound && !details.engineFound) {
1043
1174
  return {
@@ -1164,18 +1295,19 @@ export class WorkBuddyHostInstaller {
1164
1295
  nextAction: manifest.nextAction,
1165
1296
  };
1166
1297
  }
1167
- // 8. Install ≠ enable (OD-03): the host.workbuddy flag stays at its quiet
1168
- // default (OFF). No config.yaml override is written here.
1169
- // Only a truly NEW WorkBuddy governance workspace gets both gates on.
1170
- // Existing config and reinstalls retain their previous effective state.
1171
- const keywordDefaults = freshKeywordInstall ? enableFreshWorkbuddyKeywordPain(p.governanceDir) : null;
1172
- if (keywordDefaults !== null && !keywordDefaults.ok) {
1298
+ // 8. Install ⇒ governance ON by default (PRI-1064, Owner directive
1299
+ // 2026-10-31): the ONLY preserved-off state is an explicit opt-out the
1300
+ // Owner wrote (enabled: false). Sparse/legacy configs left OFF by a
1301
+ // failed install round are turned ON here — an install that ends with
1302
+ // every hook skipping (host.workbuddy_disabled) is the P1 defect this
1303
+ // replaces. The summary line below always states the effective state.
1304
+ const governanceConfigExists = existsSync(path.join(p.governanceDir, '.pd', 'config.yaml'));
1305
+ const governanceDefaults = governanceConfigExists ? ensureWorkbuddyGovernanceEnabled(p.governanceDir) : null;
1306
+ if (governanceDefaults !== null && !governanceDefaults.ok) {
1173
1307
  return { success: false, hostId: this.hostId, configPath: p.settingsPath,
1174
- configAction: registration.settingsAction, reason: keywordDefaults.reason, nextAction: keywordDefaults.nextAction };
1308
+ configAction: registration.settingsAction, reason: governanceDefaults.reason, nextAction: governanceDefaults.nextAction };
1175
1309
  }
1176
- const keywordDefaultsNote = keywordDefaults !== null
1177
- ? ' New WorkBuddy governance and four-term keyword Pain detection are ENABLED by default.'
1178
- : ' Existing governance flags were PRESERVED without implicit opt-in.';
1310
+ const governanceDefaultsNote = describeGovernanceDefaults(governanceDefaults, p.governanceDir);
1179
1311
  const effectiveNote = 'Registration takes effect in NEW WorkBuddy sessions (or /reload-plugins in a running CLI session).';
1180
1312
  // Round-4 S1: honest pending-config surface — legacy init rows and Owner
1181
1313
  // rows are kept (no silent override); the rebind path is stated, never
@@ -1188,8 +1320,20 @@ export class WorkBuddyHostInstaller {
1188
1320
  hostId: this.hostId,
1189
1321
  configPath: p.settingsPath,
1190
1322
  configAction: registration.settingsAction,
1191
- reason: `Registered ${WORKBUDDY_PLUGIN_KEY} via ${registration.mode}${registration.mode === 'engine' ? '' : ` (engine unreachable: ${registration.engineNote})`}. Governance workspace initialized at ${p.governanceDir}${governance.dbInit === 'skipped' ? ` (${governance.note})` : ''}.${profileNote}${keywordDefaultsNote}`,
1192
- nextAction: `${effectiveNote}${governance.dbInit === 'skipped' ? ` After the install, run "pd runtime init --workspace ${p.governanceDir}" to create the governance databases.` : ''} To disable keyword Pain, set features.workbuddy_live_keyword_pain.enabled=false; to disable all WorkBuddy governance, set features.host.workbuddy.enabled=false. Existing workspaces retain their prior settings.${pendingRebindNote}`,
1323
+ governance: governanceDefaults === null
1324
+ ? undefined
1325
+ : {
1326
+ enabled: !governanceDefaults.hostExplicitOff,
1327
+ explicitOptOut: governanceDefaults.hostExplicitOff,
1328
+ keywordPainEnabled: !governanceDefaults.keywordExplicitOff,
1329
+ configPath: governanceDefaults.configPath,
1330
+ },
1331
+ reason: `Registered ${WORKBUDDY_PLUGIN_KEY} via ${registration.mode}${registration.mode === 'engine' ? '' : ` (engine unreachable: ${registration.engineNote})`}. Governance workspace initialized at ${p.governanceDir}${governance.dbInit === 'skipped' ? ` (${governance.note})` : ''}.${profileNote}${governanceDefaultsNote}`,
1332
+ // PRI-1063 copy (single-line flat-key flow mapping) carried over from
1333
+ // main; the "Existing workspaces retain their prior settings" sentence is
1334
+ // deliberately dropped — PRI-1064 turns governance ON for those
1335
+ // workspaces, so keeping it would state the opposite of what happens.
1336
+ nextAction: `${effectiveNote}${governance.dbInit === 'skipped' ? ` After the install, run "pd runtime init --workspace ${p.governanceDir}" to create the governance databases.` : ''} To disable, edit ${path.join(p.governanceDir, '.pd', 'config.yaml')} — each flag id is ONE flat key (not nested). In the existing "features:" block set workbuddy_live_keyword_pain: {enabled: false} to disable keyword Pain only, or host.workbuddy: {enabled: false} to disable all WorkBuddy governance.${pendingRebindNote}`,
1193
1337
  };
1194
1338
  }
1195
1339
  /**