@cat-factory/orchestration 0.177.1 → 0.179.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 (80) hide show
  1. package/dist/container/dependencies.d.ts +12 -1
  2. package/dist/container/dependencies.d.ts.map +1 -1
  3. package/dist/container/execution-service.d.ts +33 -0
  4. package/dist/container/execution-service.d.ts.map +1 -0
  5. package/dist/container/execution-service.js +84 -0
  6. package/dist/container/execution-service.js.map +1 -0
  7. package/dist/container/platform-modules.d.ts +2 -1
  8. package/dist/container/platform-modules.d.ts.map +1 -1
  9. package/dist/container/platform-modules.js +3 -1
  10. package/dist/container/platform-modules.js.map +1 -1
  11. package/dist/container-content-libraries.d.ts +28 -1
  12. package/dist/container-content-libraries.d.ts.map +1 -1
  13. package/dist/container-content-libraries.js +47 -1
  14. package/dist/container-content-libraries.js.map +1 -1
  15. package/dist/container.d.ts +4 -2
  16. package/dist/container.d.ts.map +1 -1
  17. package/dist/container.js +20 -67
  18. package/dist/container.js.map +1 -1
  19. package/dist/index.d.ts +1 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/modules/execution/AgentContextBuilder.d.ts +31 -24
  23. package/dist/modules/execution/AgentContextBuilder.d.ts.map +1 -1
  24. package/dist/modules/execution/AgentContextBuilder.js +62 -84
  25. package/dist/modules/execution/AgentContextBuilder.js.map +1 -1
  26. package/dist/modules/execution/ExecutionService.d.ts +11 -10
  27. package/dist/modules/execution/ExecutionService.d.ts.map +1 -1
  28. package/dist/modules/execution/ExecutionService.js +72 -94
  29. package/dist/modules/execution/ExecutionService.js.map +1 -1
  30. package/dist/modules/execution/ExecutionServiceDependencies.d.ts +14 -1
  31. package/dist/modules/execution/ExecutionServiceDependencies.d.ts.map +1 -1
  32. package/dist/modules/execution/RunAdmission.d.ts.map +1 -1
  33. package/dist/modules/execution/RunAdmission.js +4 -2
  34. package/dist/modules/execution/RunAdmission.js.map +1 -1
  35. package/dist/modules/execution/RunDispatcher.d.ts.map +1 -1
  36. package/dist/modules/execution/RunDispatcher.js +2 -39
  37. package/dist/modules/execution/RunDispatcher.js.map +1 -1
  38. package/dist/modules/execution/RunStateMachine.d.ts +44 -1
  39. package/dist/modules/execution/RunStateMachine.d.ts.map +1 -1
  40. package/dist/modules/execution/RunStateMachine.js +92 -1
  41. package/dist/modules/execution/RunStateMachine.js.map +1 -1
  42. package/dist/modules/execution/builder-context-files.d.ts +36 -0
  43. package/dist/modules/execution/builder-context-files.d.ts.map +1 -0
  44. package/dist/modules/execution/builder-context-files.js +54 -0
  45. package/dist/modules/execution/builder-context-files.js.map +1 -0
  46. package/dist/modules/execution/dispatchPromptSettings.d.ts +43 -0
  47. package/dist/modules/execution/dispatchPromptSettings.d.ts.map +1 -0
  48. package/dist/modules/execution/dispatchPromptSettings.js +76 -0
  49. package/dist/modules/execution/dispatchPromptSettings.js.map +1 -0
  50. package/dist/modules/execution/job-facts.d.ts +12 -0
  51. package/dist/modules/execution/job-facts.d.ts.map +1 -0
  52. package/dist/modules/execution/job-facts.js +50 -0
  53. package/dist/modules/execution/job-facts.js.map +1 -0
  54. package/dist/modules/execution/run-context-admission.d.ts +1 -1
  55. package/dist/modules/execution/run-context-admission.d.ts.map +1 -1
  56. package/dist/modules/execution/run-context-admission.js +1 -0
  57. package/dist/modules/execution/run-context-admission.js.map +1 -1
  58. package/dist/modules/execution/run-foundational-services.d.ts +83 -0
  59. package/dist/modules/execution/run-foundational-services.d.ts.map +1 -0
  60. package/dist/modules/execution/run-foundational-services.js +76 -0
  61. package/dist/modules/execution/run-foundational-services.js.map +1 -0
  62. package/dist/modules/execution/runStart.d.ts +50 -0
  63. package/dist/modules/execution/runStart.d.ts.map +1 -0
  64. package/dist/modules/execution/runStart.js +53 -0
  65. package/dist/modules/execution/runStart.js.map +1 -0
  66. package/dist/modules/kaizen/KaizenService.d.ts.map +1 -1
  67. package/dist/modules/kaizen/KaizenService.js +7 -5
  68. package/dist/modules/kaizen/KaizenService.js.map +1 -1
  69. package/dist/modules/kaizen/kaizen.logic.d.ts +24 -9
  70. package/dist/modules/kaizen/kaizen.logic.d.ts.map +1 -1
  71. package/dist/modules/kaizen/kaizen.logic.js +25 -10
  72. package/dist/modules/kaizen/kaizen.logic.js.map +1 -1
  73. package/dist/modules/pipelines/pipelineShape.d.ts +27 -0
  74. package/dist/modules/pipelines/pipelineShape.d.ts.map +1 -1
  75. package/dist/modules/pipelines/pipelineShape.js +44 -1
  76. package/dist/modules/pipelines/pipelineShape.js.map +1 -1
  77. package/dist/validation/validateRegistrations.d.ts.map +1 -1
  78. package/dist/validation/validateRegistrations.js +92 -0
  79. package/dist/validation/validateRegistrations.js.map +1 -1
  80. package/package.json +11 -11
