@riddledc/riddle-proof 0.5.22 → 0.5.24
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-PJ3RTT5D.js → chunk-46355FJD.js} +25 -2
- package/dist/engine-harness.cjs +25 -2
- package/dist/engine-harness.js +1 -1
- package/dist/index.cjs +25 -2
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/runtime/lib/implement.py +23 -4
- package/runtime/tests/recon_verify_smoke.py +52 -0
|
@@ -89,8 +89,20 @@ function loadRunState(input) {
|
|
|
89
89
|
state_path: statePath
|
|
90
90
|
});
|
|
91
91
|
}
|
|
92
|
+
function isProtectedFinalStatus(status) {
|
|
93
|
+
return status === "ready_to_ship" || status === "shipped" || status === "completed";
|
|
94
|
+
}
|
|
95
|
+
function shouldPreserveFinalizedRunState(filePath, incoming) {
|
|
96
|
+
const existing = readJson(filePath);
|
|
97
|
+
if (!existing?.finalized || !isProtectedFinalStatus(existing.status)) return false;
|
|
98
|
+
if (!incoming.finalized) return true;
|
|
99
|
+
if (existing.status === incoming.status) return false;
|
|
100
|
+
return !(existing.status === "ready_to_ship" && incoming.status === "shipped");
|
|
101
|
+
}
|
|
92
102
|
function persist(state) {
|
|
93
|
-
if (state.state_path)
|
|
103
|
+
if (!state.state_path) return;
|
|
104
|
+
if (shouldPreserveFinalizedRunState(state.state_path, state)) return;
|
|
105
|
+
writeJson(state.state_path, state);
|
|
94
106
|
}
|
|
95
107
|
function recordEvent(state, event) {
|
|
96
108
|
appendRunEvent(state, event);
|
|
@@ -124,6 +136,16 @@ function fullRiddleState(result, state) {
|
|
|
124
136
|
function workdirFromState(state) {
|
|
125
137
|
return nonEmptyString(state?.after_worktree) || nonEmptyString(state?.worktree_path) || null;
|
|
126
138
|
}
|
|
139
|
+
function parseGitStatusPaths(status) {
|
|
140
|
+
return status.split(/\r?\n/).map((line) => line.trimEnd()).filter(Boolean).map((line) => {
|
|
141
|
+
let item = line.length > 3 ? line.slice(3) : line;
|
|
142
|
+
if (item.includes(" -> ")) item = item.split(" -> ").pop() || item;
|
|
143
|
+
return item.trim();
|
|
144
|
+
}).filter(Boolean);
|
|
145
|
+
}
|
|
146
|
+
function isToolNoisePath(filePath) {
|
|
147
|
+
return filePath === ".codex" || filePath.startsWith(".codex/") || filePath === ".oc-smoke" || filePath.startsWith(".oc-smoke/");
|
|
148
|
+
}
|
|
127
149
|
function hasGitDiff(workdir) {
|
|
128
150
|
if (!workdir || !existsSync(workdir)) return false;
|
|
129
151
|
try {
|
|
@@ -132,7 +154,7 @@ function hasGitDiff(workdir) {
|
|
|
132
154
|
encoding: "utf-8",
|
|
133
155
|
timeout: 1e4
|
|
134
156
|
});
|
|
135
|
-
return status.
|
|
157
|
+
return parseGitStatusPaths(status).some((filePath) => !isToolNoisePath(filePath));
|
|
136
158
|
} catch {
|
|
137
159
|
return false;
|
|
138
160
|
}
|
|
@@ -315,6 +337,7 @@ function engineFailureBlocker(result, checkpoint) {
|
|
|
315
337
|
}
|
|
316
338
|
function terminalResult(state, status, result, summary, raw = {}) {
|
|
317
339
|
setRunStatus(state, status);
|
|
340
|
+
if (isProtectedFinalStatus(status)) state.finalized = true;
|
|
318
341
|
const metadata = normalizeTerminalMetadata({
|
|
319
342
|
riddleState: result ? fullRiddleState(result, state) : null,
|
|
320
343
|
engineResult: result
|
package/dist/engine-harness.cjs
CHANGED
|
@@ -3091,8 +3091,20 @@ function loadRunState(input) {
|
|
|
3091
3091
|
state_path: statePath
|
|
3092
3092
|
});
|
|
3093
3093
|
}
|
|
3094
|
+
function isProtectedFinalStatus(status) {
|
|
3095
|
+
return status === "ready_to_ship" || status === "shipped" || status === "completed";
|
|
3096
|
+
}
|
|
3097
|
+
function shouldPreserveFinalizedRunState(filePath, incoming) {
|
|
3098
|
+
const existing = readJson(filePath);
|
|
3099
|
+
if (!existing?.finalized || !isProtectedFinalStatus(existing.status)) return false;
|
|
3100
|
+
if (!incoming.finalized) return true;
|
|
3101
|
+
if (existing.status === incoming.status) return false;
|
|
3102
|
+
return !(existing.status === "ready_to_ship" && incoming.status === "shipped");
|
|
3103
|
+
}
|
|
3094
3104
|
function persist(state) {
|
|
3095
|
-
if (state.state_path)
|
|
3105
|
+
if (!state.state_path) return;
|
|
3106
|
+
if (shouldPreserveFinalizedRunState(state.state_path, state)) return;
|
|
3107
|
+
writeJson(state.state_path, state);
|
|
3096
3108
|
}
|
|
3097
3109
|
function recordEvent(state, event) {
|
|
3098
3110
|
appendRunEvent(state, event);
|
|
@@ -3126,6 +3138,16 @@ function fullRiddleState(result, state) {
|
|
|
3126
3138
|
function workdirFromState(state) {
|
|
3127
3139
|
return nonEmptyString(state?.after_worktree) || nonEmptyString(state?.worktree_path) || null;
|
|
3128
3140
|
}
|
|
3141
|
+
function parseGitStatusPaths(status) {
|
|
3142
|
+
return status.split(/\r?\n/).map((line) => line.trimEnd()).filter(Boolean).map((line) => {
|
|
3143
|
+
let item = line.length > 3 ? line.slice(3) : line;
|
|
3144
|
+
if (item.includes(" -> ")) item = item.split(" -> ").pop() || item;
|
|
3145
|
+
return item.trim();
|
|
3146
|
+
}).filter(Boolean);
|
|
3147
|
+
}
|
|
3148
|
+
function isToolNoisePath(filePath) {
|
|
3149
|
+
return filePath === ".codex" || filePath.startsWith(".codex/") || filePath === ".oc-smoke" || filePath.startsWith(".oc-smoke/");
|
|
3150
|
+
}
|
|
3129
3151
|
function hasGitDiff(workdir) {
|
|
3130
3152
|
if (!workdir || !(0, import_node_fs3.existsSync)(workdir)) return false;
|
|
3131
3153
|
try {
|
|
@@ -3134,7 +3156,7 @@ function hasGitDiff(workdir) {
|
|
|
3134
3156
|
encoding: "utf-8",
|
|
3135
3157
|
timeout: 1e4
|
|
3136
3158
|
});
|
|
3137
|
-
return status.
|
|
3159
|
+
return parseGitStatusPaths(status).some((filePath) => !isToolNoisePath(filePath));
|
|
3138
3160
|
} catch {
|
|
3139
3161
|
return false;
|
|
3140
3162
|
}
|
|
@@ -3317,6 +3339,7 @@ function engineFailureBlocker(result, checkpoint) {
|
|
|
3317
3339
|
}
|
|
3318
3340
|
function terminalResult(state, status, result, summary, raw = {}) {
|
|
3319
3341
|
setRunStatus(state, status);
|
|
3342
|
+
if (isProtectedFinalStatus(status)) state.finalized = true;
|
|
3320
3343
|
const metadata = normalizeTerminalMetadata({
|
|
3321
3344
|
riddleState: result ? fullRiddleState(result, state) : null,
|
|
3322
3345
|
engineResult: result
|
package/dist/engine-harness.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -3647,8 +3647,20 @@ function loadRunState(input) {
|
|
|
3647
3647
|
state_path: statePath
|
|
3648
3648
|
});
|
|
3649
3649
|
}
|
|
3650
|
+
function isProtectedFinalStatus(status) {
|
|
3651
|
+
return status === "ready_to_ship" || status === "shipped" || status === "completed";
|
|
3652
|
+
}
|
|
3653
|
+
function shouldPreserveFinalizedRunState(filePath, incoming) {
|
|
3654
|
+
const existing = readJson(filePath);
|
|
3655
|
+
if (!existing?.finalized || !isProtectedFinalStatus(existing.status)) return false;
|
|
3656
|
+
if (!incoming.finalized) return true;
|
|
3657
|
+
if (existing.status === incoming.status) return false;
|
|
3658
|
+
return !(existing.status === "ready_to_ship" && incoming.status === "shipped");
|
|
3659
|
+
}
|
|
3650
3660
|
function persist(state) {
|
|
3651
|
-
if (state.state_path)
|
|
3661
|
+
if (!state.state_path) return;
|
|
3662
|
+
if (shouldPreserveFinalizedRunState(state.state_path, state)) return;
|
|
3663
|
+
writeJson(state.state_path, state);
|
|
3652
3664
|
}
|
|
3653
3665
|
function recordEvent(state, event) {
|
|
3654
3666
|
appendRunEvent(state, event);
|
|
@@ -3682,6 +3694,16 @@ function fullRiddleState(result, state) {
|
|
|
3682
3694
|
function workdirFromState(state) {
|
|
3683
3695
|
return nonEmptyString(state?.after_worktree) || nonEmptyString(state?.worktree_path) || null;
|
|
3684
3696
|
}
|
|
3697
|
+
function parseGitStatusPaths(status) {
|
|
3698
|
+
return status.split(/\r?\n/).map((line) => line.trimEnd()).filter(Boolean).map((line) => {
|
|
3699
|
+
let item = line.length > 3 ? line.slice(3) : line;
|
|
3700
|
+
if (item.includes(" -> ")) item = item.split(" -> ").pop() || item;
|
|
3701
|
+
return item.trim();
|
|
3702
|
+
}).filter(Boolean);
|
|
3703
|
+
}
|
|
3704
|
+
function isToolNoisePath(filePath) {
|
|
3705
|
+
return filePath === ".codex" || filePath.startsWith(".codex/") || filePath === ".oc-smoke" || filePath.startsWith(".oc-smoke/");
|
|
3706
|
+
}
|
|
3685
3707
|
function hasGitDiff(workdir) {
|
|
3686
3708
|
if (!workdir || !(0, import_node_fs3.existsSync)(workdir)) return false;
|
|
3687
3709
|
try {
|
|
@@ -3690,7 +3712,7 @@ function hasGitDiff(workdir) {
|
|
|
3690
3712
|
encoding: "utf-8",
|
|
3691
3713
|
timeout: 1e4
|
|
3692
3714
|
});
|
|
3693
|
-
return status.
|
|
3715
|
+
return parseGitStatusPaths(status).some((filePath) => !isToolNoisePath(filePath));
|
|
3694
3716
|
} catch {
|
|
3695
3717
|
return false;
|
|
3696
3718
|
}
|
|
@@ -3873,6 +3895,7 @@ function engineFailureBlocker(result, checkpoint) {
|
|
|
3873
3895
|
}
|
|
3874
3896
|
function terminalResult(state, status, result, summary, raw = {}) {
|
|
3875
3897
|
setRunStatus(state, status);
|
|
3898
|
+
if (isProtectedFinalStatus(status)) state.finalized = true;
|
|
3876
3899
|
const metadata = normalizeTerminalMetadata({
|
|
3877
3900
|
riddleState: result ? fullRiddleState(result, state) : null,
|
|
3878
3901
|
engineResult: result
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
package/runtime/lib/implement.py
CHANGED
|
@@ -9,6 +9,8 @@ import json, os, sys
|
|
|
9
9
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
10
10
|
from util import load_state, save_state, git, shell_quote
|
|
11
11
|
|
|
12
|
+
TOOL_NOISE_PATHS = ('.codex', '.oc-smoke')
|
|
13
|
+
|
|
12
14
|
|
|
13
15
|
def unique_nonempty(items):
|
|
14
16
|
seen = set()
|
|
@@ -37,6 +39,15 @@ def parse_status_paths(lines):
|
|
|
37
39
|
return unique_nonempty(paths)
|
|
38
40
|
|
|
39
41
|
|
|
42
|
+
def is_tool_noise_path(path):
|
|
43
|
+
text = str(path or '').strip()
|
|
44
|
+
return any(text == prefix or text.startswith(prefix + '/') for prefix in TOOL_NOISE_PATHS)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def material_paths(paths):
|
|
48
|
+
return [path for path in unique_nonempty(paths) if not is_tool_noise_path(path)]
|
|
49
|
+
|
|
50
|
+
|
|
40
51
|
s = load_state()
|
|
41
52
|
after_dir = (s.get('after_worktree') or '').strip()
|
|
42
53
|
if not after_dir or not os.path.exists(after_dir):
|
|
@@ -45,7 +56,9 @@ if not after_dir or not os.path.exists(after_dir):
|
|
|
45
56
|
base_branch = s.get('base_branch', 'main')
|
|
46
57
|
base_ref = (s.get('before_ref') or '').strip() or ('origin/' + base_branch)
|
|
47
58
|
dirty = [ln for ln in git('git status --short', after_dir).stdout.splitlines() if ln.strip()]
|
|
48
|
-
|
|
59
|
+
dirty_paths_all = parse_status_paths(dirty)
|
|
60
|
+
dirty_paths = material_paths(dirty_paths_all)
|
|
61
|
+
ignored_dirty_paths = [path for path in dirty_paths_all if is_tool_noise_path(path)]
|
|
49
62
|
|
|
50
63
|
diff_probes = []
|
|
51
64
|
|
|
@@ -70,7 +83,9 @@ if diff_result.returncode != 0:
|
|
|
70
83
|
if diff_result.returncode != 0 and not committed:
|
|
71
84
|
fallback, committed = run_diff_probe('head_parent', 'git diff --name-only HEAD~1 HEAD')
|
|
72
85
|
|
|
73
|
-
|
|
86
|
+
committed_material = material_paths(committed)
|
|
87
|
+
ignored_committed_paths = [path for path in committed if is_tool_noise_path(path)]
|
|
88
|
+
changed = unique_nonempty(dirty_paths + committed_material)
|
|
74
89
|
authored = bool((s.get('capture_script') or '').strip()) and bool((s.get('proof_plan') or '').strip())
|
|
75
90
|
|
|
76
91
|
detection = {
|
|
@@ -81,9 +96,13 @@ detection = {
|
|
|
81
96
|
'base_ref_requested': base_ref,
|
|
82
97
|
'dirty_status_lines': dirty[:20],
|
|
83
98
|
'dirty_paths': dirty_paths[:20],
|
|
99
|
+
'ignored_dirty_paths': ignored_dirty_paths[:20],
|
|
84
100
|
'dirty_path_count': len(dirty_paths),
|
|
85
|
-
'
|
|
86
|
-
'
|
|
101
|
+
'dirty_path_count_including_noise': len(dirty_paths_all),
|
|
102
|
+
'committed_paths': committed_material[:20],
|
|
103
|
+
'ignored_committed_paths': ignored_committed_paths[:20],
|
|
104
|
+
'committed_path_count': len(committed_material),
|
|
105
|
+
'committed_path_count_including_noise': len(committed),
|
|
87
106
|
'changed_paths': changed[:20],
|
|
88
107
|
'changed_path_count': len(changed),
|
|
89
108
|
'diff_probes': diff_probes[:6],
|
|
@@ -637,6 +637,7 @@ def run_implement_records_detection_when_changes_missing():
|
|
|
637
637
|
})
|
|
638
638
|
write_state(state_path, state)
|
|
639
639
|
os.environ['RIDDLE_PROOF_STATE_FILE'] = str(state_path)
|
|
640
|
+
load_module('util', UTIL_PATH)
|
|
640
641
|
|
|
641
642
|
try:
|
|
642
643
|
load_module('implement_changes_missing_state', IMPLEMENT_PATH)
|
|
@@ -673,6 +674,56 @@ def run_implement_records_detection_when_changes_missing():
|
|
|
673
674
|
shutil.rmtree(tempdir, ignore_errors=True)
|
|
674
675
|
|
|
675
676
|
|
|
677
|
+
def run_implement_ignores_tool_noise_when_detecting_changes():
|
|
678
|
+
tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-implement-noise-'))
|
|
679
|
+
state_path = tempdir / 'state.json'
|
|
680
|
+
previous_state_file = os.environ.get('RIDDLE_PROOF_STATE_FILE')
|
|
681
|
+
try:
|
|
682
|
+
state = base_state(tempdir, reference='before')
|
|
683
|
+
after_dir = Path(state['after_worktree'])
|
|
684
|
+
init_git_repo(after_dir)
|
|
685
|
+
codex_dir = after_dir / '.codex'
|
|
686
|
+
codex_dir.mkdir(parents=True, exist_ok=True)
|
|
687
|
+
(codex_dir / 'session.json').write_text('{}\n')
|
|
688
|
+
state.update({
|
|
689
|
+
'recon_status': 'ready_for_proof_plan',
|
|
690
|
+
'author_status': 'ready',
|
|
691
|
+
'proof_plan_status': 'ready',
|
|
692
|
+
'proof_plan': 'Capture the pricing CTA after the implementation is applied.',
|
|
693
|
+
'capture_script': "await page.waitForSelector('[data-testid=pricing-cta]'); await saveScreenshot('after-proof');",
|
|
694
|
+
})
|
|
695
|
+
write_state(state_path, state)
|
|
696
|
+
os.environ['RIDDLE_PROOF_STATE_FILE'] = str(state_path)
|
|
697
|
+
load_module('util', UTIL_PATH)
|
|
698
|
+
|
|
699
|
+
try:
|
|
700
|
+
load_module('implement_ignores_tool_noise', IMPLEMENT_PATH)
|
|
701
|
+
except SystemExit as exc:
|
|
702
|
+
assert 'No implementation detected on the after worktree.' in str(exc), exc
|
|
703
|
+
else:
|
|
704
|
+
raise AssertionError('implement stage should have halted when only tool noise changed')
|
|
705
|
+
|
|
706
|
+
after_state = json.loads(state_path.read_text())
|
|
707
|
+
detection = after_state['implementation_detection']
|
|
708
|
+
assert detection['outcome'] == 'no_changes_detected'
|
|
709
|
+
assert detection['diff_detected'] is False
|
|
710
|
+
assert detection['dirty_path_count'] == 0
|
|
711
|
+
assert detection['dirty_path_count_including_noise'] >= 1
|
|
712
|
+
assert any(str(path).startswith('.codex') for path in detection['ignored_dirty_paths'])
|
|
713
|
+
assert detection['changed_path_count'] == 0
|
|
714
|
+
assert after_state['changed_files'] == []
|
|
715
|
+
return {
|
|
716
|
+
'ok': True,
|
|
717
|
+
'ignored_dirty_paths': detection['ignored_dirty_paths'],
|
|
718
|
+
}
|
|
719
|
+
finally:
|
|
720
|
+
if previous_state_file is None:
|
|
721
|
+
os.environ.pop('RIDDLE_PROOF_STATE_FILE', None)
|
|
722
|
+
else:
|
|
723
|
+
os.environ['RIDDLE_PROOF_STATE_FILE'] = previous_state_file
|
|
724
|
+
shutil.rmtree(tempdir, ignore_errors=True)
|
|
725
|
+
|
|
726
|
+
|
|
676
727
|
def run_recon_then_author_request():
|
|
677
728
|
tempdir = Path(tempfile.mkdtemp(prefix='riddle-proof-supervisor-request-'))
|
|
678
729
|
state_path = tempdir / 'state.json'
|
|
@@ -1481,6 +1532,7 @@ if __name__ == '__main__':
|
|
|
1481
1532
|
'apply_auth_context': run_apply_auth_context_passes_supported_auth_payloads(),
|
|
1482
1533
|
'run_project_build_retries_after_clean_failure': run_project_build_retries_after_clean_failure(),
|
|
1483
1534
|
'implement_records_detection_when_changes_missing': run_implement_records_detection_when_changes_missing(),
|
|
1535
|
+
'implement_ignores_tool_noise_when_detecting_changes': run_implement_ignores_tool_noise_when_detecting_changes(),
|
|
1484
1536
|
'verify_quality_ignores_proof_telemetry_console_text': run_verify_quality_ignores_proof_telemetry_console_text(),
|
|
1485
1537
|
'recon_then_author_request': run_recon_then_author_request(),
|
|
1486
1538
|
'recon_preserves_query_route': run_recon_preserves_query_route(),
|