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 { ScribePromptBuilder } from './scribe-prompt-builder.js';
5
- const DEFAULT_SCRIBE_RUNNER_OPTIONS = {
4
+ import { injectRunnerLineageIfAbsent } from './peer-runner-contracts.js';
5
+ import { BasePeerRunner } from '../runner/base-peer-runner.js';
6
+ export const DEFAULT_SCRIBE_RUNNER_OPTIONS = {
6
7
  pollIntervalMs: 5_000,
7
8
  timeoutMs: 300_000,
8
9
  defaultMaxAttempts: 3,
9
10
  agentId: 'scribe',
10
11
  };
11
- function resolveScribeRunnerOptions(options) {
12
+ export function resolveScribeRunnerOptions(options) {
12
13
  return {
13
14
  pollIntervalMs: options.pollIntervalMs ?? DEFAULT_SCRIBE_RUNNER_OPTIONS.pollIntervalMs,
14
15
  timeoutMs: options.timeoutMs ?? DEFAULT_SCRIBE_RUNNER_OPTIONS.timeoutMs,
@@ -18,116 +19,22 @@ function resolveScribeRunnerOptions(options) {
18
19
  agentId: options.agentId ?? DEFAULT_SCRIBE_RUNNER_OPTIONS.agentId,
19
20
  };
20
21
  }
21
- export class ScribeRunner {
22
- phase = RunnerPhase.Idle;
23
- resolvedOptions;
24
- stateManager;
25
- runtimeAdapter;
26
- eventEmitter;
22
+ // ── ScribeRunner ─────────────────────────────────────────────────────────────
23
+ export class ScribeRunner extends BasePeerRunner {
27
24
  validator;
28
- artifactStore;
29
25
  constructor(deps, options) {
30
- this.stateManager = deps.stateManager;
31
- this.runtimeAdapter = deps.runtimeAdapter;
32
- this.eventEmitter = deps.eventEmitter;
33
- this.validator = deps.validator;
34
- this.artifactStore = deps.artifactStore;
35
- this.resolvedOptions = resolveScribeRunnerOptions(options);
36
- }
37
- get currentPhase() {
38
- return this.phase;
39
- }
40
- emitScribeEvent(eventType, taskId, payload) {
41
- this.eventEmitter.emitTelemetry({
42
- eventType: eventType,
43
- traceId: taskId,
44
- timestamp: new Date().toISOString(),
45
- sessionId: this.resolvedOptions.owner,
46
- agentId: this.resolvedOptions.agentId,
47
- payload,
26
+ super(deps, options, {
27
+ runnerName: 'scribe',
28
+ expectedTaskKind: 'scribe',
29
+ defaultAgentId: 'scribe',
30
+ resultRefPrefix: 'scribe',
48
31
  });
32
+ this.validator = deps.validator;
49
33
  }
50
- async run(taskId) {
51
- this.phase = RunnerPhase.Idle;
52
- // eslint-disable-next-line @typescript-eslint/init-declarations
53
- let leasedTask;
54
- try {
55
- leasedTask = await this.stateManager.acquireLease({
56
- taskId,
57
- owner: this.resolvedOptions.owner,
58
- runtimeKind: this.resolvedOptions.runtimeKind,
59
- });
60
- }
61
- catch (error) {
62
- return await this.handleLeaseOrPhaseError(taskId, error);
63
- }
64
- if (leasedTask.taskKind !== 'scribe') {
65
- this.emitScribeEvent('scribe_wrong_task_kind', taskId, {
66
- expectedKind: 'scribe',
67
- actualKind: leasedTask.taskKind,
68
- });
69
- await this.stateManager.markTaskFailed(taskId, 'input_invalid');
70
- return {
71
- status: 'failed',
72
- taskId,
73
- errorCategory: 'input_invalid',
74
- failureReason: `Task kind must be 'scribe', got '${leasedTask.taskKind}'`,
75
- attemptCount: leasedTask.attemptCount,
76
- };
77
- }
78
- this.emitScribeEvent('scribe_task_leased', taskId, {
79
- taskKind: 'scribe',
80
- attemptCount: leasedTask.attemptCount,
81
- });
82
- try {
83
- const storeRunId = await this.resolveStoreRunId(taskId);
84
- this.phase = RunnerPhase.BuildingContext;
85
- const { contextHash, philosopherArtifact, sourcePhilosopherArtifactId } = await this.buildContext(taskId);
86
- if (!philosopherArtifact) {
87
- return this.retryOrFail({
88
- taskId,
89
- task: leasedTask,
90
- errorCategory: 'input_invalid',
91
- failureReason: 'Philosopher dependency artifact not found',
92
- });
93
- }
94
- this.emitScribeEvent('scribe_context_built', taskId, { contextHash });
95
- this.phase = RunnerPhase.Invoking;
96
- const runHandle = await this.invokeRuntime({ taskId, contextHash, philosopherArtifact, sourcePhilosopherArtifactId });
97
- this.emitScribeEvent('scribe_run_started', taskId, {
98
- runtimeKind: this.resolvedOptions.runtimeKind,
99
- });
100
- this.phase = RunnerPhase.Polling;
101
- const finalStatus = await this.pollUntilTerminal(runHandle);
102
- if (finalStatus.status !== 'succeeded') {
103
- return await this.handleRuntimeFailure(taskId, leasedTask, finalStatus);
104
- }
105
- this.phase = RunnerPhase.FetchingOutput;
106
- const output = await this.fetchAndParseOutput(runHandle.runId);
107
- this.phase = RunnerPhase.Validating;
108
- const validationResult = await this.validator.validate(output, taskId, sourcePhilosopherArtifactId ?? undefined);
109
- if (!validationResult.valid) {
110
- return await this.handleValidationError({
111
- taskId,
112
- task: leasedTask,
113
- errors: validationResult.errors,
114
- errorCategory: validationResult.errorCategory,
115
- });
116
- }
117
- this.emitScribeEvent('scribe_output_validated', taskId, {
118
- principleTitle: output.principleDraft.title,
119
- });
120
- return await this.succeedTask({
121
- taskId,
122
- runId: storeRunId,
123
- output,
124
- task: leasedTask,
125
- contextHash,
126
- });
127
- }
128
- catch (error) {
129
- return await this.handlePostLeaseError(taskId, leasedTask, error);
130
- }
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']);
131
38
  }
132
39
  async buildContext(taskId) {
133
40
  const task = await this.stateManager.getTask(taskId);
@@ -137,8 +44,7 @@ export class ScribeRunner {
137
44
  const piTask = hydratePITaskRecord(task);
138
45
  const deps = piTask?.dependencyTaskIds ?? [];
139
46
  if (deps.length === 0) {
140
- this.emitScribeEvent('scribe_no_dependencies', taskId, {});
141
- return { contextHash: 'empty', philosopherArtifact: null, sourcePhilosopherArtifactId: null };
47
+ throw new PDRuntimeError('input_invalid', 'Philosopher dependency artifact not found');
142
48
  }
143
49
  for (const depId of deps) {
144
50
  const depTask = await this.stateManager.getTask(depId);
@@ -147,7 +53,7 @@ export class ScribeRunner {
147
53
  if (depTask.taskKind !== 'philosopher')
148
54
  continue;
149
55
  if (depTask.status !== 'succeeded') {
150
- this.emitScribeEvent('scribe_dependency_not_succeeded', taskId, {
56
+ this.emitEvent('dependency_not_succeeded', taskId, {
151
57
  depTaskId: depId,
152
58
  depStatus: depTask.status,
153
59
  });
@@ -161,358 +67,172 @@ export class ScribeRunner {
161
67
  continue;
162
68
  const artifactRef = depPiTask?.outputArtifactRefs?.[0]?.ref ?? `pi-artifact://${depId}`;
163
69
  return {
164
- contextHash: ScribeRunner.hashContextRefs([artifactRef]),
70
+ contextHash: BasePeerRunner.hashContextRefs([artifactRef]),
165
71
  philosopherArtifact: firstArtifact.contentJson,
166
72
  sourcePhilosopherArtifactId: firstArtifact.artifactId,
167
73
  };
168
74
  }
169
75
  }
170
- this.emitScribeEvent('scribe_no_philosopher_artifact', taskId, {});
171
- return { contextHash: 'empty', philosopherArtifact: null, sourcePhilosopherArtifactId: null };
76
+ throw new PDRuntimeError('input_invalid', 'Philosopher dependency artifact not found');
172
77
  }
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`);
78
+ async invokeRuntime(taskId, context) {
79
+ let parsedPhilosopherArtifact;
80
+ try {
81
+ parsedPhilosopherArtifact = JSON.parse(context.philosopherArtifact);
188
82
  }
189
- return latestRun.runId;
190
- }
191
- async invokeRuntime(params) {
192
- let parsedPhilosopherArtifact = null;
193
- if (params.philosopherArtifact) {
194
- try {
195
- parsedPhilosopherArtifact = JSON.parse(params.philosopherArtifact);
196
- }
197
- catch {
198
- parsedPhilosopherArtifact = params.philosopherArtifact;
199
- }
83
+ catch {
84
+ parsedPhilosopherArtifact = context.philosopherArtifact;
200
85
  }
201
86
  const builder = new ScribePromptBuilder();
202
87
  const { message } = builder.buildPrompt({
203
- taskId: params.taskId,
204
- contextHash: params.contextHash,
88
+ taskId,
89
+ contextHash: context.contextHash,
205
90
  philosopherArtifact: parsedPhilosopherArtifact,
206
- sourcePhilosopherArtifactId: params.sourcePhilosopherArtifactId ?? '',
91
+ sourcePhilosopherArtifactId: context.sourcePhilosopherArtifactId,
207
92
  });
208
- const startInput = {
93
+ return this.runtimeAdapter.startRun({
209
94
  agentSpec: { agentId: this.resolvedOptions.agentId, schemaVersion: 'v1' },
210
- taskRef: { taskId: params.taskId },
95
+ taskRef: { taskId },
211
96
  inputPayload: message,
212
97
  contextItems: [],
213
98
  outputSchemaRef: 'scribe-output-v1',
214
99
  timeoutMs: this.resolvedOptions.timeoutMs,
215
- };
216
- return this.runtimeAdapter.startRun(startInput);
100
+ });
217
101
  }
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);
102
+ async validateOutput(output, taskId, context) {
103
+ const result = await this.validator.validate(output, taskId, context.sourcePhilosopherArtifactId);
104
+ // Trust-boundary: validator is an injected dependency returning `string | undefined`
105
+ // for errorCategory. We must not `as`-cast; validate at runtime (ERR-001, ERR-005).
106
+ const rawCategory = result.errorCategory;
107
+ let errorCategory;
108
+ if (rawCategory == null) {
109
+ errorCategory = undefined;
227
110
  }
228
- let cancelFailed = false;
229
- try {
230
- await this.runtimeAdapter.cancelRun(runHandle.runId);
111
+ else if (isPDErrorCategory(rawCategory)) {
112
+ errorCategory = rawCategory;
231
113
  }
232
- catch (cancelErr) {
233
- cancelFailed = true;
234
- this.emitScribeEvent('scribe_cancel_run_failed', runHandle.runId, {
235
- runId: runHandle.runId,
236
- errorMessage: cancelErr instanceof Error ? cancelErr.message : String(cancelErr),
237
- });
114
+ else {
115
+ // Invalid errorCategory from validator — fail loud, do not pass through
116
+ return {
117
+ valid: false,
118
+ errors: [...result.errors, `invalid errorCategory: ${rawCategory}`],
119
+ errorCategory: 'output_invalid',
120
+ };
238
121
  }
239
- const cancelNote = cancelFailed ? ' (cancelRun also failed)' : '';
240
- throw new PDRuntimeError('timeout', `Run ${runHandle.runId} timed out after ${this.resolvedOptions.timeoutMs}ms${cancelNote}`);
122
+ return {
123
+ valid: result.valid,
124
+ errors: result.errors,
125
+ errorCategory,
126
+ };
241
127
  }
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}`);
128
+ // eslint-disable-next-line @typescript-eslint/max-params
129
+ async succeedTask(taskId, runId, output, task, contextHash, context) {
130
+ // Lineage consistency: sourcePhilosopherArtifactId must match buildContext result (ERR-004).
131
+ if (output.sourcePhilosopherArtifactId !== context.sourcePhilosopherArtifactId) {
132
+ throw new PDRuntimeError('output_invalid', `sourcePhilosopherArtifactId mismatch: expected ${context.sourcePhilosopherArtifactId}, got ${output.sourcePhilosopherArtifactId}`);
246
133
  }
247
- return result.payload;
248
- }
249
- async succeedTask(ctx) {
134
+ // Store output before marking succeeded
250
135
  try {
251
- await this.stateManager.updateRunOutput(ctx.runId, JSON.stringify(ctx.output));
136
+ await this.stateManager.updateRunOutput(runId, JSON.stringify(output));
252
137
  }
253
138
  catch (updateErr) {
254
- this.emitScribeEvent('scribe_update_output_failed', ctx.taskId, {
255
- runId: ctx.runId,
139
+ this.emitEvent('update_output_failed', taskId, {
140
+ runId,
256
141
  errorMessage: updateErr instanceof Error ? updateErr.message : String(updateErr),
257
142
  });
258
143
  throw updateErr;
259
144
  }
260
- const artifactId = `pi-art-${ctx.taskId}-${ctx.runId}`;
261
- const now = new Date().toISOString();
145
+ // Resolve lineage artifact IDs
262
146
  let lineageArtifactIds = [];
147
+ let lineageHasRejected = false;
263
148
  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
- }
149
+ const lineageResult = await this.resolveLineageArtifactIds(taskId);
150
+ lineageArtifactIds = lineageResult.ids;
151
+ lineageHasRejected = lineageResult.hasRejected;
152
+ }
153
+ catch (lineageErr) {
154
+ this.emitEvent('lineage_resolve_failed', taskId, {
155
+ runId,
156
+ errorMessage: lineageErr instanceof Error ? lineageErr.message : String(lineageErr),
157
+ });
158
+ }
159
+ if (lineageHasRejected) {
160
+ this.emitEvent('lineage_partial', taskId, {
161
+ runId,
162
+ resolvedCount: lineageArtifactIds.length,
163
+ warning: 'Some dependency artifact queries were rejected; lineage may be incomplete',
164
+ });
274
165
  }
275
- catch { /* lineage resolution failure is non-fatal */ }
166
+ // Write PIArtifact via artifactStore (idempotent upsert)
167
+ const artifactId = `pi-art-${taskId}-${runId}`;
168
+ const now = new Date().toISOString();
276
169
  try {
277
170
  await this.artifactStore.upsertArtifact({
278
171
  artifactId,
279
172
  artifactKind: 'principle',
280
- sourceTaskId: ctx.taskId,
173
+ sourceTaskId: taskId,
281
174
  lineageArtifactIds,
282
175
  validationStatus: 'pending',
283
- contentJson: JSON.stringify(ctx.output),
176
+ contentJson: JSON.stringify(output),
284
177
  createdAt: now,
285
178
  updatedAt: now,
286
179
  });
287
180
  }
288
181
  catch (artifactErr) {
289
- this.emitScribeEvent('scribe_artifact_write_failed', ctx.taskId, {
290
- runId: ctx.runId,
182
+ this.emitEvent('artifact_write_failed', taskId, {
183
+ runId,
291
184
  errorMessage: artifactErr instanceof Error ? artifactErr.message : String(artifactErr),
292
185
  });
293
186
  return this.retryOrFail({
294
- taskId: ctx.taskId,
295
- task: ctx.task,
187
+ taskId,
188
+ task,
296
189
  errorCategory: 'artifact_commit_failed',
297
190
  failureReason: `PIArtifact write failed: ${artifactErr instanceof Error ? artifactErr.message : String(artifactErr)}`,
298
191
  });
299
192
  }
300
- const resultRef = `scribe://${ctx.runId}`;
193
+ // Mark task succeeded
194
+ const resultRef = `${this.config.resultRefPrefix}://${runId}`;
301
195
  try {
302
- await this.stateManager.markTaskSucceeded(ctx.taskId, resultRef);
196
+ await this.stateManager.markTaskSucceeded(taskId, resultRef);
303
197
  }
304
198
  catch (stateErr) {
305
- this.emitScribeEvent('scribe_mark_succeeded_failed', ctx.taskId, {
306
- taskId: ctx.taskId,
307
- runId: ctx.runId,
199
+ this.emitEvent('mark_succeeded_failed', taskId, {
200
+ taskId,
201
+ runId,
308
202
  errorMessage: stateErr instanceof Error ? stateErr.message : String(stateErr),
309
203
  });
310
204
  throw stateErr;
311
205
  }
312
- this.emitScribeEvent('scribe_task_succeeded', ctx.taskId, {
313
- attemptCount: ctx.task.attemptCount,
206
+ this.emitEvent('task_succeeded', taskId, {
207
+ attemptCount: task.attemptCount,
314
208
  resultRef,
315
- principleTitle: ctx.output.principleDraft.title,
209
+ principleTitle: output.principleDraft.title,
316
210
  });
317
- this.phase = RunnerPhase.Completed;
318
211
  return {
319
212
  status: 'succeeded',
320
- taskId: ctx.taskId,
321
- runId: ctx.runId,
213
+ taskId,
214
+ runId,
322
215
  artifactId,
323
216
  resultRef,
324
- contextHash: ctx.contextHash,
325
- output: ctx.output,
326
- attemptCount: ctx.task.attemptCount,
217
+ contextHash,
218
+ output,
219
+ attemptCount: task.attemptCount,
327
220
  };
328
221
  }
329
- async handleRuntimeFailure(taskId, task, runStatus) {
330
- const errorCategory = this.mapRunStatusToErrorCategory(runStatus.status);
331
- this.emitScribeEvent('scribe_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.emitScribeEvent('scribe_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.emitScribeEvent('scribe_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.emitScribeEvent('scribe_run_failed', taskId, {
371
- errorCategory: classified.category,
372
- errorMessage: classified.message,
373
- });
374
- const task = {
375
- taskId,
376
- taskKind: 'scribe',
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.emitScribeEvent('scribe_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.emitScribeEvent('scribe_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.emitScribeEvent('scribe_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.emitScribeEvent('scribe_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.emitScribeEvent('scribe_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.emitScribeEvent('scribe_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.emitScribeEvent('scribe_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
- PERMANENT_ERROR_CATEGORIES = new Set(Object.freeze(['storage_unavailable', 'workspace_invalid', 'capability_missing', 'cancelled', 'input_invalid', 'output_invalid']));
490
- isPermanentError(category) {
491
- return this.PERMANENT_ERROR_CATEGORIES.has(category);
492
- }
222
+ // ── Optional hooks ─────────────────────────────────────────────────────────
223
+ /**
224
+ * Re-inject taskId if stripped by stripLineageFields (PRI-272 / ERR-008).
225
+ * Only fill when absent via Object.hasOwn — present-but-falsy values
226
+ * must reach validation and fail loud (Runtime Contract Rule 3).
227
+ */
493
228
  // eslint-disable-next-line @typescript-eslint/class-methods-use-this
494
- classifyError(error) {
495
- if (error instanceof PDRuntimeError) {
496
- return { category: error.category, message: error.message };
497
- }
498
- if (error instanceof Error) {
499
- return { category: 'execution_failed', message: error.message };
500
- }
501
- return { category: 'execution_failed', message: String(error) };
229
+ postFetchTransform(taskId, untrustedOutput) {
230
+ injectRunnerLineageIfAbsent(untrustedOutput, 'taskId', taskId);
502
231
  }
503
- // eslint-disable-next-line @typescript-eslint/class-methods-use-this
504
- mapRunStatusToErrorCategory(status) {
505
- switch (status) {
506
- case 'failed': return 'execution_failed';
507
- case 'timed_out': return 'timeout';
508
- case 'cancelled': return 'cancelled';
509
- default: return 'execution_failed';
510
- }
511
- }
512
- // eslint-disable-next-line @typescript-eslint/class-methods-use-this
513
- sleep(ms) {
514
- return new Promise((resolve) => setTimeout(resolve, ms));
232
+ emitSuccessTelemetry(taskId, output) {
233
+ this.emitEvent('principle_draft_generated', taskId, {
234
+ principleTitle: output.principleDraft.title,
235
+ });
515
236
  }
516
237
  }
517
- export { resolveScribeRunnerOptions, DEFAULT_SCRIBE_RUNNER_OPTIONS };
518
238
  //# sourceMappingURL=scribe-runner.js.map