@riddledc/riddle-proof 0.5.2 → 0.5.3
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/dist/{chunk-5GZZZ6JA.js → chunk-MLJJIKTP.js} +51 -2
- package/dist/engine-harness.cjs +179 -27
- package/dist/engine-harness.js +1 -1
- package/dist/index.cjs +179 -27
- package/dist/index.js +1 -1
- package/dist/proof-run-engine.cjs +127 -24
- package/dist/proof-run-engine.d.cts +3 -3
- package/dist/proof-run-engine.d.ts +3 -3
- package/dist/proof-run-engine.js +127 -24
- package/package.json +1 -1
- package/runtime/lib/preflight.py +13 -0
|
@@ -262,7 +262,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
|
|
|
262
262
|
blocking?: boolean;
|
|
263
263
|
details?: Record<string, unknown>;
|
|
264
264
|
ok: boolean;
|
|
265
|
-
action: "setup" | "recon" | "author" | "implement" | "verify" | "
|
|
265
|
+
action: "ship" | "setup" | "recon" | "author" | "implement" | "verify" | "run";
|
|
266
266
|
state_path: string;
|
|
267
267
|
stage: any;
|
|
268
268
|
summary: string;
|
|
@@ -342,7 +342,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
|
|
|
342
342
|
continueWithStage?: WorkflowStage | null;
|
|
343
343
|
blocking?: boolean;
|
|
344
344
|
details?: Record<string, unknown>;
|
|
345
|
-
action: "setup" | "recon" | "author" | "implement" | "verify" | "
|
|
345
|
+
action: "ship" | "setup" | "recon" | "author" | "implement" | "verify" | "run";
|
|
346
346
|
state_path: string;
|
|
347
347
|
stage: any;
|
|
348
348
|
checkpoint: string;
|
|
@@ -589,7 +589,7 @@ declare function executeWorkflow(params: WorkflowParams, pluginConfig: any, reso
|
|
|
589
589
|
error?: undefined;
|
|
590
590
|
} | {
|
|
591
591
|
ok: boolean;
|
|
592
|
-
action: "setup" | "recon" | "author" | "implement" | "verify" | "
|
|
592
|
+
action: "ship" | "setup" | "recon" | "author" | "implement" | "verify" | "run";
|
|
593
593
|
state_path: string;
|
|
594
594
|
stage: any;
|
|
595
595
|
summary: string;
|
package/dist/proof-run-engine.js
CHANGED
|
@@ -95,6 +95,88 @@ function updateState(statePath, mutate) {
|
|
|
95
95
|
writeState(statePath, state);
|
|
96
96
|
return state;
|
|
97
97
|
}
|
|
98
|
+
var RUNTIME_EVENT_LIMIT = 100;
|
|
99
|
+
function nowIso() {
|
|
100
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
101
|
+
}
|
|
102
|
+
function appendRuntimeEventToState(state, event) {
|
|
103
|
+
const events = Array.isArray(state.runtime_events) ? state.runtime_events : [];
|
|
104
|
+
state.runtime_events = [...events, event].slice(-RUNTIME_EVENT_LIMIT);
|
|
105
|
+
state.runtime_updated_at = event.ts;
|
|
106
|
+
}
|
|
107
|
+
function beginRuntimeStep(statePath, action, step, workflowPath) {
|
|
108
|
+
const timer = {
|
|
109
|
+
startedAt: nowIso(),
|
|
110
|
+
startedMs: Date.now()
|
|
111
|
+
};
|
|
112
|
+
updateState(statePath, (state) => {
|
|
113
|
+
const current = {
|
|
114
|
+
step,
|
|
115
|
+
action,
|
|
116
|
+
status: "running",
|
|
117
|
+
started_at: timer.startedAt,
|
|
118
|
+
workflow_file: path.basename(workflowPath)
|
|
119
|
+
};
|
|
120
|
+
state.current_runtime_step = current;
|
|
121
|
+
appendRuntimeEventToState(state, {
|
|
122
|
+
ts: timer.startedAt,
|
|
123
|
+
kind: "workflow.step.started",
|
|
124
|
+
step,
|
|
125
|
+
action,
|
|
126
|
+
summary: `Started ${step} workflow step.`,
|
|
127
|
+
details: {
|
|
128
|
+
workflow_file: path.basename(workflowPath)
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
return timer;
|
|
133
|
+
}
|
|
134
|
+
function finishRuntimeStep(statePath, action, result, timer) {
|
|
135
|
+
const finishedAt = nowIso();
|
|
136
|
+
const durationMs = Date.now() - timer.startedMs;
|
|
137
|
+
const summary = result.haltedForApproval ? `${result.step} halted for approval.` : result.ok ? `Finished ${result.step} workflow step.` : `${result.step} workflow step failed.`;
|
|
138
|
+
updateState(statePath, (state) => {
|
|
139
|
+
const completed = {
|
|
140
|
+
step: result.step,
|
|
141
|
+
action,
|
|
142
|
+
status: result.haltedForApproval ? "approval_required" : result.ok ? "completed" : "failed",
|
|
143
|
+
started_at: timer.startedAt,
|
|
144
|
+
finished_at: finishedAt,
|
|
145
|
+
duration_ms: durationMs,
|
|
146
|
+
ok: result.ok,
|
|
147
|
+
halted_for_approval: result.haltedForApproval || false,
|
|
148
|
+
auto_approved: result.autoApproved || false,
|
|
149
|
+
error: result.error || null
|
|
150
|
+
};
|
|
151
|
+
state.current_runtime_step = null;
|
|
152
|
+
state.last_runtime_step = completed;
|
|
153
|
+
appendRuntimeEventToState(state, {
|
|
154
|
+
ts: finishedAt,
|
|
155
|
+
kind: "workflow.step.finished",
|
|
156
|
+
step: result.step,
|
|
157
|
+
action,
|
|
158
|
+
summary,
|
|
159
|
+
details: completed
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
return {
|
|
163
|
+
...result,
|
|
164
|
+
started_at: timer.startedAt,
|
|
165
|
+
finished_at: finishedAt,
|
|
166
|
+
duration_ms: durationMs
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function executedStep(res, extra = {}) {
|
|
170
|
+
const output = {
|
|
171
|
+
step: res.step,
|
|
172
|
+
ok: res.ok,
|
|
173
|
+
haltedForApproval: res.haltedForApproval || false,
|
|
174
|
+
autoApproved: res.autoApproved || false,
|
|
175
|
+
...extra
|
|
176
|
+
};
|
|
177
|
+
if (typeof res.duration_ms === "number") output.duration_ms = res.duration_ms;
|
|
178
|
+
return output;
|
|
179
|
+
}
|
|
98
180
|
function hasSupervisorProofAssessment(state) {
|
|
99
181
|
const proofAssessment = state?.proof_assessment || {};
|
|
100
182
|
const source = String(proofAssessment?.source || state?.proof_assessment_source || "").trim().toLowerCase();
|
|
@@ -557,53 +639,74 @@ async function executeWorkflow(params, pluginConfig, resolvedConfig) {
|
|
|
557
639
|
const lobsterPrefix = process.env.RIDDLE_PROOF_LOBSTER_SCRIPT ? [process.env.RIDDLE_PROOF_LOBSTER_SCRIPT] : [];
|
|
558
640
|
const runOne = (step) => {
|
|
559
641
|
const args = step === "setup" ? buildSetupArgs(params, config) : {};
|
|
642
|
+
const stepWorkflowFile = workflowFile(config.riddleProofDir, step);
|
|
643
|
+
const timer = beginRuntimeStep(config.statePath, action, step, stepWorkflowFile);
|
|
560
644
|
let output;
|
|
561
645
|
try {
|
|
562
646
|
output = JSON.parse(
|
|
563
|
-
execFileSync(lobsterCommand, [...lobsterPrefix, "run", "--file",
|
|
647
|
+
execFileSync(lobsterCommand, [...lobsterPrefix, "run", "--file", stepWorkflowFile, "--args-json", JSON.stringify(args)], {
|
|
564
648
|
encoding: "utf-8",
|
|
565
649
|
env
|
|
566
650
|
})
|
|
567
651
|
);
|
|
568
652
|
} catch (error) {
|
|
569
|
-
return {
|
|
653
|
+
return finishRuntimeStep(config.statePath, action, {
|
|
570
654
|
ok: false,
|
|
571
655
|
step,
|
|
572
656
|
error: error?.message || String(error),
|
|
573
657
|
stdout: String(error?.stdout || ""),
|
|
574
658
|
stderr: String(error?.stderr || "")
|
|
575
|
-
};
|
|
659
|
+
}, timer);
|
|
576
660
|
}
|
|
577
661
|
if (output?.status === "needs_approval") {
|
|
578
662
|
if (!params.auto_approve) {
|
|
579
|
-
return {
|
|
663
|
+
return finishRuntimeStep(config.statePath, action, {
|
|
580
664
|
ok: false,
|
|
581
665
|
haltedForApproval: true,
|
|
582
666
|
step,
|
|
583
667
|
approval: output.requiresApproval || null,
|
|
584
668
|
raw: output
|
|
585
|
-
};
|
|
669
|
+
}, timer);
|
|
586
670
|
}
|
|
587
671
|
const token = output?.requiresApproval?.resumeToken;
|
|
588
|
-
if (!token)
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
672
|
+
if (!token) {
|
|
673
|
+
return finishRuntimeStep(config.statePath, action, {
|
|
674
|
+
ok: false,
|
|
675
|
+
step,
|
|
676
|
+
error: `${step} requested approval without a resume token.`,
|
|
677
|
+
raw: output
|
|
678
|
+
}, timer);
|
|
679
|
+
}
|
|
680
|
+
let resumed;
|
|
681
|
+
try {
|
|
682
|
+
resumed = JSON.parse(
|
|
683
|
+
execFileSync(lobsterCommand, [...lobsterPrefix, "resume", "--token", token, "--approve", "yes"], {
|
|
684
|
+
encoding: "utf-8",
|
|
685
|
+
env
|
|
686
|
+
})
|
|
687
|
+
);
|
|
688
|
+
} catch (error) {
|
|
689
|
+
return finishRuntimeStep(config.statePath, action, {
|
|
690
|
+
ok: false,
|
|
691
|
+
step,
|
|
692
|
+
autoApproved: true,
|
|
693
|
+
error: error?.message || String(error),
|
|
694
|
+
stdout: String(error?.stdout || ""),
|
|
695
|
+
stderr: String(error?.stderr || "")
|
|
696
|
+
}, timer);
|
|
697
|
+
}
|
|
698
|
+
return finishRuntimeStep(config.statePath, action, {
|
|
596
699
|
ok: resumed?.ok !== false,
|
|
597
700
|
step,
|
|
598
701
|
autoApproved: true,
|
|
599
702
|
raw: resumed
|
|
600
|
-
};
|
|
703
|
+
}, timer);
|
|
601
704
|
}
|
|
602
|
-
return {
|
|
705
|
+
return finishRuntimeStep(config.statePath, action, {
|
|
603
706
|
ok: output?.ok !== false,
|
|
604
707
|
step,
|
|
605
708
|
raw: output
|
|
606
|
-
};
|
|
709
|
+
}, timer);
|
|
607
710
|
};
|
|
608
711
|
let effectiveAdvanceStage = params.advance_stage || null;
|
|
609
712
|
const recordAttempt = (stage, status, summary, extra = {}) => {
|
|
@@ -729,7 +832,7 @@ async function executeWorkflow(params, pluginConfig, resolvedConfig) {
|
|
|
729
832
|
let state = readState(config.statePath);
|
|
730
833
|
if (!state || !state.workspace_ready || params.advance_stage === "setup") {
|
|
731
834
|
const setupRes = runOne("setup");
|
|
732
|
-
executed.push(
|
|
835
|
+
executed.push(executedStep(setupRes));
|
|
733
836
|
if (!setupRes.ok || setupRes.haltedForApproval) {
|
|
734
837
|
return failedRun("setup", setupRes.haltedForApproval ? "setup halted for approval" : "setup failed", setupRes, {
|
|
735
838
|
checkpoint: "setup_blocked"
|
|
@@ -939,7 +1042,7 @@ async function executeWorkflow(params, pluginConfig, resolvedConfig) {
|
|
|
939
1042
|
}
|
|
940
1043
|
if (!state?.recon_results || state?.stage === "setup" || state?.stage === "preflight" || ["needs_agent_decision", "needs_supervisor_judgment"].includes(state?.recon_status || "") || requestedStage === "recon") {
|
|
941
1044
|
const reconRes = runOne("recon");
|
|
942
|
-
executed.push(
|
|
1045
|
+
executed.push(executedStep(reconRes));
|
|
943
1046
|
if (!reconRes.ok || reconRes.haltedForApproval) {
|
|
944
1047
|
return failedRun("recon", reconRes.haltedForApproval ? "recon halted for approval" : "recon failed", reconRes, {
|
|
945
1048
|
checkpoint: "recon_failed",
|
|
@@ -987,7 +1090,7 @@ async function executeWorkflow(params, pluginConfig, resolvedConfig) {
|
|
|
987
1090
|
state = readState(config.statePath);
|
|
988
1091
|
if (!authorReady(state) || effectiveAdvanceStage === "author") {
|
|
989
1092
|
const authorRes = runOne("author");
|
|
990
|
-
executed.push(
|
|
1093
|
+
executed.push(executedStep(authorRes));
|
|
991
1094
|
if (!authorRes.ok || authorRes.haltedForApproval) {
|
|
992
1095
|
return failedRun("author", authorRes.haltedForApproval ? "author halted for approval" : "author failed", authorRes, {
|
|
993
1096
|
checkpoint: "author_failed",
|
|
@@ -1102,7 +1205,7 @@ async function executeWorkflow(params, pluginConfig, resolvedConfig) {
|
|
|
1102
1205
|
}
|
|
1103
1206
|
if (effectiveAdvanceStage === "implement") {
|
|
1104
1207
|
const implementRes = runOne("implement");
|
|
1105
|
-
executed.push(
|
|
1208
|
+
executed.push(executedStep(implementRes));
|
|
1106
1209
|
if (implementRes.haltedForApproval) {
|
|
1107
1210
|
return failedRun("implement", "implement halted for approval", implementRes, {
|
|
1108
1211
|
checkpoint: "implement_blocked",
|
|
@@ -1192,7 +1295,7 @@ ${implementRes.stderr || ""}`;
|
|
|
1192
1295
|
let verifyRes = { ok: true, step: "verify", reusedEvidence: canReuseVerifyEvidence };
|
|
1193
1296
|
if (!canReuseVerifyEvidence) {
|
|
1194
1297
|
verifyRes = runOne("verify");
|
|
1195
|
-
executed.push(
|
|
1298
|
+
executed.push(executedStep(verifyRes));
|
|
1196
1299
|
if (!verifyRes.ok || verifyRes.haltedForApproval) {
|
|
1197
1300
|
return failedRun("verify", verifyRes.haltedForApproval ? "verify halted for approval" : "verify failed", verifyRes, {
|
|
1198
1301
|
checkpoint: "verify_failed",
|
|
@@ -1201,7 +1304,7 @@ ${implementRes.stderr || ""}`;
|
|
|
1201
1304
|
});
|
|
1202
1305
|
}
|
|
1203
1306
|
} else {
|
|
1204
|
-
executed.push(
|
|
1307
|
+
executed.push(executedStep(verifyRes, { reusedEvidence: true }));
|
|
1205
1308
|
}
|
|
1206
1309
|
state = readState(config.statePath);
|
|
1207
1310
|
const verifyStatus = state?.verify_status || ((state?.after_cdn || "").trim() ? "evidence_captured" : "capture_incomplete");
|
|
@@ -1338,7 +1441,7 @@ ${implementRes.stderr || ""}`;
|
|
|
1338
1441
|
details: { ...verifyDetails, shipGate }
|
|
1339
1442
|
});
|
|
1340
1443
|
const shipRes = runOne("ship");
|
|
1341
|
-
executed.push(
|
|
1444
|
+
executed.push(executedStep(shipRes));
|
|
1342
1445
|
if (!shipRes.ok || shipRes.haltedForApproval) {
|
|
1343
1446
|
const shipNextAction = shipRes?.error && String(shipRes.error).includes("temporary proof branch") ? "product bug: ship resolved a temporary proof branch; resolve the PR head branch before retrying ship" : "inspect the ship error, confirm the PR head branch and verified commit, then retry ship";
|
|
1344
1447
|
return failedRun("ship", shipRes.haltedForApproval ? "ship halted for approval" : "ship failed", shipRes, {
|
|
@@ -1517,7 +1620,7 @@ ${implementRes.stderr || ""}`;
|
|
|
1517
1620
|
return shipGateBlocked(state, executed, { shipAssessment: shipAssessment.raw });
|
|
1518
1621
|
}
|
|
1519
1622
|
const shipRes = runOne("ship");
|
|
1520
|
-
executed.push(
|
|
1623
|
+
executed.push(executedStep(shipRes));
|
|
1521
1624
|
if (!shipRes.ok || shipRes.haltedForApproval) {
|
|
1522
1625
|
return failedRun("ship", shipRes.haltedForApproval ? "ship halted for approval" : "ship failed", shipRes, {
|
|
1523
1626
|
checkpoint: "ship_failed",
|
package/package.json
CHANGED
package/runtime/lib/preflight.py
CHANGED
|
@@ -239,6 +239,19 @@ if missing:
|
|
|
239
239
|
print('MISSING: ' + ', '.join(missing))
|
|
240
240
|
print('=' * 50)
|
|
241
241
|
|
|
242
|
+
# The TypeScript harness writes runtime observability fields before Lobster
|
|
243
|
+
# starts. Preflight initializes the main state file, so preserve those fields
|
|
244
|
+
# rather than making status polling go blind during setup.
|
|
245
|
+
if os.path.exists(STATE_FILE):
|
|
246
|
+
try:
|
|
247
|
+
with open(STATE_FILE) as existing_state_file:
|
|
248
|
+
existing_state = json.load(existing_state_file)
|
|
249
|
+
except Exception:
|
|
250
|
+
existing_state = {}
|
|
251
|
+
for runtime_key in ('current_runtime_step', 'last_runtime_step', 'runtime_events', 'runtime_updated_at'):
|
|
252
|
+
if runtime_key in existing_state:
|
|
253
|
+
s[runtime_key] = existing_state[runtime_key]
|
|
254
|
+
|
|
242
255
|
save_state(s)
|
|
243
256
|
|
|
244
257
|
if missing:
|