create-principles-disciple 1.79.0 → 1.81.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 (196) hide show
  1. package/console/package.json +1 -0
  2. package/core/dist/runtime-v2/__tests__/admission-gate.test.js +6 -6
  3. package/core/dist/runtime-v2/__tests__/admission-gate.test.js.map +1 -1
  4. package/core/dist/runtime-v2/__tests__/architecture-regression.test.js +39 -0
  5. package/core/dist/runtime-v2/__tests__/architecture-regression.test.js.map +1 -1
  6. package/core/dist/runtime-v2/__tests__/artificer-runner-vslice.test.js +52 -0
  7. package/core/dist/runtime-v2/__tests__/artificer-runner-vslice.test.js.map +1 -1
  8. package/core/dist/runtime-v2/__tests__/evaluator-runner-vslice.test.js +245 -1
  9. package/core/dist/runtime-v2/__tests__/evaluator-runner-vslice.test.js.map +1 -1
  10. package/core/dist/runtime-v2/__tests__/feedback/redact-sensitive.test.js +131 -1
  11. package/core/dist/runtime-v2/__tests__/feedback/redact-sensitive.test.js.map +1 -1
  12. package/core/dist/runtime-v2/__tests__/fixtures/llm-e2e-config.d.ts.map +1 -1
  13. package/core/dist/runtime-v2/__tests__/fixtures/llm-e2e-config.js +4 -2
  14. package/core/dist/runtime-v2/__tests__/fixtures/llm-e2e-config.js.map +1 -1
  15. package/core/dist/runtime-v2/__tests__/scribe-runner-vslice.test.js +425 -2
  16. package/core/dist/runtime-v2/__tests__/scribe-runner-vslice.test.js.map +1 -1
  17. package/core/dist/runtime-v2/__tests__/telemetry-event.test.d.ts +2 -0
  18. package/core/dist/runtime-v2/__tests__/telemetry-event.test.d.ts.map +1 -0
  19. package/core/dist/runtime-v2/__tests__/telemetry-event.test.js +69 -0
  20. package/core/dist/runtime-v2/__tests__/telemetry-event.test.js.map +1 -0
  21. package/core/dist/runtime-v2/admission-gate.d.ts.map +1 -1
  22. package/core/dist/runtime-v2/admission-gate.js +0 -8
  23. package/core/dist/runtime-v2/admission-gate.js.map +1 -1
  24. package/core/dist/runtime-v2/config/__tests__/pd-config-contract.test.d.ts +15 -0
  25. package/core/dist/runtime-v2/config/__tests__/pd-config-contract.test.d.ts.map +1 -0
  26. package/core/dist/runtime-v2/config/__tests__/pd-config-contract.test.js +685 -0
  27. package/core/dist/runtime-v2/config/__tests__/pd-config-contract.test.js.map +1 -0
  28. package/core/dist/runtime-v2/config/index.d.ts +14 -0
  29. package/core/dist/runtime-v2/config/index.d.ts.map +1 -0
  30. package/core/dist/runtime-v2/config/index.js +16 -0
  31. package/core/dist/runtime-v2/config/index.js.map +1 -0
  32. package/core/dist/runtime-v2/config/pd-config-defaults.d.ts +14 -0
  33. package/core/dist/runtime-v2/config/pd-config-defaults.d.ts.map +1 -0
  34. package/core/dist/runtime-v2/config/pd-config-defaults.js +74 -0
  35. package/core/dist/runtime-v2/config/pd-config-defaults.js.map +1 -0
  36. package/core/dist/runtime-v2/config/pd-config-effective.d.ts +14 -0
  37. package/core/dist/runtime-v2/config/pd-config-effective.d.ts.map +1 -0
  38. package/core/dist/runtime-v2/config/pd-config-effective.js +118 -0
  39. package/core/dist/runtime-v2/config/pd-config-effective.js.map +1 -0
  40. package/core/dist/runtime-v2/config/pd-config-feature-flags.d.ts +35 -0
  41. package/core/dist/runtime-v2/config/pd-config-feature-flags.d.ts.map +1 -0
  42. package/core/dist/runtime-v2/config/pd-config-feature-flags.js +99 -0
  43. package/core/dist/runtime-v2/config/pd-config-feature-flags.js.map +1 -0
  44. package/core/dist/runtime-v2/config/pd-config-redaction.d.ts +22 -0
  45. package/core/dist/runtime-v2/config/pd-config-redaction.d.ts.map +1 -0
  46. package/core/dist/runtime-v2/config/pd-config-redaction.js +179 -0
  47. package/core/dist/runtime-v2/config/pd-config-redaction.js.map +1 -0
  48. package/core/dist/runtime-v2/config/pd-config-types.d.ts +124 -0
  49. package/core/dist/runtime-v2/config/pd-config-types.d.ts.map +1 -0
  50. package/core/dist/runtime-v2/config/pd-config-types.js +35 -0
  51. package/core/dist/runtime-v2/config/pd-config-types.js.map +1 -0
  52. package/core/dist/runtime-v2/config/pd-config-validate.d.ts +16 -0
  53. package/core/dist/runtime-v2/config/pd-config-validate.d.ts.map +1 -0
  54. package/core/dist/runtime-v2/config/pd-config-validate.js +443 -0
  55. package/core/dist/runtime-v2/config/pd-config-validate.js.map +1 -0
  56. package/core/dist/runtime-v2/feature-flags/plugin-surface-registry.js +10 -10
  57. package/core/dist/runtime-v2/feature-flags/plugin-surface-registry.js.map +1 -1
  58. package/core/dist/runtime-v2/feedback/index.d.ts +1 -1
  59. package/core/dist/runtime-v2/feedback/index.d.ts.map +1 -1
  60. package/core/dist/runtime-v2/feedback/index.js +1 -1
  61. package/core/dist/runtime-v2/feedback/index.js.map +1 -1
  62. package/core/dist/runtime-v2/feedback/redact-sensitive.d.ts +2 -0
  63. package/core/dist/runtime-v2/feedback/redact-sensitive.d.ts.map +1 -1
  64. package/core/dist/runtime-v2/feedback/redact-sensitive.js +32 -3
  65. package/core/dist/runtime-v2/feedback/redact-sensitive.js.map +1 -1
  66. package/core/dist/runtime-v2/index.d.ts +5 -1
  67. package/core/dist/runtime-v2/index.d.ts.map +1 -1
  68. package/core/dist/runtime-v2/index.js +9 -1
  69. package/core/dist/runtime-v2/index.js.map +1 -1
  70. package/core/dist/runtime-v2/internalization/__tests__/peer-runner-lineage-injection.test.d.ts +2 -0
  71. package/core/dist/runtime-v2/internalization/__tests__/peer-runner-lineage-injection.test.d.ts.map +1 -0
  72. package/core/dist/runtime-v2/internalization/__tests__/peer-runner-lineage-injection.test.js +95 -0
  73. package/core/dist/runtime-v2/internalization/__tests__/peer-runner-lineage-injection.test.js.map +1 -0
  74. package/core/dist/runtime-v2/internalization/__tests__/philosopher-runner-trust-boundary.test.d.ts +2 -0
  75. package/core/dist/runtime-v2/internalization/__tests__/philosopher-runner-trust-boundary.test.d.ts.map +1 -0
  76. package/core/dist/runtime-v2/internalization/__tests__/philosopher-runner-trust-boundary.test.js +398 -0
  77. package/core/dist/runtime-v2/internalization/__tests__/philosopher-runner-trust-boundary.test.js.map +1 -0
  78. package/core/dist/runtime-v2/internalization/artificer-output.d.ts +3 -2
  79. package/core/dist/runtime-v2/internalization/artificer-output.d.ts.map +1 -1
  80. package/core/dist/runtime-v2/internalization/artificer-output.js +40 -31
  81. package/core/dist/runtime-v2/internalization/artificer-output.js.map +1 -1
  82. package/core/dist/runtime-v2/internalization/artificer-runner.d.ts +59 -38
  83. package/core/dist/runtime-v2/internalization/artificer-runner.d.ts.map +1 -1
  84. package/core/dist/runtime-v2/internalization/artificer-runner.js +122 -394
  85. package/core/dist/runtime-v2/internalization/artificer-runner.js.map +1 -1
  86. package/core/dist/runtime-v2/internalization/dreamer-output.d.ts +4 -3
  87. package/core/dist/runtime-v2/internalization/dreamer-output.d.ts.map +1 -1
  88. package/core/dist/runtime-v2/internalization/dreamer-output.js +11 -9
  89. package/core/dist/runtime-v2/internalization/dreamer-output.js.map +1 -1
  90. package/core/dist/runtime-v2/internalization/dreamer-runner.d.ts +31 -92
  91. package/core/dist/runtime-v2/internalization/dreamer-runner.d.ts.map +1 -1
  92. package/core/dist/runtime-v2/internalization/dreamer-runner.js +80 -492
  93. package/core/dist/runtime-v2/internalization/dreamer-runner.js.map +1 -1
  94. package/core/dist/runtime-v2/internalization/evaluator-output.d.ts +2 -2
  95. package/core/dist/runtime-v2/internalization/evaluator-output.d.ts.map +1 -1
  96. package/core/dist/runtime-v2/internalization/evaluator-output.js +29 -23
  97. package/core/dist/runtime-v2/internalization/evaluator-output.js.map +1 -1
  98. package/core/dist/runtime-v2/internalization/evaluator-runner.d.ts +74 -48
  99. package/core/dist/runtime-v2/internalization/evaluator-runner.d.ts.map +1 -1
  100. package/core/dist/runtime-v2/internalization/evaluator-runner.js +165 -443
  101. package/core/dist/runtime-v2/internalization/evaluator-runner.js.map +1 -1
  102. package/core/dist/runtime-v2/internalization/peer-runner-contracts.d.ts +14 -0
  103. package/core/dist/runtime-v2/internalization/peer-runner-contracts.d.ts.map +1 -1
  104. package/core/dist/runtime-v2/internalization/peer-runner-contracts.js +21 -0
  105. package/core/dist/runtime-v2/internalization/peer-runner-contracts.js.map +1 -1
  106. package/core/dist/runtime-v2/internalization/philosopher-output.d.ts +8 -2
  107. package/core/dist/runtime-v2/internalization/philosopher-output.d.ts.map +1 -1
  108. package/core/dist/runtime-v2/internalization/philosopher-output.js +16 -11
  109. package/core/dist/runtime-v2/internalization/philosopher-output.js.map +1 -1
  110. package/core/dist/runtime-v2/internalization/philosopher-runner.d.ts +36 -55
  111. package/core/dist/runtime-v2/internalization/philosopher-runner.d.ts.map +1 -1
  112. package/core/dist/runtime-v2/internalization/philosopher-runner.js +118 -400
  113. package/core/dist/runtime-v2/internalization/philosopher-runner.js.map +1 -1
  114. package/core/dist/runtime-v2/internalization/rollout-reviewer-runner.d.ts.map +1 -1
  115. package/core/dist/runtime-v2/internalization/rollout-reviewer-runner.js +3 -1
  116. package/core/dist/runtime-v2/internalization/rollout-reviewer-runner.js.map +1 -1
  117. package/core/dist/runtime-v2/internalization/scribe-output.d.ts +8 -2
  118. package/core/dist/runtime-v2/internalization/scribe-output.d.ts.map +1 -1
  119. package/core/dist/runtime-v2/internalization/scribe-output.js +33 -17
  120. package/core/dist/runtime-v2/internalization/scribe-output.js.map +1 -1
  121. package/core/dist/runtime-v2/internalization/scribe-runner.d.ts +56 -49
  122. package/core/dist/runtime-v2/internalization/scribe-runner.d.ts.map +1 -1
  123. package/core/dist/runtime-v2/internalization/scribe-runner.js +117 -397
  124. package/core/dist/runtime-v2/internalization/scribe-runner.js.map +1 -1
  125. package/core/dist/runtime-v2/internalization/trainer-runner.d.ts.map +1 -1
  126. package/core/dist/runtime-v2/internalization/trainer-runner.js +3 -1
  127. package/core/dist/runtime-v2/internalization/trainer-runner.js.map +1 -1
  128. package/core/dist/runtime-v2/runner/__tests__/base-peer-runner-trust-boundary.test.d.ts +2 -0
  129. package/core/dist/runtime-v2/runner/__tests__/base-peer-runner-trust-boundary.test.d.ts.map +1 -0
  130. package/core/dist/runtime-v2/runner/__tests__/base-peer-runner-trust-boundary.test.js +379 -0
  131. package/core/dist/runtime-v2/runner/__tests__/base-peer-runner-trust-boundary.test.js.map +1 -0
  132. package/core/dist/runtime-v2/runner/base-peer-runner.d.ts +122 -0
  133. package/core/dist/runtime-v2/runner/base-peer-runner.d.ts.map +1 -0
  134. package/core/dist/runtime-v2/runner/base-peer-runner.js +528 -0
  135. package/core/dist/runtime-v2/runner/base-peer-runner.js.map +1 -0
  136. package/core/dist/runtime-v2/runner/peer-runner-types.d.ts +107 -0
  137. package/core/dist/runtime-v2/runner/peer-runner-types.d.ts.map +1 -0
  138. package/core/dist/runtime-v2/runner/peer-runner-types.js +13 -0
  139. package/core/dist/runtime-v2/runner/peer-runner-types.js.map +1 -0
  140. package/core/dist/telemetry-event.d.ts +2 -2
  141. package/core/dist/telemetry-event.d.ts.map +1 -1
  142. package/core/dist/telemetry-event.js +89 -0
  143. package/core/dist/telemetry-event.js.map +1 -1
  144. package/dist/installer.d.ts +1 -1
  145. package/dist/installer.d.ts.map +1 -1
  146. package/dist/installer.js +39 -10
  147. package/dist/installer.js.map +1 -1
  148. package/dist/mvp-config.d.ts +33 -0
  149. package/dist/mvp-config.d.ts.map +1 -1
  150. package/dist/mvp-config.js +174 -0
  151. package/dist/mvp-config.js.map +1 -1
  152. package/package.json +3 -3
  153. package/pd-cli/dist/commands/config-doctor.d.ts +17 -0
  154. package/pd-cli/dist/commands/config-doctor.d.ts.map +1 -0
  155. package/pd-cli/dist/commands/config-doctor.js +143 -0
  156. package/pd-cli/dist/commands/config-doctor.js.map +1 -0
  157. package/pd-cli/dist/commands/console.d.ts +18 -0
  158. package/pd-cli/dist/commands/console.d.ts.map +1 -1
  159. package/pd-cli/dist/commands/console.js +439 -0
  160. package/pd-cli/dist/commands/console.js.map +1 -1
  161. package/pd-cli/dist/commands/runtime-features.d.ts +23 -8
  162. package/pd-cli/dist/commands/runtime-features.d.ts.map +1 -1
  163. package/pd-cli/dist/commands/runtime-features.js +72 -31
  164. package/pd-cli/dist/commands/runtime-features.js.map +1 -1
  165. package/pd-cli/dist/index.d.ts +1 -1
  166. package/pd-cli/dist/index.js +83 -31
  167. package/pd-cli/dist/index.js.map +1 -1
  168. package/pd-cli/dist/services/config-doctor.d.ts +102 -0
  169. package/pd-cli/dist/services/config-doctor.d.ts.map +1 -0
  170. package/pd-cli/dist/services/config-doctor.js +426 -0
  171. package/pd-cli/dist/services/config-doctor.js.map +1 -0
  172. package/pd-cli/dist/services/console-launcher.d.ts +110 -0
  173. package/pd-cli/dist/services/console-launcher.d.ts.map +1 -0
  174. package/pd-cli/dist/services/console-launcher.js +282 -0
  175. package/pd-cli/dist/services/console-launcher.js.map +1 -0
  176. package/pd-cli/dist/services/pd-config-loader.d.ts +64 -0
  177. package/pd-cli/dist/services/pd-config-loader.d.ts.map +1 -0
  178. package/pd-cli/dist/services/pd-config-loader.js +156 -0
  179. package/pd-cli/dist/services/pd-config-loader.js.map +1 -0
  180. package/pd-cli/package.json +3 -1
  181. package/plugin/dist/core/event-log.d.ts +10 -0
  182. package/plugin/dist/core/event-log.js +85 -1
  183. package/plugin/dist/core/pd-config-loader.d.ts +96 -0
  184. package/plugin/dist/core/pd-config-loader.js +307 -0
  185. package/plugin/dist/core/runtime-v2-prompt-activation-reader.d.ts +4 -0
  186. package/plugin/dist/core/runtime-v2-prompt-activation-reader.js +12 -56
  187. package/plugin/dist/core/surface-guard.d.ts +12 -8
  188. package/plugin/dist/core/surface-guard.js +51 -2
  189. package/plugin/dist/hooks/gate.js +3 -0
  190. package/plugin/dist/hooks/prompt.js +4 -5
  191. package/plugin/dist/index.d.ts +4 -0
  192. package/plugin/dist/index.js +70 -94
  193. package/plugin/dist/service/correction-observer-service.d.ts +8 -0
  194. package/plugin/dist/service/correction-observer-service.js +48 -29
  195. package/plugin/dist/utils/workspace-resolver.d.ts +33 -1
  196. package/plugin/dist/utils/workspace-resolver.js +182 -3
