stageflow 0.8.0 → 0.12.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.
- package/README.md +24 -14
- package/dist/agent/activity.d.ts +9 -0
- package/dist/agent/agentBackend.d.ts +32 -0
- package/dist/agent/agentBackend.js +38 -0
- package/dist/agent/claudeActivity.d.ts +15 -0
- package/dist/agent/claudeActivity.js +58 -0
- package/dist/agent/claudeAdapter.d.ts +5 -0
- package/dist/agent/claudeAdapter.js +301 -0
- package/dist/agent/claudeSession.d.ts +18 -0
- package/dist/agent/claudeSession.js +54 -0
- package/dist/agent/claudeTools.d.ts +89 -0
- package/dist/agent/claudeTools.js +135 -0
- package/dist/agent/fakeAgent.js +24 -4
- package/dist/agent/piAdapter.d.ts +6 -3
- package/dist/agent/piAdapter.js +129 -21
- package/dist/agent/port.d.ts +50 -1
- package/dist/agent/resolveAgentPort.d.ts +26 -0
- package/dist/agent/resolveAgentPort.js +39 -0
- package/dist/cli/runCommand.js +2 -2
- package/dist/cli/runsCommand.d.ts +22 -0
- package/dist/cli/runsCommand.js +773 -0
- package/dist/cli/validateOutput.d.ts +2 -2
- package/dist/cli/validateOutput.js +2 -2
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +43 -5
- package/dist/config/browseCatalog.js +1 -1
- package/dist/config/createPipeline.d.ts +2 -1
- package/dist/config/createPipeline.js +34 -9
- package/dist/config/createStage.js +14 -9
- package/dist/config/loadPipeline.js +10 -1
- package/dist/config/loadStage.js +138 -2
- package/dist/config/loadStageflowManifest.js +14 -1
- package/dist/config/mergePipelineIncludes.d.ts +1 -0
- package/dist/config/mergePipelineIncludes.js +14 -1
- package/dist/config/normalizePipelineStageEntry.d.ts +7 -2
- package/dist/config/normalizePipelineStageEntry.js +49 -6
- package/dist/config/parseCompletionContract.d.ts +8 -0
- package/dist/config/parseCompletionContract.js +218 -0
- package/dist/config/parsePreEmitChecks.d.ts +3 -0
- package/dist/config/parsePreEmitChecks.js +65 -0
- package/dist/config/pipelineNeeds.d.ts +19 -0
- package/dist/config/pipelineNeeds.js +151 -0
- package/dist/config/pipelineStageKeys.js +16 -1
- package/dist/config/resolveForkEmitContext.d.ts +6 -2
- package/dist/config/resolveForkEmitContext.js +9 -2
- package/dist/config/resolvePipelineDag.d.ts +2 -1
- package/dist/config/resolvePipelineDag.js +182 -39
- package/dist/config/validateCatalog.d.ts +1 -1
- package/dist/config/validateCompletionContract.d.ts +4 -0
- package/dist/config/validateCompletionContract.js +52 -0
- package/dist/envelope/check.d.ts +1 -1
- package/dist/envelope/check.js +86 -13
- package/dist/envelope/cloneForks.d.ts +1 -1
- package/dist/envelope/cloneForks.js +24 -9
- package/dist/envelope/feedbackLoop.d.ts +4 -0
- package/dist/envelope/feedbackLoop.js +31 -0
- package/dist/envelope/payloadSchema.d.ts +7 -1
- package/dist/envelope/payloadSchema.js +170 -13
- package/dist/envelope/preEmitChecks.d.ts +29 -0
- package/dist/envelope/preEmitChecks.js +57 -0
- package/dist/hitl/qaTrail.d.ts +25 -0
- package/dist/hitl/qaTrail.js +51 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/mcp/catalogTools.js +4 -2
- package/dist/mcp/controlTools.js +72 -0
- package/dist/mcp/waitingGates.d.ts +2 -1
- package/dist/mcp/waitingGates.js +17 -1
- package/dist/package-meta.d.ts +1 -0
- package/dist/package-meta.js +1 -0
- package/dist/projection/projectRun.d.ts +4 -1
- package/dist/projection/projectRun.js +7 -0
- package/dist/prompt/feedbackLoopContext.d.ts +2 -0
- package/dist/prompt/feedbackLoopContext.js +17 -0
- package/dist/prompt/priorEnvelope.d.ts +2 -2
- package/dist/prompt/priorEnvelope.js +4 -1
- package/dist/runstore/pipelineDagSnapshot.d.ts +1 -0
- package/dist/runstore/pipelineDagSnapshot.js +51 -11
- package/dist/runstore/port.d.ts +185 -3
- package/dist/runstore/port.js +42 -3
- package/dist/runstore/runProjection.d.ts +7 -3
- package/dist/runstore/runProjection.js +30 -15
- package/dist/runstore/sqlite/SqliteRunStore.d.ts +25 -1
- package/dist/runstore/sqlite/SqliteRunStore.js +626 -8
- package/dist/runstore/sqlite/schema.d.ts +1 -1
- package/dist/runstore/sqlite/schema.js +99 -0
- package/dist/runstore/stageInstanceId.d.ts +1 -1
- package/dist/runstore/stageInstanceId.js +3 -2
- package/dist/runstore/trackProjection.js +59 -27
- package/dist/runstore/verificationHistory.d.ts +19 -0
- package/dist/runstore/verificationHistory.js +30 -0
- package/dist/runtime/cloneSchedule.d.ts +40 -4
- package/dist/runtime/cloneSchedule.js +212 -28
- package/dist/runtime/completionCheckRunner.d.ts +137 -0
- package/dist/runtime/completionCheckRunner.js +365 -0
- package/dist/runtime/completionCheckoutBaseline.d.ts +3 -0
- package/dist/runtime/completionCheckoutBaseline.js +44 -0
- package/dist/runtime/envelopeRouting.d.ts +10 -3
- package/dist/runtime/envelopeRouting.js +146 -5
- package/dist/runtime/feedbackLoopCoordinator.d.ts +74 -0
- package/dist/runtime/feedbackLoopCoordinator.js +446 -0
- package/dist/runtime/feedbackLoopDecision.d.ts +44 -0
- package/dist/runtime/feedbackLoopDecision.js +207 -0
- package/dist/runtime/feedbackLoopRoute.d.ts +5 -0
- package/dist/runtime/feedbackLoopRoute.js +13 -0
- package/dist/runtime/feedbackLoopSchedule.d.ts +38 -0
- package/dist/runtime/feedbackLoopSchedule.js +72 -0
- package/dist/runtime/forkGeneration.d.ts +72 -0
- package/dist/runtime/forkGeneration.js +295 -0
- package/dist/runtime/gitCheckoutCapability.d.ts +7 -0
- package/dist/runtime/gitCheckoutCapability.js +97 -0
- package/dist/runtime/manualRecoveryState.d.ts +40 -0
- package/dist/runtime/manualRecoveryState.js +73 -0
- package/dist/runtime/pipelineScheduler.d.ts +13 -1
- package/dist/runtime/pipelineScheduler.js +328 -45
- package/dist/runtime/replayLifecycle.d.ts +107 -0
- package/dist/runtime/replayLifecycle.js +168 -0
- package/dist/runtime/runManager.d.ts +61 -1
- package/dist/runtime/runManager.js +501 -7
- package/dist/runtime/runRetryCoordinator.d.ts +8 -1
- package/dist/runtime/runRetryCoordinator.js +47 -10
- package/dist/runtime/stageAttemptBootstrap.d.ts +3 -1
- package/dist/runtime/stageAttemptBootstrap.js +79 -1
- package/dist/runtime/stageProcessLauncher.d.ts +1 -1
- package/dist/runtime/stageRecovery.js +1 -1
- package/dist/runtime/stageRunner.d.ts +4 -1
- package/dist/runtime/stageRunner.js +29 -3
- package/dist/runtime/stageWorker.js +69 -2
- package/dist/runtime/stageWorkerProtocol.d.ts +1 -1
- package/dist/runtime/verifiedStageExecution.d.ts +29 -0
- package/dist/runtime/verifiedStageExecution.js +119 -0
- package/dist/server/bootstrap.js +1 -0
- package/dist/server/http.js +114 -0
- package/dist/server/operatorResults.js +2 -0
- package/dist/tools/askOperator.d.ts +161 -5
- package/dist/tools/askOperator.js +58 -25
- package/dist/tools/emitStageEnvelope.d.ts +12 -12
- package/dist/tools/emitStageEnvelope.js +112 -24
- package/dist/types/completion.d.ts +43 -0
- package/dist/types/completion.js +1 -0
- package/dist/types/envelope.d.ts +18 -0
- package/dist/types/forkChoice.d.ts +9 -4
- package/dist/types/forkChoice.js +1 -1
- package/dist/types/pipeline.d.ts +39 -2
- package/dist/types/preEmitCheck.d.ts +18 -0
- package/dist/types/preEmitCheck.js +1 -0
- package/dist/types/stage.d.ts +13 -0
- package/dist/types/stageflowManifest.d.ts +2 -0
- package/dist/ui/assets/index-CXGz4nL7.js +118 -0
- package/dist/ui/assets/{index-C3N7MXAC.css → index-uVHiae8s.css} +1 -1
- package/dist/ui/index.html +2 -2
- package/package.json +2 -1
- package/skills/stageflow/references/control-surface.md +4 -2
- package/skills/stageflow-author/references/catalog-mapping.md +26 -2
- package/skills/stageflow-author/references/catalog-write-conventions.md +1 -1
- package/skills/stageflow-run/SKILL.md +56 -25
- package/skills/stageflow-run/references/mcp-call.md +2 -2
- package/skills/stageflow-run/references/native-question-ui.md +78 -0
- package/dist/ui/assets/index-CSoGDA3A.js +0 -118
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const SCHEMA_SQL = "\nCREATE TABLE IF NOT EXISTS runs (\n run_id TEXT PRIMARY KEY,\n pipeline_id TEXT NOT NULL,\n task_id TEXT,\n task_yaml TEXT NOT NULL,\n status TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n checkout_root TEXT,\n pipeline_dag_json TEXT,\n git_sha TEXT,\n ci_pr_url TEXT,\n ci_job_url TEXT,\n pipeline_path TEXT,\n task_path TEXT,\n project_root TEXT\n);\n\nCREATE TABLE IF NOT EXISTS stages (\n run_id TEXT NOT NULL,\n stage_id TEXT NOT NULL,\n status TEXT,\n summary TEXT,\n envelope_json TEXT,\n started_at TEXT,\n finished_at TEXT,\n PRIMARY KEY (run_id, stage_id),\n FOREIGN KEY (run_id) REFERENCES runs(run_id)\n);\n\nCREATE TABLE IF NOT EXISTS stage_events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n run_id TEXT NOT NULL,\n stage_id TEXT NOT NULL,\n at TEXT NOT NULL,\n event TEXT NOT NULL,\n payload_json TEXT,\n FOREIGN KEY (run_id) REFERENCES runs(run_id)\n);\n\nCREATE INDEX IF NOT EXISTS idx_runs_status_created\n ON runs (status, created_at DESC);\n\nCREATE INDEX IF NOT EXISTS idx_runs_pipeline_created\n ON runs (pipeline_id, created_at DESC);\n\nCREATE INDEX IF NOT EXISTS idx_stage_events_run_stage_at\n ON stage_events (run_id, stage_id, at);\n\nCREATE TABLE IF NOT EXISTS stage_executions (\n run_id TEXT NOT NULL,\n stage_id TEXT NOT NULL,\n attempt INTEGER NOT NULL,\n status TEXT NOT NULL,\n started_at TEXT,\n finished_at TEXT,\n envelope_json TEXT,\n PRIMARY KEY (run_id, stage_id, attempt),\n FOREIGN KEY (run_id) REFERENCES runs(run_id)\n);\n\nCREATE INDEX IF NOT EXISTS idx_stage_executions_run_stage\n ON stage_executions (run_id, stage_id, attempt);\n";
|
|
1
|
+
export declare const SCHEMA_SQL = "\nCREATE TABLE IF NOT EXISTS runs (\n run_id TEXT PRIMARY KEY,\n pipeline_id TEXT NOT NULL,\n task_id TEXT,\n task_yaml TEXT NOT NULL,\n status TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n checkout_root TEXT,\n pipeline_dag_json TEXT,\n git_sha TEXT,\n ci_pr_url TEXT,\n ci_job_url TEXT,\n pipeline_path TEXT,\n task_path TEXT,\n project_root TEXT\n);\n\nCREATE TABLE IF NOT EXISTS stages (\n run_id TEXT NOT NULL,\n stage_id TEXT NOT NULL,\n status TEXT,\n summary TEXT,\n envelope_json TEXT,\n started_at TEXT,\n finished_at TEXT,\n PRIMARY KEY (run_id, stage_id),\n FOREIGN KEY (run_id) REFERENCES runs(run_id)\n);\n\nCREATE TABLE IF NOT EXISTS stage_events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n run_id TEXT NOT NULL,\n stage_id TEXT NOT NULL,\n at TEXT NOT NULL,\n event TEXT NOT NULL,\n payload_json TEXT,\n FOREIGN KEY (run_id) REFERENCES runs(run_id)\n);\n\nCREATE INDEX IF NOT EXISTS idx_runs_status_created\n ON runs (status, created_at DESC);\n\nCREATE INDEX IF NOT EXISTS idx_runs_pipeline_created\n ON runs (pipeline_id, created_at DESC);\n\nCREATE INDEX IF NOT EXISTS idx_stage_events_run_stage_at\n ON stage_events (run_id, stage_id, at);\n\nCREATE TABLE IF NOT EXISTS stage_executions (\n run_id TEXT NOT NULL,\n stage_id TEXT NOT NULL,\n attempt INTEGER NOT NULL,\n status TEXT NOT NULL,\n verification_outcome TEXT NOT NULL DEFAULT 'not_run',\n started_at TEXT,\n finished_at TEXT,\n envelope_json TEXT,\n PRIMARY KEY (run_id, stage_id, attempt),\n FOREIGN KEY (run_id) REFERENCES runs(run_id)\n);\n\nCREATE INDEX IF NOT EXISTS idx_stage_executions_run_stage\n ON stage_executions (run_id, stage_id, attempt);\n\nCREATE TABLE IF NOT EXISTS verification_check_results (\n run_id TEXT NOT NULL,\n stage_id TEXT NOT NULL,\n attempt INTEGER NOT NULL,\n check_id TEXT NOT NULL,\n check_type TEXT NOT NULL,\n status TEXT NOT NULL,\n started_at TEXT,\n finished_at TEXT,\n evidence_json TEXT,\n PRIMARY KEY (run_id, stage_id, attempt, check_id),\n FOREIGN KEY (run_id, stage_id, attempt)\n REFERENCES stage_executions(run_id, stage_id, attempt)\n);\n\nCREATE INDEX IF NOT EXISTS idx_verification_check_results_execution\n ON verification_check_results (run_id, stage_id, attempt, check_id);\n\nCREATE TABLE IF NOT EXISTS feedback_loops (\n run_id TEXT NOT NULL,\n loop_id TEXT NOT NULL,\n source_stage_id TEXT NOT NULL,\n source_attempt INTEGER NOT NULL,\n policy_json TEXT NOT NULL,\n state TEXT NOT NULL,\n current_replay_id TEXT,\n current_replay_number INTEGER,\n deferred_send_back_json TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n PRIMARY KEY (run_id, loop_id),\n FOREIGN KEY (run_id) REFERENCES runs(run_id)\n);\n\nCREATE INDEX IF NOT EXISTS idx_feedback_loops_run_state\n ON feedback_loops (run_id, state, created_at);\n\nCREATE TABLE IF NOT EXISTS feedback_replays (\n run_id TEXT NOT NULL,\n replay_id TEXT NOT NULL,\n loop_id TEXT NOT NULL,\n source_stage_id TEXT NOT NULL,\n source_attempt INTEGER NOT NULL,\n target_stage_id TEXT NOT NULL,\n replay_number INTEGER NOT NULL,\n max_replays INTEGER NOT NULL,\n replay_session TEXT NOT NULL,\n route_stage_ids_json TEXT NOT NULL,\n feedback_envelope_json TEXT NOT NULL,\n status TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n PRIMARY KEY (run_id, replay_id),\n FOREIGN KEY (run_id, loop_id) REFERENCES feedback_loops(run_id, loop_id)\n);\n\nCREATE UNIQUE INDEX IF NOT EXISTS idx_feedback_replays_loop_number\n ON feedback_replays (run_id, loop_id, replay_number);\nCREATE INDEX IF NOT EXISTS idx_feedback_replays_run_loop\n ON feedback_replays (run_id, loop_id, created_at);\n\nCREATE TABLE IF NOT EXISTS feedback_replay_stage_passes (\n run_id TEXT NOT NULL,\n replay_id TEXT NOT NULL,\n stage_id TEXT NOT NULL,\n stage_attempt INTEGER NOT NULL,\n session_origin_attempt INTEGER,\n session_mode TEXT NOT NULL,\n status TEXT NOT NULL,\n started_at TEXT,\n finished_at TEXT,\n emitted_envelope_json TEXT,\n PRIMARY KEY (run_id, replay_id, stage_id),\n FOREIGN KEY (run_id, replay_id) REFERENCES feedback_replays(run_id, replay_id)\n);\n\nCREATE INDEX IF NOT EXISTS idx_feedback_replay_stage_passes_replay\n ON feedback_replay_stage_passes (run_id, replay_id, stage_id);\n\nCREATE TABLE IF NOT EXISTS fork_generations (\n run_id TEXT NOT NULL,\n generation_id TEXT NOT NULL,\n replay_id TEXT,\n fork_parent_stage_id TEXT NOT NULL,\n generation_number INTEGER NOT NULL,\n clone_stage_ids_json TEXT NOT NULL,\n status TEXT NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n PRIMARY KEY (run_id, generation_id),\n FOREIGN KEY (run_id, replay_id) REFERENCES feedback_replays(run_id, replay_id)\n);\n\nCREATE UNIQUE INDEX IF NOT EXISTS idx_fork_generations_parent_number\n ON fork_generations (run_id, fork_parent_stage_id, generation_number);\nCREATE INDEX IF NOT EXISTS idx_fork_generations_run_replay\n ON fork_generations (run_id, replay_id, created_at);\n";
|
|
@@ -53,6 +53,7 @@ CREATE TABLE IF NOT EXISTS stage_executions (
|
|
|
53
53
|
stage_id TEXT NOT NULL,
|
|
54
54
|
attempt INTEGER NOT NULL,
|
|
55
55
|
status TEXT NOT NULL,
|
|
56
|
+
verification_outcome TEXT NOT NULL DEFAULT 'not_run',
|
|
56
57
|
started_at TEXT,
|
|
57
58
|
finished_at TEXT,
|
|
58
59
|
envelope_json TEXT,
|
|
@@ -62,4 +63,102 @@ CREATE TABLE IF NOT EXISTS stage_executions (
|
|
|
62
63
|
|
|
63
64
|
CREATE INDEX IF NOT EXISTS idx_stage_executions_run_stage
|
|
64
65
|
ON stage_executions (run_id, stage_id, attempt);
|
|
66
|
+
|
|
67
|
+
CREATE TABLE IF NOT EXISTS verification_check_results (
|
|
68
|
+
run_id TEXT NOT NULL,
|
|
69
|
+
stage_id TEXT NOT NULL,
|
|
70
|
+
attempt INTEGER NOT NULL,
|
|
71
|
+
check_id TEXT NOT NULL,
|
|
72
|
+
check_type TEXT NOT NULL,
|
|
73
|
+
status TEXT NOT NULL,
|
|
74
|
+
started_at TEXT,
|
|
75
|
+
finished_at TEXT,
|
|
76
|
+
evidence_json TEXT,
|
|
77
|
+
PRIMARY KEY (run_id, stage_id, attempt, check_id),
|
|
78
|
+
FOREIGN KEY (run_id, stage_id, attempt)
|
|
79
|
+
REFERENCES stage_executions(run_id, stage_id, attempt)
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
CREATE INDEX IF NOT EXISTS idx_verification_check_results_execution
|
|
83
|
+
ON verification_check_results (run_id, stage_id, attempt, check_id);
|
|
84
|
+
|
|
85
|
+
CREATE TABLE IF NOT EXISTS feedback_loops (
|
|
86
|
+
run_id TEXT NOT NULL,
|
|
87
|
+
loop_id TEXT NOT NULL,
|
|
88
|
+
source_stage_id TEXT NOT NULL,
|
|
89
|
+
source_attempt INTEGER NOT NULL,
|
|
90
|
+
policy_json TEXT NOT NULL,
|
|
91
|
+
state TEXT NOT NULL,
|
|
92
|
+
current_replay_id TEXT,
|
|
93
|
+
current_replay_number INTEGER,
|
|
94
|
+
deferred_send_back_json TEXT,
|
|
95
|
+
created_at TEXT NOT NULL,
|
|
96
|
+
updated_at TEXT NOT NULL,
|
|
97
|
+
PRIMARY KEY (run_id, loop_id),
|
|
98
|
+
FOREIGN KEY (run_id) REFERENCES runs(run_id)
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
CREATE INDEX IF NOT EXISTS idx_feedback_loops_run_state
|
|
102
|
+
ON feedback_loops (run_id, state, created_at);
|
|
103
|
+
|
|
104
|
+
CREATE TABLE IF NOT EXISTS feedback_replays (
|
|
105
|
+
run_id TEXT NOT NULL,
|
|
106
|
+
replay_id TEXT NOT NULL,
|
|
107
|
+
loop_id TEXT NOT NULL,
|
|
108
|
+
source_stage_id TEXT NOT NULL,
|
|
109
|
+
source_attempt INTEGER NOT NULL,
|
|
110
|
+
target_stage_id TEXT NOT NULL,
|
|
111
|
+
replay_number INTEGER NOT NULL,
|
|
112
|
+
max_replays INTEGER NOT NULL,
|
|
113
|
+
replay_session TEXT NOT NULL,
|
|
114
|
+
route_stage_ids_json TEXT NOT NULL,
|
|
115
|
+
feedback_envelope_json TEXT NOT NULL,
|
|
116
|
+
status TEXT NOT NULL,
|
|
117
|
+
created_at TEXT NOT NULL,
|
|
118
|
+
updated_at TEXT NOT NULL,
|
|
119
|
+
PRIMARY KEY (run_id, replay_id),
|
|
120
|
+
FOREIGN KEY (run_id, loop_id) REFERENCES feedback_loops(run_id, loop_id)
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_feedback_replays_loop_number
|
|
124
|
+
ON feedback_replays (run_id, loop_id, replay_number);
|
|
125
|
+
CREATE INDEX IF NOT EXISTS idx_feedback_replays_run_loop
|
|
126
|
+
ON feedback_replays (run_id, loop_id, created_at);
|
|
127
|
+
|
|
128
|
+
CREATE TABLE IF NOT EXISTS feedback_replay_stage_passes (
|
|
129
|
+
run_id TEXT NOT NULL,
|
|
130
|
+
replay_id TEXT NOT NULL,
|
|
131
|
+
stage_id TEXT NOT NULL,
|
|
132
|
+
stage_attempt INTEGER NOT NULL,
|
|
133
|
+
session_origin_attempt INTEGER,
|
|
134
|
+
session_mode TEXT NOT NULL,
|
|
135
|
+
status TEXT NOT NULL,
|
|
136
|
+
started_at TEXT,
|
|
137
|
+
finished_at TEXT,
|
|
138
|
+
emitted_envelope_json TEXT,
|
|
139
|
+
PRIMARY KEY (run_id, replay_id, stage_id),
|
|
140
|
+
FOREIGN KEY (run_id, replay_id) REFERENCES feedback_replays(run_id, replay_id)
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
CREATE INDEX IF NOT EXISTS idx_feedback_replay_stage_passes_replay
|
|
144
|
+
ON feedback_replay_stage_passes (run_id, replay_id, stage_id);
|
|
145
|
+
|
|
146
|
+
CREATE TABLE IF NOT EXISTS fork_generations (
|
|
147
|
+
run_id TEXT NOT NULL,
|
|
148
|
+
generation_id TEXT NOT NULL,
|
|
149
|
+
replay_id TEXT,
|
|
150
|
+
fork_parent_stage_id TEXT NOT NULL,
|
|
151
|
+
generation_number INTEGER NOT NULL,
|
|
152
|
+
clone_stage_ids_json TEXT NOT NULL,
|
|
153
|
+
status TEXT NOT NULL,
|
|
154
|
+
created_at TEXT NOT NULL,
|
|
155
|
+
updated_at TEXT NOT NULL,
|
|
156
|
+
PRIMARY KEY (run_id, generation_id),
|
|
157
|
+
FOREIGN KEY (run_id, replay_id) REFERENCES feedback_replays(run_id, replay_id)
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_fork_generations_parent_number
|
|
161
|
+
ON fork_generations (run_id, fork_parent_stage_id, generation_number);
|
|
162
|
+
CREATE INDEX IF NOT EXISTS idx_fork_generations_run_replay
|
|
163
|
+
ON fork_generations (run_id, replay_id, created_at);
|
|
65
164
|
`;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { RunPipelineDagSnapshot } from "./port.js";
|
|
2
2
|
export declare function mintCloneInstanceId(catalogId: string, n: number): string;
|
|
3
|
-
export declare function mintCloneInstanceIds(catalogId: string, count: number): string[];
|
|
3
|
+
export declare function mintCloneInstanceIds(catalogId: string, count: number, startAt?: number): string[];
|
|
4
4
|
export declare function definitionIdForInstance(snapshot: RunPipelineDagSnapshot | null | undefined, instanceId: string): string;
|
|
@@ -11,9 +11,10 @@ export function mintCloneInstanceId(catalogId, n) {
|
|
|
11
11
|
guardStageId(instanceId);
|
|
12
12
|
return instanceId;
|
|
13
13
|
}
|
|
14
|
-
export function mintCloneInstanceIds(catalogId, count) {
|
|
14
|
+
export function mintCloneInstanceIds(catalogId, count, startAt = 1) {
|
|
15
15
|
guardPositiveInteger(count, "count");
|
|
16
|
-
|
|
16
|
+
guardPositiveInteger(startAt, "startAt");
|
|
17
|
+
return Array.from({ length: count }, (_, i) => mintCloneInstanceId(catalogId, startAt + i));
|
|
17
18
|
}
|
|
18
19
|
export function definitionIdForInstance(snapshot, instanceId) {
|
|
19
20
|
const node = snapshot?.nodes.find((n) => n.id === instanceId);
|
|
@@ -1,14 +1,38 @@
|
|
|
1
|
+
import { isNeedTerminalState, predecessorEdges } from "../config/pipelineNeeds.js";
|
|
1
2
|
import { instancesOfDefinition, linearCompatDagSnapshot, } from "./pipelineDagSnapshot.js";
|
|
3
|
+
import { definitionIdForInstance } from "./stageInstanceId.js";
|
|
2
4
|
function stageStarted(stage) {
|
|
3
5
|
return stage.events.some((e) => e.event === "started" || e.event === "resumed");
|
|
4
6
|
}
|
|
5
|
-
function runHalted(stages) {
|
|
6
|
-
return stages.some((s) => s.status === "failed");
|
|
7
|
-
}
|
|
8
7
|
function predecessorIds(dag, needs) {
|
|
9
8
|
const preds = instancesOfDefinition(dag, needs);
|
|
10
9
|
return preds.length > 0 ? preds : [needs];
|
|
11
10
|
}
|
|
11
|
+
function inboundFromIds(dag, node) {
|
|
12
|
+
if (!node)
|
|
13
|
+
return [];
|
|
14
|
+
const ids = [];
|
|
15
|
+
for (const edge of predecessorEdges(node)) {
|
|
16
|
+
ids.push(...predecessorIds(dag, edge.id));
|
|
17
|
+
}
|
|
18
|
+
return ids;
|
|
19
|
+
}
|
|
20
|
+
function failureIsAccepted(dag, failedId, snapshotsById) {
|
|
21
|
+
const defId = definitionIdForInstance(dag, failedId);
|
|
22
|
+
for (const node of dag.nodes) {
|
|
23
|
+
const edge = predecessorEdges(node).find((item) => item.id === failedId || item.id === defId);
|
|
24
|
+
if (!edge?.on.includes("failed"))
|
|
25
|
+
continue;
|
|
26
|
+
const join = snapshotsById.get(node.id);
|
|
27
|
+
if (join && join.status !== "skipped")
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
function runHalted(dag, stages, snapshotsById) {
|
|
33
|
+
return stages.some((s) => s.status === "failed" &&
|
|
34
|
+
!failureIsAccepted(dag, s.stage_id, snapshotsById));
|
|
35
|
+
}
|
|
12
36
|
function computeLayers(dag) {
|
|
13
37
|
const layers = new Map();
|
|
14
38
|
const nodeById = new Map(dag.nodes.map((n) => [n.id, n]));
|
|
@@ -16,12 +40,11 @@ function computeLayers(dag) {
|
|
|
16
40
|
const cached = layers.get(id);
|
|
17
41
|
if (cached !== undefined)
|
|
18
42
|
return cached;
|
|
19
|
-
const
|
|
20
|
-
if (
|
|
43
|
+
const fromIds = inboundFromIds(dag, nodeById.get(id));
|
|
44
|
+
if (fromIds.length === 0) {
|
|
21
45
|
layers.set(id, 0);
|
|
22
46
|
return 0;
|
|
23
47
|
}
|
|
24
|
-
const fromIds = predecessorIds(dag, node.needs);
|
|
25
48
|
const l = Math.max(...fromIds.map(layerFor)) + 1;
|
|
26
49
|
layers.set(id, l);
|
|
27
50
|
return l;
|
|
@@ -47,17 +70,22 @@ function deriveReadiness(stage, dag, snapshotsById, halted) {
|
|
|
47
70
|
return { readiness: "skipped" };
|
|
48
71
|
}
|
|
49
72
|
const node = dag.nodes.find((n) => n.id === stage.stage_id);
|
|
50
|
-
const
|
|
51
|
-
if (
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
73
|
+
const unresolved = [];
|
|
74
|
+
if (node) {
|
|
75
|
+
for (const edge of predecessorEdges(node)) {
|
|
76
|
+
for (const fromId of predecessorIds(dag, edge.id)) {
|
|
77
|
+
const predecessor = snapshotsById.get(fromId);
|
|
78
|
+
if (!predecessor ||
|
|
79
|
+
!isNeedTerminalState(predecessor.status) ||
|
|
80
|
+
!edge.on.includes(predecessor.status)) {
|
|
81
|
+
unresolved.push(fromId);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
59
84
|
}
|
|
60
85
|
}
|
|
86
|
+
if (unresolved.length > 0) {
|
|
87
|
+
return { readiness: "blocked", blocked_by: unresolved };
|
|
88
|
+
}
|
|
61
89
|
return { readiness: "ready" };
|
|
62
90
|
}
|
|
63
91
|
export function buildPipelineTrack(input) {
|
|
@@ -66,7 +94,7 @@ export function buildPipelineTrack(input) {
|
|
|
66
94
|
input.stages.map((s) => s.stage_id);
|
|
67
95
|
const dag = input.dagSnapshot ?? linearCompatDagSnapshot(stageIds);
|
|
68
96
|
const layers = computeLayers(dag);
|
|
69
|
-
const halted = runHalted(input.stages);
|
|
97
|
+
const halted = runHalted(dag, input.stages, snapshotsById);
|
|
70
98
|
const nodes = dag.stage_ids.map((stageId) => {
|
|
71
99
|
const stage = snapshotsById.get(stageId);
|
|
72
100
|
if (!stage) {
|
|
@@ -87,23 +115,27 @@ export function buildPipelineTrack(input) {
|
|
|
87
115
|
if (blocked_by?.length)
|
|
88
116
|
trackNode.blocked_by = blocked_by;
|
|
89
117
|
const gateKinds = dag.gate_kinds?.[definitionId] ?? dag.gate_kinds?.[stageId];
|
|
90
|
-
if (gateKinds
|
|
118
|
+
if (gateKinds !== undefined)
|
|
91
119
|
trackNode.gate_kinds = gateKinds;
|
|
120
|
+
const feedbackTarget = node?.feedback_loop?.target;
|
|
121
|
+
if (feedbackTarget !== undefined && feedbackTarget.trim() !== "") {
|
|
122
|
+
trackNode.feedback_loop = { target: feedbackTarget };
|
|
123
|
+
}
|
|
92
124
|
return trackNode;
|
|
93
125
|
});
|
|
94
126
|
const edges = [];
|
|
95
127
|
for (const node of dag.nodes) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
128
|
+
for (const edge of predecessorEdges(node)) {
|
|
129
|
+
const fromIds = predecessorIds(dag, edge.id);
|
|
130
|
+
for (const fromId of fromIds) {
|
|
131
|
+
const fromStage = snapshotsById.get(fromId);
|
|
132
|
+
const trackEdge = { from: fromId, to: node.id };
|
|
133
|
+
if (fromStage?.status === "succeeded" &&
|
|
134
|
+
fromStage.envelope?.summary) {
|
|
135
|
+
trackEdge.envelope_summary = fromStage.envelope.summary;
|
|
136
|
+
}
|
|
137
|
+
edges.push(trackEdge);
|
|
105
138
|
}
|
|
106
|
-
edges.push(edge);
|
|
107
139
|
}
|
|
108
140
|
}
|
|
109
141
|
return { nodes, edges };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { RunStore, StageExecution, VerificationCheckResult } from "./port.js";
|
|
2
|
+
/**
|
|
3
|
+
* The audit trail for every execution of one stage. This is deliberately a
|
|
4
|
+
* stage-scoped read model: command output and other check evidence can be
|
|
5
|
+
* substantial, so it does not belong in a run listing or summary.
|
|
6
|
+
*/
|
|
7
|
+
export type StageVerificationAttempt = Pick<StageExecution, "attempt" | "status" | "verification_outcome" | "started_at" | "finished_at"> & {
|
|
8
|
+
checks: VerificationCheckResult[];
|
|
9
|
+
};
|
|
10
|
+
export type StageVerificationHistory = {
|
|
11
|
+
run_id: string;
|
|
12
|
+
stage_id: string;
|
|
13
|
+
attempts: StageVerificationAttempt[];
|
|
14
|
+
manual_recovery?: {
|
|
15
|
+
status: "available" | "stopped";
|
|
16
|
+
failed_attempt: number;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
export declare function readStageVerificationHistory(store: RunStore, runId: string, stageId: string): Promise<StageVerificationHistory>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { manualRecoveryHistory, readManualRecoveryState, } from "../runtime/manualRecoveryState.js";
|
|
2
|
+
export async function readStageVerificationHistory(store, runId, stageId) {
|
|
3
|
+
const run = await store.readRun(runId);
|
|
4
|
+
if (!run.stages.some((stage) => stage.stage_id === stageId)) {
|
|
5
|
+
throw new Error(`Stage not found: ${stageId}`);
|
|
6
|
+
}
|
|
7
|
+
const executions = await store.listStageExecutions(runId, stageId);
|
|
8
|
+
const attempts = await Promise.all(executions.map(async (execution) => ({
|
|
9
|
+
attempt: execution.attempt,
|
|
10
|
+
status: execution.status,
|
|
11
|
+
verification_outcome: execution.verification_outcome,
|
|
12
|
+
...(execution.started_at !== undefined
|
|
13
|
+
? { started_at: execution.started_at }
|
|
14
|
+
: {}),
|
|
15
|
+
...(execution.finished_at !== undefined
|
|
16
|
+
? { finished_at: execution.finished_at }
|
|
17
|
+
: {}),
|
|
18
|
+
checks: await store.listVerificationCheckResults(runId, stageId, execution.attempt),
|
|
19
|
+
})));
|
|
20
|
+
const recovery = manualRecoveryHistory(await readManualRecoveryState(store, runId, stageId));
|
|
21
|
+
if (recovery === undefined) {
|
|
22
|
+
return { run_id: runId, stage_id: stageId, attempts };
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
run_id: runId,
|
|
26
|
+
stage_id: stageId,
|
|
27
|
+
attempts,
|
|
28
|
+
manual_recovery: recovery,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -1,18 +1,54 @@
|
|
|
1
1
|
import type { RunPipelineDagSnapshot } from "../runstore/port.js";
|
|
2
2
|
import type { StageEnvelope } from "../types/envelope.js";
|
|
3
|
-
import type { ResolvedPipelineDag } from "../types/pipeline.js";
|
|
3
|
+
import type { NeedTerminalState, ResolvedPipelineDag } from "../types/pipeline.js";
|
|
4
|
+
import { type ActiveCohort } from "./forkGeneration.js";
|
|
4
5
|
import type { StageScheduleState } from "./pipelineScheduler.js";
|
|
5
6
|
export declare function isCloneInstance(dag: ResolvedPipelineDag, stageId: string): boolean;
|
|
6
7
|
export declare function sequentialLaterCloneIds(dag: ResolvedPipelineDag, stageId: string, completedEnvelopes: Map<string, StageEnvelope>): string[];
|
|
7
|
-
export declare function
|
|
8
|
+
export declare function skipRejectedNeedDependents(dag: ResolvedPipelineDag, parentId: string, states: Map<string, StageScheduleState>, observed: NeedTerminalState, onSkip: (stageId: string) => void): void;
|
|
9
|
+
export declare function failureIsAccepted(dag: ResolvedPipelineDag, failedId: string, states: Map<string, StageScheduleState>): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* A fresh clone_forks fanout targeting a catalog id that already has
|
|
12
|
+
* instances is only safe when every existing instance was put back to
|
|
13
|
+
* `pending` by the current retry cascade (`retryDownstreamIds`) — that means
|
|
14
|
+
* an ancestor was legitimately retried and this parent re-emitted the same
|
|
15
|
+
* fanout for reactivation. Instances that are still active/terminal, or
|
|
16
|
+
* merely `pending` without having gone through a retry reset (e.g. an
|
|
17
|
+
* envelope processed twice in one live run), are rejected as before.
|
|
18
|
+
*
|
|
19
|
+
* Feedback-loop replay is different: the prior cohort was superseded
|
|
20
|
+
* (`skipped`) and a new generation must mint fresh `~N` ids, so
|
|
21
|
+
* `forceFreshCloneIds` bypasses the conflict.
|
|
22
|
+
*/
|
|
23
|
+
export declare function cloneFanoutConflict(dag: ResolvedPipelineDag, envelope: StageEnvelope, states: Map<string, StageScheduleState>, retryDownstreamIds: ReadonlySet<string>, options?: {
|
|
24
|
+
forceFreshCloneIds?: boolean;
|
|
25
|
+
}): string | undefined;
|
|
26
|
+
export declare function nextFreeCloneSuffix(snapshot: RunPipelineDagSnapshot, catalogId: string): number;
|
|
8
27
|
export declare function protectedClonableChildIds(dag: ResolvedPipelineDag, predecessorId: string, envelope: StageEnvelope): Set<string>;
|
|
28
|
+
/**
|
|
29
|
+
* Downstream closure for a retry, resolved through clone-instance ids and
|
|
30
|
+
* static multi-parent edges. Catalog-level children (e.g. a join stage) are
|
|
31
|
+
* registered in `childrenOf` under the *definition* id, not per clone
|
|
32
|
+
* instance, so a plain childrenOf walk starting above a fanout dead-ends at
|
|
33
|
+
* the instance ids it discovers transitively. Resolving definition-id
|
|
34
|
+
* children and `predecessorEdges` join successors at every step means
|
|
35
|
+
* retrying an ancestor or a single clone instance still reaches the join
|
|
36
|
+
* and everything after it, without pulling in sibling terminals.
|
|
37
|
+
*/
|
|
9
38
|
export declare function cloneRetryDownstream(dag: ResolvedPipelineDag, stageIds: string[]): Set<string>;
|
|
10
39
|
export declare function cloneFailureContinuesSchedule(dag: ResolvedPipelineDag, stageId: string, completedEnvelopes: Map<string, StageEnvelope>): boolean;
|
|
11
40
|
export declare function cloneFailFastSkipIds(dag: ResolvedPipelineDag, stageId: string, completedEnvelopes: Map<string, StageEnvelope>): string[];
|
|
12
|
-
export declare function cloneScheduleAllowsRun(dag: ResolvedPipelineDag, stageId: string, states: Map<string, StageScheduleState>, completedEnvelopes: Map<string, StageEnvelope
|
|
41
|
+
export declare function cloneScheduleAllowsRun(dag: ResolvedPipelineDag, stageId: string, states: Map<string, StageScheduleState>, completedEnvelopes: Map<string, StageEnvelope>, options?: {
|
|
42
|
+
activeCohortForNeeds?: (needsId: string) => ActiveCohort;
|
|
43
|
+
activeCloneIdsForNeeds?: (needsId: string) => Set<string> | null;
|
|
44
|
+
}): boolean;
|
|
13
45
|
export type ApplyCloneForksResult = {
|
|
14
46
|
dag: RunPipelineDagSnapshot;
|
|
15
47
|
skippedIds: string[];
|
|
48
|
+
/** Freshly minted instance ids keyed by clonable catalog successor id. */
|
|
49
|
+
mintedBySuccessor?: Map<string, string[]>;
|
|
16
50
|
};
|
|
17
|
-
export declare function applyCloneForksToSchedule(dag: ResolvedPipelineDag, predecessorId: string, envelope: StageEnvelope, states: Map<string, StageScheduleState
|
|
51
|
+
export declare function applyCloneForksToSchedule(dag: ResolvedPipelineDag, predecessorId: string, envelope: StageEnvelope, states: Map<string, StageScheduleState>, options?: {
|
|
52
|
+
forceFreshCloneIds?: boolean;
|
|
53
|
+
}): ApplyCloneForksResult;
|
|
18
54
|
export declare function applyCloneForksFromEnvelopes(dag: ResolvedPipelineDag, states: Map<string, StageScheduleState>, completedEnvelopes: Map<string, StageEnvelope>): ApplyCloneForksResult;
|