@@ -0,0 +1,43 @@
1
+ import type { AgentPromptRepository, Logger, PipelineStep, WorkspaceAgentSettingsRepository } from '@cat-factory/kernel';
2
+ import type { AgentKindRegistry } from '@cat-factory/agents';
3
+ /** The narrow slice of the builder's dependencies these two resolvers need. */
4
+ export interface DispatchPromptSettingsDeps {
5
+ agentKindRegistry: AgentKindRegistry;
6
+ /** The append-only per-workspace prompt log. Absent ⇒ the override feature is not wired. */
7
+ agentPrompts?: AgentPromptRepository;
8
+ /** The per-workspace, per-kind generation settings. Absent ⇒ the feature is not wired. */
9
+ agentSettings?: WorkspaceAgentSettingsRepository;
10
+ logger?: Logger;
11
+ }
12
+ /**
13
+ * The base system prompt this dispatch replaces the shipped one with, or undefined to run the
14
+ * shipped one. Two tiers converge here — the deployment's registered agent-kind VARIANT for this
15
+ * step and the WORKSPACE's edited prompt for the kind — because they are the same unit of text.
16
+ *
17
+ * The head revision's `text` is `null` when the workspace deliberately went BACK to the built-in —
18
+ * a real state, distinct from never having edited the kind, which is why it is recorded rather than
19
+ * deleted. Both resolve to "no override" here, so a revert keeps tracking the shipped prompt as the
20
+ * product bumps it instead of pinning a stale copy.
21
+ *
22
+ * MUTATES the step to pin what it resolved (`promptRevision`, `promptVariant`), because neither can
23
+ * be re-derived afterwards: the prompt log is append-only, so re-reading it at any later point — a
24
+ * Kaizen grading, a debug read, a post-mortem — would answer about whatever landed since. The
25
+ * VARIANT is pinned for a second reason: `stepOptions.agentVariantId` is what the pipeline ASKED
26
+ * for, and a workspace override or a withdrawal can mean the variant's text never reached the
27
+ * prompt, so only a pin taken HERE can answer what the step actually ran under.
28
+ */
29
+ export declare function resolveDispatchSystemPrompt(deps: DispatchPromptSettingsDeps, workspaceId: string, agentKind: string, step: PipelineStep): Promise<{
30
+ systemPromptOverride?: string;
31
+ }>;
32
+ /**
33
+ * The output-token ceiling this dispatch runs under, or undefined to run the deployment routing
34
+ * default.
35
+ *
36
+ * NARROWEST TIER WINS: the step's own `stepOptions.maxOutputTokens` beats the workspace's per-kind
37
+ * setting, which beats the deployment routing ceiling. The step value is read WITHOUT touching the
38
+ * repository, so a pipeline that pins its own budget costs no query.
39
+ */
40
+ export declare function resolveDispatchMaxOutputTokens(deps: DispatchPromptSettingsDeps, workspaceId: string, agentKind: string, step: PipelineStep): Promise<{
41
+ maxOutputTokens?: number;
42
+ }>;
43
+ //# sourceMappingURL=dispatchPromptSettings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatchPromptSettings.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/dispatchPromptSettings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,MAAM,EACN,YAAY,EACZ,gCAAgC,EACjC,MAAM,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAsB5D,+EAA+E;AAC/E,MAAM,WAAW,0BAA0B;IACzC,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,4FAA4F;IAC5F,YAAY,CAAC,EAAE,qBAAqB,CAAA;IACpC,0FAA0F;IAC1F,aAAa,CAAC,EAAE,gCAAgC,CAAA;IAChD,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE,0BAA0B,EAChC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC;IAAE,oBAAoB,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA+C5C;AAED;;;;;;;GAOG;AACH,wBAAsB,8BAA8B,CAClD,IAAI,EAAE,0BAA0B,EAChC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC;IAAE,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAKvC"}
@@ -0,0 +1,76 @@
1
+ import { applyAgentVariant, shippedBasePromptFor } from '@cat-factory/agents';
2
+ /**
3
+ * The base system prompt this dispatch replaces the shipped one with, or undefined to run the
4
+ * shipped one. Two tiers converge here — the deployment's registered agent-kind VARIANT for this
5
+ * step and the WORKSPACE's edited prompt for the kind — because they are the same unit of text.
6
+ *
7
+ * The head revision's `text` is `null` when the workspace deliberately went BACK to the built-in —
8
+ * a real state, distinct from never having edited the kind, which is why it is recorded rather than
9
+ * deleted. Both resolve to "no override" here, so a revert keeps tracking the shipped prompt as the
10
+ * product bumps it instead of pinning a stale copy.
11
+ *
12
+ * MUTATES the step to pin what it resolved (`promptRevision`, `promptVariant`), because neither can
13
+ * be re-derived afterwards: the prompt log is append-only, so re-reading it at any later point — a
14
+ * Kaizen grading, a debug read, a post-mortem — would answer about whatever landed since. The
15
+ * VARIANT is pinned for a second reason: `stepOptions.agentVariantId` is what the pipeline ASKED
16
+ * for, and a workspace override or a withdrawal can mean the variant's text never reached the
17
+ * prompt, so only a pin taken HERE can answer what the step actually ran under.
18
+ */
19
+ export async function resolveDispatchSystemPrompt(deps, workspaceId, agentKind, step) {
20
+ const head = await deps.agentPrompts?.head(workspaceId, agentKind);
21
+ // Cleared, not left stale: a re-dispatch after the workspace reverted must not keep reporting
22
+ // the revision the previous attempt ran under.
23
+ step.promptRevision = head?.text ? head.revision : undefined;
24
+ // The variant applies only when the kind being dispatched IS the step's own — a helper dispatched
25
+ // off this step (a gate's fixer, the fork proposer) is a different agent and must not inherit the
26
+ // step's alternate prompt. Same rule as `followUpCompanion`.
27
+ const variantId = agentKind === step.agentKind ? step.stepOptions?.agentVariantId : undefined;
28
+ const variant = variantId ? deps.agentKindRegistry.variant(variantId) : undefined;
29
+ // A variant the deployment has since withdrawn: the step runs the SHIPPED prompt, which is the
30
+ // safe disposition, but it is not what the pipeline asked for — so say so rather than let a step
31
+ // quietly stop being the variation someone configured.
32
+ if (variantId && !variant) {
33
+ deps.logger?.warn('Agent kind variant is not registered; running the shipped prompt', {
34
+ agentKind,
35
+ variantId,
36
+ });
37
+ }
38
+ const { prompt, applied, fingerprint } = applyAgentVariant(
39
+ // Only paid for when a variant is actually selected; the shipped prompt is what its addition
40
+ // folds onto and what its replacement is measured against.
41
+ variant ? shippedBasePromptFor(agentKind, deps.agentKindRegistry) : '', variant, head?.text ?? undefined);
42
+ // The workspace out-ranks the deployment on the same unit of text, so its edit DISPLACES a
43
+ // variant's replacement. That is the intended precedence, but it is a silent loss of something a
44
+ // deployment configured in code — the one disposition here with no other symptom — so it is
45
+ // reported at the fold, exactly as a withdrawal is above.
46
+ if (applied === 'superseded' || applied === 'addition-only') {
47
+ deps.logger?.warn("Workspace prompt override displaced the agent variant's own prompt for this dispatch", { agentKind, variantId, promptRevision: step.promptRevision, applied });
48
+ }
49
+ // What the dispatch DID with the step's selected variant, so a later reader is never told a step
50
+ // ran a variation whose text never reached it. Cleared, not left stale, for the same reason
51
+ // `promptRevision` is: a re-dispatch resolves it afresh.
52
+ step.promptVariant = variantId
53
+ ? {
54
+ id: variantId,
55
+ applied: variant ? applied : 'withdrawn',
56
+ ...(fingerprint ? { fingerprint } : {}),
57
+ }
58
+ : undefined;
59
+ return prompt ? { systemPromptOverride: prompt } : {};
60
+ }
61
+ /**
62
+ * The output-token ceiling this dispatch runs under, or undefined to run the deployment routing
63
+ * default.
64
+ *
65
+ * NARROWEST TIER WINS: the step's own `stepOptions.maxOutputTokens` beats the workspace's per-kind
66
+ * setting, which beats the deployment routing ceiling. The step value is read WITHOUT touching the
67
+ * repository, so a pipeline that pins its own budget costs no query.
68
+ */
69
+ export async function resolveDispatchMaxOutputTokens(deps, workspaceId, agentKind, step) {
70
+ const fromStep = step.stepOptions?.maxOutputTokens;
71
+ if (fromStep != null)
72
+ return { maxOutputTokens: fromStep };
73
+ const configured = await deps.agentSettings?.get(workspaceId, agentKind);
74
+ return configured?.maxOutputTokens != null ? { maxOutputTokens: configured.maxOutputTokens } : {};
75
+ }
76
+ //# sourceMappingURL=dispatchPromptSettings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatchPromptSettings.js","sourceRoot":"","sources":["../../../src/modules/execution/dispatchPromptSettings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { PipelineStep } from '@cat-factory/contracts';
2
+ import type { AgentRunResult, Clock, ExecutionInstance } from '@cat-factory/kernel';
3
+ import type { SpendService } from '@cat-factory/spend';
4
+ import type { AgentContextBuilder } from './AgentContextBuilder.js';
5
+ export interface JobFactsDeps {
6
+ clock: Clock;
7
+ spend: SpendService;
8
+ contextBuilder: AgentContextBuilder;
9
+ }
10
+ /** Record the facts the just-settled job reported. See the module note for the ordering rule. */
11
+ export declare function recordJobFacts(deps: JobFactsDeps, workspaceId: string, instance: ExecutionInstance, step: PipelineStep, result: AgentRunResult): Promise<void>;
12
+ //# sourceMappingURL=job-facts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-facts.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/job-facts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACnF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAiBnE,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,KAAK,CAAA;IACZ,KAAK,EAAE,YAAY,CAAA;IACnB,cAAc,EAAE,mBAAmB,CAAA;CACpC;AAED,iGAAiG;AACjG,wBAAsB,cAAc,CAClC,IAAI,EAAE,YAAY,EAClB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,iBAAiB,EAC3B,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,IAAI,CAAC,CAgDf"}
@@ -0,0 +1,50 @@
1
+ import { applyValidationReport } from './validation.logic.js';
2
+ import { recordReproductionOutcome } from './reproductionProof.logic.js';
3
+ /** Record the facts the just-settled job reported. See the module note for the ordering rule. */
4
+ export async function recordJobFacts(deps, workspaceId, instance, step, result) {
5
+ // The container agent's effort self-assessment (how hard the work was, what reduced its
6
+ // effectiveness, the obstacles it hit) describes the JOB THAT JUST RAN, so record it before
7
+ // any of the paths below can return early — exactly like the usage metering under it. It
8
+ // used to sit with the normal completion further down, which meant every kind whose verdict
9
+ // drives run flow silently dropped it: a `pr-reviewer` parking on its findings, a container
10
+ // companion applying its verdict, the fork proposer, a Tester withholding its greenlight, a
11
+ // step raising a human decision. Those are the runs whose self-assessment is most worth
12
+ // reading, and none of them ever reaches the normal completion with the result in hand.
13
+ if (result.effortReport)
14
+ step.effortReport = result.effortReport;
15
+ // The FOUNDATIONAL SERVICES this step's design declared, read out of the reply it just
16
+ // returned. Recorded HERE, beside the effort report, for the same reason: every path below can
17
+ // return early (a raised decision, a companion applying a rework loop), and a design step that
18
+ // parks would otherwise lose its declaration — every consumer then reads "nothing was checked".
19
+ // Read back by the context BUILDER, which handed the design its catalog and already holds the
20
+ // resolver + registry, so the completion hub takes no dependency of its own for it.
21
+ await deps.contextBuilder.recordFoundationalDeclaration(workspaceId, step, result.output);
22
+ // The pre-PR validation report of a coding step whose service configured checks — recorded
23
+ // here for the same reason as the effort report above: it describes the JOB THAT JUST RAN,
24
+ // so it must land before any early-returning path below. On this (successful) path it is
25
+ // the captured proof the checkout was green BEFORE the PR opened; the failed path records
26
+ // it in `PollCompletionController.handleFailedPoll`.
27
+ applyValidationReport(step, result.validationReport);
28
+ // The BUGFIX REPRODUCTION PROOF of a coding step — the harness's verdict, or (for a run whose
29
+ // reproduction step conceded, which dispatches no proof at all) the structural infeasibility
30
+ // declaration the engine mints itself. Recorded here for the same reason as the validation
31
+ // report above: it describes the JOB THAT JUST RAN, so it must land before any early return.
32
+ recordReproductionOutcome(step, result.reproductionReport, instance, deps.clock.now());
33
+ // Meter the LLM call into the usage ledger. Recorded whether the step completed or
34
+ // raised a decision — both consumed tokens. A subscription-harness result is tagged
35
+ // `'subscription'` so it's counted for the usage report but EXCLUDED from the budget
36
+ // rollups (a flat-rate quota plan costs nothing per token); an inline metered call
37
+ // defaults to `'metered'` and is summed by the spend gate as before.
38
+ if (result.usage) {
39
+ await deps.spend.record({
40
+ workspaceId,
41
+ executionId: instance.id,
42
+ agentKind: step.agentKind,
43
+ model: result.model ?? 'unknown',
44
+ usage: result.usage,
45
+ billing: result.usageBilling ?? 'metered',
46
+ vendor: result.usageVendor ?? null,
47
+ });
48
+ }
49
+ }
50
+ //# sourceMappingURL=job-facts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-facts.js","sourceRoot":"","sources":["../../../src/modules/execution/job-facts.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAC7D,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAA;AAqBxE,iGAAiG;AACjG,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAkB,EAClB,WAAmB,EACnB,QAA2B,EAC3B,IAAkB,EAClB,MAAsB;IAEtB,wFAAwF;IACxF,4FAA4F;IAC5F,yFAAyF;IACzF,4FAA4F;IAC5F,4FAA4F;IAC5F,4FAA4F;IAC5F,wFAAwF;IACxF,wFAAwF;IACxF,IAAI,MAAM,CAAC,YAAY;QAAE,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,CAAA;IAEhE,uFAAuF;IACvF,+FAA+F;IAC/F,+FAA+F;IAC/F,gGAAgG;IAChG,8FAA8F;IAC9F,oFAAoF;IACpF,MAAM,IAAI,CAAC,cAAc,CAAC,6BAA6B,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;IAEzF,2FAA2F;IAC3F,2FAA2F;IAC3F,yFAAyF;IACzF,0FAA0F;IAC1F,qDAAqD;IACrD,qBAAqB,CAAC,IAAI,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAA;IAEpD,8FAA8F;IAC9F,6FAA6F;IAC7F,2FAA2F;IAC3F,6FAA6F;IAC7F,yBAAyB,CAAC,IAAI,EAAE,MAAM,CAAC,kBAAkB,EAAE,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAA;IAEtF,mFAAmF;IACnF,oFAAoF;IACpF,qFAAqF;IACrF,mFAAmF;IACnF,qEAAqE;IACrE,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;YACtB,WAAW;YACX,WAAW,EAAE,QAAQ,CAAC,EAAE;YACxB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,SAAS;YAChC,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,OAAO,EAAE,MAAM,CAAC,YAAY,IAAI,SAAS;YACzC,MAAM,EAAE,MAAM,CAAC,WAAW,IAAI,IAAI;SACnC,CAAC,CAAA;IACJ,CAAC;AACH,CAAC"}
@@ -17,7 +17,7 @@ import type { ExecutionServiceDependencies } from './ExecutionService.js';
17
17
  * value the constructor passed inline, so the two collaborators are built from an identical
