devlyn-cli 2.10.1 → 3.0.1

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.
Files changed (77) hide show
  1. package/AGENTS.md +8 -9
  2. package/CLAUDE.md +17 -17
  3. package/README.md +33 -9
  4. package/benchmark/auto-resolve/results/20260507-f10-f11-tier1-full-pipeline/headroom-gate.json +25 -0
  5. package/benchmark/auto-resolve/results/20260507-f10-f11-tier1-full-pipeline/headroom-gate.md +10 -0
  6. package/benchmark/auto-resolve/results/20260508-f22-exact-error-headroom/headroom-gate.json +18 -0
  7. package/benchmark/auto-resolve/results/20260508-f22-exact-error-headroom/headroom-gate.md +9 -0
  8. package/benchmark/auto-resolve/results/20260508-f26-headroom/headroom-gate.json +18 -0
  9. package/benchmark/auto-resolve/results/20260508-f26-headroom/headroom-gate.md +9 -0
  10. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/F16-cli-quote-tax-rules/l2_risk_probes/result.json +28 -0
  11. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/F23-cli-fulfillment-wave/l2_risk_probes/result.json +28 -0
  12. package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/F25-cli-cart-promotion-rules/l2_risk_probes/result.json +30 -0
  13. package/benchmark/auto-resolve/results/20260511-f12-webhook-headroom/headroom-gate.json +28 -0
  14. package/benchmark/auto-resolve/results/20260511-f12-webhook-headroom/headroom-gate.md +15 -0
  15. package/benchmark/auto-resolve/results/20260511-f15-concurrency-headroom/headroom-gate.json +28 -0
  16. package/benchmark/auto-resolve/results/20260511-f15-concurrency-headroom/headroom-gate.md +15 -0
  17. package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/F21-cli-scheduler-priority/l2_risk_probes/result.json +32 -0
  18. package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/full-pipeline-pair-gate.json +44 -0
  19. package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/full-pipeline-pair-gate.md +16 -0
  20. package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/headroom-gate.json +18 -0
  21. package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/headroom-gate.md +9 -0
  22. package/benchmark/auto-resolve/results/20260511-f3-http-error-headroom/headroom-gate.json +28 -0
  23. package/benchmark/auto-resolve/results/20260511-f3-http-error-headroom/headroom-gate.md +15 -0
  24. package/benchmark/auto-resolve/results/20260512-f2-medium-headroom/headroom-gate.json +28 -0
  25. package/benchmark/auto-resolve/results/20260512-f2-medium-headroom/headroom-gate.md +15 -0
  26. package/benchmark/auto-resolve/results/20260512-f31-seat-rebalance-headroom/headroom-gate.json +28 -0
  27. package/benchmark/auto-resolve/results/20260512-f31-seat-rebalance-headroom/headroom-gate.md +15 -0
  28. package/benchmark/auto-resolve/results/20260512-f32-subscription-renewal-headroom/headroom-gate.json +28 -0
  29. package/benchmark/auto-resolve/results/20260512-f32-subscription-renewal-headroom/headroom-gate.md +15 -0
  30. package/benchmark/auto-resolve/results/20260512-f4-web-headroom/headroom-gate.json +28 -0
  31. package/benchmark/auto-resolve/results/20260512-f4-web-headroom/headroom-gate.md +15 -0
  32. package/benchmark/auto-resolve/results/20260512-f5-fixloop-headroom/headroom-gate.json +28 -0
  33. package/benchmark/auto-resolve/results/20260512-f5-fixloop-headroom/headroom-gate.md +15 -0
  34. package/benchmark/auto-resolve/results/20260512-f6-checksum-headroom/headroom-gate.json +28 -0
  35. package/benchmark/auto-resolve/results/20260512-f6-checksum-headroom/headroom-gate.md +15 -0
  36. package/benchmark/auto-resolve/results/20260512-f7-scope-headroom/headroom-gate.json +28 -0
  37. package/benchmark/auto-resolve/results/20260512-f7-scope-headroom/headroom-gate.md +15 -0
  38. package/benchmark/auto-resolve/results/20260512-f9-e2e-headroom/headroom-gate.json +28 -0
  39. package/benchmark/auto-resolve/results/20260512-f9-e2e-headroom/headroom-gate.md +15 -0
  40. package/bin/devlyn.js +9 -2
  41. package/config/skills/_shared/.ruff.toml +2 -0
  42. package/config/skills/_shared/adapters/claude.md +9 -1
  43. package/config/skills/_shared/adapters/codex.md +5 -0
  44. package/config/skills/_shared/adapters/grok.md +4 -2
  45. package/config/skills/_shared/archive_run.py +738 -56
  46. package/config/skills/_shared/codex-config.md +19 -4
  47. package/config/skills/_shared/codex-monitored.sh +81 -12
  48. package/config/skills/_shared/collect-codex-findings.py +311 -128
  49. package/config/skills/_shared/engine-preflight.md +8 -7
  50. package/config/skills/_shared/expected.schema.json +61 -0
  51. package/config/skills/_shared/finish-gate.py +12 -11
  52. package/config/skills/_shared/grok-anchor-guard.py +18 -1
  53. package/config/skills/_shared/invocation-receipt.py +1041 -0
  54. package/config/skills/_shared/judge-output-parser.py +200 -0
  55. package/config/skills/_shared/judge-role-evidence.py +273 -0
  56. package/config/skills/_shared/process-evidence.py +909 -0
  57. package/config/skills/_shared/resolve-bootstrap.py +776 -84
  58. package/config/skills/_shared/resolve-stop-hook.py +33 -1
  59. package/config/skills/_shared/role-config.py +552 -0
  60. package/config/skills/_shared/run-bounded.py +1 -1
  61. package/config/skills/_shared/spec-verify-check.py +749 -181
  62. package/config/skills/_shared/state-phase-write.py +1838 -58
  63. package/config/skills/_shared/terminal-claim-check.py +15 -0
  64. package/config/skills/_shared/verify-merge-findings.py +958 -51
  65. package/config/skills/devlyn:engines/SKILL.md +8 -16
  66. package/config/skills/devlyn:ideate/SKILL.md +2 -2
  67. package/config/skills/devlyn:ideate/references/spec-template.md +6 -5
  68. package/config/skills/devlyn:queue/SKILL.md +7 -4
  69. package/config/skills/devlyn:resolve/SKILL.md +93 -35
  70. package/config/skills/devlyn:resolve/references/free-form-mode.md +1 -0
  71. package/config/skills/devlyn:resolve/references/outer-loop.md +15 -0
  72. package/config/skills/devlyn:resolve/references/phases/build-gate.md +31 -2
  73. package/config/skills/devlyn:resolve/references/phases/implement.md +3 -2
  74. package/config/skills/devlyn:resolve/references/phases/verify.md +120 -84
  75. package/config/skills/devlyn:resolve/references/state-schema.md +22 -8
  76. package/package.json +5 -1
  77. package/scripts/lint-skills.sh +314 -285
@@ -56,9 +56,16 @@ fi
56
56
  # plus the `_shared/` kernel. Keep this list single-source so all installed
57
57
  # mirror parity checks cover the same files.
