create-principles-disciple 1.145.30 → 1.145.33

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 (92) hide show
  1. package/_release/product-identity.json +2 -2
  2. package/codex-adapter/dist/ingestion/ingestion.js +3 -1
  3. package/codex-adapter/package.json +1 -1
  4. package/console/dist/server/models/ActivationsConsoleModel.d.ts +19 -2
  5. package/console/dist/server/models/ActivationsConsoleModel.js +124 -10
  6. package/console/dist/server/models/OwnerDecisionConsoleModel.d.ts +3 -1
  7. package/console/dist/server/models/OwnerDecisionConsoleModel.js +6 -2
  8. package/console/dist/server/routes/activations.js +7 -2
  9. package/console/dist/server/routes/owner-decisions.js +1 -1
  10. package/core/dist/runtime-v2/activation/index.d.ts +6 -0
  11. package/core/dist/runtime-v2/activation/index.d.ts.map +1 -1
  12. package/core/dist/runtime-v2/activation/index.js +3 -0
  13. package/core/dist/runtime-v2/activation/index.js.map +1 -1
  14. package/core/dist/runtime-v2/activation/openclaw-promotion-checks.d.ts +75 -0
  15. package/core/dist/runtime-v2/activation/openclaw-promotion-checks.d.ts.map +1 -1
  16. package/core/dist/runtime-v2/activation/openclaw-promotion-checks.js +131 -37
  17. package/core/dist/runtime-v2/activation/openclaw-promotion-checks.js.map +1 -1
  18. package/core/dist/runtime-v2/activation/production-gate-deps.d.ts.map +1 -1
  19. package/core/dist/runtime-v2/activation/production-gate-deps.js +7 -3
  20. package/core/dist/runtime-v2/activation/production-gate-deps.js.map +1 -1
  21. package/core/dist/runtime-v2/activation/recovery-composition.d.ts +54 -0
  22. package/core/dist/runtime-v2/activation/recovery-composition.d.ts.map +1 -0
  23. package/core/dist/runtime-v2/activation/recovery-composition.js +129 -0
  24. package/core/dist/runtime-v2/activation/recovery-composition.js.map +1 -0
  25. package/core/dist/runtime-v2/activation/recovery-control-surfaces.d.ts +62 -0
  26. package/core/dist/runtime-v2/activation/recovery-control-surfaces.d.ts.map +1 -0
  27. package/core/dist/runtime-v2/activation/recovery-control-surfaces.js +84 -0
  28. package/core/dist/runtime-v2/activation/recovery-control-surfaces.js.map +1 -0
  29. package/core/dist/runtime-v2/activation/rulecode-shadow-summary.d.ts +13 -1
  30. package/core/dist/runtime-v2/activation/rulecode-shadow-summary.d.ts.map +1 -1
  31. package/core/dist/runtime-v2/activation/rulecode-shadow-summary.js +24 -1
  32. package/core/dist/runtime-v2/activation/rulecode-shadow-summary.js.map +1 -1
  33. package/core/dist/runtime-v2/index.d.ts +2 -2
  34. package/core/dist/runtime-v2/index.d.ts.map +1 -1
  35. package/core/dist/runtime-v2/index.js +1 -1
  36. package/core/dist/runtime-v2/index.js.map +1 -1
  37. package/core/dist/runtime-v2/trajectory-schema.d.ts.map +1 -1
  38. package/core/dist/runtime-v2/trajectory-schema.js +12 -1
  39. package/core/dist/runtime-v2/trajectory-schema.js.map +1 -1
  40. package/core/dist/runtime-v2/types/event-types.d.ts +10 -0
  41. package/core/dist/runtime-v2/types/event-types.d.ts.map +1 -1
  42. package/core/dist/runtime-v2/types/event-types.js +1 -0
  43. package/core/dist/runtime-v2/types/event-types.js.map +1 -1
  44. package/core/package.json +1 -1
  45. package/dist/installer.d.ts +16 -0
  46. package/dist/installer.d.ts.map +1 -1
  47. package/dist/installer.js +49 -13
  48. package/dist/installer.js.map +1 -1
  49. package/host-runtime/dist/cli-recovery-probe.d.ts +30 -0
  50. package/host-runtime/dist/cli-recovery-probe.js +169 -0
  51. package/host-runtime/dist/governance-signal-admission.js +22 -5
  52. package/host-runtime/dist/host-liveness-contract.d.ts +51 -28
  53. package/host-runtime/dist/host-liveness-contract.js +143 -46
  54. package/host-runtime/dist/index.d.ts +2 -0
  55. package/host-runtime/dist/index.js +2 -0
  56. package/host-runtime/dist/production-pain-evidence.d.ts +2 -0
  57. package/host-runtime/dist/production-pain-evidence.js +46 -8
  58. package/host-runtime/dist/production-rulehost-gate.js +24 -6
  59. package/host-runtime/dist/workbuddy-rule-context-provider.d.ts +33 -0
  60. package/host-runtime/dist/workbuddy-rule-context-provider.js +126 -0
  61. package/host-runtime/dist/workspace-behavior-evidence.d.ts +22 -5
  62. package/host-runtime/dist/workspace-behavior-evidence.js +41 -11
  63. package/host-runtime/package.json +1 -1
  64. package/package.json +2 -2
  65. package/pd-cli/dist/commands/recovery-reachability-probe.d.ts +25 -0
  66. package/pd-cli/dist/commands/recovery-reachability-probe.d.ts.map +1 -0
  67. package/pd-cli/dist/commands/recovery-reachability-probe.js +50 -0
  68. package/pd-cli/dist/commands/recovery-reachability-probe.js.map +1 -0
  69. package/pd-cli/dist/commands/runtime-activation.d.ts +10 -1
  70. package/pd-cli/dist/commands/runtime-activation.d.ts.map +1 -1
  71. package/pd-cli/dist/commands/runtime-activation.js +81 -3
  72. package/pd-cli/dist/commands/runtime-activation.js.map +1 -1
  73. package/pd-cli/dist/services/pain-recall.d.ts +79 -0
  74. package/pd-cli/dist/services/pain-recall.d.ts.map +1 -1
  75. package/pd-cli/dist/services/pain-recall.js +295 -12
  76. package/pd-cli/dist/services/pain-recall.js.map +1 -1
  77. package/pd-cli/package.json +1 -1
  78. package/plugin/dist/bundle.js +385 -385
  79. package/plugin/dist/governance-audit.js +1 -1
  80. package/plugin/dist/openclaw.plugin.json +1 -1
  81. package/plugin/dist/rulehost-evidence.js +1 -1
  82. package/plugin/openclaw.plugin.json +1 -1
  83. package/plugin/package.json +3 -24
  84. package/release-manager/dist/installer.d.ts +16 -0
  85. package/release-manager/dist/installer.d.ts.map +1 -1
  86. package/release-manager/dist/installer.js +49 -13
  87. package/release-manager/dist/installer.js.map +1 -1
  88. package/release-manager/package.json +2 -2
  89. package/workbuddy-adapter/dist/codec/input-decoder.d.ts +14 -11
  90. package/workbuddy-adapter/dist/codec/input-decoder.js +28 -14
  91. package/workbuddy-adapter/dist/pd-hook.js +31 -12
  92. package/workbuddy-adapter/package.json +1 -1
