@riddledc/riddle-proof 0.5.52 → 0.5.54

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 CHANGED
@@ -64,6 +64,7 @@ Codex/CLI-style testing:
64
64
  ```sh
65
65
  riddle-proof-loop run --request-json request.json --checkpoint-mode yield
66
66
  riddle-proof-loop checkpoint --state-path /tmp/riddle-proof-run.json
67
+ riddle-proof-loop checkpoint --state-path /tmp/riddle-proof-run.json --format markdown
67
68
  riddle-proof-loop run --request-json request.json --agent local
68
69
  riddle-proof-loop status --state-path /tmp/riddle-proof-run.json
69
70
  riddle-proof-loop respond --state-path /tmp/riddle-proof-run.json --response-json response.json
@@ -499,8 +499,8 @@ function buildProofAssessmentCheckpointPacket(input) {
499
499
  const artifactContract = recordValue(proofAssessmentRequest.artifact_contract) || recordValue(bundle?.artifact_contract);
500
500
  const requiredSignals = recordValue(recordValue(artifactContract)?.required);
501
501
  const visualDelta = visualDeltaFromState(fullState);
502
- const verificationMode = nonEmptyString(input.request.verification_mode) || nonEmptyString(fullState.verification_mode) || nonEmptyString(bundle?.verification_mode) || "proof";
503
- const visualDeltaRequired = requiredSignals?.visual_delta === true || verificationModeRequiresVisualDelta(verificationMode);
502
+ const verificationMode = nonEmptyString(bundle?.verification_mode) || nonEmptyString(fullState.verification_mode) || nonEmptyString(input.request.verification_mode) || "proof";
503
+ const visualDeltaRequired = requiredSignals?.visual_delta !== false && (requiredSignals?.visual_delta === true || verificationModeRequiresVisualDelta(verificationMode));
504
504
  const evidenceIssueCode = visualDeltaIssueCode(visualDelta, visualDeltaRequired);
505
505
  const summary = nonEmptyString(input.engineResult.summary) || nonEmptyString(fullState.verify_summary) || "Verify captured evidence and needs a supervising proof assessment.";
506
506
  const recoveryHint = evidenceIssueCode ? "Required visual_delta evidence is incomplete. Keep this same run in verify/evidence recovery with decision=revise_capture and continue_with_stage=verify unless the evidence proves an implementation or recon problem." : "Assess whether the current artifacts prove the requested change, then choose the next stage.";
@@ -13,7 +13,7 @@ import {
13
13
  normalizeCheckpointResponse,
14
14
  proofContractFromAuthorCheckpointResponse,
15
15
  statePathsForRunState
16
- } from "./chunk-T5RHGGQ2.js";
16
+ } from "./chunk-33XO42CY.js";
17
17
  import "./chunk-DUFDZJOF.js";
18
18
  export {
19
19
  RIDDLE_PROOF_CHECKPOINT_PACKET_VERSION,
@@ -445,8 +445,8 @@ function buildProofAssessmentCheckpointPacket(input) {
445
445
  const artifactContract = recordValue(proofAssessmentRequest.artifact_contract) || recordValue(bundle?.artifact_contract);
446
446
  const requiredSignals = recordValue(recordValue(artifactContract)?.required);
447
447
  const visualDelta = visualDeltaFromState(fullState);
448
- const verificationMode = nonEmptyString(input.request.verification_mode) || nonEmptyString(fullState.verification_mode) || nonEmptyString(bundle?.verification_mode) || "proof";
449
- const visualDeltaRequired = requiredSignals?.visual_delta === true || verificationModeRequiresVisualDelta(verificationMode);
448
+ const verificationMode = nonEmptyString(bundle?.verification_mode) || nonEmptyString(fullState.verification_mode) || nonEmptyString(input.request.verification_mode) || "proof";
449
+ const visualDeltaRequired = requiredSignals?.visual_delta !== false && (requiredSignals?.visual_delta === true || verificationModeRequiresVisualDelta(verificationMode));
450
450
  const evidenceIssueCode = visualDeltaIssueCode(visualDelta, visualDeltaRequired);
451
451
  const summary = nonEmptyString(input.engineResult.summary) || nonEmptyString(fullState.verify_summary) || "Verify captured evidence and needs a supervising proof assessment.";
452
452
  const recoveryHint = evidenceIssueCode ? "Required visual_delta evidence is incomplete. Keep this same run in verify/evidence recovery with decision=revise_capture and continue_with_stage=verify unless the evidence proves an implementation or recon problem." : "Assess whether the current artifacts prove the requested change, then choose the next stage.";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  statePathsForRunState
3
- } from "./chunk-T5RHGGQ2.js";
3
+ } from "./chunk-33XO42CY.js";
4
4
  import {
5
5
  compactRecord,
6
6
  isTerminalStatus,
@@ -2,7 +2,7 @@ import {
2
2
  visualDeltaForState,
3
3
  visualDeltaRequiredForState,
4
4
  visualDeltaShipGateReason
5
- } from "./chunk-4ASMX4R6.js";
5
+ } from "./chunk-RFJ5BQF6.js";
6
6
  import {
7
7
  appendRunEvent,
8
8
  appendStageHeartbeat,
@@ -10,10 +10,10 @@ import {
10
10
  createRunStatusSnapshot,
11
11
  normalizeRunParams,
12
12
  setRunStatus
13
- } from "./chunk-PVUZZ2P6.js";
13
+ } from "./chunk-MO24D3PY.js";
14
14
  import {
15
15
  createRiddleProofRunCard
16
- } from "./chunk-53UPEUVU.js";
16
+ } from "./chunk-3UHWI3FO.js";
17
17
  import {
18
18
  authorPacketPayloadFromCheckpointResponse,
19
19
  buildCheckpointPacketForEngineResult,
@@ -23,7 +23,7 @@ import {
23
23
  normalizeCheckpointResponse,
24
24
  proofContractFromAuthorCheckpointResponse,
25
25
  statePathsForRunState
26
- } from "./chunk-T5RHGGQ2.js";
26
+ } from "./chunk-33XO42CY.js";
27
27
  import {
28
28
  applyTerminalMetadata,
29
29
  compactRecord,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createRiddleProofRunCard
3
- } from "./chunk-53UPEUVU.js";
3
+ } from "./chunk-3UHWI3FO.js";
4
4
  import {
5
5
  compactRecord,
6
6
  isTerminalStatus,
@@ -108,6 +108,7 @@ function normalizeRunParams(input) {
108
108
  leave_draft: input.leave_draft,
109
109
  engine_state_path: input.engine_state_path,
110
110
  harness_state_path: input.harness_state_path,
111
+ riddle_engine_module_url: input.riddle_engine_module_url,
111
112
  max_iterations: input.max_iterations,
112
113
  auto_approve: input.auto_approve,
113
114
  dry_run: input.dry_run,
@@ -355,6 +355,7 @@ function visualDeltaRequiredForState(state = {}) {
355
355
  const bundle = objectValue(state?.evidence_bundle);
356
356
  const contract = objectValue(bundle.artifact_contract);
357
357
  const required = objectValue(contract.required);
358
+ if (required.visual_delta === false) return false;
358
359
  return required.visual_delta === true || VISUAL_FIRST_MODES.has(normalizedVerificationMode(state));
359
360
  }
360
361
  function visualDeltaForState(state = {}) {
@@ -3,7 +3,7 @@ import {
3
3
  appendStageHeartbeat,
4
4
  createRunState,
5
5
  setRunStatus
6
- } from "./chunk-PVUZZ2P6.js";
6
+ } from "./chunk-MO24D3PY.js";
7
7
  import {
8
8
  createRunResult
9
9
  } from "./chunk-DUFDZJOF.js";
@@ -0,0 +1,163 @@
1
+ // src/riddle-client.ts
2
+ import { execFileSync } from "child_process";
3
+ import { existsSync, mkdtempSync, readFileSync, rmSync } from "fs";
4
+ import { tmpdir } from "os";
5
+ import path from "path";
6
+ var DEFAULT_RIDDLE_API_BASE_URL = "https://api.riddledc.com";
7
+ var DEFAULT_RIDDLE_API_KEY_FILE = "/tmp/riddle-api-key";
8
+ var RiddleApiError = class extends Error {
9
+ constructor(pathname, status, body) {
10
+ super(`Riddle API ${pathname} failed HTTP ${status}: ${body}`);
11
+ this.name = "RiddleApiError";
12
+ this.status = status;
13
+ this.body = body;
14
+ this.path = pathname;
15
+ }
16
+ };
17
+ function normalizeBaseUrl(value) {
18
+ return (value || DEFAULT_RIDDLE_API_BASE_URL).replace(/\/$/, "");
19
+ }
20
+ function fetchFor(config = {}) {
21
+ return config.fetchImpl || fetch;
22
+ }
23
+ function resolveRiddleApiKey(config = {}) {
24
+ if (config.apiKey?.trim()) return config.apiKey.trim();
25
+ if (process.env.RIDDLE_API_KEY?.trim()) return process.env.RIDDLE_API_KEY.trim();
26
+ const keyFile = config.apiKeyFile || process.env.RIDDLE_API_KEY_FILE || DEFAULT_RIDDLE_API_KEY_FILE;
27
+ if (existsSync(keyFile)) {
28
+ const key = readFileSync(keyFile, "utf8").trim();
29
+ if (key) return key;
30
+ }
31
+ throw new Error(`Riddle API key missing. Set RIDDLE_API_KEY or write ${DEFAULT_RIDDLE_API_KEY_FILE}.`);
32
+ }
33
+ async function riddleRequestJson(config, pathname, init = {}) {
34
+ const response = await fetchFor(config)(`${normalizeBaseUrl(config.apiBaseUrl)}${pathname}`, {
35
+ ...init,
36
+ headers: {
37
+ Authorization: `Bearer ${resolveRiddleApiKey(config)}`,
38
+ "Content-Type": "application/json",
39
+ ...init.headers || {}
40
+ }
41
+ });
42
+ const text = await response.text();
43
+ let json = null;
44
+ try {
45
+ json = JSON.parse(text);
46
+ } catch {
47
+ }
48
+ if (!response.ok) throw new RiddleApiError(pathname, response.status, text);
49
+ return json ?? text;
50
+ }
51
+ async function deployRiddleStaticPreview(config, directory, label) {
52
+ if (!directory?.trim()) throw new Error("directory is required");
53
+ if (!label?.trim()) throw new Error("label is required");
54
+ const created = await riddleRequestJson(config, "/v1/preview", {
55
+ method: "POST",
56
+ body: JSON.stringify({ framework: "spa", label })
57
+ });
58
+ const id = String(created.id || "");
59
+ const uploadUrl = String(created.upload_url || "");
60
+ if (!id || !uploadUrl) throw new Error("Riddle preview create response was missing id or upload_url.");
61
+ const scratch = mkdtempSync(path.join(tmpdir(), "riddle-preview-upload-"));
62
+ const tarball = path.join(scratch, `${id}.tar.gz`);
63
+ try {
64
+ execFileSync("tar", ["czf", tarball, "-C", directory, "."], { stdio: "pipe" });
65
+ const upload = await fetchFor(config)(uploadUrl, {
66
+ method: "PUT",
67
+ headers: { "Content-Type": "application/gzip" },
68
+ body: readFileSync(tarball)
69
+ });
70
+ if (!upload.ok) {
71
+ throw new RiddleApiError(uploadUrl, upload.status, await upload.text());
72
+ }
73
+ } finally {
74
+ rmSync(scratch, { recursive: true, force: true });
75
+ }
76
+ const published = await riddleRequestJson(config, `/v1/preview/${id}/publish`, {
77
+ method: "POST"
78
+ });
79
+ return {
80
+ ok: true,
81
+ id: String(published.id || id),
82
+ label,
83
+ preview_url: String(published.preview_url || ""),
84
+ file_count: typeof published.file_count === "number" ? published.file_count : void 0,
85
+ total_bytes: typeof published.total_bytes === "number" ? published.total_bytes : void 0,
86
+ expires_at: typeof created.expires_at === "string" ? created.expires_at : void 0,
87
+ raw: published
88
+ };
89
+ }
90
+ function parseRiddleViewport(value) {
91
+ if (!value) return void 0;
92
+ const match = /^(\d+)x(\d+)$/.exec(value.trim());
93
+ if (!match) throw new Error("viewport must look like 1280x720");
94
+ return { width: Number(match[1]), height: Number(match[2]) };
95
+ }
96
+ async function runRiddleScript(config, input) {
97
+ if (!input.url?.trim()) throw new Error("url is required");
98
+ if (!input.script?.trim()) throw new Error("script is required");
99
+ const payload = {
100
+ url: input.url,
101
+ script: input.script,
102
+ sync: input.sync ?? false,
103
+ timeout_sec: input.timeoutSec || 120
104
+ };
105
+ if (input.viewport) payload.viewport = input.viewport;
106
+ if (input.include) payload.include = input.include;
107
+ if (input.options) payload.options = input.options;
108
+ return riddleRequestJson(config, "/v1/run", {
109
+ method: "POST",
110
+ body: JSON.stringify(payload)
111
+ });
112
+ }
113
+ function isTerminalRiddleJobStatus(status) {
114
+ return ["completed", "complete", "completed_error", "completed_timeout", "failed"].includes(String(status || ""));
115
+ }
116
+ async function pollRiddleJob(config, jobId, options = {}) {
117
+ if (!jobId?.trim()) throw new Error("jobId is required");
118
+ const attempts = options.attempts || (options.wait ? 60 : 1);
119
+ const intervalMs = options.intervalMs || 2e3;
120
+ let job = null;
121
+ for (let index = 0; index < attempts; index += 1) {
122
+ job = await riddleRequestJson(config, `/v1/jobs/${jobId}`);
123
+ if (isTerminalRiddleJobStatus(job.status)) break;
124
+ if (index + 1 < attempts) {
125
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
126
+ }
127
+ }
128
+ const status = job?.status ? String(job.status) : null;
129
+ if (!isTerminalRiddleJobStatus(status)) {
130
+ return { ok: true, job_id: jobId, status, terminal: false, job };
131
+ }
132
+ const artifacts = await riddleRequestJson(config, `/v1/jobs/${jobId}/artifacts`);
133
+ return {
134
+ ok: status === "completed" || status === "complete",
135
+ job_id: jobId,
136
+ status,
137
+ terminal: true,
138
+ job,
139
+ artifacts
140
+ };
141
+ }
142
+ function createRiddleApiClient(config = {}) {
143
+ return {
144
+ requestJson: (pathname, init) => riddleRequestJson(config, pathname, init),
145
+ deployStaticPreview: (directory, label) => deployRiddleStaticPreview(config, directory, label),
146
+ runScript: (input) => runRiddleScript(config, input),
147
+ pollJob: (jobId, options) => pollRiddleJob(config, jobId, options)
148
+ };
149
+ }
150
+
151
+ export {
152
+ DEFAULT_RIDDLE_API_BASE_URL,
153
+ DEFAULT_RIDDLE_API_KEY_FILE,
154
+ RiddleApiError,
155
+ resolveRiddleApiKey,
156
+ riddleRequestJson,
157
+ deployRiddleStaticPreview,
158
+ parseRiddleViewport,
159
+ runRiddleScript,
160
+ isTerminalRiddleJobStatus,
161
+ pollRiddleJob,
162
+ createRiddleApiClient
163
+ };