@riddledc/riddle-proof 0.1.1 → 0.3.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 +29 -3
- package/dist/{chunk-2ZQNXVQC.js → chunk-5DC6YXN4.js} +4 -0
- package/dist/{chunk-EPVZKWUS.js → chunk-IQIEOQZF.js} +59 -1
- package/dist/chunk-P3FUU5X4.js +495 -0
- package/dist/index.cjs +548 -0
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +10 -2
- package/dist/openclaw.js +2 -2
- package/dist/result.cjs +4 -0
- package/dist/result.js +1 -1
- package/dist/runner.cjs +697 -0
- package/dist/runner.d.cts +22 -0
- package/dist/runner.d.ts +22 -0
- package/dist/runner.js +8 -0
- package/dist/state.cjs +60 -0
- package/dist/state.d.cts +17 -2
- package/dist/state.d.ts +17 -2
- package/dist/state.js +6 -2
- package/dist/types.d.cts +74 -2
- package/dist/types.d.ts +74 -2
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -7,9 +7,11 @@ Riddle Proof is agent-agnostic. Bring a coding agent through an adapter; Riddle
|
|
|
7
7
|
Proof standardizes evidence, proof assessment, ship gates, terminal results,
|
|
8
8
|
and integration metadata.
|
|
9
9
|
|
|
10
|
-
This package
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
This package includes the reusable runner harness that drives a request through
|
|
11
|
+
preflight, setup, implementation, proof capture, judgment, shipping, and notification
|
|
12
|
+
adapters. The current OpenClaw `proofed_change_run` implementation remains the
|
|
13
|
+
reference workflow while adapter implementations are extracted behind parity
|
|
14
|
+
tests.
|
|
13
15
|
|
|
14
16
|
## Initial Scope
|
|
15
17
|
|
|
@@ -17,6 +19,9 @@ reusable contracts and low-risk helpers are extracted here.
|
|
|
17
19
|
- Evidence bundle and proof assessment types
|
|
18
20
|
- Adapter interfaces
|
|
19
21
|
- State/event helpers for wrappers that need a stable run envelope
|
|
22
|
+
- Runner harness for preflight -> setup -> implement -> prove -> judge -> ship -> notify
|
|
23
|
+
- Stage heartbeat and run status snapshot helpers
|
|
24
|
+
- Worktree metadata and proof artifact role contracts
|
|
20
25
|
- Terminal ship metadata normalization
|
|
21
26
|
- Stable result helpers
|
|
22
27
|
- OpenClaw parameter normalization via `@riddledc/riddle-proof/openclaw`
|
|
@@ -40,6 +45,7 @@ npm install @riddledc/riddle-proof
|
|
|
40
45
|
|
|
41
46
|
```ts
|
|
42
47
|
import { createRunResult, createRunState } from "@riddledc/riddle-proof";
|
|
48
|
+
import { runRiddleProof } from "@riddledc/riddle-proof/runner";
|
|
43
49
|
import { toRiddleProofRunParams } from "@riddledc/riddle-proof/openclaw";
|
|
44
50
|
```
|
|
45
51
|
|
|
@@ -48,6 +54,26 @@ adapters are exposed through subpaths such as
|
|
|
48
54
|
`@riddledc/riddle-proof/openclaw`, so wrappers can reuse the mapping logic
|
|
49
55
|
without depending on another plugin runtime.
|
|
50
56
|
|
|
57
|
+
## Runner Harness
|
|
58
|
+
|
|
59
|
+
`runRiddleProof` is the reusable idea-to-PR workflow driver. It does not ship
|
|
60
|
+
credentials or a coding agent. It calls adapters supplied by the host
|
|
61
|
+
integration:
|
|
62
|
+
|
|
63
|
+
```text
|
|
64
|
+
preflight -> setup -> implement -> prove -> judge -> ship -> notify
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The preflight adapter checks model/tool availability before proof work starts.
|
|
68
|
+
The setup adapter should report the isolated worktree path, branch, and cleanup
|
|
69
|
+
policy it chose. During the run, wrappers can emit `appendStageHeartbeat`
|
|
70
|
+
events and return `createRunStatusSnapshot` for cheap observer status.
|
|
71
|
+
|
|
72
|
+
The proof adapter is where a host wires Riddle server-backed capture. The ship
|
|
73
|
+
adapter is where a host commits, pushes, opens or updates a PR, and waits for CI
|
|
74
|
+
when configured. The notification adapter is where a host updates Discord,
|
|
75
|
+
OpenClaw, GitHub, or another integration.
|
|
76
|
+
|
|
51
77
|
## OpenClaw Adapter Boundary
|
|
52
78
|
|
|
53
79
|
`@riddledc/riddle-proof/openclaw` translates the current
|
|
@@ -52,7 +52,11 @@ function createRunResult(input) {
|
|
|
52
52
|
return compactRecord({
|
|
53
53
|
ok,
|
|
54
54
|
status,
|
|
55
|
+
run_id: state.run_id,
|
|
55
56
|
state_path: input.state_path ?? state.state_path ?? null,
|
|
57
|
+
worktree_path: state.worktree_path ?? null,
|
|
58
|
+
branch: state.branch ?? null,
|
|
59
|
+
current_stage: state.current_stage ?? null,
|
|
56
60
|
iterations: state.iterations,
|
|
57
61
|
last_checkpoint: state.last_checkpoint ?? null,
|
|
58
62
|
last_summary: input.last_summary ?? null,
|
|
@@ -2,13 +2,24 @@ import {
|
|
|
2
2
|
compactRecord,
|
|
3
3
|
nonEmptyString,
|
|
4
4
|
recordValue
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-5DC6YXN4.js";
|
|
6
6
|
|
|
7
7
|
// src/state.ts
|
|
8
8
|
var RIDDLE_PROOF_RUN_STATE_VERSION = "riddle-proof.run-state.v1";
|
|
9
9
|
function timestamp() {
|
|
10
10
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
11
11
|
}
|
|
12
|
+
function createRunId(createdAt) {
|
|
13
|
+
const stamp = createdAt.replace(/\D/g, "").slice(0, 14) || "unknown";
|
|
14
|
+
const entropy = Math.random().toString(36).slice(2, 8) || "run";
|
|
15
|
+
return `rp_${stamp}_${entropy}`;
|
|
16
|
+
}
|
|
17
|
+
function elapsedMs(start, end) {
|
|
18
|
+
const startMs = start ? Date.parse(start) : NaN;
|
|
19
|
+
const endMs = end ? Date.parse(end) : NaN;
|
|
20
|
+
if (!Number.isFinite(startMs) || !Number.isFinite(endMs)) return void 0;
|
|
21
|
+
return Math.max(0, endMs - startMs);
|
|
22
|
+
}
|
|
12
23
|
function normalizeIntegrationContext(input, fallbackSource) {
|
|
13
24
|
const value = recordValue(input);
|
|
14
25
|
if (!value) {
|
|
@@ -59,7 +70,12 @@ function createRunState(input) {
|
|
|
59
70
|
const createdAt = input.created_at || timestamp();
|
|
60
71
|
return compactRecord({
|
|
61
72
|
version: RIDDLE_PROOF_RUN_STATE_VERSION,
|
|
73
|
+
run_id: input.run_id || createRunId(createdAt),
|
|
62
74
|
state_path: input.state_path,
|
|
75
|
+
worktree_path: input.worktree_path,
|
|
76
|
+
branch: input.branch || input.request.branch,
|
|
77
|
+
current_stage: input.current_stage ?? null,
|
|
78
|
+
stage_started_at: input.stage_started_at ?? null,
|
|
63
79
|
status: input.status || "running",
|
|
64
80
|
created_at: createdAt,
|
|
65
81
|
updated_at: input.updated_at || createdAt,
|
|
@@ -87,9 +103,49 @@ function appendRunEvent(state, input) {
|
|
|
87
103
|
details: event.details
|
|
88
104
|
}));
|
|
89
105
|
if (input.checkpoint !== void 0) state.last_checkpoint = input.checkpoint;
|
|
106
|
+
if (input.stage !== void 0) {
|
|
107
|
+
if (state.current_stage !== input.stage) state.stage_started_at = event.ts;
|
|
108
|
+
state.current_stage = input.stage;
|
|
109
|
+
}
|
|
90
110
|
state.updated_at = event.ts;
|
|
91
111
|
return state;
|
|
92
112
|
}
|
|
113
|
+
function appendStageHeartbeat(state, input) {
|
|
114
|
+
const at = input.ts || timestamp();
|
|
115
|
+
return appendRunEvent(state, {
|
|
116
|
+
ts: at,
|
|
117
|
+
kind: "stage.heartbeat",
|
|
118
|
+
checkpoint: input.checkpoint || `${input.stage}_heartbeat`,
|
|
119
|
+
stage: input.stage,
|
|
120
|
+
summary: input.summary || `${input.stage} stage is active.`,
|
|
121
|
+
details: compactRecord({
|
|
122
|
+
elapsed_ms: elapsedMs(state.created_at, at),
|
|
123
|
+
stage_elapsed_ms: elapsedMs(state.stage_started_at, at),
|
|
124
|
+
wait_reason: input.wait_reason,
|
|
125
|
+
blocker: input.blocker,
|
|
126
|
+
...input.details
|
|
127
|
+
})
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
function createRunStatusSnapshot(state, at = timestamp()) {
|
|
131
|
+
const latestEvent = state.events[state.events.length - 1];
|
|
132
|
+
const runId = state.run_id || "unknown";
|
|
133
|
+
return compactRecord({
|
|
134
|
+
run_id: runId,
|
|
135
|
+
status: state.status,
|
|
136
|
+
current_stage: state.current_stage ?? null,
|
|
137
|
+
state_path: state.state_path ?? null,
|
|
138
|
+
worktree_path: state.worktree_path ?? null,
|
|
139
|
+
branch: state.branch ?? null,
|
|
140
|
+
iterations: state.iterations,
|
|
141
|
+
last_checkpoint: state.last_checkpoint ?? null,
|
|
142
|
+
updated_at: state.updated_at,
|
|
143
|
+
elapsed_ms: elapsedMs(state.created_at, at),
|
|
144
|
+
stage_elapsed_ms: elapsedMs(state.stage_started_at, at),
|
|
145
|
+
blocker: state.blocker,
|
|
146
|
+
latest_event: latestEvent
|
|
147
|
+
});
|
|
148
|
+
}
|
|
93
149
|
function setRunStatus(state, status, at = timestamp()) {
|
|
94
150
|
state.status = status;
|
|
95
151
|
state.ok = status !== "blocked" && status !== "failed";
|
|
@@ -103,5 +159,7 @@ export {
|
|
|
103
159
|
normalizeRunParams,
|
|
104
160
|
createRunState,
|
|
105
161
|
appendRunEvent,
|
|
162
|
+
appendStageHeartbeat,
|
|
163
|
+
createRunStatusSnapshot,
|
|
106
164
|
setRunStatus
|
|
107
165
|
};
|
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
import {
|
|
2
|
+
appendRunEvent,
|
|
3
|
+
appendStageHeartbeat,
|
|
4
|
+
createRunState,
|
|
5
|
+
setRunStatus
|
|
6
|
+
} from "./chunk-IQIEOQZF.js";
|
|
7
|
+
import {
|
|
8
|
+
createRunResult
|
|
9
|
+
} from "./chunk-5DC6YXN4.js";
|
|
10
|
+
|
|
11
|
+
// src/runner.ts
|
|
12
|
+
function errorDetails(error) {
|
|
13
|
+
if (error instanceof Error) {
|
|
14
|
+
return {
|
|
15
|
+
name: error.name,
|
|
16
|
+
message: error.message
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
return { message: String(error) };
|
|
20
|
+
}
|
|
21
|
+
function adapterBlocker(code, message, checkpoint, details) {
|
|
22
|
+
return {
|
|
23
|
+
code,
|
|
24
|
+
message,
|
|
25
|
+
checkpoint,
|
|
26
|
+
details
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function blockRun(input) {
|
|
30
|
+
input.state.blocker = input.blocker;
|
|
31
|
+
appendRunEvent(input.state, {
|
|
32
|
+
kind: "run.blocked",
|
|
33
|
+
checkpoint: input.blocker.checkpoint,
|
|
34
|
+
stage: input.stage,
|
|
35
|
+
summary: input.blocker.message,
|
|
36
|
+
details: {
|
|
37
|
+
code: input.blocker.code,
|
|
38
|
+
...input.blocker.details
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
setRunStatus(input.state, "blocked");
|
|
42
|
+
return createRunResult({
|
|
43
|
+
state: input.state,
|
|
44
|
+
status: "blocked",
|
|
45
|
+
last_summary: input.blocker.message,
|
|
46
|
+
evidence_bundle: input.evidence_bundle,
|
|
47
|
+
raw: input.raw
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function shouldIterate(assessment) {
|
|
51
|
+
const nextStage = assessment.continue_with_stage || assessment.recommended_stage;
|
|
52
|
+
return nextStage === "implement" || nextStage === "author";
|
|
53
|
+
}
|
|
54
|
+
async function notifyIfConfigured(input) {
|
|
55
|
+
if (!input.notification) return input.result;
|
|
56
|
+
try {
|
|
57
|
+
const notification = await input.notification.notify({
|
|
58
|
+
state: input.state,
|
|
59
|
+
result: input.result
|
|
60
|
+
});
|
|
61
|
+
input.state.notification = notification;
|
|
62
|
+
appendRunEvent(input.state, {
|
|
63
|
+
kind: "notification.completed",
|
|
64
|
+
checkpoint: "notification_completed",
|
|
65
|
+
stage: "notify",
|
|
66
|
+
summary: "Integration notification completed."
|
|
67
|
+
});
|
|
68
|
+
} catch (error) {
|
|
69
|
+
appendRunEvent(input.state, {
|
|
70
|
+
kind: "notification.failed",
|
|
71
|
+
checkpoint: "notification_failed",
|
|
72
|
+
stage: "notify",
|
|
73
|
+
summary: "Integration notification failed.",
|
|
74
|
+
details: errorDetails(error)
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return createRunResult({
|
|
78
|
+
state: input.state,
|
|
79
|
+
status: input.state.status,
|
|
80
|
+
last_summary: input.result.last_summary,
|
|
81
|
+
evidence_bundle: input.result.evidence_bundle,
|
|
82
|
+
raw: input.result.raw
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
async function runRiddleProof(input) {
|
|
86
|
+
const state = input.state || createRunState({
|
|
87
|
+
request: input.request,
|
|
88
|
+
state_path: input.state_path,
|
|
89
|
+
worktree_path: input.workdir
|
|
90
|
+
});
|
|
91
|
+
const adapters = input.adapters || {};
|
|
92
|
+
const maxIterations = Math.max(1, Math.trunc(input.max_iterations ?? 1));
|
|
93
|
+
appendRunEvent(state, {
|
|
94
|
+
kind: "run.started",
|
|
95
|
+
checkpoint: "run_started",
|
|
96
|
+
stage: "setup",
|
|
97
|
+
summary: "Riddle Proof run started.",
|
|
98
|
+
details: {
|
|
99
|
+
run_id: state.run_id,
|
|
100
|
+
state_path: state.state_path,
|
|
101
|
+
worktree_path: state.worktree_path,
|
|
102
|
+
branch: state.branch,
|
|
103
|
+
max_iterations: maxIterations,
|
|
104
|
+
ship_mode: state.request.ship_mode || "none"
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
appendStageHeartbeat(state, {
|
|
108
|
+
stage: "setup",
|
|
109
|
+
summary: "Setup stage is active.",
|
|
110
|
+
details: {
|
|
111
|
+
run_id: state.run_id,
|
|
112
|
+
state_path: state.state_path,
|
|
113
|
+
worktree_path: state.worktree_path,
|
|
114
|
+
branch: state.branch
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
let workdir = input.workdir;
|
|
118
|
+
let evidenceContext;
|
|
119
|
+
if (adapters.preflight) {
|
|
120
|
+
appendRunEvent(state, {
|
|
121
|
+
kind: "preflight.started",
|
|
122
|
+
checkpoint: "preflight_started",
|
|
123
|
+
stage: "preflight",
|
|
124
|
+
summary: "Riddle Proof preflight adapter started."
|
|
125
|
+
});
|
|
126
|
+
try {
|
|
127
|
+
const preflight = await adapters.preflight.preflight({ request: state.request, state });
|
|
128
|
+
if (!preflight.ok) {
|
|
129
|
+
return blockRun({
|
|
130
|
+
state,
|
|
131
|
+
stage: "preflight",
|
|
132
|
+
blocker: adapterBlocker(
|
|
133
|
+
"preflight_failed",
|
|
134
|
+
"The preflight adapter found blocking tool or model configuration issues.",
|
|
135
|
+
"preflight_failed",
|
|
136
|
+
{
|
|
137
|
+
blockers: preflight.blockers,
|
|
138
|
+
warnings: preflight.warnings,
|
|
139
|
+
degraded_capabilities: preflight.degraded_capabilities
|
|
140
|
+
}
|
|
141
|
+
),
|
|
142
|
+
raw: { preflight }
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
appendRunEvent(state, {
|
|
146
|
+
kind: "preflight.completed",
|
|
147
|
+
checkpoint: "preflight_completed",
|
|
148
|
+
stage: "preflight",
|
|
149
|
+
summary: "Riddle Proof preflight adapter completed.",
|
|
150
|
+
details: {
|
|
151
|
+
warnings: preflight.warnings,
|
|
152
|
+
degraded_capabilities: preflight.degraded_capabilities
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
} catch (error) {
|
|
156
|
+
return blockRun({
|
|
157
|
+
state,
|
|
158
|
+
stage: "preflight",
|
|
159
|
+
blocker: adapterBlocker("preflight_exception", "The preflight adapter threw an exception.", "preflight_failed", errorDetails(error))
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (adapters.setup) {
|
|
164
|
+
appendRunEvent(state, {
|
|
165
|
+
kind: "setup.started",
|
|
166
|
+
checkpoint: "setup_started",
|
|
167
|
+
stage: "setup",
|
|
168
|
+
summary: "Riddle Proof setup adapter started."
|
|
169
|
+
});
|
|
170
|
+
try {
|
|
171
|
+
const setup = await adapters.setup.setup({ request: state.request, state });
|
|
172
|
+
if (!setup.ok) {
|
|
173
|
+
return blockRun({
|
|
174
|
+
state,
|
|
175
|
+
stage: "setup",
|
|
176
|
+
blocker: adapterBlocker(
|
|
177
|
+
"setup_failed",
|
|
178
|
+
"The setup adapter did not complete successfully.",
|
|
179
|
+
"setup_failed",
|
|
180
|
+
{ blockers: setup.blockers }
|
|
181
|
+
),
|
|
182
|
+
raw: { setup }
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
workdir = setup.worktree_path || setup.workdir || workdir;
|
|
186
|
+
state.worktree_path = setup.worktree_path || setup.workdir || state.worktree_path;
|
|
187
|
+
state.branch = setup.branch || state.branch;
|
|
188
|
+
evidenceContext = setup.evidence_context;
|
|
189
|
+
appendRunEvent(state, {
|
|
190
|
+
kind: "setup.completed",
|
|
191
|
+
checkpoint: "setup_completed",
|
|
192
|
+
stage: "setup",
|
|
193
|
+
summary: "Riddle Proof setup adapter completed.",
|
|
194
|
+
details: {
|
|
195
|
+
has_workdir: Boolean(workdir),
|
|
196
|
+
worktree_path: state.worktree_path,
|
|
197
|
+
branch: state.branch,
|
|
198
|
+
cleanup_policy: setup.cleanup_policy,
|
|
199
|
+
has_evidence_context: Boolean(evidenceContext)
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
} catch (error) {
|
|
203
|
+
return blockRun({
|
|
204
|
+
state,
|
|
205
|
+
stage: "setup",
|
|
206
|
+
blocker: adapterBlocker("setup_exception", "The setup adapter threw an exception.", "setup_failed", errorDetails(error))
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
const changeRequest = state.request.change_request?.trim();
|
|
211
|
+
if (!changeRequest) {
|
|
212
|
+
return blockRun({
|
|
213
|
+
state,
|
|
214
|
+
stage: "setup",
|
|
215
|
+
blocker: adapterBlocker("change_request_required", "A change request is required before implementation.", "request_invalid")
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
if (!workdir) {
|
|
219
|
+
return blockRun({
|
|
220
|
+
state,
|
|
221
|
+
stage: "setup",
|
|
222
|
+
blocker: adapterBlocker("workdir_not_configured", "A workdir or setup adapter result is required before implementation.", "setup_required")
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
if (!adapters.implementation) {
|
|
226
|
+
return blockRun({
|
|
227
|
+
state,
|
|
228
|
+
stage: "implement",
|
|
229
|
+
blocker: adapterBlocker("implementation_adapter_not_configured", "An implementation adapter is required to change code.", "implementation_required")
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
if (!adapters.proof) {
|
|
233
|
+
return blockRun({
|
|
234
|
+
state,
|
|
235
|
+
stage: "prove",
|
|
236
|
+
blocker: adapterBlocker("proof_adapter_not_configured", "A proof adapter is required to capture evidence.", "proof_required")
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
if (!adapters.judge) {
|
|
240
|
+
return blockRun({
|
|
241
|
+
state,
|
|
242
|
+
stage: "verify",
|
|
243
|
+
blocker: adapterBlocker("judge_adapter_not_configured", "A judge adapter is required to assess proof.", "judge_required")
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
let implementation;
|
|
247
|
+
let evidenceBundle;
|
|
248
|
+
let assessment;
|
|
249
|
+
for (let attempt = 0; attempt < maxIterations; attempt += 1) {
|
|
250
|
+
state.iterations += 1;
|
|
251
|
+
appendStageHeartbeat(state, {
|
|
252
|
+
stage: "implement",
|
|
253
|
+
summary: "Implementation stage is active.",
|
|
254
|
+
details: { iteration: state.iterations }
|
|
255
|
+
});
|
|
256
|
+
appendRunEvent(state, {
|
|
257
|
+
kind: "implementation.started",
|
|
258
|
+
checkpoint: "implementation_started",
|
|
259
|
+
stage: "implement",
|
|
260
|
+
summary: "Implementation adapter started.",
|
|
261
|
+
details: { iteration: state.iterations }
|
|
262
|
+
});
|
|
263
|
+
try {
|
|
264
|
+
implementation = await adapters.implementation.implement({
|
|
265
|
+
workdir,
|
|
266
|
+
change_request: changeRequest,
|
|
267
|
+
evidence_context: evidenceContext,
|
|
268
|
+
state
|
|
269
|
+
});
|
|
270
|
+
} catch (error) {
|
|
271
|
+
return blockRun({
|
|
272
|
+
state,
|
|
273
|
+
stage: "implement",
|
|
274
|
+
blocker: adapterBlocker("implementation_exception", "The implementation adapter threw an exception.", "implementation_failed", errorDetails(error)),
|
|
275
|
+
evidence_bundle: evidenceBundle
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
if (!implementation.ok) {
|
|
279
|
+
return blockRun({
|
|
280
|
+
state,
|
|
281
|
+
stage: "implement",
|
|
282
|
+
blocker: adapterBlocker(
|
|
283
|
+
"implementation_failed",
|
|
284
|
+
"The implementation adapter did not complete successfully.",
|
|
285
|
+
"implementation_failed",
|
|
286
|
+
{ blockers: implementation.blockers }
|
|
287
|
+
),
|
|
288
|
+
evidence_bundle: evidenceBundle,
|
|
289
|
+
raw: { implementation }
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
appendRunEvent(state, {
|
|
293
|
+
kind: "implementation.completed",
|
|
294
|
+
checkpoint: "implementation_completed",
|
|
295
|
+
stage: "implement",
|
|
296
|
+
summary: "Implementation adapter completed.",
|
|
297
|
+
details: {
|
|
298
|
+
changed_files: implementation.changed_files,
|
|
299
|
+
tests_run: implementation.tests_run
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
appendStageHeartbeat(state, {
|
|
303
|
+
stage: "prove",
|
|
304
|
+
summary: "Proof capture stage is active.",
|
|
305
|
+
details: {
|
|
306
|
+
verification_mode: state.request.verification_mode
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
appendRunEvent(state, {
|
|
310
|
+
kind: "proof.started",
|
|
311
|
+
checkpoint: "proof_started",
|
|
312
|
+
stage: "prove",
|
|
313
|
+
summary: "Proof adapter started."
|
|
314
|
+
});
|
|
315
|
+
try {
|
|
316
|
+
const proof = await adapters.proof.prove({
|
|
317
|
+
state,
|
|
318
|
+
implementation,
|
|
319
|
+
evidence_context: evidenceContext
|
|
320
|
+
});
|
|
321
|
+
if (!proof.ok || !proof.evidence_bundle) {
|
|
322
|
+
return blockRun({
|
|
323
|
+
state,
|
|
324
|
+
stage: "prove",
|
|
325
|
+
blocker: adapterBlocker(
|
|
326
|
+
"proof_failed",
|
|
327
|
+
"The proof adapter did not produce a usable evidence bundle.",
|
|
328
|
+
"proof_failed",
|
|
329
|
+
{ blockers: proof.blockers }
|
|
330
|
+
),
|
|
331
|
+
raw: { proof }
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
evidenceBundle = proof.evidence_bundle;
|
|
335
|
+
appendRunEvent(state, {
|
|
336
|
+
kind: "proof.completed",
|
|
337
|
+
checkpoint: "proof_completed",
|
|
338
|
+
stage: "prove",
|
|
339
|
+
summary: "Proof adapter completed.",
|
|
340
|
+
details: {
|
|
341
|
+
verification_mode: evidenceBundle.verification_mode,
|
|
342
|
+
artifact_count: evidenceBundle.artifacts?.length ?? 0
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
} catch (error) {
|
|
346
|
+
return blockRun({
|
|
347
|
+
state,
|
|
348
|
+
stage: "prove",
|
|
349
|
+
blocker: adapterBlocker("proof_exception", "The proof adapter threw an exception.", "proof_failed", errorDetails(error))
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
appendRunEvent(state, {
|
|
353
|
+
kind: "judge.started",
|
|
354
|
+
checkpoint: "judge_started",
|
|
355
|
+
stage: "verify",
|
|
356
|
+
summary: "Judge adapter started."
|
|
357
|
+
});
|
|
358
|
+
appendStageHeartbeat(state, {
|
|
359
|
+
stage: "verify",
|
|
360
|
+
summary: "Verification stage is active.",
|
|
361
|
+
details: {
|
|
362
|
+
verification_mode: evidenceBundle.verification_mode
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
try {
|
|
366
|
+
assessment = await adapters.judge.assessProof({ state, evidence_bundle: evidenceBundle });
|
|
367
|
+
state.proof_decision = assessment.decision;
|
|
368
|
+
appendRunEvent(state, {
|
|
369
|
+
kind: "judge.completed",
|
|
370
|
+
checkpoint: "judge_completed",
|
|
371
|
+
stage: "verify",
|
|
372
|
+
summary: assessment.summary,
|
|
373
|
+
details: {
|
|
374
|
+
decision: assessment.decision,
|
|
375
|
+
recommended_stage: assessment.recommended_stage,
|
|
376
|
+
continue_with_stage: assessment.continue_with_stage,
|
|
377
|
+
reasons: assessment.reasons
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
} catch (error) {
|
|
381
|
+
return blockRun({
|
|
382
|
+
state,
|
|
383
|
+
stage: "verify",
|
|
384
|
+
blocker: adapterBlocker("judge_exception", "The judge adapter threw an exception.", "judge_failed", errorDetails(error)),
|
|
385
|
+
evidence_bundle: evidenceBundle
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
if (assessment.decision === "ready_to_ship") break;
|
|
389
|
+
if (attempt + 1 < maxIterations && shouldIterate(assessment)) {
|
|
390
|
+
evidenceContext = evidenceBundle;
|
|
391
|
+
appendRunEvent(state, {
|
|
392
|
+
kind: "run.iterating",
|
|
393
|
+
checkpoint: "iteration_requested",
|
|
394
|
+
stage: "implement",
|
|
395
|
+
summary: "Judge requested another implementation iteration.",
|
|
396
|
+
details: {
|
|
397
|
+
decision: assessment.decision,
|
|
398
|
+
next_iteration: state.iterations + 1
|
|
399
|
+
}
|
|
400
|
+
});
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
return blockRun({
|
|
404
|
+
state,
|
|
405
|
+
stage: "verify",
|
|
406
|
+
blocker: adapterBlocker(
|
|
407
|
+
"proof_not_ready",
|
|
408
|
+
assessment.summary || "Proof is not ready to ship.",
|
|
409
|
+
"judge_completed",
|
|
410
|
+
{
|
|
411
|
+
decision: assessment.decision,
|
|
412
|
+
recommended_stage: assessment.recommended_stage,
|
|
413
|
+
continue_with_stage: assessment.continue_with_stage,
|
|
414
|
+
reasons: assessment.reasons
|
|
415
|
+
}
|
|
416
|
+
),
|
|
417
|
+
evidence_bundle: evidenceBundle,
|
|
418
|
+
raw: { assessment }
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
if (!assessment || !evidenceBundle) {
|
|
422
|
+
return blockRun({
|
|
423
|
+
state,
|
|
424
|
+
stage: "verify",
|
|
425
|
+
blocker: adapterBlocker("runner_incomplete", "The runner ended without proof assessment.", "runner_incomplete")
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
if (state.request.ship_mode !== "ship") {
|
|
429
|
+
setRunStatus(state, "ready_to_ship");
|
|
430
|
+
const result2 = createRunResult({
|
|
431
|
+
state,
|
|
432
|
+
status: "ready_to_ship",
|
|
433
|
+
last_summary: assessment.summary,
|
|
434
|
+
evidence_bundle: evidenceBundle,
|
|
435
|
+
raw: { implementation, assessment }
|
|
436
|
+
});
|
|
437
|
+
return notifyIfConfigured({ state, result: result2, notification: adapters.notification });
|
|
438
|
+
}
|
|
439
|
+
if (!adapters.ship) {
|
|
440
|
+
return blockRun({
|
|
441
|
+
state,
|
|
442
|
+
stage: "ship",
|
|
443
|
+
blocker: adapterBlocker("ship_adapter_not_configured", "A ship adapter is required when ship_mode is ship.", "ship_required"),
|
|
444
|
+
evidence_bundle: evidenceBundle,
|
|
445
|
+
raw: { implementation, assessment }
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
appendRunEvent(state, {
|
|
449
|
+
kind: "ship.started",
|
|
450
|
+
checkpoint: "ship_started",
|
|
451
|
+
stage: "ship",
|
|
452
|
+
summary: "Ship adapter started."
|
|
453
|
+
});
|
|
454
|
+
appendStageHeartbeat(state, {
|
|
455
|
+
stage: "ship",
|
|
456
|
+
summary: "Ship stage is active."
|
|
457
|
+
});
|
|
458
|
+
let metadata;
|
|
459
|
+
try {
|
|
460
|
+
metadata = await adapters.ship.ship({ state, assessment });
|
|
461
|
+
} catch (error) {
|
|
462
|
+
return blockRun({
|
|
463
|
+
state,
|
|
464
|
+
stage: "ship",
|
|
465
|
+
blocker: adapterBlocker("ship_exception", "The ship adapter threw an exception.", "ship_failed", errorDetails(error)),
|
|
466
|
+
evidence_bundle: evidenceBundle,
|
|
467
|
+
raw: { implementation, assessment }
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
appendRunEvent(state, {
|
|
471
|
+
kind: "ship.completed",
|
|
472
|
+
checkpoint: "ship_completed",
|
|
473
|
+
stage: "ship",
|
|
474
|
+
summary: "Ship adapter completed.",
|
|
475
|
+
details: {
|
|
476
|
+
pr_url: metadata.pr_url,
|
|
477
|
+
marked_ready: metadata.marked_ready,
|
|
478
|
+
finalized: metadata.finalized
|
|
479
|
+
}
|
|
480
|
+
});
|
|
481
|
+
setRunStatus(state, "shipped");
|
|
482
|
+
const result = createRunResult({
|
|
483
|
+
state,
|
|
484
|
+
status: "shipped",
|
|
485
|
+
last_summary: "Riddle Proof shipped.",
|
|
486
|
+
metadata,
|
|
487
|
+
evidence_bundle: evidenceBundle,
|
|
488
|
+
raw: { implementation, assessment }
|
|
489
|
+
});
|
|
490
|
+
return notifyIfConfigured({ state, result, notification: adapters.notification });
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
export {
|
|
494
|
+
runRiddleProof
|
|
495
|
+
};
|