18
18
  * input to before.
19
19
  */
20
- export type RunContextAdmissionDeps = Pick<ExecutionServiceDependencies, 'workspaceRepository' | 'blockRepository' | 'executionRepository' | 'accountRepository' | 'agentKindRegistry' | 'initiativePresetRegistry' | 'agentPromptRepository' | 'consensusGroupRepository' | 'documentRepository' | 'documentUrlResolver' | 'taskRepository' | 'requirementReviewRepository' | 'docInterviewRepository' | 'clarityReviewRepository' | 'brainstormSessionRepository' | 'initiativeRepository' | 'environmentProvisioning' | 'resolveTestSecretRefs' | 'resolveValidationChecks' | 'fragmentResolver' | 'skillResolver' | 'spendService' | 'workspaceSettingsService' | 'resolveBinaryArtifactStore' | 'resolveProviderCapabilities' | 'inlineHarnessRef' | 'resolveWorkspaceModelDefault' | 'assertAgentBackendConfigured' | 'logger' | 'workspaceAgentSettingsRepository'>;
20
+ export type RunContextAdmissionDeps = Pick<ExecutionServiceDependencies, 'workspaceRepository' | 'blockRepository' | 'executionRepository' | 'accountRepository' | 'agentKindRegistry' | 'initiativePresetRegistry' | 'agentPromptRepository' | 'consensusGroupRepository' | 'documentRepository' | 'documentUrlResolver' | 'taskRepository' | 'requirementReviewRepository' | 'docInterviewRepository' | 'clarityReviewRepository' | 'brainstormSessionRepository' | 'initiativeRepository' | 'environmentProvisioning' | 'resolveTestSecretRefs' | 'resolveValidationChecks' | 'fragmentResolver' | 'skillResolver' | 'spendService' | 'workspaceSettingsService' | 'resolveBinaryArtifactStore' | 'resolveProviderCapabilities' | 'inlineHarnessRef' | 'resolveWorkspaceModelDefault' | 'assertAgentBackendConfigured' | 'logger' | 'workspaceAgentSettingsRepository' | 'foundationalServiceResolver'>;
21
21
  export declare function buildRunContextAndAdmission(deps: RunContextAdmissionDeps): {
22
22
  contextBuilder: AgentContextBuilder;
23
23
  admission: RunAdmission;
@@ -1 +1 @@
1
- {"version":3,"file":"run-context-admission.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/run-context-admission.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAA;AAEzE;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG,IAAI,CACxC,4BAA4B,EAC1B,qBAAqB,GACrB,iBAAiB,GACjB,qBAAqB,GACrB,mBAAmB,GACnB,mBAAmB,GACnB,0BAA0B,GAC1B,uBAAuB,GACvB,0BAA0B,GAC1B,oBAAoB,GACpB,qBAAqB,GACrB,gBAAgB,GAChB,6BAA6B,GAC7B,wBAAwB,GACxB,yBAAyB,GACzB,6BAA6B,GAC7B,sBAAsB,GACtB,yBAAyB,GACzB,uBAAuB,GACvB,yBAAyB,GACzB,kBAAkB,GAClB,eAAe,GACf,cAAc,GACd,0BAA0B,GAC1B,4BAA4B,GAC5B,6BAA6B,GAC7B,kBAAkB,GAClB,8BAA8B,GAC9B,8BAA8B,GAC9B,QAAQ,GACR,kCAAkC,CACrC,CAAA;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,uBAAuB,GAAG;IAC1E,cAAc,EAAE,mBAAmB,CAAA;IACnC,SAAS,EAAE,YAAY,CAAA;CACxB,CA2CA"}
1
+ {"version":3,"file":"run-context-admission.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/run-context-admission.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAA;AAEzE;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG,IAAI,CACxC,4BAA4B,EAC1B,qBAAqB,GACrB,iBAAiB,GACjB,qBAAqB,GACrB,mBAAmB,GACnB,mBAAmB,GACnB,0BAA0B,GAC1B,uBAAuB,GACvB,0BAA0B,GAC1B,oBAAoB,GACpB,qBAAqB,GACrB,gBAAgB,GAChB,6BAA6B,GAC7B,wBAAwB,GACxB,yBAAyB,GACzB,6BAA6B,GAC7B,sBAAsB,GACtB,yBAAyB,GACzB,uBAAuB,GACvB,yBAAyB,GACzB,kBAAkB,GAClB,eAAe,GACf,cAAc,GACd,0BAA0B,GAC1B,4BAA4B,GAC5B,6BAA6B,GAC7B,kBAAkB,GAClB,8BAA8B,GAC9B,8BAA8B,GAC9B,QAAQ,GACR,kCAAkC,GAClC,6BAA6B,CAChC,CAAA;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,uBAAuB,GAAG;IAC1E,cAAc,EAAE,mBAAmB,CAAA;IACnC,SAAS,EAAE,YAAY,CAAA;CACxB,CA4CA"}
@@ -34,6 +34,7 @@ export function buildRunContextAndAdmission(deps) {
34
34
  resolveValidationChecks: deps.resolveValidationChecks,
35
35
  fragmentResolver: deps.fragmentResolver,
36
36
  skillResolver: deps.skillResolver,
37
+ foundationalServiceResolver: deps.foundationalServiceResolver,
37
38
  logger: deps.logger,
38
39
  });
