create-principles-disciple 1.97.1 → 1.99.0

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 (189) hide show
  1. package/console/dist/server/models/ActivationsConsoleModel.js +29 -3
  2. package/console/dist/server/models/ApprovalsConsoleModel.d.ts +13 -0
  3. package/console/dist/server/models/ApprovalsConsoleModel.js +95 -3
  4. package/console/dist/server/models/FeedbackReportConsoleModel.js +1 -1
  5. package/console/dist/ui/api.js +1 -1
  6. package/console/dist/ui/pages/pain/PainEvidenceValidators.js +1 -1
  7. package/console/dist/web/assets/app.js +10 -6
  8. package/console/package.json +1 -1
  9. package/core/dist/runtime-v2/__tests__/architecture-regression.test.js +8 -7
  10. package/core/dist/runtime-v2/__tests__/architecture-regression.test.js.map +1 -1
  11. package/core/dist/runtime-v2/__tests__/artificer-runner-vslice.test.js +45 -0
  12. package/core/dist/runtime-v2/__tests__/artificer-runner-vslice.test.js.map +1 -1
  13. package/core/dist/runtime-v2/__tests__/dreamer-runner.test.js +15 -2
  14. package/core/dist/runtime-v2/__tests__/dreamer-runner.test.js.map +1 -1
  15. package/core/dist/runtime-v2/__tests__/evaluator-runner-vslice-v2.test.js +44 -0
  16. package/core/dist/runtime-v2/__tests__/evaluator-runner-vslice-v2.test.js.map +1 -1
  17. package/core/dist/runtime-v2/activation/__tests__/activation-re-dispatch.test.d.ts +2 -0
  18. package/core/dist/runtime-v2/activation/__tests__/activation-re-dispatch.test.d.ts.map +1 -0
  19. package/core/dist/runtime-v2/activation/__tests__/activation-re-dispatch.test.js +149 -0
  20. package/core/dist/runtime-v2/activation/__tests__/activation-re-dispatch.test.js.map +1 -0
  21. package/core/dist/runtime-v2/activation/__tests__/sqlite-activation-state-store.test.js +72 -2
  22. package/core/dist/runtime-v2/activation/__tests__/sqlite-activation-state-store.test.js.map +1 -1
  23. package/core/dist/runtime-v2/activation/activation-dispatcher.d.ts.map +1 -1
  24. package/core/dist/runtime-v2/activation/activation-dispatcher.js +5 -0
  25. package/core/dist/runtime-v2/activation/activation-dispatcher.js.map +1 -1
  26. package/core/dist/runtime-v2/activation/activation-types.d.ts +1 -0
  27. package/core/dist/runtime-v2/activation/activation-types.d.ts.map +1 -1
  28. package/core/dist/runtime-v2/activation/activation-types.js.map +1 -1
  29. package/core/dist/runtime-v2/activation/memory-activation-state-store.d.ts.map +1 -1
  30. package/core/dist/runtime-v2/activation/memory-activation-state-store.js +6 -1
  31. package/core/dist/runtime-v2/activation/memory-activation-state-store.js.map +1 -1
  32. package/core/dist/runtime-v2/activation/memory-approval-store.js +1 -1
  33. package/core/dist/runtime-v2/activation/memory-approval-store.js.map +1 -1
  34. package/core/dist/runtime-v2/activation/sqlite-activation-state-store.d.ts +1 -0
  35. package/core/dist/runtime-v2/activation/sqlite-activation-state-store.d.ts.map +1 -1
  36. package/core/dist/runtime-v2/activation/sqlite-activation-state-store.js +64 -10
  37. package/core/dist/runtime-v2/activation/sqlite-activation-state-store.js.map +1 -1
  38. package/core/dist/runtime-v2/activation/sqlite-approval-store.d.ts.map +1 -1
  39. package/core/dist/runtime-v2/activation/sqlite-approval-store.js +9 -1
  40. package/core/dist/runtime-v2/activation/sqlite-approval-store.js.map +1 -1
  41. package/core/dist/runtime-v2/activation/writers/__tests__/rule-host-writer.test.js +18 -9
  42. package/core/dist/runtime-v2/activation/writers/__tests__/rule-host-writer.test.js.map +1 -1
  43. package/core/dist/runtime-v2/activation/writers/rule-host-writer.d.ts.map +1 -1
  44. package/core/dist/runtime-v2/activation/writers/rule-host-writer.js +8 -1
  45. package/core/dist/runtime-v2/activation/writers/rule-host-writer.js.map +1 -1
  46. package/core/dist/runtime-v2/adapter/__tests__/principle-tree-ledger-adapter.test.d.ts +2 -0
  47. package/core/dist/runtime-v2/adapter/__tests__/principle-tree-ledger-adapter.test.d.ts.map +1 -0
  48. package/core/dist/runtime-v2/adapter/__tests__/principle-tree-ledger-adapter.test.js +134 -0
  49. package/core/dist/runtime-v2/adapter/__tests__/principle-tree-ledger-adapter.test.js.map +1 -0
  50. package/core/dist/runtime-v2/adapter/openclaw-cli-runtime-adapter.js +1 -1
  51. package/core/dist/runtime-v2/adapter/openclaw-cli-runtime-adapter.js.map +1 -1
  52. package/core/dist/runtime-v2/adapter/pi-ai-runtime-adapter.js +2 -2
  53. package/core/dist/runtime-v2/adapter/pi-ai-runtime-adapter.js.map +1 -1
  54. package/core/dist/runtime-v2/adapter/principle-tree-ledger-adapter.d.ts +15 -0
  55. package/core/dist/runtime-v2/adapter/principle-tree-ledger-adapter.d.ts.map +1 -1
  56. package/core/dist/runtime-v2/adapter/principle-tree-ledger-adapter.js +23 -1
  57. package/core/dist/runtime-v2/adapter/principle-tree-ledger-adapter.js.map +1 -1
  58. package/core/dist/runtime-v2/control-plane-triage.js +2 -2
  59. package/core/dist/runtime-v2/control-plane-triage.js.map +1 -1
  60. package/core/dist/runtime-v2/error-categories.js +1 -1
  61. package/core/dist/runtime-v2/error-categories.js.map +1 -1
  62. package/core/dist/runtime-v2/golden-trace.js +1 -1
  63. package/core/dist/runtime-v2/golden-trace.js.map +1 -1
  64. package/core/dist/runtime-v2/index.d.ts +1 -1
  65. package/core/dist/runtime-v2/index.d.ts.map +1 -1
  66. package/core/dist/runtime-v2/index.js +1 -1
  67. package/core/dist/runtime-v2/index.js.map +1 -1
  68. package/core/dist/runtime-v2/intent/__tests__/intent-browser.test.d.ts +2 -0
  69. package/core/dist/runtime-v2/intent/__tests__/intent-browser.test.d.ts.map +1 -0
  70. package/core/dist/runtime-v2/intent/__tests__/intent-browser.test.js +93 -0
  71. package/core/dist/runtime-v2/intent/__tests__/intent-browser.test.js.map +1 -0
  72. package/core/dist/runtime-v2/intent/__tests__/intent-doc-version-edge-cases.test.d.ts +2 -0
  73. package/core/dist/runtime-v2/intent/__tests__/intent-doc-version-edge-cases.test.d.ts.map +1 -0
  74. package/core/dist/runtime-v2/intent/__tests__/intent-doc-version-edge-cases.test.js +182 -0
  75. package/core/dist/runtime-v2/intent/__tests__/intent-doc-version-edge-cases.test.js.map +1 -0
  76. package/core/dist/runtime-v2/internalization/__tests__/artificer-prompt-builder-v2.test.js +20 -0
  77. package/core/dist/runtime-v2/internalization/__tests__/artificer-prompt-builder-v2.test.js.map +1 -1
  78. package/core/dist/runtime-v2/internalization/__tests__/artificer-prompt-builder.test.js +69 -13
  79. package/core/dist/runtime-v2/internalization/__tests__/artificer-prompt-builder.test.js.map +1 -1
  80. package/core/dist/runtime-v2/internalization/__tests__/artificer-rule-output.test.js +13 -6
  81. package/core/dist/runtime-v2/internalization/__tests__/artificer-rule-output.test.js.map +1 -1
  82. package/core/dist/runtime-v2/internalization/__tests__/split-diagnostician-runner-retry.test.js +113 -0
  83. package/core/dist/runtime-v2/internalization/__tests__/split-diagnostician-runner-retry.test.js.map +1 -1
  84. package/core/dist/runtime-v2/internalization/artificer-output.d.ts.map +1 -1
  85. package/core/dist/runtime-v2/internalization/artificer-output.js +8 -2
  86. package/core/dist/runtime-v2/internalization/artificer-output.js.map +1 -1
  87. package/core/dist/runtime-v2/internalization/artificer-prompt-builder.d.ts +6 -1
  88. package/core/dist/runtime-v2/internalization/artificer-prompt-builder.d.ts.map +1 -1
  89. package/core/dist/runtime-v2/internalization/artificer-prompt-builder.js +33 -7
  90. package/core/dist/runtime-v2/internalization/artificer-prompt-builder.js.map +1 -1
  91. package/core/dist/runtime-v2/internalization/artificer-runner.d.ts +5 -0
  92. package/core/dist/runtime-v2/internalization/artificer-runner.d.ts.map +1 -1
  93. package/core/dist/runtime-v2/internalization/artificer-runner.js +68 -3
  94. package/core/dist/runtime-v2/internalization/artificer-runner.js.map +1 -1
  95. package/core/dist/runtime-v2/internalization/dreamer-runner.d.ts.map +1 -1
  96. package/core/dist/runtime-v2/internalization/dreamer-runner.js +4 -0
  97. package/core/dist/runtime-v2/internalization/dreamer-runner.js.map +1 -1
  98. package/core/dist/runtime-v2/internalization/evaluator-runner.d.ts.map +1 -1
  99. package/core/dist/runtime-v2/internalization/evaluator-runner.js +3 -1
  100. package/core/dist/runtime-v2/internalization/evaluator-runner.js.map +1 -1
  101. package/core/dist/runtime-v2/internalization/intake-to-internalization-bridge.d.ts.map +1 -1
  102. package/core/dist/runtime-v2/internalization/intake-to-internalization-bridge.js +1 -0
  103. package/core/dist/runtime-v2/internalization/intake-to-internalization-bridge.js.map +1 -1
  104. package/core/dist/runtime-v2/internalization/split-diagnostician-runner.d.ts.map +1 -1
  105. package/core/dist/runtime-v2/internalization/split-diagnostician-runner.js +27 -0
  106. package/core/dist/runtime-v2/internalization/split-diagnostician-runner.js.map +1 -1
  107. package/core/dist/runtime-v2/internalization-chain-integrity-read-model.d.ts.map +1 -1
  108. package/core/dist/runtime-v2/internalization-chain-integrity-read-model.js +4 -1
  109. package/core/dist/runtime-v2/internalization-chain-integrity-read-model.js.map +1 -1
  110. package/core/dist/runtime-v2/pain-signal-bridge.d.ts.map +1 -1
  111. package/core/dist/runtime-v2/pain-signal-bridge.js +1 -0
  112. package/core/dist/runtime-v2/pain-signal-bridge.js.map +1 -1
  113. package/core/dist/runtime-v2/pain-signal-runtime-factory.d.ts.map +1 -1
  114. package/core/dist/runtime-v2/pain-signal-runtime-factory.js +1 -0
  115. package/core/dist/runtime-v2/pain-signal-runtime-factory.js.map +1 -1
  116. package/core/dist/runtime-v2/proven-channel-baseline.js +1 -1
  117. package/core/dist/runtime-v2/proven-channel-baseline.js.map +1 -1
  118. package/core/dist/runtime-v2/store/commit/diagnostician-committer.d.ts.map +1 -1
  119. package/core/dist/runtime-v2/store/commit/diagnostician-committer.js +1 -0
  120. package/core/dist/runtime-v2/store/commit/diagnostician-committer.js.map +1 -1
  121. package/core/dist/runtime-v2/store/context/resilient-context-assembler.js +1 -1
  122. package/core/dist/runtime-v2/store/context/resilient-context-assembler.js.map +1 -1
  123. package/core/dist/runtime-v2/store/sqlite-connection.d.ts.map +1 -1
  124. package/core/dist/runtime-v2/store/sqlite-connection.js +4 -0
  125. package/core/dist/runtime-v2/store/sqlite-connection.js.map +1 -1
  126. package/core/dist/runtime-v2/types/event-types.d.ts +4 -0
  127. package/core/dist/runtime-v2/types/event-types.d.ts.map +1 -1
  128. package/core/dist/runtime-v2/types/event-types.js +5 -0
  129. package/core/dist/runtime-v2/types/event-types.js.map +1 -1
  130. package/dist/installer.js +1 -1
  131. package/dist/installer.js.map +1 -1
  132. package/dist/mvp-config.js +1 -1
  133. package/dist/mvp-config.js.map +1 -1
  134. package/dist/uninstaller.js +2 -2
  135. package/dist/uninstaller.js.map +1 -1
  136. package/package.json +2 -2
  137. package/pd-cli/dist/commands/__tests__/run-rulehost-flag-wiring.test.js +9 -0
  138. package/pd-cli/dist/commands/__tests__/run-rulehost-flag-wiring.test.js.map +1 -1
  139. package/pd-cli/dist/commands/candidate.d.ts.map +1 -1
  140. package/pd-cli/dist/commands/candidate.js +3 -0
  141. package/pd-cli/dist/commands/candidate.js.map +1 -1
  142. package/pd-cli/dist/commands/diagnose.d.ts.map +1 -1
  143. package/pd-cli/dist/commands/diagnose.js +72 -4
  144. package/pd-cli/dist/commands/diagnose.js.map +1 -1
  145. package/pd-cli/dist/commands/pain-record.d.ts.map +1 -1
  146. package/pd-cli/dist/commands/pain-record.js +21 -0
  147. package/pd-cli/dist/commands/pain-record.js.map +1 -1
  148. package/pd-cli/dist/commands/pain-retry.d.ts.map +1 -1
  149. package/pd-cli/dist/commands/pain-retry.js +1 -0
  150. package/pd-cli/dist/commands/pain-retry.js.map +1 -1
  151. package/pd-cli/dist/commands/runtime-activation.d.ts +26 -0
  152. package/pd-cli/dist/commands/runtime-activation.d.ts.map +1 -1
  153. package/pd-cli/dist/commands/runtime-activation.js +319 -3
  154. package/pd-cli/dist/commands/runtime-activation.js.map +1 -1
  155. package/pd-cli/dist/commands/runtime-internalization-enqueue-successors.d.ts.map +1 -1
  156. package/pd-cli/dist/commands/runtime-internalization-enqueue-successors.js +3 -1
  157. package/pd-cli/dist/commands/runtime-internalization-enqueue-successors.js.map +1 -1
  158. package/pd-cli/dist/commands/runtime-internalization-run-rulehost.d.ts +1 -0
  159. package/pd-cli/dist/commands/runtime-internalization-run-rulehost.d.ts.map +1 -1
  160. package/pd-cli/dist/commands/runtime-internalization-run-rulehost.js +149 -6
  161. package/pd-cli/dist/commands/runtime-internalization-run-rulehost.js.map +1 -1
  162. package/pd-cli/dist/commands/runtime-uat.d.ts.map +1 -1
  163. package/pd-cli/dist/commands/runtime-uat.js +4 -3
  164. package/pd-cli/dist/commands/runtime-uat.js.map +1 -1
  165. package/pd-cli/dist/config-reader.js +1 -1
  166. package/pd-cli/dist/config-reader.js.map +1 -1
  167. package/pd-cli/dist/index.js +22 -1
  168. package/pd-cli/dist/index.js.map +1 -1
  169. package/pd-cli/dist/services/pd-config-loader.js +2 -2
  170. package/pd-cli/dist/services/pd-config-loader.js.map +1 -1
  171. package/pd-cli/dist/services/rulehost-pipeline-runner.d.ts +5 -1
  172. package/pd-cli/dist/services/rulehost-pipeline-runner.d.ts.map +1 -1
  173. package/pd-cli/dist/services/rulehost-pipeline-runner.js +4 -1
  174. package/pd-cli/dist/services/rulehost-pipeline-runner.js.map +1 -1
  175. package/plugin/dist/core/behavior-example-pack-assembler.d.ts +6 -11
  176. package/plugin/dist/core/behavior-example-pack-assembler.js +44 -84
  177. package/plugin/dist/core/pd-config-loader.js +1 -1
  178. package/plugin/dist/core/rule-host.d.ts +22 -1
  179. package/plugin/dist/core/rule-host.js +107 -18
  180. package/plugin/dist/core/trajectory-types.d.ts +4 -0
  181. package/plugin/dist/core/trajectory.d.ts +6 -2
  182. package/plugin/dist/core/trajectory.js +41 -0
  183. package/plugin/dist/core/workflow-funnel-loader.js +2 -2
  184. package/plugin/dist/core/workspace-context.d.ts +4 -0
  185. package/plugin/dist/core/workspace-context.js +13 -0
  186. package/plugin/dist/hooks/gate.js +42 -50
  187. package/plugin/dist/rulehost-evidence.d.ts +4 -0
  188. package/plugin/dist/rulehost-evidence.js +3 -0
  189. package/plugin/package.json +5 -1
