@kontextmind/kxm 0.7.39 → 0.7.43
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.
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +41 -7
- package/docs/README.md +5 -3
- package/docs/agent-skills.md +1 -1
- package/docs/architecture.md +1 -1
- package/docs/configuration.md +28 -5
- package/docs/{vnext → contracts}/README.md +7 -7
- package/docs/{vnext → contracts}/architecture.md +2 -2
- package/docs/{vnext → contracts}/migration.md +25 -25
- package/docs/{vnext → contracts}/routing.md +2 -2
- package/docs/{vnext → contracts}/synchronization.md +1 -1
- package/docs/{vnext → contracts}/validation.md +7 -7
- package/docs/getting-started.md +1 -1
- package/docs/kb/qa-authentik-authentication.md +47 -0
- package/docs/kb/qa-extension-install-and-hub-bootstrap.md +68 -0
- package/docs/kb/qa-hub-on-a-public-host.md +31 -0
- package/docs/kb/qa-sqlite-vs-duckdb.md +18 -0
- package/docs/kb/qa-what-the-hub-stores.md +47 -0
- package/docs/packages.md +91 -0
- package/docs/templates/architecture.md +1 -1
- package/docs/test-matrix.md +6 -6
- package/docs/tui-components.md +131 -0
- package/examples/README.md +2 -2
- package/examples/{vnext → project}/.kxm/agents/critic-3.yaml +1 -1
- package/examples/{vnext → project}/README.md +4 -4
- package/package.json +18 -8
- package/packages/core/tui/CHANGELOG.md +19 -0
- package/packages/core/tui/LICENSE +21 -0
- package/packages/core/tui/README.md +45 -0
- package/packages/core/tui/dist/index.js +1439 -0
- package/packages/core/tui/src/adapters/pi.ts +73 -0
- package/packages/core/tui/src/adapters/terminal.ts +106 -0
- package/packages/core/tui/src/exports/index.ts +30 -0
- package/packages/core/tui/src/services/registry.ts +274 -0
- package/packages/core/tui/src/tui/keys.ts +130 -0
- package/packages/core/tui/src/tui/layout.ts +117 -0
- package/packages/core/tui/src/tui/panel.ts +435 -0
- package/packages/core/tui/src/tui/panelComponent.ts +208 -0
- package/packages/core/tui/src/tui/render.ts +309 -0
- package/packages/core/tui/src/tui/theme.ts +145 -0
- package/packages/core/tui/src/types/surface.ts +407 -0
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/cli.js +681 -553
- package/plugins/kxm/dist/extension.js +18 -18
- package/plugins/kxm/dist/mcp-server.js +1 -1
- package/plugins/kxm/dist/{vnext-runtime-supervisor.js → runtime-supervisor.js} +553 -553
- package/plugins/kxm/dist/runtime.js +608 -608
- package/plugins/kxm/dist/server.js +13 -13
- package/plugins/kxm/package.json +2 -2
- package/plugins/kxm/skills/kxm-project-setup/SKILL.md +2 -2
- package/plugins/kxm/skills/kxm-runs/SKILL.md +3 -3
- package/plugins/kxm/skills/kxm-session/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-workflow/SKILL.md +1 -1
- package/plugins/kxm/src/autocomplete.ts +4 -4
- package/plugins/kxm/src/{vnext-bindings.ts → bindings.ts} +48 -48
- package/plugins/kxm/src/cli/hub.ts +3 -3
- package/plugins/kxm/src/cli/{vnext.ts → project.ts} +106 -106
- package/plugins/kxm/src/cli/roles.ts +9 -9
- package/plugins/kxm/src/cli/system.ts +2 -2
- package/plugins/kxm/src/cli/tasks.ts +8 -8
- package/plugins/kxm/src/cli/workflows.ts +8 -8
- package/plugins/kxm/src/cli.ts +47 -47
- package/plugins/kxm/src/config.ts +69 -14
- package/plugins/kxm/src/database.ts +4 -4
- package/plugins/kxm/src/{vnext-engine-artifacts.ts → engine-artifacts.ts} +7 -7
- package/plugins/kxm/src/{vnext-engine-command.ts → engine-command.ts} +40 -40
- package/plugins/kxm/src/{vnext-engine-compile.ts → engine-compile.ts} +64 -64
- package/plugins/kxm/src/{vnext-engine-evidence.ts → engine-evidence.ts} +26 -26
- package/plugins/kxm/src/{vnext-engine-fold.ts → engine-fold.ts} +99 -99
- package/plugins/kxm/src/{vnext-engine-gate-records.ts → engine-gate-records.ts} +105 -105
- package/plugins/kxm/src/{vnext-engine-plan.ts → engine-plan.ts} +69 -69
- package/plugins/kxm/src/{vnext-engine.ts → engine.ts} +502 -502
- package/plugins/kxm/src/gate-hash.ts +10 -0
- package/plugins/kxm/src/{vnext-harness.ts → harness.ts} +1 -1
- package/plugins/kxm/src/hub.ts +1 -1
- package/plugins/kxm/src/init-guide-setup.ts +3 -3
- package/plugins/kxm/src/{vnext-init.ts → init.ts} +93 -93
- package/plugins/kxm/src/kxm-install-kind.ts +1 -1
- package/plugins/kxm/src/kxm-update-config.ts +2 -2
- package/plugins/kxm/src/local-snapshot.ts +23 -23
- package/plugins/kxm/src/mcp-server.ts +1 -1
- package/plugins/kxm/src/{vnext-migrate.ts → migrate.ts} +123 -123
- package/plugins/kxm/src/model-inventory.ts +1 -1
- package/plugins/kxm/src/{vnext-oneshot-evidence.ts → oneshot-evidence.ts} +2 -2
- package/plugins/kxm/src/{vnext-oneshot-process.ts → oneshot-process.ts} +4 -4
- package/plugins/kxm/src/{vnext-oneshot-producer.ts → oneshot-producer.ts} +24 -24
- package/plugins/kxm/src/{vnext-permission.ts → permission.ts} +86 -86
- package/plugins/kxm/src/{vnext-pi-producer.ts → pi-producer.ts} +13 -13
- package/plugins/kxm/src/{vnext-config.ts → project-config.ts} +177 -177
- package/plugins/kxm/src/{vnext-repair.ts → repair.ts} +159 -159
- package/plugins/kxm/src/restricted-yaml.d.mts +3 -3
- package/plugins/kxm/src/restricted-yaml.mjs +4 -4
- package/plugins/kxm/src/{vnext-runtime-owner.ts → runtime-owner.ts} +35 -35
- package/plugins/kxm/src/{vnext-runtime.ts → runtime-service.ts} +136 -136
- package/plugins/kxm/src/{vnext-runtime-store.ts → runtime-store.ts} +145 -145
- package/plugins/kxm/src/{vnext-runtime-supervisor.ts → runtime-supervisor.ts} +80 -80
- package/plugins/kxm/src/runtime.ts +6 -6
- package/plugins/kxm/src/session-work.ts +3 -3
- package/plugins/kxm/src/studio-layout.ts +6 -6
- package/plugins/kxm/src/{vnext-template.ts → template.ts} +33 -33
- package/plugins/kxm/src/tui.ts +10 -24
- package/schemas/{vnext/README.md → README.md} +3 -3
- package/schemas/{vnext/agent.schema.json → agent.schema.json} +1 -1
- package/schemas/{vnext/assignment-result.schema.json → assignment-result.schema.json} +1 -1
- package/schemas/{vnext/backup-manifest.schema.json → backup-manifest.schema.json} +1 -1
- package/schemas/{vnext/candidate.schema.json → candidate.schema.json} +1 -1
- package/schemas/{vnext/common.schema.json → common.schema.json} +2 -2
- package/schemas/{vnext/context-candidate.schema.json → context-candidate.schema.json} +1 -1
- package/schemas/{vnext/context-packet.schema.json → context-packet.schema.json} +1 -1
- package/schemas/{vnext/delivery-manifest.schema.json → delivery-manifest.schema.json} +1 -1
- package/schemas/{vnext/drive-receipt.schema.json → drive-receipt.schema.json} +2 -2
- package/schemas/{vnext/environment.schema.json → environment.schema.json} +1 -1
- package/schemas/{vnext/gate-registry.schema.json → gate-registry.schema.json} +1 -1
- package/schemas/{vnext/handoff-manifest.schema.json → handoff-manifest.schema.json} +1 -1
- package/schemas/{vnext/init-operation.schema.json → init-operation.schema.json} +1 -1
- package/schemas/{vnext/local-repository-bindings.schema.json → local-repository-bindings.schema.json} +1 -1
- package/schemas/{vnext/memory-record.schema.json → memory-record.schema.json} +1 -1
- package/schemas/{vnext/migration-decision.schema.json → migration-decision.schema.json} +1 -1
- package/schemas/{vnext/migration-plan.schema.json → migration-plan.schema.json} +1 -1
- package/schemas/{vnext/migration-receipt.schema.json → migration-receipt.schema.json} +1 -1
- package/schemas/{vnext/model.schema.json → model.schema.json} +1 -1
- package/schemas/{vnext/modes.schema.json → modes.schema.json} +1 -1
- package/schemas/{vnext/permission-diff.schema.json → permission-diff.schema.json} +1 -1
- package/schemas/policy-draft/README.md +2 -2
- package/schemas/{vnext/prices.schema.json → prices.schema.json} +1 -1
- package/schemas/{vnext/project.schema.json → project.schema.json} +1 -1
- package/schemas/{vnext/repository.schema.json → repository.schema.json} +1 -1
- package/schemas/{vnext/role.schema.json → role.schema.json} +1 -1
- package/schemas/{vnext/run-event.schema.json → run-event.schema.json} +1 -1
- package/schemas/{vnext/session-brief.schema.json → session-brief.schema.json} +2 -2
- package/schemas/{vnext/sync-event.schema.json → sync-event.schema.json} +1 -1
- package/schemas/{vnext/template-provenance.schema.json → template-provenance.schema.json} +1 -1
- package/schemas/{vnext/workflow.schema.json → workflow.schema.json} +1 -1
- package/scripts/build-package.mjs +59 -0
- package/scripts/build-runtime.mjs +3 -2
- package/scripts/check-generated.mjs +2 -1
- package/scripts/check-versions.mjs +12 -1
- package/scripts/docker-install-smoke.mjs +268 -0
- package/scripts/emit-codex-artifacts.mjs +1 -1
- package/scripts/kxm-bump-version.mjs +53 -3
- package/scripts/kxm-runtime-supervisor.mjs +3 -3
- package/scripts/package-surfaces.mjs +39 -0
- package/scripts/roster-policy.mjs +1 -1
- package/plugins/kxm/src/vnext-gate-hash.ts +0 -10
- /package/docs/{vnext → contracts}/effects-and-recovery.md +0 -0
- /package/docs/{vnext → contracts}/lifecycles.md +0 -0
- /package/docs/{vnext → contracts}/terminology.md +0 -0
- /package/examples/{vnext → project}/.kxm/agents/coordinator.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/agents/critic-1.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/agents/critic-2.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/agents/implementer.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/agents/planner.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/agents/reproducer.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/agents/reviewer.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/gates.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/models/critic-claude.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/models/critic-gemini.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/models/critic-grok.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/models/implementation.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/models/primary.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/prices.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/project/env.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/project.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/repo/repo.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/workflows/default.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/workflows/fix.yaml +0 -0
- /package/examples/{vnext → project}/.kxm/workflows/improve.yaml +0 -0
- /package/examples/{vnext → project}/records/assignment-result-recorded.json +0 -0
- /package/examples/{vnext → project}/records/assignment-result.json +0 -0
- /package/examples/{vnext → project}/records/context-candidate.json +0 -0
- /package/examples/{vnext → project}/records/delivery-manifest.json +0 -0
- /package/examples/{vnext → project}/records/effect-uncertainty-resolved-sync.json +0 -0
- /package/examples/{vnext → project}/records/effect-uncertainty-resolved.json +0 -0
- /package/examples/{vnext → project}/records/run-created.json +0 -0
- /package/examples/{vnext → project}/records/sync-event.json +0 -0
- /package/examples/{vnext → project}/repositories/api/.kxm/repo/env.yaml +0 -0
- /package/examples/{vnext → project}/repositories/api/.kxm/repo/repo.yaml +0 -0
- /package/examples/{vnext → project}/repositories/web/.kxm/repo/repo.yaml +0 -0
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { KxmCompiledPlan, KxmCompiledStep, KxmCompiledTransition, KxmTerminalStatus } from "./engine-compile.ts";
|
|
2
2
|
import {
|
|
3
3
|
runtimeError,
|
|
4
|
-
type
|
|
5
|
-
type
|
|
6
|
-
type
|
|
7
|
-
} from "./
|
|
4
|
+
type KxmRunEvent,
|
|
5
|
+
type KxmRunRecord,
|
|
6
|
+
type KxmRunStatus,
|
|
7
|
+
} from "./runtime-store.ts";
|
|
8
8
|
|
|
9
|
-
export const
|
|
9
|
+
export const KXM_RUN_STATE_SCHEMA = "kxm.run-state.v2";
|
|
10
10
|
export const FOLD_PANEL_BOUND = 1;
|
|
11
11
|
|
|
12
|
-
const RUN_STATUSES = new Set<
|
|
13
|
-
const TERMINAL_RUN = new Set<
|
|
12
|
+
const RUN_STATUSES = new Set<KxmRunStatus>(["created", "preparing", "running", "waiting", "blocked_uncertain", "cancelling", "cancelled", "completed", "failed"]);
|
|
13
|
+
const TERMINAL_RUN = new Set<KxmRunStatus>(["cancelled", "completed", "failed"]);
|
|
14
14
|
const STEP_STATUSES = new Set(["pending", "preparing", "running", "passed", "failed", "cancelled"]);
|
|
15
15
|
const ASSIGNMENT_STATUSES = new Set(["created", "accepted", "dispatched", "executing", "result_recorded", "terminal"]);
|
|
16
16
|
const ATTEMPT_STATUSES = new Set(["created", "starting", "executing", "settling", "terminal"]);
|
|
17
17
|
const RESULT_CLASSES = new Set(["outcome", "outcome_unknown", "producer_rejected", "cancelled"]);
|
|
18
|
-
const SLICE_BLOCKED_RUN = new Set<
|
|
19
|
-
const RUN_EDGES: Readonly<Record<string, ReadonlySet<
|
|
18
|
+
const SLICE_BLOCKED_RUN = new Set<KxmRunStatus>(["waiting"]);
|
|
19
|
+
const RUN_EDGES: Readonly<Record<string, ReadonlySet<KxmRunStatus>>> = {
|
|
20
20
|
created: new Set(["preparing", "cancelled", "failed"]),
|
|
21
21
|
preparing: new Set(["running", "cancelled", "failed"]),
|
|
22
22
|
running: new Set(["blocked_uncertain", "cancelling", "cancelled", "completed", "failed"]),
|
|
@@ -46,7 +46,7 @@ const ATTEMPT_EDGES: Readonly<Record<string, ReadonlySet<string>>> = {
|
|
|
46
46
|
settling: new Set(["terminal"]),
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
-
export type
|
|
49
|
+
export type KxmRunEffectState =
|
|
50
50
|
| "intent"
|
|
51
51
|
| "dispatched"
|
|
52
52
|
| "observed-complete"
|
|
@@ -56,7 +56,7 @@ export type VnextRunEffectState =
|
|
|
56
56
|
| "settled"
|
|
57
57
|
| "settled-proof";
|
|
58
58
|
|
|
59
|
-
export interface
|
|
59
|
+
export interface KxmFoldOptions {
|
|
60
60
|
readonly observationLookup?: (
|
|
61
61
|
attemptId: string,
|
|
62
62
|
observationId: string,
|
|
@@ -67,17 +67,17 @@ export interface VnextFoldOptions {
|
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
export type
|
|
70
|
+
export type KxmRunDurationBudgetSource = "workflow" | "project" | "both";
|
|
71
71
|
|
|
72
|
-
export interface
|
|
72
|
+
export interface KxmRunDurationBudget {
|
|
73
73
|
readonly budgetMs: number;
|
|
74
|
-
readonly source:
|
|
74
|
+
readonly source: KxmRunDurationBudgetSource;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
export function effectiveRunDurationBudget(
|
|
78
78
|
planLimits: { readonly maxRunDurationMs?: number } | undefined,
|
|
79
79
|
projectLimits: { readonly maxRunDurationMs?: number } | undefined,
|
|
80
|
-
):
|
|
80
|
+
): KxmRunDurationBudget | undefined {
|
|
81
81
|
const workflow = planLimits?.maxRunDurationMs;
|
|
82
82
|
const project = projectLimits?.maxRunDurationMs;
|
|
83
83
|
if (workflow === undefined && project === undefined) return undefined;
|
|
@@ -88,42 +88,42 @@ export function effectiveRunDurationBudget(
|
|
|
88
88
|
return { budgetMs: project!, source: "project" };
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
export interface
|
|
91
|
+
export interface KxmFoldAttemptState {
|
|
92
92
|
readonly status: string;
|
|
93
93
|
readonly resultClass?: string | undefined;
|
|
94
94
|
readonly outcome?: string | undefined;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
export interface
|
|
97
|
+
export interface KxmFoldAssignmentState {
|
|
98
98
|
readonly status: string;
|
|
99
99
|
readonly currentAttemptId?: string | undefined;
|
|
100
|
-
readonly attempts: Readonly<Record<string,
|
|
100
|
+
readonly attempts: Readonly<Record<string, KxmFoldAttemptState>>;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
export interface
|
|
103
|
+
export interface KxmFoldPanel {
|
|
104
104
|
readonly order: readonly string[];
|
|
105
|
-
readonly assignments: Readonly<Record<string,
|
|
105
|
+
readonly assignments: Readonly<Record<string, KxmFoldAssignmentState>>;
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
export type
|
|
108
|
+
export type KxmJoinAllResult =
|
|
109
109
|
| { readonly tag: "unsatisfied" }
|
|
110
110
|
| { readonly tag: "outcome"; readonly outcome: string }
|
|
111
111
|
| { readonly tag: "conflict" }
|
|
112
112
|
| { readonly tag: "rejected" }
|
|
113
113
|
| { readonly tag: "cancelled" };
|
|
114
114
|
|
|
115
|
-
export interface
|
|
115
|
+
export interface KxmRunCurrentStep {
|
|
116
116
|
readonly stepId: string;
|
|
117
117
|
readonly stepAttempt: number;
|
|
118
118
|
readonly status: string;
|
|
119
|
-
readonly panel:
|
|
119
|
+
readonly panel: KxmFoldPanel;
|
|
120
120
|
readonly assignmentId?: string | undefined;
|
|
121
121
|
readonly attemptId?: string | undefined;
|
|
122
122
|
readonly assignmentStatus?: string | undefined;
|
|
123
123
|
readonly attemptStatus?: string | undefined;
|
|
124
124
|
readonly outcome?: string | undefined;
|
|
125
125
|
readonly effectId?: string | undefined;
|
|
126
|
-
readonly effectState?:
|
|
126
|
+
readonly effectState?: KxmRunEffectState | undefined;
|
|
127
127
|
readonly observationId?: string | undefined;
|
|
128
128
|
readonly observationHash?: string | undefined;
|
|
129
129
|
readonly observationCompleteness?: "complete" | "no-start" | "unknown" | undefined;
|
|
@@ -131,26 +131,26 @@ export interface VnextRunCurrentStep {
|
|
|
131
131
|
readonly evidenceRefs?: readonly { id: string; kind: string; hash: string; status: string }[] | undefined;
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
export interface
|
|
134
|
+
export interface KxmRunDriveBinding {
|
|
135
135
|
readonly driveId: string;
|
|
136
136
|
readonly mode: "simulated" | "live";
|
|
137
137
|
readonly openedSequence: number;
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
export interface
|
|
141
|
-
readonly schema: typeof
|
|
140
|
+
export interface KxmRunState {
|
|
141
|
+
readonly schema: typeof KXM_RUN_STATE_SCHEMA;
|
|
142
142
|
readonly runId: string;
|
|
143
|
-
readonly status:
|
|
143
|
+
readonly status: KxmRunStatus;
|
|
144
144
|
readonly runPlanHash?: string | undefined;
|
|
145
145
|
readonly pendingStepId?: string | undefined;
|
|
146
|
-
readonly currentStep?:
|
|
146
|
+
readonly currentStep?: KxmRunCurrentStep | undefined;
|
|
147
147
|
readonly stepAttempts: Readonly<Record<string, number>>;
|
|
148
148
|
readonly edgeTransitions: Readonly<Record<string, number>>;
|
|
149
149
|
readonly transitionsUsed: number;
|
|
150
150
|
readonly cancelRequested: boolean;
|
|
151
151
|
readonly terminalReason?: string | undefined;
|
|
152
152
|
readonly failureReason?: string | undefined;
|
|
153
|
-
readonly drive?:
|
|
153
|
+
readonly drive?: KxmRunDriveBinding | undefined;
|
|
154
154
|
readonly runningSince?: string | undefined;
|
|
155
155
|
}
|
|
156
156
|
|
|
@@ -178,7 +178,7 @@ interface MutableCurrentStep {
|
|
|
178
178
|
panel: MutablePanel;
|
|
179
179
|
outcome?: string | undefined;
|
|
180
180
|
effectId?: string | undefined;
|
|
181
|
-
effectState?:
|
|
181
|
+
effectState?: KxmRunEffectState | undefined;
|
|
182
182
|
observationId?: string | undefined;
|
|
183
183
|
observationHash?: string | undefined;
|
|
184
184
|
observationCompleteness?: "complete" | "no-start" | "unknown" | undefined;
|
|
@@ -187,9 +187,9 @@ interface MutableCurrentStep {
|
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
interface MutableState {
|
|
190
|
-
schema: typeof
|
|
190
|
+
schema: typeof KXM_RUN_STATE_SCHEMA;
|
|
191
191
|
runId: string;
|
|
192
|
-
status:
|
|
192
|
+
status: KxmRunStatus;
|
|
193
193
|
runPlanHash?: string | undefined;
|
|
194
194
|
pendingStepId?: string | undefined;
|
|
195
195
|
currentStep?: MutableCurrentStep | undefined;
|
|
@@ -202,8 +202,8 @@ interface MutableState {
|
|
|
202
202
|
lastOutcomeEvent?: { stepId: string; stepAttempt: number; outcome: string } | undefined;
|
|
203
203
|
awaitingTransition: boolean;
|
|
204
204
|
cancelCommandId?: string | undefined;
|
|
205
|
-
lastTerminalTransition?:
|
|
206
|
-
drive?:
|
|
205
|
+
lastTerminalTransition?: KxmTerminalStatus | undefined;
|
|
206
|
+
drive?: KxmRunDriveBinding | undefined;
|
|
207
207
|
runningSince?: string | undefined;
|
|
208
208
|
}
|
|
209
209
|
|
|
@@ -230,10 +230,10 @@ function panelAttempt(current: MutableCurrentStep): MutableAttempt | undefined {
|
|
|
230
230
|
return attemptId ? assignment.attempts[attemptId] : undefined;
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
-
export function
|
|
234
|
-
step:
|
|
233
|
+
export function kxmFoldPanelAttempt(
|
|
234
|
+
step: KxmRunCurrentStep | MutableCurrentStep | undefined,
|
|
235
235
|
attemptId: string,
|
|
236
|
-
): { assignmentId: string; assignment: MutableAssignment |
|
|
236
|
+
): { assignmentId: string; assignment: MutableAssignment | KxmFoldAssignmentState; attempt: MutableAttempt | KxmFoldAttemptState } | undefined {
|
|
237
237
|
if (!step) return undefined;
|
|
238
238
|
for (const assignmentId of step.panel.order) {
|
|
239
239
|
const assignment = step.panel.assignments[assignmentId];
|
|
@@ -255,7 +255,7 @@ function findPanelAttempt(
|
|
|
255
255
|
return undefined;
|
|
256
256
|
}
|
|
257
257
|
|
|
258
|
-
function panelAssignmentBound(plan:
|
|
258
|
+
function panelAssignmentBound(plan: KxmCompiledPlan | undefined, current: MutableCurrentStep): number {
|
|
259
259
|
const step = plan?.steps[current.stepId];
|
|
260
260
|
if (!step) return FOLD_PANEL_BOUND;
|
|
261
261
|
if ((step.kind === "agent" || step.kind === "moa") && (step.join.strategy === "all" || step.join.strategy === "all-settled")) {
|
|
@@ -303,7 +303,7 @@ function panelFrozen(current: MutableCurrentStep): boolean {
|
|
|
303
303
|
|| current.status === "cancelled";
|
|
304
304
|
}
|
|
305
305
|
|
|
306
|
-
function createdOnlySingletonCancel(state: MutableState, step:
|
|
306
|
+
function createdOnlySingletonCancel(state: MutableState, step: KxmCompiledStep, current: MutableCurrentStep, status: string): boolean {
|
|
307
307
|
const assignmentId = current.panel.order[0];
|
|
308
308
|
const assignment = assignmentId ? current.panel.assignments[assignmentId] : undefined;
|
|
309
309
|
return status === "cancelled"
|
|
@@ -313,7 +313,7 @@ function createdOnlySingletonCancel(state: MutableState, step: VnextCompiledStep
|
|
|
313
313
|
&& assignment?.status === "created";
|
|
314
314
|
}
|
|
315
315
|
|
|
316
|
-
function authorizedCancelStep(state: MutableState, step:
|
|
316
|
+
function authorizedCancelStep(state: MutableState, step: KxmCompiledStep, current: MutableCurrentStep, status: string): boolean {
|
|
317
317
|
if (status !== "cancelled" || !state.cancelRequested) return false;
|
|
318
318
|
if (createdOnlySingletonCancel(state, step, current, status)) return true;
|
|
319
319
|
if (!panelIssuedAttemptsTerminal(current) || !panelAssignmentsTerminal(current)) return false;
|
|
@@ -349,14 +349,14 @@ function currentAttemptOf(assignment: {
|
|
|
349
349
|
return attemptId ? assignment.attempts[attemptId] : undefined;
|
|
350
350
|
}
|
|
351
351
|
|
|
352
|
-
function expectedStatusForDeclaredOutcome(step:
|
|
352
|
+
function expectedStatusForDeclaredOutcome(step: KxmCompiledStep, outcome: string): "passed" | "failed" | "cancelled" {
|
|
353
353
|
// Classify by outcome name only, never terminal target
|
|
354
354
|
if (outcome === "passed") return "passed";
|
|
355
355
|
if (outcome === "cancelled") return "cancelled";
|
|
356
356
|
return "failed";
|
|
357
357
|
}
|
|
358
358
|
|
|
359
|
-
export function
|
|
359
|
+
export function kxmJoinAll(step: KxmCompiledStep, panel: KxmFoldPanel | MutablePanel): KxmJoinAllResult {
|
|
360
360
|
if (panel.order.length < step.assignments.minimum) return { tag: "unsatisfied" };
|
|
361
361
|
const members: Array<{ resultClass: string; outcome?: string | undefined }> = [];
|
|
362
362
|
for (const assignmentId of panel.order) {
|
|
@@ -414,7 +414,7 @@ function putAssignment(current: MutableCurrentStep, assignmentId: string, assign
|
|
|
414
414
|
};
|
|
415
415
|
}
|
|
416
416
|
|
|
417
|
-
export function
|
|
417
|
+
export function kxmFoldPanelAttemptIds(step: KxmRunCurrentStep | MutableCurrentStep | undefined): string[] {
|
|
418
418
|
if (!step) return [];
|
|
419
419
|
const ids: string[] = [];
|
|
420
420
|
for (const assignmentId of step.panel.order) {
|
|
@@ -425,17 +425,17 @@ export function vnextFoldPanelAttemptIds(step: VnextRunCurrentStep | MutableCurr
|
|
|
425
425
|
return ids;
|
|
426
426
|
}
|
|
427
427
|
|
|
428
|
-
export function
|
|
429
|
-
run:
|
|
430
|
-
plan:
|
|
431
|
-
events: readonly
|
|
432
|
-
options:
|
|
433
|
-
):
|
|
428
|
+
export function foldKxmRunState(
|
|
429
|
+
run: KxmRunRecord,
|
|
430
|
+
plan: KxmCompiledPlan | undefined,
|
|
431
|
+
events: readonly KxmRunEvent[],
|
|
432
|
+
options: KxmFoldOptions = {},
|
|
433
|
+
): KxmRunState {
|
|
434
434
|
if (events.length === 0) {
|
|
435
435
|
throw runtimeError("run_events_illegal", run.runId, "run has no events");
|
|
436
436
|
}
|
|
437
437
|
const state: MutableState = {
|
|
438
|
-
schema:
|
|
438
|
+
schema: KXM_RUN_STATE_SCHEMA,
|
|
439
439
|
runId: run.runId,
|
|
440
440
|
status: "created",
|
|
441
441
|
stepAttempts: Object.create(null) as Record<string, number>,
|
|
@@ -563,7 +563,7 @@ export function foldVnextRunState(
|
|
|
563
563
|
return freezeState(state);
|
|
564
564
|
}
|
|
565
565
|
|
|
566
|
-
function assertEventIdentity(run:
|
|
566
|
+
function assertEventIdentity(run: KxmRunRecord, event: KxmRunEvent): void {
|
|
567
567
|
if (event.schema !== "kxm.run-event.v1") {
|
|
568
568
|
throw runtimeError("run_events_illegal", run.runId, "event schema is not kxm.run-event.v1");
|
|
569
569
|
}
|
|
@@ -580,7 +580,7 @@ function assertEventIdentity(run: VnextRunRecord, event: VnextRunEvent): void {
|
|
|
580
580
|
}
|
|
581
581
|
}
|
|
582
582
|
|
|
583
|
-
function foldRunCreated(state: MutableState, run:
|
|
583
|
+
function foldRunCreated(state: MutableState, run: KxmRunRecord, event: KxmRunEvent, index: number): void {
|
|
584
584
|
if (index !== 0 || event.sequence !== 1) {
|
|
585
585
|
throw runtimeError("run_events_illegal", state.runId, "run.created is only legal at sequence 1");
|
|
586
586
|
}
|
|
@@ -593,12 +593,12 @@ function foldRunCreated(state: MutableState, run: VnextRunRecord, event: VnextRu
|
|
|
593
593
|
state.status = "created";
|
|
594
594
|
}
|
|
595
595
|
|
|
596
|
-
function foldRunStatus(state: MutableState, plan:
|
|
596
|
+
function foldRunStatus(state: MutableState, plan: KxmCompiledPlan | undefined, event: KxmRunEvent): void {
|
|
597
597
|
const next = event.payload.status;
|
|
598
|
-
if (typeof next !== "string" || !RUN_STATUSES.has(next as
|
|
598
|
+
if (typeof next !== "string" || !RUN_STATUSES.has(next as KxmRunStatus)) {
|
|
599
599
|
throw runtimeError("run_events_illegal", state.runId, `run.status_changed has invalid status ${String(next)}`);
|
|
600
600
|
}
|
|
601
|
-
const status = next as
|
|
601
|
+
const status = next as KxmRunStatus;
|
|
602
602
|
if (SLICE_BLOCKED_RUN.has(status)) {
|
|
603
603
|
throw runtimeError("run_events_illegal", state.runId, `event type ${event.eventType} is not legal in this engine slice`);
|
|
604
604
|
}
|
|
@@ -649,9 +649,9 @@ function foldRunStatus(state: MutableState, plan: VnextCompiledPlan | undefined,
|
|
|
649
649
|
|
|
650
650
|
function assertTerminalRunStatus(
|
|
651
651
|
state: MutableState,
|
|
652
|
-
plan:
|
|
653
|
-
status:
|
|
654
|
-
event:
|
|
652
|
+
plan: KxmCompiledPlan | undefined,
|
|
653
|
+
status: KxmRunStatus,
|
|
654
|
+
event: KxmRunEvent,
|
|
655
655
|
): void {
|
|
656
656
|
if (status === "completed") {
|
|
657
657
|
if (state.lastTerminalTransition !== "completed") {
|
|
@@ -699,7 +699,7 @@ function assertTerminalRunStatus(
|
|
|
699
699
|
}
|
|
700
700
|
}
|
|
701
701
|
|
|
702
|
-
function isProvenFailure(state: MutableState, plan:
|
|
702
|
+
function isProvenFailure(state: MutableState, plan: KxmCompiledPlan | undefined): boolean {
|
|
703
703
|
const current = state.currentStep;
|
|
704
704
|
if (current) {
|
|
705
705
|
const stepTerminal = current.status === "passed" || current.status === "failed" || current.status === "cancelled";
|
|
@@ -707,7 +707,7 @@ function isProvenFailure(state: MutableState, plan: VnextCompiledPlan | undefine
|
|
|
707
707
|
if (stepTerminal && settled) {
|
|
708
708
|
const step = plan?.steps[current.stepId];
|
|
709
709
|
if (step && current.status === "failed") {
|
|
710
|
-
const joined =
|
|
710
|
+
const joined = kxmJoinAll(step, current.panel);
|
|
711
711
|
if (joined.tag === "rejected" || joined.tag === "conflict") return true;
|
|
712
712
|
}
|
|
713
713
|
if (plan && current.outcome) {
|
|
@@ -734,7 +734,7 @@ function isProvenFailure(state: MutableState, plan: VnextCompiledPlan | undefine
|
|
|
734
734
|
return Boolean(step && used >= step.maxAttempts);
|
|
735
735
|
}
|
|
736
736
|
|
|
737
|
-
function foldDriveOpened(state: MutableState, event:
|
|
737
|
+
function foldDriveOpened(state: MutableState, event: KxmRunEvent): void {
|
|
738
738
|
if (state.status !== "running" && state.status !== "blocked_uncertain") {
|
|
739
739
|
throw runtimeError("run_events_illegal", state.runId, "run.drive_opened is only legal while running or blocked_uncertain");
|
|
740
740
|
}
|
|
@@ -748,9 +748,9 @@ function foldDriveOpened(state: MutableState, event: VnextRunEvent): void {
|
|
|
748
748
|
|
|
749
749
|
function foldCancelRequested(
|
|
750
750
|
state: MutableState,
|
|
751
|
-
event:
|
|
752
|
-
plan:
|
|
753
|
-
options:
|
|
751
|
+
event: KxmRunEvent,
|
|
752
|
+
plan: KxmCompiledPlan | undefined,
|
|
753
|
+
options: KxmFoldOptions,
|
|
754
754
|
): void {
|
|
755
755
|
if (state.cancelRequested || TERMINAL_RUN.has(state.status)) {
|
|
756
756
|
throw runtimeError("run_events_illegal", state.runId, "duplicate run.cancel_requested is not legal");
|
|
@@ -791,7 +791,7 @@ function requireRunning(state: MutableState, eventType: string): void {
|
|
|
791
791
|
}
|
|
792
792
|
}
|
|
793
793
|
|
|
794
|
-
function foldStepEntered(state: MutableState, plan:
|
|
794
|
+
function foldStepEntered(state: MutableState, plan: KxmCompiledPlan, event: KxmRunEvent): void {
|
|
795
795
|
if (state.status !== "running") {
|
|
796
796
|
throw runtimeError("run_events_illegal", state.runId, "step.entered is only legal while running");
|
|
797
797
|
}
|
|
@@ -819,7 +819,7 @@ function foldStepEntered(state: MutableState, plan: VnextCompiledPlan, event: Vn
|
|
|
819
819
|
state.currentStep = { stepId, stepAttempt, status: "pending", panel: emptyPanel() };
|
|
820
820
|
}
|
|
821
821
|
|
|
822
|
-
function foldStepStatus(state: MutableState, plan:
|
|
822
|
+
function foldStepStatus(state: MutableState, plan: KxmCompiledPlan | undefined, event: KxmRunEvent): void {
|
|
823
823
|
requireActiveStep(state, "step.status_changed");
|
|
824
824
|
const stepId = stringPayload(event, "stepId");
|
|
825
825
|
const status = stringPayload(event, "status");
|
|
@@ -840,7 +840,7 @@ function foldStepStatus(state: MutableState, plan: VnextCompiledPlan | undefined
|
|
|
840
840
|
}
|
|
841
841
|
const step = plan ? requireStep(plan, current.stepId, state.runId) : undefined;
|
|
842
842
|
if (step) {
|
|
843
|
-
const joined =
|
|
843
|
+
const joined = kxmJoinAll(step, current.panel);
|
|
844
844
|
if (joined.tag === "outcome") {
|
|
845
845
|
const expectedStatus = expectedStatusForDeclaredOutcome(step, joined.outcome);
|
|
846
846
|
const selected = step.transitions[joined.outcome];
|
|
@@ -891,7 +891,7 @@ function foldStepStatus(state: MutableState, plan: VnextCompiledPlan | undefined
|
|
|
891
891
|
state.currentStep = { ...state.currentStep!, status };
|
|
892
892
|
}
|
|
893
893
|
|
|
894
|
-
function foldOutcome(state: MutableState, plan:
|
|
894
|
+
function foldOutcome(state: MutableState, plan: KxmCompiledPlan, event: KxmRunEvent): void {
|
|
895
895
|
requireActiveStep(state, "step.outcome_recorded");
|
|
896
896
|
const stepId = stringPayload(event, "stepId");
|
|
897
897
|
const stepAttempt = integerPayload(event, "stepAttempt");
|
|
@@ -907,7 +907,7 @@ function foldOutcome(state: MutableState, plan: VnextCompiledPlan, event: VnextR
|
|
|
907
907
|
throw runtimeError("run_events_illegal", state.runId, "step.outcome_recorded cannot overwrite a recorded outcome");
|
|
908
908
|
}
|
|
909
909
|
const step = requireStep(plan, stepId, state.runId);
|
|
910
|
-
const joined =
|
|
910
|
+
const joined = kxmJoinAll(step, current.panel);
|
|
911
911
|
if (joined.tag !== "outcome" || joined.outcome !== outcome) {
|
|
912
912
|
throw runtimeError("run_events_illegal", state.runId, "step.outcome_recorded does not match the recorded assignment outcome");
|
|
913
913
|
}
|
|
@@ -918,7 +918,7 @@ function foldOutcome(state: MutableState, plan: VnextCompiledPlan, event: VnextR
|
|
|
918
918
|
state.lastOutcomeEvent = { stepId, stepAttempt, outcome };
|
|
919
919
|
}
|
|
920
920
|
|
|
921
|
-
function foldTransitioned(state: MutableState, plan:
|
|
921
|
+
function foldTransitioned(state: MutableState, plan: KxmCompiledPlan, event: KxmRunEvent): void {
|
|
922
922
|
requireActiveStep(state, "step.transitioned");
|
|
923
923
|
const fromStepId = stringPayload(event, "fromStepId");
|
|
924
924
|
const outcome = stringPayload(event, "outcome");
|
|
@@ -936,7 +936,7 @@ function foldTransitioned(state: MutableState, plan: VnextCompiledPlan, event: V
|
|
|
936
936
|
throw runtimeError("run_events_illegal", state.runId, "step.transitioned requires every panel assignment and issued attempt to be terminal");
|
|
937
937
|
}
|
|
938
938
|
const step = requireStep(plan, fromStepId, state.runId);
|
|
939
|
-
const joined =
|
|
939
|
+
const joined = kxmJoinAll(step, current.panel);
|
|
940
940
|
if (joined.tag !== "outcome" || joined.outcome !== outcome) {
|
|
941
941
|
throw runtimeError("run_events_illegal", state.runId, "step.transitioned requires a matching joined declared outcome");
|
|
942
942
|
}
|
|
@@ -971,7 +971,7 @@ function foldTransitioned(state: MutableState, plan: VnextCompiledPlan, event: V
|
|
|
971
971
|
state.lastOutcomeEvent = undefined;
|
|
972
972
|
}
|
|
973
973
|
|
|
974
|
-
function assertTransitionPayload(runId: string, selected:
|
|
974
|
+
function assertTransitionPayload(runId: string, selected: KxmCompiledTransition, event: KxmRunEvent): void {
|
|
975
975
|
if (selected.to === "step") {
|
|
976
976
|
if (event.payload.toStepId !== selected.target) {
|
|
977
977
|
throw runtimeError("run_events_illegal", runId, "step.transitioned toStepId does not match the compiled target");
|
|
@@ -989,7 +989,7 @@ function assertTransitionPayload(runId: string, selected: VnextCompiledTransitio
|
|
|
989
989
|
}
|
|
990
990
|
}
|
|
991
991
|
|
|
992
|
-
function foldAssignmentCreated(state: MutableState, plan:
|
|
992
|
+
function foldAssignmentCreated(state: MutableState, plan: KxmCompiledPlan | undefined, event: KxmRunEvent): void {
|
|
993
993
|
requireActiveStep(state, "assignment.created");
|
|
994
994
|
const current = state.currentStep!;
|
|
995
995
|
if (state.status !== "running" || state.cancelRequested || panelFrozen(current)) {
|
|
@@ -1019,7 +1019,7 @@ function foldAssignmentCreated(state: MutableState, plan: VnextCompiledPlan | un
|
|
|
1019
1019
|
};
|
|
1020
1020
|
}
|
|
1021
1021
|
|
|
1022
|
-
function foldAssignmentAdvance(state: MutableState, plan:
|
|
1022
|
+
function foldAssignmentAdvance(state: MutableState, plan: KxmCompiledPlan, event: KxmRunEvent, next: string): void {
|
|
1023
1023
|
requireActiveStep(state, `assignment.${next}`);
|
|
1024
1024
|
const current = state.currentStep!;
|
|
1025
1025
|
if (current.panel.order.length === 0) {
|
|
@@ -1131,7 +1131,7 @@ function foldAssignmentAdvance(state: MutableState, plan: VnextCompiledPlan, eve
|
|
|
1131
1131
|
state.currentStep = putAssignment(current, assignmentId, nextAssignment);
|
|
1132
1132
|
}
|
|
1133
1133
|
|
|
1134
|
-
function foldAttemptCreated(state: MutableState, event:
|
|
1134
|
+
function foldAttemptCreated(state: MutableState, event: KxmRunEvent): void {
|
|
1135
1135
|
requireActiveStep(state, "attempt.created");
|
|
1136
1136
|
const current = state.currentStep!;
|
|
1137
1137
|
if (state.status !== "running" || state.cancelRequested || panelFrozen(current)) {
|
|
@@ -1156,10 +1156,10 @@ function foldAttemptCreated(state: MutableState, event: VnextRunEvent): void {
|
|
|
1156
1156
|
});
|
|
1157
1157
|
}
|
|
1158
1158
|
|
|
1159
|
-
function foldAttemptStatus(state: MutableState, plan:
|
|
1159
|
+
function foldAttemptStatus(state: MutableState, plan: KxmCompiledPlan, event: KxmRunEvent): void {
|
|
1160
1160
|
requireActiveStep(state, "attempt.status_changed");
|
|
1161
1161
|
const current = state.currentStep!;
|
|
1162
|
-
if (
|
|
1162
|
+
if (kxmFoldPanelAttemptIds(current).length === 0) {
|
|
1163
1163
|
throw runtimeError("run_events_illegal", state.runId, "attempt.status_changed has no active attempt");
|
|
1164
1164
|
}
|
|
1165
1165
|
const attemptId = stringPayload(event, "attemptId");
|
|
@@ -1198,7 +1198,7 @@ function foldAttemptStatus(state: MutableState, plan: VnextCompiledPlan, event:
|
|
|
1198
1198
|
});
|
|
1199
1199
|
}
|
|
1200
1200
|
|
|
1201
|
-
function requireGateEffect(state: MutableState, plan:
|
|
1201
|
+
function requireGateEffect(state: MutableState, plan: KxmCompiledPlan, event: KxmRunEvent): NonNullable<MutableState["currentStep"]> {
|
|
1202
1202
|
requireActiveStep(state, event.eventType);
|
|
1203
1203
|
const current = state.currentStep!;
|
|
1204
1204
|
const step = requireStep(plan, current.stepId, state.runId);
|
|
@@ -1209,7 +1209,7 @@ function requireGateEffect(state: MutableState, plan: VnextCompiledPlan, event:
|
|
|
1209
1209
|
return current;
|
|
1210
1210
|
}
|
|
1211
1211
|
|
|
1212
|
-
function assertEffectIdentity(state: MutableState, event:
|
|
1212
|
+
function assertEffectIdentity(state: MutableState, event: KxmRunEvent, current: NonNullable<MutableState["currentStep"]>): void {
|
|
1213
1213
|
const effect = event.payload.effect;
|
|
1214
1214
|
if (!effect || typeof effect !== "object" || Array.isArray(effect)) {
|
|
1215
1215
|
throw runtimeError("run_events_illegal", state.runId, `${event.eventType} is missing effect`);
|
|
@@ -1230,7 +1230,7 @@ function assertEffectIdentity(state: MutableState, event: VnextRunEvent, current
|
|
|
1230
1230
|
}
|
|
1231
1231
|
}
|
|
1232
1232
|
|
|
1233
|
-
function foldEffectIntent(state: MutableState, plan:
|
|
1233
|
+
function foldEffectIntent(state: MutableState, plan: KxmCompiledPlan, event: KxmRunEvent): void {
|
|
1234
1234
|
const current = requireGateEffect(state, plan, event);
|
|
1235
1235
|
if (panelAttempt(current)?.status !== "starting" || current.effectState) {
|
|
1236
1236
|
throw runtimeError("run_events_illegal", state.runId, "effect.intent_recorded requires a starting attempt with no effect");
|
|
@@ -1239,7 +1239,7 @@ function foldEffectIntent(state: MutableState, plan: VnextCompiledPlan, event: V
|
|
|
1239
1239
|
state.currentStep = { ...current, effectId, effectState: "intent" };
|
|
1240
1240
|
}
|
|
1241
1241
|
|
|
1242
|
-
function foldEffectDispatched(state: MutableState, plan:
|
|
1242
|
+
function foldEffectDispatched(state: MutableState, plan: KxmCompiledPlan, event: KxmRunEvent): void {
|
|
1243
1243
|
const current = requireGateEffect(state, plan, event);
|
|
1244
1244
|
if (current.effectState !== "intent") {
|
|
1245
1245
|
throw runtimeError("run_events_illegal", state.runId, "effect.dispatched requires effect intent");
|
|
@@ -1250,7 +1250,7 @@ function foldEffectDispatched(state: MutableState, plan: VnextCompiledPlan, even
|
|
|
1250
1250
|
state.currentStep = { ...current, effectState: "dispatched" };
|
|
1251
1251
|
}
|
|
1252
1252
|
|
|
1253
|
-
function foldEffectObserved(state: MutableState, plan:
|
|
1253
|
+
function foldEffectObserved(state: MutableState, plan: KxmCompiledPlan, event: KxmRunEvent, options: KxmFoldOptions): void {
|
|
1254
1254
|
const current = requireGateEffect(state, plan, event);
|
|
1255
1255
|
if (current.effectState === "observed-complete" || current.effectState === "observed-no-start" || current.effectState === "observed-unknown") {
|
|
1256
1256
|
throw runtimeError("run_events_illegal", state.runId, "a completed observation cannot be rewritten");
|
|
@@ -1277,7 +1277,7 @@ function foldEffectObserved(state: MutableState, plan: VnextCompiledPlan, event:
|
|
|
1277
1277
|
throw runtimeError("run_events_illegal", state.runId, "effect.observed receipt.kind does not match the pinned definition");
|
|
1278
1278
|
}
|
|
1279
1279
|
const looked = options.observationLookup?.(panelAttemptId(current)!, receiptId);
|
|
1280
|
-
let effectState:
|
|
1280
|
+
let effectState: KxmRunEffectState = "observed-unknown";
|
|
1281
1281
|
if (looked) {
|
|
1282
1282
|
if (looked.completeness === "complete") {
|
|
1283
1283
|
if (current.effectState === "intent" && expectedKind !== "artifacts-exist") {
|
|
@@ -1302,7 +1302,7 @@ function foldEffectObserved(state: MutableState, plan: VnextCompiledPlan, event:
|
|
|
1302
1302
|
};
|
|
1303
1303
|
}
|
|
1304
1304
|
|
|
1305
|
-
function foldEffectSettled(state: MutableState, plan:
|
|
1305
|
+
function foldEffectSettled(state: MutableState, plan: KxmCompiledPlan, event: KxmRunEvent): void {
|
|
1306
1306
|
const current = requireGateEffect(state, plan, event);
|
|
1307
1307
|
const hasOutcome = event.payload.outcome !== undefined;
|
|
1308
1308
|
const hasEvidence = event.payload.evidenceRefs !== undefined;
|
|
@@ -1349,7 +1349,7 @@ function foldEffectSettled(state: MutableState, plan: VnextCompiledPlan, event:
|
|
|
1349
1349
|
state.currentStep = { ...current, effectState: "settled-proof" };
|
|
1350
1350
|
}
|
|
1351
1351
|
|
|
1352
|
-
function foldEffectUncertain(state: MutableState, plan:
|
|
1352
|
+
function foldEffectUncertain(state: MutableState, plan: KxmCompiledPlan, event: KxmRunEvent): void {
|
|
1353
1353
|
const current = requireGateEffect(state, plan, event);
|
|
1354
1354
|
if (current.effectState === "observed-complete" || current.effectState === "observed-no-start" || current.effectState === "observed-unknown") {
|
|
1355
1355
|
throw runtimeError("run_events_illegal", state.runId, "blocked_uncertain after an observation is illegal");
|
|
@@ -1380,13 +1380,13 @@ function requireActiveStep(state: MutableState, eventType: string): void {
|
|
|
1380
1380
|
}
|
|
1381
1381
|
}
|
|
1382
1382
|
|
|
1383
|
-
function requireStep(plan:
|
|
1383
|
+
function requireStep(plan: KxmCompiledPlan, stepId: string, runId: string): KxmCompiledStep {
|
|
1384
1384
|
const step = plan.steps[stepId];
|
|
1385
1385
|
if (!step) throw runtimeError("run_events_illegal", runId, `unknown step ${stepId}`);
|
|
1386
1386
|
return step;
|
|
1387
1387
|
}
|
|
1388
1388
|
|
|
1389
|
-
function stringPayload(event:
|
|
1389
|
+
function stringPayload(event: KxmRunEvent, field: string): string {
|
|
1390
1390
|
const value = event.payload[field];
|
|
1391
1391
|
if (typeof value !== "string" || value.length === 0) {
|
|
1392
1392
|
throw runtimeError("run_events_illegal", event.runId, `${event.eventType} is missing ${field}`);
|
|
@@ -1394,7 +1394,7 @@ function stringPayload(event: VnextRunEvent, field: string): string {
|
|
|
1394
1394
|
return value;
|
|
1395
1395
|
}
|
|
1396
1396
|
|
|
1397
|
-
function integerPayload(event:
|
|
1397
|
+
function integerPayload(event: KxmRunEvent, field: string): number {
|
|
1398
1398
|
const value = event.payload[field];
|
|
1399
1399
|
if (typeof value !== "number" || !Number.isInteger(value) || value < 1) {
|
|
1400
1400
|
throw runtimeError("run_events_illegal", event.runId, `${event.eventType} is missing a valid ${field}`);
|
|
@@ -1402,11 +1402,11 @@ function integerPayload(event: VnextRunEvent, field: string): number {
|
|
|
1402
1402
|
return value;
|
|
1403
1403
|
}
|
|
1404
1404
|
|
|
1405
|
-
function freezePanel(panel: MutablePanel):
|
|
1406
|
-
const assignments: Record<string,
|
|
1405
|
+
function freezePanel(panel: MutablePanel): KxmFoldPanel {
|
|
1406
|
+
const assignments: Record<string, KxmFoldAssignmentState> = Object.create(null);
|
|
1407
1407
|
for (const assignmentId of Object.keys(panel.assignments).sort()) {
|
|
1408
1408
|
const assignment = panel.assignments[assignmentId]!;
|
|
1409
|
-
const attempts: Record<string,
|
|
1409
|
+
const attempts: Record<string, KxmFoldAttemptState> = Object.create(null);
|
|
1410
1410
|
for (const attemptId of Object.keys(assignment.attempts).sort()) {
|
|
1411
1411
|
attempts[attemptId] = Object.freeze(omitUndefined({ ...assignment.attempts[attemptId]! }));
|
|
1412
1412
|
}
|
|
@@ -1422,7 +1422,7 @@ function freezePanel(panel: MutablePanel): VnextFoldPanel {
|
|
|
1422
1422
|
});
|
|
1423
1423
|
}
|
|
1424
1424
|
|
|
1425
|
-
function freezeCurrentStep(current: MutableCurrentStep):
|
|
1425
|
+
function freezeCurrentStep(current: MutableCurrentStep): KxmRunCurrentStep {
|
|
1426
1426
|
const panel = freezePanel(current.panel);
|
|
1427
1427
|
const assignmentId = panel.order.length === 1 ? panel.order[0] : undefined;
|
|
1428
1428
|
const assignment = assignmentId ? panel.assignments[assignmentId] : undefined;
|
|
@@ -1448,9 +1448,9 @@ function freezeCurrentStep(current: MutableCurrentStep): VnextRunCurrentStep {
|
|
|
1448
1448
|
}));
|
|
1449
1449
|
}
|
|
1450
1450
|
|
|
1451
|
-
function freezeState(state: MutableState):
|
|
1452
|
-
const frozen:
|
|
1453
|
-
schema:
|
|
1451
|
+
function freezeState(state: MutableState): KxmRunState {
|
|
1452
|
+
const frozen: KxmRunState = {
|
|
1453
|
+
schema: KXM_RUN_STATE_SCHEMA,
|
|
1454
1454
|
runId: state.runId,
|
|
1455
1455
|
status: state.status,
|
|
1456
1456
|
...(state.runPlanHash !== undefined ? { runPlanHash: state.runPlanHash } : {}),
|
|
@@ -1476,10 +1476,10 @@ function omitUndefined<T extends Record<string, unknown>>(value: T): T {
|
|
|
1476
1476
|
return copy;
|
|
1477
1477
|
}
|
|
1478
1478
|
|
|
1479
|
-
export function isTerminalRunStatus(status:
|
|
1479
|
+
export function isTerminalRunStatus(status: KxmRunStatus): boolean {
|
|
1480
1480
|
return TERMINAL_RUN.has(status);
|
|
1481
1481
|
}
|
|
1482
1482
|
|
|
1483
|
-
export function
|
|
1483
|
+
export function isKxmTerminalStatus(value: string): value is KxmTerminalStatus {
|
|
1484
1484
|
return value === "completed" || value === "failed" || value === "cancelled";
|
|
1485
1485
|
}
|