@riddledc/riddle-proof 0.5.37 → 0.5.38
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 +12 -8
- package/lib/workspace-core.mjs +32 -1
- package/package.json +1 -1
- package/runtime/lib/setup.py +55 -9
package/README.md
CHANGED
|
@@ -82,21 +82,25 @@ updates Discord, OpenClaw, GitHub, or another integration.
|
|
|
82
82
|
|
|
83
83
|
The packaged proof-run setup uses isolated git worktrees for before and after
|
|
84
84
|
states. By default those worktrees now live under
|
|
85
|
-
`/tmp/.riddle-proof-worktrees`, with dependency caches under
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
`/var/tmp/riddle-proof/.riddle-proof-worktrees`, with dependency caches under
|
|
86
|
+
the matching disk-backed scratch root. This keeps repeated `node_modules` cache
|
|
87
|
+
materialization off tmpfs `/tmp` and away from EFS or other shared workspace
|
|
88
|
+
filesystems.
|
|
89
89
|
|
|
90
90
|
Set `RIDDLE_PROOF_WORKTREE_ROOT` to choose an explicit location. Set
|
|
91
91
|
`RIDDLE_PROOF_USE_WORKSPACE_WORKTREE_ROOT=1` to keep the previous behavior of
|
|
92
|
-
placing proof worktrees next to the active repository.
|
|
92
|
+
placing proof worktrees next to the active repository. Set
|
|
93
|
+
`RIDDLE_PROOF_SCRATCH_ROOT` to choose the scratch parent, or
|
|
94
|
+
`RIDDLE_PROOF_USE_TMP_SCRATCH=1` to force tmp-backed scratch for a short-lived
|
|
95
|
+
test.
|
|
93
96
|
|
|
94
97
|
When local scratch storage is low, setup prunes stale
|
|
95
98
|
`riddle-proof-*` worktrees from the scratch root before creating the next run.
|
|
96
99
|
This preserves the dependency cache for speed while avoiding old failed runs
|
|
97
|
-
filling
|
|
98
|
-
|
|
99
|
-
`
|
|
100
|
+
filling the scratch disk. Setup also records scratch disk snapshots in the run
|
|
101
|
+
state so disk blockers are visible during proof inspection. Set
|
|
102
|
+
`RIDDLE_PROOF_KEEP_SCRATCH_WORKTREES=1` to disable that cleanup for debugging,
|
|
103
|
+
or tune the low-space threshold with `RIDDLE_PROOF_MIN_SCRATCH_FREE_MB`.
|
|
100
104
|
|
|
101
105
|
## Capture Diagnostics
|
|
102
106
|
|
package/lib/workspace-core.mjs
CHANGED
|
@@ -15,6 +15,8 @@ import {
|
|
|
15
15
|
import path from "node:path";
|
|
16
16
|
import { fileURLToPath } from "node:url";
|
|
17
17
|
|
|
18
|
+
const DEFAULT_RIDDLE_PROOF_SCRATCH_ROOT = "/var/tmp/riddle-proof";
|
|
19
|
+
|
|
18
20
|
function commandEnv() {
|
|
19
21
|
return { ...process.env, HOME: "/root" };
|
|
20
22
|
}
|
|
@@ -58,6 +60,26 @@ export function uniqueToken(now = new Date()) {
|
|
|
58
60
|
return `${stamp}-${randomUUID().slice(0, 8)}`;
|
|
59
61
|
}
|
|
60
62
|
|
|
63
|
+
function envFlag(name, defaultValue = false) {
|
|
64
|
+
const raw = String(process.env[name] || "").trim().toLowerCase();
|
|
65
|
+
if (["1", "true", "yes", "on"].includes(raw)) return true;
|
|
66
|
+
if (["0", "false", "no", "off"].includes(raw)) return false;
|
|
67
|
+
return defaultValue;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function riddleProofScratchRoot() {
|
|
71
|
+
const configured = (process.env.RIDDLE_PROOF_SCRATCH_ROOT || "").trim();
|
|
72
|
+
if (configured) return path.resolve(configured);
|
|
73
|
+
if (envFlag("RIDDLE_PROOF_USE_TMP_SCRATCH", false)) {
|
|
74
|
+
return path.join("/tmp", "riddle-proof");
|
|
75
|
+
}
|
|
76
|
+
return DEFAULT_RIDDLE_PROOF_SCRATCH_ROOT;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function defaultRiddleProofWorktreeRoot() {
|
|
80
|
+
return path.join(riddleProofScratchRoot(), ".riddle-proof-worktrees");
|
|
81
|
+
}
|
|
82
|
+
|
|
61
83
|
export function workspaceRoots({ workspaceRoot = "", currentRepoDir = "" } = {}) {
|
|
62
84
|
const roots = [];
|
|
63
85
|
for (const candidate of [
|
|
@@ -332,7 +354,7 @@ function dependencyCacheRoot(projectDir) {
|
|
|
332
354
|
if (worktreeIndex >= 0) {
|
|
333
355
|
return path.join(resolved.slice(0, worktreeIndex), ".riddle-proof-deps-cache");
|
|
334
356
|
}
|
|
335
|
-
return path.join(
|
|
357
|
+
return path.join(riddleProofScratchRoot(), ".riddle-proof-deps-cache");
|
|
336
358
|
}
|
|
337
359
|
|
|
338
360
|
function dependencyCacheKey(fingerprint, installCmd) {
|
|
@@ -497,6 +519,15 @@ async function main() {
|
|
|
497
519
|
case "dependency-fingerprint":
|
|
498
520
|
ok({ fingerprint: computeDependencyFingerprint(payload.projectDir) });
|
|
499
521
|
return;
|
|
522
|
+
case "scratch-root":
|
|
523
|
+
ok({
|
|
524
|
+
scratchRoot: riddleProofScratchRoot(),
|
|
525
|
+
worktreeRoot: defaultRiddleProofWorktreeRoot(),
|
|
526
|
+
});
|
|
527
|
+
return;
|
|
528
|
+
case "dependency-cache-root":
|
|
529
|
+
ok({ cacheRoot: dependencyCacheRoot(payload.projectDir || process.cwd()) });
|
|
530
|
+
return;
|
|
500
531
|
default:
|
|
501
532
|
throw new Error(`Unsupported command: ${command}`);
|
|
502
533
|
}
|
package/package.json
CHANGED
package/runtime/lib/setup.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"""Setup: create worktrees, install deps, validate args, write state.
|
|
2
2
|
|
|
3
|
-
Idempotent — safe to re-run. Creates per-run worktrees under
|
|
4
|
-
|
|
5
|
-
/tmp/.riddle-proof-worktrees/riddle-proof-<run_id>-before
|
|
6
|
-
/tmp/.riddle-proof-worktrees/riddle-proof-<run_id>-after
|
|
3
|
+
Idempotent — safe to re-run. Creates per-run worktrees under disk-backed
|
|
4
|
+
scratch storage by default:
|
|
5
|
+
/var/tmp/riddle-proof/.riddle-proof-worktrees/riddle-proof-<run_id>-before
|
|
6
|
+
/var/tmp/riddle-proof/.riddle-proof-worktrees/riddle-proof-<run_id>-after
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
import json, subprocess as sp, os, sys, shutil, time, tempfile
|
|
@@ -24,6 +24,7 @@ SAFE_RUN_ID = ''.join(ch if ch.isalnum() or ch in ('-', '_') else '-' for ch in
|
|
|
24
24
|
|
|
25
25
|
AFTER_WORKTREE_BRANCH = 'riddle-proof/' + SAFE_RUN_ID + '-after'
|
|
26
26
|
LEGACY_WORKTREE_DIRS = ('/tmp/riddle-proof-before', '/tmp/riddle-proof-after')
|
|
27
|
+
DEFAULT_SCRATCH_ROOT = '/var/tmp/riddle-proof'
|
|
27
28
|
|
|
28
29
|
if branch.startswith('riddle-proof/'):
|
|
29
30
|
raise SystemExit(
|
|
@@ -158,17 +159,26 @@ def compatible_reuse_source(source_dir, target_dirs):
|
|
|
158
159
|
|
|
159
160
|
|
|
160
161
|
def resolve_worktree_root(repo_dir):
|
|
161
|
-
configured = (
|
|
162
|
+
configured = (os.environ.get('RIDDLE_PROOF_WORKTREE_ROOT') or '').strip()
|
|
162
163
|
if configured:
|
|
163
164
|
return os.path.abspath(os.path.expanduser(configured))
|
|
165
|
+
state_worktree_root = (s.get('worktree_root') or '').strip()
|
|
166
|
+
legacy_tmp_root = os.path.abspath(os.path.join(tempfile.gettempdir(), '.riddle-proof-worktrees'))
|
|
167
|
+
if state_worktree_root and os.path.abspath(os.path.expanduser(state_worktree_root)) != legacy_tmp_root:
|
|
168
|
+
return os.path.abspath(os.path.expanduser(state_worktree_root))
|
|
164
169
|
if os.environ.get('RIDDLE_PROOF_USE_WORKSPACE_WORKTREE_ROOT', '').strip().lower() in ('1', 'true', 'yes'):
|
|
165
170
|
repo_parent = os.path.dirname(os.path.abspath(repo_dir))
|
|
166
171
|
return os.path.join(repo_parent, '.riddle-proof-worktrees')
|
|
167
172
|
|
|
168
|
-
# Proof worktrees are
|
|
169
|
-
#
|
|
170
|
-
#
|
|
171
|
-
|
|
173
|
+
# Proof worktrees and dependency caches are large generated data. Keep
|
|
174
|
+
# them on disk-backed scratch storage by default so tmpfs /tmp remains
|
|
175
|
+
# available for small state files and short-lived artifacts.
|
|
176
|
+
scratch_root = (s.get('scratch_root') or os.environ.get('RIDDLE_PROOF_SCRATCH_ROOT') or '').strip()
|
|
177
|
+
if scratch_root:
|
|
178
|
+
return os.path.join(os.path.abspath(os.path.expanduser(scratch_root)), '.riddle-proof-worktrees')
|
|
179
|
+
if os.environ.get('RIDDLE_PROOF_USE_TMP_SCRATCH', '').strip().lower() in ('1', 'true', 'yes'):
|
|
180
|
+
return os.path.join(tempfile.gettempdir(), 'riddle-proof', '.riddle-proof-worktrees')
|
|
181
|
+
return os.path.join(DEFAULT_SCRATCH_ROOT, '.riddle-proof-worktrees')
|
|
172
182
|
|
|
173
183
|
|
|
174
184
|
def env_flag(name, default=False):
|
|
@@ -202,6 +212,33 @@ def disk_free_bytes(path):
|
|
|
202
212
|
return 0
|
|
203
213
|
|
|
204
214
|
|
|
215
|
+
def disk_snapshot(path):
|
|
216
|
+
probe = path
|
|
217
|
+
while probe and not os.path.exists(probe):
|
|
218
|
+
parent = os.path.dirname(probe)
|
|
219
|
+
if parent == probe:
|
|
220
|
+
break
|
|
221
|
+
probe = parent
|
|
222
|
+
try:
|
|
223
|
+
usage = shutil.disk_usage(probe or tempfile.gettempdir())
|
|
224
|
+
except Exception as exc:
|
|
225
|
+
return {
|
|
226
|
+
'path': path,
|
|
227
|
+
'probe_path': probe or tempfile.gettempdir(),
|
|
228
|
+
'error': str(exc)[:200],
|
|
229
|
+
}
|
|
230
|
+
used = usage.total - usage.free
|
|
231
|
+
percent_used = round((used / usage.total) * 100, 1) if usage.total else 0
|
|
232
|
+
return {
|
|
233
|
+
'path': path,
|
|
234
|
+
'probe_path': probe or tempfile.gettempdir(),
|
|
235
|
+
'total_bytes': usage.total,
|
|
236
|
+
'used_bytes': used,
|
|
237
|
+
'free_bytes': usage.free,
|
|
238
|
+
'percent_used': percent_used,
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
|
|
205
242
|
def prune_scratch_worktrees(worktree_root, keep_dirs, repo_dir):
|
|
206
243
|
report = {
|
|
207
244
|
'requested': True,
|
|
@@ -475,16 +512,24 @@ s['branch'] = branch
|
|
|
475
512
|
s['target_branch'] = target_branch
|
|
476
513
|
s['ship_target_branch'] = target_branch
|
|
477
514
|
s['worktree_root'] = WORKTREE_ROOT
|
|
515
|
+
s['scratch_root'] = os.path.dirname(WORKTREE_ROOT)
|
|
516
|
+
try:
|
|
517
|
+
cache_result = workspace_core('dependency-cache-root', {'projectDir': AFTER_DIR}, timeout=30)
|
|
518
|
+
s['dependency_cache_root'] = cache_result.get('cacheRoot') or ''
|
|
519
|
+
except Exception as exc:
|
|
520
|
+
s['dependency_cache_root_error'] = str(exc)[:200]
|
|
478
521
|
capture_hint = apply_capture_hint(s)
|
|
479
522
|
if capture_hint and capture_hint.get('applied_fields'):
|
|
480
523
|
print('Applied last-good capture hint: ' + ', '.join(capture_hint.get('applied_fields') or []))
|
|
481
524
|
save_state(s)
|
|
482
525
|
print('Prepared workspace via ' + setup.get('source', 'workspace_core') + ': ' + repo_dir)
|
|
483
526
|
os.makedirs(WORKTREE_ROOT, exist_ok=True)
|
|
527
|
+
s['scratch_disk_before_cleanup'] = disk_snapshot(WORKTREE_ROOT)
|
|
484
528
|
scratch_cleanup = prune_scratch_worktrees(WORKTREE_ROOT, (BEFORE_DIR, AFTER_DIR), repo_dir)
|
|
485
529
|
if scratch_cleanup.get('removed') or scratch_cleanup.get('errors'):
|
|
486
530
|
print('Scratch cleanup: removed ' + str(len(scratch_cleanup.get('removed') or [])) + ' stale proof worktree(s)')
|
|
487
531
|
s['scratch_cleanup'] = scratch_cleanup
|
|
532
|
+
s['scratch_disk_after_cleanup'] = disk_snapshot(WORKTREE_ROOT)
|
|
488
533
|
save_state(s)
|
|
489
534
|
cleanup_legacy_branch_worktrees(repo_dir, base_branch)
|
|
490
535
|
|
|
@@ -605,6 +650,7 @@ s['dependency_install'] = {
|
|
|
605
650
|
'before': before_dep_status,
|
|
606
651
|
'after': after_dep_status,
|
|
607
652
|
}
|
|
653
|
+
s['scratch_disk_after_setup'] = disk_snapshot(WORKTREE_ROOT)
|
|
608
654
|
if not (s.get('capture_script') or '').strip():
|
|
609
655
|
s['proof_plan_status'] = 'pending_recon'
|
|
610
656
|
save_state(s)
|