@@ -1,14 +1,15 @@
1
- import { PDRuntimeError } from '../error-categories.js';
1
+ import { PDRuntimeError, isPDErrorCategory } from '../error-categories.js';
2
2
  import { hydratePITaskRecord } from './pitask-metadata.js';
3
- import { RunnerPhase } from '../runner/runner-phase.js';
4
3
  import { PhilosopherPromptBuilder } from './philosopher-prompt-builder.js';
5
- const DEFAULT_PHILOSOPHER_RUNNER_OPTIONS = {
4
+ import { injectRunnerLineageIfAbsent } from './peer-runner-contracts.js';
5
+ import { BasePeerRunner } from '../runner/base-peer-runner.js';
6
+ export const DEFAULT_PHILOSOPHER_RUNNER_OPTIONS = {
6
7
  pollIntervalMs: 5_000,
7
8
  timeoutMs: 300_000,
8
9
  defaultMaxAttempts: 3,
9
10
  agentId: 'philosopher',
10
11
  };
11
- function resolvePhilosopherRunnerOptions(options) {
12
+ export function resolvePhilosopherRunnerOptions(options) {
12
13
  return {
13
14
  pollIntervalMs: options.pollIntervalMs ?? DEFAULT_PHILOSOPHER_RUNNER_OPTIONS.pollIntervalMs,
14
15
  timeoutMs: options.timeoutMs ?? DEFAULT_PHILOSOPHER_RUNNER_OPTIONS.timeoutMs,
@@ -18,119 +19,23 @@ function resolvePhilosopherRunnerOptions(options) {
18
19
  agentId: options.agentId ?? DEFAULT_PHILOSOPHER_RUNNER_OPTIONS.agentId,
19
20
  };
20
21
  }
21
- // ── PhilosopherRunner ──────────────────────────────────────────────────────────
22
- export class PhilosopherRunner {
23
- phase = RunnerPhase.Idle;
24
- resolvedOptions;
25
- stateManager;
26
- runtimeAdapter;
27
- eventEmitter;
22
+ // ── PhilosopherRunner ────────────────────────────────────────────────────────
23
+ export class PhilosopherRunner extends BasePeerRunner {
28
24
  validator;
29
- artifactStore;
30
25
  constructor(deps, options) {
31
- this.stateManager = deps.stateManager;
32
- this.runtimeAdapter = deps.runtimeAdapter;
33
- this.eventEmitter = deps.eventEmitter;
34
- this.validator = deps.validator;
35
- this.artifactStore = deps.artifactStore;
36
- this.resolvedOptions = resolvePhilosopherRunnerOptions(options);
37
- }
38
- get currentPhase() {
39
- return this.phase;
40
- }
41
- emitPhilosopherEvent(eventType, taskId, payload) {
42
- this.eventEmitter.emitTelemetry({
43
- eventType: eventType,
44
- traceId: taskId,
45
- timestamp: new Date().toISOString(),
46
- sessionId: this.resolvedOptions.owner,
47
- agentId: this.resolvedOptions.agentId,
48
- payload,
26
+ super(deps, options, {
27
+ runnerName: 'philosopher',
28
+ expectedTaskKind: 'philosopher',
29
+ defaultAgentId: 'philosopher',
30
+ resultRefPrefix: 'philosopher',
49
31
  });
32
+ this.validator = deps.validator;
50
33
  }
51
- async run(taskId) {
52
- this.phase = RunnerPhase.Idle;
53
- // eslint-disable-next-line @typescript-eslint/init-declarations
54
- let leasedTask;
55
- try {
56
- leasedTask = await this.stateManager.acquireLease({
57
- taskId,
58
- owner: this.resolvedOptions.owner,
59
- runtimeKind: this.resolvedOptions.runtimeKind,
60
- });
61
- }
62
- catch (error) {
63
- return await this.handleLeaseOrPhaseError(taskId, error);
64
- }
65
- if (leasedTask.taskKind !== 'philosopher') {
66
- this.emitPhilosopherEvent('philosopher_wrong_task_kind', taskId, {
67
- expectedKind: 'philosopher',
68
- actualKind: leasedTask.taskKind,
69
- });
70
- await this.stateManager.markTaskFailed(taskId, 'input_invalid');
71
- return {
72
- status: 'failed',
73
- taskId,
74
- errorCategory: 'input_invalid',
75
- failureReason: `Task kind must be 'philosopher', got '${leasedTask.taskKind}'`,
76
- attemptCount: leasedTask.attemptCount,
77
- };
78
- }
79
- this.emitPhilosopherEvent('philosopher_task_leased', taskId, {
80
- taskKind: 'philosopher',
81
- attemptCount: leasedTask.attemptCount,
82
- });
83
- try {
84
- const storeRunId = await this.resolveStoreRunId(taskId);
85
- this.phase = RunnerPhase.BuildingContext;
86
- const { contextHash, dreamerArtifact, sourceDreamerArtifactId } = await this.buildContext(taskId);
87
- if (!dreamerArtifact) {
88
- return this.retryOrFail({
89
- taskId,
90
- task: leasedTask,
91
- errorCategory: 'input_invalid',
92
- failureReason: 'Dreamer dependency artifact not found',
93
- });
94
- }
95
- this.emitPhilosopherEvent('philosopher_context_built', taskId, { contextHash });
96
- this.phase = RunnerPhase.Invoking;
97
- const runHandle = await this.invokeRuntime({ taskId, contextHash, dreamerArtifact, sourceDreamerArtifactId });
98
- this.emitPhilosopherEvent('philosopher_run_started', taskId, {
99
- runtimeKind: this.resolvedOptions.runtimeKind,
100
- });
101
- this.phase = RunnerPhase.Polling;
102
- const finalStatus = await this.pollUntilTerminal(runHandle);
103
- if (finalStatus.status !== 'succeeded') {
104
- return await this.handleRuntimeFailure(taskId, leasedTask, finalStatus);
105
- }
106
- this.phase = RunnerPhase.FetchingOutput;
107
- const output = await this.fetchAndParseOutput(runHandle.runId);
108
- this.phase = RunnerPhase.Validating;
109
- const validationResult = await this.validator.validate(output, taskId);
110
- if (!validationResult.valid) {
111
- return await this.handleValidationError({
112
- taskId,
113
- task: leasedTask,
114
- errors: validationResult.errors,
115
- errorCategory: validationResult.errorCategory,
116
- });
117
- }
118
- this.emitPhilosopherEvent('philosopher_output_validated', taskId, {
119
- principleTitle: output.principleCandidate.title,
120
- });
121
- return await this.succeedTask({
122
- taskId,
123
- runId: storeRunId,
124
- output,
125
- task: leasedTask,
126
- contextHash,
127
- });
128
- }
129
- catch (error) {
130
- return await this.handlePostLeaseError(taskId, leasedTask, error);
131
- }
34
+ // ── Abstract implementations ───────────────────────────────────────────────
35
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
36
+ get permanentErrorCategories() {
37
+ return new Set(['storage_unavailable', 'workspace_invalid', 'capability_missing', 'cancelled', 'input_invalid']);
132
38
  }
133
- // ── Phase methods ─────────────────────────────────────────────────────────
134
39
  async buildContext(taskId) {
135
40
  const task = await this.stateManager.getTask(taskId);
136
41
  if (!task) {
@@ -139,15 +44,14 @@ export class PhilosopherRunner {
139
44
  const piTask = hydratePITaskRecord(task);
140
45
  const deps = piTask?.dependencyTaskIds ?? [];
141
46
  if (deps.length === 0) {
142
- this.emitPhilosopherEvent('philosopher_no_dependencies', taskId, {});
143
- return { contextHash: 'empty', dreamerArtifact: null, sourceDreamerArtifactId: null };
47
+ throw new PDRuntimeError('input_invalid', 'Dreamer dependency artifact not found');
144
48
  }
145
49
  for (const depId of deps) {
146
50
  const depTask = await this.stateManager.getTask(depId);
147
51
  if (!depTask)
148
52
  continue;
149
53
  if (depTask.status !== 'succeeded') {
150
- this.emitPhilosopherEvent('philosopher_dependency_not_succeeded', taskId, {
54
+ this.emitEvent('dependency_not_succeeded', taskId, {
151
55
  depTaskId: depId,
152
56
  depStatus: depTask.status,
153
57
  });
@@ -161,359 +65,173 @@ export class PhilosopherRunner {
161
65
  continue;
162
66
  const artifactRef = depPiTask?.outputArtifactRefs?.[0]?.ref ?? `pi-artifact://${depId}`;
163
67
  return {
164
- contextHash: PhilosopherRunner.hashContextRefs([artifactRef]),
68
+ contextHash: BasePeerRunner.hashContextRefs([artifactRef]),
165
69
  dreamerArtifact: firstArtifact.contentJson,
166
70
  sourceDreamerArtifactId: firstArtifact.artifactId,
167
71
  };
168
72
  }
169
73
  }
170
- this.emitPhilosopherEvent('philosopher_no_dreamer_artifact', taskId, {});
171
- return { contextHash: 'empty', dreamerArtifact: null, sourceDreamerArtifactId: null };
74
+ throw new PDRuntimeError('input_invalid', 'Dreamer dependency artifact not found');
172
75
  }
173
- static hashContextRefs(refs) {
174
- if (refs.length === 0)
175
- return 'empty';
176
- const str = refs.join('|');
177
- let hash = 0;
178
- for (let i = 0; i < str.length; i++) {
179
- hash = (Math.imul(31, hash) + str.charCodeAt(i)) | 0;
180
- }
181
- return `ctx-${Math.abs(hash).toString(16)}`;
182
- }
183
- async resolveStoreRunId(taskId) {
184
- const runs = await this.stateManager.getRunsByTask(taskId);
185
- const latestRun = runs[runs.length - 1];
186
- if (!latestRun) {
187
- throw new PDRuntimeError('execution_failed', `No run records found for task ${taskId} after lease acquisition`);
76
+ async invokeRuntime(taskId, context) {
77
+ let parsedDreamerArtifact;
78
+ try {
79
+ parsedDreamerArtifact = JSON.parse(context.dreamerArtifact);
188
80
  }
189
- return latestRun.runId;
190
- }
191
- async invokeRuntime(params) {
192
- let parsedDreamerArtifact = null;
193
- if (params.dreamerArtifact) {
194
- try {
195
- parsedDreamerArtifact = JSON.parse(params.dreamerArtifact);
196
- }
197
- catch {
198
- parsedDreamerArtifact = params.dreamerArtifact;
199
- }
81
+ catch {
82
+ parsedDreamerArtifact = context.dreamerArtifact;
200
83
  }
201
84
  const builder = new PhilosopherPromptBuilder();
202
85
  const { message } = builder.buildPrompt({
203
- taskId: params.taskId,
204
- contextHash: params.contextHash,
86
+ taskId,
87
+ contextHash: context.contextHash,
205
88
  dreamerArtifact: parsedDreamerArtifact,
206
- sourceDreamerArtifactId: params.sourceDreamerArtifactId ?? '',
89
+ sourceDreamerArtifactId: context.sourceDreamerArtifactId,
207
90
  });
208
- const startInput = {
91
+ return this.runtimeAdapter.startRun({
209
92
  agentSpec: { agentId: this.resolvedOptions.agentId, schemaVersion: 'v1' },
210
- taskRef: { taskId: params.taskId },
93
+ taskRef: { taskId },
211
94
  inputPayload: message,
212
95
  contextItems: [],
213
96
  outputSchemaRef: 'philosopher-output-v1',
214
97
  timeoutMs: this.resolvedOptions.timeoutMs,
215
- };
216
- return this.runtimeAdapter.startRun(startInput);
98
+ });
217
99
  }
218
- async pollUntilTerminal(runHandle) {
219
- const deadline = Date.now() + this.resolvedOptions.timeoutMs;
220
- const terminalStatuses = ['succeeded', 'failed', 'timed_out', 'cancelled'];
221
- while (Date.now() < deadline) {
222
- const status = await this.runtimeAdapter.pollRun(runHandle.runId);
223
- if (terminalStatuses.includes(status.status)) {
224
- return status;
225
- }
226
- await this.sleep(this.resolvedOptions.pollIntervalMs);
100
+ async validateOutput(output, taskId) {
101
+ const result = await this.validator.validate(output, taskId);
102
+ // Trust-boundary: validator is an injected dependency returning `string | undefined`
103
+ // for errorCategory. We must not `as`-cast; validate at runtime (ERR-001, ERR-005).
104
+ const rawCategory = result.errorCategory;
105
+ let errorCategory;
106
+ if (rawCategory == null) {
107
+ errorCategory = undefined;
227
108
  }
228
- let cancelFailed = false;
229
- try {
230
- await this.runtimeAdapter.cancelRun(runHandle.runId);
109
+ else if (isPDErrorCategory(rawCategory)) {
110
+ errorCategory = rawCategory;
231
111
  }
232
- catch (cancelErr) {
233
- cancelFailed = true;
234
- this.emitPhilosopherEvent('philosopher_cancel_run_failed', runHandle.runId, {
235
- runId: runHandle.runId,
236
- errorMessage: cancelErr instanceof Error ? cancelErr.message : String(cancelErr),
237
- });
112
+ else {
113
+ // Invalid errorCategory from validator — fail loud, do not pass through
114
+ return {
115
+ valid: false,
116
+ errors: [...result.errors, `invalid errorCategory: ${rawCategory}`],
117
+ errorCategory: 'output_invalid',
118
+ };
238
119
  }
239
- const cancelNote = cancelFailed ? ' (cancelRun also failed)' : '';
240
- throw new PDRuntimeError('timeout', `Run ${runHandle.runId} timed out after ${this.resolvedOptions.timeoutMs}ms${cancelNote}`);
120
+ return {
121
+ valid: result.valid,
122
+ errors: result.errors,
123
+ errorCategory,
124
+ };
241
125
  }
242
- async fetchAndParseOutput(runId) {
243
- const result = await this.runtimeAdapter.fetchOutput(runId);
244
- if (!result || !result.payload) {
245
- throw new PDRuntimeError('output_invalid', `No output available for run ${runId}`);
126
+ // eslint-disable-next-line @typescript-eslint/max-params
127
+ async succeedTask(taskId, runId, output, task, contextHash, context) {
128
+ // Lineage consistency: sourceDreamerArtifactId must match buildContext result (ERR-004).
129
+ if (output.sourceDreamerArtifactId !== context.sourceDreamerArtifactId) {
130
+ throw new PDRuntimeError('output_invalid', `sourceDreamerArtifactId mismatch: expected ${context.sourceDreamerArtifactId}, got ${output.sourceDreamerArtifactId}`);
246
131
  }
247
- return result.payload;
248
- }
249
- async succeedTask(ctx) {
132
+ // Store output before marking succeeded
250
133
  try {
251
- await this.stateManager.updateRunOutput(ctx.runId, JSON.stringify(ctx.output));
134
+ await this.stateManager.updateRunOutput(runId, JSON.stringify(output));
252
135
  }
253
136
  catch (updateErr) {
254
- this.emitPhilosopherEvent('philosopher_update_output_failed', ctx.taskId, {
255
- runId: ctx.runId,
137
+ this.emitEvent('update_output_failed', taskId, {
138
+ runId,
256
139
  errorMessage: updateErr instanceof Error ? updateErr.message : String(updateErr),
257
140
  });
258
141
  throw updateErr;
259
142
  }
260
- const artifactId = `pi-art-${ctx.taskId}-${ctx.runId}`;
261
- const now = new Date().toISOString();
143
+ // Resolve lineage artifact IDs
262
144
  let lineageArtifactIds = [];
145
+ let lineageHasRejected = false;
263
146
  try {
264
- const piTask = hydratePITaskRecord(ctx.task);
265
- const deps = piTask?.dependencyTaskIds ?? [];
266
- const results = await Promise.allSettled(deps.map((depId) => this.artifactStore.listBySourceTaskId(depId)));
267
- for (const result of results) {
268
- if (result.status === 'fulfilled') {
269
- for (const artifact of result.value) {
270
- lineageArtifactIds.push(artifact.artifactId);
271
- }
272
- }
273
- }
147
+ const lineageResult = await this.resolveLineageArtifactIds(taskId);
148
+ lineageArtifactIds = lineageResult.ids;
149
+ lineageHasRejected = lineageResult.hasRejected;
150
+ }
151
+ catch (lineageErr) {
152
+ this.emitEvent('lineage_resolve_failed', taskId, {
153
+ runId,
154
+ errorMessage: lineageErr instanceof Error ? lineageErr.message : String(lineageErr),
155
+ });
156
+ }
157
+ if (lineageHasRejected) {
158
+ this.emitEvent('lineage_partial', taskId, {
159
+ runId,
160
+ resolvedCount: lineageArtifactIds.length,
161
+ warning: 'Some dependency artifact queries were rejected; lineage may be incomplete',
162
+ });
274
163
  }
275
- catch { /* lineage resolution failure is non-fatal */ }
164
+ // Write PIArtifact via artifactStore (idempotent upsert)
165
+ const artifactId = `pi-art-${taskId}-${runId}`;
166
+ const now = new Date().toISOString();
276
167
  try {
277
168
  await this.artifactStore.upsertArtifact({
278
169
  artifactId,
279
170
  artifactKind: 'principle',
280
- sourceTaskId: ctx.taskId,
171
+ sourceTaskId: taskId,
281
172
  lineageArtifactIds,
282
173
  validationStatus: 'pending',
283
- contentJson: JSON.stringify(ctx.output),
174
+ contentJson: JSON.stringify(output),
284
175
  createdAt: now,
285
176
  updatedAt: now,
286
177
  });
287
178
  }
288
179
  catch (artifactErr) {
289
- this.emitPhilosopherEvent('philosopher_artifact_write_failed', ctx.taskId, {
290
- runId: ctx.runId,
180
+ this.emitEvent('artifact_write_failed', taskId, {
181
+ runId,
291
182
  errorMessage: artifactErr instanceof Error ? artifactErr.message : String(artifactErr),
292
183
  });
293
184
  return this.retryOrFail({
294
- taskId: ctx.taskId,
295
- task: ctx.task,
185
+ taskId,
186
+ task,
296
187
  errorCategory: 'artifact_commit_failed',
297
188
  failureReason: `PIArtifact write failed: ${artifactErr instanceof Error ? artifactErr.message : String(artifactErr)}`,
298
189
  });
299
190
  }
300
- const resultRef = `philosopher://${ctx.runId}`;
191
+ // Mark task succeeded
192
+ const resultRef = `${this.config.resultRefPrefix}://${runId}`;
301
193
  try {
302
- await this.stateManager.markTaskSucceeded(ctx.taskId, resultRef);
194
+ await this.stateManager.markTaskSucceeded(taskId, resultRef);
303
195
  }
304
196
  catch (stateErr) {
305
- this.emitPhilosopherEvent('philosopher_mark_succeeded_failed', ctx.taskId, {
306
- taskId: ctx.taskId,
307
- runId: ctx.runId,
197
+ this.emitEvent('mark_succeeded_failed', taskId, {
198
+ taskId,
199
+ runId,
308
200
  errorMessage: stateErr instanceof Error ? stateErr.message : String(stateErr),
309
201
  });
310
202
  throw stateErr;
311
203
  }
312
- this.emitPhilosopherEvent('philosopher_task_succeeded', ctx.taskId, {
313
- attemptCount: ctx.task.attemptCount,
204
+ this.emitEvent('task_succeeded', taskId, {
205
+ attemptCount: task.attemptCount,
314
206
  resultRef,
315
- principleTitle: ctx.output.principleCandidate.title,
207
+ principleTitle: output.principleCandidate.title,
316
208
  });
317
- this.phase = RunnerPhase.Completed;
318
209
  return {
319
210
  status: 'succeeded',
320
- taskId: ctx.taskId,
321
- runId: ctx.runId,
211
+ taskId,
212
+ runId,
322
213
  artifactId,
323
214
  resultRef,
324
- contextHash: ctx.contextHash,
325
- output: ctx.output,
326
- attemptCount: ctx.task.attemptCount,
215
+ contextHash,
216
+ output,
217
+ attemptCount: task.attemptCount,
327
218
  };
328
219
  }
329
- async handleRuntimeFailure(taskId, task, runStatus) {
330
- const errorCategory = this.mapRunStatusToErrorCategory(runStatus.status);
331
- this.emitPhilosopherEvent('philosopher_run_failed', taskId, {
332
- runStatus: runStatus.status,
333
- errorCategory,
334
- });
335
- return this.retryOrFail({
336
- taskId,
337
- task,
338
- errorCategory,
339
- failureReason: `Runtime execution ended with status: ${runStatus.status}`,
340
- });
341
- }
342
- async handleValidationError(ctx) {
343
- const category = (ctx.errorCategory ?? 'output_invalid');
344
- this.emitPhilosopherEvent('philosopher_output_invalid', ctx.taskId, {
345
- errorCount: ctx.errors.length,
346
- errorCategory: category,
347
- });
348
- return this.retryOrFail({
349
- taskId: ctx.taskId,
350
- task: ctx.task,
351
- errorCategory: category,
352
- failureReason: `Validation failed: ${ctx.errors.join('; ')}`,
353
- });
354
- }
355
- async handleLeaseOrPhaseError(taskId, error) {
356
- const classified = this.classifyError(error);
357
- if (classified.category === 'lease_conflict') {
358
- this.emitPhilosopherEvent('philosopher_run_failed', taskId, {
359
- errorCategory: 'lease_conflict',
360
- errorMessage: classified.message,
361
- });
362
- return {
363
- status: 'failed',
364
- taskId,
365
- errorCategory: 'lease_conflict',
366
- failureReason: classified.message,
367
- attemptCount: 1,
368
- };
369
- }
370
- this.emitPhilosopherEvent('philosopher_run_failed', taskId, {
371
- errorCategory: classified.category,
372
- errorMessage: classified.message,
373
- });
374
- const task = {
375
- taskId,
376
- taskKind: 'philosopher',
377
- status: 'leased',
378
- createdAt: new Date().toISOString(),
379
- updatedAt: new Date().toISOString(),
380
- attemptCount: 1,
381
- maxAttempts: this.resolvedOptions.defaultMaxAttempts,
382
- };
383
- return this.retryOrFail({ taskId, task, errorCategory: classified.category, failureReason: classified.message });
384
- }
385
- async handlePostLeaseError(taskId, task, error) {
386
- const classified = this.classifyError(error);
387
- this.emitPhilosopherEvent('philosopher_run_failed', taskId, {
388
- errorCategory: classified.category,
389
- errorMessage: classified.message,
390
- });
391
- return this.retryOrFail({ taskId, task, errorCategory: classified.category, failureReason: classified.message });
392
- }
393
- async retryOrFail(ctx) {
394
- if (this.isPermanentError(ctx.errorCategory)) {
395
- try {
396
- await this.stateManager.markTaskFailed(ctx.taskId, ctx.errorCategory);
397
- }
398
- catch (stateErr) {
399
- this.emitPhilosopherEvent('philosopher_mark_failed_error', ctx.taskId, {
400
- errorCategory: 'storage_unavailable',
401
- attemptCount: ctx.task.attemptCount,
402
- errorMessage: stateErr instanceof Error ? stateErr.message : String(stateErr),
403
- });
404
- return {
405
- status: 'failed',
406
- taskId: ctx.taskId,
407
- errorCategory: 'storage_unavailable',
408
- failureReason: `State manager error: ${ctx.failureReason}`,
409
- attemptCount: ctx.task.attemptCount,
410
- };
411
- }
412
- this.emitPhilosopherEvent('philosopher_task_failed', ctx.taskId, {
413
- errorCategory: ctx.errorCategory,
414
- attemptCount: ctx.task.attemptCount,
415
- failureReason: ctx.failureReason,
416
- });
417
- this.phase = RunnerPhase.Failed;
418
- return {
419
- status: 'failed',
420
- taskId: ctx.taskId,
421
- errorCategory: ctx.errorCategory,
422
- failureReason: ctx.failureReason,
423
- attemptCount: ctx.task.attemptCount,
424
- };
425
- }
426
- const shouldRetry = this.stateManager.getRetryPolicy().shouldRetry(ctx.task);
427
- if (shouldRetry) {
428
- try {
429
- await this.stateManager.markTaskRetryWait(ctx.taskId, ctx.errorCategory);
430
- }
431
- catch (stateErr) {
432
- this.emitPhilosopherEvent('philosopher_mark_retry_error', ctx.taskId, {
433
- errorCategory: 'storage_unavailable',
434
- attemptCount: ctx.task.attemptCount,
435
- errorMessage: stateErr instanceof Error ? stateErr.message : String(stateErr),
436
- });
437
- return {
438
- status: 'failed',
439
- taskId: ctx.taskId,
440
- errorCategory: 'storage_unavailable',
441
- failureReason: `State manager error: ${ctx.failureReason}`,
442
- attemptCount: ctx.task.attemptCount,
443
- };
444
- }
445
- this.emitPhilosopherEvent('philosopher_task_retried', ctx.taskId, {
446
- errorCategory: ctx.errorCategory,
447
- attemptCount: ctx.task.attemptCount,
448
- });
449
- this.phase = RunnerPhase.RetryWaiting;
450
- return {
451
- status: 'retried',
452
- taskId: ctx.taskId,
453
- errorCategory: ctx.errorCategory,
454
- failureReason: ctx.failureReason,
455
- attemptCount: ctx.task.attemptCount,
456
- };
457
- }
458
- try {
459
- await this.stateManager.markTaskFailed(ctx.taskId, 'max_attempts_exceeded');
460
- }
461
- catch (stateErr) {
462
- this.emitPhilosopherEvent('philosopher_mark_failed_error', ctx.taskId, {
463
- errorCategory: 'storage_unavailable',
464
- attemptCount: ctx.task.attemptCount,
465
- errorMessage: stateErr instanceof Error ? stateErr.message : String(stateErr),
466
- });
467
- return {
468
- status: 'failed',
469
- taskId: ctx.taskId,
470
- errorCategory: 'storage_unavailable',
471
- failureReason: `State manager error: ${ctx.failureReason}`,
472
- attemptCount: ctx.task.attemptCount,
473
- };
474
- }
475
- this.emitPhilosopherEvent('philosopher_task_failed', ctx.taskId, {
476
- errorCategory: 'max_attempts_exceeded',
477
- attemptCount: ctx.task.attemptCount,
478
- failureReason: `Max attempts exceeded: ${ctx.failureReason}`,
479
- });
480
- this.phase = RunnerPhase.Failed;
481
- return {
482
- status: 'failed',
483
- taskId: ctx.taskId,
484
- errorCategory: 'max_attempts_exceeded',
485
- failureReason: `Max attempts exceeded: ${ctx.failureReason}`,
486
- attemptCount: ctx.task.attemptCount,
487
- };
488
- }
489
- // ── Error classification ──────────────────────────────────────────────────
490
- PERMANENT_ERROR_CATEGORIES = new Set(Object.freeze(['storage_unavailable', 'workspace_invalid', 'capability_missing', 'cancelled', 'input_invalid']));
491
- isPermanentError(category) {
492
- return this.PERMANENT_ERROR_CATEGORIES.has(category);
493
- }
220
+ // ── Optional hooks ─────────────────────────────────────────────────────────
221
+ /**
222
+ * Re-inject taskId if stripped by stripLineageFields (PRI-272 / ERR-008).
223
+ * Only fill when absent via Object.hasOwn — present-but-falsy values
224
+ * must reach validation and fail loud (Runtime Contract Rule 3).
225
+ */
494
226
  // eslint-disable-next-line @typescript-eslint/class-methods-use-this
495
- classifyError(error) {
496
- if (error instanceof PDRuntimeError) {
497
- return { category: error.category, message: error.message };
498
- }
499
- if (error instanceof Error) {
500
- return { category: 'execution_failed', message: error.message };
501
- }
502
- return { category: 'execution_failed', message: String(error) };
227
+ postFetchTransform(taskId, untrustedOutput) {
228
+ injectRunnerLineageIfAbsent(untrustedOutput, 'taskId', taskId);
503
229
  }
504
- // eslint-disable-next-line @typescript-eslint/class-methods-use-this
505
- mapRunStatusToErrorCategory(status) {
506
- switch (status) {
507
- case 'failed': return 'execution_failed';
508
- case 'timed_out': return 'timeout';
509
- case 'cancelled': return 'cancelled';
510
- default: return 'execution_failed';
511
- }
512
- }
513
- // eslint-disable-next-line @typescript-eslint/class-methods-use-this
514
- sleep(ms) {
515
- return new Promise((resolve) => setTimeout(resolve, ms));
230
+ emitSuccessTelemetry(taskId, output) {
231
+ this.emitEvent('principle_candidate_generated', taskId, {
232
+ principleTitle: output.principleCandidate.title,
233
+ confidence: output.principleCandidate.confidence,
234
+ });
516
235
  }
517
236
  }
518
- export { resolvePhilosopherRunnerOptions, DEFAULT_PHILOSOPHER_RUNNER_OPTIONS };
519
237
  //# sourceMappingURL=philosopher-runner.js.map