58
58
  critical_path_files=$(cat <<'EOF'
59
+ _shared/.ruff.toml
60
+ _shared/process-evidence.py
61
+ _shared/invocation-receipt.py
62
+ _shared/role-config.py
63
+ _shared/judge-role-evidence.py
59
64
  _shared/spec-verify-check.py
65
+ _shared/judge-output-parser.py
60
66
  _shared/collect-codex-findings.py
61
67
  _shared/verify-merge-findings.py
68
+ _shared/archive_run.py
62
69
  _shared/state-phase-write.py
63
70
  _shared/terminal-claim-check.py
64
71
  _shared/resolve-stop-hook.py
@@ -207,8 +214,8 @@ else
207
214
  fi
208
215
 
209
216
  # ---------------------------------------------------------------------------
210
- # 4. No model-pinned Claude references, any generation, except the adjudicated
211
- # SURFACE_CLOSE envelope whose requested id must equal CLI arg and modelUsage.
217
+ # 4. No model-pinned Claude references, any generation, except the
218
+ # validated explicit-effort capability declaration.
212
219
  # ---------------------------------------------------------------------------
213
220
  section "Check 4: No model-pinned Claude references"
214
221
  offenders=$(grep -RInE 'Claude (Opus|Sonnet|Haiku|Fable)|claude-(opus|sonnet|haiku|fable)-[0-9]' \
@@ -217,7 +224,7 @@ offenders=$(grep -RInE 'Claude (Opus|Sonnet|Haiku|Fable)|claude-(opus|sonnet|hai
217
224
  | grep -v 'config/skills/devlyn:auto-resolve-workspace/' \
218
225
  | grep -v 'config/skills/devlyn:ideate-workspace/' \
219
226
  | grep -v 'config/skills/preflight-workspace/' \
220
- | grep -vE '^config/skills/devlyn:resolve/SKILL\.md:[0-9]+:Freeze .*--tools "Read,Grep,Glob,Edit,Write" --dangerously-skip-permissions --model claude-sonnet-5 --output-format json --strict-mcp-config --mcp-config '\''\{"mcpServers":\{\}\}'\''.*, recording the same model at SPW spawn\.' \
227
+ | grep -vE '^config/skills/_shared/adapters/claude\.md:[0-9]+:<!-- devlyn-effort 2\.1\.263 claude-fable-5-1 low,medium,high,xhigh,max -->$' \
221
228
  | cut -d: -f1 \
222
229
  | sort -u \
223
230
  || true)
@@ -276,13 +283,22 @@ section "Check 5b: Installed skill roots carry exact version markers"
276
283
  if make_temp_dir tmp_install_marker /tmp/devlyn-install-marker.XXXXXX; then
277
284
  marker_home="$tmp_install_marker/home"
278
285
  marker_project="$tmp_install_marker/project"
286
+ timeout_low="$tmp_install_marker/timeout-low"
287
+ timeout_high="$tmp_install_marker/timeout-high"
279
288
  installer="$PWD/bin/devlyn.js"
280
- mkdir -p "$marker_home" "$marker_project"
289
+ mkdir -p "$marker_home" "$marker_project" "$timeout_low/.claude" "$timeout_high/.claude"
290
+ printf '{"env":{"BASH_MAX_TIMEOUT_MS":"600000"}}\n' > "$timeout_low/.claude/settings.json"
291
+ printf '{"env":{"BASH_MAX_TIMEOUT_MS":"7200000"}}\n' > "$timeout_high/.claude/settings.json"
281
292
 
282
293
  if (cd "$marker_project" \
283
294
  && HOME="$marker_home" node "$installer" -y >"$tmp_install_marker/claude.log" 2>&1 \
284
- && HOME="$marker_home" node "$installer" agents all >"$tmp_install_marker/agents.log" 2>&1); then
285
- if python3 - "$installer" "$marker_home" "$marker_project" <<'PY'
295
+ && HOME="$marker_home" node "$installer" agents all >"$tmp_install_marker/agents.log" 2>&1) \
296
+ && (cd "$timeout_low" && HOME="$marker_home" node "$installer" -y >"$tmp_install_marker/timeout-low.log" 2>&1) \
297
+ && cp "$timeout_low/.claude/settings.json" "$tmp_install_marker/timeout-low-first.json" \
298
+ && (cd "$timeout_low" && HOME="$marker_home" node "$installer" -y >"$tmp_install_marker/timeout-low-second.log" 2>&1) \
299
+ && cmp -s "$timeout_low/.claude/settings.json" "$tmp_install_marker/timeout-low-first.json" \
300
+ && (cd "$timeout_high" && HOME="$marker_home" node "$installer" -y >"$tmp_install_marker/timeout-high.log" 2>&1); then
301
+ if python3 - "$installer" "$marker_home" "$marker_project" "$timeout_low" "$timeout_high" <<'PY'
286
302
  import json
287
303
  import pathlib
288
304
  import stat
@@ -291,6 +307,8 @@ import sys
291
307
  installer = pathlib.Path(sys.argv[1])
292
308
  home = pathlib.Path(sys.argv[2])
293
309
  project = pathlib.Path(sys.argv[3])
310
+ timeout_low = pathlib.Path(sys.argv[4])
311
+ timeout_high = pathlib.Path(sys.argv[5])
294
312
  package = json.loads((installer.parent.parent / "package.json").read_text())
295
313
  expected = {"schemaVersion": 1, "package": package["name"], "version": package["version"]}
296
314
  roots = [
@@ -308,10 +326,20 @@ for root in roots:
308
326
  raise SystemExit(f"{marker}: expected mode 0600")
309
327
  if list(root.glob(".devlyn-install.json.*.tmp")):
310
328
  raise SystemExit(f"{root}: stale marker temp file")
329
+ for target, expected_timeout in (
330
+ (project, "3600000"),
331
+ (timeout_low, "3600000"),
332
+ (timeout_high, "7200000"),
333
+ ):
334
+ env = json.loads((target / ".claude" / "settings.json").read_text())["env"]
335
+ if env.get("BASH_MAX_TIMEOUT_MS") != expected_timeout:
336
+ raise SystemExit(f"{target}: expected BASH_MAX_TIMEOUT_MS={expected_timeout}")
337
+ if "BASH_DEFAULT_TIMEOUT_MS" in env:
338
+ raise SystemExit(f"{target}: BASH_DEFAULT_TIMEOUT_MS must not be installed")
311
339
  PY
312
340
  then
313
341
  if grep -Fxq '.claude/skills/.devlyn-install.json' "$marker_project/.gitignore"; then
314
- ok "Claude, Codex, shared-agent, and Grok roots have exact 0600 markers; project marker is ignored"
342
+ ok "managed roots have exact 0600 markers; Bash max is installed, raised, preserved, and idempotent"
315
343
  else
316
344
  bad "Claude project install must ignore its local marker"
317
345
  fi
@@ -373,6 +401,14 @@ check_skill_mirror_parity \
373
401
 
374
402
  # ---------------------------------------------------------------------------
375
403
  # 6b. VERIFY merge verdict binding self-test.
404
+ for helper in role-config judge-role-evidence; do
405
+ if python3 "config/skills/_shared/$helper.py" --self-test >/dev/null 2>&1; then
406
+ ok "$helper.py self-test passed"
407
+ else
408
+ bad "$helper.py self-test failed"
409
+ fi
410
+ done
411
+
376
412
  # F23 full-pipeline prompt-fix rerun exposed a real failure where Codex
377
413
  # pair-JUDGE emitted HIGH findings but state kept pair_judge as
378
414
  # PASS_WITH_ISSUES. Routing severity must be deterministic, not prose.
@@ -383,6 +419,7 @@ if python3 config/skills/_shared/verify-merge-findings.py --self-test >/dev/null
383
419
  else
384
420
  bad "verify-merge-findings.py self-test failed"
385
421
  fi
422
+
386
423
  if ! grep -Fq 'def pair_trigger_skip_contract_violation' config/skills/_shared/verify-merge-findings.py \
387
424
  || ! grep -Fq 'def pair_trigger_missing_contract_violation' config/skills/_shared/verify-merge-findings.py \
388
425
  || ! grep -Fq 'def pair_trigger_reason_completeness_violation' config/skills/_shared/verify-merge-findings.py \
@@ -447,7 +484,6 @@ fi
447
484
  verify_merge_risk_profile_guard_missing=0
448
485
  for file in \
449
486
  config/skills/_shared/verify-merge-findings.py \
450
- .claude/skills/_shared/verify-merge-findings.py \
451
487
  .agents/skills/_shared/verify-merge-findings.py; do
452
488
  if ! grep -Fq 'def risk_profile_contract_violation' "$file" \
453
489
  || ! grep -Fq 'verify-risk-profile-malformed' "$file" \
@@ -461,6 +497,34 @@ if [ $verify_merge_risk_profile_guard_missing -eq 0 ]; then
461
497
  ok "verify-merge-findings.py risk_profile shape guard is mirrored"
462
498
  fi
463
499
 
500
+ section "Check 6b1: Process evidence runner is sealed"
501
+ if python3 config/skills/_shared/process-evidence.py --self-test >/dev/null 2>&1; then
502
+ ok "process-evidence.py self-test passed"
503
+ else
504
+ bad "process-evidence.py self-test failed"
505
+ fi
506
+ if ! grep -Fq 'PHASES = {"implement", "build_gate", "verify"}' config/skills/_shared/process-evidence.py \
507
+ || ! grep -Fq 'classification' config/skills/_shared/process-evidence.py \
508
+ || ! grep -Fq 'validate_bound_carrier' config/skills/_shared/process-evidence.py \
509
+ || ! grep -Fq 'validate_summary_commands' config/skills/_shared/process-evidence.py; then
510
+ bad "process-evidence.py must preserve phase identity, capability classification, and bound-byte validation"
511
+ fi
512
+
513
+ section "Check 6b2: Codex invocation receipts are phase-owned"
514
+ if python3 config/skills/_shared/invocation-receipt.py --self-test >/dev/null 2>&1; then
515
+ ok "invocation-receipt.py self-test passed"
516
+ else
517
+ bad "invocation-receipt.py self-test failed"
518
+ fi
519
+ if ! grep -Fq 'sandbox must remain workspace-write' config/skills/_shared/invocation-receipt.py \
520
+ || ! grep -Fq 'SCHEMA_VERSION = "2.0"' config/skills/_shared/invocation-receipt.py \
521
+ || ! grep -Fq 'sandbox_workspace_write.network_access' config/skills/_shared/invocation-receipt.py \
522
+ || ! grep -Fq 'forbidden Codex bypass flag' config/skills/_shared/invocation-receipt.py \
523
+ || ! grep -Fq 'forbidden Codex sandbox: danger-full-access' config/skills/_shared/codex-monitored.sh \
524
+ || ! grep -Fq 'DEVLYN_INVOCATION_RECEIPT' config/skills/_shared/codex-monitored.sh; then
525
+ bad "Codex invocation receipts must bind phase identity and reject authority widening"
526
+ fi
527
+
464
528
  section "Check 6c: Codex stdout collection writes canonical pair findings"
465
529
  if python3 config/skills/_shared/collect-codex-findings.py --self-test >/dev/null 2>&1; then
466
530
  ok "collect-codex-findings.py self-test passed"
@@ -476,7 +540,8 @@ else
476
540
  bad "collector contract failed — run benchmark/ceiling/probes/r-weld-0082/test-collector-contract.py"
477
541
  fi
478
542
  if ! grep -Fq 'def reject_json_constant' config/skills/_shared/collect-codex-findings.py \
479
- || ! grep -Fq 'loads_strict_json(raw)' config/skills/_shared/collect-codex-findings.py \
543
+ || ! grep -Fq 'PARSER["collect_stdout"]' config/skills/_shared/collect-codex-findings.py \
544
+ || ! grep -Fq 'parse_constant=reject_json_constant' config/skills/_shared/judge-output-parser.py \
480
545
  || ! grep -Fq 'NaN pair-JUDGE stdout finding' config/skills/_shared/collect-codex-findings.py; then
481
546
  bad "collect-codex-findings.py must reject non-standard JSON constants in pair-JUDGE stdout"
482
547
  fi
@@ -494,6 +559,7 @@ if ! grep -Fq 'SAFE_RUN_ID_RE' config/skills/_shared/archive_run.py \
494
559
  || ! grep -Fq 'invalid JSON numeric constant: NaN' config/skills/_shared/archive_run.py \
495
560
  || ! grep -Fq '"verify.pair.findings.jsonl"' config/skills/_shared/archive_run.py \
496
561
  || ! grep -Fq '"verify-merge.summary.json"' config/skills/_shared/archive_run.py \
562
+ || ! grep -Fq '"verify.primary.timeout.json"' config/skills/_shared/archive_run.py \
497
563
  || ! grep -Fq '"surface-close.output.json"' config/skills/_shared/archive_run.py \
498
564
  || ! grep -Fq '"*-judge.*"' config/skills/_shared/archive_run.py; then
499
565
  bad "archive_run.py must safely archive pair/risk-probe evidence and reject unsafe run ids"
@@ -506,17 +572,50 @@ if python3 config/skills/_shared/state-phase-write.py --self-test >/dev/null 2>&
506
572
  else
507
573
  bad "state-phase-write.py SURFACE_CLOSE self-test failed"
508
574
  fi
575
+ if python3 - <<'PY'
576
+ import ast
577
+ import runpy
578
+
579
+ entries = ["src/{a,b}/**"]
580
+ paths = ("src/a/example.py", "src/b/example.py", "src/c/example.py")
581
+ expected = (True, True, False)
582
+ sources = {"path_matches_surface": [], "validate_surface_brace_glob": []}
583
+ for name in ("state-phase-write.py", "spec-verify-check.py"):
584
+ path = f"config/skills/_shared/{name}"
585
+ module = runpy.run_path(path)
586
+ actual = tuple(module["path_matches_surface"](path, entries) for path in paths)
587
+ assert actual == expected, (name, actual)
588
+ tree = ast.parse(open(path, encoding="utf-8").read())
589
+ text = open(path, encoding="utf-8").read()
590
+ for function_name in sources:
591
+ function = next(node for node in tree.body if isinstance(node, ast.FunctionDef) and node.name == function_name)
592
+ sources[function_name].append(ast.get_source_segment(text, function))
593
+ for invalid in ("src/{a,b", "src/{a,}/**", "src/{a,{b,c}}", "src/{a,**}"):
594
+ try:
595
+ module["path_matches_surface"]("src/a/example.py", [invalid])
596
+ except ValueError as exc:
597
+ assert invalid in str(exc) and "supported form" in str(exc)
598
+ else:
599
+ raise AssertionError((name, invalid))
600
+ for function_name, bodies in sources.items():
601
+ assert bodies[0] == bodies[1], f"{function_name} bodies differ"
602
+ PY
603
+ then
604
+ ok "brace-glob surface matching and errors are byte-parity checked in both consumers"
605
+ else
606
+ bad "brace-glob surface matching or errors drifted between state and spec checks"
607
+ fi
509
608
  if ! grep -Fq 'rollback_surface_delta' config/skills/_shared/state-phase-write.py \
510
609
  || ! grep -Fq 'validate_surface_adjudication' config/skills/_shared/state-phase-write.py \
511
610
  || ! grep -Fq 'validate_surface_execution' config/skills/_shared/state-phase-write.py \
512
611
  || ! grep -Fq 'phases.surface_close spawn requires --engine claude' config/skills/_shared/state-phase-write.py \
513
- || ! grep -Fq 'phases.surface_close spawn requires --model' config/skills/_shared/state-phase-write.py \
612
+ || ! grep -Fq 'SURFACE_CLOSE requires canonical native JSON' config/skills/_shared/state-phase-write.py \
514
613
  || ! grep -Fq 'BLOCKED:surface-close-input-mismatch' config/skills/_shared/state-phase-write.py \
515
614
  || ! grep -Fq 'surface-check' config/skills/_shared/state-phase-write.py \
516
615
  || ! grep -Fq 'surface-rollback' config/skills/_shared/state-phase-write.py; then
517
616
  bad "state-phase-write.py must mechanically adjudicate, audit, guard, and roll back SURFACE_CLOSE"
518
617
  fi
519
- for tree in config/skills .claude/skills .agents/skills; do
618
+ for tree in config/skills .agents/skills; do
520
619
  skill="$tree/devlyn:resolve/SKILL.md"
521
620
  phase="$tree/devlyn:resolve/references/phases/surface-close.md"
522
621
  if ! grep -Fq '## PHASE 2.5: SURFACE_CLOSE' "$skill" \
@@ -526,7 +625,7 @@ for tree in config/skills .claude/skills .agents/skills; do
526
625
  || ! grep -Fq 'auto_surface_close_claude_unavailable' "$skill" \
527
626
  || ! grep -Fq 'canonical body VERBATIM' "$skill" \
528
627
  || ! grep -Fq 'run-bounded.py 600 -- claude -p' "$skill" \
529
- || ! grep -Fq -- '--tools "Read,Grep,Glob,Edit,Write" --dangerously-skip-permissions --model claude-sonnet-5 --output-format json --strict-mcp-config --mcp-config '\''{"mcpServers":{}}'\''' "$skill" \
628
+ || ! grep -Fq -- '--tools "Read,Grep,Glob,Edit,Write" --dangerously-skip-permissions --output-format json --strict-mcp-config --mcp-config '\''{"mcpServers":{}}'\''' "$skill" \
530
629
  || ! grep -Fq '.devlyn/surface-close.output.json' "$skill" \
531
630
  || ! grep -Fq '**Common post-fix checkpoint (BUILD_GATE and VERIFY):**' "$skill" \
532
631
  || ! grep -Fq 'durability-enforce --round <n> --origin-phase <build_gate|verify>' "$skill" \
@@ -570,16 +669,6 @@ if ! grep -Fq 'generated criteria carrier was not staged into .devlyn/spec-verif
570
669
  || ! grep -Fq 'def source_integrity_error' config/skills/_shared/spec-verify-check.py \
571
670
  || ! grep -Fq 'source.criteria_sha256 mismatch' config/skills/_shared/spec-verify-check.py \
572
671
  || ! grep -Fq 'Generated criteria were written without one' config/skills/_shared/spec-verify-check.py \
573
- || ! grep -Fq 'generated criteria carrier was not staged into .devlyn/spec-verify.json' .claude/skills/_shared/spec-verify-check.py \
574
- || ! grep -Fq 'spec source with mismatched source.spec_sha256 was accepted' .claude/skills/_shared/spec-verify-check.py \
575
- || ! grep -Fq 'spec source with matching source.spec_sha256 was not staged' .claude/skills/_shared/spec-verify-check.py \
576
- || ! grep -Fq 'source.spec_sha256 mismatch' .claude/skills/_shared/spec-verify-check.py \
577
- || ! grep -Fq 'generated criteria without a JSON carrier was accepted' .claude/skills/_shared/spec-verify-check.py \
578
- || ! grep -Fq 'generated criteria without source.criteria_sha256 was accepted' .claude/skills/_shared/spec-verify-check.py \
579
- || ! grep -Fq 'generated criteria with mismatched source.criteria_sha256 was accepted' .claude/skills/_shared/spec-verify-check.py \
580
- || ! grep -Fq 'def source_integrity_error' .claude/skills/_shared/spec-verify-check.py \
581
- || ! grep -Fq 'source.criteria_sha256 mismatch' .claude/skills/_shared/spec-verify-check.py \
582
- || ! grep -Fq 'Generated criteria were written without one' .claude/skills/_shared/spec-verify-check.py \
583
672
  || ! grep -Fq 'generated criteria carrier was not staged into .devlyn/spec-verify.json' .agents/skills/_shared/spec-verify-check.py \
584
673
  || ! grep -Fq 'spec source with mismatched source.spec_sha256 was accepted' .agents/skills/_shared/spec-verify-check.py \
585
674
  || ! grep -Fq 'spec source with matching source.spec_sha256 was not staged' .agents/skills/_shared/spec-verify-check.py \
@@ -616,27 +705,6 @@ if ! grep -Fq 'def validate_present_solo_headroom_hypothesis' config/skills/_sha
616
705
  || ! grep -Fq 'weak sibling solo-headroom hypothesis was accepted by --check-expected' config/skills/_shared/spec-verify-check.py \
617
706
  || ! grep -Fq 'docs-style solo-headroom hypothesis was rejected by --check' config/skills/_shared/spec-verify-check.py \
618
707
  || ! grep -Fq 'docs-style sibling solo-headroom command was rejected by --check-expected' config/skills/_shared/spec-verify-check.py \
619
- || ! grep -Fq 'def validate_present_solo_headroom_hypothesis' .claude/skills/_shared/spec-verify-check.py \
620
- || ! grep -Fq 'def state_requires_risk_probes' .claude/skills/_shared/spec-verify-check.py \
621
- || ! grep -Fq 'def risk_probes_state_error' .claude/skills/_shared/spec-verify-check.py \
622
- || ! grep -Fq -- '--include-risk-probes accepted missing required risk-probes.jsonl' .claude/skills/_shared/spec-verify-check.py \
623
- || ! grep -Fq -- '--include-risk-probes accepted non-boolean risk_probes_enabled' .claude/skills/_shared/spec-verify-check.py \
624
- || ! grep -Fq -- '--include-risk-probes accepted non-object risk_profile' .claude/skills/_shared/spec-verify-check.py \
625
- || ! grep -Fq 'def validate_risk_probes_cover_solo_headroom_hypothesis' .claude/skills/_shared/spec-verify-check.py \
626
- || ! grep -Fq 'def has_backticked_observable_miss_command' .claude/skills/_shared/spec-verify-check.py \
627
- || ! grep -Fq 'backticked command/observable line that exposes the miss' .claude/skills/_shared/spec-verify-check.py \
628
- || ! grep -Fq 'weak solo-headroom hypothesis was accepted by --check' .claude/skills/_shared/spec-verify-check.py \
629
- || ! grep -Fq 'descriptive backtick solo-headroom hypothesis was accepted by --check' .claude/skills/_shared/spec-verify-check.py \
630
- || ! grep -Fq 'risk probe missing solo-headroom command coverage was accepted' .claude/skills/_shared/spec-verify-check.py \
631
- || ! grep -Fq 'risk probe with unrelated solo-headroom derived_from was accepted' .claude/skills/_shared/spec-verify-check.py \
632
- || ! grep -Fq 'risk-probes[0].derived_from must reference the solo-headroom hypothesis bullet' .claude/skills/_shared/spec-verify-check.py \
633
- || ! grep -Fq 'solo-headroom command in a later risk probe was accepted' .claude/skills/_shared/spec-verify-check.py \
634
- || ! grep -Fq 'solo-headroom command prefix match was accepted' .claude/skills/_shared/spec-verify-check.py \
635
- || ! grep -Fq '(?<![A-Za-z0-9_.:/=-])' .claude/skills/_shared/spec-verify-check.py \
636
- || ! grep -Fq 'risk-probes[0].cmd must contain a solo-headroom hypothesis observable command' .claude/skills/_shared/spec-verify-check.py \
637
- || ! grep -Fq 'weak sibling solo-headroom hypothesis was accepted by --check-expected' .claude/skills/_shared/spec-verify-check.py \
638
- || ! grep -Fq 'docs-style solo-headroom hypothesis was rejected by --check' .claude/skills/_shared/spec-verify-check.py \
639
- || ! grep -Fq 'docs-style sibling solo-headroom command was rejected by --check-expected' .claude/skills/_shared/spec-verify-check.py \
640
708
  || ! grep -Fq 'def validate_present_solo_headroom_hypothesis' .agents/skills/_shared/spec-verify-check.py \
641
709
  || ! grep -Fq 'def state_requires_risk_probes' .agents/skills/_shared/spec-verify-check.py \
642
710
  || ! grep -Fq 'def risk_probes_state_error' .agents/skills/_shared/spec-verify-check.py \
@@ -663,29 +731,22 @@ else
663
731
  ok "spec-verify-check.py rejects weak solo-headroom hypotheses"
664
732
  fi
665
733
  if ! grep -Fq 'requires `.devlyn/risk-probes.jsonl`' config/skills/devlyn:resolve/SKILL.md \
666
- || ! grep -Fq 'requires `.devlyn/risk-probes.jsonl`' .claude/skills/devlyn:resolve/SKILL.md \
667
734
  || ! grep -Fq 'requires `.devlyn/risk-probes.jsonl`' .agents/skills/devlyn:resolve/SKILL.md \
668
735
  || ! grep -Fq 'missing `.devlyn/risk-probes.jsonl` is a CRITICAL mechanical blocker' config/skills/devlyn:resolve/SKILL.md \
669
- || ! grep -Fq 'missing `.devlyn/risk-probes.jsonl` is a CRITICAL mechanical blocker' .claude/skills/devlyn:resolve/SKILL.md \
670
736
  || ! grep -Fq 'missing `.devlyn/risk-probes.jsonl` is a CRITICAL mechanical blocker' .agents/skills/devlyn:resolve/SKILL.md \
671
737
  || ! grep -Fq 'requires that file when `state.risk_profile.risk_probes_enabled == true`' config/skills/devlyn:resolve/references/phases/build-gate.md \
672
- || ! grep -Fq 'requires that file when `state.risk_profile.risk_probes_enabled == true`' .claude/skills/devlyn:resolve/references/phases/build-gate.md \
673
738
  || ! grep -Fq 'requires that file when `state.risk_profile.risk_probes_enabled == true`' .agents/skills/devlyn:resolve/references/phases/build-gate.md \
674
739
  || ! grep -Fq 'Malformed `state.risk_profile` is also CRITICAL because it can hide enabled risk probes' config/skills/devlyn:resolve/references/phases/build-gate.md \
675
- || ! grep -Fq 'Malformed `state.risk_profile` is also CRITICAL because it can hide enabled risk probes' .claude/skills/devlyn:resolve/references/phases/build-gate.md \
676
740
  || ! grep -Fq 'Malformed `state.risk_profile` is also CRITICAL because it can hide enabled risk probes' .agents/skills/devlyn:resolve/references/phases/build-gate.md \
677
741
  || ! grep -Fq 'When `state.risk_profile.risk_probes_enabled == true`, missing `.devlyn/risk-probes.jsonl` is also CRITICAL' config/skills/devlyn:resolve/references/phases/verify.md \
678
- || ! grep -Fq 'When `state.risk_profile.risk_probes_enabled == true`, missing `.devlyn/risk-probes.jsonl` is also CRITICAL' .claude/skills/devlyn:resolve/references/phases/verify.md \
679
742
  || ! grep -Fq 'When `state.risk_profile.risk_probes_enabled == true`, missing `.devlyn/risk-probes.jsonl` is also CRITICAL' .agents/skills/devlyn:resolve/references/phases/verify.md; then
680
743
  bad "BUILD_GATE and VERIFY must fail closed when enabled risk probes are missing"
681
744
  else
682
745
  ok "BUILD_GATE and VERIFY require enabled risk probes"
683
746
  fi
684
747
  if grep -Fq 'or any(char.isspace() for char in stripped)' config/skills/_shared/spec-verify-check.py \
685
- || grep -Fq 'or any(char.isspace() for char in stripped)' .claude/skills/_shared/spec-verify-check.py \
686
748
  || grep -Fq 'or any(char.isspace() for char in stripped)' .agents/skills/_shared/spec-verify-check.py \
687
749
  || grep -Fq 'or any(char.isspace() for char in stripped)' config/skills/_shared/verify-merge-findings.py \
688
- || grep -Fq 'or any(char.isspace() for char in stripped)' .claude/skills/_shared/verify-merge-findings.py \
689
750
  || grep -Fq 'or any(char.isspace() for char in stripped)' .agents/skills/_shared/verify-merge-findings.py \
690
751
  || grep -Fq 'or any(char.isspace() for char in stripped)' benchmark/auto-resolve/scripts/pair_evidence_contract.py; then
691
752
  bad "solo-headroom command detection must not treat descriptive whitespace as a command"
@@ -693,10 +754,8 @@ else
693
754
  ok "solo-headroom command detection rejects descriptive whitespace"
694
755
  fi
695
756
  if ! grep -Fq '"printf",' config/skills/_shared/spec-verify-check.py \
696
- || ! grep -Fq '"printf",' .claude/skills/_shared/spec-verify-check.py \
697
757
  || ! grep -Fq '"printf",' .agents/skills/_shared/spec-verify-check.py \
698
758
  || ! grep -Fq '"printf",' config/skills/_shared/verify-merge-findings.py \
699
- || ! grep -Fq '"printf",' .claude/skills/_shared/verify-merge-findings.py \
700
759
  || ! grep -Fq '"printf",' .agents/skills/_shared/verify-merge-findings.py \
701
760
  || ! grep -Fq '"printf",' benchmark/auto-resolve/scripts/pair_evidence_contract.py; then
702
761
  bad "solo-headroom command detection must keep explicit printf command support"
@@ -711,10 +770,8 @@ import sys
711
770
  files = [
712
771
  pathlib.Path("benchmark/auto-resolve/scripts/pair_evidence_contract.py"),
713
772
  pathlib.Path("config/skills/_shared/spec-verify-check.py"),
714
- pathlib.Path(".claude/skills/_shared/spec-verify-check.py"),
715
773
  pathlib.Path(".agents/skills/_shared/spec-verify-check.py"),
716
774
  pathlib.Path("config/skills/_shared/verify-merge-findings.py"),
717
- pathlib.Path(".claude/skills/_shared/verify-merge-findings.py"),
718
775
  pathlib.Path(".agents/skills/_shared/verify-merge-findings.py"),
719
776
  ]
720
777
  names = [
@@ -843,40 +900,28 @@ if [ $expected_check_missing -eq 0 ]; then
843
900
  ok "ideate docs require --check-expected for sibling expected contracts"
844
901
  fi
845
902
  if ! grep -Fq 'any present actionable solo-headroom hypothesis' config/skills/devlyn:ideate/SKILL.md \
846
- || ! grep -Fq 'any present actionable solo-headroom hypothesis' .claude/skills/devlyn:ideate/SKILL.md \
847
903
  || ! grep -Fq 'any present actionable solo-headroom hypothesis' .agents/skills/devlyn:ideate/SKILL.md \
848
904
  || ! grep -Fq 'any present actionable solo-headroom hypothesis' config/skills/devlyn:ideate/references/elicitation.md \
849
- || ! grep -Fq 'any present actionable solo-headroom hypothesis' .claude/skills/devlyn:ideate/references/elicitation.md \
850
905
  || ! grep -Fq 'any present actionable solo-headroom hypothesis' .agents/skills/devlyn:ideate/references/elicitation.md \
851
906
  || ! grep -Fq 'any present actionable solo-headroom hypothesis' config/skills/devlyn:ideate/references/project-mode.md \
852
- || ! grep -Fq 'any present actionable solo-headroom hypothesis' .claude/skills/devlyn:ideate/references/project-mode.md \
853
907
  || ! grep -Fq 'any present actionable solo-headroom hypothesis' .agents/skills/devlyn:ideate/references/project-mode.md \
854
908
  || ! grep -Fq 'any present actionable solo-headroom hypothesis' config/skills/devlyn:resolve/SKILL.md \
855
- || ! grep -Fq 'any present actionable solo-headroom hypothesis' .claude/skills/devlyn:resolve/SKILL.md \
856
909
  || ! grep -Fq 'any present actionable solo-headroom hypothesis' .agents/skills/devlyn:resolve/SKILL.md \
857
910
  || ! grep -Fq "legacy inline \`## Verification\` JSON carrier" config/skills/devlyn:ideate/SKILL.md \
858
- || ! grep -Fq "legacy inline \`## Verification\` JSON carrier" .claude/skills/devlyn:ideate/SKILL.md \
859
911
  || ! grep -Fq "legacy inline \`## Verification\` JSON carrier" .agents/skills/devlyn:ideate/SKILL.md \
860
912
  || ! grep -Fq "legacy inline \`## Verification\` JSON carrier" config/skills/devlyn:ideate/references/elicitation.md \
861
- || ! grep -Fq "legacy inline \`## Verification\` JSON carrier" .claude/skills/devlyn:ideate/references/elicitation.md \
862
913
  || ! grep -Fq "legacy inline \`## Verification\` JSON carrier" .agents/skills/devlyn:ideate/references/elicitation.md \
863
914
  || ! grep -Fq "legacy inline \`## Verification\` JSON carrier" config/skills/devlyn:ideate/references/from-spec-mode.md \
864
- || ! grep -Fq "legacy inline \`## Verification\` JSON carrier" .claude/skills/devlyn:ideate/references/from-spec-mode.md \
865
915
  || ! grep -Fq "legacy inline \`## Verification\` JSON carrier" .agents/skills/devlyn:ideate/references/from-spec-mode.md \
866
916
  || ! grep -Fq "inline \`## Verification\` JSON carrier" config/skills/devlyn:resolve/SKILL.md \
867
- || ! grep -Fq "inline \`## Verification\` JSON carrier" .claude/skills/devlyn:resolve/SKILL.md \
868
917
  || ! grep -Fq "inline \`## Verification\` JSON carrier" .agents/skills/devlyn:resolve/SKILL.md \
869
918
  || ! grep -Fq 'spec.expected.json.verification_commands[].cmd' config/skills/devlyn:ideate/SKILL.md \
870
- || ! grep -Fq 'spec.expected.json.verification_commands[].cmd' .claude/skills/devlyn:ideate/SKILL.md \
871
919
  || ! grep -Fq 'spec.expected.json.verification_commands[].cmd' .agents/skills/devlyn:ideate/SKILL.md \
872
920
  || ! grep -Fq 'spec.expected.json.verification_commands[].cmd' config/skills/devlyn:ideate/references/elicitation.md \
873
- || ! grep -Fq 'spec.expected.json.verification_commands[].cmd' .claude/skills/devlyn:ideate/references/elicitation.md \
874
921
  || ! grep -Fq 'spec.expected.json.verification_commands[].cmd' .agents/skills/devlyn:ideate/references/elicitation.md \
875
922
  || ! grep -Fq 'spec.expected.json.verification_commands[].cmd' config/skills/devlyn:ideate/references/project-mode.md \
876
- || ! grep -Fq 'spec.expected.json.verification_commands[].cmd' .claude/skills/devlyn:ideate/references/project-mode.md \
877
923
  || ! grep -Fq 'spec.expected.json.verification_commands[].cmd' .agents/skills/devlyn:ideate/references/project-mode.md \
878
924
  || ! grep -Fq 'spec.expected.json.verification_commands[].cmd' config/skills/devlyn:resolve/SKILL.md \
879
- || ! grep -Fq 'spec.expected.json.verification_commands[].cmd' .claude/skills/devlyn:resolve/SKILL.md \
880
925
  || ! grep -Fq 'spec.expected.json.verification_commands[].cmd' .agents/skills/devlyn:resolve/SKILL.md; then
881
926
  bad "ideate/resolve docs must describe mechanical solo-headroom validation"
882
927
  else
@@ -897,18 +942,6 @@ if ! grep -Fq 'def validate_expected_against_sibling_spec' config/skills/_shared
897
942
  || ! grep -Fq 'actionable solo ceiling avoidance was rejected by --check' config/skills/_shared/spec-verify-check.py \
898
943
  || ! grep -Fq 'weak sibling solo ceiling avoidance was accepted by --check-expected' config/skills/_shared/spec-verify-check.py \
899
944
  || ! grep -Fq 'actionable sibling solo ceiling avoidance was rejected by --check-expected' config/skills/_shared/spec-verify-check.py \
900
- || ! grep -Fq 'backticked_observable_miss_commands(spec_text)' .claude/skills/_shared/spec-verify-check.py \
901
- || ! grep -Fq 'observable command must match spec.expected.json' .claude/skills/_shared/spec-verify-check.py \
902
- || ! grep -Fq 'observable command must match `## Verification` JSON carrier' .claude/skills/_shared/spec-verify-check.py \
903
- || ! grep -Fq 'mismatched inline solo-headroom command was accepted by --check' .claude/skills/_shared/spec-verify-check.py \
904
- || ! grep -Fq 'matched inline solo-headroom command was rejected by --check' .claude/skills/_shared/spec-verify-check.py \
905
- || ! grep -Fq 'mismatched sibling solo-headroom command was accepted by --check-expected' .claude/skills/_shared/spec-verify-check.py \
906
- || ! grep -Fq 'matched sibling solo-headroom command was rejected by --check-expected' .claude/skills/_shared/spec-verify-check.py \
907
- || ! grep -Fq 'def validate_present_solo_ceiling_avoidance' .claude/skills/_shared/spec-verify-check.py \
908
- || ! grep -Fq 'weak solo ceiling avoidance was accepted by --check' .claude/skills/_shared/spec-verify-check.py \
909
- || ! grep -Fq 'actionable solo ceiling avoidance was rejected by --check' .claude/skills/_shared/spec-verify-check.py \
910
- || ! grep -Fq 'weak sibling solo ceiling avoidance was accepted by --check-expected' .claude/skills/_shared/spec-verify-check.py \
911
- || ! grep -Fq 'actionable sibling solo ceiling avoidance was rejected by --check-expected' .claude/skills/_shared/spec-verify-check.py \
912
945
  || ! grep -Fq 'backticked_observable_miss_commands(spec_text)' .agents/skills/_shared/spec-verify-check.py \
913
946
  || ! grep -Fq 'observable command must match spec.expected.json' .agents/skills/_shared/spec-verify-check.py \
914
947
  || ! grep -Fq 'observable command must match `## Verification` JSON carrier' .agents/skills/_shared/spec-verify-check.py \
@@ -925,147 +958,106 @@ if ! grep -Fq 'def validate_expected_against_sibling_spec' config/skills/_shared
925
958
  fi
926
959
  if ! grep -Fq 'Verification includes at least one compound scenario that exercises the interaction end-to-end' \
927
960
  config/skills/devlyn:ideate/references/spec-template.md \
928
- || ! grep -Fq 'Verification includes at least one compound scenario that exercises the interaction end-to-end' \
929
- .claude/skills/devlyn:ideate/references/spec-template.md \
930
- || ! grep -Fq 'Verification includes at least one compound scenario that exercises the interaction end-to-end' \
931
- .agents/skills/devlyn:ideate/references/spec-template.md; then
961
+ || ! grep -Fq 'Verification includes at least one compound scenario that exercises the interaction end-to-end' .agents/skills/devlyn:ideate/references/spec-template.md; then
932
962
  bad "ideate spec template must require compound interaction verification for pair-relevant high-risk specs"
933
963
  else
934
964
  ok "ideate spec template requires compound interaction verification for pair-relevant specs"
935
965
  fi
936
966
  if ! grep -Fq 'ask for one concrete compound' config/skills/devlyn:ideate/references/elicitation.md \
937
- || ! grep -Fq 'ask for one concrete compound' .claude/skills/devlyn:ideate/references/elicitation.md \
938
967
  || ! grep -Fq 'ask for one concrete compound' .agents/skills/devlyn:ideate/references/elicitation.md; then
939
968
  bad "ideate elicitation must ask for compound interaction scenarios when pair-relevant risks appear"
940
969
  else
941
970
  ok "ideate elicitation asks for compound interaction scenarios when pair-relevant risks appear"
942
971
  fi
943
972
  if ! grep -Fq 'solo-headroom hypothesis inside `## Verification`' config/skills/devlyn:ideate/references/spec-template.md \
944
- || ! grep -Fq 'solo-headroom hypothesis inside `## Verification`' .claude/skills/devlyn:ideate/references/spec-template.md \
945
973
  || ! grep -Fq 'solo-headroom hypothesis inside `## Verification`' .agents/skills/devlyn:ideate/references/spec-template.md \
946
974
  || ! grep -Fq 'ask for one solo-headroom hypothesis' config/skills/devlyn:ideate/references/elicitation.md \
947
- || ! grep -Fq 'ask for one solo-headroom hypothesis' .claude/skills/devlyn:ideate/references/elicitation.md \
948
975
  || ! grep -Fq 'ask for one solo-headroom hypothesis' .agents/skills/devlyn:ideate/references/elicitation.md; then
949
976
  bad "ideate must require a visible solo-headroom hypothesis for benchmark and pair-evidence specs"
950
977
  else
951
978
  ok "ideate requires solo-headroom hypothesis for benchmark and pair-evidence specs"
952
979
  fi
953
980
  if ! grep -Fq 'must literally contain `solo-headroom hypothesis`' config/skills/devlyn:ideate/references/spec-template.md \
954
- || ! grep -Fq 'must literally contain `solo-headroom hypothesis`' .claude/skills/devlyn:ideate/references/spec-template.md \
955
981
  || ! grep -Fq 'must literally contain `solo-headroom hypothesis`' .agents/skills/devlyn:ideate/references/spec-template.md \
956
982
  || ! grep -Fq 'backticked line itself must contain `miss`' config/skills/devlyn:ideate/references/spec-template.md \
957
- || ! grep -Fq 'backticked line itself must contain `miss`' .claude/skills/devlyn:ideate/references/spec-template.md \
958
983
  || ! grep -Fq 'backticked line itself must contain `miss`' .agents/skills/devlyn:ideate/references/spec-template.md \
959
984
  || ! grep -Fq '`solo_claude`, `miss`, and a backticked observable command' config/skills/devlyn:ideate/references/spec-template.md \
960
- || ! grep -Fq '`solo_claude`, `miss`, and a backticked observable command' .claude/skills/devlyn:ideate/references/spec-template.md \
961
985
  || ! grep -Fq '`solo_claude`, `miss`, and a backticked observable command' .agents/skills/devlyn:ideate/references/spec-template.md \
962
986
  || ! grep -Fq 'command/observable' config/skills/devlyn:ideate/references/spec-template.md \
963
- || ! grep -Fq 'command/observable' .claude/skills/devlyn:ideate/references/spec-template.md \
964
987
  || ! grep -Fq 'command/observable' .agents/skills/devlyn:ideate/references/spec-template.md \
965
988
  || ! grep -Fq 'must literally contain `solo-headroom hypothesis`' config/skills/devlyn:ideate/references/elicitation.md \
966
- || ! grep -Fq 'must literally contain `solo-headroom hypothesis`' .claude/skills/devlyn:ideate/references/elicitation.md \
967
989
  || ! grep -Fq 'must literally contain `solo-headroom hypothesis`' .agents/skills/devlyn:ideate/references/elicitation.md \
968
990
  || ! grep -Fq 'line itself must contain `miss`' config/skills/devlyn:ideate/references/elicitation.md \
969
- || ! grep -Fq 'line itself must contain `miss`' .claude/skills/devlyn:ideate/references/elicitation.md \
970
991
  || ! grep -Fq 'line itself must contain `miss`' .agents/skills/devlyn:ideate/references/elicitation.md \
971
992
  || ! grep -Fq 'Do not write a benchmark/risk-probe/pair-evidence spec until this' config/skills/devlyn:ideate/references/elicitation.md \
972
- || ! grep -Fq 'Do not write a benchmark/risk-probe/pair-evidence spec until this' .claude/skills/devlyn:ideate/references/elicitation.md \
973
993
  || ! grep -Fq 'Do not write a benchmark/risk-probe/pair-evidence spec until this' .agents/skills/devlyn:ideate/references/elicitation.md \
974
994
  || ! grep -Fq 'spec not ready — solo-headroom hypothesis required' config/skills/devlyn:ideate/references/elicitation.md \
975
- || ! grep -Fq 'spec not ready — solo-headroom hypothesis required' .claude/skills/devlyn:ideate/references/elicitation.md \
976
995
  || ! grep -Fq 'spec not ready — solo-headroom hypothesis required' .agents/skills/devlyn:ideate/references/elicitation.md \
977
996
  || ! grep -Fq '`solo_claude`, `miss`, and a backticked observable command' config/skills/devlyn:ideate/references/elicitation.md \
978
- || ! grep -Fq '`solo_claude`, `miss`, and a backticked observable command' .claude/skills/devlyn:ideate/references/elicitation.md \
979
997
  || ! grep -Fq '`solo_claude`, `miss`, and a backticked observable command' .agents/skills/devlyn:ideate/references/elicitation.md \
980
998
  || ! grep -Fq 'command/observable' config/skills/devlyn:ideate/references/elicitation.md \
981
- || ! grep -Fq 'command/observable' .claude/skills/devlyn:ideate/references/elicitation.md \
982
999
  || ! grep -Fq 'command/observable' .agents/skills/devlyn:ideate/references/elicitation.md \
983
1000
  || ! grep -Fq 'Verification literally contains `solo-headroom hypothesis`, `solo_claude`' config/skills/devlyn:ideate/references/from-spec-mode.md \
984
- || ! grep -Fq 'Verification literally contains `solo-headroom hypothesis`, `solo_claude`' .claude/skills/devlyn:ideate/references/from-spec-mode.md \
985
1001
  || ! grep -Fq 'Verification literally contains `solo-headroom hypothesis`, `solo_claude`' .agents/skills/devlyn:ideate/references/from-spec-mode.md \
986
1002
  || ! grep -Fq 'backticked line itself must contain `miss`' config/skills/devlyn:ideate/references/from-spec-mode.md \
987
- || ! grep -Fq 'backticked line itself must contain `miss`' .claude/skills/devlyn:ideate/references/from-spec-mode.md \
988
1003
  || ! grep -Fq 'backticked line itself must contain `miss`' .agents/skills/devlyn:ideate/references/from-spec-mode.md \
989
1004
  || ! grep -Fq 'command/observable' config/skills/devlyn:ideate/references/from-spec-mode.md \
990
- || ! grep -Fq 'command/observable' .claude/skills/devlyn:ideate/references/from-spec-mode.md \
991
1005
  || ! grep -Fq 'command/observable' .agents/skills/devlyn:ideate/references/from-spec-mode.md \
992
1006
  || ! grep -Fq 'spec.expected.json.verification_commands[].cmd' config/skills/devlyn:ideate/references/from-spec-mode.md \
993
- || ! grep -Fq 'spec.expected.json.verification_commands[].cmd' .claude/skills/devlyn:ideate/references/from-spec-mode.md \
994
1007
  || ! grep -Fq 'spec.expected.json.verification_commands[].cmd' .agents/skills/devlyn:ideate/references/from-spec-mode.md \
995
1008
  || ! grep -Fq "source for VERIFY's canonical \`spec.solo_headroom_hypothesis\` trigger reason" config/skills/devlyn:ideate/references/spec-template.md \
996
- || ! grep -Fq "source for VERIFY's canonical \`spec.solo_headroom_hypothesis\` trigger reason" .claude/skills/devlyn:ideate/references/spec-template.md \
997
1009
  || ! grep -Fq "source for VERIFY's canonical \`spec.solo_headroom_hypothesis\` trigger reason" .agents/skills/devlyn:ideate/references/spec-template.md \
998
1010
  || ! grep -Fq 'spec.expected.json.verification_commands[].cmd' config/skills/devlyn:ideate/references/spec-template.md \
999
- || ! grep -Fq 'spec.expected.json.verification_commands[].cmd' .claude/skills/devlyn:ideate/references/spec-template.md \
1000
1011
  || ! grep -Fq 'spec.expected.json.verification_commands[].cmd' .agents/skills/devlyn:ideate/references/spec-template.md; then
1001
1012
  bad "ideate solo-headroom hypothesis prompt must match the actionable checker contract"
1002
1013
  else
1003
1014
  ok "ideate solo-headroom hypothesis prompt matches checker contract"
1004
1015
  fi
1005
1016
  if ! grep -Fq 'quick mode must not infer a solo-headroom hypothesis' config/skills/devlyn:ideate/references/elicitation.md \
1006
- || ! grep -Fq 'quick mode must not infer a solo-headroom hypothesis' .claude/skills/devlyn:ideate/references/elicitation.md \
1007
1017
  || ! grep -Fq 'quick mode must not infer a solo-headroom hypothesis' .agents/skills/devlyn:ideate/references/elicitation.md \
1008
1018
  || ! grep -Fq 'do not infer a solo-headroom hypothesis' config/skills/devlyn:ideate/SKILL.md \
1009
- || ! grep -Fq 'do not infer a solo-headroom hypothesis' .claude/skills/devlyn:ideate/SKILL.md \
1010
1019
  || ! grep -Fq 'do not infer a solo-headroom hypothesis' .agents/skills/devlyn:ideate/SKILL.md; then
1011
1020
  bad "ideate quick mode must not invent solo-headroom hypotheses"
1012
1021
  else
1013
1022
  ok "ideate quick mode does not invent solo-headroom hypotheses"
1014
1023
  fi
1015
1024
  if ! grep -Fq 'solo ceiling avoidance' config/skills/devlyn:ideate/references/spec-template.md \
1016
- || ! grep -Fq 'solo ceiling avoidance' .claude/skills/devlyn:ideate/references/spec-template.md \
1017
1025
  || ! grep -Fq 'solo ceiling avoidance' .agents/skills/devlyn:ideate/references/spec-template.md \
1018
1026
  || ! grep -Fq 'rejected or solo-saturated controls such as `S2`-`S6`' config/skills/devlyn:ideate/references/spec-template.md \
1019
- || ! grep -Fq 'rejected or solo-saturated controls such as `S2`-`S6`' .claude/skills/devlyn:ideate/references/spec-template.md \
1020
1027
  || ! grep -Fq 'rejected or solo-saturated controls such as `S2`-`S6`' .agents/skills/devlyn:ideate/references/spec-template.md \
1021
1028
  || ! grep -Fq 'Solo ceiling avoidance' config/skills/devlyn:ideate/references/elicitation.md \
1022
- || ! grep -Fq 'Solo ceiling avoidance' .claude/skills/devlyn:ideate/references/elicitation.md \
1023
1029
  || ! grep -Fq 'Solo ceiling avoidance' .agents/skills/devlyn:ideate/references/elicitation.md \
1024
1030
  || ! grep -Fq 'spec not ready — solo ceiling avoidance required' config/skills/devlyn:ideate/references/elicitation.md \
1025
- || ! grep -Fq 'spec not ready — solo ceiling avoidance required' .claude/skills/devlyn:ideate/references/elicitation.md \
1026
1031
  || ! grep -Fq 'spec not ready — solo ceiling avoidance required' .agents/skills/devlyn:ideate/references/elicitation.md \
1027
1032
  || ! grep -Fq 'pair-evidence not ready — Pair-candidate headroom is unproven until the spec states solo ceiling avoidance' config/skills/devlyn:ideate/references/from-spec-mode.md \
1028
- || ! grep -Fq 'pair-evidence not ready — Pair-candidate headroom is unproven until the spec states solo ceiling avoidance' .claude/skills/devlyn:ideate/references/from-spec-mode.md \
1029
1033
  || ! grep -Fq 'pair-evidence not ready — Pair-candidate headroom is unproven until the spec states solo ceiling avoidance' .agents/skills/devlyn:ideate/references/from-spec-mode.md \
1030
1034
  || ! grep -Fq 'also do not infer solo ceiling avoidance' config/skills/devlyn:ideate/SKILL.md \
1031
- || ! grep -Fq 'also do not infer solo ceiling avoidance' .claude/skills/devlyn:ideate/SKILL.md \
1032
1035
  || ! grep -Fq 'also do not infer solo ceiling avoidance' .agents/skills/devlyn:ideate/SKILL.md \
1033
1036
  || ! grep -Fq 'per-feature Verification must also include a solo ceiling avoidance note' config/skills/devlyn:ideate/references/project-mode.md \
1034
- || ! grep -Fq 'per-feature Verification must also include a solo ceiling avoidance note' .claude/skills/devlyn:ideate/references/project-mode.md \
1035
1037
  || ! grep -Fq 'per-feature Verification must also include a solo ceiling avoidance note' .agents/skills/devlyn:ideate/references/project-mode.md; then
1036
1038
  bad "ideate must require solo ceiling avoidance for new unmeasured pair candidates"
1037
1039
  else
1038
1040
  ok "ideate requires solo ceiling avoidance for new unmeasured pair candidates"
1039
1041
  fi
1040
1042
  if ! grep -Fq 'complexity: medium' config/skills/devlyn:ideate/references/spec-template.md \
1041
- || ! grep -Fq 'complexity: medium' .claude/skills/devlyn:ideate/references/spec-template.md \
1042
1043
  || ! grep -Fq 'complexity: medium' .agents/skills/devlyn:ideate/references/spec-template.md \
1043
1044
  || ! grep -Fq 'Complexity signal' config/skills/devlyn:ideate/references/elicitation.md \
1044
- || ! grep -Fq 'Complexity signal' .claude/skills/devlyn:ideate/references/elicitation.md \
1045
1045
  || ! grep -Fq 'Complexity signal' .agents/skills/devlyn:ideate/references/elicitation.md \
1046
1046
  || ! grep -Fq 'downstream VERIFY pair-trigger signal' config/skills/devlyn:ideate/references/elicitation.md \
1047
- || ! grep -Fq 'downstream VERIFY pair-trigger signal' .claude/skills/devlyn:ideate/references/elicitation.md \
1048
1047
  || ! grep -Fq 'downstream VERIFY pair-trigger signal' .agents/skills/devlyn:ideate/references/elicitation.md \
1049
1048
  || ! grep -Fq 'complexity=medium default' config/skills/devlyn:ideate/references/from-spec-mode.md \
1050
- || ! grep -Fq 'complexity=medium default' .claude/skills/devlyn:ideate/references/from-spec-mode.md \
1051
1049
  || ! grep -Fq 'complexity=medium default' .agents/skills/devlyn:ideate/references/from-spec-mode.md \
1052
1050
  || ! grep -Fq 'supported `complexity` frontmatter' config/skills/devlyn:ideate/SKILL.md \
1053
- || ! grep -Fq 'supported `complexity` frontmatter' .claude/skills/devlyn:ideate/SKILL.md \
1054
1051
  || ! grep -Fq 'supported `complexity` frontmatter' .agents/skills/devlyn:ideate/SKILL.md \
1055
1052
  || ! grep -Fq 'supported `complexity` frontmatter' config/skills/devlyn:ideate/references/elicitation.md \
1056
- || ! grep -Fq 'supported `complexity` frontmatter' .claude/skills/devlyn:ideate/references/elicitation.md \
1057
1053
  || ! grep -Fq 'supported `complexity` frontmatter' .agents/skills/devlyn:ideate/references/elicitation.md \
1058
1054
  || ! grep -Fq 'supported `complexity` frontmatter' config/skills/devlyn:resolve/SKILL.md \
1059
- || ! grep -Fq 'supported `complexity` frontmatter' .claude/skills/devlyn:resolve/SKILL.md \
1060
1055
  || ! grep -Fq 'supported `complexity` frontmatter' .agents/skills/devlyn:resolve/SKILL.md \
1061
1056
  || ! grep -Fq 'sibling spec `complexity` frontmatter' config/skills/devlyn:ideate/SKILL.md \
1062
- || ! grep -Fq 'sibling spec `complexity` frontmatter' .claude/skills/devlyn:ideate/SKILL.md \
1063
1057
  || ! grep -Fq 'sibling spec `complexity` frontmatter' .agents/skills/devlyn:ideate/SKILL.md \
1064
1058
  || ! grep -Fq 'sibling spec `complexity` frontmatter' config/skills/devlyn:resolve/SKILL.md \
1065
- || ! grep -Fq 'sibling spec `complexity` frontmatter' .claude/skills/devlyn:resolve/SKILL.md \
1066
1059
  || ! grep -Fq 'sibling spec `complexity` frontmatter' .agents/skills/devlyn:resolve/SKILL.md \
1067
1060
  || ! grep -Fq 'Frontmatter has `id`, `title`, `kind`, `status: planned`, `complexity`' config/skills/devlyn:ideate/SKILL.md \
1068
- || ! grep -Fq 'Frontmatter has `id`, `title`, `kind`, `status: planned`, `complexity`' .claude/skills/devlyn:ideate/SKILL.md \
1069
1061
  || ! grep -Fq 'Frontmatter has `id`, `title`, `kind`, `status: planned`, `complexity`' .agents/skills/devlyn:ideate/SKILL.md; then
1070
1062
  bad "ideate specs must emit complexity frontmatter for resolve pair triggers"
1071
1063
  else
@@ -1073,163 +1065,97 @@ else
1073
1065
  fi
1074
1066
  if ! grep -Fq 'warning: Verification may need one compound end-to-end scenario before pair-relevant risks are measurable' \
1075
1067
  config/skills/devlyn:ideate/references/from-spec-mode.md \
1076
- || ! grep -Fq 'warning: Verification may need one compound end-to-end scenario before pair-relevant risks are measurable' \
1077
- .claude/skills/devlyn:ideate/references/from-spec-mode.md \
1078
- || ! grep -Fq 'warning: Verification may need one compound end-to-end scenario before pair-relevant risks are measurable' \
1079
- .agents/skills/devlyn:ideate/references/from-spec-mode.md; then
1068
+ || ! grep -Fq 'warning: Verification may need one compound end-to-end scenario before pair-relevant risks are measurable' .agents/skills/devlyn:ideate/references/from-spec-mode.md; then
1080
1069
  bad "ideate from-spec mode must warn when preserved high-risk specs lack compound verification"
1081
1070
  else
1082
1071
  ok "ideate from-spec mode warns on pair-relevant specs with weak verification"
1083
1072
  fi
1084
1073
  if ! grep -Fq 'pair-evidence not ready — Pair-candidate headroom is unproven until the spec states a solo-headroom hypothesis' \
1085
1074
  config/skills/devlyn:ideate/references/from-spec-mode.md \
1086
- || ! grep -Fq 'pair-evidence not ready — Pair-candidate headroom is unproven until the spec states a solo-headroom hypothesis' \
1087
- .claude/skills/devlyn:ideate/references/from-spec-mode.md \
1088
- || ! grep -Fq 'pair-evidence not ready — Pair-candidate headroom is unproven until the spec states a solo-headroom hypothesis' \
1089
- .agents/skills/devlyn:ideate/references/from-spec-mode.md \
1075
+ || ! grep -Fq 'pair-evidence not ready — Pair-candidate headroom is unproven until the spec states a solo-headroom hypothesis' .agents/skills/devlyn:ideate/references/from-spec-mode.md \
1090
1076
  || ! grep -Fq 'Do not call' config/skills/devlyn:ideate/references/from-spec-mode.md \
1091
- || ! grep -Fq 'Do not call' .claude/skills/devlyn:ideate/references/from-spec-mode.md \
1092
1077
  || ! grep -Fq 'Do not call' .agents/skills/devlyn:ideate/references/from-spec-mode.md \
1093
1078
  || ! grep -Fq 'announcement must say `pair-evidence not ready`' config/skills/devlyn:ideate/SKILL.md \
1094
- || ! grep -Fq 'announcement must say `pair-evidence not ready`' .claude/skills/devlyn:ideate/SKILL.md \
1095
1079
  || ! grep -Fq 'announcement must say `pair-evidence not ready`' .agents/skills/devlyn:ideate/SKILL.md; then
1096
1080
  bad "ideate from-spec mode must warn when pair-candidate specs lack solo-headroom hypothesis"
1097
1081
  else
1098
1082
  ok "ideate from-spec mode warns on missing solo-headroom hypothesis"
1099
1083
  fi
1100
1084
  if ! grep -Fq 'per-feature Verification must' config/skills/devlyn:ideate/references/project-mode.md \
1101
- || ! grep -Fq 'per-feature Verification must' .claude/skills/devlyn:ideate/references/project-mode.md \
1102
1085
  || ! grep -Fq 'per-feature Verification must' .agents/skills/devlyn:ideate/references/project-mode.md; then
1103
1086
  bad "ideate project mode must require compound verification inside each pair-relevant feature spec"
1104
1087
  else
1105
1088
  ok "ideate project mode keeps compound verification inside pair-relevant feature specs"
1106
1089
  fi
1107
1090
  if ! grep -Fq 'per-feature Verification must include a solo-headroom' config/skills/devlyn:ideate/references/project-mode.md \
1108
- || ! grep -Fq 'per-feature Verification must include a solo-headroom' .claude/skills/devlyn:ideate/references/project-mode.md \
1109
1091
  || ! grep -Fq 'per-feature Verification must include a solo-headroom' .agents/skills/devlyn:ideate/references/project-mode.md \
1110
- || grep -rq 'Context or Verification' config/skills/devlyn:ideate/references .claude/skills/devlyn:ideate/references .agents/skills/devlyn:ideate/references; then
1092
+ || grep -rq 'Context or Verification' config/skills/devlyn:ideate/references .agents/skills/devlyn:ideate/references; then
1111
1093
  bad "ideate project mode must keep solo-headroom hypothesis inside each pair-candidate feature spec"
1112
1094
  else
1113
1095
  ok "ideate project mode keeps solo-headroom hypothesis inside each pair-candidate feature spec"
1114
1096
  fi
1115
- if ! grep -Fq 'feature spec must literally contain' \
1116
- config/skills/devlyn:ideate/references/project-mode.md \
1117
- || ! grep -Fq 'feature spec must literally contain' \
1118
- .claude/skills/devlyn:ideate/references/project-mode.md \
1119
- || ! grep -Fq 'feature spec must literally contain' \
1120
- .agents/skills/devlyn:ideate/references/project-mode.md \
1121
- || ! grep -Fq '`solo-headroom hypothesis`, `solo_claude`, `miss`, and a backticked' \
1122
- config/skills/devlyn:ideate/references/project-mode.md \
1123
- || ! grep -Fq '`solo-headroom hypothesis`, `solo_claude`, `miss`, and a backticked' \
1124
- .claude/skills/devlyn:ideate/references/project-mode.md \
1125
- || ! grep -Fq '`solo-headroom hypothesis`, `solo_claude`, `miss`, and a backticked' \
1126
- .agents/skills/devlyn:ideate/references/project-mode.md \
1097
+ if ! grep -Fq 'feature spec must literally contain' config/skills/devlyn:ideate/references/project-mode.md \
1098
+ || ! grep -Fq 'feature spec must literally contain' .agents/skills/devlyn:ideate/references/project-mode.md \
1099
+ || ! grep -Fq '`solo-headroom hypothesis`, `solo_claude`, `miss`, and a backticked' config/skills/devlyn:ideate/references/project-mode.md \
1100
+ || ! grep -Fq '`solo-headroom hypothesis`, `solo_claude`, `miss`, and a backticked' .agents/skills/devlyn:ideate/references/project-mode.md \
1127
1101
  || ! grep -Fq 'behavior a capable' config/skills/devlyn:ideate/references/project-mode.md \
1128
- || ! grep -Fq 'behavior a capable' .claude/skills/devlyn:ideate/references/project-mode.md \
1129
1102
  || ! grep -Fq 'behavior a capable' .agents/skills/devlyn:ideate/references/project-mode.md \
1130
1103
  || ! grep -Fq 'backticked line itself must' config/skills/devlyn:ideate/references/project-mode.md \
1131
- || ! grep -Fq 'backticked line itself must' .claude/skills/devlyn:ideate/references/project-mode.md \
1132
1104
  || ! grep -Fq 'backticked line itself must' .agents/skills/devlyn:ideate/references/project-mode.md \
1133
- || ! grep -Fq 'command/observable' \
1134
- config/skills/devlyn:ideate/references/project-mode.md \
1135
- || ! grep -Fq 'command/observable' \
1136
- .claude/skills/devlyn:ideate/references/project-mode.md \
1137
- || ! grep -Fq 'command/observable' \
1138
- .agents/skills/devlyn:ideate/references/project-mode.md; then
1105
+ || ! grep -Fq 'command/observable' config/skills/devlyn:ideate/references/project-mode.md \
1106
+ || ! grep -Fq 'command/observable' .agents/skills/devlyn:ideate/references/project-mode.md; then
1139
1107
  bad "ideate project mode solo-headroom prompt must keep the actionable checker contract"
1140
1108
  else
1141
1109
  ok "ideate project mode solo-headroom prompt keeps checker contract"
1142
1110
  fi
1143
1111
 
1144
- if ! grep -Fq 'If the visible spec includes a solo-headroom hypothesis, the first probe must' \
1145
- config/skills/devlyn:resolve/references/phases/probe-derive.md \
1146
- || ! grep -Fq 'If the visible spec includes a solo-headroom hypothesis, the first probe must' \
1147
- .claude/skills/devlyn:resolve/references/phases/probe-derive.md \
1148
- || ! grep -Fq 'If the visible spec includes a solo-headroom hypothesis, the first probe must' \
1149
- .agents/skills/devlyn:resolve/references/phases/probe-derive.md \
1150
- || ! grep -Fq 'When the visible spec includes a solo-headroom hypothesis, the first probe must' \
1151
- config/skills/devlyn:resolve/SKILL.md \
1152
- || ! grep -Fq 'When the visible spec includes a solo-headroom hypothesis, the first probe must' \
1153
- .claude/skills/devlyn:resolve/SKILL.md \
1154
- || ! grep -Fq 'When the visible spec includes a solo-headroom hypothesis, the first probe must' \
1155
- .agents/skills/devlyn:resolve/SKILL.md \
1156
- || ! grep -Fq 'its `cmd` must contain the hypothesis'\''s backticked' \
1157
- config/skills/devlyn:resolve/SKILL.md \
1158
- || ! grep -Fq 'its `cmd` must contain the hypothesis'\''s backticked' \
1159
- .claude/skills/devlyn:resolve/SKILL.md \
1160
- || ! grep -Fq 'its `cmd` must contain the hypothesis'\''s backticked' \
1161
- .agents/skills/devlyn:resolve/SKILL.md \
1162
- || ! grep -Fq 'its `derived_from` must reference the hypothesis bullet' \
1163
- config/skills/devlyn:resolve/SKILL.md \
1164
- || ! grep -Fq 'its `derived_from` must reference the hypothesis bullet' \
1165
- .claude/skills/devlyn:resolve/SKILL.md \
1166
- || ! grep -Fq 'its `derived_from` must reference the hypothesis bullet' \
1167
- .agents/skills/devlyn:resolve/SKILL.md; then
1112
+ if ! grep -Fq 'If the visible spec includes a solo-headroom hypothesis, the first probe must' config/skills/devlyn:resolve/references/phases/probe-derive.md \
1113
+ || ! grep -Fq 'If the visible spec includes a solo-headroom hypothesis, the first probe must' .agents/skills/devlyn:resolve/references/phases/probe-derive.md \
1114
+ || ! grep -Fq 'When the visible spec includes a solo-headroom hypothesis, the first probe must' config/skills/devlyn:resolve/SKILL.md \
1115
+ || ! grep -Fq 'When the visible spec includes a solo-headroom hypothesis, the first probe must' .agents/skills/devlyn:resolve/SKILL.md \
1116
+ || ! grep -Fq 'its `cmd` must contain the hypothesis'\''s backticked' config/skills/devlyn:resolve/SKILL.md \
1117
+ || ! grep -Fq 'its `cmd` must contain the hypothesis'\''s backticked' .agents/skills/devlyn:resolve/SKILL.md \
1118
+ || ! grep -Fq 'its `derived_from` must reference the hypothesis bullet' config/skills/devlyn:resolve/SKILL.md \
1119
+ || ! grep -Fq 'its `derived_from` must reference the hypothesis bullet' .agents/skills/devlyn:resolve/SKILL.md; then
1168
1120
  bad "resolve risk-probe prompts must consume solo-headroom hypothesis before pair-evidence work"
1169
1121
  else
1170
1122
  ok "resolve risk-probe prompts consume solo-headroom hypothesis"
1171
1123
  fi
1172
- if ! grep -Fq 'the behavior the spec says `solo_claude` is expected to miss' \
1173
- config/skills/devlyn:resolve/references/phases/probe-derive.md \
1174
- || ! grep -Fq 'the behavior the spec says `solo_claude` is expected to miss' \
1175
- .claude/skills/devlyn:resolve/references/phases/probe-derive.md \
1176
- || ! grep -Fq 'the behavior the spec says `solo_claude` is expected to miss' \
1177
- .agents/skills/devlyn:resolve/references/phases/probe-derive.md \
1178
- || ! grep -Fq 'exercise the stated `solo_claude` miss' \
1179
- config/skills/devlyn:resolve/references/phases/probe-derive.md \
1180
- || ! grep -Fq 'exercise the stated `solo_claude` miss' \
1181
- .claude/skills/devlyn:resolve/references/phases/probe-derive.md \
1182
- || ! grep -Fq 'exercise the stated `solo_claude` miss' \
1183
- .agents/skills/devlyn:resolve/references/phases/probe-derive.md \
1184
- || ! grep -Fq 'with a `cmd` containing the hypothesis'\''s' \
1185
- config/skills/devlyn:resolve/references/phases/probe-derive.md \
1186
- || ! grep -Fq 'with a `cmd` containing the hypothesis'\''s' \
1187
- .claude/skills/devlyn:resolve/references/phases/probe-derive.md \
1188
- || ! grep -Fq 'with a `cmd` containing the hypothesis'\''s' \
1189
- .agents/skills/devlyn:resolve/references/phases/probe-derive.md \
1190
- || ! grep -Fq '`derived_from` pointing at the hypothesis' \
1191
- config/skills/devlyn:resolve/references/phases/probe-derive.md \
1192
- || ! grep -Fq '`derived_from` pointing at the hypothesis' \
1193
- .claude/skills/devlyn:resolve/references/phases/probe-derive.md \
1194
- || ! grep -Fq '`derived_from` pointing at the hypothesis' \
1195
- .agents/skills/devlyn:resolve/references/phases/probe-derive.md; then
1124
+ if ! grep -Fq 'the behavior the spec says `solo_claude` is expected to miss' config/skills/devlyn:resolve/references/phases/probe-derive.md \
1125
+ || ! grep -Fq 'the behavior the spec says `solo_claude` is expected to miss' .agents/skills/devlyn:resolve/references/phases/probe-derive.md \
1126
+ || ! grep -Fq 'exercise the stated `solo_claude` miss' config/skills/devlyn:resolve/references/phases/probe-derive.md \
1127
+ || ! grep -Fq 'exercise the stated `solo_claude` miss' .agents/skills/devlyn:resolve/references/phases/probe-derive.md \
1128
+ || ! grep -Fq 'with a `cmd` containing the hypothesis'\''s' config/skills/devlyn:resolve/references/phases/probe-derive.md \
1129
+ || ! grep -Fq 'with a `cmd` containing the hypothesis'\''s' .agents/skills/devlyn:resolve/references/phases/probe-derive.md \
1130
+ || ! grep -Fq '`derived_from` pointing at the hypothesis' config/skills/devlyn:resolve/references/phases/probe-derive.md \
1131
+ || ! grep -Fq '`derived_from` pointing at the hypothesis' .agents/skills/devlyn:resolve/references/phases/probe-derive.md; then
1196
1132
  bad "resolve risk-probe solo-headroom prompt must target the stated solo_claude miss"
1197
1133
  else
1198
1134
  ok "resolve risk-probe solo-headroom prompt targets the stated solo_claude miss"
1199
1135
  fi
1200
- if ! grep -Fq 'If the spec includes a solo-headroom hypothesis, one of the two targeted' \
1136
+ if ! grep -Fq 'If the spec includes a solo-headroom hypothesis, one targeted review must use' \
1201
1137
  config/skills/devlyn:resolve/references/phases/verify.md \
1202
- || ! grep -Fq 'If the spec includes a solo-headroom hypothesis, one of the two targeted' \
1203
- .claude/skills/devlyn:resolve/references/phases/verify.md \
1204
- || ! grep -Fq 'If the spec includes a solo-headroom hypothesis, one of the two targeted' \
1138
+ || ! grep -Fq 'If the spec includes a solo-headroom hypothesis, one targeted review must use' \
1205
1139
  .agents/skills/devlyn:resolve/references/phases/verify.md \
1206
- || ! grep -Fq 'If the spec includes a solo-headroom hypothesis, one of those targeted probes must' \
1140
+ || ! grep -Fq 'If the spec includes a solo-headroom hypothesis, one targeted review must use' \
1207
1141
  config/skills/devlyn:resolve/SKILL.md \
1208
- || ! grep -Fq 'If the spec includes a solo-headroom hypothesis, one of those targeted probes must' \
1209
- .claude/skills/devlyn:resolve/SKILL.md \
1210
- || ! grep -Fq 'If the spec includes a solo-headroom hypothesis, one of those targeted probes must' \
1142
+ || ! grep -Fq 'If the spec includes a solo-headroom hypothesis, one targeted review must use' \
1211
1143
  .agents/skills/devlyn:resolve/SKILL.md \
1212
- || ! grep -Fq 'using the hypothesis'\''s backticked observable command as its command anchor' \
1144
+ || ! grep -Fq 'hypothesis'\''s backticked observable command as the exact anchor' \
1213
1145
  config/skills/devlyn:resolve/SKILL.md \
1214
- || ! grep -Fq 'using the hypothesis'\''s backticked observable command as its command anchor' \
1215
- .claude/skills/devlyn:resolve/SKILL.md \
1216
- || ! grep -Fq 'using the hypothesis'\''s backticked observable command as its command anchor' \
1146
+ || ! grep -Fq 'hypothesis'\''s backticked observable command as the exact anchor' \
1217
1147
  .agents/skills/devlyn:resolve/SKILL.md \
1218
- || ! grep -Fq 'hypothesis'\''s backticked observable command as its command anchor' \
1148
+ || ! grep -Fq 'hypothesis'\''s backticked observable command as its exact anchor' \
1219
1149
  config/skills/devlyn:resolve/references/phases/verify.md \
1220
- || ! grep -Fq 'hypothesis'\''s backticked observable command as its command anchor' \
1221
- .claude/skills/devlyn:resolve/references/phases/verify.md \
1222
- || ! grep -Fq 'hypothesis'\''s backticked observable command as its command anchor' \
1150
+ || ! grep -Fq 'hypothesis'\''s backticked observable command as its exact anchor' \
1223
1151
  .agents/skills/devlyn:resolve/references/phases/verify.md; then
1224
1152
  bad "resolve pair-JUDGE prompts must prioritize solo-headroom hypothesis"
1225
1153
  else
1226
1154
  ok "resolve pair-JUDGE prompts prioritize solo-headroom hypothesis"
1227
1155
  fi
1228
1156
  if ! grep -Fq 'The `--engine` flag does not disable default pairing' config/skills/devlyn:resolve/references/phases/verify.md \
1229
- || ! grep -Fq 'The `--engine` flag does not disable default pairing' .claude/skills/devlyn:resolve/references/phases/verify.md \
1230
1157
  || ! grep -Fq 'The `--engine` flag does not disable default pairing' .agents/skills/devlyn:resolve/references/phases/verify.md \
1231
1158
  || ! grep -Fq 'the second judge uses the OTHER engine by default when available' config/skills/devlyn:resolve/SKILL.md \
1232
- || ! grep -Fq 'the second judge uses the OTHER engine by default when available' .claude/skills/devlyn:resolve/SKILL.md \
1233
1159
  || ! grep -Fq 'the second judge uses the OTHER engine by default when available' .agents/skills/devlyn:resolve/SKILL.md \
1234
1160
  || ! grep -Fq '_shared/adapters/<name>.md' config/skills/devlyn:resolve/references/phases/verify.md \
1235
1161
  || ! grep -Fq '`## Invocation`' config/skills/devlyn:resolve/references/phases/verify.md \
@@ -1241,22 +1167,16 @@ else
1241
1167
  ok "engine-neutral pair-judge dual declaration (iter-0060) in sync"
1242
1168
  fi
1243
1169
  if ! grep -Fq '`complexity.high`, `complexity.large`' config/skills/devlyn:resolve/SKILL.md \
1244
- || ! grep -Fq '`complexity.high`, `complexity.large`' .claude/skills/devlyn:resolve/SKILL.md \
1245
1170
  || ! grep -Fq '`complexity.high`, `complexity.large`' .agents/skills/devlyn:resolve/SKILL.md \
1246
1171
  || ! grep -Fq '`spec.complexity.high`, `spec.complexity.large`' config/skills/devlyn:resolve/SKILL.md \
1247
- || ! grep -Fq '`spec.complexity.high`, `spec.complexity.large`' .claude/skills/devlyn:resolve/SKILL.md \
1248
1172
  || ! grep -Fq '`spec.complexity.high`, `spec.complexity.large`' .agents/skills/devlyn:resolve/SKILL.md \
1249
1173
  || ! grep -Fq 'Legacy complexity values remain accepted only for archived compatibility' config/skills/devlyn:resolve/references/state-schema.md \
1250
- || ! grep -Fq 'Legacy complexity values remain accepted only for archived compatibility' .claude/skills/devlyn:resolve/references/state-schema.md \
1251
1174
  || ! grep -Fq 'Legacy complexity values remain accepted only for archived compatibility' .agents/skills/devlyn:resolve/references/state-schema.md \
1252
1175
  || ! grep -Fq '`complexity.high`, `complexity.large`, `spec.complexity.high`, `spec.complexity.large`' config/skills/devlyn:resolve/references/state-schema.md \
1253
- || ! grep -Fq '`complexity.high`, `complexity.large`, `spec.complexity.high`, `spec.complexity.large`' .claude/skills/devlyn:resolve/references/state-schema.md \
1254
1176
  || ! grep -Fq '`complexity.high`, `complexity.large`, `spec.complexity.high`, `spec.complexity.large`' .agents/skills/devlyn:resolve/references/state-schema.md \
1255
1177
  || ! grep -Fq '`complexity.large`, `spec.complexity.high`, `spec.complexity.large`,' config/skills/devlyn:resolve/references/phases/verify.md \
1256
- || ! grep -Fq '`complexity.large`, `spec.complexity.high`, `spec.complexity.large`,' .claude/skills/devlyn:resolve/references/phases/verify.md \
1257
1178
  || ! grep -Fq '`complexity.large`, `spec.complexity.high`, `spec.complexity.large`,' .agents/skills/devlyn:resolve/references/phases/verify.md \
1258
1179
  || ! grep -Fq '`spec.solo_headroom_hypothesis`, `risk.high`, `risk_probes.enabled`,' config/skills/devlyn:resolve/references/phases/verify.md \
1259
- || ! grep -Fq '`spec.solo_headroom_hypothesis`, `risk.high`, `risk_probes.enabled`,' .claude/skills/devlyn:resolve/references/phases/verify.md \
1260
1180
  || ! grep -Fq '`spec.solo_headroom_hypothesis`, `risk.high`, `risk_probes.enabled`,' .agents/skills/devlyn:resolve/references/phases/verify.md; then
1261
1181
  bad "resolve VERIFY docs must distinguish current large complexity, legacy high state, and legacy large spec compatibility"
1262
1182
  else
@@ -1279,23 +1199,6 @@ if ! grep -Fq 'def spec_has_solo_headroom_hypothesis' config/skills/_shared/veri
1279
1199
  || ! grep -Fq 'spec_has_solo_headroom_hypothesis(' config/skills/_shared/verify-merge-findings.py \
1280
1200
  || ! grep -Fq ') is False' config/skills/_shared/verify-merge-findings.py \
1281
1201
  || ! grep -Fq ') is True' config/skills/_shared/verify-merge-findings.py \
1282
- || ! grep -Fq 'def spec_has_solo_headroom_hypothesis' .claude/skills/_shared/verify-merge-findings.py \
1283
- || ! grep -Fq 'spec.solo_headroom_hypothesis' .claude/skills/_shared/verify-merge-findings.py \
1284
- || ! grep -Fq 'and "solo_claude" in lower' .claude/skills/_shared/verify-merge-findings.py \
1285
- || ! grep -Fq 'and "miss" in lower' .claude/skills/_shared/verify-merge-findings.py \
1286
- || ! grep -Fq 'OBSERVABLE_COMMAND_MARKERS = ("command", "observable", "expose")' .claude/skills/_shared/verify-merge-findings.py \
1287
- || ! grep -Fq 'def is_command_like_backtick' .claude/skills/_shared/verify-merge-findings.py \
1288
- || ! grep -Fq 'for key in ("spec_path", "criteria_path")' .claude/skills/_shared/verify-merge-findings.py \
1289
- || ! grep -Fq 'has_backticked_observable_command(text)' .claude/skills/_shared/verify-merge-findings.py \
1290
- || ! grep -Fq 'Observable command: `node check.js` exposes behavior' .claude/skills/_shared/verify-merge-findings.py \
1291
- || ! grep -Fq 'observable `SOLO_CLAUDE` exposes the miss' .claude/skills/_shared/verify-merge-findings.py \
1292
- || ! grep -Fq 'observable `priority rollback` exposes the miss' .claude/skills/_shared/verify-merge-findings.py \
1293
- || ! grep -Fq 'implementation token `rollback`' .claude/skills/_shared/verify-merge-findings.py \
1294
- || ! grep -Fq '`SOLO_CLAUDE` should miss' .claude/skills/_shared/verify-merge-findings.py \
1295
- || ! grep -Fq '{"source": {"criteria_path": str(criteria_path)}}' .claude/skills/_shared/verify-merge-findings.py \
1296
- || ! grep -Fq 'spec_has_solo_headroom_hypothesis(' .claude/skills/_shared/verify-merge-findings.py \
1297
- || ! grep -Fq ') is False' .claude/skills/_shared/verify-merge-findings.py \
1298
- || ! grep -Fq ') is True' .claude/skills/_shared/verify-merge-findings.py \
1299
1202
  || ! grep -Fq 'def spec_has_solo_headroom_hypothesis' .agents/skills/_shared/verify-merge-findings.py \
1300
1203
  || ! grep -Fq 'spec.solo_headroom_hypothesis' .agents/skills/_shared/verify-merge-findings.py \
1301
1204
  || ! grep -Fq 'and "solo_claude" in lower' .agents/skills/_shared/verify-merge-findings.py \
@@ -1313,63 +1216,43 @@ if ! grep -Fq 'def spec_has_solo_headroom_hypothesis' config/skills/_shared/veri
1313
1216
  || ! grep -Fq 'spec_has_solo_headroom_hypothesis(' .agents/skills/_shared/verify-merge-findings.py \
1314
1217
  || ! grep -Fq ') is False' .agents/skills/_shared/verify-merge-findings.py \
1315
1218
  || ! grep -Fq ') is True' .agents/skills/_shared/verify-merge-findings.py \
1316
- || ! grep -Fq '`spec.solo_headroom_hypothesis`' \
1317
- config/skills/devlyn:resolve/references/phases/verify.md \
1318
- || ! grep -Fq '`spec.solo_headroom_hypothesis`' \
1319
- .claude/skills/devlyn:resolve/references/phases/verify.md \
1320
- || ! grep -Fq '`spec.solo_headroom_hypothesis`' \
1321
- .agents/skills/devlyn:resolve/references/phases/verify.md \
1219
+ || ! grep -Fq '`spec.solo_headroom_hypothesis`' config/skills/devlyn:resolve/references/phases/verify.md \
1220
+ || ! grep -Fq '`spec.solo_headroom_hypothesis`' .agents/skills/devlyn:resolve/references/phases/verify.md \
1322
1221
  || ! grep -Fq '`spec.solo_headroom_hypothesis`' config/skills/devlyn:resolve/references/state-schema.md \
1323
- || ! grep -Fq '`spec.solo_headroom_hypothesis`' .claude/skills/devlyn:resolve/references/state-schema.md \
1324
1222
  || ! grep -Fq '`spec.solo_headroom_hypothesis`' .agents/skills/devlyn:resolve/references/state-schema.md \
1325
1223
  || ! grep -Fq 'same actionable solo-headroom hypothesis is a VERIFY pair-trigger reason' config/skills/devlyn:resolve/SKILL.md \
1326
- || ! grep -Fq 'same actionable solo-headroom hypothesis is a VERIFY pair-trigger reason' .claude/skills/devlyn:resolve/SKILL.md \
1327
1224
  || ! grep -Fq 'same actionable solo-headroom hypothesis is a VERIFY pair-trigger reason' .agents/skills/devlyn:resolve/SKILL.md; then
1328
1225
  bad "resolve VERIFY pair trigger must include actionable solo-headroom hypothesis specs"
1329
1226
  else
1330
1227
  ok "resolve VERIFY pair trigger includes actionable solo-headroom hypothesis specs"
1331
1228
  fi
1332
1229
  if ! grep -Fq 'pair_evidence_intent' config/skills/devlyn:resolve/references/free-form-mode.md \
1333
- || ! grep -Fq 'pair_evidence_intent' .claude/skills/devlyn:resolve/references/free-form-mode.md \
1334
1230
  || ! grep -Fq 'pair_evidence_intent' .agents/skills/devlyn:resolve/references/free-form-mode.md \
1335
1231
  || ! grep -Fq 'has_actionable_solo_headroom' config/skills/devlyn:resolve/references/free-form-mode.md \
1336
- || ! grep -Fq 'has_actionable_solo_headroom' .claude/skills/devlyn:resolve/references/free-form-mode.md \
1337
1232
  || ! grep -Fq 'has_actionable_solo_headroom' .agents/skills/devlyn:resolve/references/free-form-mode.md \
1338
1233
  || ! grep -Fq 'state.source.type = "generated"' config/skills/devlyn:resolve/SKILL.md \
1339
- || ! grep -Fq 'state.source.type = "generated"' .claude/skills/devlyn:resolve/SKILL.md \
1340
1234
  || ! grep -Fq 'state.source.type = "generated"' .agents/skills/devlyn:resolve/SKILL.md \
1341
1235
  || ! grep -Fq 'state.source.criteria_path = ".devlyn/criteria.generated.md"' config/skills/devlyn:resolve/references/free-form-mode.md \
1342
- || ! grep -Fq 'state.source.criteria_path = ".devlyn/criteria.generated.md"' .claude/skills/devlyn:resolve/references/free-form-mode.md \
1343
1236
  || ! grep -Fq 'state.source.criteria_path = ".devlyn/criteria.generated.md"' .agents/skills/devlyn:resolve/references/free-form-mode.md \
1344
1237
  || ! grep -Fq 'state.source.criteria_sha256' config/skills/devlyn:resolve/references/free-form-mode.md \
1345
- || ! grep -Fq 'state.source.criteria_sha256' .claude/skills/devlyn:resolve/references/free-form-mode.md \
1346
1238
  || ! grep -Fq 'state.source.criteria_sha256' .agents/skills/devlyn:resolve/references/free-form-mode.md \
1347
1239
  || ! grep -Fq 'state.source.criteria_sha256` for generated free-form mode' config/skills/devlyn:resolve/references/phases/verify.md \
1348
- || ! grep -Fq 'state.source.criteria_sha256` for generated free-form mode' .claude/skills/devlyn:resolve/references/phases/verify.md \
1349
1240
  || ! grep -Fq 'state.source.criteria_sha256` for generated free-form mode' .agents/skills/devlyn:resolve/references/phases/verify.md \
1350
1241
  || ! grep -Fq 'Free-form sets `type: "generated"`' config/skills/devlyn:resolve/references/state-schema.md \
1351
- || ! grep -Fq 'Free-form sets `type: "generated"`' .claude/skills/devlyn:resolve/references/state-schema.md \
1352
1242
  || ! grep -Fq 'Free-form sets `type: "generated"`' .agents/skills/devlyn:resolve/references/state-schema.md \
1353
1243
  || ! grep -Fq 'backticked observable command line that itself contains `miss`' config/skills/devlyn:resolve/references/free-form-mode.md \
1354
- || ! grep -Fq 'backticked observable command line that itself contains `miss`' .claude/skills/devlyn:resolve/references/free-form-mode.md \
1355
1244
  || ! grep -Fq 'backticked observable command line that itself contains `miss`' .agents/skills/devlyn:resolve/references/free-form-mode.md \
1356
1245
  || ! grep -Fq 'BLOCKED:solo-headroom-hypothesis-required' config/skills/devlyn:resolve/references/free-form-mode.md \
1357
- || ! grep -Fq 'BLOCKED:solo-headroom-hypothesis-required' .claude/skills/devlyn:resolve/references/free-form-mode.md \
1358
1246
  || ! grep -Fq 'BLOCKED:solo-headroom-hypothesis-required' .agents/skills/devlyn:resolve/references/free-form-mode.md \
1359
1247
  || ! grep -Fq 'pair-evidence intent without an actionable solo-headroom hypothesis must halt' config/skills/devlyn:resolve/SKILL.md \
1360
- || ! grep -Fq 'pair-evidence intent without an actionable solo-headroom hypothesis must halt' .claude/skills/devlyn:resolve/SKILL.md \
1361
1248
  || ! grep -Fq 'pair-evidence intent without an actionable solo-headroom hypothesis must halt' .agents/skills/devlyn:resolve/SKILL.md \
1362
1249
  || ! grep -Fq 'preserve that literal hypothesis in `.devlyn/criteria.generated.md`' config/skills/devlyn:resolve/references/free-form-mode.md \
1363
- || ! grep -Fq 'preserve that literal hypothesis in `.devlyn/criteria.generated.md`' .claude/skills/devlyn:resolve/references/free-form-mode.md \
1364
1250
  || ! grep -Fq 'preserve that literal hypothesis in `.devlyn/criteria.generated.md`' .agents/skills/devlyn:resolve/references/free-form-mode.md \
1365
1251
  || ! grep -Fq 'emit the canonical `spec.solo_headroom_hypothesis` pair trigger reason' config/skills/devlyn:resolve/references/free-form-mode.md \
1366
- || ! grep -Fq 'emit the canonical `spec.solo_headroom_hypothesis` pair trigger reason' .claude/skills/devlyn:resolve/references/free-form-mode.md \
1367
1252
  || ! grep -Fq 'emit the canonical `spec.solo_headroom_hypothesis` pair trigger reason' .agents/skills/devlyn:resolve/references/free-form-mode.md \
1368
1253
  || ! grep -Fq '/devlyn:ideate` guidance for `BLOCKED:solo-headroom-hypothesis-required`' config/skills/devlyn:resolve/references/state-schema.md \
1369
- || ! grep -Fq '/devlyn:ideate` guidance for `BLOCKED:solo-headroom-hypothesis-required`' .claude/skills/devlyn:resolve/references/state-schema.md \
1370
1254
  || ! grep -Fq '/devlyn:ideate` guidance for `BLOCKED:solo-headroom-hypothesis-required`' .agents/skills/devlyn:resolve/references/state-schema.md \
1371
1255
  || ! grep -Fq '/devlyn:ideate` guidance after `BLOCKED:solo-headroom-hypothesis-required`' config/skills/devlyn:resolve/SKILL.md \
1372
- || ! grep -Fq '/devlyn:ideate` guidance after `BLOCKED:solo-headroom-hypothesis-required`' .claude/skills/devlyn:resolve/SKILL.md \
1373
1256
  || ! grep -Fq '/devlyn:ideate` guidance after `BLOCKED:solo-headroom-hypothesis-required`' .agents/skills/devlyn:resolve/SKILL.md \
1374
1257
  || ! grep -Fq 'Free-form goals that ask for benchmark evidence, pair-evidence, risk-probe' README.md \
1375
1258
  || ! grep -Fq '`/devlyn:resolve` stops with `BLOCKED:solo-headroom-hypothesis-required`' README.md \
@@ -1379,22 +1262,16 @@ else
1379
1262
  ok "resolve free-form mode blocks pair-evidence goals without actionable solo-headroom hypothesis"
1380
1263
  fi
1381
1264
  if ! grep -Fq 'unmeasured_pair_candidate_intent' config/skills/devlyn:resolve/references/free-form-mode.md \
1382
- || ! grep -Fq 'unmeasured_pair_candidate_intent' .claude/skills/devlyn:resolve/references/free-form-mode.md \
1383
1265
  || ! grep -Fq 'unmeasured_pair_candidate_intent' .agents/skills/devlyn:resolve/references/free-form-mode.md \
1384
1266
  || ! grep -Fq 'has_solo_ceiling_avoidance' config/skills/devlyn:resolve/references/free-form-mode.md \
1385
- || ! grep -Fq 'has_solo_ceiling_avoidance' .claude/skills/devlyn:resolve/references/free-form-mode.md \
1386
1267
  || ! grep -Fq 'has_solo_ceiling_avoidance' .agents/skills/devlyn:resolve/references/free-form-mode.md \
1387
1268
  || ! grep -Fq 'BLOCKED:solo-ceiling-avoidance-required' config/skills/devlyn:resolve/references/free-form-mode.md \
1388
- || ! grep -Fq 'BLOCKED:solo-ceiling-avoidance-required' .claude/skills/devlyn:resolve/references/free-form-mode.md \
1389
1269
  || ! grep -Fq 'BLOCKED:solo-ceiling-avoidance-required' .agents/skills/devlyn:resolve/references/free-form-mode.md \
1390
1270
  || ! grep -Fq 'unmeasured pair-candidate intent without solo ceiling avoidance must halt' config/skills/devlyn:resolve/SKILL.md \
1391
- || ! grep -Fq 'unmeasured pair-candidate intent without solo ceiling avoidance must halt' .claude/skills/devlyn:resolve/SKILL.md \
1392
1271
  || ! grep -Fq 'unmeasured pair-candidate intent without solo ceiling avoidance must halt' .agents/skills/devlyn:resolve/SKILL.md \
1393
1272
  || ! grep -Fq '/devlyn:ideate` guidance after `BLOCKED:solo-ceiling-avoidance-required`' config/skills/devlyn:resolve/SKILL.md \
1394
- || ! grep -Fq '/devlyn:ideate` guidance after `BLOCKED:solo-ceiling-avoidance-required`' .claude/skills/devlyn:resolve/SKILL.md \
1395
1273
  || ! grep -Fq '/devlyn:ideate` guidance after `BLOCKED:solo-ceiling-avoidance-required`' .agents/skills/devlyn:resolve/SKILL.md \
1396
1274
  || ! grep -Fq '/devlyn:ideate` guidance for `BLOCKED:solo-ceiling-avoidance-required`' config/skills/devlyn:resolve/references/state-schema.md \
1397
- || ! grep -Fq '/devlyn:ideate` guidance for `BLOCKED:solo-ceiling-avoidance-required`' .claude/skills/devlyn:resolve/references/state-schema.md \
1398
1275
  || ! grep -Fq '/devlyn:ideate` guidance for `BLOCKED:solo-ceiling-avoidance-required`' .agents/skills/devlyn:resolve/references/state-schema.md \
1399
1276
  || ! grep -Fq '`/devlyn:resolve` stops with `BLOCKED:solo-ceiling-avoidance-required`' README.md; then
1400
1277
  bad "resolve free-form mode must block new unmeasured pair candidates without solo ceiling avoidance"
@@ -1459,11 +1336,61 @@ if [ $verify_mech_missing -eq 0 ]; then
1459
1336
  ok "spec-verify VERIFY output routes into verify-merge-findings.py"
1460
1337
  fi
1461
1338
 
1339
+ section "Check 6i1: Verification provenance contract is wired"
1340
+ verification_provenance_missing=0
1341
+ for file in \
1342
+ config/skills/devlyn:resolve/SKILL.md \
1343
+ .agents/skills/devlyn:resolve/SKILL.md
1344
+ do
1345
+ if ! grep -Fq 'resolved BUILD_GATE engine through the fresh-worker route' "$file" \
1346
+ || ! grep -Fq 'BLOCKED:build-env-underprovisioned' "$file" \
1347
+ || ! grep -Fq '.devlyn/<primary-engine>-judge.stdout' "$file" \
1348
+ || ! grep -Fq '.devlyn/<other-engine>-judge.stdout' "$file" \
1349
+ || ! grep -Fq 'state-bound process-evidence manifest/raw stream' "$file"; then
1350
+ bad "$file — orchestrator provenance/capability/archive contract missing"
1351
+ verification_provenance_missing=1
1352
+ fi
1353
+ done
1354
+ for file in \
1355
+ config/skills/devlyn:resolve/references/phases/verify.md \
1356
+ .agents/skills/devlyn:resolve/references/phases/verify.md
1357
+ do
1358
+ if ! grep -Fq 'executable verification belongs exclusively to MECHANICAL' "$file" \
1359
+ || ! grep -Fq 'native read/search tools or non-mutating shell commands' "$file" \
1360
+ || ! grep -Fq 'JUDGE does not execute literal verification, lint, test, build, risk-probe, or' "$file" \
1361
+ || ! grep -Fq 'newly invented interaction commands.' "$file" \
1362
+ || ! grep -Fq '.devlyn/<primary-engine>-judge.stdout' "$file" \
1363
+ || ! grep -Fq '.devlyn/<other-engine>-judge.stdout' "$file" \
1364
+ || ! grep -Fq 'process-evidence manifest and raw stdout/stderr streams' "$file"; then
1365
+ bad "$file — JUDGE sealed-evidence contract missing"
1366
+ verification_provenance_missing=1
1367
+ fi
1368
+ if grep -Fq 'execute at least one combined adversarial check' "$file" \
1369
+ || grep -Fq 'Execute at most two targeted probes' "$file" \
1370
+ || grep -Fq "repo's CLI/API/test runner" "$file"; then
1371
+ bad "$file — stale JUDGE command-execution instruction remains"
1372
+ verification_provenance_missing=1
1373
+ fi
1374
+ done
1375
+ for file in \
1376
+ config/skills/devlyn:resolve/SKILL.md \
1377
+ .agents/skills/devlyn:resolve/SKILL.md \
1378
+ config/skills/devlyn:resolve/references/phases/verify.md \
1379
+ .agents/skills/devlyn:resolve/references/phases/verify.md
1380
+ do
1381
+ if grep -Eiq 'executes? no commands|no code-mutation or command-execution tools|do not receive command-execution tools' "$file"; then
1382
+ bad "$file — blanket JUDGE inspection prohibition remains"
1383
+ verification_provenance_missing=1
1384
+ fi
1385
+ done
1386
+ if [ $verification_provenance_missing -eq 0 ]; then
1387
+ ok "BUILD_GATE, sealed JUDGE inputs, canonical captures, and archive flow are wired"
1388
+ fi
1389
+
1462
1390
  section "Check 6j: VERIFY default pair dispatches concurrently"
1463
1391
  pair_trigger_order_missing=0
1464
1392
  for file in \
1465
1393
  config/skills/devlyn:resolve/SKILL.md \
1466
- .claude/skills/devlyn:resolve/SKILL.md \
1467
1394
  .agents/skills/devlyn:resolve/SKILL.md
1468
1395
  do
1469
1396
  if ! grep -Fq 'Verify dual-judge is default-when-available' "$file" \
@@ -1479,7 +1406,6 @@ do
1479
1406
  done
1480
1407
  for file in \
1481
1408
  config/skills/devlyn:resolve/references/phases/verify.md \
1482
- .claude/skills/devlyn:resolve/references/phases/verify.md \
1483
1409
  .agents/skills/devlyn:resolve/references/phases/verify.md
1484
1410
  do
1485
1411
  if ! grep -Fq 'Pair-mode (default when OTHER engine is available)' "$file" \
@@ -1495,7 +1421,6 @@ do
1495
1421
  done
1496
1422
  for file in \
1497
1423
  config/skills/devlyn:resolve/references/state-schema.md \
1498
- .claude/skills/devlyn:resolve/references/state-schema.md \
1499
1424
  .agents/skills/devlyn:resolve/references/state-schema.md
1500
1425
  do
1501
1426
  if ! grep -Fq '"version": "3.0"' "$file" \
@@ -1634,6 +1559,72 @@ fi
1634
1559
  # The wrapper owns the flag expansion; skill docs own requiring
1635
1560
  # CODEX_MONITORED_ISOLATED=1 for probe-derive and pair-JUDGE.
1636
1561
  # ---------------------------------------------------------------------------
1562
+ section "Check 10a0: Codex primary VERIFY budget is bounded and mirrored"
1563
+ primary_verify_missing=0
1564
+ primary_verify_route='CODEX_MONITORED_ISOLATED=1 CODEX_MONITORED_TIMEOUT_SEC=600 bash "$CODEX_MONITORED_PATH" -C "$PWD" -s read-only -c model_reasoning_effort=high "<primary prompt>" >.devlyn/codex-judge.stdout 2>.devlyn/codex-judge.stderr'
1565
+ for file in \
1566
+ config/skills/devlyn:resolve/SKILL.md \
1567
+ .agents/skills/devlyn:resolve/SKILL.md \
1568
+ config/skills/devlyn:resolve/references/phases/verify.md \
1569
+ .agents/skills/devlyn:resolve/references/phases/verify.md
1570
+ do
1571
+ if { ! grep -Fxq "$primary_verify_route" "$file" \
1572
+ && ! grep -Fq "\`$primary_verify_route\`" "$file"; } \
1573
+ || ! grep -Fq '.devlyn/verify.primary.timeout.json' "$file" \
1574
+ || ! grep -Fq 'pair-style `TIMEOUT`' "$file"; then
1575
+ bad "$file — Codex primary-JUDGE route/timeout authority missing"
1576
+ primary_verify_missing=1
1577
+ fi
1578
+ done
1579
+ for file in \
1580
+ config/skills/devlyn:resolve/references/phases/verify.md \
1581
+ .agents/skills/devlyn:resolve/references/phases/verify.md
1582
+ do
1583
+ for needle in \
1584
+ 'one broad pass over the' \
1585
+ 'It then makes one' \
1586
+ 'targeted interaction pass over the clauses the broad pass left unresolved.' \
1587
+ 'Before any third pass' \
1588
+ 'verdict-binding BLOCKED coverage finding'
1589
+ do
1590
+ if ! grep -Fq "$needle" "$file"; then
1591
+ bad "$file — bounded primary review instruction missing: $needle"
1592
+ primary_verify_missing=1
1593
+ fi
1594
+ done
1595
+ done
1596
+ for file in \
1597
+ config/skills/_shared/adapters/codex.md \
1598
+ .agents/skills/_shared/adapters/codex.md
1599
+ do
1600
+ for needle in \
1601
+ 'batch related reads' \
1602
+ 'sealed parity proves' \
1603
+ 'Open self-test bodies or MECHANICAL raw streams only for a'
1604
+ do
1605
+ if ! grep -Fq "$needle" "$file"; then
1606
+ bad "$file — Codex bounded retrieval tactic missing: $needle"
1607
+ primary_verify_missing=1
1608
+ fi
1609
+ done
1610
+ done
1611
+ for file in \
1612
+ config/skills/_shared/verify-merge-findings.py \
1613
+ .agents/skills/_shared/verify-merge-findings.py \
1614
+ config/skills/_shared/archive_run.py \
1615
+ .agents/skills/_shared/archive_run.py \
1616
+ config/skills/_shared/resolve-bootstrap.py \
1617
+ .agents/skills/_shared/resolve-bootstrap.py
1618
+ do
1619
+ if ! grep -Fq 'verify.primary.timeout.json' "$file"; then
1620
+ bad "$file — primary timeout deterministic/archive contract missing"
1621
+ primary_verify_missing=1
1622
+ fi
1623
+ done
1624
+ if [ $primary_verify_missing -eq 0 ]; then
1625
+ ok "Codex primary VERIFY is bounded, fail-closed, archived, and mirrored"
1626
+ fi
1627
+
1637
1628
  section "Check 10a: Bounded Codex calls use isolated wrapper mode"
1638
1629
  isolation_missing=0
1639
1630
  for needle in \
@@ -1695,12 +1686,18 @@ cat > "$tmp_iso/codex" <<'EOF'
1695
1686
  printf '%s\n' "$@" > "$CODEX_FAKE_ARGS_OUT"
1696
1687
  EOF
1697
1688
  chmod +x "$tmp_iso/codex"
1698
- CODEX_FAKE_ARGS_OUT="$tmp_iso/args.txt" \
1699
- CODEX_MONITORED_ISOLATED=1 \
1700
- CODEX_MONITORED_HEARTBEAT=999 \
1701
- CODEX_BIN="$tmp_iso/codex" \
1702
- bash config/skills/_shared/codex-monitored.sh -s read-only prompt \
1703
- >"$tmp_iso/stdout.txt" 2>"$tmp_iso/stderr.txt"
1689
+ (
1690
+ unset DEVLYN_INVOCATION_RUN_ID DEVLYN_INVOCATION_PHASE \
1691
+ DEVLYN_INVOCATION_ROUND DEVLYN_INVOCATION_WORKDIR \
1692
+ DEVLYN_INVOCATION_PROMPT_FILE DEVLYN_INVOCATION_SESSION_FILE \
1693
+ DEVLYN_INVOCATION_RECEIPT
1694
+ CODEX_FAKE_ARGS_OUT="$tmp_iso/args.txt" \
1695
+ CODEX_MONITORED_ISOLATED=1 \
1696
+ CODEX_MONITORED_HEARTBEAT=999 \
1697
+ CODEX_BIN="$tmp_iso/codex" \
1698
+ bash config/skills/_shared/codex-monitored.sh -s read-only prompt \
1699
+ >"$tmp_iso/stdout.txt" 2>"$tmp_iso/stderr.txt"
1700
+ )
1704
1701
  iso_exit=$?
1705
1702
  if [ $iso_exit -ne 0 ]; then
1706
1703
  bad "codex-monitored.sh isolated fake invocation exited $iso_exit"
@@ -1738,6 +1735,34 @@ else
1738
1735
  while IFS= read -r f; do bad "$f"; done <<< "$shared_path_offenders"
1739
1736
  fi
1740
1737
 
1738
+ section "Check 10a2: Bounded non-interactive calls discard inherited input"
1739
+ if python3 - <<'PY'
1740
+ import json, subprocess, sys
1741
+
1742
+ prompt = "sealed argv prompt\n두 번째 줄"
1743
+ poison = b"OPERATOR_HEREDOC_SHOULD_NOT_BECOME_USER_INPUT\n"
1744
+ child = (
1745
+ "import json,sys,time; "
1746
+ "print(json.dumps({'argv':sys.argv[1:],'stdin_hex':sys.stdin.buffer.read().hex()},ensure_ascii=False),flush=True); "
1747
+ "print('stderr preserved',file=sys.stderr,flush=True); "
1748
+ "time.sleep(float(sys.argv[2])); raise SystemExit(int(sys.argv[3]))"
1749
+ )
1750
+ for label, delay, code, expected_exit in (("normal", 0, 0, 0), ("nonzero", 0, 17, 17), ("timeout", 30, 0, 124)):
1751
+ args = [prompt, str(delay), str(code)]
1752
+ result = subprocess.run(
1753
+ [sys.executable, "config/skills/_shared/run-bounded.py", "1", "--", sys.executable, "-c", child, *args],
1754
+ input=poison, capture_output=True, timeout=9,
1755
+ )
1756
+ assert result.returncode == expected_exit, (label, result.returncode)
1757
+ assert json.loads(result.stdout) == {"argv": args, "stdin_hex": ""}, (label, result.stdout)
1758
+ assert result.stderr == b"stderr preserved\n", (label, result.stderr)
1759
+ PY
1760
+ then
1761
+ ok "run-bounded.py closes child stdin and preserves argv, streams, exits and timeout"
1762
+ else
1763
+ bad "run-bounded.py inherited-input/exit/timeout regression failed"
1764
+ fi
1765
+
1741
1766
  # ---------------------------------------------------------------------------
1742
1767
  # 10b. Shared routing docs must describe the current 2-skill surface.
1743
1768
  # A stale auto-resolve/preflight/ideate-CHALLENGE reference can misroute
@@ -2763,7 +2788,7 @@ if ! grep -Fq 'solo_claude beats bare' benchmark/auto-resolve/scripts/build-pair
2763
2788
  || ! grep -Fq 'wrong mapping' benchmark/auto-resolve/scripts/test-build-pair-eligible-manifest.sh; then
2764
2789
  offenders="${offenders}"$'\n'"build-pair-eligible-manifest.py must use arm-mapped clean scores for F9 and L1<=L0 promotion"
2765
2790
  fi
2766
- if [ -d benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/F16-cli-quote-tax-rules ] \
2791
+ if [ -f benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/F16-cli-quote-tax-rules/judge.json ] \
2767
2792
  && ! python3 benchmark/auto-resolve/scripts/full-pipeline-pair-gate.py \
2768
2793
  --run-id 20260510-f16-f23-f25-combined-proof \
2769
2794
  --pair-arm l2_risk_probes \
@@ -2774,7 +2799,7 @@ if [ -d benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/F16-c
2774
2799
  --out-md /tmp/devlyn-lint-f16-f23-f25-pair-gate.md >/dev/null 2>&1; then
2775
2800
  offenders="${offenders}"$'\n'"current local artifacts for 20260510-f16-f23-f25-combined-proof must re-gate as PASS"
2776
2801
  fi
2777
- if [ -d benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/F21-cli-scheduler-priority ] \
2802
+ if [ -f benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/F21-cli-scheduler-priority/judge.json ] \
2778
2803
  && ! python3 benchmark/auto-resolve/scripts/full-pipeline-pair-gate.py \
2779
2804
  --run-id 20260511-f21-current-riskprobes-v1 \
2780
2805
  --pair-arm l2_risk_probes \
@@ -3522,7 +3547,7 @@ if ! grep -Fq '"max_observed_pair_solo_wall_ratio": 2.2506234413965087' benchmar
3522
3547
  fi
3523
3548
  if make_temp_dir package_results /tmp/devlyn-lint-package-results.XXXXXX \
3524
3549
  && make_temp_dir package_audit /tmp/devlyn-lint-package-audit.XXXXXX \
3525
- && make_temp_file package_audit_stdout /tmp/devlyn-lint-package-audit.XXXXXX.out; then
3550
+ && make_temp_file package_audit_stdout /tmp/devlyn-lint-package-audit.out.XXXXXX; then
3526
3551
  cp -R benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof "$package_results/"
3527
3552
  cp -R benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1 "$package_results/"
3528
3553
  for rejected_run in \
@@ -3630,7 +3655,7 @@ PY
3630
3655
  else
3631
3656
  offenders="${offenders}"$'\n'"packaged pair evidence subset could not allocate temporary audit workspace"
3632
3657
  fi
3633
- if make_temp_file pack_json /tmp/devlyn-lint-pack.XXXXXX.json \
3658
+ if make_temp_file pack_json /tmp/devlyn-lint-pack.json.XXXXXX \
3634
3659
  && make_temp_dir pack_cache /tmp/devlyn-lint-pack-cache.XXXXXX; then
3635
3660
  if npm_config_cache="$pack_cache" npm pack --dry-run --json > "$pack_json" 2>/dev/null; then
3636
3661
  if ! node - "$pack_json" <<'NODE'
@@ -3658,10 +3683,14 @@ const required = [
3658
3683
  "benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/headroom-gate.json",
3659
3684
  "benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/full-pipeline-pair-gate.md",
3660
3685
  "benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/full-pipeline-pair-gate.json",
3686
+ "benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/F16-cli-quote-tax-rules/l2_risk_probes/result.json",
3687
+ "benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/F23-cli-fulfillment-wave/l2_risk_probes/result.json",
3688
+ "benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/F25-cli-cart-promotion-rules/l2_risk_probes/result.json",
3661
3689
  "benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/headroom-gate.md",
3662
3690
  "benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/headroom-gate.json",
3663
3691
  "benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/full-pipeline-pair-gate.md",
3664
3692
  "benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/full-pipeline-pair-gate.json",
3693
+ "benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/F21-cli-scheduler-priority/l2_risk_probes/result.json",
3665
3694
  "benchmark/auto-resolve/results/20260512-f2-medium-headroom/headroom-gate.json",
3666
3695
  "benchmark/auto-resolve/results/20260512-f31-seat-rebalance-headroom/headroom-gate.json",
3667
3696
  "benchmark/auto-resolve/results/20260512-f32-subscription-renewal-headroom/headroom-gate.json",
@@ -4085,7 +4114,7 @@ else
4085
4114
  else
4086
4115
  bad "idgen temp files unavailable; cannot verify determinism"
4087
4116
  fi
4088
- if make_temp_dir tmp_bad && make_temp_file idgen_nan_out /tmp/pair-plan-idgen-nan.XXXXXX.out; then
4117
+ if make_temp_dir tmp_bad && make_temp_file idgen_nan_out /tmp/pair-plan-idgen-nan.out.XXXXXX; then
4089
4118
  cp -R "$fixture/." "$tmp_bad/"
4090
4119
  printf '{"verification_commands": NaN}\n' > "$tmp_bad/expected.json"
4091
4120
  if python3 "$idgen" --fixture "$tmp_bad" --generated-at 2026-04-29T18:30:00Z >"$idgen_nan_out" 2>&1; then
@@ -4096,7 +4125,7 @@ else
4096
4125
  rm -rf "$tmp_bad" "$idgen_nan_out"
4097
4126
  fi
4098
4127
 
4099
- if make_temp_file bad_plan && make_temp_file plan_lint_nan_out /tmp/pair-plan-lint-nan.XXXXXX.out; then
4128
+ if make_temp_file bad_plan && make_temp_file plan_lint_nan_out /tmp/pair-plan-lint-nan.out.XXXXXX; then
4100
4129
  printf '{"schema_version": NaN}\n' > "$bad_plan"
4101
4130
  if python3 benchmark/auto-resolve/scripts/pair-plan-lint.py --plan "$bad_plan" --quiet >"$plan_lint_nan_out" 2>&1; then
4102
4131
  bad "pair-plan-lint.py accepted NaN in pair-plan.json"