devlyn-cli 3.2.0 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +2 -2
- package/CLAUDE.md +2 -2
- package/README.md +22 -113
- package/bin/devlyn.js +13 -225
- package/bin/instruction-templates.json +752 -1
- package/bin/instructions.js +101 -17
- package/config/skills/_shared/adapters/grok.md +1 -2
- package/config/skills/_shared/archive_run.py +15 -3
- package/config/skills/_shared/judge-role-evidence.py +21 -1
- package/config/skills/_shared/runtime-principles.md +1 -1
- package/config/skills/_shared/spec-verify-check.py +0 -653
- package/config/skills/_shared/state-phase-write.py +371 -30
- package/config/skills/_shared/task-complete.py +635 -143
- package/config/skills/_shared/terminal-claim-check.py +229 -4
- package/config/skills/_shared/verify-merge-findings.py +93 -2
- package/config/skills/devlyn:ideate/SKILL.md +3 -4
- package/config/skills/devlyn:ideate/references/elicitation.md +2 -35
- package/config/skills/devlyn:ideate/references/from-spec-mode.md +3 -18
- package/config/skills/devlyn:ideate/references/project-mode.md +1 -16
- package/config/skills/devlyn:ideate/references/spec-template.md +0 -2
- package/config/skills/devlyn:queue/SKILL.md +6 -4
- package/config/skills/devlyn:resolve/SKILL.md +16 -25
- package/config/skills/devlyn:resolve/references/free-form-mode.md +0 -14
- package/config/skills/devlyn:resolve/references/outer-loop.md +1 -1
- package/config/skills/devlyn:resolve/references/phases/build-gate.md +1 -1
- package/config/skills/devlyn:resolve/references/phases/cleanup.md +3 -3
- package/config/skills/devlyn:resolve/references/phases/implement.md +1 -1
- package/config/skills/devlyn:resolve/references/phases/probe-derive.md +1 -16
- package/config/skills/devlyn:resolve/references/phases/verify.md +4 -9
- package/config/skills/devlyn:resolve/references/state-schema.md +9 -7
- package/config/skills/devlyn:resolve/references/task-completion.md +46 -37
- package/{config/skills → optional-skills}/code-health-standards/SKILL.md +4 -13
- package/{config/skills → optional-skills}/code-review-standards/SKILL.md +4 -12
- package/{config/skills → optional-skills}/root-cause-analysis/SKILL.md +4 -12
- package/{config/skills → optional-skills}/ui-implementation-standards/SKILL.md +4 -14
- package/package.json +1 -57
- package/benchmark/auto-resolve/BENCHMARK-DESIGN.md +0 -289
- package/benchmark/auto-resolve/BENCHMARK-RESULTS.md +0 -341
- package/benchmark/auto-resolve/README.md +0 -696
- package/benchmark/auto-resolve/RUBRIC.md +0 -177
- package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/NOTES.md +0 -34
- package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/expected.json +0 -68
- package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/setup.sh +0 -4
- package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/spec.md +0 -44
- package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/task.ko.txt +0 -8
- package/benchmark/auto-resolve/fixtures/F1-cli-trivial-flag/task.txt +0 -8
- package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/NOTES.md +0 -68
- package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/expected.json +0 -60
- package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/setup.sh +0 -17
- package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/spec.md +0 -51
- package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/task.txt +0 -9
- package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/verifiers/invalid.js +0 -29
- package/benchmark/auto-resolve/fixtures/F10-persist-write-collision/verifiers/parallel.js +0 -50
- package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/NOTES.md +0 -75
- package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/expected.json +0 -52
- package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/setup.sh +0 -171
- package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/spec.md +0 -50
- package/benchmark/auto-resolve/fixtures/F11-batch-import-all-or-nothing/task.txt +0 -9
- package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/NOTES.md +0 -89
- package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/expected.json +0 -74
- package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/setup.sh +0 -251
- package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/spec.md +0 -57
- package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/task.txt +0 -13
- package/benchmark/auto-resolve/fixtures/F12-webhook-raw-body-signature/verifiers/replay-malformed-body.js +0 -64
- package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/NOTES.md +0 -104
- package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/expected.json +0 -46
- package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/setup.sh +0 -336
- package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/spec.md +0 -51
- package/benchmark/auto-resolve/fixtures/F15-frozen-diff-race-review/task.txt +0 -9
- package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/NOTES.md +0 -38
- package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/expected.json +0 -64
- package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/setup.sh +0 -32
- package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/spec.md +0 -63
- package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/task.txt +0 -7
- package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/verifiers/exact-success.js +0 -54
- package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/verifiers/no-hardcoded-pricing.js +0 -47
- package/benchmark/auto-resolve/fixtures/F16-cli-quote-tax-rules/verifiers/stock-error.js +0 -45
- package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/NOTES.md +0 -57
- package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/expected-pair-plan-registry.json +0 -170
- package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/expected.json +0 -84
- package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/metadata.json +0 -21
- package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/pair-plan.sample-fail.json +0 -214
- package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/pair-plan.sample-pass.json +0 -223
- package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/setup.sh +0 -5
- package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/spec.md +0 -55
- package/benchmark/auto-resolve/fixtures/F2-cli-medium-subcommand/task.txt +0 -14
- package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/NOTES.md +0 -39
- package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/expected.json +0 -62
- package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/setup.sh +0 -2
- package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/spec.md +0 -67
- package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/task.txt +0 -7
- package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/verifiers/error-order.js +0 -55
- package/benchmark/auto-resolve/fixtures/F21-cli-scheduler-priority/verifiers/priority-blocked.js +0 -48
- package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/NOTES.md +0 -35
- package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/expected.json +0 -56
- package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/setup.sh +0 -2
- package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/spec.md +0 -64
- package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/task.txt +0 -7
- package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/verifiers/conflicting-duplicate.js +0 -34
- package/benchmark/auto-resolve/fixtures/F22-cli-ledger-close/verifiers/idempotent-close.js +0 -41
- package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/NOTES.md +0 -39
- package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/expected.json +0 -56
- package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/setup.sh +0 -2
- package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/spec.md +0 -76
- package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/task.txt +0 -7
- package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/verifiers/priority-rollback.js +0 -64
- package/benchmark/auto-resolve/fixtures/F23-cli-fulfillment-wave/verifiers/single-warehouse-fefo.js +0 -66
- package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/NOTES.md +0 -40
- package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/expected.json +0 -66
- package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/setup.sh +0 -36
- package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/spec.md +0 -71
- package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/task.txt +0 -7
- package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/verifiers/catalog-source.js +0 -57
- package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/verifiers/exact-success.js +0 -63
- package/benchmark/auto-resolve/fixtures/F25-cli-cart-promotion-rules/verifiers/stock-error.js +0 -34
- package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/NOTES.md +0 -31
- package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/expected.json +0 -68
- package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/setup.sh +0 -17
- package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/spec.md +0 -68
- package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/task.txt +0 -7
- package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/verifiers/conflicting-duplicate.js +0 -29
- package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/verifiers/exact-payout.js +0 -58
- package/benchmark/auto-resolve/fixtures/F26-cli-payout-ledger-rules/verifiers/rules-source.js +0 -56
- package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/NOTES.md +0 -35
- package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/expected-pair-plan-registry.json +0 -162
- package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/expected.json +0 -67
- package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/metadata.json +0 -19
- package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/setup.sh +0 -4
- package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/spec.md +0 -55
- package/benchmark/auto-resolve/fixtures/F3-backend-contract-risk/task.txt +0 -9
- package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/NOTES.md +0 -34
- package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/expected.json +0 -57
- package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/setup.sh +0 -2
- package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/spec.md +0 -67
- package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/task.txt +0 -7
- package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/verifiers/duplicate-event-error.js +0 -35
- package/benchmark/auto-resolve/fixtures/F31-cli-seat-rebalance/verifiers/priority-transfer-rollback.js +0 -53
- package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/NOTES.md +0 -38
- package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/expected.json +0 -57
- package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/setup.sh +0 -2
- package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/spec.md +0 -70
- package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/task.txt +0 -3
- package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/verifiers/duplicate-renewal-error.js +0 -42
- package/benchmark/auto-resolve/fixtures/F32-cli-subscription-renewal/verifiers/priority-credit-rollback.js +0 -70
- package/benchmark/auto-resolve/fixtures/F4-web-browser-design/NOTES.md +0 -47
- package/benchmark/auto-resolve/fixtures/F4-web-browser-design/expected.json +0 -57
- package/benchmark/auto-resolve/fixtures/F4-web-browser-design/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/F4-web-browser-design/setup.sh +0 -6
- package/benchmark/auto-resolve/fixtures/F4-web-browser-design/spec.md +0 -48
- package/benchmark/auto-resolve/fixtures/F4-web-browser-design/task.txt +0 -9
- package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/NOTES.md +0 -45
- package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/expected.json +0 -65
- package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/setup.sh +0 -55
- package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/spec.md +0 -48
- package/benchmark/auto-resolve/fixtures/F5-fix-loop-red-green/task.txt +0 -7
- package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/NOTES.md +0 -43
- package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/expected.json +0 -77
- package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/setup.sh +0 -4
- package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/spec.md +0 -48
- package/benchmark/auto-resolve/fixtures/F6-dep-audit-native-module/task.txt +0 -10
- package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/NOTES.md +0 -57
- package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/expected.json +0 -76
- package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/setup.sh +0 -36
- package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/spec.md +0 -45
- package/benchmark/auto-resolve/fixtures/F7-out-of-scope-trap/task.txt +0 -7
- package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/NOTES.md +0 -53
- package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/expected.json +0 -63
- package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/setup.sh +0 -4
- package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/spec.md +0 -48
- package/benchmark/auto-resolve/fixtures/F8-known-limit-ambiguous/task.txt +0 -1
- package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/NOTES.md +0 -105
- package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/expected.json +0 -74
- package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/setup.sh +0 -28
- package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/spec.md +0 -59
- package/benchmark/auto-resolve/fixtures/F9-e2e-ideate-to-resolve/task.txt +0 -5
- package/benchmark/auto-resolve/fixtures/SCHEMA.md +0 -188
- package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/NOTES.md +0 -37
- package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/RETIRED.md +0 -13
- package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/expected.json +0 -56
- package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/setup.sh +0 -18
- package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/spec.md +0 -69
- package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/task.txt +0 -7
- package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/verifiers/exact-proration.js +0 -48
- package/benchmark/auto-resolve/fixtures/retired/F27-cli-subscription-proration/verifiers/rules-source-and-conflict.js +0 -79
- package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/NOTES.md +0 -54
- package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/RETIRED.md +0 -7
- package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/expected.json +0 -67
- package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/setup.sh +0 -2
- package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/spec.md +0 -67
- package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/task.txt +0 -5
- package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/verifiers/policy-precedence.js +0 -72
- package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/verifiers/validation-and-immutability.js +0 -43
- package/benchmark/auto-resolve/fixtures/retired/F28-cli-return-authorization/verifiers/validation-boundary.js +0 -116
- package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/NOTES.md +0 -35
- package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/RETIRED.md +0 -12
- package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/expected.json +0 -58
- package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/setup.sh +0 -2
- package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/spec.md +0 -73
- package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/task.txt +0 -17
- package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/verifiers/mixed-idempotent-settlement.js +0 -53
- package/benchmark/auto-resolve/fixtures/retired/F30-cli-credit-hold-settlement/verifiers/rejection-boundaries.js +0 -74
- package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/NOTES.md +0 -28
- package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/RETIRED.md +0 -15
- package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/expected.json +0 -57
- package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/setup.sh +0 -50
- package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/spec.md +0 -59
- package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/task.txt +0 -9
- package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/verifiers/ordered-settlement.js +0 -88
- package/benchmark/auto-resolve/fixtures/retired/F34-cli-settle-inflight/verifiers/reject-invalid.js +0 -45
- package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/NOTES.md +0 -30
- package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/RETIRED.md +0 -16
- package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/expected.json +0 -64
- package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/setup.sh +0 -21
- package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/spec.md +0 -58
- package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/task.txt +0 -9
- package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/verifiers/dup-op.js +0 -54
- package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/verifiers/priority-apply.js +0 -82
- package/benchmark/auto-resolve/fixtures/retired/F35-cli-apply-journal/verifiers/rollback.js +0 -77
- package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/NOTES.md +0 -99
- package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/RETIRED.md +0 -18
- package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/expected.json +0 -64
- package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/setup.sh +0 -4
- package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/spec.md +0 -61
- package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/task.txt +0 -9
- package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/verifiers/correctness-small.js +0 -135
- package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/verifiers/scale.js +0 -100
- package/benchmark/auto-resolve/fixtures/retired/F36-cli-session-admission/verifiers/validation.js +0 -75
- package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/NOTES.md +0 -93
- package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/RETIRED.md +0 -16
- package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/expected.json +0 -65
- package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/setup.sh +0 -18
- package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/spec.md +0 -66
- package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/task.txt +0 -9
- package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/verifiers/correctness-small.js +0 -84
- package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/verifiers/scale.js +0 -184
- package/benchmark/auto-resolve/fixtures/retired/F37-cli-rule-lookup/verifiers/validation.js +0 -74
- package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/NOTES.md +0 -60
- package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/RETIRED.md +0 -29
- package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/expected.json +0 -73
- package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/metadata.json +0 -10
- package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/setup.sh +0 -28
- package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/spec.md +0 -58
- package/benchmark/auto-resolve/fixtures/retired/F9-e2e-ideate-to-preflight/task.txt +0 -5
- package/benchmark/auto-resolve/fixtures/test-repo/README.md +0 -12
- package/benchmark/auto-resolve/fixtures/test-repo/bin/cli.js +0 -63
- package/benchmark/auto-resolve/fixtures/test-repo/package-lock.json +0 -823
- package/benchmark/auto-resolve/fixtures/test-repo/package.json +0 -22
- package/benchmark/auto-resolve/fixtures/test-repo/playwright.config.js +0 -17
- package/benchmark/auto-resolve/fixtures/test-repo/server/index.js +0 -37
- package/benchmark/auto-resolve/fixtures/test-repo/tests/cli.test.js +0 -25
- package/benchmark/auto-resolve/fixtures/test-repo/tests/server.test.js +0 -58
- package/benchmark/auto-resolve/fixtures/test-repo/web/index.html +0 -37
- package/benchmark/auto-resolve/results/20260507-f10-f11-tier1-full-pipeline/headroom-gate.json +0 -25
- package/benchmark/auto-resolve/results/20260507-f10-f11-tier1-full-pipeline/headroom-gate.md +0 -10
- package/benchmark/auto-resolve/results/20260508-f22-exact-error-headroom/headroom-gate.json +0 -18
- package/benchmark/auto-resolve/results/20260508-f22-exact-error-headroom/headroom-gate.md +0 -9
- package/benchmark/auto-resolve/results/20260508-f26-headroom/headroom-gate.json +0 -18
- package/benchmark/auto-resolve/results/20260508-f26-headroom/headroom-gate.md +0 -9
- package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/F16-cli-quote-tax-rules/l2_risk_probes/result.json +0 -28
- package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/F23-cli-fulfillment-wave/l2_risk_probes/result.json +0 -28
- package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/F25-cli-cart-promotion-rules/l2_risk_probes/result.json +0 -30
- package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/full-pipeline-pair-gate.json +0 -82
- package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/full-pipeline-pair-gate.md +0 -18
- package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/headroom-gate.json +0 -46
- package/benchmark/auto-resolve/results/20260510-f16-f23-f25-combined-proof/headroom-gate.md +0 -17
- package/benchmark/auto-resolve/results/20260511-f12-webhook-headroom/headroom-gate.json +0 -28
- package/benchmark/auto-resolve/results/20260511-f12-webhook-headroom/headroom-gate.md +0 -15
- package/benchmark/auto-resolve/results/20260511-f15-concurrency-headroom/headroom-gate.json +0 -28
- package/benchmark/auto-resolve/results/20260511-f15-concurrency-headroom/headroom-gate.md +0 -15
- package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/F21-cli-scheduler-priority/l2_risk_probes/result.json +0 -32
- package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/full-pipeline-pair-gate.json +0 -44
- package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/full-pipeline-pair-gate.md +0 -16
- package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/headroom-gate.json +0 -18
- package/benchmark/auto-resolve/results/20260511-f21-current-riskprobes-v1/headroom-gate.md +0 -9
- package/benchmark/auto-resolve/results/20260511-f3-http-error-headroom/headroom-gate.json +0 -28
- package/benchmark/auto-resolve/results/20260511-f3-http-error-headroom/headroom-gate.md +0 -15
- package/benchmark/auto-resolve/results/20260512-f2-medium-headroom/headroom-gate.json +0 -28
- package/benchmark/auto-resolve/results/20260512-f2-medium-headroom/headroom-gate.md +0 -15
- package/benchmark/auto-resolve/results/20260512-f31-seat-rebalance-headroom/headroom-gate.json +0 -28
- package/benchmark/auto-resolve/results/20260512-f31-seat-rebalance-headroom/headroom-gate.md +0 -15
- package/benchmark/auto-resolve/results/20260512-f32-subscription-renewal-headroom/headroom-gate.json +0 -28
- package/benchmark/auto-resolve/results/20260512-f32-subscription-renewal-headroom/headroom-gate.md +0 -15
- package/benchmark/auto-resolve/results/20260512-f4-web-headroom/headroom-gate.json +0 -28
- package/benchmark/auto-resolve/results/20260512-f4-web-headroom/headroom-gate.md +0 -15
- package/benchmark/auto-resolve/results/20260512-f5-fixloop-headroom/headroom-gate.json +0 -28
- package/benchmark/auto-resolve/results/20260512-f5-fixloop-headroom/headroom-gate.md +0 -15
- package/benchmark/auto-resolve/results/20260512-f6-checksum-headroom/headroom-gate.json +0 -28
- package/benchmark/auto-resolve/results/20260512-f6-checksum-headroom/headroom-gate.md +0 -15
- package/benchmark/auto-resolve/results/20260512-f7-scope-headroom/headroom-gate.json +0 -28
- package/benchmark/auto-resolve/results/20260512-f7-scope-headroom/headroom-gate.md +0 -15
- package/benchmark/auto-resolve/results/20260512-f9-e2e-headroom/headroom-gate.json +0 -28
- package/benchmark/auto-resolve/results/20260512-f9-e2e-headroom/headroom-gate.md +0 -15
- package/benchmark/auto-resolve/run-real-benchmark.md +0 -303
- package/benchmark/auto-resolve/scripts/audit-headroom-rejections.py +0 -441
- package/benchmark/auto-resolve/scripts/audit-pair-evidence.py +0 -1256
- package/benchmark/auto-resolve/scripts/build-pair-eligible-manifest.py +0 -306
- package/benchmark/auto-resolve/scripts/check-f9-artifacts.py +0 -268
- package/benchmark/auto-resolve/scripts/collect-swebench-predictions.py +0 -108
- package/benchmark/auto-resolve/scripts/compile-report.py +0 -493
- package/benchmark/auto-resolve/scripts/fetch-swebench-instances.py +0 -129
- package/benchmark/auto-resolve/scripts/frozen-verify-gate.py +0 -434
- package/benchmark/auto-resolve/scripts/full-pipeline-pair-gate.py +0 -612
- package/benchmark/auto-resolve/scripts/headroom-gate.py +0 -378
- package/benchmark/auto-resolve/scripts/iter-0033c-compare.py +0 -683
- package/benchmark/auto-resolve/scripts/iter-0033c-l1-summary.py +0 -97
- package/benchmark/auto-resolve/scripts/judge-opus-pass.sh +0 -542
- package/benchmark/auto-resolve/scripts/judge.sh +0 -565
- package/benchmark/auto-resolve/scripts/oracle-scope-tier-a.py +0 -256
- package/benchmark/auto-resolve/scripts/oracle-scope-tier-b.py +0 -287
- package/benchmark/auto-resolve/scripts/oracle-test-fidelity.py +0 -328
- package/benchmark/auto-resolve/scripts/pair-candidate-frontier.py +0 -469
- package/benchmark/auto-resolve/scripts/pair-plan-idgen.py +0 -401
- package/benchmark/auto-resolve/scripts/pair-plan-lint.py +0 -475
- package/benchmark/auto-resolve/scripts/pair-rejected-fixtures.sh +0 -103
- package/benchmark/auto-resolve/scripts/pair_evidence_contract.py +0 -270
- package/benchmark/auto-resolve/scripts/prepare-swebench-frozen-case.py +0 -273
- package/benchmark/auto-resolve/scripts/prepare-swebench-frozen-corpus.py +0 -148
- package/benchmark/auto-resolve/scripts/prepare-swebench-solver-worktree.py +0 -210
- package/benchmark/auto-resolve/scripts/recent-benchmark-summary.py +0 -232
- package/benchmark/auto-resolve/scripts/run-fixture.sh +0 -1024
- package/benchmark/auto-resolve/scripts/run-frozen-verify-pair.sh +0 -683
- package/benchmark/auto-resolve/scripts/run-full-pipeline-pair-candidate.sh +0 -458
- package/benchmark/auto-resolve/scripts/run-headroom-candidate.sh +0 -336
- package/benchmark/auto-resolve/scripts/run-iter-0033c.sh +0 -208
- package/benchmark/auto-resolve/scripts/run-suite.sh +0 -251
- package/benchmark/auto-resolve/scripts/run-swebench-frozen-corpus.sh +0 -310
- package/benchmark/auto-resolve/scripts/run-swebench-solver-batch.sh +0 -257
- package/benchmark/auto-resolve/scripts/ship-gate.py +0 -391
- package/benchmark/auto-resolve/scripts/solo-ceiling-avoidance.py +0 -53
- package/benchmark/auto-resolve/scripts/solo-headroom-hypothesis.py +0 -77
- package/benchmark/auto-resolve/scripts/swebench-frozen-matrix.py +0 -478
- package/benchmark/auto-resolve/scripts/test-audit-headroom-rejections.sh +0 -288
- package/benchmark/auto-resolve/scripts/test-audit-pair-evidence.sh +0 -1672
- package/benchmark/auto-resolve/scripts/test-benchmark-arg-parsing.sh +0 -1015
- package/benchmark/auto-resolve/scripts/test-build-pair-eligible-manifest.sh +0 -491
- package/benchmark/auto-resolve/scripts/test-check-f9-artifacts.sh +0 -91
- package/benchmark/auto-resolve/scripts/test-frozen-verify-gate.sh +0 -517
- package/benchmark/auto-resolve/scripts/test-full-pipeline-pair-gate.sh +0 -610
- package/benchmark/auto-resolve/scripts/test-headroom-gate.sh +0 -401
- package/benchmark/auto-resolve/scripts/test-iter-0033c-compare.sh +0 -525
- package/benchmark/auto-resolve/scripts/test-iter-0033c-l1-summary.sh +0 -254
- package/benchmark/auto-resolve/scripts/test-lint-fixtures.sh +0 -580
- package/benchmark/auto-resolve/scripts/test-pair-candidate-frontier.sh +0 -591
- package/benchmark/auto-resolve/scripts/test-run-full-pipeline-pair-candidate.sh +0 -497
- package/benchmark/auto-resolve/scripts/test-run-headroom-candidate.sh +0 -401
- package/benchmark/auto-resolve/scripts/test-run-swebench-solver-batch.sh +0 -111
- package/benchmark/auto-resolve/scripts/test-ship-gate.sh +0 -1189
- package/benchmark/auto-resolve/scripts/test-swebench-frozen-case.sh +0 -1221
- package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/NOTES.md +0 -28
- package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/expected.json +0 -63
- package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/metadata.json +0 -10
- package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/setup.sh +0 -3
- package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/spec.md +0 -47
- package/benchmark/auto-resolve/shadow-fixtures/S1-cli-lang-flag/task.txt +0 -1
- package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/NOTES.md +0 -34
- package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/expected.json +0 -53
- package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/metadata.json +0 -10
- package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/setup.sh +0 -3
- package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/spec.md +0 -50
- package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/task.txt +0 -1
- package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/verifiers/duplicate-order-error.js +0 -27
- package/benchmark/auto-resolve/shadow-fixtures/S2-cli-inventory-reservation/verifiers/priority-stock-reservation.js +0 -44
- package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/NOTES.md +0 -34
- package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/expected.json +0 -55
- package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/metadata.json +0 -10
- package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/setup.sh +0 -3
- package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/spec.md +0 -52
- package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/task.txt +0 -1
- package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/verifiers/duplicate-ticket-error.js +0 -29
- package/benchmark/auto-resolve/shadow-fixtures/S3-cli-ticket-assignment/verifiers/priority-agent-assignment.js +0 -48
- package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/NOTES.md +0 -34
- package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/expected.json +0 -55
- package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/metadata.json +0 -10
- package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/setup.sh +0 -3
- package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/spec.md +0 -55
- package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/task.txt +0 -1
- package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/verifiers/duplicate-return-error.js +0 -43
- package/benchmark/auto-resolve/shadow-fixtures/S4-cli-return-routing/verifiers/priority-return-routing.js +0 -70
- package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/NOTES.md +0 -37
- package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/expected.json +0 -54
- package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/metadata.json +0 -10
- package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/setup.sh +0 -3
- package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/spec.md +0 -59
- package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/task.txt +0 -1
- package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/verifiers/credit-ledger-priority.js +0 -98
- package/benchmark/auto-resolve/shadow-fixtures/S5-cli-credit-grant-ledger/verifiers/duplicate-charge-error.js +0 -38
- package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/NOTES.md +0 -36
- package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/expected.json +0 -56
- package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/metadata.json +0 -10
- package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/setup.sh +0 -3
- package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/spec.md +0 -59
- package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/task.txt +0 -1
- package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/verifiers/duplicate-refund-error.js +0 -41
- package/benchmark/auto-resolve/shadow-fixtures/S6-cli-refund-window-ledger/verifiers/priority-refund-ledger.js +0 -65
- package/config/skills/_shared/pair-plan-schema.md +0 -298
- package/scripts/lint-fixtures.sh +0 -352
- package/scripts/lint-shadow-fixtures.sh +0 -58
- package/scripts/lint-skills.sh +0 -4265
- package/scripts/test-owner-phases.py +0 -193
|
@@ -1,1024 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# run-fixture.sh — run ONE fixture, ONE arm, end-to-end. Self-contained.
|
|
3
|
-
#
|
|
4
|
-
# Prepares a fresh work dir, applies setup, invokes the arm via `claude -p`
|
|
5
|
-
# subprocess (isolated session), then captures artifacts + runs verification.
|
|
6
|
-
#
|
|
7
|
-
# Usage:
|
|
8
|
-
# run-fixture.sh --fixture <FID> --arm <variant|solo_claude|bare|l2_gated|l2_risk_probes|l2_forced> --run-id <ID>
|
|
9
|
-
# run-fixture.sh --fixture <FID> --arm <variant|solo_claude|bare|l2_gated|l2_risk_probes|l2_forced> --run-id <ID> --dry-run
|
|
10
|
-
#
|
|
11
|
-
# Outputs to benchmark/auto-resolve/results/<run-id>/<fixture>/<arm>/:
|
|
12
|
-
# input.md, transcript.txt, diff.patch, changed-files.txt, verify.json,
|
|
13
|
-
# timing.json, result.json, setup.log (if setup ran)
|
|
14
|
-
|
|
15
|
-
set -euo pipefail
|
|
16
|
-
|
|
17
|
-
usage() {
|
|
18
|
-
echo "usage: $0 --fixture <FID> --arm <variant|solo_claude|bare|l2_gated|l2_risk_probes|l2_forced> --run-id <ID> [--resolve-skill new] [--engines-config '<json>'] [--dry-run]"
|
|
19
|
-
exit 1
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
require_value() {
|
|
23
|
-
local flag="$1"
|
|
24
|
-
local value="${2:-}"
|
|
25
|
-
if [ -z "$value" ] || [[ "$value" == --* ]]; then
|
|
26
|
-
echo "$flag requires a value" >&2
|
|
27
|
-
exit 1
|
|
28
|
-
fi
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
kill_worktree_processes() {
|
|
32
|
-
local work_dir="$1"
|
|
33
|
-
local signal="$2"
|
|
34
|
-
local physical_work_dir current_pgid
|
|
35
|
-
physical_work_dir="$(cd "$work_dir" 2>/dev/null && pwd -P || printf '%s' "$work_dir")"
|
|
36
|
-
current_pgid="$(ps -o pgid= -p "$$" | tr -d ' ')"
|
|
37
|
-
ps -axo pid=,pgid=,command= \
|
|
38
|
-
| awk -v p1="$work_dir" -v p2="$physical_work_dir" -v self="$$" -v current_pgid="$current_pgid" '
|
|
39
|
-
$1 != self && $2 != current_pgid && (index($0, p1) || index($0, p2)) { print $2 }
|
|
40
|
-
' \
|
|
41
|
-
| sort -u \
|
|
42
|
-
| while IFS= read -r pgid; do
|
|
43
|
-
[ -n "$pgid" ] || continue
|
|
44
|
-
kill "-$signal" -- "-$pgid" 2>/dev/null || true
|
|
45
|
-
done
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
FIXTURE=""; ARM=""; RUN_ID=""; DRY_RUN=0
|
|
49
|
-
RESOLVE_SKILL="new"
|
|
50
|
-
ENGINES_CONFIG=""
|
|
51
|
-
while [ $# -gt 0 ]; do
|
|
52
|
-
case "$1" in
|
|
53
|
-
--fixture) require_value "$1" "${2:-}"; FIXTURE="$2"; shift 2;;
|
|
54
|
-
--arm) require_value "$1" "${2:-}"; ARM="$2"; shift 2;;
|
|
55
|
-
--run-id) require_value "$1" "${2:-}"; RUN_ID="$2"; shift 2;;
|
|
56
|
-
--resolve-skill) require_value "$1" "${2:-}"; RESOLVE_SKILL="$2"; shift 2;;
|
|
57
|
-
--engines-config) require_value "$1" "${2:-}"; ENGINES_CONFIG="$2"; shift 2;;
|
|
58
|
-
--dry-run) DRY_RUN=1; shift;;
|
|
59
|
-
*) usage;;
|
|
60
|
-
esac
|
|
61
|
-
done
|
|
62
|
-
[ -n "$FIXTURE" ] && [ -n "$ARM" ] && [ -n "$RUN_ID" ] || usage
|
|
63
|
-
|
|
64
|
-
# iter-0038: --engines-config stages a machine-config role pin
|
|
65
|
-
# (.devlyn/engines.json) into the arm worktree so engine COMBINATIONS are
|
|
66
|
-
# runnable as variant-class arms without new hardcoded arm names. Existing
|
|
67
|
-
# arm launch commands are untouched when the flag is absent. Fail fast on
|
|
68
|
-
# malformed JSON, and refuse bare (no skills — the config would be dead
|
|
69
|
-
# weight that silently mis-labels the arm as configured).
|
|
70
|
-
if [ -n "$ENGINES_CONFIG" ]; then
|
|
71
|
-
if [ "$ARM" = "bare" ]; then
|
|
72
|
-
echo "--engines-config is invalid for the bare arm (no skills consume it)" >&2
|
|
73
|
-
exit 1
|
|
74
|
-
fi
|
|
75
|
-
if ! printf '%s' "$ENGINES_CONFIG" | python3 -c 'import json,sys; json.load(sys.stdin)' 2>/dev/null; then
|
|
76
|
-
echo "--engines-config is not valid JSON" >&2
|
|
77
|
-
exit 1
|
|
78
|
-
fi
|
|
79
|
-
fi
|
|
80
|
-
# iter-0019/0037: 3 smoke arms — variant (L2: Claude orchestrator + risk-probes pair path),
|
|
81
|
-
# solo_claude (L1: Claude orchestrator, codex blocked by shim+wrapper enforcement),
|
|
82
|
-
# bare (L0: direct claude -p, no skill, no codex).
|
|
83
|
-
# iter-0033c (Codex R0-infra adoption, 2026-05-02): two L2 diagnostic arms for /devlyn:resolve —
|
|
84
|
-
# l2_gated (--engine claude, no --pair-verify; pair fires only on natural triggers),
|
|
85
|
-
# l2_risk_probes (--engine claude --risk-probes; pair converts visible Verification bullets to executable probes before IMPLEMENT),
|
|
86
|
-
# l2_forced (--engine claude --pair-verify; retired because it leaks pair-awareness before IMPLEMENT).
|
|
87
|
-
[ "$ARM" = "variant" ] || [ "$ARM" = "solo_claude" ] || [ "$ARM" = "bare" ] \
|
|
88
|
-
|| [ "$ARM" = "l2_gated" ] || [ "$ARM" = "l2_risk_probes" ] || [ "$ARM" = "l2_forced" ] || \
|
|
89
|
-
{ echo "arm must be variant|solo_claude|bare|l2_gated|l2_risk_probes|l2_forced"; exit 1; }
|
|
90
|
-
# iter-0033c (Codex R0-infra Q2): l2_* arms require NEW skill surface (only NEW
|
|
91
|
-
# `/devlyn:resolve` honors --pair-verify; OLD `/devlyn:auto-resolve` would silently
|
|
92
|
-
# ignore the flag and produce mis-attributed L2 numbers).
|
|
93
|
-
if { [ "$ARM" = "l2_gated" ] || [ "$ARM" = "l2_risk_probes" ] || [ "$ARM" = "l2_forced" ]; } && [ "$RESOLVE_SKILL" != "new" ]; then
|
|
94
|
-
echo "l2_* arms require --resolve-skill new (got '$RESOLVE_SKILL')"; exit 1
|
|
95
|
-
fi
|
|
96
|
-
if [ "$ARM" = "l2_forced" ]; then
|
|
97
|
-
echo "l2_forced is retired: it puts --pair-verify in the initial prompt, so IMPLEMENT can become pair-aware before the diff is frozen. Use scripts/run-frozen-verify-pair.sh for leak-free VERIFY-pair measurement." >&2
|
|
98
|
-
exit 1
|
|
99
|
-
fi
|
|
100
|
-
# iter-0034 Phase 4 cutover (2026-05-03): OLD `/devlyn:auto-resolve` was
|
|
101
|
-
# deleted. Only `new` (= /devlyn:resolve --spec) is supported. The flag stays
|
|
102
|
-
# an accepted no-op so historical runners (run-iter-0033c.sh:137) keep working
|
|
103
|
-
# unchanged. `old` is hard-errored — silently downgrading to `new` would
|
|
104
|
-
# produce mis-attributed results in any pre-cutover replay attempt.
|
|
105
|
-
if [ "$RESOLVE_SKILL" = "old" ]; then
|
|
106
|
-
echo "--resolve-skill old is no longer supported: /devlyn:auto-resolve was deleted in the iter-0034 Phase 4 cutover. Use --resolve-skill new (default) or omit the flag." >&2
|
|
107
|
-
exit 1
|
|
108
|
-
fi
|
|
109
|
-
[ "$RESOLVE_SKILL" = "new" ] || \
|
|
110
|
-
{ echo "--resolve-skill must be 'new' (got '$RESOLVE_SKILL')"; exit 1; }
|
|
111
|
-
|
|
112
|
-
BENCH_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
113
|
-
REPO_ROOT="$(cd "$BENCH_ROOT/../.." && pwd)"
|
|
114
|
-
|
|
115
|
-
FIX_DIR=""
|
|
116
|
-
for candidate in "$BENCH_ROOT/fixtures/$FIXTURE" "$BENCH_ROOT/shadow-fixtures/$FIXTURE"; do
|
|
117
|
-
if [ -d "$candidate" ]; then FIX_DIR="$candidate"; break; fi
|
|
118
|
-
done
|
|
119
|
-
[ -n "$FIX_DIR" ] || { echo "fixture not found in fixtures/ or shadow-fixtures/: $FIXTURE"; exit 1; }
|
|
120
|
-
|
|
121
|
-
META="$FIX_DIR/metadata.json"
|
|
122
|
-
EXPECTED="$FIX_DIR/expected.json"
|
|
123
|
-
SPEC="$FIX_DIR/spec.md"
|
|
124
|
-
TASK="$FIX_DIR/task.txt"
|
|
125
|
-
SETUP="$FIX_DIR/setup.sh"
|
|
126
|
-
for f in "$META" "$EXPECTED" "$SPEC" "$TASK"; do
|
|
127
|
-
[ -f "$f" ] || { echo "fixture missing required file: $f (see SCHEMA.md)"; exit 1; }
|
|
128
|
-
done
|
|
129
|
-
|
|
130
|
-
TIMEOUT=$(python3 - "$META" "$BENCH_ROOT/scripts" <<'PY'
|
|
131
|
-
import pathlib
|
|
132
|
-
import sys
|
|
133
|
-
|
|
134
|
-
sys.path.insert(0, sys.argv[2])
|
|
135
|
-
from pair_evidence_contract import loads_strict_json_object
|
|
136
|
-
|
|
137
|
-
metadata = loads_strict_json_object(pathlib.Path(sys.argv[1]).read_text())
|
|
138
|
-
timeout = metadata.get("timeout_seconds")
|
|
139
|
-
if not isinstance(timeout, int) or isinstance(timeout, bool) or timeout <= 0:
|
|
140
|
-
raise SystemExit("metadata timeout_seconds must be a positive integer")
|
|
141
|
-
print(timeout)
|
|
142
|
-
PY
|
|
143
|
-
)
|
|
144
|
-
if [ "$ARM" = "variant" ] || [ "$ARM" = "l2_risk_probes" ]; then
|
|
145
|
-
# This arm adds a bounded Codex probe-derive phase before IMPLEMENT and a
|
|
146
|
-
# bounded Codex pair-JUDGE during VERIFY. The full-pipeline gate still
|
|
147
|
-
# enforces wall-time efficiency by pair/solo ratio; this budget prevents a
|
|
148
|
-
# false timeout before the mandatory second judge can emit its contract line.
|
|
149
|
-
TIMEOUT=$((TIMEOUT + 600))
|
|
150
|
-
fi
|
|
151
|
-
|
|
152
|
-
RESULT_DIR="$BENCH_ROOT/results/$RUN_ID/$FIXTURE/$ARM"
|
|
153
|
-
mkdir -p "$RESULT_DIR"
|
|
154
|
-
|
|
155
|
-
# Fresh copy of test-repo — order matters. We copy arm-env files (skills,
|
|
156
|
-
# CLAUDE.md) BEFORE the baseline commit so they do NOT appear in the diff
|
|
157
|
-
# the arm produces. That keeps diff.patch focused on the arm's actual code
|
|
158
|
-
# changes, so forbidden-pattern scans and judge rubrics see only real work.
|
|
159
|
-
WORK_DIR="/tmp/bench-${RUN_ID}-${FIXTURE}-${ARM}"
|
|
160
|
-
rm -rf "$WORK_DIR"
|
|
161
|
-
cp -R "$BENCH_ROOT/fixtures/test-repo" "$WORK_DIR"
|
|
162
|
-
|
|
163
|
-
# All skill-driven arms (variant / solo_claude / l2_gated / l2_risk_probes /
|
|
164
|
-
# l2_forced) get devlyn skills + project CLAUDE.md pre-baseline + codex shim
|
|
165
|
-
# + monitored wrapper. Bare gets nothing (no skill, no shim, no env).
|
|
166
|
-
#
|
|
167
|
-
# iter-0019: solo_claude (L1) shares variant-arm staging because the L1 arm
|
|
168
|
-
# runs the same orchestrator on the same skills — only difference is codex
|
|
169
|
-
# is blocked. Shim catches PATH resolution; wrapper catches direct-path
|
|
170
|
-
# invocations.
|
|
171
|
-
# iter-0033c/0037 (Codex R0-infra Q6 + risk probes): pair arms share variant
|
|
172
|
-
# staging (codex unblocked, shim+wrapper routing). The smoke `variant` arm now
|
|
173
|
-
# follows the current measured risk-probes path rather than an older
|
|
174
|
-
# auto-engine implement route.
|
|
175
|
-
if [ "$ARM" = "variant" ] || [ "$ARM" = "solo_claude" ] \
|
|
176
|
-
|| [ "$ARM" = "l2_gated" ] || [ "$ARM" = "l2_risk_probes" ] || [ "$ARM" = "l2_forced" ]; then
|
|
177
|
-
mkdir -p "$WORK_DIR/.claude"
|
|
178
|
-
if [ -d "$REPO_ROOT/.claude/skills" ]; then
|
|
179
|
-
cp -R "$REPO_ROOT/.claude/skills" "$WORK_DIR/.claude/skills"
|
|
180
|
-
else
|
|
181
|
-
echo "warning: $REPO_ROOT/.claude/skills missing — $ARM may lack project skills" >&2
|
|
182
|
-
fi
|
|
183
|
-
if [ -f "$REPO_ROOT/CLAUDE.md" ]; then
|
|
184
|
-
cp "$REPO_ROOT/CLAUDE.md" "$WORK_DIR/CLAUDE.md"
|
|
185
|
-
fi
|
|
186
|
-
# iter-0038: stage the engine role pin (validated above) pre-baseline.
|
|
187
|
-
# test-repo/.gitignore covers .devlyn, so it never enters scaffold commits
|
|
188
|
-
# or arm diffs. A verbatim copy lands in RESULT_DIR as run evidence.
|
|
189
|
-
if [ -n "$ENGINES_CONFIG" ]; then
|
|
190
|
-
mkdir -p "$WORK_DIR/.devlyn"
|
|
191
|
-
printf '%s\n' "$ENGINES_CONFIG" > "$WORK_DIR/.devlyn/engines.json"
|
|
192
|
-
printf '%s\n' "$ENGINES_CONFIG" > "$RESULT_DIR/engines-config.json"
|
|
193
|
-
fi
|
|
194
|
-
# Stage the codex PATH shim. Required for both variant (route to monitored
|
|
195
|
-
# wrapper) and solo_claude (CODEX_BLOCKED enforcement at PATH layer).
|
|
196
|
-
if command -v codex >/dev/null 2>&1; then
|
|
197
|
-
CODEX_REAL_BIN="$(command -v codex)"
|
|
198
|
-
SHIM_SRC="$REPO_ROOT/scripts/codex-shim/codex"
|
|
199
|
-
WRAPPER_SRC="$REPO_ROOT/config/skills/_shared/codex-monitored.sh"
|
|
200
|
-
if [ ! -x "$SHIM_SRC" ] || [ ! -r "$WRAPPER_SRC" ]; then
|
|
201
|
-
echo "fatal: iter-0009 shim/wrapper missing at $SHIM_SRC / $WRAPPER_SRC" >&2
|
|
202
|
-
exit 1
|
|
203
|
-
fi
|
|
204
|
-
mkdir -p "$WORK_DIR/.devlyn-bin"
|
|
205
|
-
cp "$SHIM_SRC" "$WORK_DIR/.devlyn-bin/codex"
|
|
206
|
-
chmod +x "$WORK_DIR/.devlyn-bin/codex"
|
|
207
|
-
CODEX_MONITORED_PATH="$WORK_DIR/.claude/skills/_shared/codex-monitored.sh"
|
|
208
|
-
[ -r "$CODEX_MONITORED_PATH" ] || {
|
|
209
|
-
echo "fatal: codex-monitored.sh not present in staged skills at $CODEX_MONITORED_PATH" >&2
|
|
210
|
-
exit 1
|
|
211
|
-
}
|
|
212
|
-
export CODEX_REAL_BIN CODEX_MONITORED_PATH
|
|
213
|
-
SNAPSHOT_PATH=$(grep -m1 '^export PATH=' \
|
|
214
|
-
"$HOME/.claude/shell-snapshots/snapshot-zsh-"*.sh 2>/dev/null \
|
|
215
|
-
| head -1 | sed 's/^[^=]*=//' | tr -d '"' || true)
|
|
216
|
-
[ -n "$SNAPSHOT_PATH" ] || SNAPSHOT_PATH="$PATH"
|
|
217
|
-
INJECTED_PATH="$WORK_DIR/.devlyn-bin:$SNAPSHOT_PATH"
|
|
218
|
-
# iter-0019: arm-specific env. variant gets the codex routing pair;
|
|
219
|
-
# solo_claude gets CODEX_BLOCKED=1 (shim + wrapper both refuse).
|
|
220
|
-
# iter-0019.5 (Codex R1, 2026-04-28): when ARM=solo_claude, OMIT
|
|
221
|
-
# CODEX_REAL_BIN + CODEX_MONITORED_PATH from the env block. Reason: the
|
|
222
|
-
# absolute path to the real codex binary in CODEX_REAL_BIN is itself
|
|
223
|
-
# the bypass weapon — the orchestrator could `Bash("$CODEX_REAL_BIN
|
|
224
|
-
# exec ...")` and reach real codex, defeating both shim (PATH lookup
|
|
225
|
-
# bypassed) and wrapper (codex-monitored.sh not invoked). With the
|
|
226
|
-
# var absent: shim's BLOCKED check fires before it needs CODEX_REAL_BIN
|
|
227
|
-
# so removing it doesn't break the shim path; if CODEX_BLOCKED is
|
|
228
|
-
# somehow unset later, the shim now FAILS CLOSED (no real binary to
|
|
229
|
-
# delegate to) rather than silently delegating. The earlier "diagnostic
|
|
230
|
-
# visibility" justification was inverted — it handed the orchestrator
|
|
231
|
-
# the bypass weapon. Across iter-0019 paid 5-fixture run the bypass
|
|
232
|
-
# was OPEN but never exercised; this closes the surface preemptively
|
|
233
|
-
# before iter-0020's 9-fixture L0/L1/L2 run.
|
|
234
|
-
# iter-0033c/0037 (Codex R0-infra Q5 + risk probes): l2_* arms are codex-UNBLOCKED
|
|
235
|
-
# (codex must be reachable for VERIFY pair-JUDGE). They take the variant
|
|
236
|
-
# path: ARM_CODEX_BLOCKED=0 → python writer omits CODEX_BLOCKED from env
|
|
237
|
-
# entirely (the shim refuses on any non-empty value, so 0 ≠ unset).
|
|
238
|
-
if [ "$ARM" = "solo_claude" ]; then
|
|
239
|
-
ARM_CODEX_BLOCKED=1
|
|
240
|
-
else
|
|
241
|
-
ARM_CODEX_BLOCKED=0
|
|
242
|
-
fi
|
|
243
|
-
python3 - "$WORK_DIR/.claude/settings.json" \
|
|
244
|
-
"$INJECTED_PATH" "$CODEX_REAL_BIN" "$CODEX_MONITORED_PATH" "$ARM_CODEX_BLOCKED" "$ARM" <<'PY'
|
|
245
|
-
import json, sys
|
|
246
|
-
out_path, path_val, real_bin, monitored, codex_blocked, arm = sys.argv[1:7]
|
|
247
|
-
env = {
|
|
248
|
-
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1",
|
|
249
|
-
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
|
|
250
|
-
"DISABLE_AUTOUPDATER": "1",
|
|
251
|
-
"PATH": path_val,
|
|
252
|
-
}
|
|
253
|
-
if codex_blocked == "1":
|
|
254
|
-
# iter-0019.5: solo_claude (L1 arm) — codex blocked at binary layer.
|
|
255
|
-
# Do NOT export CODEX_REAL_BIN / CODEX_MONITORED_PATH to the
|
|
256
|
-
# orchestrator subshell; those vars become bypass weapons under any
|
|
257
|
-
# CODEX_BLOCKED enforcement gap.
|
|
258
|
-
env["CODEX_BLOCKED"] = "1"
|
|
259
|
-
else:
|
|
260
|
-
# variant / pair arms — codex routes through wrapper for risk-probe
|
|
261
|
-
# derivation and VERIFY pair-JUDGE; both vars are required by the
|
|
262
|
-
# shim/wrapper handshake.
|
|
263
|
-
env["CODEX_REAL_BIN"] = real_bin
|
|
264
|
-
env["CODEX_MONITORED_PATH"] = monitored
|
|
265
|
-
if arm in ("variant", "l2_risk_probes"):
|
|
266
|
-
# Risk-probe derivation is a bounded contract-conversion step. A long
|
|
267
|
-
# Codex run is a harness failure, not useful extra quality signal.
|
|
268
|
-
env["CODEX_MONITORED_TIMEOUT_SEC"] = "300"
|
|
269
|
-
data = {"env": env}
|
|
270
|
-
with open(out_path, "w") as f:
|
|
271
|
-
json.dump(data, f, indent=2)
|
|
272
|
-
f.write("\n")
|
|
273
|
-
PY
|
|
274
|
-
else
|
|
275
|
-
echo "warning: codex not on PATH — $ARM cannot exercise iter-0009 wrapper / iter-0019 BLOCKED enforcement" >&2
|
|
276
|
-
CODEX_REAL_BIN=""
|
|
277
|
-
CODEX_MONITORED_PATH=""
|
|
278
|
-
fi
|
|
279
|
-
fi
|
|
280
|
-
|
|
281
|
-
(cd "$WORK_DIR" \
|
|
282
|
-
&& git init -q \
|
|
283
|
-
&& git add -A \
|
|
284
|
-
&& git -c user.email=b@b -c user.name=b commit -q -m baseline) \
|
|
285
|
-
|| { echo "baseline git init failed"; exit 1; }
|
|
286
|
-
|
|
287
|
-
# Native security-review Skill expects `refs/remotes/origin/HEAD` to identify
|
|
288
|
-
# the diff surface. Fresh `git init` has no remote, which made a prior F8 run
|
|
289
|
-
# spend ~56 minutes inside CRITIC recovering this manually. Configure a
|
|
290
|
-
# synthetic origin pointing at the work dir itself (no network I/O) and
|
|
291
|
-
# wire origin/HEAD → origin/<current-branch> so security-review resolves
|
|
292
|
-
# immediately.
|
|
293
|
-
(
|
|
294
|
-
cd "$WORK_DIR"
|
|
295
|
-
git remote add origin "$WORK_DIR" 2>/dev/null || true
|
|
296
|
-
BRANCH=$(git branch --show-current 2>/dev/null || echo master)
|
|
297
|
-
git update-ref "refs/remotes/origin/$BRANCH" HEAD 2>/dev/null || true
|
|
298
|
-
git symbolic-ref refs/remotes/origin/HEAD "refs/remotes/origin/$BRANCH" 2>/dev/null || true
|
|
299
|
-
) >/dev/null 2>&1 || true
|
|
300
|
-
|
|
301
|
-
# Fixture-specific setup (applied post-baseline so the diff shows fixture
|
|
302
|
-
# framing as part of the arm's environment, not its work product). Commit
|
|
303
|
-
# failures here break arm-only diff isolation, so fail loudly.
|
|
304
|
-
if [ -f "$SETUP" ] && [ -s "$SETUP" ]; then
|
|
305
|
-
chmod +x "$SETUP"
|
|
306
|
-
if ! (cd "$WORK_DIR" && "$SETUP") > "$RESULT_DIR/setup.log" 2>&1; then
|
|
307
|
-
echo "setup.sh failed; see $RESULT_DIR/setup.log"
|
|
308
|
-
exit 1
|
|
309
|
-
fi
|
|
310
|
-
if ! (cd "$WORK_DIR" \
|
|
311
|
-
&& git add -A \
|
|
312
|
-
&& git -c user.email=b@b -c user.name=b commit -q --allow-empty -m "fixture-setup"); then
|
|
313
|
-
echo "fixture-setup commit failed — arm diff isolation broken"
|
|
314
|
-
exit 1
|
|
315
|
-
fi
|
|
316
|
-
fi
|
|
317
|
-
|
|
318
|
-
# iter-0019.6: stage normalized .devlyn/spec-verify.json for BUILD_GATE.
|
|
319
|
-
# Only commands safe to reveal before IMPLEMENT may be staged here. Commands
|
|
320
|
-
# that reference BENCH_FIXTURE_DIR are hidden post-run oracles; staging their
|
|
321
|
-
# path leaks verifier names into the arm and lets agents search for answer-key
|
|
322
|
-
# files. Those commands still run in the post-run verifier below.
|
|
323
|
-
if [ "$ARM" = "variant" ] || [ "$ARM" = "solo_claude" ] \
|
|
324
|
-
|| [ "$ARM" = "l2_gated" ] || [ "$ARM" = "l2_risk_probes" ] || [ "$ARM" = "l2_forced" ]; then
|
|
325
|
-
python3 - "$EXPECTED" "$WORK_DIR/.devlyn/spec-verify.json" "$BENCH_ROOT/scripts" <<'PY'
|
|
326
|
-
import json, os, pathlib, sys
|
|
327
|
-
sys.path.insert(0, sys.argv[3])
|
|
328
|
-
from pair_evidence_contract import loads_strict_json_object
|
|
329
|
-
|
|
330
|
-
expected = loads_strict_json_object(pathlib.Path(sys.argv[1]).read_text())
|
|
331
|
-
out_path = sys.argv[2]
|
|
332
|
-
visible_commands = [
|
|
333
|
-
cmd for cmd in expected.get("verification_commands", [])
|
|
334
|
-
if "BENCH_FIXTURE_DIR" not in str(cmd.get("cmd", ""))
|
|
335
|
-
]
|
|
336
|
-
normalized = {"verification_commands": visible_commands}
|
|
337
|
-
os.makedirs(os.path.dirname(out_path), exist_ok=True)
|
|
338
|
-
if not visible_commands:
|
|
339
|
-
raise SystemExit(0)
|
|
340
|
-
with open(out_path, "w") as f:
|
|
341
|
-
json.dump(normalized, f, indent=2)
|
|
342
|
-
f.write("\n")
|
|
343
|
-
PY
|
|
344
|
-
fi
|
|
345
|
-
|
|
346
|
-
# Build arm-specific prompt + place arm-specific environment files. Anything
|
|
347
|
-
# that's "benchmark scaffolding" (spec path placement, prompt wrapper) is
|
|
348
|
-
# committed to the work repo as a separate pre-model commit so the model's
|
|
349
|
-
# diff shows only its own work.
|
|
350
|
-
#
|
|
351
|
-
# Per-arm prompt selection is:
|
|
352
|
-
# 1. Fixture-id-aware for F9 (end-to-end novice fixture, no pre-placed spec).
|
|
353
|
-
# 2. Spec-mode `/devlyn:resolve --spec <path>` for the rest (post iter-0034
|
|
354
|
-
# Phase 4 cutover the OLD `/devlyn:auto-resolve` route was deleted).
|
|
355
|
-
PROMPT_FILE="$RESULT_DIR/input.md"
|
|
356
|
-
# Variant uses the current measured risk-probes pair path; solo_claude uses
|
|
357
|
-
# --engine claude explicitly so the orchestrator routes every implementation
|
|
358
|
-
# phase to Claude and never tries to invoke codex. The CODEX_BLOCKED shim
|
|
359
|
-
# enforces this at the binary layer if the orchestrator misroutes. Both arms
|
|
360
|
-
# pass the engine flag explicitly so they survive future runtime-default
|
|
361
|
-
# changes (post iter-0020 close-out: default flipped to claude).
|
|
362
|
-
if [ "$ARM" = "variant" ] || [ "$ARM" = "solo_claude" ] \
|
|
363
|
-
|| [ "$ARM" = "l2_gated" ] || [ "$ARM" = "l2_risk_probes" ] || [ "$ARM" = "l2_forced" ]; then
|
|
364
|
-
case "$ARM" in
|
|
365
|
-
solo_claude)
|
|
366
|
-
# L1 = pure solo by construction. --no-risk-probes --no-pair so a high-risk
|
|
367
|
-
# spec measures Claude-only solo deterministically instead of auto-escalating
|
|
368
|
-
# toward the (blocked) OTHER engine. Without these, a security/high-risk
|
|
369
|
-
# fixture auto-triggers the cross-engine path and the arm mis-measures L1.
|
|
370
|
-
ENGINE_CLAUSE="--engine claude --no-risk-probes --no-pair"
|
|
371
|
-
ENGINE_PROMPT_HINT="Run with \`--engine claude --no-risk-probes --no-pair\` for every phase — pure solo L1. Codex must not be invoked — the harness has blocked it at the binary layer for this run."
|
|
372
|
-
;;
|
|
373
|
-
variant)
|
|
374
|
-
ENGINE_CLAUSE="--engine claude --risk-probes"
|
|
375
|
-
ENGINE_PROMPT_HINT="Run with \`--engine claude --risk-probes\` so the smoke L2 arm uses the current measured pair path: Claude implements, Codex derives bounded visible-verification probes and can act as VERIFY pair-JUDGE."
|
|
376
|
-
;;
|
|
377
|
-
l2_gated)
|
|
378
|
-
# NEW L2 with natural pair-mode triggers. Claude does IMPLEMENT;
|
|
379
|
-
# pair-JUDGE in VERIFY fires per /devlyn:resolve PHASE 5 policy
|
|
380
|
-
# (high complexity, coverage_failed, or warning-level mechanical
|
|
381
|
-
# findings; never after HIGH/CRITICAL mechanical blockers). Codex
|
|
382
|
-
# remains available as the OTHER-engine pair-JUDGE candidate.
|
|
383
|
-
ENGINE_CLAUSE="--engine claude"
|
|
384
|
-
ENGINE_PROMPT_HINT="Run with \`--engine claude\` and let the orchestrator's pair-mode (VERIFY) trigger naturally per its policy. Codex is available as the OTHER-engine pair-JUDGE — the harness has not blocked it. Do NOT pass \`--pair-verify\`; this arm measures gated triggering."
|
|
385
|
-
;;
|
|
386
|
-
l2_risk_probes)
|
|
387
|
-
# NEW L2 probe-derive arm. Claude plans/implements; Codex is used before
|
|
388
|
-
# IMPLEMENT only to derive bounded executable probes from visible
|
|
389
|
-
# Verification bullets. BUILD_GATE and VERIFY execute those probes
|
|
390
|
-
# mechanically via spec-verify-check.py.
|
|
391
|
-
ENGINE_CLAUSE="--engine claude --risk-probes"
|
|
392
|
-
ENGINE_PROMPT_HINT="Run with \`--engine claude --risk-probes\`. Codex is available as the OTHER-engine probe derivation and pair-JUDGE engine. The probe phase may only derive executable checks from visible \`## Verification\` text; it must not read hidden fixture/verifier paths."
|
|
393
|
-
;;
|
|
394
|
-
l2_forced)
|
|
395
|
-
# iter-0033c: NEW L2 forced — pair-JUDGE always fires. Diagnostic arm
|
|
396
|
-
# for Gate 6 fixture-level cross-check + Gate 7 attribution causality.
|
|
397
|
-
ENGINE_CLAUSE="--engine claude --pair-verify"
|
|
398
|
-
ENGINE_PROMPT_HINT="Run with \`--engine claude --pair-verify\` so VERIFY pair-mode fires unconditionally. Codex is the OTHER-engine pair-JUDGE."
|
|
399
|
-
;;
|
|
400
|
-
esac
|
|
401
|
-
if [ "$FIXTURE" = "F9-e2e-ideate-to-resolve" ]; then
|
|
402
|
-
# F9 NEW chain (iter-0033a): /devlyn:ideate --quick → /devlyn:resolve
|
|
403
|
-
# --spec <emitted-path>. No pre-placed spec; the variant arm generates it
|
|
404
|
-
# via ideate. No preflight (folded into resolve's VERIFY phase).
|
|
405
|
-
#
|
|
406
|
-
# --quick is mandatory in autonomous (claude -p) mode: default ideate
|
|
407
|
-
# invokes interactive Q&A which has no human to answer in a benchmark
|
|
408
|
-
# subprocess — the agent asks questions and stops. --quick uses
|
|
409
|
-
# single-turn assume-and-confirm: AI synthesizes the spec from the goal
|
|
410
|
-
# plus an explicit assumptions block, so the chain proceeds end-to-end
|
|
411
|
-
# without user input. Smoke 3 (iter-0033a, 2026-04-30) caught this:
|
|
412
|
-
# default-mode F9 produced empty diffs after 54s of Q&A waiting.
|
|
413
|
-
cat > "$PROMPT_FILE" <<EOF
|
|
414
|
-
You are a first-time devlyn-cli user. You have a vague idea and want the 2-skill harness to take it from unstructured ask to shipped, verified feature. Run the chain:
|
|
415
|
-
|
|
416
|
-
1. Invoke \`/devlyn:ideate --quick ${ENGINE_CLAUSE}\` to turn the idea into a verifiable spec. \`--quick\` is mandatory: this is an autonomous run with no human to answer interactive questions, so ideate must synthesize the spec single-turn from the goal text and emit assumptions explicitly. The skill announces \`spec ready — /devlyn:resolve --spec <emitted-path>\` when done. The emitted spec lives at \`docs/specs/<id>-<slug>/spec.md\` with a sibling \`spec.expected.json\`.
|
|
417
|
-
2. Take the emitted spec path verbatim from the announce line and invoke \`/devlyn:resolve --spec <that-path> ${ENGINE_CLAUSE}\` to run PLAN → IMPLEMENT → BUILD_GATE → CLEANUP → VERIFY (VERIFY is the fresh-subagent final phase — there is no separate preflight skill in the 2-skill design).
|
|
418
|
-
|
|
419
|
-
${ENGINE_PROMPT_HINT}
|
|
420
|
-
|
|
421
|
-
Follow the skills to completion. Do not short-circuit. Do not invoke \`/devlyn:auto-resolve\` or \`/devlyn:preflight\` — they are not part of the 2-skill chain. Do not stop after ideate; the chain only counts as complete after \`/devlyn:resolve\` returns a terminal verdict.
|
|
422
|
-
|
|
423
|
-
After the whole chain, briefly report: (a) the spec path ideate produced, (b) the resolve terminal verdict, (c) whether VERIFY surfaced any findings.
|
|
424
|
-
|
|
425
|
-
RAW IDEA:
|
|
426
|
-
$(cat "$TASK")
|
|
427
|
-
EOF
|
|
428
|
-
else
|
|
429
|
-
# Spec-mode /devlyn:resolve: spec pre-placed at the canonical roadmap path
|
|
430
|
-
# the harness has used since iter-0019. Pre-Phase-4 this branch shared
|
|
431
|
-
# staging with the OLD /devlyn:auto-resolve route; iter-0034 deleted the
|
|
432
|
-
# OLD branch and this is now the only non-F9 path.
|
|
433
|
-
mkdir -p "$WORK_DIR/docs/roadmap/phase-1"
|
|
434
|
-
cp "$SPEC" "$WORK_DIR/docs/roadmap/phase-1/$FIXTURE.md"
|
|
435
|
-
# iter-0049: fixtures keep spec.md prose-only (expected.json is the real
|
|
436
|
-
# carrier, validated separately by lint-fixtures.sh) but spec-verify-check.py
|
|
437
|
-
# now locates the visible ## Verification prose via a <!-- devlyn:verification -->
|
|
438
|
-
# sentinel rather than the English header text. Inject it into the WORK_DIR
|
|
439
|
-
# copy only, so risk-probe derived_from substring matching still finds the
|
|
440
|
-
# section during a run; the source fixture repo stays untouched.
|
|
441
|
-
if ! grep -q '<!-- devlyn:verification -->' "$WORK_DIR/docs/roadmap/phase-1/$FIXTURE.md"; then
|
|
442
|
-
sed -i.bak 's/^## Verification\b/<!-- devlyn:verification -->\n## Verification/' \
|
|
443
|
-
"$WORK_DIR/docs/roadmap/phase-1/$FIXTURE.md"
|
|
444
|
-
rm -f "$WORK_DIR/docs/roadmap/phase-1/$FIXTURE.md.bak"
|
|
445
|
-
fi
|
|
446
|
-
cat > "$PROMPT_FILE" <<EOF
|
|
447
|
-
Use the \`/devlyn:resolve --spec docs/roadmap/phase-1/$FIXTURE.md ${ENGINE_CLAUSE}\` skill to implement the spec. ${ENGINE_PROMPT_HINT}
|
|
448
|
-
|
|
449
|
-
The 2-skill design folds verification into resolve's VERIFY phase — there is no separate \`/devlyn:preflight\`, \`/devlyn:auto-resolve\`, or other 3-skill orchestrator at HEAD.
|
|
450
|
-
|
|
451
|
-
After the pipeline finishes, report the terminal verdict and list of files changed so the benchmark runner can capture state.
|
|
452
|
-
EOF
|
|
453
|
-
fi
|
|
454
|
-
else
|
|
455
|
-
# Bare — same prompt for F9 as any other fixture: task.txt with anti-skill rules.
|
|
456
|
-
cat > "$PROMPT_FILE" <<EOF
|
|
457
|
-
You are acting as a smart engineer implementing the following request directly. No skill pipeline.
|
|
458
|
-
|
|
459
|
-
HARD RULES:
|
|
460
|
-
- Do NOT invoke any \`/devlyn:*\` skill (no auto-resolve, evaluate, review, clean, update-docs, team-*, etc.).
|
|
461
|
-
- Do NOT invoke native \`simplify\` or \`security-review\` skills.
|
|
462
|
-
- Use only direct tools: Read, Write, Edit, Grep, Glob, Bash.
|
|
463
|
-
- Write code to satisfy the request. Run the verification commands the user implies. Fix failures until they pass.
|
|
464
|
-
|
|
465
|
-
REQUEST:
|
|
466
|
-
$(cat "$TASK")
|
|
467
|
-
EOF
|
|
468
|
-
fi
|
|
469
|
-
|
|
470
|
-
# Commit scaffolding so the upcoming arm-only diff excludes it. A failure
|
|
471
|
-
# here means arm work would appear mixed with scaffolding in the diff — fail
|
|
472
|
-
# loudly rather than silently producing corrupted data.
|
|
473
|
-
if ! (cd "$WORK_DIR" \
|
|
474
|
-
&& git add -A \
|
|
475
|
-
&& git -c user.email=b@b -c user.name=b commit -q --allow-empty -m "bench-scaffold"); then
|
|
476
|
-
echo "bench-scaffold commit failed — arm diff isolation broken"
|
|
477
|
-
exit 1
|
|
478
|
-
fi
|
|
479
|
-
# Capture the scaffold commit SHA so the arm-only diff can be computed even
|
|
480
|
-
# when the arm makes its own commits internally (e.g. variant's auto-resolve
|
|
481
|
-
# pipeline commits after each phase). Diffing against HEAD would miss those.
|
|
482
|
-
SCAFFOLD_SHA=$(cd "$WORK_DIR" && git rev-parse HEAD)
|
|
483
|
-
|
|
484
|
-
# Timing start
|
|
485
|
-
T_START=$(date +%s)
|
|
486
|
-
cat > "$RESULT_DIR/timing.json" <<EOF
|
|
487
|
-
{
|
|
488
|
-
"run_id": "$RUN_ID",
|
|
489
|
-
"fixture": "$FIXTURE",
|
|
490
|
-
"arm": "$ARM",
|
|
491
|
-
"work_dir": "$WORK_DIR",
|
|
492
|
-
"start_epoch": $T_START
|
|
493
|
-
}
|
|
494
|
-
EOF
|
|
495
|
-
|
|
496
|
-
# --- Invocation -------------------------------------------------------------
|
|
497
|
-
# Exit code is captured so infrastructure failures don't silently look like
|
|
498
|
-
# a weak diff. See invoke_exit in result.json.
|
|
499
|
-
INVOKE_EXIT=0
|
|
500
|
-
# iter-0012: WATCHDOG_FIRED is the truth source for `timed_out` in result.json.
|
|
501
|
-
# Set to 1 only when the watchdog flag file existed at post-wait check
|
|
502
|
-
# (lines 332-336). Initialized here so the `set -u` `export` below at the
|
|
503
|
-
# Python aggregator works in both branches (dry-run never sets it).
|
|
504
|
-
WATCHDOG_FIRED=0
|
|
505
|
-
if [ $DRY_RUN -eq 1 ]; then
|
|
506
|
-
echo "[run-fixture] DRY RUN — prepared $WORK_DIR, skipping model invocation" \
|
|
507
|
-
> "$RESULT_DIR/transcript.txt"
|
|
508
|
-
else
|
|
509
|
-
command -v claude >/dev/null 2>&1 || {
|
|
510
|
-
echo "claude CLI not on PATH — cannot invoke arm"; exit 1;
|
|
511
|
-
}
|
|
512
|
-
# Arm uses real HOME so Claude auth (macOS Keychain + ~/.claude session
|
|
513
|
-
# state) works. Fixtures that need HOME isolation override it inline in
|
|
514
|
-
# their verification commands (e.g. F2 uses `HOME=/nonexistent` per command).
|
|
515
|
-
# Variant-arm skills are resolved from $WORK_DIR/.claude/skills (project
|
|
516
|
-
# scope), so bare-arm runs never see them regardless of HOME.
|
|
517
|
-
#
|
|
518
|
-
# Portable wall-clock watchdog. macOS lacks GNU `timeout` by default; the
|
|
519
|
-
# earlier fallback ran arms unbounded, which produced a multi-hour F7 hang
|
|
520
|
-
# when the inner `codex exec` raced against a lingering codex-mcp-server.
|
|
521
|
-
# We background the arm in its own process group (`set -m` + `exec`) so the
|
|
522
|
-
# watchdog can `kill -- -PGID` and reap codex/codex-mcp-server descendants
|
|
523
|
-
# together with the parent. A flag file disambiguates timeout from natural
|
|
524
|
-
# exit; on timeout we set INVOKE_EXIT=124 (GNU timeout convention) so the
|
|
525
|
-
# downstream `invoke_failure` logic routes the run into BLOCKED. iter-0012:
|
|
526
|
-
# the same flag also flips WATCHDOG_FIRED=1, which is exported and consumed
|
|
527
|
-
# by the Python aggregator below to derive result.json.timed_out — so a
|
|
528
|
-
# natural exit at or past the budget is no longer mislabeled as timeout.
|
|
529
|
-
#
|
|
530
|
-
# MCP/config isolation (iter 0004). The harness's `claude -p` subprocess
|
|
531
|
-
# must not load the operator's user-level MCP/plugins/settings (pencil,
|
|
532
|
-
# codex-cli, telegram, vercel, ...). Project policy is "MCP/plugins are not in
|
|
533
|
-
# the loop"; loading user config inside the arm is uncontrolled environment
|
|
534
|
-
# leaking into the experiment. `--setting-sources project,local` keeps user
|
|
535
|
-
# plugin enablement out of the run but Claude Code still reads the installed
|
|
536
|
-
# plugin registry for autoupdate. Official Claude Code settings document
|
|
537
|
-
# `DISABLE_AUTOUPDATER=1` / `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1` as the
|
|
538
|
-
# supported way to disable that background traffic, while preserving OAuth
|
|
539
|
-
# auth from the real HOME. `--strict-mcp-config` + an empty `mcpServers` object
|
|
540
|
-
# forces a hermetic MCP set. Skills still resolve via the project
|
|
541
|
-
# `.claude/skills` staged into the worktree.
|
|
542
|
-
# `--debug-file` records per-arm init/runtime so the next hang has a
|
|
543
|
-
# location, not a guess.
|
|
544
|
-
TIMEOUT_FLAG="$RESULT_DIR/.timed_out"
|
|
545
|
-
rm -f "$TIMEOUT_FLAG"
|
|
546
|
-
|
|
547
|
-
set +e
|
|
548
|
-
set -m
|
|
549
|
-
(
|
|
550
|
-
cd "$WORK_DIR"
|
|
551
|
-
# iter-0009 + iter-0019: prepend codex shim PATH for any arm that staged
|
|
552
|
-
# one. variant routes through codex-monitored.sh; solo_claude refuses on
|
|
553
|
-
# CODEX_BLOCKED=1; bare has no shim.
|
|
554
|
-
# iter-0033c/0037 (Codex R0-infra Q6 + risk probes): l2_* arms ALSO need the shim
|
|
555
|
-
# PATH — they route Claude IMPLEMENT but Codex pair-JUDGE in VERIFY hits
|
|
556
|
-
# `codex exec` through the wrapper for starvation safety.
|
|
557
|
-
if { [ "$ARM" = "variant" ] || [ "$ARM" = "solo_claude" ] \
|
|
558
|
-
|| [ "$ARM" = "l2_gated" ] || [ "$ARM" = "l2_risk_probes" ] || [ "$ARM" = "l2_forced" ]; } \
|
|
559
|
-
&& [ -x "$WORK_DIR/.devlyn-bin/codex" ]; then
|
|
560
|
-
export PATH="$WORK_DIR/.devlyn-bin:$PATH"
|
|
561
|
-
[ "$ARM" = "solo_claude" ] && export CODEX_BLOCKED=1
|
|
562
|
-
fi
|
|
563
|
-
# iter-0019.6: BUILD_GATE's spec-verify-check.py uses BENCH_WORKDIR for
|
|
564
|
-
# commands that escape the work-dir (e.g. F9's outside-repo check via
|
|
565
|
-
# `cd /tmp && node $BENCH_WORKDIR/bin/cli.js gitstats`). Mirror exactly
|
|
566
|
-
# what the post-run verifier (run-fixture.sh:431-434) sets so the gate
|
|
567
|
-
# sees the same environment shape.
|
|
568
|
-
export BENCH_WORKDIR="$WORK_DIR"
|
|
569
|
-
# Python helper scripts run inside the benchmark worktree. Do not let them
|
|
570
|
-
# rewrite tracked __pycache__ artifacts and pollute the arm-only diff.
|
|
571
|
-
export PYTHONDONTWRITEBYTECODE=1
|
|
572
|
-
# Official Claude Code setting: disable background plugin/autoupdate traffic
|
|
573
|
-
# before process startup. Project settings env is not early enough for all
|
|
574
|
-
# startup paths.
|
|
575
|
-
export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1
|
|
576
|
-
export DISABLE_AUTOUPDATER=1
|
|
577
|
-
exec claude \
|
|
578
|
-
-p "$(cat "$PROMPT_FILE")" \
|
|
579
|
-
--dangerously-skip-permissions \
|
|
580
|
-
--effort xhigh \
|
|
581
|
-
--setting-sources project,local \
|
|
582
|
-
--strict-mcp-config \
|
|
583
|
-
--mcp-config '{"mcpServers":{}}' \
|
|
584
|
-
--debug-file "$RESULT_DIR/claude-debug.log"
|
|
585
|
-
) > "$RESULT_DIR/transcript.txt" 2>&1 &
|
|
586
|
-
CHILD_PID=$!
|
|
587
|
-
set +m
|
|
588
|
-
|
|
589
|
-
(
|
|
590
|
-
deadline=$((T_START + TIMEOUT))
|
|
591
|
-
while kill -0 "$CHILD_PID" 2>/dev/null; do
|
|
592
|
-
now=$(date +%s)
|
|
593
|
-
if [ "$now" -ge "$deadline" ]; then
|
|
594
|
-
: > "$TIMEOUT_FLAG"
|
|
595
|
-
kill -TERM -- "-$CHILD_PID" 2>/dev/null
|
|
596
|
-
kill_worktree_processes "$WORK_DIR" TERM
|
|
597
|
-
sleep 5
|
|
598
|
-
kill -KILL -- "-$CHILD_PID" 2>/dev/null
|
|
599
|
-
kill_worktree_processes "$WORK_DIR" KILL
|
|
600
|
-
exit 0
|
|
601
|
-
fi
|
|
602
|
-
remaining=$((deadline - now))
|
|
603
|
-
[ "$remaining" -gt 30 ] && sleep 30 || sleep "$remaining"
|
|
604
|
-
done
|
|
605
|
-
) &
|
|
606
|
-
WATCHDOG_PID=$!
|
|
607
|
-
|
|
608
|
-
wait "$CHILD_PID"
|
|
609
|
-
INVOKE_EXIT=$?
|
|
610
|
-
|
|
611
|
-
kill -TERM "$WATCHDOG_PID" 2>/dev/null || true
|
|
612
|
-
wait "$WATCHDOG_PID" 2>/dev/null || true
|
|
613
|
-
|
|
614
|
-
if [ -f "$TIMEOUT_FLAG" ]; then
|
|
615
|
-
INVOKE_EXIT=124
|
|
616
|
-
WATCHDOG_FIRED=1
|
|
617
|
-
rm -f "$TIMEOUT_FLAG"
|
|
618
|
-
kill_worktree_processes "$WORK_DIR" TERM
|
|
619
|
-
sleep 1
|
|
620
|
-
kill_worktree_processes "$WORK_DIR" KILL
|
|
621
|
-
echo "[run-fixture] arm timed out after ${TIMEOUT}s — INVOKE_EXIT=124" >&2
|
|
622
|
-
else
|
|
623
|
-
# A clean `claude -p` exit can still leave OTHER-engine pair-JUDGE
|
|
624
|
-
# descendants alive; reap any process group rooted in this arm worktree.
|
|
625
|
-
kill_worktree_processes "$WORK_DIR" TERM
|
|
626
|
-
sleep 1
|
|
627
|
-
kill_worktree_processes "$WORK_DIR" KILL
|
|
628
|
-
fi
|
|
629
|
-
set -e
|
|
630
|
-
fi
|
|
631
|
-
|
|
632
|
-
T_END=$(date +%s)
|
|
633
|
-
ELAPSED=$((T_END - T_START))
|
|
634
|
-
|
|
635
|
-
# Restore tracked Python bytecode to the scaffold commit and remove only
|
|
636
|
-
# untracked bytecode. Helper invocations must not count as model work, but
|
|
637
|
-
# deleting tracked scaffold files would also pollute changed-files.txt.
|
|
638
|
-
(cd "$WORK_DIR" \
|
|
639
|
-
&& git restore --source "$SCAFFOLD_SHA" -- .claude/skills/_shared/__pycache__ 2>/dev/null || true)
|
|
640
|
-
cleanup_roots=()
|
|
641
|
-
[ -d "$WORK_DIR/.claude" ] && cleanup_roots+=("$WORK_DIR/.claude")
|
|
642
|
-
[ -d "$WORK_DIR/.devlyn" ] && cleanup_roots+=("$WORK_DIR/.devlyn")
|
|
643
|
-
if [ ${#cleanup_roots[@]} -gt 0 ]; then
|
|
644
|
-
find "${cleanup_roots[@]}" -type f \( -name '*.pyc' -o -name '*.pyo' \) -print0 \
|
|
645
|
-
| while IFS= read -r -d '' py_file; do
|
|
646
|
-
rel="${py_file#$WORK_DIR/}"
|
|
647
|
-
if ! (cd "$WORK_DIR" && git ls-files --error-unmatch "$rel" >/dev/null 2>&1); then
|
|
648
|
-
rm -f "$py_file"
|
|
649
|
-
fi
|
|
650
|
-
done
|
|
651
|
-
find "${cleanup_roots[@]}" -type d -name __pycache__ -empty -delete || true
|
|
652
|
-
fi
|
|
653
|
-
|
|
654
|
-
# Capture the ARM-ONLY diff against the scaffold commit. Variant's
|
|
655
|
-
# auto-resolve pipeline commits internally after each phase, so diffing
|
|
656
|
-
# against HEAD would miss committed work. Diffing against SCAFFOLD_SHA after
|
|
657
|
-
# `git add -A` picks up both scaffold..HEAD committed deltas AND any
|
|
658
|
-
# staged-but-not-yet-committed leftovers (unstaged or untracked).
|
|
659
|
-
(cd "$WORK_DIR" \
|
|
660
|
-
&& git add -A 2>/dev/null \
|
|
661
|
-
&& git diff "$SCAFFOLD_SHA") > "$RESULT_DIR/diff.patch" 2>&1 || true
|
|
662
|
-
(cd "$WORK_DIR" \
|
|
663
|
-
&& git diff "$SCAFFOLD_SHA" --name-only) > "$RESULT_DIR/changed-files.txt" 2>&1 || true
|
|
664
|
-
|
|
665
|
-
# Deterministic oracles. Hard/flag findings are merged into verify.json below.
|
|
666
|
-
python3 "$BENCH_ROOT/scripts/oracle-test-fidelity.py" \
|
|
667
|
-
--work "$WORK_DIR" --scaffold "$SCAFFOLD_SHA" \
|
|
668
|
-
> "$RESULT_DIR/oracle-test-fidelity.json" 2>/dev/null || \
|
|
669
|
-
echo '{"oracle":"test-fidelity","findings":[],"error":"oracle invocation failed"}' \
|
|
670
|
-
> "$RESULT_DIR/oracle-test-fidelity.json"
|
|
671
|
-
|
|
672
|
-
python3 "$BENCH_ROOT/scripts/oracle-scope-tier-a.py" \
|
|
673
|
-
--work "$WORK_DIR" --scaffold "$SCAFFOLD_SHA" --expected "$EXPECTED" \
|
|
674
|
-
> "$RESULT_DIR/oracle-scope-tier-a.json" 2>/dev/null || \
|
|
675
|
-
echo '{"oracle":"scope-tier-a","findings":[],"error":"oracle invocation failed"}' \
|
|
676
|
-
> "$RESULT_DIR/oracle-scope-tier-a.json"
|
|
677
|
-
|
|
678
|
-
python3 "$BENCH_ROOT/scripts/oracle-scope-tier-b.py" \
|
|
679
|
-
--work "$WORK_DIR" --scaffold "$SCAFFOLD_SHA" --expected "$EXPECTED" \
|
|
680
|
-
> "$RESULT_DIR/oracle-scope-tier-b.json" 2>/dev/null || \
|
|
681
|
-
echo '{"oracle":"scope-tier-b","findings":[],"error":"oracle invocation failed"}' \
|
|
682
|
-
> "$RESULT_DIR/oracle-scope-tier-b.json"
|
|
683
|
-
|
|
684
|
-
if { [ "$ARM" = "variant" ] || [ "$ARM" = "solo_claude" ] \
|
|
685
|
-
|| [ "$ARM" = "l2_gated" ] || [ "$ARM" = "l2_risk_probes" ]; } \
|
|
686
|
-
&& [ -f "$WORK_DIR/.devlyn/pipeline.state.json" ] \
|
|
687
|
-
&& [ -f "$WORK_DIR/.claude/skills/_shared/verify-merge-findings.py" ]; then
|
|
688
|
-
if [ -f "$WORK_DIR/.devlyn/codex-judge.stdout" ] \
|
|
689
|
-
&& [ -f "$WORK_DIR/.claude/skills/_shared/collect-codex-findings.py" ]; then
|
|
690
|
-
if ! python3 "$WORK_DIR/.claude/skills/_shared/collect-codex-findings.py" \
|
|
691
|
-
--devlyn-dir "$WORK_DIR/.devlyn" \
|
|
692
|
-
> "$RESULT_DIR/collect-codex-findings.log" 2>&1; then
|
|
693
|
-
echo "[run-fixture] Codex pair findings collection failed; see $RESULT_DIR/collect-codex-findings.log" >&2
|
|
694
|
-
fi
|
|
695
|
-
fi
|
|
696
|
-
if ! python3 "$WORK_DIR/.claude/skills/_shared/verify-merge-findings.py" \
|
|
697
|
-
--devlyn-dir "$WORK_DIR/.devlyn" --write-state \
|
|
698
|
-
> "$RESULT_DIR/verify-merge-normalize.log" 2>&1; then
|
|
699
|
-
echo "[run-fixture] verify merge normalization failed; see $RESULT_DIR/verify-merge-normalize.log" >&2
|
|
700
|
-
fi
|
|
701
|
-
fi
|
|
702
|
-
|
|
703
|
-
if { [ "$ARM" = "variant" ] || [ "$ARM" = "solo_claude" ] \
|
|
704
|
-
|| [ "$ARM" = "l2_gated" ] || [ "$ARM" = "l2_risk_probes" ]; } && [ -d "$WORK_DIR/.devlyn" ]; then
|
|
705
|
-
run_dir=$(find "$WORK_DIR/.devlyn/runs" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sort | tail -1 || true)
|
|
706
|
-
if [ -n "$run_dir" ]; then
|
|
707
|
-
rm -rf "$RESULT_DIR/run-archive"
|
|
708
|
-
cp -R "$run_dir" "$RESULT_DIR/run-archive"
|
|
709
|
-
[ -f "$RESULT_DIR/run-archive/pipeline.state.json" ] \
|
|
710
|
-
|| [ ! -f "$WORK_DIR/.devlyn/pipeline.state.json" ] \
|
|
711
|
-
|| cp "$WORK_DIR/.devlyn/pipeline.state.json" "$RESULT_DIR/run-archive/pipeline.state.json"
|
|
712
|
-
else
|
|
713
|
-
rm -rf "$RESULT_DIR/run-archive"
|
|
714
|
-
mkdir -p "$RESULT_DIR/run-archive"
|
|
715
|
-
find "$WORK_DIR/.devlyn" -maxdepth 1 -type f -exec cp {} "$RESULT_DIR/run-archive/" \;
|
|
716
|
-
fi
|
|
717
|
-
fi
|
|
718
|
-
|
|
719
|
-
# Run verification commands + forbidden pattern scan + deps check. Uses
|
|
720
|
-
# the operator's real HOME (same as the arm saw). Fixtures that need HOME
|
|
721
|
-
# isolation override it inline per verification command.
|
|
722
|
-
python3 - "$EXPECTED" "$RESULT_DIR" "$WORK_DIR" "$BENCH_ROOT/scripts" <<'PY'
|
|
723
|
-
import json, os, pathlib, re, subprocess, sys
|
|
724
|
-
|
|
725
|
-
sys.path.insert(0, sys.argv[4])
|
|
726
|
-
from pair_evidence_contract import loads_strict_json_object
|
|
727
|
-
|
|
728
|
-
expected = loads_strict_json_object(pathlib.Path(sys.argv[1]).read_text())
|
|
729
|
-
result_dir = sys.argv[2]
|
|
730
|
-
work = sys.argv[3]
|
|
731
|
-
|
|
732
|
-
verify_env = os.environ.copy()
|
|
733
|
-
# Expose the work-dir path so fixtures whose verification needs to reference
|
|
734
|
-
# the work root can do so portably (e.g. F9's out-of-repo check).
|
|
735
|
-
verify_env["BENCH_WORKDIR"] = work
|
|
736
|
-
# Hidden benchmark verifiers live in the fixture directory, outside the arm's
|
|
737
|
-
# work tree. This keeps oracle code from becoming implementation context.
|
|
738
|
-
verify_env["BENCH_FIXTURE_DIR"] = os.path.dirname(os.path.abspath(sys.argv[1]))
|
|
739
|
-
|
|
740
|
-
verify = {"commands": [], "forbidden_pattern_hits": [], "deps_added": 0,
|
|
741
|
-
"max_deps_added": expected.get("max_deps_added", 0),
|
|
742
|
-
"missing_required_files": [], "forbidden_files_present": [],
|
|
743
|
-
"oracle_findings": [], "oracle_disqualifier": False}
|
|
744
|
-
|
|
745
|
-
for vc in expected.get("verification_commands", []):
|
|
746
|
-
try:
|
|
747
|
-
timeout_sec = vc.get("timeout_sec", 60)
|
|
748
|
-
if (
|
|
749
|
-
isinstance(timeout_sec, bool)
|
|
750
|
-
or not isinstance(timeout_sec, int)
|
|
751
|
-
or not 1 <= timeout_sec <= 600
|
|
752
|
-
):
|
|
753
|
-
raise ValueError(
|
|
754
|
-
"timeout_sec must be an integer from 1 to 600 (bool is not allowed)"
|
|
755
|
-
)
|
|
756
|
-
proc = subprocess.run(vc["cmd"], cwd=work, shell=True, env=verify_env,
|
|
757
|
-
capture_output=True, text=True,
|
|
758
|
-
timeout=timeout_sec)
|
|
759
|
-
out = (proc.stdout or "") + (proc.stderr or "")
|
|
760
|
-
ok_exit = proc.returncode == vc.get("exit_code", 0)
|
|
761
|
-
ok_contains = all(s in out for s in vc.get("stdout_contains", []))
|
|
762
|
-
ok_not = not any(s in out for s in vc.get("stdout_not_contains", []))
|
|
763
|
-
verify["commands"].append({
|
|
764
|
-
"cmd": vc["cmd"],
|
|
765
|
-
"expected_exit": vc.get("exit_code", 0),
|
|
766
|
-
"actual_exit": proc.returncode,
|
|
767
|
-
"pass": bool(ok_exit and ok_contains and ok_not),
|
|
768
|
-
"reason": None if (ok_exit and ok_contains and ok_not)
|
|
769
|
-
else ("exit" if not ok_exit
|
|
770
|
-
else ("missing_contains" if not ok_contains else "unexpected_text")),
|
|
771
|
-
"stdout_tail": out[-500:],
|
|
772
|
-
})
|
|
773
|
-
except subprocess.TimeoutExpired:
|
|
774
|
-
verify["commands"].append({"cmd": vc["cmd"], "pass": False, "reason": "timeout"})
|
|
775
|
-
except Exception as e:
|
|
776
|
-
verify["commands"].append({"cmd": vc["cmd"], "pass": False,
|
|
777
|
-
"reason": f"error:{e.__class__.__name__}:{e}"})
|
|
778
|
-
|
|
779
|
-
# Forbidden pattern scan over diff.patch. Each pattern may declare a `files`
|
|
780
|
-
# allowlist; when present, we slice the diff to only those files' hunks.
|
|
781
|
-
diff_text = ""
|
|
782
|
-
try:
|
|
783
|
-
with open(os.path.join(result_dir, "diff.patch")) as fh:
|
|
784
|
-
diff_text = fh.read()
|
|
785
|
-
except Exception:
|
|
786
|
-
pass
|
|
787
|
-
|
|
788
|
-
def slice_diff_to_files(diff, files):
|
|
789
|
-
"""Return the subset of a unified diff touching any of `files`.
|
|
790
|
-
Hunks outside the allowlist are dropped."""
|
|
791
|
-
if not files:
|
|
792
|
-
return diff
|
|
793
|
-
out, keep = [], False
|
|
794
|
-
for line in diff.splitlines(keepends=True):
|
|
795
|
-
if line.startswith("diff --git "):
|
|
796
|
-
keep = any(f in line for f in files)
|
|
797
|
-
if keep:
|
|
798
|
-
out.append(line)
|
|
799
|
-
return "".join(out)
|
|
800
|
-
|
|
801
|
-
for fp in expected.get("forbidden_patterns", []):
|
|
802
|
-
scope = slice_diff_to_files(diff_text, fp.get("files") or [])
|
|
803
|
-
if re.search(fp["pattern"], scope):
|
|
804
|
-
verify["forbidden_pattern_hits"].append({
|
|
805
|
-
"pattern": fp["pattern"],
|
|
806
|
-
"severity": fp.get("severity", "warning"),
|
|
807
|
-
"description": fp.get("description", ""),
|
|
808
|
-
"scoped_to": fp.get("files") or "all",
|
|
809
|
-
})
|
|
810
|
-
|
|
811
|
-
# Deps added count (naive: count top-level added lines under dependencies keys)
|
|
812
|
-
try:
|
|
813
|
-
proc = subprocess.run(["git", "diff", "HEAD", "--", "package.json"],
|
|
814
|
-
cwd=work, capture_output=True, text=True)
|
|
815
|
-
in_deps = False
|
|
816
|
-
for line in (proc.stdout or "").splitlines():
|
|
817
|
-
if line.startswith("+ ") or line.startswith("- "):
|
|
818
|
-
continue
|
|
819
|
-
if '"dependencies"' in line or '"devDependencies"' in line:
|
|
820
|
-
in_deps = True
|
|
821
|
-
elif line.strip().startswith("}"):
|
|
822
|
-
in_deps = False
|
|
823
|
-
elif in_deps and line.startswith("+") and not line.startswith("+++"):
|
|
824
|
-
if re.search(r'"[^"]+"\s*:\s*"[^"]+"', line):
|
|
825
|
-
verify["deps_added"] += 1
|
|
826
|
-
except Exception:
|
|
827
|
-
pass
|
|
828
|
-
|
|
829
|
-
# Required / forbidden files
|
|
830
|
-
try:
|
|
831
|
-
with open(os.path.join(result_dir, "changed-files.txt")) as fh:
|
|
832
|
-
changed = [l.strip() for l in fh.read().splitlines() if l.strip()]
|
|
833
|
-
except Exception:
|
|
834
|
-
changed = []
|
|
835
|
-
verify["missing_required_files"] = [
|
|
836
|
-
f for f in expected.get("required_files", [])
|
|
837
|
-
if not os.path.exists(os.path.join(work, f))
|
|
838
|
-
]
|
|
839
|
-
verify["forbidden_files_present"] = [
|
|
840
|
-
f for f in expected.get("forbidden_files", []) if f in changed
|
|
841
|
-
]
|
|
842
|
-
|
|
843
|
-
total = len(verify["commands"])
|
|
844
|
-
passed = sum(1 for r in verify["commands"] if r.get("pass"))
|
|
845
|
-
verify["commands_passed"] = passed
|
|
846
|
-
verify["commands_total"] = total
|
|
847
|
-
verify["verify_score"] = (passed / total) if total else 1.0
|
|
848
|
-
|
|
849
|
-
for oracle_file in (
|
|
850
|
-
"oracle-scope-tier-a.json",
|
|
851
|
-
"oracle-scope-tier-b.json",
|
|
852
|
-
"oracle-test-fidelity.json",
|
|
853
|
-
):
|
|
854
|
-
oracle_path = os.path.join(result_dir, oracle_file)
|
|
855
|
-
try:
|
|
856
|
-
raw_oracle = loads_strict_json_object(pathlib.Path(oracle_path).read_text())
|
|
857
|
-
except (OSError, ValueError) as exc:
|
|
858
|
-
oracle_name = oracle_file.removesuffix(".json")
|
|
859
|
-
verify["oracle_findings"].append({
|
|
860
|
-
"oracle": oracle_name,
|
|
861
|
-
"type": "oracle-error",
|
|
862
|
-
"severity": "hard",
|
|
863
|
-
"verdict": "Deterministic oracle failed or emitted an invalid artifact",
|
|
864
|
-
"error": f"oracle artifact malformed or unreadable: {exc}",
|
|
865
|
-
})
|
|
866
|
-
verify["oracle_disqualifier"] = True
|
|
867
|
-
continue
|
|
868
|
-
data = raw_oracle
|
|
869
|
-
oracle_name = data.get("oracle") or oracle_file.removesuffix(".json")
|
|
870
|
-
if not isinstance(oracle_name, str) or not oracle_name:
|
|
871
|
-
oracle_name = oracle_file.removesuffix(".json")
|
|
872
|
-
oracle_error = data.get("error")
|
|
873
|
-
if isinstance(oracle_error, str) and oracle_error:
|
|
874
|
-
verify["oracle_findings"].append({
|
|
875
|
-
"oracle": oracle_name,
|
|
876
|
-
"type": "oracle-error",
|
|
877
|
-
"severity": "hard",
|
|
878
|
-
"verdict": "Deterministic oracle failed or emitted an invalid artifact",
|
|
879
|
-
"error": oracle_error,
|
|
880
|
-
})
|
|
881
|
-
verify["oracle_disqualifier"] = True
|
|
882
|
-
raw_findings = data.get("findings")
|
|
883
|
-
findings = raw_findings if isinstance(raw_findings, list) else []
|
|
884
|
-
for finding in findings:
|
|
885
|
-
if not isinstance(finding, dict):
|
|
886
|
-
continue
|
|
887
|
-
item = dict(finding)
|
|
888
|
-
item["oracle"] = oracle_name
|
|
889
|
-
verify["oracle_findings"].append(item)
|
|
890
|
-
if item.get("severity") in ("disqualifier", "hard", "flag"):
|
|
891
|
-
verify["oracle_disqualifier"] = True
|
|
892
|
-
|
|
893
|
-
verify["disqualifier"] = (
|
|
894
|
-
any(h["severity"] == "disqualifier" for h in verify["forbidden_pattern_hits"])
|
|
895
|
-
or verify["deps_added"] > verify["max_deps_added"]
|
|
896
|
-
or bool(verify["missing_required_files"])
|
|
897
|
-
or bool(verify["forbidden_files_present"])
|
|
898
|
-
or verify["oracle_disqualifier"]
|
|
899
|
-
)
|
|
900
|
-
|
|
901
|
-
json.dump(verify, open(os.path.join(result_dir, "verify.json"), "w"), indent=2)
|
|
902
|
-
PY
|
|
903
|
-
|
|
904
|
-
# Timing + aggregate
|
|
905
|
-
export INVOKE_EXIT WATCHDOG_FIRED
|
|
906
|
-
python3 - "$RESULT_DIR" "$FIXTURE" "$ARM" "$RUN_ID" "$T_END" "$ELAPSED" "$TIMEOUT" "$BENCH_ROOT/scripts" <<'PY'
|
|
907
|
-
import json, os, pathlib, sys
|
|
908
|
-
result_dir, fixture, arm, run_id = sys.argv[1:5]
|
|
909
|
-
t_end, elapsed, timeout = int(sys.argv[5]), int(sys.argv[6]), int(sys.argv[7])
|
|
910
|
-
|
|
911
|
-
sys.path.insert(0, sys.argv[8])
|
|
912
|
-
from pair_evidence_contract import loads_strict_json_object
|
|
913
|
-
|
|
914
|
-
timing = loads_strict_json_object(pathlib.Path(result_dir, "timing.json").read_text())
|
|
915
|
-
timing["end_epoch"] = t_end
|
|
916
|
-
timing["elapsed_seconds"] = elapsed
|
|
917
|
-
timing["timeout_seconds"] = timeout
|
|
918
|
-
# iter-0012: derive from watchdog signal, not elapsed wall time. Natural
|
|
919
|
-
# exits at-or-past the budget (budget == elapsed, or up to ~5s past due to
|
|
920
|
-
# SIGTERM grace) are no longer mislabeled as timeouts. Source of truth is
|
|
921
|
-
# WATCHDOG_FIRED, set in run-fixture.sh when TIMEOUT_FLAG existed post-wait.
|
|
922
|
-
timing["timed_out"] = os.environ.get("WATCHDOG_FIRED", "0") == "1"
|
|
923
|
-
json.dump(timing, open(os.path.join(result_dir, "timing.json"), "w"), indent=2)
|
|
924
|
-
|
|
925
|
-
def as_dict(value):
|
|
926
|
-
return value if isinstance(value, dict) else {}
|
|
927
|
-
|
|
928
|
-
verify = as_dict(loads_strict_json_object(pathlib.Path(result_dir, "verify.json").read_text()))
|
|
929
|
-
try:
|
|
930
|
-
with open(os.path.join(result_dir, "diff.patch")) as f: diff_size = len(f.read())
|
|
931
|
-
except Exception: diff_size = 0
|
|
932
|
-
try:
|
|
933
|
-
with open(os.path.join(result_dir, "changed-files.txt")) as f:
|
|
934
|
-
changed = [l for l in f.read().splitlines() if l.strip()]
|
|
935
|
-
except Exception:
|
|
936
|
-
changed = []
|
|
937
|
-
|
|
938
|
-
state = {}
|
|
939
|
-
state_path = os.path.join(result_dir, "run-archive", "pipeline.state.json")
|
|
940
|
-
if os.path.isfile(state_path):
|
|
941
|
-
state = as_dict(loads_strict_json_object(pathlib.Path(state_path).read_text()))
|
|
942
|
-
phases = as_dict(state.get("phases"))
|
|
943
|
-
verify_phase = as_dict(phases.get("verify"))
|
|
944
|
-
legacy_verify = as_dict(state.get("verify"))
|
|
945
|
-
sub_verdicts = verify_phase.get("sub_verdicts")
|
|
946
|
-
pair_trigger = verify_phase.get("pair_trigger") or legacy_verify.get("pair_trigger")
|
|
947
|
-
PAIR_VERDICTS = {"PASS", "PASS_WITH_ISSUES", "NEEDS_WORK", "BLOCKED", "FAIL"}
|
|
948
|
-
|
|
949
|
-
def has_pair_judge_verdict(sub_verdicts):
|
|
950
|
-
return isinstance(sub_verdicts, dict) and (
|
|
951
|
-
sub_verdicts.get("judge_codex") in PAIR_VERDICTS
|
|
952
|
-
or sub_verdicts.get("pair_judge") in PAIR_VERDICTS
|
|
953
|
-
)
|
|
954
|
-
|
|
955
|
-
pair_mode = has_pair_judge_verdict(sub_verdicts) or verify_phase.get("pair_mode") is True
|
|
956
|
-
|
|
957
|
-
invoke_exit = int(os.environ.get("INVOKE_EXIT", "0"))
|
|
958
|
-
plugin_contamination = False
|
|
959
|
-
plugin_contamination_reason = None
|
|
960
|
-
debug_path = os.path.join(result_dir, "claude-debug.log")
|
|
961
|
-
try:
|
|
962
|
-
with open(debug_path, errors="replace") as f:
|
|
963
|
-
debug_text = f.read()
|
|
964
|
-
except OSError:
|
|
965
|
-
debug_text = ""
|
|
966
|
-
if (
|
|
967
|
-
"Plugin autoupdate: checking installed plugins" in debug_text
|
|
968
|
-
or "Caching plugin from source:" in debug_text
|
|
969
|
-
or "Cloned repository from " in debug_text
|
|
970
|
-
or "Successfully cached plugin " in debug_text
|
|
971
|
-
or "Found 8 plugins (8 enabled" in debug_text
|
|
972
|
-
):
|
|
973
|
-
if "Plugin autoupdate: skipped (auto-updater disabled)" not in debug_text:
|
|
974
|
-
plugin_contamination = True
|
|
975
|
-
plugin_contamination_reason = "plugin_contamination"
|
|
976
|
-
|
|
977
|
-
invoke_failure = (
|
|
978
|
-
(invoke_exit not in (0,) and not timing["timed_out"])
|
|
979
|
-
or plugin_contamination
|
|
980
|
-
)
|
|
981
|
-
invoke_failure_reason = None
|
|
982
|
-
if plugin_contamination:
|
|
983
|
-
invoke_failure_reason = plugin_contamination_reason
|
|
984
|
-
elif invoke_failure:
|
|
985
|
-
transcript_path = os.path.join(result_dir, "transcript.txt")
|
|
986
|
-
haystack = ""
|
|
987
|
-
for path in (transcript_path, debug_path):
|
|
988
|
-
try:
|
|
989
|
-
with open(path, errors="replace") as f:
|
|
990
|
-
haystack += "\n" + f.read()
|
|
991
|
-
except OSError:
|
|
992
|
-
pass
|
|
993
|
-
if "You've hit your limit" in haystack or "rate_limit_error" in haystack:
|
|
994
|
-
invoke_failure_reason = "provider_limit"
|
|
995
|
-
|
|
996
|
-
result = {
|
|
997
|
-
"fixture": fixture,
|
|
998
|
-
"arm": arm,
|
|
999
|
-
"run_id": run_id,
|
|
1000
|
-
"disqualifier": verify.get("disqualifier", False),
|
|
1001
|
-
"oracle_disqualifier": verify.get("oracle_disqualifier", False),
|
|
1002
|
-
"oracle_findings_count": len(verify.get("oracle_findings", [])),
|
|
1003
|
-
"verify_score": verify.get("verify_score", 0.0),
|
|
1004
|
-
"commands_passed": verify.get("commands_passed", 0),
|
|
1005
|
-
"commands_total": verify.get("commands_total", 0),
|
|
1006
|
-
"diff_bytes": diff_size,
|
|
1007
|
-
"files_changed": len(changed),
|
|
1008
|
-
"elapsed_seconds": elapsed,
|
|
1009
|
-
"timed_out": timing["timed_out"],
|
|
1010
|
-
"environment_contamination": plugin_contamination,
|
|
1011
|
-
"environment_contamination_reason": plugin_contamination_reason,
|
|
1012
|
-
"invoke_exit": invoke_exit,
|
|
1013
|
-
"invoke_failure": invoke_failure,
|
|
1014
|
-
"invoke_failure_reason": invoke_failure_reason,
|
|
1015
|
-
"terminal_verdict": as_dict(phases.get("final_report")).get("verdict"),
|
|
1016
|
-
"verify_verdict": verify_phase.get("verdict"),
|
|
1017
|
-
"pair_trigger": pair_trigger,
|
|
1018
|
-
"pair_mode": pair_mode,
|
|
1019
|
-
}
|
|
1020
|
-
json.dump(result, open(os.path.join(result_dir, "result.json"), "w"), indent=2)
|
|
1021
|
-
print(json.dumps(result, indent=2))
|
|
1022
|
-
PY
|
|
1023
|
-
|
|
1024
|
-
echo "[run-fixture] done: $RESULT_DIR"
|