-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcontracts.sh
More file actions
executable file
·575 lines (540 loc) · 33.3 KB
/
Copy pathcontracts.sh
File metadata and controls
executable file
·575 lines (540 loc) · 33.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
#!/usr/bin/env bash
# completely :: contract tests — assert the harness's deterministic contracts actually bite.
# "TDD for the process" (Maslennikov): test the contracts, not the model. Backend for `cmpl test`.
#
# Covers what is verifiable without a live agent: guard, sync idempotency, lint, emit, doctor.
# Live-agent contracts (matrix-before-delegate / real parallel spawn / closeout rejects no-evidence)
# are SKIPPED with a clear marker — they need a real session, and are NOT silently dropped.
set -uo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)" # plugin root
PASS=0; FAIL=0; SKIP=0
ok() { echo " PASS $1"; PASS=$((PASS+1)); }
no() { echo " FAIL $1"; FAIL=$((FAIL+1)); }
skip() { echo " SKIP $1"; SKIP=$((SKIP+1)); }
mktmp(){ local d; d=$(mktemp -d /tmp/cmptestXXXXXX); ( cd "$d" && git init -q 2>/dev/null && bd init proj --stealth >/dev/null 2>&1 ); printf '%s' "$d"; }
count(){ ( cd "$1" && bd list --all --json 2>/dev/null | python3 -c 'import json,sys
d=json.load(sys.stdin); print(len(d if isinstance(d,list) else d.get("issues",[])))' ); }
echo "== guard-dangerous =="
g(){ printf '{"tool_input":{"command":%s}}' "$(python3 -c 'import json,sys;print(json.dumps(sys.argv[1]))' "$1")" \
| bash "$ROOT/hooks/guard-dangerous.sh" >/dev/null 2>&1; echo $?; }
[ "$(g 'rm -rf /')" = 2 ] && ok "blocks rm -rf" || no "blocks rm -rf"
[ "$(g 'git push --force')" = 2 ] && ok "blocks force-push" || no "blocks force-push"
[ "$(g 'DROP TABLE users;')" = 2 ] && ok "blocks DROP TABLE" || no "blocks DROP TABLE"
[ "$(g 'ls -la')" = 0 ] && ok "allows ls" || no "allows ls"
echo "== bd-close gate (commit-before-close) =="
GD=$(mktmp)
( cd "$GD" && git -c user.email=t@t -c user.name=t commit -qm init --allow-empty 2>/dev/null )
gc(){ printf '{"tool_input":{"command":%s}}' "$(python3 -c 'import json,sys;print(json.dumps(sys.argv[1]))' "$1")" \
| ( cd "$GD" && bash "$ROOT/hooks/guard-close.sh" >/dev/null 2>&1 ); echo $?; }
gco(){ printf '{"tool_input":{"command":%s}}' "$(python3 -c 'import json,sys;print(json.dumps(sys.argv[1]))' "$1")" \
| ( cd "$GD" && CMP_ALLOW_DIRTY_CLOSE=1 bash "$ROOT/hooks/guard-close.sh" >/dev/null 2>&1 ); echo $?; }
[ "$(gc 'bd close abc-1')" = 0 ] && ok "close allowed on clean tree" || no "close clean allow"
[ "$(gc 'bd ready')" = 0 ] && ok "gate ignores non-close bd commands" || no "close gate over-broad"
( cd "$GD" && echo x > f.txt && git add f.txt )
[ "$(gc 'bd close abc-1')" = 2 ] && ok "close BLOCKED on uncommitted tracked changes" || no "close dirty block"
[ "$(gc 'bd update abc-1 --status=closed')" = 2 ] && ok "gate also catches --status=closed (equals form)" || no "close equals-form block"
[ "$(gco 'bd close abc-1')" = 0 ] && ok "CMP_ALLOW_DIRTY_CLOSE overrides the gate" || no "close override"
rm -rf "$GD"
echo "== sync idempotency =="
D=$(mktmp); printf -- '- [ ] alpha\n- [x] beta\n' > "$D/IMPLEMENTATION_PLAN.md"
bash "$ROOT/scripts/sync.sh" "$D" >/dev/null 2>&1; n1=$(count "$D")
bash "$ROOT/scripts/sync.sh" "$D" >/dev/null 2>&1; n2=$(count "$D")
{ [ "$n1" = 2 ] && [ "$n2" = 2 ]; } && ok "sync upserts 2, no dupes ($n1->$n2)" || no "sync idempotency ($n1->$n2)"
rm -rf "$D"
echo "== lint worker-contract =="
D=$(mktmp); ( cd "$D" && bd create "bad" -t task >/dev/null 2>&1 )
( cd "$D" && bash "$ROOT/scripts/lint.sh" >/dev/null 2>&1 ) && r=0 || r=1
[ "$r" = 1 ] && ok "lint FAILs on missing contract" || no "lint FAILs on missing contract"
( cd "$D" && BAD=$(bd list --json | python3 -c 'import json,sys
d=json.load(sys.stdin); d=d if isinstance(d,list) else d.get("issues",[])
print([i["id"] for i in d if i["title"]=="bad"][0])'); bd close "$BAD" >/dev/null 2>&1
bd create "good" -t task --acceptance "x works" --design "approach" --metadata '{"write_zone":["a.ts"],"verify":"npm test"}' >/dev/null 2>&1 )
( cd "$D" && bash "$ROOT/scripts/lint.sh" >/dev/null 2>&1 ) && r=0 || r=1
[ "$r" = 0 ] && ok "lint PASSes when contract present" || no "lint PASSes when contract present"
rm -rf "$D"
echo "== lint: metadata.verify required + entrypoint real-path floor =="
D=$(mktmp)
( cd "$D" && bd create "nv" -t task --acceptance x --design y --metadata '{"write_zone":["a.ts"]}' >/dev/null 2>&1 )
( cd "$D" && bash "$ROOT/scripts/lint.sh" >/dev/null 2>&1 ) && rv=0 || rv=1
[ "$rv" = 1 ] && ok "lint FAILs on missing metadata.verify" || no "lint missing-verify"
( cd "$D" && nv=$(bd list --json | python3 -c 'import json,sys
d=json.load(sys.stdin); d=d if isinstance(d,list) else d.get("issues",[])
print([i["id"] for i in d if i["title"]=="nv"][0])'); bd close "$nv" >/dev/null 2>&1 )
( cd "$D" && bd create "epx" -t task --acceptance x --design y --metadata '{"write_zone":["plugin/scripts/run.sh"],"verify":"pytest tests/test_x.py"}' >/dev/null 2>&1 )
( cd "$D" && bash "$ROOT/scripts/lint.sh" >/dev/null 2>&1 ) && rv=0 || rv=1
[ "$rv" = 1 ] && ok "lint FAILs entrypoint task with proxy verify" || no "lint entrypoint-proxy-verify"
( cd "$D" && ep=$(bd list --json | python3 -c 'import json,sys
d=json.load(sys.stdin); d=d if isinstance(d,list) else d.get("issues",[])
print([i["id"] for i in d if i["title"]=="epx"][0])'); bd close "$ep" >/dev/null 2>&1 )
( cd "$D" && bd create "epr" -t task --acceptance x --design y --metadata '{"write_zone":["plugin/scripts/run.sh"],"verify":"bash plugin/tests/contracts.sh"}' >/dev/null 2>&1 )
( cd "$D" && bash "$ROOT/scripts/lint.sh" >/dev/null 2>&1 ) && rv=0 || rv=1
[ "$rv" = 0 ] && ok "lint PASSes entrypoint task with real-path verify" || no "lint entrypoint-real-verify"
( cd "$D" && bd create "hookx" -t task --acceptance x --design y --metadata '{"write_zone":["plugin/hooks/guard-x.sh"],"verify":"pytest unit"}' >/dev/null 2>&1 )
( cd "$D" && bash "$ROOT/scripts/lint.sh" >/dev/null 2>&1 ) && rv=0 || rv=1
[ "$rv" = 1 ] && ok "lint FAILs hooks-entrypoint task w/ proxy verify (HIGH#1 fix)" || no "lint hooks-entrypoint"
rm -rf "$D"
echo "== cmpl lint self-test (NCR/blocked path — now gated by cmpl test) =="
if bash "$ROOT/scripts/lint.sh" --self-test >/dev/null 2>&1; then ok "lint.sh --self-test green (NCR + blocked + verify-clean)"; else no "lint.sh --self-test"; fi
echo "== emit idempotency =="
D=$(mktmp)
printf '# P\n<tasks>\n<task type="auto"><name>T1</name><files>a.ts</files><action>do</action><verify>t</verify><done>acc</done></task>\n</tasks>\n' > "$D/X-PLAN.md"
( cd "$D" && bash "$ROOT/scripts/emit.sh" X-PLAN.md >/dev/null 2>&1 ); m1=$(count "$D")
( cd "$D" && bash "$ROOT/scripts/emit.sh" X-PLAN.md >/dev/null 2>&1 ); m2=$(count "$D")
{ [ "$m1" = 2 ] && [ "$m2" = 2 ]; } && ok "emit epic+task idempotent ($m1->$m2)" || no "emit idempotency ($m1->$m2)"
rm -rf "$D"
echo "== bridge: GSD frontmatter -> Beads (waves + must_haves) =="
D=$(mktmp)
cat > "$D/09-01-PLAN.md" <<'PLAN'
---
phase: 09-bridge
plan: 01
type: execute
wave: 1
depends_on: []
requirements: [BR-01, BR-02]
must_haves:
truths:
- "emit writes must_haves onto the epic"
artifacts:
- path: "plugin/scripts/emit-gsd.py"
provides: "frontmatter parser"
key_links:
- from: "epic"
to: "evaluator"
---
# Bridge plan 01
<tasks>
<task type="auto">
<name>T1 alpha</name>
<files>a.py</files>
<action>do A</action>
<verify>pytest</verify>
<done>alpha works</done>
</task>
<task type="auto">
<name>T2 beta</name>
<files>b.py</files>
<action>do B</action>
<verify>pytest</verify>
<done>beta works</done>
</task>
</tasks>
PLAN
( cd "$D" && bash "$ROOT/scripts/emit.sh" 09-01-PLAN.md >/dev/null 2>&1 )
EM=$( cd "$D" && bd list --all --json 2>/dev/null | python3 -c '
import json,sys
d=json.load(sys.stdin); d=d if isinstance(d,list) else d.get("issues",[])
ep=[i for i in d if i.get("issue_type")=="epic"]
m=(ep[0].get("metadata") or {}) if ep else {}
print("OK" if (m.get("must_haves") and m.get("requirements")) else "NO")' )
[ "$EM" = OK ] && ok "bridge: epic carries must_haves + requirements" || no "bridge epic metadata ($EM)"
RW=$( cd "$D" && bd ready --json 2>/dev/null | python3 -c '
import json,sys
d=json.load(sys.stdin); d=d if isinstance(d,list) else d.get("issues",[])
t=[i["title"] for i in d if i.get("issue_type")!="epic"]
print("OK" if (any("alpha" in x for x in t) and not any("beta" in x for x in t)) else "NO")' )
[ "$RW" = OK ] && ok "bridge: intra-plan edge — only T1 ready" || no "bridge wave gating ($RW)"
AC=$( cd "$D" && bd list --all --json 2>/dev/null | python3 -c '
import json,sys
d=json.load(sys.stdin); d=d if isinstance(d,list) else d.get("issues",[])
v=[i.get("acceptance_criteria") for i in d if "alpha" in i.get("title","")]
print(v[0] if v else "")' )
[ "$AC" = "alpha works" ] && ok "bridge: acceptance maps from <done>" || no "bridge acceptance source ($AC)"
cat > "$D/09-02-PLAN.md" <<'PLAN'
---
phase: 09-bridge
plan: 02
type: execute
wave: 2
depends_on: [09-bridge-01]
requirements: [BR-03]
must_haves:
truths:
- "second plan exists"
---
# Bridge plan 02
<tasks>
<task type="auto">
<name>T3 gamma</name>
<files>c.py</files>
<action>do C</action>
<verify>pytest</verify>
<done>gamma works</done>
</task>
</tasks>
PLAN
( cd "$D" && bash "$ROOT/scripts/emit.sh" 09-02-PLAN.md >/dev/null 2>&1 )
XP=$( cd "$D" && bd ready --json 2>/dev/null | python3 -c '
import json,sys
d=json.load(sys.stdin); d=d if isinstance(d,list) else d.get("issues",[])
print("OK" if not any("gamma" in i["title"] for i in d) else "NO")' )
[ "$XP" = OK ] && ok "bridge: cross-plan edge gates plan-02 tasks" || no "bridge cross-plan edge ($XP)"
( cd "$D" && bash "$ROOT/scripts/emit.sh" 09-01-PLAN.md >/dev/null 2>&1 )
RE=$( cd "$D" && bd ready --json 2>/dev/null | python3 -c '
import json,sys
d=json.load(sys.stdin); d=d if isinstance(d,list) else d.get("issues",[])
t=[i["title"] for i in d if i.get("issue_type")!="epic"]
print("OK" if (any("alpha" in x for x in t) and not any("beta" in x for x in t) and not any("gamma" in x for x in t)) else "NO")' )
[ "$RE" = OK ] && ok "bridge: re-emit keeps edges stable (idempotent graph)" || no "bridge re-emit idempotency ($RE)"
rm -rf "$D"
echo "== emit-gsd parser: latent edge cases (nested dict-in-list, comma-in-quoted scalar) =="
# Latent in GSD 1.3.1 (always inline dict-in-seq, comma-free ids) but the parser must hold.
PR=$( python3 - "$ROOT/scripts/emit-gsd.py" <<'PY' 2>&1
import importlib.util, sys
spec = importlib.util.spec_from_file_location('eg', sys.argv[1])
m = importlib.util.module_from_spec(spec); spec.loader.exec_module(m)
# (1) seq-dict: first key has a nested mapping block — must NOT drop `path`
fm1 = m.parse_frontmatter('''---
must_haves:
artifacts:
- path:
kind: py
loc: "100"
provides: parser
---
body
''')
arts = fm1.get('must_haves', {}).get('artifacts') or []
first = arts[0] if (arts and isinstance(arts[0], dict)) else {}
ok1 = (len(arts) == 1
and first.get('path') == {'kind': 'py', 'loc': '100'}
and first.get('provides') == 'parser')
# (2) inline list with comma inside a quoted scalar — must NOT split mid-quote
fm2 = m.parse_frontmatter('''---
requirements: [a, "b, c", d]
---
''')
ok2 = fm2.get('requirements') == ['a', 'b, c', 'd']
print('A' if ok1 else 'a-FAIL:%r' % arts, 'B' if ok2 else 'b-FAIL:%r' % fm2.get('requirements'))
PY
)
case "$PR" in
"A B") ok "emit-gsd: seq-dict first-key nested block preserved" ; ok "emit-gsd: inline list respects quotes" ;;
"A "*) ok "emit-gsd: seq-dict first-key nested block preserved" ; no "emit-gsd inline-list quote-aware ($PR)" ;;
*" B") no "emit-gsd seq-dict first-key nested block ($PR)" ; ok "emit-gsd: inline list respects quotes" ;;
*) no "emit-gsd parser edge cases ($PR)" ; no "emit-gsd parser edge cases ($PR)" ;;
esac
echo "== run.sh land-guard (git identity so per-task commits land) =="
D=$(mktmp)
( cd "$D" && bd create "t" -t task --acceptance a --design d --metadata '{"write_zone":["x"]}' >/dev/null 2>&1 )
( cd "$D" && GIT_CONFIG_GLOBAL=/dev/null GIT_CONFIG_SYSTEM=/dev/null CMP_CLAUDE_CMD="true" \
bash "$ROOT/scripts/run.sh" --dry-run >/dev/null 2>&1 )
GI=$( cd "$D" && GIT_CONFIG_GLOBAL=/dev/null git config user.email 2>/dev/null )
[ -n "$GI" ] && ok "run.sh ensures a git identity before the loop ($GI)" || no "run.sh land-guard (no identity set)"
rm -rf "$D"
echo "== user-perceived correctness (hll: evaluator exercises as a user, no-run==FAIL) =="
if grep -qi 'user-perceived' "$ROOT/agents/evaluator.md" \
&& grep -qiE 'No run.*== *FAIL|no observed behavior' "$ROOT/agents/evaluator.md"; then
ok "evaluator.md has the User-Perceived dimension (no run / no observed behavior == FAIL)"
else
no "evaluator.md missing user-perceived dimension / no-run-FAIL rule"
fi
if grep -qi 'user-perceived' "$ROOT/core/task-engine.md"; then
ok "task-engine VERIFY step wires user-perceived correctness"
else
no "task-engine VERIFY missing user-perceived wiring"
fi
if CMP_RUN_PROMPT=/dev/null bash "$ROOT/scripts/run.sh" --show-prompt DEMO 2>/dev/null | grep -qi 'USER-PERCEIVED correctness'; then
ok "worker prompt injects user-perceived requirement at step=verify (enforced, not doc-only)"
else
no "user-perceived not injected into worker prompt"
fi
if grep -qi 'Code-Read' "$ROOT/agents/evaluator.md" && grep -qi 'read .*code itself\|code not read' "$ROOT/agents/evaluator.md"; then
ok "evaluator.md has the Code-Read dimension (judge the code itself, code-not-read == FAIL)"
else
no "evaluator.md missing Code-Read dimension"
fi
if CMP_RUN_PROMPT=/dev/null bash "$ROOT/scripts/run.sh" --show-prompt DEMO 2>/dev/null | grep -q 'READ THE CODE ITSELF'; then
ok "worker prompt injects Code-Read requirement at step=verify (evaluator reads the diff)"
else
no "Code-Read not injected into worker prompt"
fi
echo "== run dispatcher (parallel disjoint / serial same-zone) =="
if bash "$ROOT/scripts/run.sh" --self-test >/dev/null 2>&1; then
ok "cmpl run dispatcher: disjoint tasks parallel, same write_zone serializes"
else
no "cmpl run dispatcher self-test"
fi
echo "== reviewer findings binding (b3y: guard-close refuses close while open_findings non-empty) =="
BY_D=$(mktemp -d /tmp/cmpl-b3y-XXXXXX)
if ( cd "$BY_D" && git init -q && git -c user.email=t@t -c user.name=t commit -qm i --allow-empty \
&& bd init proj --stealth ) >/dev/null 2>&1; then
( cd "$BY_D"
bd create "has-finding" -t task --acceptance a --design d --metadata '{"write_zone":["x"],"verify":"x","open_findings":["HIGH: x"]}' >/dev/null 2>&1
bd create "clean" -t task --acceptance a --design d --metadata '{"write_zone":["y"],"verify":"x"}' >/dev/null 2>&1 )
BY_F=$( cd "$BY_D" && bd list --json | python3 -c 'import json,sys;d=json.load(sys.stdin);print([i["id"] for i in d if i["title"]=="has-finding"][0])' )
BY_C=$( cd "$BY_D" && bd list --json | python3 -c 'import json,sys;d=json.load(sys.stdin);print([i["id"] for i in d if i["title"]=="clean"][0])' )
( cd "$BY_D" && printf '{"tool_input":{"command":"bd close %s"}}' "$BY_F" | CMP_ALLOW_DIRTY_CLOSE=1 bash "$ROOT/hooks/guard-close.sh" >/dev/null 2>&1 ); rcf=$?
( cd "$BY_D" && printf '{"tool_input":{"command":"bd close %s"}}' "$BY_C" | CMP_ALLOW_DIRTY_CLOSE=1 bash "$ROOT/hooks/guard-close.sh" >/dev/null 2>&1 ); rcc=$?
if [ "$rcf" = 2 ]; then ok "guard-close refuses close with an open CRITICAL/HIGH finding (exit 2)"; else no "b3y: open finding not gated (rc=$rcf)"; fi
if [ "$rcc" = 0 ]; then ok "guard-close allows close with no open findings (exit 0)"; else no "b3y: clean bead blocked (rc=$rcc)"; fi
else
skip "reviewer findings binding (bd repo setup failed in tmp)"
fi
echo "== guard-write-zone (edit-time write_zone fence, PreToolUse) =="
if bash "$ROOT/hooks/guard-write-zone.sh" --self-test >/dev/null 2>&1; then
ok "guard-write-zone: denies edits outside zone, allows inside, interactive no-op"
else
no "guard-write-zone --self-test"
fi
echo "== read_context wiring (3jh: plan-apply emits it, worker prompt injects it before UNDERSTAND) =="
RC_D=$(mktemp -d /tmp/cmpl-rc-XXXXXX)
if ( cd "$RC_D" && git init -q && git -c user.email=t@t -c user.name=t commit -qm i --allow-empty \
&& bd init proj --stealth ) >/dev/null 2>&1; then
RC_PLAN='{"epic":"E","tasks":[{"key":"rc","title":"rc","acceptance":"a","design":"d","write_zone":["src/api.py"],"verify":"true","read_context":["src/schemas.py","src/db/models.py"]}]}'
( cd "$RC_D" && printf '%s' "$RC_PLAN" | python3 "$ROOT/scripts/plan-apply.py" >/dev/null 2>&1 )
RC_ID=$( cd "$RC_D" && bd list --json 2>/dev/null | python3 -c 'import json,sys
d=json.load(sys.stdin); d=d if isinstance(d,list) else d.get("issues",[])
print(next((i["id"] for i in d if i.get("title")=="rc"), ""))' )
RC_MD=$( cd "$RC_D" && bd show "$RC_ID" --json 2>/dev/null | python3 -c 'import json,sys
d=json.load(sys.stdin); d=d[0] if isinstance(d,list) else d
print(",".join((d.get("metadata") or {}).get("read_context") or []))' )
if [ "$RC_MD" = "src/schemas.py,src/db/models.py" ]; then ok "plan-apply round-trips metadata.read_context from a plan"; else no "read_context round-trip (got: '$RC_MD')"; fi
RC_PROMPT=$( cd "$RC_D" && CMP_RUN_PROMPT=/dev/null bash "$ROOT/scripts/run.sh" --show-prompt "$RC_ID" 2>/dev/null )
if printf '%s' "$RC_PROMPT" | grep -q 'READ these first' && printf '%s' "$RC_PROMPT" | grep -q 'src/schemas.py'; then
ok "worker prompt injects read_context (read-before-UNDERSTAND)"
else
no "worker prompt missing read_context injection"
fi
else
skip "read_context wiring (bd repo setup failed in tmp)"
fi
echo "== cmpl status (prs: read-only loop-health rollup) =="
PS_D=$(mktemp -d /tmp/cmpl-prs-XXXXXX)
if ( cd "$PS_D" && git init -q && git -c user.email=t@t -c user.name=t commit -qm i --allow-empty \
&& bd init proj --stealth ) >/dev/null 2>&1; then
( cd "$PS_D"
bd create "orphan-me" -t task --acceptance a --design d --metadata '{"write_zone":["a"],"verify":"x"}' >/dev/null 2>&1
PSID=$(bd list --json | python3 -c 'import json,sys;d=json.load(sys.stdin);print(d[0]["id"])')
bd update "$PSID" --status in_progress >/dev/null 2>&1
bd update "$PSID" --metadata '{"write_zone":["a"],"verify":"x","worker_id":"run-dead/pid9","heartbeat":1}' >/dev/null 2>&1
echo dirty > wip.txt )
PS_OUT=$( cd "$PS_D" && CMP_HEARTBEAT_STALE=300 bash "$ROOT/scripts/status.sh" 2>/dev/null )
PS_AFTER=$( cd "$PS_D" && bd list --status in_progress --json 2>/dev/null | python3 -c 'import json,sys
d=json.load(sys.stdin); d=d if isinstance(d,list) else d.get("issues",[]); print(len(d))' )
if printf '%s' "$PS_OUT" | grep -q 'INCOMPLETE' && printf '%s' "$PS_OUT" | grep -q 'stale claim' \
&& printf '%s' "$PS_OUT" | grep -q 'uncommitted file'; then
ok "cmpl status reports injected orphan + dirty tree -> INCOMPLETE"
else
no "cmpl status rollup (missing orphan/dirty/INCOMPLETE)"
fi
if [ "$PS_AFTER" = "1" ]; then ok "cmpl status is read-only (orphan left in_progress, not reaped)"; else no "cmpl status mutated state (in_progress=$PS_AFTER)"; fi
else
skip "cmpl status rollup (bd repo setup failed in tmp)"
fi
echo "== run parallel spawn loop (real dispatch+reap, mock worker — no LLM) =="
# Integration test: the dispatcher UNIT (self-test) passed while the BASH spawn/reap loop that
# consumes its output crashed at runtime ("invalid variable name" iterating the PID maps). This
# drives the real loop with a mock worker (CMP_CLAUDE_CMD=true) on two disjoint tasks.
PD=$(mktmp)
( cd "$PD" && git -c user.email=t@t -c user.name=t commit -qm init --allow-empty >/dev/null 2>&1
bd create "A" -t task --acceptance a --design d --metadata '{"write_zone":["a.txt"]}' >/dev/null 2>&1
bd create "B" -t task --acceptance a --design d --metadata '{"write_zone":["b.txt"]}' >/dev/null 2>&1 )
PDOUT=$( cd "$PD" && CMP_CLAUDE_CMD='true' CMP_PARALLEL=2 CMP_STALL=1 timeout 60 bash "$ROOT/scripts/run.sh" --mode unattended 2>&1 )
if printf '%s' "$PDOUT" | grep -qiE 'invalid variable|: line [0-9]+:|syntax error'; then
no "run parallel spawn loop crashes ($(printf '%s' "$PDOUT" | grep -iE 'invalid variable|line [0-9]' | head -1))"
elif printf '%s' "$PDOUT" | grep -q 'ready queue drained'; then
ok "run parallel spawn loop: disjoint workers dispatched + reaped, no crash"
else
no "run parallel spawn loop did not complete cleanly"
fi
rm -rf "$PD"
echo "== doctor =="
bash "$ROOT/scripts/doctor.sh" >/dev/null 2>&1; dr=$?
# 0 = no drift, 1 = drift (quarantine written) — both are a successful run; >1 = crash.
if [ "$dr" -le 1 ]; then ok "doctor runs (exit $dr: 0=clean, 1=drift)"; else no "doctor crashed (exit $dr)"; fi
echo "== doctor quarantine =="
ST=$(mktemp -d /tmp/cmpqtXXXXXX)
sed 's/^gsd=.*/gsd=0.0.0-FAKE/' "$ROOT/versions.lock" > "$ST/lock"
CMP_LOCK="$ST/lock" CMP_STATE="$ST" bash "$ROOT/scripts/doctor.sh" >/dev/null 2>&1; dqrc=$?
grep -qx gsd "$ST/quarantine.txt" 2>/dev/null && ok "drift writes quarantine" || no "drift writes quarantine"
[ "$dqrc" = 1 ] && ok "doctor exits 1 on drift (meaningful for automation)" || no "doctor drift exit code (got $dqrc, want 1)"
DQ=$(mktmp)
printf '# P\n<tasks>\n<task type="auto"><name>T</name><files>a</files><action>x</action><verify>v</verify><done>d</done></task>\n</tasks>\n' > "$DQ/P-PLAN.md"
( cd "$DQ" && CMP_STATE="$ST" bash "$ROOT/scripts/emit.sh" P-PLAN.md >/dev/null 2>&1 ); rc=$?
[ "$rc" = 3 ] && ok "quarantined emit refuses (exit 3)" || no "quarantined emit refuses (got $rc)"
rm -rf "$ST" "$DQ"
echo "== cmpl check (concise output) =="
D=$(mktmp)
printf '[check]\ncommands = [ { name = "ok", cmd = "true" }, { name = "bad", cmd = "echo E123; exit 1" } ]\n' > "$D/completely.toml"
bash "$ROOT/scripts/check.sh" "$D" >/tmp/cmpcc.out 2>&1; rc=$?
{ [ "$rc" = 1 ] && grep -q '✗ bad' /tmp/cmpcc.out && grep -q E123 /tmp/cmpcc.out && ! grep -q '✗ ok' /tmp/cmpcc.out; } \
&& ok "check fails, shows only failing output" || no "check fail-path"
printf '[check]\ncommands = [ { name = "ok", cmd = "true" } ]\n' > "$D/completely.toml"
bash "$ROOT/scripts/check.sh" "$D" >/dev/null 2>&1 && ok "check clean -> exit 0" || no "check clean exit"
rm -rf "$D" /tmp/cmpcc.out
echo "== root completely.toml gates this repo (no-op regression) =="
RNAMES=$(python3 "$ROOT/scripts/config.py" checks "$ROOT/.." 2>/dev/null | python3 -c 'import sys
names=sorted(l.split("\t")[0] for l in sys.stdin.read().splitlines() if l.strip())
print(",".join(names))')
[ "$RNAMES" = "contracts,ruff" ] && ok "root completely.toml resolves ruff + contracts (cmpl check not a no-op)" || no "root [check] regression ($RNAMES)"
echo "== plan-apply (Beads-first, no markdown) =="
D=$(mktmp)
printf '%s' '{"epic":"E","tasks":[{"key":"a","title":"A","acceptance":"x","design":"y","write_zone":["a"],"verify":"pytest -q","deps":[]},{"key":"b","title":"B","acceptance":"x","design":"y","write_zone":["b"],"verify":"pytest -q","deps":["a"]}]}' \
| ( cd "$D" && bash "$ROOT/scripts/plan.sh" >/dev/null 2>&1 )
n1=$(count "$D")
printf '%s' '{"epic":"E","tasks":[{"key":"a","title":"A","acceptance":"x","design":"y","write_zone":["a"],"verify":"pytest -q","deps":[]},{"key":"b","title":"B","acceptance":"x","design":"y","write_zone":["b"],"verify":"pytest -q","deps":["a"]}]}' \
| ( cd "$D" && bash "$ROOT/scripts/plan.sh" >/dev/null 2>&1 )
n2=$(count "$D")
{ [ "$n1" = "$n2" ] && [ "$n1" -ge 3 ]; } && ok "plan-apply idempotent ($n1->$n2)" || no "plan-apply idempotency ($n1->$n2)"
( cd "$D" && bash "$ROOT/scripts/lint.sh" >/dev/null 2>&1 ) && ok "plan-apply tasks are lint-clean" || no "plan-apply lint"
rm -rf "$D"
echo "== plan-apply field reconcile =="
D=$(mktmp)
printf '%s' '{"epic":"R","tasks":[{"key":"a","title":"A","acceptance":"v1","design":"d","write_zone":["a"]}]}' \
| ( cd "$D" && bash "$ROOT/scripts/plan.sh" >/dev/null 2>&1 )
printf '%s' '{"epic":"R","tasks":[{"key":"a","title":"A","acceptance":"v2","design":"d","write_zone":["a"]}]}' \
| ( cd "$D" && bash "$ROOT/scripts/plan.sh" >/dev/null 2>&1 )
AC=$( cd "$D" && bd list --all --json | python3 -c 'import json,sys
d=json.load(sys.stdin); d=d if isinstance(d,list) else d.get("issues",[])
vals=[i.get("acceptance_criteria") for i in d if i.get("title")=="A"]
print(vals[0] if vals else "")' )
[ "$AC" = "v2" ] && ok "plan-apply reconciles changed acceptance" || no "plan-apply reconcile (got: $AC)"
rm -rf "$D"
echo "== plan-apply must_haves + requirements (bridge consumer parity) =="
D=$(mktmp)
printf '%s' '{"epic":"M","tasks":[{"key":"a","title":"A","acceptance":"x","design":"d","write_zone":["a"],"requirements":["R-1"],"must_haves":{"truths":["t1"]}}]}' \
| ( cd "$D" && bash "$ROOT/scripts/plan.sh" >/dev/null 2>&1 )
MM=$( cd "$D" && bd list --all --json | python3 -c 'import json,sys
d=json.load(sys.stdin); d=d if isinstance(d,list) else d.get("issues",[])
m=[i.get("metadata") or {} for i in d if i.get("title")=="A"]
m=m[0] if m else {}
print("OK" if (m.get("must_haves") and m.get("requirements")) else "NO")' )
[ "$MM" = OK ] && ok "plan-apply: must_haves + requirements in task metadata" || no "plan-apply must_haves/requirements ($MM)"
rm -rf "$D"
echo "== bench harness (mock, no LLM spend) =="
if bash "$ROOT/tests/bench-mock.sh" >/dev/null 2>&1; then ok "cmpl bench: worktree/judge/cost/CSV/\$per-passed green"; else no "cmpl bench mock-harness failed"; fi
echo "== craft router (stack -> existing tools) =="
if bash "$ROOT/tests/craft-mock.sh" >/dev/null 2>&1; then ok "cmpl craft: stack-aware routing to existing specialists"; else no "cmpl craft router failed"; fi
echo "== evaluator: adversarial claim-vs-refute mode (port ECC gan-* pair) =="
EV="$ROOT/agents/evaluator.md"
grep -q "Adversarial mode" "$EV" && ok "evaluator: adversarial mode section present" || no "evaluator: missing adversarial mode section"
grep -qi "claim" "$EV" && grep -qi "refute" "$EV" && ok "evaluator: claim + refute language present" || no "evaluator: claim/refute language missing"
grep -q "eval_mode" "$EV" && ok "evaluator: opt-in trigger documented (eval_mode)" || no "evaluator: opt-in trigger missing"
# REFUTED stays default until the evaluator finds the claim withstands an active refutation attempt
grep -q "REFUTED" "$EV" && grep -q "WITHSTOOD" "$EV" && ok "evaluator: per-claim verdicts named (REFUTED/WITHSTOOD)" || no "evaluator: per-claim verdict tokens missing"
# regression-bite: not just "tokens exist" — the output table header AND the Beads comment tag must be present
grep -q '| # | Claim |' "$EV" && ok "evaluator: adversarial output table header wired" || no "evaluator: adversarial output table header missing"
grep -q 'EVALUATOR (adversarial)' "$EV" && ok "evaluator: Beads comment carries (adversarial) tag" || no "evaluator: missing (adversarial) tag on Beads comment"
echo "== cost-tracker hook (opt-in PostToolUse — exit 0, bounded, no secrets) =="
CT_HOOK="$ROOT/hooks/cost-tracker.sh"
[ -x "$CT_HOOK" ] && ok "cost-tracker.sh exists and is executable" || no "cost-tracker.sh missing/not-executable"
# wired into hooks.json under PostToolUse with matcher * (real-path floor)
python3 - "$ROOT/hooks/hooks.json" <<'PY' >/dev/null 2>&1 && ok "hooks.json wires cost-tracker under PostToolUse *" || no "hooks.json missing cost-tracker wiring"
import json, sys
d=json.load(open(sys.argv[1]))
post=d.get("hooks",{}).get("PostToolUse",[])
hit=any(h.get("matcher")=="*" and any("cost-tracker.sh" in (x.get("command","") or "") for x in (h.get("hooks") or [])) for h in post)
sys.exit(0 if hit else 1)
PY
CT_DIR=$(mktemp -d /tmp/cmpct.XXXXXX)
CT_LOG="$CT_DIR/cost.jsonl"
# opt-out: no CMP_COST_TRACK -> no log, exit 0
printf '{"tool_name":"Bash","tool_input":{"command":"ls"},"tool_response":{"output":"ok"}}' \
| CMP_COST_LOG="$CT_LOG" bash "$CT_HOOK" >/dev/null 2>&1
rc=$?
{ [ "$rc" = 0 ] && [ ! -f "$CT_LOG" ]; } && ok "opt-out: hook is a no-op (no file, exit 0)" || no "opt-out: rc=$rc, file?=$( [ -f "$CT_LOG" ] && echo yes || echo no )"
# opt-in: payload carrying multiple secret shapes (AWS key, sk- token, cookie, Bearer)
CT_SECRET='AWS_SECRET_ACCESS_KEY=wJalrXUtSECRET-cookie=sess=abcd-Bearer-tok-1234'
printf '{"tool_name":"Bash","tool_input":{"command":"%s curl evil"},"tool_response":{"output":"sk-leaked-2222"}}' "$CT_SECRET" \
| CMP_COST_TRACK=1 CMP_COST_LOG="$CT_LOG" bash "$CT_HOOK" >/dev/null 2>&1
rc=$?
[ "$rc" = 0 ] && ok "opt-in: exit 0" || no "opt-in: rc=$rc"
[ -s "$CT_LOG" ] && ok "opt-in: record written" || no "opt-in: no record written"
# log must contain NONE of the secret material we fed in
if grep -qE 'AWS_SECRET|wJalrXUtSECRET|sk-leaked|cookie=sess|Bearer-tok|evil|curl' "$CT_LOG" 2>/dev/null; then
no "cost-tracker LEAKED secrets — log contains forbidden strings"
else
ok "cost-tracker carries NO secrets (only ts/tool/sizes/ok)"
fi
# Stronger bite: every record's keys must be a subset of the fixed schema. This
# catches a regression like `rec["cmd"] = (ti.get("command") or "")[:128]` even
# if the test payload doesn't happen to contain any of the sentinel strings.
python3 - "$CT_LOG" <<'PY' >/dev/null 2>&1 && ok "cost-tracker record has ONLY schema keys (ts/tool/in_b/out_b/ok)" || no "cost-tracker record carries extra (potentially content) keys"
import json, sys
allowed = {"ts","tool","in_b","out_b","ok"}
for line in open(sys.argv[1]):
line = line.strip()
if not line: continue
extra = set(json.loads(line).keys()) - allowed
if extra: raise SystemExit(1)
PY
# bounded: every line strictly < 1024 bytes
awk '{ if (length($0) >= 1024) exit 1 }' "$CT_LOG" 2>/dev/null && ok "cost-tracker line bounded (< 1024 B)" || no "cost-tracker line unbounded"
# exactly one record per invocation
[ "$(wc -l < "$CT_LOG" 2>/dev/null)" = 1 ] && ok "cost-tracker writes exactly one record per call" || no "cost-tracker record count != 1"
# malformed JSON in -> exit 0 still
printf 'not json at all' | CMP_COST_TRACK=1 CMP_COST_LOG="$CT_DIR/bad.jsonl" bash "$CT_HOOK" >/dev/null 2>&1
[ $? = 0 ] && ok "cost-tracker handles malformed payload (exit 0)" || no "cost-tracker crashes on malformed payload"
# rotation: tiny cap forces .1 rollover, original resets
for i in 1 2 3 4 5; do
printf '{"tool_name":"Bash","tool_input":{},"tool_response":{}}' \
| CMP_COST_TRACK=1 CMP_COST_LOG="$CT_DIR/rot.jsonl" CMP_COST_MAX_BYTES=64 bash "$CT_HOOK" >/dev/null 2>&1
done
{ [ -f "$CT_DIR/rot.jsonl.1" ] && [ "$(wc -c < "$CT_DIR/rot.jsonl" 2>/dev/null)" -le 200 ]; } \
&& ok "cost-tracker rotates to .1 when CMP_COST_MAX_BYTES exceeded" || no "cost-tracker rotation broken"
# end-to-end self-test green (schema + rotation + malformed combined)
bash "$CT_HOOK" --self-test >/dev/null 2>&1 && ok "cost-tracker --self-test green" || no "cost-tracker --self-test FAILED"
rm -rf "$CT_DIR"
echo "== rtk: OPTIONAL upstream wired in bootstrap (present/hint/install/OPTIONAL list) =="
grep -q ' rtk)' "$ROOT/scripts/bootstrap.sh" && grep -qE 'OPTIONAL=.*rtk' "$ROOT/scripts/bootstrap.sh" \
&& ok "bootstrap: rtk in present/hint/install_one + OPTIONAL list" \
|| no "bootstrap: rtk wiring missing"
echo "== rtk: pinned in versions.lock =="
grep -qE '^rtk=' "$ROOT/versions.lock" && ok "versions.lock pins rtk= (doctor reports drift if installed != tested)" \
|| no "versions.lock missing rtk= pin"
echo "== rtk: doctor.sh handles drift with narrow affected scope (gate cmds excluded) =="
grep -q ' rtk)' "$ROOT/scripts/doctor.sh" && grep -qi 'excluded\|bench --rtk' "$ROOT/scripts/doctor.sh" \
&& ok "doctor.sh: rtk case present + narrow scope language (no gate-cmd impact)" \
|| no "doctor.sh: missing rtk case or scope language"
echo "== rtk: bench --rtk on/off dimension exposed =="
python3 "$ROOT/scripts/bench.py" --help 2>&1 | grep -q -- '--rtk' \
&& ok "bench.py: --rtk flag exposed" || no "bench.py: --rtk flag missing"
echo "== rtk: gate-parser safety (cmpl check byte-equal w/ rtk active vs absent) + negative control =="
# Build a mock 'rtk' that, when invoked as `rtk wrap CMD…`, truncates output to the first 3 lines.
# Truncation is deterministic and visibly mangling — so the negative control bites.
MD=$(mktemp -d /tmp/cmprtkmock.XXXXXX)
cat > "$MD/rtk" <<'RTK'
#!/usr/bin/env bash
case "${1:-}" in
wrap) shift; "$@" 2>&1 | sed -n '1,3p' ;;
init|--version|version) printf "rtk mock 0.1.0\n"; exit 0 ;;
*) exec "$@" ;;
esac
RTK
chmod +x "$MD/rtk"
# Minimal cmpl check workspace — enough commands that truncation to 3 lines is observable.
CD=$(mktemp -d /tmp/cmprtkcheck.XXXXXX)
cat > "$CD/completely.toml" <<'TOML'
[check]
commands = [
{ name = "a", cmd = "echo line-a" },
{ name = "b", cmd = "echo line-b" },
{ name = "c", cmd = "echo line-c" },
{ name = "d", cmd = "echo line-d" },
]
TOML
# (1) BASELINE: cmpl check with NO mock rtk on PATH, no CMP_RTK.
OUT_BASE=$(bash "$ROOT/scripts/check.sh" "$CD" 2>&1)
# (2) GATE-SAFETY: cmpl check with mock rtk on PATH + CMP_RTK=1.
# Output MUST be byte-identical to baseline — proving cmpl check does NOT route through rtk.
OUT_RTK=$(PATH="$MD:$PATH" CMP_RTK=1 bash "$ROOT/scripts/check.sh" "$CD" 2>&1)
[ "$OUT_BASE" = "$OUT_RTK" ] \
&& ok "gate-parser safety: cmpl check output BYTE-EQUAL with rtk active vs absent (exclusion holds)" \
|| no "gate-parser safety FAILED — rtk leaked into cmpl check parser"
# (3) NEGATIVE CONTROL: bypass the exclusion by actively wrapping check through the mock rtk.
# OUT_NEG must DIFFER from OUT_BASE — proving the mock actually corrupts and the (2) assertion bites.
# Invoke the mock rtk by ABSOLUTE PATH ("$MD/rtk") — relying on PATH lookup here would silently
# resolve to a host-installed rtk (or to nothing) and the test would pass for the wrong reason.
OUT_NEG=$("$MD/rtk" wrap bash "$ROOT/scripts/check.sh" "$CD" 2>&1)
[ "$OUT_NEG" != "$OUT_BASE" ] \
&& ok "negative control bites: rtk wrap of cmpl check IS corrupting (truncation observable)" \
|| no "negative control vacuous — mock rtk didn't corrupt (gate-safety test doesn't bite)"
rm -rf "$MD" "$CD"
echo "== live-agent contracts =="
skip "orchestrator builds parallel-decomposition matrix before delegating"
skip "two independent streams actually spawn in parallel"
skip "closeout rejects a completion with no verification evidence"
echo
echo "tests: $PASS passed, $FAIL failed, $SKIP skipped (live)"
[ "$FAIL" -eq 0 ]