@riddledc/riddle-proof 0.5.22 → 0.5.23
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-M4MISBQV.js} +11 -1
- package/dist/engine-harness.cjs +11 -1
- package/dist/engine-harness.js +1 -1
- package/dist/index.cjs +11 -1
- 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
|
@@ -124,6 +124,16 @@ function fullRiddleState(result, state) {
|
|
|
124
124
|
function workdirFromState(state) {
|
|
125
125
|
return nonEmptyString(state?.after_worktree) || nonEmptyString(state?.worktree_path) || null;
|
|
126
126
|
}
|
|
127
|
+
function parseGitStatusPaths(status) {
|
|
128
|
+
return status.split(/\r?\n/).map((line) => line.trimEnd()).filter(Boolean).map((line) => {
|
|
129
|
+
let item = line.length > 3 ? line.slice(3) : line;
|
|
130
|
+
if (item.includes(" -> ")) item = item.split(" -> ").pop() || item;
|
|
131
|
+
return item.trim();
|
|
132
|
+
}).filter(Boolean);
|
|
133
|
+
}
|
|
134
|
+
function isToolNoisePath(filePath) {
|
|
135
|
+
return filePath === ".codex" || filePath.startsWith(".codex/") || filePath === ".oc-smoke" || filePath.startsWith(".oc-smoke/");
|
|
136
|
+
}
|
|
127
137
|
function hasGitDiff(workdir) {
|
|
128
138
|
if (!workdir || !existsSync(workdir)) return false;
|
|
129
139
|
try {
|
|
@@ -132,7 +142,7 @@ function hasGitDiff(workdir) {
|
|
|
132
142
|
encoding: "utf-8",
|
|
133
143
|
timeout: 1e4
|
|
134
144
|
});
|
|
135
|
-
return status.
|
|
145
|
+
return parseGitStatusPaths(status).some((filePath) => !isToolNoisePath(filePath));
|
|
136
146
|
} catch {
|
|
137
147
|
return false;
|
|
138
148
|
}
|
package/dist/engine-harness.cjs
CHANGED
|
@@ -3126,6 +3126,16 @@ function fullRiddleState(result, state) {
|
|
|
3126
3126
|
function workdirFromState(state) {
|
|
3127
3127
|
return nonEmptyString(state?.after_worktree) || nonEmptyString(state?.worktree_path) || null;
|
|
3128
3128
|
}
|
|
3129
|
+
function parseGitStatusPaths(status) {
|
|
3130
|
+
return status.split(/\r?\n/).map((line) => line.trimEnd()).filter(Boolean).map((line) => {
|
|
3131
|
+
let item = line.length > 3 ? line.slice(3) : line;
|
|
3132
|
+
if (item.includes(" -> ")) item = item.split(" -> ").pop() || item;
|
|
3133
|
+
return item.trim();
|
|
3134
|
+
}).filter(Boolean);
|
|
3135
|
+
}
|
|
3136
|
+
function isToolNoisePath(filePath) {
|
|
3137
|
+
return filePath === ".codex" || filePath.startsWith(".codex/") || filePath === ".oc-smoke" || filePath.startsWith(".oc-smoke/");
|
|
3138
|
+
}
|
|
3129
3139
|
function hasGitDiff(workdir) {
|
|
3130
3140
|
if (!workdir || !(0, import_node_fs3.existsSync)(workdir)) return false;
|
|
3131
3141
|
try {
|
|
@@ -3134,7 +3144,7 @@ function hasGitDiff(workdir) {
|
|
|
3134
3144
|
encoding: "utf-8",
|
|
3135
3145
|
timeout: 1e4
|
|
3136
3146
|
});
|
|
3137
|
-
return status.
|
|
3147
|
+
return parseGitStatusPaths(status).some((filePath) => !isToolNoisePath(filePath));
|
|
3138
3148
|
} catch {
|
|
3139
3149
|
return false;
|
|
3140
3150
|
}
|
package/dist/engine-harness.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -3682,6 +3682,16 @@ function fullRiddleState(result, state) {
|
|
|
3682
3682
|
function workdirFromState(state) {
|
|
3683
3683
|
return nonEmptyString(state?.after_worktree) || nonEmptyString(state?.worktree_path) || null;
|
|
3684
3684
|
}
|
|
3685
|
+
function parseGitStatusPaths(status) {
|
|
3686
|
+
return status.split(/\r?\n/).map((line) => line.trimEnd()).filter(Boolean).map((line) => {
|
|
3687
|
+
let item = line.length > 3 ? line.slice(3) : line;
|
|
3688
|
+
if (item.includes(" -> ")) item = item.split(" -> ").pop() || item;
|
|
3689
|
+
return item.trim();
|
|
3690
|
+
}).filter(Boolean);
|
|
3691
|
+
}
|
|
3692
|
+
function isToolNoisePath(filePath) {
|
|
3693
|
+
return filePath === ".codex" || filePath.startsWith(".codex/") || filePath === ".oc-smoke" || filePath.startsWith(".oc-smoke/");
|
|
3694
|
+
}
|
|
3685
3695
|
function hasGitDiff(workdir) {
|
|
3686
3696
|
if (!workdir || !(0, import_node_fs3.existsSync)(workdir)) return false;
|
|
3687
3697
|
try {
|
|
@@ -3690,7 +3700,7 @@ function hasGitDiff(workdir) {
|
|
|
3690
3700
|
encoding: "utf-8",
|
|
3691
3701
|
timeout: 1e4
|
|
3692
3702
|
});
|
|
3693
|
-
return status.
|
|
3703
|
+
return parseGitStatusPaths(status).some((filePath) => !isToolNoisePath(filePath));
|
|
3694
3704
|
} catch {
|
|
3695
3705
|
return false;
|
|
3696
3706
|
}
|
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(),
|