39
40
  // The run-admission preflights (the shared start/retry/restart `assert*` gate family).
@@ -1 +1 @@
1
- {"version":3,"file":"run-context-admission.js","sourceRoot":"","sources":["../../../src/modules/execution/run-context-admission.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AA0ChD,MAAM,UAAU,2BAA2B,CAAC,IAA6B;IAIvE,MAAM,cAAc,GAAG,IAAI,mBAAmB,CAAC;QAC7C,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;QAC7C,eAAe,EAAE,IAAI,CAAC,eAAe;QACrC,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;QACzC,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;QACzC,wBAAwB,EAAE,IAAI,CAAC,wBAAwB;QACvD,YAAY,EAAE,IAAI,CAAC,qBAAqB;QACxC,aAAa,EAAE,IAAI,CAAC,gCAAgC;QACpD,eAAe,EAAE,IAAI,CAAC,wBAAwB;QAC9C,SAAS,EAAE,IAAI,CAAC,kBAAkB;QAClC,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;QAC7C,KAAK,EAAE,IAAI,CAAC,cAAc;QAC1B,kBAAkB,EAAE,IAAI,CAAC,2BAA2B;QACpD,aAAa,EAAE,IAAI,CAAC,sBAAsB;QAC1C,cAAc,EAAE,IAAI,CAAC,uBAAuB;QAC5C,kBAAkB,EAAE,IAAI,CAAC,2BAA2B;QACpD,WAAW,EAAE,IAAI,CAAC,oBAAoB;QACtC,uBAAuB,EAAE,IAAI,CAAC,uBAAuB;QACrD,qBAAqB,EAAE,IAAI,CAAC,qBAAqB;QACjD,uBAAuB,EAAE,IAAI,CAAC,uBAAuB;QACrD,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;QACvC,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC,CAAA;IACF,uFAAuF;IACvF,gFAAgF;IAChF,MAAM,SAAS,GAAG,IAAI,YAAY,CAAC;QACjC,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;QAC7C,eAAe,EAAE,IAAI,CAAC,eAAe;QACrC,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;QAC7C,cAAc;QACd,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;QACzC,KAAK,EAAE,IAAI,CAAC,YAAY;QACxB,uBAAuB,EAAE,IAAI,CAAC,uBAAuB;QACrD,wBAAwB,EAAE,IAAI,CAAC,wBAAwB;QACvD,0BAA0B,EAAE,IAAI,CAAC,0BAA0B;QAC3D,2BAA2B,EAAE,IAAI,CAAC,2BAA2B;QAC7D,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;QACvC,4BAA4B,EAAE,IAAI,CAAC,4BAA4B;QAC/D,4BAA4B,EAAE,IAAI,CAAC,4BAA4B;KAChE,CAAC,CAAA;IACF,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,CAAA;AACtC,CAAC"}
1
+ {"version":3,"file":"run-context-admission.js","sourceRoot":"","sources":["../../../src/modules/execution/run-context-admission.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AA2ChD,MAAM,UAAU,2BAA2B,CAAC,IAA6B;IAIvE,MAAM,cAAc,GAAG,IAAI,mBAAmB,CAAC;QAC7C,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;QAC7C,eAAe,EAAE,IAAI,CAAC,eAAe;QACrC,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;QACzC,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;QACzC,wBAAwB,EAAE,IAAI,CAAC,wBAAwB;QACvD,YAAY,EAAE,IAAI,CAAC,qBAAqB;QACxC,aAAa,EAAE,IAAI,CAAC,gCAAgC;QACpD,eAAe,EAAE,IAAI,CAAC,wBAAwB;QAC9C,SAAS,EAAE,IAAI,CAAC,kBAAkB;QAClC,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;QAC7C,KAAK,EAAE,IAAI,CAAC,cAAc;QAC1B,kBAAkB,EAAE,IAAI,CAAC,2BAA2B;QACpD,aAAa,EAAE,IAAI,CAAC,sBAAsB;QAC1C,cAAc,EAAE,IAAI,CAAC,uBAAuB;QAC5C,kBAAkB,EAAE,IAAI,CAAC,2BAA2B;QACpD,WAAW,EAAE,IAAI,CAAC,oBAAoB;QACtC,uBAAuB,EAAE,IAAI,CAAC,uBAAuB;QACrD,qBAAqB,EAAE,IAAI,CAAC,qBAAqB;QACjD,uBAAuB,EAAE,IAAI,CAAC,uBAAuB;QACrD,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;QACvC,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,2BAA2B,EAAE,IAAI,CAAC,2BAA2B;QAC7D,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC,CAAA;IACF,uFAAuF;IACvF,gFAAgF;IAChF,MAAM,SAAS,GAAG,IAAI,YAAY,CAAC;QACjC,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;QAC7C,eAAe,EAAE,IAAI,CAAC,eAAe;QACrC,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;QAC7C,cAAc;QACd,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;QACzC,KAAK,EAAE,IAAI,CAAC,YAAY;QACxB,uBAAuB,EAAE,IAAI,CAAC,uBAAuB;QACrD,wBAAwB,EAAE,IAAI,CAAC,wBAAwB;QACvD,0BAA0B,EAAE,IAAI,CAAC,0BAA0B;QAC3D,2BAA2B,EAAE,IAAI,CAAC,2BAA2B;QAC7D,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;QACvC,4BAA4B,EAAE,IAAI,CAAC,4BAA4B;QAC/D,4BAA4B,EAAE,IAAI,CAAC,4BAA4B;KAChE,CAAC,CAAA;IACF,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,CAAA;AACtC,CAAC"}
@@ -0,0 +1,83 @@
1
+ import type { AgentKindRegistry } from '@cat-factory/agents';
2
+ import type { FoundationalServiceSelection, PipelineStep } from '@cat-factory/contracts';
3
+ import type { AgentKind, FoundationalCatalogView, InjectedContextFile, Logger } from '@cat-factory/kernel';
4
+ /**
5
+ * The engine-facing seam over the catalog, implemented by
6
+ * `FoundationalServiceRunResolver` (`@cat-factory/agents`) and wired only when the catalog is
7
+ * configured. Absent ⇒ nothing is injected, which is exactly the prior behaviour.
8
+ */
9
+ export interface FoundationalServiceResolver {
10
+ catalogFor(workspaceId: string): Promise<FoundationalCatalogView[]>;
11
+ /**
12
+ * Just the ids in the merged catalog — what a settled design's declaration is checked
13
+ * against. Its own method rather than a `catalogFor().map()` at the call site because the
14
+ * completion path has no use for the rest of a catalog entry, and reading the ids is what
15
+ * lets an invented id be reported as unknown instead of silently accepted.
16
+ */
17
+ catalogIdsFor(workspaceId: string): Promise<string[]>;
18
+ contextFilesFor(workspaceId: string, selection: FoundationalServiceSelection | undefined): Promise<InjectedContextFile[]>;
19
+ }
20
+ export interface ResolveFoundationalContextInput {
21
+ workspaceId: string;
22
+ /** The EFFECTIVE dispatched kind (a gate helper dispatches its own kind, not the step's). */
23
+ agentKind: AgentKind;
24
+ agentKindRegistry: AgentKindRegistry;
25
+ /** The run's steps BEFORE the one being dispatched, newest-last. */
26
+ priorSteps: PipelineStep[];
27
+ foundationalServiceResolver?: FoundationalServiceResolver;
28
+ logger?: Logger;
29
+ }
30
+ /**
31
+ * The `.cat-context/` files this dispatch gets from the foundational-services catalog:
32
+ *
33
+ * - a kind carrying `foundational-catalog` (the architect) gets the CATALOG — identity,
34
+ * capabilities and operation names for every registered service, no document bodies;
35
+ * - a kind carrying `foundational-contracts` (the researcher, the coder) gets the full API
36
+ * CONTRACTS, for exactly the ids a prior design step declared;
37
+ * - anything else gets nothing, and pays for nothing.
38
+ *
39
+ * BEST-EFFORT as a whole: the catalog is enrichment, and an unreachable store must not fail a
40
+ * run that would otherwise proceed exactly as it did before the feature existed. A failure is
41
+ * logged with its cause rather than swallowed.
42
+ */
43
+ export declare function resolveFoundationalContext(input: ResolveFoundationalContextInput): Promise<InjectedContextFile[]>;
44
+ /**
45
+ * The declaration a consumer dispatch reads: the LAST prior step that recorded one.
46
+ *
47
+ * "Last" rather than "first" because a run can design more than once — a companion that bounces
48
+ * the architect for rework re-runs it, and the rework's declaration is the current one. Reading
49
+ * the persisted STEP (rather than re-parsing outputs here) is what makes this survive a durable
50
+ * replay: the parse happened once, when the step settled.
51
+ *
52
+ * Returns `undefined` when no prior step declared anything at all, which the renderer states
53
+ * as "nothing was checked" — distinct from an empty selection, which is a design that ran and
54
+ * concluded no shared service applies.
55
+ */
56
+ export declare function declaredSelection(priorSteps: PipelineStep[]): FoundationalServiceSelection | undefined;
57
+ /**
58
+ * Read a settled design step's declaration out of the reply it just produced and record it on
59
+ * the step. Called by the engine when a step whose kind carries `foundational-catalog` finishes.
60
+ *
61
+ * Recorded even when the agent declared NOTHING (an empty selection), because that is a real
62
+ * and different answer from "no design step ran" — the two are what the consumer's index file
63
+ * distinguishes, and only a written row can tell them apart later.
64
+ *
65
+ * BEST-EFFORT: the declaration is enrichment on top of a step that already succeeded, so a
66
+ * catalog read that fails leaves the step unannotated (⇒ consumers read "nothing was checked")
67
+ * rather than failing a completed design.
68
+ */
69
+ export type FoundationalDeclarationRecorder = (workspaceId: string, step: PipelineStep,
70
+ /** The reply the job just returned. Read from the RESULT, not `step.output`, which the
71
+ * completion paths downstream of this hook have not assigned yet. */
72
+ output: string | undefined) => Promise<void>;
73
+ /**
74
+ * Bind a {@link FoundationalDeclarationRecorder} to the dispatcher's collaborators, so the
75
+ * completion hub calls one function instead of restating the trait check, the catalog read and
76
+ * the failure policy at its call site. An unwired catalog binds to a no-op.
77
+ */
78
+ export declare function createFoundationalDeclarationRecorder(deps: {
79
+ agentKindRegistry: AgentKindRegistry;
80
+ foundationalServiceResolver?: FoundationalServiceResolver;
81
+ logger?: Logger;
82
+ }): FoundationalDeclarationRecorder;
83
+ //# sourceMappingURL=run-foundational-services.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-foundational-services.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/run-foundational-services.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAM5D,OAAO,KAAK,EAAE,4BAA4B,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AACxF,OAAO,KAAK,EACV,SAAS,EACT,uBAAuB,EACvB,mBAAmB,EACnB,MAAM,EACP,MAAM,qBAAqB,CAAA;AAsB5B;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IAC1C,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,EAAE,CAAC,CAAA;IACnE;;;;;OAKG;IACH,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IACrD,eAAe,CACb,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,4BAA4B,GAAG,SAAS,GAClD,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAA;CAClC;AAED,MAAM,WAAW,+BAA+B;IAC9C,WAAW,EAAE,MAAM,CAAA;IACnB,6FAA6F;IAC7F,SAAS,EAAE,SAAS,CAAA;IACpB,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,oEAAoE;IACpE,UAAU,EAAE,YAAY,EAAE,CAAA;IAC1B,2BAA2B,CAAC,EAAE,2BAA2B,CAAA;IACzD,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,+BAA+B,GACrC,OAAO,CAAC,mBAAmB,EAAE,CAAC,CA8BhC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,YAAY,EAAE,GACzB,4BAA4B,GAAG,SAAS,CAM1C;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,+BAA+B,GAAG,CAC5C,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,YAAY;AAClB;sEACsE;AACtE,MAAM,EAAE,MAAM,GAAG,SAAS,KACvB,OAAO,CAAC,IAAI,CAAC,CAAA;AAElB;;;;GAIG;AACH,wBAAgB,qCAAqC,CAAC,IAAI,EAAE;IAC1D,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,2BAA2B,CAAC,EAAE,2BAA2B,CAAA;IACzD,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,GAAG,+BAA+B,CAelC"}
@@ -0,0 +1,76 @@
1
+ import { FOUNDATIONAL_CATALOG_TRAIT, FOUNDATIONAL_CONTRACTS_TRAIT, hasTrait, } from '@cat-factory/agents';
2
+ import { FOUNDATIONAL_CATALOG_FILE, noopLogger, parseFoundationalDeclaration, renderFoundationalCatalog, runBestEffort, } from '@cat-factory/kernel';
3
+ /**
4
+ * The `.cat-context/` files this dispatch gets from the foundational-services catalog:
5
+ *
6
+ * - a kind carrying `foundational-catalog` (the architect) gets the CATALOG — identity,
7
+ * capabilities and operation names for every registered service, no document bodies;
8
+ * - a kind carrying `foundational-contracts` (the researcher, the coder) gets the full API
9
+ * CONTRACTS, for exactly the ids a prior design step declared;
10
+ * - anything else gets nothing, and pays for nothing.
11
+ *
12
+ * BEST-EFFORT as a whole: the catalog is enrichment, and an unreachable store must not fail a
13
+ * run that would otherwise proceed exactly as it did before the feature existed. A failure is
14
+ * logged with its cause rather than swallowed.
15
+ */
16
+ export async function resolveFoundationalContext(input) {
17
+ const resolver = input.foundationalServiceResolver;
18
+ if (!resolver)
19
+ return [];
20
+ const { agentKind, agentKindRegistry } = input;
21
+ if (hasTrait(agentKind, FOUNDATIONAL_CATALOG_TRAIT, agentKindRegistry)) {
22
+ const files = await runBestEffort(input.logger ?? noopLogger, 'foundationalServices.catalog', async () => {
23
+ const catalog = await resolver.catalogFor(input.workspaceId);
24
+ // Rendered even when EMPTY: the catalog file then states that none are registered,
25
+ // which is the answer the design guidance asks the agent to act on. Omitting the file
26
+ // would leave the prompt pointing at a path that does not exist, which reads as a
27
+ // platform fault rather than as "there are none".
28
+ return [{ path: FOUNDATIONAL_CATALOG_FILE, content: renderFoundationalCatalog(catalog) }];
29
+ }, { workspaceId: input.workspaceId, agentKind });
30
+ return files ?? [];
31
+ }
32
+ if (hasTrait(agentKind, FOUNDATIONAL_CONTRACTS_TRAIT, agentKindRegistry)) {
33
+ const files = await runBestEffort(input.logger ?? noopLogger, 'foundationalServices.contracts', () => resolver.contextFilesFor(input.workspaceId, declaredSelection(input.priorSteps)), { workspaceId: input.workspaceId, agentKind });
34
+ return files ?? [];
35
+ }
36
+ return [];
37
+ }
38
+ /**
39
+ * The declaration a consumer dispatch reads: the LAST prior step that recorded one.
40
+ *
41
+ * "Last" rather than "first" because a run can design more than once — a companion that bounces
42
+ * the architect for rework re-runs it, and the rework's declaration is the current one. Reading
43
+ * the persisted STEP (rather than re-parsing outputs here) is what makes this survive a durable
44
+ * replay: the parse happened once, when the step settled.
45
+ *
46
+ * Returns `undefined` when no prior step declared anything at all, which the renderer states
47
+ * as "nothing was checked" — distinct from an empty selection, which is a design that ran and
48
+ * concluded no shared service applies.
49
+ */
50
+ export function declaredSelection(priorSteps) {
51
+ for (let i = priorSteps.length - 1; i >= 0; i--) {
52
+ const selection = priorSteps[i]?.foundationalServices;
53
+ if (selection)
54
+ return selection;
55
+ }
56
+ return undefined;
57
+ }
58
+ /**
59
+ * Bind a {@link FoundationalDeclarationRecorder} to the dispatcher's collaborators, so the
60
+ * completion hub calls one function instead of restating the trait check, the catalog read and
61
+ * the failure policy at its call site. An unwired catalog binds to a no-op.
62
+ */
63
+ export function createFoundationalDeclarationRecorder(deps) {
64
+ const resolver = deps.foundationalServiceResolver;
65
+ if (!resolver)
66
+ return async () => { };
67
+ return async (workspaceId, step, output) => {
68
+ if (!hasTrait(step.agentKind, FOUNDATIONAL_CATALOG_TRAIT, deps.agentKindRegistry))
69
+ return;
70
+ await runBestEffort(deps.logger ?? noopLogger, 'foundationalServices.recordDeclaration', async () => {
71
+ const known = await resolver.catalogIdsFor(workspaceId);
72
+ step.foundationalServices = parseFoundationalDeclaration(output, known);
73
+ }, { workspaceId, agentKind: step.agentKind });
74
+ };
75
+ }
76
+ //# sourceMappingURL=run-foundational-services.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-foundational-services.js","sourceRoot":"","sources":["../../../src/modules/execution/run-foundational-services.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import type { Block, ExecutionInstance } from '@cat-factory/kernel';
2
+ export interface RunStartDeps {
3
+ /** `ExecutionRepository.insertLive` — the atomic one-live-run-per-block claim. */
4
+ insertLive: (workspaceId: string, instance: ExecutionInstance, options: {
5
+ replaceId?: string;
6
+ }) => Promise<boolean>;
7
+ /** Hand the run to the durable runner (`WorkRunner.startRun`). */
8
+ startRun: (workspaceId: string, executionId: string) => Promise<void>;
9
+ /** Push the run to the SPA (`RunStateMachine.emitInstance`). */
10
+ emitInstance: (workspaceId: string, instance: ExecutionInstance) => Promise<void>;
11
+ /** Announce `run.started` outward (`RunStateMachine.publishRunStarted`). */
12
+ publishRunStarted: (workspaceId: string, instance: ExecutionInstance, block: Block | null | undefined) => Promise<void>;
13
+ }
14
+ /**
15
+ * Insert a freshly-built run, enforcing the one-live-run-per-block invariant at the DB in a single
16
+ * atomic write (see `ExecutionRepository.insertLive`). Callers must NOT `deleteByBlock` first:
17
+ * `insertLive` itself clears the block's terminal rows (and `replaceId`, the specific prior run a
18
+ * `retry`/`restart` is knowingly superseding) in the SAME transaction as the insert.
19
+ *
20
+ * A `false` return means a genuinely-concurrent start (double click, recurring-vs-manual,
21
+ * notification-vs-human retry) already created the block's live run — so we REFUSE this duplicate
22
+ * rather than materialise a second driver + container on the same branch. The winning run is
23
+ * untouched (the losing transaction only deletes terminal rows / its own `replaceId`, never the
24
+ * winner). Surfaces as a 409 the SPA shows as a toast.
25
+ *
26
+ * Nothing else belongs in here. This is the run's atomic claim, and an external call placed
27
+ * between it and the caller's block write is a fault that can strand a live run on a block never
28
+ * marked `in_progress` and never handed to a driver — see {@link handOffLiveRun}.
29
+ */
30
+ export declare function claimLiveRunOrConflict(deps: RunStartDeps, workspaceId: string, instance: ExecutionInstance, replaceId?: string): Promise<void>;
31
+ /**
32
+ * The ONE hand-off every start path ends with, once the run is claimed and the block committed:
33
+ * give the run to the durable runner, push it to the SPA, then announce `run.started` outward.
34
+ *
35
+ * The order is the point. The outbound announcement is LAST because it is the only step that
36
+ * leaves the deployment — the platform's rule is to commit local state first and run the external
37
+ * call behind it, so a slow or black-holing receiver costs the announcement and never the run.
38
+ *
39
+ * `run.started` is still exactly once per run: {@link claimLiveRunOrConflict} is what mints a live
40
+ * run, so a concurrent double-start has already lost by the time we get here. A start path added
41
+ * later inherits the announcement because skipping this funnel would also skip `startRun` — a run
42
+ * that never progresses, not an event that silently never fires. `retry`/`restartFrom` each mint a
43
+ * FRESH run id, so they announce genuinely new runs; otherwise a receiver would see `run.failed`
44
+ * for one id and later `run.completed` for another it never learned about.
45
+ *
46
+ * The block is threaded through because every caller already holds it — re-reading it here would
47
+ * be an extra round trip per run start (a NETWORK one on a mothership deployment).
48
+ */
49
+ export declare function handOffLiveRun(deps: RunStartDeps, workspaceId: string, instance: ExecutionInstance, block: Block | null | undefined): Promise<void>;
50
+ //# sourceMappingURL=runStart.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runStart.d.ts","sourceRoot":"","sources":["../../../src/modules/execution/runStart.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAgBnE,MAAM,WAAW,YAAY;IAC3B,kFAAkF;IAClF,UAAU,EAAE,CACV,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KAC5B,OAAO,CAAC,OAAO,CAAC,CAAA;IACrB,kEAAkE;IAClE,QAAQ,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACrE,gEAAgE;IAChE,YAAY,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACjF,4EAA4E;IAC5E,iBAAiB,EAAE,CACjB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,iBAAiB,EAC3B,KAAK,EAAE,KAAK,GAAG,IAAI,GAAG,SAAS,KAC5B,OAAO,CAAC,IAAI,CAAC,CAAA;CACnB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,YAAY,EAClB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAQf;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,YAAY,EAClB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,iBAAiB,EAC3B,KAAK,EAAE,KAAK,GAAG,IAAI,GAAG,SAAS,GAC9B,OAAO,CAAC,IAAI,CAAC,CAOf"}
@@ -0,0 +1,53 @@
1
+ import { ConflictError } from '@cat-factory/kernel';
2
+ /**
3
+ * Insert a freshly-built run, enforcing the one-live-run-per-block invariant at the DB in a single
4
+ * atomic write (see `ExecutionRepository.insertLive`). Callers must NOT `deleteByBlock` first:
5
+ * `insertLive` itself clears the block's terminal rows (and `replaceId`, the specific prior run a
6
+ * `retry`/`restart` is knowingly superseding) in the SAME transaction as the insert.
7
+ *
8
+ * A `false` return means a genuinely-concurrent start (double click, recurring-vs-manual,
9
+ * notification-vs-human retry) already created the block's live run — so we REFUSE this duplicate
10
+ * rather than materialise a second driver + container on the same branch. The winning run is
11
+ * untouched (the losing transaction only deletes terminal rows / its own `replaceId`, never the
12
+ * winner). Surfaces as a 409 the SPA shows as a toast.
13
+ *
14
+ * Nothing else belongs in here. This is the run's atomic claim, and an external call placed
15
+ * between it and the caller's block write is a fault that can strand a live run on a block never
16
+ * marked `in_progress` and never handed to a driver — see {@link handOffLiveRun}.
17
+ */
18
+ export async function claimLiveRunOrConflict(deps, workspaceId, instance, replaceId) {
19
+ const inserted = await deps.insertLive(workspaceId, instance, { replaceId });
20
+ if (!inserted) {
21
+ // No machine `reason`: this is a rare double-start edge, not a distinct client-handled
22
+ // conflict, so the human message drives the SPA's generic 409 toast (no new
23
+ // ConflictReason + exhaustive-Record/i18n cascade for a transient race).
24
+ throw new ConflictError('A run is already active for this block.');
25
+ }
26
+ }
27
+ /**
28
+ * The ONE hand-off every start path ends with, once the run is claimed and the block committed:
29
+ * give the run to the durable runner, push it to the SPA, then announce `run.started` outward.
30
+ *
31
+ * The order is the point. The outbound announcement is LAST because it is the only step that
32
+ * leaves the deployment — the platform's rule is to commit local state first and run the external
33
+ * call behind it, so a slow or black-holing receiver costs the announcement and never the run.
34
+ *
35
+ * `run.started` is still exactly once per run: {@link claimLiveRunOrConflict} is what mints a live
36
+ * run, so a concurrent double-start has already lost by the time we get here. A start path added
37
+ * later inherits the announcement because skipping this funnel would also skip `startRun` — a run
38
+ * that never progresses, not an event that silently never fires. `retry`/`restartFrom` each mint a
39
+ * FRESH run id, so they announce genuinely new runs; otherwise a receiver would see `run.failed`
40
+ * for one id and later `run.completed` for another it never learned about.
41
+ *
42
+ * The block is threaded through because every caller already holds it — re-reading it here would
43
+ * be an extra round trip per run start (a NETWORK one on a mothership deployment).
44
+ */
45
+ export async function handOffLiveRun(deps, workspaceId, instance, block) {
46
+ // Hand the run off to the durable runner so it progresses server-side without a browser open.
47
+ // With the no-op runner (tests) this does nothing and the run is advanced directly via
48
+ // advanceInstance.
49
+ await deps.startRun(workspaceId, instance.id);
50
+ await deps.emitInstance(workspaceId, instance);
51
+ await deps.publishRunStarted(workspaceId, instance, block);
52
+ }
53
+ //# sourceMappingURL=runStart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runStart.js","sourceRoot":"","sources":["../../../src/modules/execution/runStart.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAkCnD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,IAAkB,EAClB,WAAmB,EACnB,QAA2B,EAC3B,SAAkB;IAElB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,QAAQ,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;IAC5E,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,uFAAuF;QACvF,4EAA4E;QAC5E,yEAAyE;QACzE,MAAM,IAAI,aAAa,CAAC,yCAAyC,CAAC,CAAA;IACpE,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAkB,EAClB,WAAmB,EACnB,QAA2B,EAC3B,KAA+B;IAE/B,8FAA8F;IAC9F,uFAAuF;IACvF,mBAAmB;IACnB,MAAM,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAA;IAC7C,MAAM,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAA;IAC9C,MAAM,IAAI,CAAC,iBAAiB,CAAC,WAAW,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAA;AAC5D,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"KaizenService.d.ts","sourceRoot":"","sources":["../../../src/modules/kaizen/KaizenService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,eAAe,EACf,KAAK,EACL,uBAAuB,EACvB,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,uBAAuB,EACvB,cAAc,EACd,6BAA6B,EAE7B,uBAAuB,EACvB,aAAa,EACb,qBAAqB,EACrB,QAAQ,EAER,2BAA2B,EAC5B,MAAM,qBAAqB,CAAA;AAa5B,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,sDAAsD,CAAA;AAS5G,MAAM,WAAW,yBAAyB;IACxC,uBAAuB,EAAE,uBAAuB,CAAA;IAChD,6BAA6B,EAAE,6BAA6B,CAAA;IAC5D,eAAe,EAAE,eAAe,CAAA;IAChC,uBAAuB,EAAE,uBAAuB,CAAA;IAChD,6FAA6F;IAC7F,yBAAyB,EAAE,gCAAgC,CAAA;IAC3D,gFAAgF;IAChF,2BAA2B,CAAC,EAAE,2BAA2B,CAAA;IACzD,WAAW,EAAE,WAAW,CAAA;IACxB,KAAK,EAAE,KAAK,CAAA;IACZ,qFAAqF;IACrF,MAAM,CAAC,EAAE,uBAAuB,CAAA;IAChC,qFAAqF;IACrF,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;IAC7C,kFAAkF;IAClF,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,kFAAkF;IAClF,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,KAAK,QAAQ,GAAG,SAAS,CAAA;IACzE;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,OAAO,CAAA;IACvC,+EAA+E;IAC/E,4BAA4B,CAAC,EAAE,CAC7B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,MAAM,KACnB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;CACjC;AAED;;;;;;;;;;GAUG;AACH,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,yBAAyB,EAAI;IAEhE,qFAAqF;IACrF,IAAI,OAAO,IAAI,OAAO,CAErB;IAID;;;;OAIG;IACG,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6CpF;IAID;;;OAGG;IACG,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBpE;IAED,+FAA+F;IACzF,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA0E3E;IAID,8EAA8E;IACxE,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,SAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAM3E;IAED,8EAA8E;IAC9E,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAEnF;YAIa,aAAa;IAM3B,yFAAyF;IACzF,OAAO,CAAC,WAAW;YAIL,eAAe;YAef,YAAY;IAe1B;;;;;;OAMG;YACW,QAAQ;YAmBR,WAAW;YAaX,IAAI;YAWJ,IAAI;CAOnB"}
1
+ {"version":3,"file":"KaizenService.d.ts","sourceRoot":"","sources":["../../../src/modules/kaizen/KaizenService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,eAAe,EACf,KAAK,EACL,uBAAuB,EACvB,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,uBAAuB,EACvB,cAAc,EACd,6BAA6B,EAE7B,uBAAuB,EACvB,aAAa,EACb,qBAAqB,EACrB,QAAQ,EAER,2BAA2B,EAC5B,MAAM,qBAAqB,CAAA;AAa5B,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,sDAAsD,CAAA;AAS5G,MAAM,WAAW,yBAAyB;IACxC,uBAAuB,EAAE,uBAAuB,CAAA;IAChD,6BAA6B,EAAE,6BAA6B,CAAA;IAC5D,eAAe,EAAE,eAAe,CAAA;IAChC,uBAAuB,EAAE,uBAAuB,CAAA;IAChD,6FAA6F;IAC7F,yBAAyB,EAAE,gCAAgC,CAAA;IAC3D,gFAAgF;IAChF,2BAA2B,CAAC,EAAE,2BAA2B,CAAA;IACzD,WAAW,EAAE,WAAW,CAAA;IACxB,KAAK,EAAE,KAAK,CAAA;IACZ,qFAAqF;IACrF,MAAM,CAAC,EAAE,uBAAuB,CAAA;IAChC,qFAAqF;IACrF,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;IAC7C,kFAAkF;IAClF,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,kFAAkF;IAClF,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,KAAK,QAAQ,GAAG,SAAS,CAAA;IACzE;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,OAAO,CAAA;IACvC,+EAA+E;IAC/E,4BAA4B,CAAC,EAAE,CAC7B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,MAAM,KACnB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;CACjC;AAED;;;;;;;;;;GAUG;AACH,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,yBAAyB,EAAI;IAEhE,qFAAqF;IACrF,IAAI,OAAO,IAAI,OAAO,CAErB;IAID;;;;OAIG;IACG,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqDpF;IAID;;;OAGG;IACG,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBpE;IAED,+FAA+F;IACzF,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA0E3E;IAID,8EAA8E;IACxE,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,SAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAM3E;IAED,8EAA8E;IAC9E,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAEnF;YAIa,aAAa;IAM3B,yFAAyF;IACzF,OAAO,CAAC,WAAW;YAIL,eAAe;YAef,YAAY;IAe1B;;;;;;OAMG;YACW,QAAQ;YAmBR,WAAW;YAaX,IAAI;YAWJ,IAAI;CAOnB"}
@@ -45,11 +45,13 @@ export class KaizenService {
45
45
  continue;
46
46
  const model = step.model;
47
47
  const promptVersion = promptVersionForKind(step.agentKind);
48
- // `promptRevision` is the workspace's own prompt for this kind, pinned onto the step at
49
- // dispatch (absent ⇒ it ran the shipped prompt). Read off the STEP rather than the prompt
50
- // log, which is append-only: a later revision would otherwise re-key gradings of text the
51
- // step never saw.
52
- const comboKey = comboKeyFor(step.agentKind, model, promptVersion, step.promptRevision);
48
+ // Both prompt-text facts are read off the STEP, where the dispatch pinned them, rather than
49
+ // re-resolved here: the prompt log is append-only, so a later revision would re-key
50
+ // gradings of text the step never saw, and the variant registry can have moved on too.
51
+ // `promptVariant` is deliberately the PIN and not `stepOptions.agentVariantId` — the option
52
+ // is what the pipeline asked for, while the pin says what actually reached the prompt, and
53
+ // keying on the ask would credit a variant whose text a workspace override displaced.
54
+ const comboKey = comboKeyFor(step.agentKind, model, promptVersion, step.promptRevision, step.promptVariant);
53
55
  const combo = await this.deps.kaizenVerifiedComboRepository.getByKey(workspaceId, comboKey);
54
56
  if (isVerified(combo))
55
57
  continue;