@@ -314,6 +314,22 @@ function ensureToolCallsProjectDirColumn(db) {
314
314
  // the prepared-statement readiness check below fails loud if absent.
315
315
  }
316
316
  }
317
+ /**
318
+ * SPEC-RULECODE-HOST-PROMOTION-001 R2: additive migration for producer host
319
+ * attribution. Legacy rows stay NULL — the WorkBuddy rule-context reader
320
+ * treats a NULL stamp as unprovable (never guessed), so no backfill exists.
321
+ */
322
+ function ensureToolCallsHostKindColumn(db) {
323
+ const columns = db.prepare('PRAGMA table_info(tool_calls)').all();
324
+ if (columns.some((row) => pragmaField(row, 'name') === 'host_kind'))
325
+ return;
326
+ try {
327
+ db.exec('ALTER TABLE tool_calls ADD COLUMN host_kind TEXT');
328
+ }
329
+ catch {
330
+ // Same concurrent-writer contract as the sibling migrations above.
331
+ }
332
+ }
317
333
  /**
318
334
  * SPEC-CODEX-PAIN-CLOSURE-001 CR-01: upgrade the live-hook observation of a
319
335
  * tool call with the host-verified final result (exit code) read through the
@@ -342,9 +358,18 @@ export function recordVerifiedToolOutcomes(args) {
342
358
  if (!hasToolCalls)
343
359
  applyTrajectorySchemaBase(db);
344
360
  ensureToolCallsToolUseIdColumn(db);
345
- const findByToolUseId = db.prepare('SELECT id, outcome FROM tool_calls WHERE session_id = ? AND tool_use_id = ? ORDER BY id LIMIT 1');
361
+ ensureToolCallsHostKindColumn(db);
362
+ // Review R3/P2: a KNOWN host's call identity includes its attribution.
363
+ // The lookup matches ONLY rows of the same host — a colliding row from
364
+ // another host (or an unattributed legacy row) is a DIFFERENT record: the
365
+ // caller inserts its own row instead of swallowing or claiming it.
366
+ // Callers without a hostKind keep the historical match-any semantics
367
+ // (explicit compat contract, asserted by tests).
368
+ const findByToolUseId = args.hostKind !== undefined
369
+ ? db.prepare('SELECT id, outcome FROM tool_calls WHERE session_id = ? AND tool_use_id = ? AND host_kind = ? ORDER BY id LIMIT 1')
370
+ : db.prepare('SELECT id, outcome FROM tool_calls WHERE session_id = ? AND tool_use_id = ? ORDER BY id LIMIT 1');
346
371
  const upgradeUnknown = db.prepare("UPDATE tool_calls SET outcome = ?, exit_code = ?, result_preview = COALESCE(?, result_preview) WHERE id = ? AND outcome = 'unknown'");
347
- const insertVerified = db.prepare('INSERT INTO tool_calls (session_id, tool_name, outcome, duration_ms, exit_code, error_type, error_message, gfi_before, gfi_after, params_json, result_preview, created_at, tool_use_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)');
372
+ const insertVerified = db.prepare('INSERT INTO tool_calls (session_id, tool_name, outcome, duration_ms, exit_code, error_type, error_message, gfi_before, gfi_after, params_json, result_preview, created_at, tool_use_id, host_kind) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)');
348
373
  const upsertSession = db.prepare('INSERT INTO sessions (session_id, started_at, updated_at) VALUES (?, ?, ?) ON CONFLICT(session_id) DO UPDATE SET updated_at = excluded.updated_at');
349
374
  const createdAt = new Date().toISOString();
350
375
  db.transaction(() => {
@@ -352,7 +377,9 @@ export function recordVerifiedToolOutcomes(args) {
352
377
  if (typeof input.exitCode !== 'number' || !Number.isInteger(input.exitCode))
353
378
  continue;
354
379
  const finalOutcome = input.exitCode === 0 ? 'success' : 'failure';
355
- const existing = findByToolUseId.get(args.sessionId, input.toolUseId);
380
+ const existing = (args.hostKind !== undefined
381
+ ? findByToolUseId.get(args.sessionId, input.toolUseId, args.hostKind)
382
+ : findByToolUseId.get(args.sessionId, input.toolUseId));
356
383
  const boundedPreview = typeof input.outputPreview === 'string' && input.outputPreview.length > 0
357
384
  ? input.outputPreview.slice(0, MAX_PREVIEW)
358
385
  : null;
@@ -368,7 +395,7 @@ export function recordVerifiedToolOutcomes(args) {
368
395
  }
369
396
  upsertSession.run(args.sessionId, createdAt, createdAt);
370
397
  const sanitizedParams = sanitizeToolParams(input.params ?? {}, args.workspaceDir);
371
- const info = insertVerified.run(args.sessionId, input.toolName, finalOutcome, null, input.exitCode, null, null, null, null, stable(sanitizedParams), boundedPreview, createdAt, input.toolUseId);
398
+ const info = insertVerified.run(args.sessionId, input.toolName, finalOutcome, null, input.exitCode, null, null, null, null, stable(sanitizedParams), boundedPreview, createdAt, input.toolUseId, args.hostKind ?? null);
372
399
  results.push({ status: 'inserted', id: Number(info.lastInsertRowid) });
373
400
  }
374
401
  })();
@@ -426,6 +453,7 @@ export function createProductionPainEvidenceHandler(options = {}) {
426
453
  db.pragma('busy_timeout = 5000');
427
454
  ensureToolCallsToolUseIdColumn(db);
428
455
  ensureToolCallsProjectDirColumn(db);
456
+ ensureToolCallsHostKindColumn(db);
429
457
  if (!hasCanonicalSchema(db)) {
430
458
  db.close();
431
459
  db = undefined;
@@ -520,20 +548,30 @@ export function createProductionPainEvidenceHandler(options = {}) {
520
548
  // CR-01: the host tool-call id is the stable join key for the
521
549
  // consent-gated transcript upgrade (recordVerifiedToolOutcomes);
522
550
  // content-shape probing stays the fallback for hosts without ids.
551
+ // Review R3/P2: for a known host the identity is host-scoped — a
552
+ // colliding row from ANOTHER host (or an unattributed legacy row) is
553
+ // NOT this delivery's duplicate, so both hosts keep independent
554
+ // records instead of the second being swallowed.
523
555
  if (event.context.toolCallId !== undefined
524
- && db.prepare('SELECT 1 FROM tool_calls WHERE session_id = ? AND tool_use_id = ?').get(event.context.sessionId, event.context.toolCallId) !== undefined) {
556
+ && (options.hostKind !== undefined
557
+ ? db.prepare('SELECT 1 FROM tool_calls WHERE session_id = ? AND tool_use_id = ? AND host_kind = ?').get(event.context.sessionId, event.context.toolCallId, options.hostKind)
558
+ : db.prepare('SELECT 1 FROM tool_calls WHERE session_id = ? AND tool_use_id = ?').get(event.context.sessionId, event.context.toolCallId)) !== undefined) {
525
559
  duplicate = true;
526
560
  duplicateAdmitted = db.prepare('SELECT 1 FROM pain_events WHERE canonical_pain_id = ?').get(painId) !== undefined;
527
561
  return;
528
562
  }
529
- if (db.prepare('SELECT 1 FROM tool_calls WHERE session_id = ? AND tool_name = ? AND params_json = ? AND outcome = ? AND exit_code IS ? AND error_message IS ? AND result_preview IS ?').get(event.context.sessionId, toolName, paramsJson, outcome.outcome, outcome.exitCode, outcome.error ?? null, resultPreview)) {
563
+ // Review R3/P2: the content-shape fallback dedup is host-scoped the
564
+ // same way — identical content from two hosts is two records.
565
+ if ((options.hostKind !== undefined
566
+ ? db.prepare('SELECT 1 FROM tool_calls WHERE session_id = ? AND tool_name = ? AND params_json = ? AND outcome = ? AND exit_code IS ? AND error_message IS ? AND result_preview IS ? AND host_kind = ?').get(event.context.sessionId, toolName, paramsJson, outcome.outcome, outcome.exitCode, outcome.error ?? null, resultPreview, options.hostKind)
567
+ : db.prepare('SELECT 1 FROM tool_calls WHERE session_id = ? AND tool_name = ? AND params_json = ? AND outcome = ? AND exit_code IS ? AND error_message IS ? AND result_preview IS ?').get(event.context.sessionId, toolName, paramsJson, outcome.outcome, outcome.exitCode, outcome.error ?? null, resultPreview)) !== undefined) {
530
568
  duplicate = true;
531
569
  duplicateAdmitted = db.prepare('SELECT 1 FROM pain_events WHERE canonical_pain_id = ?').get(painId) !== undefined;
532
570
  return;
533
571
  }
534
572
  db.prepare(`INSERT INTO sessions (session_id, started_at, updated_at) VALUES (?, ?, ?) ON CONFLICT(session_id) DO UPDATE SET updated_at = excluded.updated_at`).run(event.context.sessionId, createdAt, createdAt);
535
- db.prepare(`INSERT INTO tool_calls (session_id, tool_name, outcome, duration_ms, exit_code, error_type, error_message, gfi_before, gfi_after, params_json, result_preview, created_at, tool_use_id, project_dir) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
536
- .run(event.context.sessionId, toolName, outcome.outcome, outcome.durationMs ?? null, outcome.exitCode, outcome.error ? outcome.error.split(/[\s:]/, 1)[0] : null, outcome.error ?? null, null, null, paramsJson, resultPreview, createdAt, event.context.toolCallId ?? null, path.resolve(options.projectDir ?? event.context.workspaceDir));
573
+ db.prepare(`INSERT INTO tool_calls (session_id, tool_name, outcome, duration_ms, exit_code, error_type, error_message, gfi_before, gfi_after, params_json, result_preview, created_at, tool_use_id, project_dir, host_kind) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
574
+ .run(event.context.sessionId, toolName, outcome.outcome, outcome.durationMs ?? null, outcome.exitCode, outcome.error ? outcome.error.split(/[\s:]/, 1)[0] : null, outcome.error ?? null, null, null, paramsJson, resultPreview, createdAt, event.context.toolCallId ?? null, path.resolve(options.projectDir ?? event.context.workspaceDir), options.hostKind ?? null);
537
575
  if (admitted) {
538
576
  // Raw observation only (Pain Diagnosis Persistence SPEC §8): the
539
577
  // pain row must record WHAT happened, not WHY. Attribution
@@ -350,21 +350,26 @@ export function createProductionRuleHostGate(options = {}) {
350
350
  // evaluator replay; merely wiring history must not revive old
351
351
  // activations. Live execution additionally needs the existing
352
352
  // promotion decision's binding to this exact artifact snapshot.
353
- if (options.hostKind === 'codex') {
353
+ // SPEC-RULECODE-HOST-PROMOTION-001 §11.3: the SAME qualification
354
+ // gates every host with a V2 context path — WorkBuddy must not
355
+ // auto-execute historical V2 artifacts stamped for another host
356
+ // (the hostKinds binding below rejects them by the exact same
357
+ // includes() check Codex uses).
358
+ if (options.hostKind === 'codex' || options.hostKind === 'workbuddy') {
354
359
  const contract = content.ruleHostInputContract;
355
360
  const hosts = isRecord(contract) ? contract.hostKinds : undefined;
356
361
  let contentBindingVerified = digestCheck.outcome === 'verified';
357
362
  if (activationMode === 'shadow' && row.owner_approved === 1) {
358
363
  // Old databases remain readable without writing a migration
359
364
  // from this enforcement reader. A legacy approval without a
360
- // content digest cannot grant Codex V2 execution eligibility.
365
+ // content digest cannot grant V2 execution eligibility.
361
366
  const approvalColumns = connection.getDb().prepare('PRAGMA table_info(approvals)').all();
362
367
  if (approvalColumns.some((column) => isRecord(column) && column.name === 'artifact_digest')) {
363
368
  const approval = connection.getDb().prepare(`
364
369
  SELECT artifact_digest FROM approvals
365
370
  WHERE artifact_id = ? AND channel = 'code_tool_hook' AND status = 'approved'
366
371
  ORDER BY decided_at DESC LIMIT 1
367
- `).get(artifactId);
372
+ `).get(artifactId);
368
373
  const approvalDigest = isRecord(approval) && typeof approval.artifact_digest === 'string'
369
374
  ? approval.artifact_digest : null;
370
375
  contentBindingVerified = verifyPiArtifactRowDigest(contentRow, contentJson, approvalDigest).outcome === 'verified';
@@ -375,9 +380,9 @@ export function createProductionRuleHostGate(options = {}) {
375
380
  }
376
381
  if (!isRecord(contract) || contract.version !== 1 || contract.contextVersion !== 2
377
382
  || !Array.isArray(hosts) || !hosts.every((host) => typeof host === 'string')
378
- || !hosts.includes('codex') || row.owner_approved !== 1
383
+ || !hosts.includes(options.hostKind) || row.owner_approved !== 1
379
384
  || !contentBindingVerified) {
380
- addWarning(warnings, `codex_rule_context_v2_unqualified: activation=${activationId}`, 'regenerate and replay this artifact for Codex, approve it for shadow observation, and use the existing Owner promotion flow for live execution');
385
+ addWarning(warnings, `${options.hostKind}_rule_context_v2_unqualified: activation=${activationId}`, `regenerate and replay this artifact for ${options.hostKind}, approve it for shadow observation, and use the existing Owner promotion flow for live execution`);
381
386
  continue;
382
387
  }
383
388
  }
@@ -419,7 +424,18 @@ export function createProductionRuleHostGate(options = {}) {
419
424
  : context === UNAVAILABLE_RULE_CONTEXT
420
425
  ? (contextFault ?? 'provider_invalid')
421
426
  : 'history_unavailable';
422
- addWarning(warnings, `rule_context_v2_unavailable: ${fault} (activation=${activationId})`, 'enable and wire the host rule context provider, or regenerate the rule without context dependence');
427
+ // SPEC-RULECODE-HOST-PROMOTION-001 R2: a schema-valid
428
+ // unavailable context carries the provider's precise reason
429
+ // (e.g. workbuddy_history_attribution_conflict) — surface it
430
+ // in the warning instead of collapsing every legit
431
+ // unavailability into one opaque class (rc-9).
432
+ const preciseReason = context !== undefined
433
+ && context !== UNAVAILABLE_RULE_CONTEXT
434
+ && typeof context.history.unavailableReason === 'string'
435
+ && context.history.unavailableReason.length > 0
436
+ ? `:${context.history.unavailableReason}`
437
+ : '';
438
+ addWarning(warnings, `rule_context_v2_unavailable: ${fault}${preciseReason} (activation=${activationId})`, 'enable and wire the host rule context provider, or regenerate the rule without context dependence');
423
439
  continue;
424
440
  }
425
441
  const inputContract = content.ruleHostInputContract;
@@ -547,6 +563,7 @@ export function createProductionRuleHostGate(options = {}) {
547
563
  ruleId: candidate.ruleId,
548
564
  activationId: candidate.implId,
549
565
  activationMode: 'shadow',
566
+ ...(options.hostKind !== undefined ? { hostKind: options.hostKind } : {}),
550
567
  });
551
568
  }
552
569
  }
@@ -604,6 +621,7 @@ export function createProductionRuleHostGate(options = {}) {
604
621
  ...(result?.ruleId !== undefined ? { ruleId: result.ruleId } : {}),
605
622
  ...(liveActivationId !== undefined ? { activationId: liveActivationId } : {}),
606
623
  activationMode: 'live',
624
+ ...(options.hostKind !== undefined ? { hostKind: options.hostKind } : {}),
607
625
  },
608
626
  ...shadowEvaluations,
609
627
  ];
@@ -0,0 +1,33 @@
1
+ import { type ToolSemanticRegistry } from '@principles/core/runtime-v2';
2
+ import type { RuleContextProvider } from './production-rulehost-gate.js';
3
+ export interface WorkbuddyRuleContextProviderOptions {
4
+ /** The WorkBuddy governance workspace whose trajectory database is authoritative. */
5
+ workspaceDir: string;
6
+ /** The host project cwd the hook observed (payload cwd); history rows must have this exact stored scope. Absent on channels that carry none. */
7
+ projectDir?: string;
8
+ /** The existing `rulecode_context_v2` gate. */
9
+ enabled: boolean;
10
+ /** Timestamp captured immediately after decoding this hook event. */
11
+ cutoffAt: Date;
12
+ /** Host-authoritative current WorkBuddy call_id, excluded even on timestamp ties. */
13
+ currentToolCallId: string;
14
+ toolSemantics: ToolSemanticRegistry;
15
+ }
16
+ /**
17
+ * SPEC-RULECODE-HOST-PROMOTION-001 C: the WorkBuddy RuleContext provider.
18
+ *
19
+ * It reads the SAME canonical trajectory store the shared afterToolCall
20
+ * production path writes for WorkBuddy (`tool_calls` rows carrying the
21
+ * host's natural session/call ids and the observed project cwd) — genuinely
22
+ * observable WorkBuddy data, never borrowed Codex history. WorkBuddy has no
23
+ * design-gate declaration entry point (the Codex-native attestation source
24
+ * is Codex-only), so this provider deliberately supplies NO designGate
25
+ * fact: a rule whose required facts include design_approval stays suspended
26
+ * on this host with the precise `rule_required_fact_unavailable` warning
27
+ * instead of inheriting another host's attestation.
28
+ *
29
+ * Disabled, unscoped or unverifiable sources return explicit unavailable
30
+ * contexts — v2 rules then suspend through the existing shared-gate
31
+ * contract, which is the honest state until the missing input exists.
32
+ */
33
+ export declare function createWorkbuddyRuleContextProvider(options: WorkbuddyRuleContextProviderOptions): RuleContextProvider;
@@ -0,0 +1,126 @@
1
+ import path from 'node:path';
2
+ import { computeBehaviorFacts, } from '@principles/core/runtime-v2';
3
+ import { assembleBehaviorHistory } from './behavior-history.js';
4
+ import { readWorkspaceRuleContextRowsBefore } from './workspace-behavior-evidence.js';
5
+ const HISTORY_LIMIT = 100;
6
+ const MAX_REASON_LENGTH = 240;
7
+ function isRecord(value) {
8
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
9
+ }
10
+ function unavailable(reason) {
11
+ const history = {
12
+ status: 'unavailable',
13
+ unavailableReason: reason.replace(/\s+/g, ' ').slice(0, MAX_REASON_LENGTH),
14
+ truncated: false,
15
+ calls: [],
16
+ };
17
+ return {
18
+ version: 2,
19
+ history,
20
+ facts: computeBehaviorFacts(history, null, null),
21
+ };
22
+ }
23
+ /**
24
+ * SPEC-RULECODE-HOST-PROMOTION-001 C: the WorkBuddy RuleContext provider.
25
+ *
26
+ * It reads the SAME canonical trajectory store the shared afterToolCall
27
+ * production path writes for WorkBuddy (`tool_calls` rows carrying the
28
+ * host's natural session/call ids and the observed project cwd) — genuinely
29
+ * observable WorkBuddy data, never borrowed Codex history. WorkBuddy has no
30
+ * design-gate declaration entry point (the Codex-native attestation source
31
+ * is Codex-only), so this provider deliberately supplies NO designGate
32
+ * fact: a rule whose required facts include design_approval stays suspended
33
+ * on this host with the precise `rule_required_fact_unavailable` warning
34
+ * instead of inheriting another host's attestation.
35
+ *
36
+ * Disabled, unscoped or unverifiable sources return explicit unavailable
37
+ * contexts — v2 rules then suspend through the existing shared-gate
38
+ * contract, which is the honest state until the missing input exists.
39
+ */
40
+ export function createWorkbuddyRuleContextProvider(options) {
41
+ const workspaceDir = path.resolve(options.workspaceDir);
42
+ const projectDir = options.projectDir !== undefined ? path.resolve(options.projectDir) : undefined;
43
+ return (request) => {
44
+ if (typeof request.sessionId !== 'string' || request.sessionId.trim().length === 0) {
45
+ return unavailable('session_id_invalid');
46
+ }
47
+ if (!options.enabled)
48
+ return unavailable('workbuddy_rule_context_disabled');
49
+ if (path.resolve(request.workspaceDir) !== workspaceDir)
50
+ return unavailable('workspace_scope_mismatch');
51
+ if (projectDir === undefined || !path.isAbsolute(projectDir)) {
52
+ return unavailable('workbuddy_project_scope_unavailable');
53
+ }
54
+ const raw = request.rawPayload;
55
+ const toolInput = isRecord(raw) && isRecord(raw.toolInput) ? raw.toolInput : null;
56
+ if (toolInput === null
57
+ || toolInput.toolName !== request.toolName
58
+ || !isRecord(toolInput.params)
59
+ || options.currentToolCallId.trim().length === 0) {
60
+ return unavailable('workbuddy_pre_tool_scope_mismatch');
61
+ }
62
+ const cutoff = options.cutoffAt;
63
+ if (!(cutoff instanceof Date) || !Number.isFinite(cutoff.getTime()))
64
+ return unavailable('history_cutoff_invalid');
65
+ try {
66
+ const historyRows = readWorkspaceRuleContextRowsBefore(workspaceDir, {
67
+ sessionId: request.sessionId,
68
+ projectDir,
69
+ beforeCreatedAt: cutoff.toISOString(),
70
+ excludeToolUseId: options.currentToolCallId,
71
+ limit: HISTORY_LIMIT,
72
+ // Review R2: consume ONLY rows PROVEN to be WorkBuddy's (stamped by
73
+ // this host's own writer). "Same workspace + same session id +
74
+ // same project" is NOT proof — a Codex session id colliding here
75
+ // must never lend its reads to a WorkBuddy read-before-write rule.
76
+ hostKind: 'workbuddy',
77
+ });
78
+ if (historyRows.unscopedPriorRows)
79
+ return unavailable('trajectory_project_scope_incomplete');
80
+ if ((historyRows.otherHostRows ?? 0) > 0) {
81
+ return unavailable('workbuddy_history_attribution_conflict');
82
+ }
83
+ if (historyRows.rows.length === 0) {
84
+ // Fail closed with the precise reason: legacy rows exist but cannot
85
+ // be PROVEN WorkBuddy's (never back-filled, never assumed).
86
+ if ((historyRows.unattributedRows ?? 0) > 0)
87
+ return unavailable('workbuddy_history_attribution_unprovable');
88
+ return unavailable('no_prior_session_history');
89
+ }
90
+ if ((historyRows.unattributedRows ?? 0) > 0) {
91
+ // Mixed window: consuming only the proven subset could UNDERCOUNT
92
+ // prior reads (a hidden foreign read would flip priorReadOfTarget),
93
+ // so the window is unprovable as a whole — suspend precisely.
94
+ return unavailable('workbuddy_history_attribution_unprovable');
95
+ }
96
+ const history = assembleBehaviorHistory(historyRows.rows, historyRows.truncated, {
97
+ projectDir,
98
+ toolSemantics: options.toolSemantics,
99
+ });
100
+ // WorkBuddy exposes its shell as the Bash tool, and MCP-style tools may
101
+ // resolve to 'other' absent from this host's semantic registry. Either
102
+ // may read or mutate files, so target-read absence and exact action
103
+ // counts cannot be asserted from this partial semantic view (same
104
+ // conservative rule as the Codex provider).
105
+ const factsIncomplete = history.truncated || history.calls.some((call) => call.canonicalKind === 'execute' || call.canonicalKind === 'other');
106
+ const computedFacts = computeBehaviorFacts(history, factsIncomplete ? null : request.targetPath, null);
107
+ const facts = factsIncomplete
108
+ ? {
109
+ priorReadOfTarget: 'unknown',
110
+ readCount: null,
111
+ writeCount: null,
112
+ uniqueWritePathCount: null,
113
+ sameActionBlockCount: null,
114
+ }
115
+ : computedFacts;
116
+ return {
117
+ version: 2,
118
+ history,
119
+ facts,
120
+ };
121
+ }
122
+ catch (error) {
123
+ return unavailable(`trajectory_history_unavailable:${error instanceof Error ? error.message : String(error)}`);
124
+ }
125
+ };
126
+ }
@@ -7,18 +7,35 @@ export declare function createWorkspaceBehaviorEvidencePort(workspaceDir: string
7
7
  * database. The timestamp is the caller's pre-event cutoff; rows at or after
8
8
  * it are excluded so replayed/future calls cannot enter a live RuleContext.
9
9
  * This is read-only and never creates or migrates trajectory state.
10
+ *
11
+ * Review R2 (SPEC-RULECODE-HOST-PROMOTION-001): when `hostKind` is supplied,
12
+ * the reader partitions the window by PROVEN producer attribution
13
+ * (`tool_calls.host_kind`, stamped by each host's writer) instead of handing
14
+ * back every row: `rows` carries only rows stamped with that host,
15
+ * `otherHostRows` counts rows stamped with a different host (a cross-host
16
+ * session-id collision), and `unattributedRows` counts legacy rows with no
17
+ * stamp (written before the column existed — attribution is unprovable, not
18
+ * assumed). A database whose tool_calls predates the column entirely counts
19
+ * every row in the unattributed bucket. The caller decides the failure
20
+ * policy; this reader never guesses an attribution.
10
21
  */
22
+ export interface WorkspaceRuleContextRowsResult {
23
+ rows: readonly RuleHostContextRow[];
24
+ truncated: boolean;
25
+ unscopedPriorRows: boolean;
26
+ /** Present only for attribution-aware reads: rows stamped with ANOTHER host (never zero-checked when hostKind is absent). */
27
+ otherHostRows?: number;
28
+ /** Present only for attribution-aware reads: legacy rows with no host stamp. */
29
+ unattributedRows?: number;
30
+ }
11
31
  export declare function readWorkspaceRuleContextRowsBefore(workspaceDir: string, input: {
12
32
  sessionId: string;
13
33
  projectDir: string;
14
34
  beforeCreatedAt: string;
15
35
  excludeToolUseId: string;
16
36
  limit: number;
17
- }): {
18
- rows: readonly RuleHostContextRow[];
19
- truncated: boolean;
20
- unscopedPriorRows: boolean;
21
- };
37
+ hostKind?: string;
38
+ }): WorkspaceRuleContextRowsResult;
22
39
  /**
23
40
  * List only Codex sessions proven by normalized host evidence and a matching
24
41
  * project-scoped trajectory row. The trajectory schema has no host_kind on
@@ -74,12 +74,6 @@ export function createWorkspaceBehaviorEvidencePort(workspaceDir, toolSemantics)
74
74
  },
75
75
  };
76
76
  }
77
- /**
78
- * Read one bounded, same-session history window from the canonical trajectory
79
- * database. The timestamp is the caller's pre-event cutoff; rows at or after
80
- * it are excluded so replayed/future calls cannot enter a live RuleContext.
81
- * This is read-only and never creates or migrates trajectory state.
82
- */
83
77
  export function readWorkspaceRuleContextRowsBefore(workspaceDir, input) {
84
78
  const { sessionId, projectDir, beforeCreatedAt, excludeToolUseId, limit } = input;
85
79
  if (sessionId.trim().length === 0)
@@ -95,9 +89,21 @@ export function readWorkspaceRuleContextRowsBefore(workspaceDir, input) {
95
89
  const db = new Database(path.join(workspaceDir, '.state', 'trajectory.db'), { readonly: true, fileMustExist: true });
96
90
  try {
97
91
  db.pragma('busy_timeout = 100');
92
+ const attributionAware = input.hostKind !== undefined;
93
+ // Select host_kind ONLY for attribution-aware reads on schemas that carry
94
+ // the column. A plain read (or a legacy schema without the column) keeps
95
+ // the historical column list — never a failing query.
96
+ const includeHostKind = attributionAware && (() => {
97
+ const columns = db.prepare('PRAGMA table_info(tool_calls)').all();
98
+ return Array.isArray(columns)
99
+ && columns.some((column) => record(column) && typeof column.name === 'string' && column.name === 'host_kind');
100
+ })();
98
101
  return db.transaction(() => {
99
- const rows = db.prepare(`
100
- SELECT id, tool_name, outcome, params_json
102
+ // Attribution-aware read: fetch one extra slot beyond the limit so the
103
+ // partition counts stay truthful about a truncated window's tail.
104
+ const selectColumns = includeHostKind ? 'id, tool_name, outcome, params_json, host_kind' : 'id, tool_name, outcome, params_json';
105
+ const fetched = db.prepare(`
106
+ SELECT ${selectColumns}
101
107
  FROM tool_calls
102
108
  WHERE session_id = ? AND project_dir = ? AND created_at < ? AND (tool_use_id IS NULL OR tool_use_id <> ?)
103
109
  ORDER BY created_at DESC, id DESC
@@ -108,12 +114,36 @@ export function readWorkspaceRuleContextRowsBefore(workspaceDir, input) {
108
114
  WHERE session_id = ? AND project_dir IS NULL AND created_at < ?
109
115
  AND (tool_use_id IS NULL OR tool_use_id <> ?) LIMIT 1
110
116
  `).get(sessionId, beforeCreatedAt, excludeToolUseId);
111
- if (!Array.isArray(rows))
117
+ if (!Array.isArray(fetched))
112
118
  throw new Error('history_query_invalid');
119
+ if (!attributionAware) {
120
+ return {
121
+ rows: fetched.slice(0, limit).reverse().map(contextRow),
122
+ truncated: fetched.length > limit,
123
+ unscopedPriorRows: unscoped !== undefined,
124
+ };
125
+ }
126
+ let otherHostRows = 0;
127
+ let unattributedRows = 0;
128
+ const matching = [];
129
+ for (const row of fetched) {
130
+ if (!record(row) || !Object.hasOwn(row, 'host_kind') || row.host_kind === null || row.host_kind === undefined) {
131
+ // No stamp (or no column): unprovable — never guessed into the host.
132
+ unattributedRows += 1;
133
+ continue;
134
+ }
135
+ if (row.host_kind !== input.hostKind) {
136
+ otherHostRows += 1;
137
+ continue;
138
+ }
139
+ matching.push(row);
140
+ }
113
141
  return {
114
- rows: rows.slice(0, limit).reverse().map(contextRow),
115
- truncated: rows.length > limit,
142
+ rows: matching.slice(0, limit).reverse().map(contextRow),
143
+ truncated: fetched.length > limit,
116
144
  unscopedPriorRows: unscoped !== undefined,
145
+ otherHostRows,
146
+ unattributedRows,
117
147
  };
118
148
  })();
119
149
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@principles/host-runtime",
3
- "version": "0.14.1",
3
+ "version": "0.14.2",
4
4
  "description": "Shared host-neutral orchestration for Principles Disciple MVP-Core hook paths.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-principles-disciple",
3
- "version": "1.145.30",
3
+ "version": "1.145.33",
4
4
  "description": "Interactive CLI installer for Principles Disciple OpenClaw plugin",
5
5
  "type": "module",
6
6
  "bin": {
@@ -89,6 +89,6 @@
89
89
  "directory": "packages/create-principles-disciple"
90
90
  },
91
91
  "pd": {
92
- "bundledPluginVersion": "2.2.5"
92
+ "bundledPluginVersion": "2.2.7"
93
93
  }
94
94
  }
@@ -0,0 +1,25 @@
1
+ import type { RecoveryCapabilityEvidence } from '@principles/core/runtime-v2';
2
+ /**
3
+ * SPEC-RULECODE-HOST-PROMOTION-001 R3/R4: CLI-channel recovery reachability
4
+ * for the pd-cli readiness path. Thin wrapper — the real subprocess probes
5
+ * live in host-runtime (`probeCliRecoveryCapabilities`) so the Console
6
+ * readiness assembly reuses the SAME implementation. This wrapper only
7
+ * resolves the built pd CLI entry for the CURRENT environment and fails
8
+ * closed (all capabilities not-verified) when it cannot.
9
+ *
10
+ * Evidence semantics (R4/P1): the CLI subprocess channel can prove
11
+ * `pd_status` and `rulecode_deactivate` (real `--dry-run` validation path —
12
+ * no audit write, no mutation); the console-channel capabilities are
13
+ * reported NOT-VERIFIED with the precise reason — never fabricated as ok.
14
+ */
15
+ export { DEACTIVATE_DRY_RUN_PROBE_ACTIVATION_ID } from '@principles/host-runtime';
16
+ /**
17
+ * Probe the CLI-channel recovery capabilities against the target workspace.
18
+ * When `expectedActivationId` is supplied, pd_status additionally requires
19
+ * that activation to appear in the listing — proof the probe targeted the
20
+ * governed workspace, not merely some workspace.
21
+ */
22
+ export declare function probeCliRecoveryReachability(workspaceDir: string, expectedActivationId?: string, options?: {
23
+ timeoutMs?: number;
24
+ }): Promise<RecoveryCapabilityEvidence[]>;
25
+ //# sourceMappingURL=recovery-reachability-probe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recovery-reachability-probe.d.ts","sourceRoot":"","sources":["../../src/commands/recovery-reachability-probe.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AAE9E;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,sCAAsC,EAAE,MAAM,0BAA0B,CAAC;AAelF;;;;;GAKG;AACH,wBAAsB,4BAA4B,CAAC,YAAY,EAAE,MAAM,EAAE,oBAAoB,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,0BAA0B,EAAE,CAAC,CAW/K"}
@@ -0,0 +1,50 @@
1
+ import { existsSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { probeCliRecoveryCapabilities } from '@principles/host-runtime';
5
+ /**
6
+ * SPEC-RULECODE-HOST-PROMOTION-001 R3/R4: CLI-channel recovery reachability
7
+ * for the pd-cli readiness path. Thin wrapper — the real subprocess probes
8
+ * live in host-runtime (`probeCliRecoveryCapabilities`) so the Console
9
+ * readiness assembly reuses the SAME implementation. This wrapper only
10
+ * resolves the built pd CLI entry for the CURRENT environment and fails
11
+ * closed (all capabilities not-verified) when it cannot.
12
+ *
13
+ * Evidence semantics (R4/P1): the CLI subprocess channel can prove
14
+ * `pd_status` and `rulecode_deactivate` (real `--dry-run` validation path —
15
+ * no audit write, no mutation); the console-channel capabilities are
16
+ * reported NOT-VERIFIED with the precise reason — never fabricated as ok.
17
+ */
18
+ export { DEACTIVATE_DRY_RUN_PROBE_ACTIVATION_ID } from '@principles/host-runtime';
19
+ function resolveCliEntry() {
20
+ // Built layout: dist/commands/<this>.js with the entry at dist/index.js.
21
+ const here = path.dirname(fileURLToPath(import.meta.url));
22
+ const candidates = [
23
+ path.resolve(here, '..', 'index.js'),
24
+ path.resolve(process.cwd(), 'dist', 'index.js'),
25
+ ];
26
+ for (const candidate of candidates) {
27
+ if (existsSync(candidate))
28
+ return candidate;
29
+ }
30
+ return null;
31
+ }
32
+ /**
33
+ * Probe the CLI-channel recovery capabilities against the target workspace.
34
+ * When `expectedActivationId` is supplied, pd_status additionally requires
35
+ * that activation to appear in the listing — proof the probe targeted the
36
+ * governed workspace, not merely some workspace.
37
+ */
38
+ export async function probeCliRecoveryReachability(workspaceDir, expectedActivationId, options) {
39
+ const cliEntry = resolveCliEntry();
40
+ if (cliEntry === null) {
41
+ return [
42
+ { capabilityId: 'pd_status', channel: 'cli', ok: false, workspaceMatched: false, detail: 'pd CLI entry not found (built entry missing in this environment)' },
43
+ { capabilityId: 'rulecode_deactivate', channel: 'cli', ok: false, workspaceMatched: false, detail: 'pd CLI entry not found (built entry missing in this environment)' },
44
+ { capabilityId: 'rulecode_global_pause', channel: 'console', ok: false, workspaceMatched: false, detail: 'console-channel control: verifying the HTTP-only recovery entry requires the Owner Console process; a CLI subprocess cannot produce this evidence' },
45
+ { capabilityId: 'owner_review_access', channel: 'console', ok: false, workspaceMatched: false, detail: 'console-channel control: verifying the HTTP-only recovery entry requires the Owner Console process; a CLI subprocess cannot produce this evidence' },
46
+ ];
47
+ }
48
+ return probeCliRecoveryCapabilities({ cliEntry, workspaceDir, ...(expectedActivationId !== undefined ? { expectedActivationId } : {}), ...(options?.timeoutMs !== undefined ? { timeoutMs: options.timeoutMs } : {}) });
49
+ }
50
+ //# sourceMappingURL=recovery-reachability-probe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recovery-reachability-probe.js","sourceRoot":"","sources":["../../src/commands/recovery-reachability-probe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,4BAA4B,EAAE,MAAM,0BAA0B,CAAC;AAGxE;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,sCAAsC,EAAE,MAAM,0BAA0B,CAAC;AAElF,SAAS,eAAe;IACtB,yEAAyE;IACzE,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC;QACpC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC;KAChD,CAAC;IACF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;IAC9C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,YAAoB,EAAE,oBAA6B,EAAE,OAAgC;IACtI,MAAM,QAAQ,GAAG,eAAe,EAAE,CAAC;IACnC,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtB,OAAO;YACL,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,kEAAkE,EAAE;YAC7J,EAAE,YAAY,EAAE,qBAAqB,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,kEAAkE,EAAE;YACvK,EAAE,YAAY,EAAE,uBAAuB,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,mJAAmJ,EAAE;YAC9P,EAAE,YAAY,EAAE,qBAAqB,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,mJAAmJ,EAAE;SAC7P,CAAC;IACJ,CAAC;IACD,OAAO,4BAA4B,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,CAAC,oBAAoB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,oBAAoB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,OAAO,EAAE,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;AAC1N,CAAC"}
@@ -29,7 +29,7 @@ export interface CollectedRuleCodeEventEntries {
29
29
  */
30
30
  export declare function collectRuleCodeEventEntries(workspaceDir: string): CollectedRuleCodeEventEntries;
31
31
  /** Exported for PRI-577 regression tests and reuse by promote evidence assembly. */
32
- export declare function readShadowSummaryForActivation(workspaceDir: string, activationId: string): PromotionEvidenceSnapshot['shadowSummary'];
32
+ export declare function readShadowSummaryForActivation(workspaceDir: string, activationId: string, targetHostKind?: string): PromotionEvidenceSnapshot['shadowSummary'];
33
33
  interface ActivationDispatchOptions {
34
34
  workspace?: string;
35
35
  artifactId?: string;
@@ -44,6 +44,15 @@ interface ActivationDeactivateOptions {
44
44
  activationId?: string;
45
45
  reasonCode?: string;
46
46
  json?: boolean;
47
+ /**
48
+ * SPEC-RULECODE-HOST-PROMOTION-001 R4/P1: non-destructive validation path
49
+ * for the recovery reachability probe. Runs the REAL entry through real
50
+ * parsing, workspace binding, and target-resolution preconditions, then
51
+ * returns BEFORE the governance audit write and BEFORE any store mutation.
52
+ * Mutually exclusive with an actual deactivation by construction: the
53
+ * dry-run branch never reaches the deactivate call.
54
+ */
55
+ dryRun?: boolean;
47
56
  }
48
57
  export interface DeactivateResult {
49
58
  ok: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-activation.d.ts","sourceRoot":"","sources":["../../src/commands/runtime-activation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runtime-activation.d.ts","sourceRoot":"","sources":["../../src/commands/runtime-activation.ts"],"names":[],"mappings":"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"}