@@ -1,4 +1,4 @@
1
- import { SqliteConnection, SqliteActivationStateStore, SqlitePIArtifactStore, } from '@principles/core/runtime-v2';
1
+ import { SqliteConnection, SqliteActivationStateStore, SqlitePIArtifactStore, extractPrincipleId, } from '@principles/core/runtime-v2';
2
2
  import * as fs from 'node:fs';
3
3
  import * as path from 'node:path';
4
4
  function isMissingTableError(err) {
@@ -6,6 +6,26 @@ function isMissingTableError(err) {
6
6
  return false;
7
7
  return err.message.includes('no such table');
8
8
  }
9
+ /**
10
+ * Bug-O L2 fix: adapt PIArtifactRecord (DB row) to PIArtifactSnapshot (activation
11
+ * contract type). The two interfaces have identical fields but different names —
12
+ * we use explicit field copy instead of `as` to comply with rc-2-no-as-bypass
13
+ * and to surface future field drift as a compile error.
14
+ */
15
+ function toSnapshot(record) {
16
+ return {
17
+ artifactId: record.artifactId,
18
+ artifactKind: record.artifactKind,
19
+ sourceTaskId: record.sourceTaskId,
20
+ sourcePrincipleId: record.sourcePrincipleId,
21
+ sourceRuleId: record.sourceRuleId,
22
+ lineageArtifactIds: record.lineageArtifactIds,
23
+ validationStatus: record.validationStatus,
24
+ contentJson: record.contentJson,
25
+ createdAt: record.createdAt,
26
+ updatedAt: record.updatedAt,
27
+ };
28
+ }
9
29
  export class ActivationsConsoleModel {
10
30
  workspaceDir;
11
31
  constructor(workspaceDir) {
@@ -30,13 +50,19 @@ export class ActivationsConsoleModel {
30
50
  }
31
51
  throw err;
32
52
  }
33
- // Build artifactId → sourcePrincipleId map from PIArtifactSnapshot
53
+ // Build artifactId → principleId map. Bug-O L2 fix: use extractPrincipleId
54
+ // (4-step fallback: column → parsed.principleId → parsed.sourcePrincipleId
55
+ // → parsed.principleDraft.title) instead of only reading the column.
56
+ // Without this, dreamer artifacts whose sourcePrincipleId was stripped
57
+ // (non-core-principle case) would show 'unlinked' even when contentJson
58
+ // carries a resolvable principleId.
34
59
  const artifactPrincipleMap = new Map();
35
60
  for (const activation of allActivations) {
36
61
  if (!artifactPrincipleMap.has(activation.artifactId)) {
37
62
  try {
38
63
  const artifact = await artifactStore.getArtifactById(activation.artifactId);
39
- artifactPrincipleMap.set(activation.artifactId, artifact?.sourcePrincipleId ?? null);
64
+ const principleId = artifact ? extractPrincipleId(toSnapshot(artifact)) : null;
65
+ artifactPrincipleMap.set(activation.artifactId, principleId);
40
66
  }
41
67
  catch (err) {
42
68
  if (isMissingTableError(err)) {
@@ -38,6 +38,19 @@ export declare class ApprovalsConsoleModel {
38
38
  isMvpProven: boolean;
39
39
  }) | null>;
40
40
  approve(approvalId: string, decidedBy: string, note?: string): Promise<ApproveWithActivationResult>;
41
+ /**
42
+ * Bug-O L3b fix: upgrade the ledger principle linked to `artifactId` from
43
+ * 'candidate' to 'active'. Called by {@link approve} after a successful
44
+ * activation. Non-fatal on failure — the activation is already committed;
45
+ * ledger failure is surfaced as a warning string (rc-9).
46
+ *
47
+ * The principleId is resolved via {@link extractPrincipleId}'s 4-step
48
+ * fallback (column → parsed.principleId → parsed.sourcePrincipleId →
49
+ * parsed.principleDraft.title) so dreamer artifacts whose
50
+ * sourcePrincipleId column was stripped by stripFabricatedCorePrincipleIds
51
+ * can still be linked via contentJson.
52
+ */
53
+ private upgradeLedgerPrinciple;
41
54
  /**
42
55
  * Edit a pending approval's artifact to a new version (P1 #2 fix).
43
56
  *
@@ -1,6 +1,6 @@
1
1
  import * as fs from 'node:fs';
2
2
  import * as path from 'node:path';
3
- import { SqliteConnection, SqliteApprovalQueueStore, SqliteActivationStateStore, SqlitePIArtifactStore, ActivationDispatcher, PromptWriter, DeferArchiveWriter, RuleHostWriter, createProductionGateDeps, ApprovalCompletionService, ApprovalQueue, mapConfidenceToLabel, isArtifactRevisionOf, MVP_CHANNELS, } from '@principles/core/runtime-v2';
3
+ import { SqliteConnection, SqliteApprovalQueueStore, SqliteActivationStateStore, SqlitePIArtifactStore, ActivationDispatcher, PromptWriter, DeferArchiveWriter, RuleHostWriter, createProductionGateDeps, ApprovalCompletionService, ApprovalQueue, mapConfidenceToLabel, isArtifactRevisionOf, extractPrincipleId, PrincipleTreeLedgerAdapter, MVP_CHANNELS, } from '@principles/core/runtime-v2';
4
4
  import { loadPdConfig, computeFlagsFromLoadResult } from '../config/pd-config-store.js';
5
5
  const MVP_PROVEN_CHANNELS = new Set(MVP_CHANNELS);
6
6
  const EMPTY_STATS = { pending: 0, approved: 0, rejected: 0, cancelled: 0 };
@@ -12,6 +12,26 @@ function isMissingTableError(err) {
12
12
  function isActivationSuccess(activation) {
13
13
  return activation.decision === 'activated' || activation.decision === 'already_activated';
14
14
  }
15
+ /**
16
+ * Bug-O L3b fix: adapt a PIArtifactRecord (DB row) to a PIArtifactSnapshot
17
+ * (activation contract type). The two interfaces have identical fields but
18
+ * different names — explicit field copy surfaces future field drift as a
19
+ * compile error and complies with rc-2-no-as-bypass.
20
+ */
21
+ function toArtifactSnapshot(record) {
22
+ return {
23
+ artifactId: record.artifactId,
24
+ artifactKind: record.artifactKind,
25
+ sourceTaskId: record.sourceTaskId,
26
+ sourcePrincipleId: record.sourcePrincipleId,
27
+ sourceRuleId: record.sourceRuleId,
28
+ lineageArtifactIds: record.lineageArtifactIds,
29
+ validationStatus: record.validationStatus,
30
+ contentJson: record.contentJson,
31
+ createdAt: record.createdAt,
32
+ updatedAt: record.updatedAt,
33
+ };
34
+ }
15
35
  function stateDbExists(workspaceDir) {
16
36
  return fs.existsSync(path.join(workspaceDir, '.pd', 'state.db'));
17
37
  }
@@ -103,6 +123,7 @@ export class ApprovalsConsoleModel {
103
123
  const activation = await this.dispatchActivationAfterApproval(existing, decidedBy);
104
124
  // If activation failed, roll back approval to pending so the user can retry.
105
125
  if (activation && !isActivationSuccess(activation)) {
126
+ // eslint-disable-next-line no-restricted-syntax -- 'in' required for discriminated union narrowing (ActivationDecision)
106
127
  const detail = 'reason' in activation ? activation.reason : activation.decision;
107
128
  let approvalRolledBack = false;
108
129
  try {
@@ -133,7 +154,75 @@ export class ApprovalsConsoleModel {
133
154
  warning: 'activation_skipped_feature_flag_disabled: approval is recorded but activation was not dispatched. Enable story_a_approval_completion flag or manually run "pd runtime activation dispatch" to activate.',
134
155
  };
135
156
  }
136
- return { ok: true, record: approvalResult.record, activation };
157
+ // Bug-O L3b fix: after a successful activation, upgrade the corresponding
158
+ // ledger principle from 'candidate' to 'active'. The activation is already
159
+ // committed to SQLite; a ledger failure here is non-fatal and surfaced as
160
+ // a warning (rc-9-no-silent-fallback) — the owner is informed that the
161
+ // ledger state may be out of sync and can be repaired separately.
162
+ //
163
+ // CodeRabbit review fix: use approvalResult.record.artifactId (post-approve
164
+ // source of truth) instead of the pre-read `existing.artifactId`. If
165
+ // editApproval() changed the artifact pointer between read and write, the
166
+ // pre-read value would bind the ledger upgrade to the wrong artifact while
167
+ // the returned record points to the new one.
168
+ let ledgerWarning;
169
+ if (isActivationSuccess(activation)) {
170
+ ledgerWarning = await this.upgradeLedgerPrinciple(approvalResult.record.artifactId);
171
+ }
172
+ return { ok: true, record: approvalResult.record, activation, warning: ledgerWarning };
173
+ }
174
+ /**
175
+ * Bug-O L3b fix: upgrade the ledger principle linked to `artifactId` from
176
+ * 'candidate' to 'active'. Called by {@link approve} after a successful
177
+ * activation. Non-fatal on failure — the activation is already committed;
178
+ * ledger failure is surfaced as a warning string (rc-9).
179
+ *
180
+ * The principleId is resolved via {@link extractPrincipleId}'s 4-step
181
+ * fallback (column → parsed.principleId → parsed.sourcePrincipleId →
182
+ * parsed.principleDraft.title) so dreamer artifacts whose
183
+ * sourcePrincipleId column was stripped by stripFabricatedCorePrincipleIds
184
+ * can still be linked via contentJson.
185
+ */
186
+ async upgradeLedgerPrinciple(artifactId) {
187
+ const stateDir = path.join(this.workspaceDir, '.state');
188
+ const { connection } = this.createReadContext();
189
+ try {
190
+ const piArtifactStore = new SqlitePIArtifactStore(connection);
191
+ const artifact = await piArtifactStore.getArtifactById(artifactId);
192
+ if (!artifact) {
193
+ // rc-9: surface the reason instead of silently returning.
194
+ return `ledger_activate_skipped: artifact ${artifactId} not found in artifact store`;
195
+ }
196
+ const principleId = extractPrincipleId(toArtifactSnapshot(artifact));
197
+ if (!principleId) {
198
+ // No principleId resolvable from any source — this is a legitimate
199
+ // skip (e.g. rule-only artifact), not an error. Surface it so the
200
+ // owner can verify whether the link was supposed to exist.
201
+ return `ledger_activate_skipped: artifact ${artifactId} has no resolvable principleId`;
202
+ }
203
+ const ledger = new PrincipleTreeLedgerAdapter({ stateDir });
204
+ const result = ledger.activatePrinciple(principleId);
205
+ if (!result.ok) {
206
+ // Reason is already prefixed with `ledger_activate_failed:`.
207
+ return result.reason;
208
+ }
209
+ return undefined;
210
+ }
211
+ catch (err) {
212
+ // CodeRabbit review fix: read-side failures (getArtifactById, missing
213
+ // table, connection errors) must NOT propagate upward and fail the
214
+ // approval flow after activation is already committed. The activation
215
+ // succeeded; ledger upgrade is a non-fatal post-step. Surface the error
216
+ // as a warning so the owner can repair the ledger separately (rc-9).
217
+ const message = err instanceof Error ? err.message : String(err);
218
+ return `ledger_activate_failed: ${message}`;
219
+ }
220
+ finally {
221
+ try {
222
+ connection.close();
223
+ }
224
+ catch { /* best-effort */ }
225
+ }
137
226
  }
138
227
  /**
139
228
  * Edit a pending approval's artifact to a new version (P1 #2 fix).
@@ -254,7 +343,10 @@ export class ApprovalsConsoleModel {
254
343
  const dispatcher = new ActivationDispatcher(artifactReadModel, activationStateStore, {
255
344
  writers: [
256
345
  new PromptWriter(),
257
- new RuleHostWriter({ gateDeps: createProductionGateDeps() }),
346
+ new RuleHostWriter({
347
+ gateDeps: createProductionGateDeps(),
348
+ featureFlagProbe: (flagId) => pdFlags.flags[flagId]?.enabled === true,
349
+ }),
258
350
  new DeferArchiveWriter(),
259
351
  ],
260
352
  approvalQueueStore,
@@ -15,7 +15,7 @@ import { randomUUID } from 'crypto';
15
15
  */
16
16
  function errMsg(e, err) {
17
17
  // Check the unknown caught value (err) for a string message first.
18
- if (err !== null && err !== undefined && typeof err === 'object' && 'message' in err) {
18
+ if (err !== null && err !== undefined && typeof err === 'object' && Object.hasOwn(err, 'message')) {
19
19
  const msg = err.message;
20
20
  if (typeof msg === 'string')
21
21
  return msg;
@@ -62,7 +62,7 @@ async function request(path, options, validate) {
62
62
  return { success: false, error: errorMessage, reason, nextAction };
63
63
  }
64
64
  const raw = await response.json();
65
- const apiData = (raw && typeof raw === "object" && "success" in raw && "data" in raw)
65
+ const apiData = (raw && typeof raw === "object" && Object.hasOwn(raw, "success") && Object.hasOwn(raw, "data"))
66
66
  ? raw.data
67
67
  : raw;
68
68
  if (validate) {
@@ -111,7 +111,7 @@ export function derivePainEvidenceFromPrinciplesList(raw) {
111
111
  * Check if a parsed result is degraded (missing data).
112
112
  */
113
113
  export function isDegraded(result) {
114
- return !('evidence' in result);
114
+ return !Object.hasOwn(result, 'evidence');
115
115
  }
116
116
  /**
117
117
  * Get error message from an unknown API error.