devlyn-cli 2.5.3 → 2.5.5

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 CHANGED
@@ -73,7 +73,7 @@ No silent fallbacks.
73
73
  - Fallbacks allowed only when widely accepted and harmless (CSS fallback fonts, CDN failover, image placeholders).
74
74
  - Silent `catch` blocks are bugs.
75
75
  - Logging is not user-visible error handling.
76
- - No engine-availability fallback is permitted for pair/risk-probe routes: if required Codex or Claude is unavailable, emit `BLOCKED:codex-unavailable` or `BLOCKED:claude-unavailable` with setup guidance. `--no-pair` and `--no-risk-probes` are explicit user opt-outs, not fallbacks.
76
+ - No engine-availability fallback for EXPLICITLY-requested routes (`--engine`, `--risk-probes`, `--pair-verify`): if the required engine is unavailable, emit `BLOCKED:codex-unavailable` or `BLOCKED:claude-unavailable` with setup guidance; never downgrade an explicit route to solo. Automatic high-risk escalations (auto risk-probes / auto VERIFY pair) are capability-gated: they activate only when the OTHER engine is available, else the run proceeds solo and reports the skip (route selection, not a fallback — keeps single-LLM users first-class). `--no-pair` and `--no-risk-probes` remain explicit opt-outs.
77
77
 
78
78
  ## Evidence Over Claim
79
79
 
package/CLAUDE.md CHANGED
@@ -6,7 +6,7 @@ devlyn-cli installs `/devlyn:ideate` (optional) and `/devlyn:resolve` (required)
6
6
 
7
7
  Seven rules govern every change. Cite them by name when a decision touches one.
8
8
 
9
- 1. **No workaround** — fix the root cause, never the symptom. Blocked patterns: `any`, `@ts-ignore`, silent `catch`, hardcoded fallback hiding a broken contract, config-level skip bypassing the real issue, helper script that routes around it. **Permitted exceptions** (widely-accepted defaults only): CSS fallback fonts, CDN failover, image placeholders. **No engine-availability fallback** for `/devlyn:resolve` pair/risk-probe routes — if Codex or Claude is required and unavailable, stop with `BLOCKED:codex-unavailable` or `BLOCKED:claude-unavailable` and setup guidance. `--no-pair` / `--no-risk-probes` are explicit user opt-outs, not fallbacks.
9
+ 1. **No workaround** — fix the root cause, never the symptom. Blocked patterns: `any`, `@ts-ignore`, silent `catch`, hardcoded fallback hiding a broken contract, config-level skip bypassing the real issue, helper script that routes around it. **Permitted exceptions** (widely-accepted defaults only): CSS fallback fonts, CDN failover, image placeholders. **No engine-availability fallback** for EXPLICITLY-requested `/devlyn:resolve` routes (`--engine`, `--risk-probes`, `--pair-verify`) — if the required engine is unavailable, stop with `BLOCKED:codex-unavailable` or `BLOCKED:claude-unavailable` and setup guidance; never downgrade an explicit route to solo. AUTOMATIC high-risk escalations (auto risk-probes / auto VERIFY pair) are capability-gated: they activate only when the OTHER engine is available; otherwise the run proceeds solo and reports the skip — route selection, not a fallback, and the reason single-LLM users stay first-class. `--no-pair` / `--no-risk-probes` remain explicit opt-outs.
10
10
  2. **No overengineering** — smallest change that closes the goal. New abstractions require an observed failure mode they prevent. Subtractive-first: ask "what can I delete instead?" before writing anything new.
11
11
  3. **No guesswork** — verify with the actual files, logs, diffs, and run output before forming conclusions. State the falsifiable prediction BEFORE the experiment; record raw results AFTER. Retroactive prediction edits are dishonest.
12
12
  4. **Worldclass** — code that survives review at a non-trivial codebase. Zero CRITICAL, zero HIGH security/design findings on the shippable path.
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bash
2
- # judge-opus-pass.sh — POST-RUN Opus 4.7 dual-judge sidecar.
2
+ # judge-opus-pass.sh — POST-RUN Opus dual-judge sidecar.
3
3
  #
4
- # Runs Opus 4.7 over the SAME sanitized blind prompts that judge.sh wrote
4
+ # Runs Opus (the Claude CLI's default model) over the SAME sanitized blind prompts that judge.sh wrote
5
5
  # (judge-prompt.txt), producing a parallel judge-opus.json alongside the
6
6
  # canonical judge.json. Does NOT modify judge.sh and does NOT change the
7
7
  # measurement contract for the in-flight run — this is a sidecar that adds
@@ -107,7 +107,7 @@ PY
107
107
  command -v claude >/dev/null 2>&1 || { echo "claude CLI not on PATH"; exit 1; }
108
108
 
109
109
  CLAUDE_CLI_VER=$(claude --version 2>/dev/null || echo "claude-cli unknown")
110
- JUDGE_MODEL_ALIAS="opus-4.7"
110
+ JUDGE_MODEL_ALIAS="opus-default"
111
111
 
112
112
  echo "[opus-judge] run-id=$RUN_ID cli=$CLAUDE_CLI_VER model=$JUDGE_MODEL_ALIAS"
113
113
 
@@ -336,8 +336,12 @@ if [ "$ARM" = "variant" ] || [ "$ARM" = "solo_claude" ] \
336
336
  || [ "$ARM" = "l2_gated" ] || [ "$ARM" = "l2_risk_probes" ] || [ "$ARM" = "l2_forced" ]; then
337
337
  case "$ARM" in
338
338
  solo_claude)
339
- ENGINE_CLAUSE="--engine claude"
340
- ENGINE_PROMPT_HINT="Run with \`--engine claude\` for every phase. Codex must not be invoked — the harness has blocked it at the binary layer for this run."
339
+ # L1 = pure solo by construction. --no-risk-probes --no-pair so a high-risk
340
+ # spec measures Claude-only solo deterministically instead of auto-escalating
341
+ # toward the (blocked) OTHER engine. Without these, a security/high-risk
342
+ # fixture auto-triggers the cross-engine path and the arm mis-measures L1.
343
+ ENGINE_CLAUSE="--engine claude --no-risk-probes --no-pair"
344
+ 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."
341
345
  ;;
342
346
  variant)
343
347
  ENGINE_CLAUSE="--engine claude --risk-probes"
@@ -14,10 +14,10 @@ This is also the load-bearing piece for **multi-LLM evolution**. When Qwen / Gem
14
14
 
15
15
  ## Format
16
16
 
17
- Each adapter is a single markdown file named `<model-id>.md` (e.g. `opus-4-7.md`, `gpt-5-5.md`). Structure:
17
+ Each adapter is a single markdown file named `<engine>.md`, matching the `--engine` selector value (e.g. `claude.md`, `codex.md`). Structure:
18
18
 
19
19
  ```markdown
20
- # <Model name> adapter
20
+ # <Engine> adapter
21
21
 
22
22
  > Source: <official-prompt-engineering-guide URL>
23
23
 
@@ -1,10 +1,10 @@
1
- # Claude Opus 4.7 adapter
1
+ # Claude Opus adapter
2
2
 
3
3
  > Source: <https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices>
4
4
 
5
5
  ## Identity
6
6
 
7
- You are Claude Opus 4.7 by Anthropic. Anthropic's prompt-engineering guide for this model governs your behavior on top of the canonical phase prompt below. When the canonical body and this header conflict on tactics, the canonical body wins on what to deliver; this header wins on how to deliver it.
7
+ You are Claude Opus by Anthropic. Anthropic's prompt-engineering guide for this model governs your behavior on top of the canonical phase prompt below. When the canonical body and this header conflict on tactics, the canonical body wins on what to deliver; this header wins on how to deliver it.
8
8
 
9
9
  ## Output discipline
10
10
 
@@ -16,7 +16,7 @@ When prompt maintenance adds examples for Claude, prefer concise positive exampl
16
16
 
17
17
  ## Tool-use posture
18
18
 
19
- You default to fewer tool calls than prior Claude generations. When the canonical body lists tools, use them when their result would change your answer. Make independent tool calls in parallel; chain only when one depends on another's output. Do not narrate "I'll now call X" preambles unless the canonical body requests progress updates.
19
+ When the canonical body lists tools, use them when their result would change your answer. Make independent tool calls in parallel; chain only when one depends on another's output. Do not narrate "I'll now call X" preambles unless the canonical body requests progress updates.
20
20
 
21
21
  ## Effort and autonomy
22
22
 
@@ -28,10 +28,10 @@ When the canonical body asks you to verify your output before declaring done ("s
28
28
 
29
29
  ## Anti-patterns
30
30
 
31
- You interpret instructions more literally than prior Claude versions. The official guide is explicit about three failure modes:
31
+ You interpret instructions literally and explicitly. The official guide is explicit about three failure modes:
32
32
 
33
33
  1. **Review-prompt self-filtering**: when the canonical body asks for findings, report every issue you find — including low-severity and low-confidence ones; do not filter for importance or confidence. The harness has a separate filter step.
34
- 2. **Subagent over-spawning**: do NOT spawn a subagent for work you can complete in a single response. Spawn only when the canonical body explicitly requests it OR when fanning out across independent items.
34
+ 2. **Subagent spawning**: do NOT spawn a subagent for work you can complete in a single response. Spawn only when the canonical body explicitly requests it OR when fanning out across independent items.
35
35
  3. **Overengineering**: do NOT add files, abstractions, error handling, validation, or "future flexibility" beyond what the spec asks. A bug fix doesn't need surrounding cleanup. The right complexity is the minimum needed for the current task.
36
36
 
37
37
  You do NOT need stronger imperatives ("CRITICAL!", "YOU MUST!") to follow rules. Normal phrasing is sufficient.
@@ -1,10 +1,10 @@
1
- # OpenAI GPT-5.5 adapter
1
+ # Codex (OpenAI) adapter
2
2
 
3
3
  > Source: <https://developers.openai.com/api/docs/guides/prompt-guidance?model=gpt-5.5>
4
4
 
5
5
  ## Identity
6
6
 
7
- You are GPT-5.5 by OpenAI. OpenAI's prompt-guidance for this model governs your behavior on top of the canonical phase prompt below. When the canonical body and this header conflict on tactics, the canonical body wins on what to deliver; this header wins on how to deliver it.
7
+ You are OpenAI's Codex model. OpenAI's prompt-guidance for this model governs your behavior on top of the canonical phase prompt below. When the canonical body and this header conflict on tactics, the canonical body wins on what to deliver; this header wins on how to deliver it.
8
8
 
9
9
  ## Output discipline
10
10
 
@@ -28,6 +28,6 @@ The official guide warns explicitly about carrying over instructions from older
28
28
 
29
29
  ## Prompt-maintenance cue
30
30
 
31
- When asked to improve a failed prompt, act as GPT-5.5 metaprompter for itself: name the observed failure, then propose the smallest instruction to add, remove, or relocate. Prefer subtractive changes before adding new rules; keep the canonical body model-neutral and put only GPT-specific tactics in this adapter.
31
+ When asked to improve a failed prompt, act as a metaprompter for itself: name the observed failure, then propose the smallest instruction to add, remove, or relocate. Prefer subtractive changes before adding new rules; keep the canonical body model-neutral and put only GPT-specific tactics in this adapter.
32
32
 
33
33
  Do not narrate internal deliberation. State results and decisions directly.
@@ -6,6 +6,11 @@ Used by `/devlyn:resolve` and `/devlyn:ideate`. One shared availability rule so
6
6
 
7
7
  Each skill resolves the effective engine from its own SKILL.md default plus any explicit `--engine` flag passed by the user. `/devlyn:resolve` also computes conditional pair/risk-probe requirements before the phase that needs the OTHER engine.
8
8
 
9
+ Engine requirements have two classes:
10
+
11
+ - **Explicit routes** — `--engine`, `--risk-probes`, `--pair-verify`. These are promises. If the required engine is unavailable, fail closed with `BLOCKED:<engine>-unavailable` and never downgrade to solo.
12
+ - **Automatic escalations** — auto high-risk risk-probes and auto VERIFY pair-JUDGE inferred from the spec. These are candidate routes, selected only when their preconditions hold, OTHER-engine availability included. If an auto candidate would fire but the OTHER engine is absent, do not select the cross-engine route: proceed solo and report the skipped escalation and its reason. This is route selection, not a fallback.
13
+
9
14
  When a run or phase requires Codex, before spawning that phase:
10
15
 
11
16
  1. Check if the Codex CLI is installed: `command -v codex >/dev/null 2>&1` (or equivalent bash test).
@@ -18,7 +23,7 @@ When a run or phase requires Claude, before spawning that phase:
18
23
  2. On failure -> set the current phase/run verdict to `BLOCKED:claude-unavailable` and show setup guidance: install/configure Claude Code, verify `claude --version` where available, then rerun.
19
24
  3. On success -> proceed.
20
25
 
21
- Never prompt the user mid-pipeline. Missing required engines are explicit BLOCKED states, not silent fallbacks.
26
+ Never prompt the user mid-pipeline. Missing engines for explicit routes are BLOCKED states, not silent fallbacks. Missing OTHER engines for automatic escalations are reported solo-skips, not fallbacks — the auto route was never selected.
22
27
 
23
28
  Per-skill defaults: `/devlyn:resolve` uses Claude for PLAN/IMPLEMENT; VERIFY may invoke the OTHER engine when its pair-JUDGE trigger fires. `/devlyn:ideate` defaults to Claude; `--engine` selects the elicitation/normalization adapter, not an automatic cross-model challenge phase. Any future ideate read-only critique must follow `_shared/codex-config.md` isolation rules. Each SKILL.md flag block is source of truth for that skill's default.
24
29
 
@@ -33,7 +33,12 @@ VERDICT_RANK = {
33
33
  "BLOCKED": 3,
34
34
  }
35
35
  RANK_VERDICT = {0: "PASS", 1: "PASS_WITH_ISSUES", 2: "NEEDS_WORK", 3: "BLOCKED"}
36
- ALLOWED_PAIR_SKIP_REASONS = {"user_no_pair", "mechanical_blocker", "primary_judge_blocker"}
36
+ ALLOWED_PAIR_SKIP_REASONS = {
37
+ "user_no_pair",
38
+ "mechanical_blocker",
39
+ "primary_judge_blocker",
40
+ "auto_pair_other_engine_unavailable",
41
+ }
37
42
  KNOWN_PAIR_TRIGGER_REASONS = {
38
43
  "mode.verify-only",
39
44
  "mode.pair-verify",
@@ -504,10 +509,28 @@ def pair_trigger_skip_contract_violation(
504
509
  "id": "verify-pair-trigger-skipped-reason-unsupported",
505
510
  "message": (
506
511
  "pair_trigger.skipped_reason must be user_no_pair, "
507
- "mechanical_blocker, primary_judge_blocker, or null."
512
+ "mechanical_blocker, primary_judge_blocker, "
513
+ "auto_pair_other_engine_unavailable, or null."
508
514
  ),
509
515
  "file": "pipeline.state.json",
510
516
  }
517
+ if skipped_reason == "auto_pair_other_engine_unavailable":
518
+ # alpha+ capability-gating: an AUTOMATIC pair trigger may skip to solo
519
+ # VERIFY when the OTHER engine is unavailable (single-LLM users stay
520
+ # first-class). An EXPLICIT --pair-verify route is a promise and must
521
+ # BLOCK on an unavailable engine, never skip — enforce that here so the
522
+ # auto-skip cannot launder an explicit request.
523
+ pair_verify = state.get("pair_verify") if isinstance(state, dict) else None
524
+ if pair_verify is True:
525
+ return {
526
+ "id": "verify-pair-trigger-auto-skip-explicit-conflict",
527
+ "message": (
528
+ "pair_trigger skipped_reason auto_pair_other_engine_unavailable is "
529
+ "only valid for an automatic trigger; an explicit --pair-verify run "
530
+ "must BLOCK on an unavailable OTHER engine, not skip."
531
+ ),
532
+ "file": "pipeline.state.json",
533
+ }
511
534
  if skipped_reason == "user_no_pair":
512
535
  risk_profile = state.get("risk_profile") if isinstance(state, dict) else {}
513
536
  if not isinstance(risk_profile, dict) or risk_profile.get("pair_default_enabled") is not False:
@@ -28,7 +28,7 @@ Read `_shared/runtime-principles.md` (Subtractive-first / Goal-locked / No-worka
28
28
  </harness_principles>
29
29
 
30
30
  <engine_routing>
31
- Default engine: Claude. The per-engine adapter from `_shared/adapters/<model>.md` is prepended to the elicitation prompt so the model honors its own official prompt-engineering guidance during the Q&A.
31
+ Default engine: Claude. The per-engine adapter from `_shared/adapters/<engine>.md` is prepended to the elicitation prompt so the model honors its own official prompt-engineering guidance during the Q&A.
32
32
  </engine_routing>
33
33
 
34
34
  <modes>
@@ -17,7 +17,7 @@ Long-horizon agentic work; context auto-compacts. State lives in `.devlyn/pipeli
17
17
  Hands-free. Measured by how far we get without human intervention.
18
18
 
19
19
  1. Do not prompt the user mid-pipeline. When tempted to ask, pick the safe default, proceed, and log it in the final report.
20
- 2. Engine availability: follow `_shared/engine-preflight.md`. When a selected or conditionally-required engine is unavailable, fail closed with `BLOCKED:<engine>-unavailable` and setup guidance; do not convert a pair-required or explicitly requested engine into a solo run.
20
+ 2. Engine availability: follow `_shared/engine-preflight.md`. Two classes. **Explicit cross-engine routes** (`--engine`, `--risk-probes`, `--pair-verify`) are promises: if the required engine is unavailable, fail closed with `BLOCKED:<engine>-unavailable` and setup guidance — never downgrade an explicitly requested route to solo. **Automatic cross-engine escalations** (auto high-risk risk-probes, auto VERIFY pair-JUDGE) are candidate routes selected only when their preconditions hold, including OTHER-engine availability. If an auto candidate would fire but the OTHER engine is absent, do not select the cross-engine route — proceed solo and report the skipped escalation and its reason. Skipping an unselected optional route is route selection, not a fallback; an explicitly requested route is never skipped this way.
21
21
  3. Phases run in declared order. No extra phases.
22
22
  4. Orchestrator does not write code. It parses input, spawns phases, reads state, branches on verdicts, emits the report.
23
23
  5. Continue by default. Halt only on (a) unrecoverable subagent failure, (b) IMPLEMENT producing zero code changes, (c) BUILD_GATE or VERIFY fix-loop exhausting `max_rounds`.
@@ -28,7 +28,7 @@ Every phase reads `_shared/runtime-principles.md` (Subtractive-first / Goal-lock
28
28
  </harness_principles>
29
29
 
30
30
  <engine_routing>
31
- Each phase routes to an engine and prepends the per-engine adapter header from `_shared/adapters/<model>.md` to the canonical phase body. Adapter is the per-model delta (Anthropic Opus 4.7 guide for Claude, OpenAI GPT-5.5 guide for Codex). Canonical body is engine-agnostic.
31
+ Each phase routes to an engine and prepends the per-engine adapter header from `_shared/adapters/<engine>.md` (e.g. `claude.md`, `codex.md`) to the canonical phase body. Adapter is the per-model delta (Anthropic's Opus prompt-engineering guide for Claude, OpenAI's GPT-5.5 guide for Codex). Canonical body is engine-agnostic.
32
32
 
33
33
  - Claude phases: spawn `Agent` (`mode: "bypassPermissions"`); prompt = adapter-header + canonical-body + task-context.
34
34
  - Codex phases: shell out via `bash _shared/codex-monitored.sh` with the same compounded prompt. The wrapper closes stdin and emits a heartbeat. No MCP.
@@ -76,7 +76,7 @@ Once `state.implement_passed_sha` is non-null (PHASE 2 returned and produced a d
76
76
  - **Spec**: validate spec exists. If sibling `spec.expected.json` exists, run `--check-expected <expected-path>` to validate both the expected contract, sibling spec `complexity` frontmatter, and any present actionable solo-headroom hypothesis; if the spec has a solo-headroom hypothesis, its observable command must match `spec.expected.json.verification_commands[].cmd`. Then stage `.devlyn/spec-verify.json` from `verification_commands`. Otherwise run `--check <spec-path>` to validate the legacy inline carrier plus supported `complexity` frontmatter and any present actionable solo-headroom hypothesis; if the spec uses an inline `## Verification` JSON carrier, any solo-headroom hypothesis command must match that carrier's `verification_commands[].cmd`. Then stage from the legacy inline carrier. Compute `state.source.spec_sha256`.
77
77
  - **Verify-only**: skip to PHASE 5 with `state.source.spec_path` set, the supplied diff captured at `.devlyn/external-diff.patch`.
78
78
 
79
- 5. Compute `state.risk_profile` from the user goal plus spec/criteria text. Mark `high_risk: true` when the work touches any of: auth/authz, permissions, security, token/session, payment/money/billing/invoice/pricing/tax/ledger, persistence/data mutation/deletion/migration, idempotency/replay/duplicate, API/webhook/raw-body/signature, allocation/scheduling/inventory/rollback/transaction, or explicit error-priority/output-shape contracts. If high-risk and `--no-risk-probes` is absent, set `risk_probes_enabled: true`; explicit `--risk-probes` also sets it true. If `--no-pair` is present, set `pair_default_enabled: false`. Add concise string reasons for the classification, but do not use reasons as substitutes for the boolean fields.
79
+ 5. Compute `state.risk_profile` from the user goal plus spec/criteria text. Mark `high_risk: true` when the work touches any of: auth/authz, permissions, security, token/session, payment/money/billing/invoice/pricing/tax/ledger, persistence/data mutation/deletion/migration, idempotency/replay/duplicate, API/webhook/raw-body/signature, allocation/scheduling/inventory/rollback/transaction, or explicit error-priority/output-shape contracts. Explicit `--risk-probes` sets `risk_probes_enabled: true` unconditionally (the OTHER engine is then a promise; unavailability blocks at PHASE 1.5). If high-risk is detected and `--no-risk-probes` is absent, this is an AUTO escalation: set `risk_probes_enabled: true` only when the OTHER engine is available (for a Claude run, `command -v codex`); if it is unavailable, leave `risk_probes_enabled: false`, keep `high_risk: true`, and append a reason such as `auto-risk-probes skipped: codex-unavailable` so the report shows it. `--no-risk-probes` disables only the auto escalation; a single-engine run does not need it to proceed. If `--no-pair` is present, set `pair_default_enabled: false`. Add concise string reasons for the classification, but do not use reasons as substitutes for the boolean fields.
80
80
 
81
81
  6. Announce one line: `resolve starting — run <run_id> — engine <engine> — mode <mode> — complexity <complexity-or-na> — pair <conditional|disabled> — risk_probes <on|off>`.
82
82
 
@@ -98,9 +98,12 @@ After return:
98
98
 
99
99
  Skip unless `--risk-probes` is set OR `state.risk_profile.risk_probes_enabled`
100
100
  is true. This phase is findings-as-executable-checks, not a second plan and not
101
- debate. If this phase is required and the OTHER engine is unavailable, halt with
101
+ debate. When it runs, the OTHER engine is required: if unavailable, halt with
102
102
  `BLOCKED:codex-unavailable` or `BLOCKED:claude-unavailable` plus setup guidance;
103
- do not silently continue without probes.
103
+ do not silently continue without probes. Reaching this halt means the route was
104
+ explicitly requested (`--risk-probes`) — an auto high-risk escalation toward an
105
+ unavailable OTHER engine was already gated off in PHASE 0 by leaving
106
+ `risk_probes_enabled: false`, so a single-engine high-risk run proceeds solo here.
104
107
 
105
108
  Engine: OTHER engine from PHASE 2's selected IMPLEMENT engine. Prompt body:
106
109
  `references/phases/probe-derive.md`.
@@ -245,10 +248,14 @@ After MECHANICAL and the primary JUDGE finish, compute `pair_trigger = { eligibl
245
248
 
246
249
  The `--engine` flag never suppresses this rule. Explicit `--engine claude`
247
250
  means "Claude is the primary judge"; it does not mean "do not run Codex as the
248
- second pair judge." The only valid skip reasons after a non-empty eligible
249
- trigger are deterministic MECHANICAL HIGH/CRITICAL blockers or an explicit
250
- `--no-pair`. Engine unavailability is a `BLOCKED:<engine>-unavailable` verdict,
251
- not a skip reason.
251
+ second pair judge." The valid skip reasons after a non-empty eligible
252
+ trigger are deterministic MECHANICAL HIGH/CRITICAL blockers, an explicit
253
+ `--no-pair`, or — when none of the applicable reasons is `mode.pair-verify` (i.e.
254
+ every reason is automatic) — the OTHER engine being unavailable. In that
255
+ auto-only-unavailable case, set `eligible: false`, leave `reasons` empty, set
256
+ `skipped_reason: "auto_pair_other_engine_unavailable"`, and run solo VERIFY.
257
+ Explicit `--pair-verify` (`mode.pair-verify`) with the OTHER engine absent is a
258
+ promise: it stays `BLOCKED:<engine>-unavailable` and is never skipped.
252
259
 
253
260
  Pair-mode JUDGE: spawn a second Agent with the OTHER engine's adapter; the second judge is a bounded adversarial complement, not a duplicate broad audit. The primary judge owns broad coverage; pair-JUDGE targets the two highest-risk explicit `## Verification` bullets that cross state mutation, all-or-nothing rollback, ordering, idempotency, auth, or error-priority clauses. If the spec includes a solo-headroom hypothesis, one of those targeted probes must exercise that hypothesis with the visible command/input shape and full externally visible result, using the hypothesis's backticked observable command as its command anchor before adding bounded input variations. It must not read `.claude/skills`, `.codex/skills`, `CLAUDE.md`, `AGENTS.md`, or other harness docs unless the orchestrator pasted a specific excerpt into the prompt. It may use only the spec, diff, implementation files, tests, and the repo's existing CLI/API/test runner. It may execute at most two targeted probes before first output, and each probe must compare the full externally visible result (exit/stdout/stderr plus full parsed output object, including accepted/scheduled rows, rejected rows, and remaining state when present), not just a single property. When the spec names exact keys, row shapes, JSON object shape, or an exact error body, pair-JUDGE must compare parsed key sets/deep equality so aliased keys, missing keys, and extra keys are verdict-binding failures, and it must construct inputs with the spec's visible key names. For priority/stateful specs, at least one probe must include an earlier input entity that would succeed under input-order processing, a later higher-priority entity that consumes or blocks the critical resource, and a failure/blocked/rollback edge that determines a later entity's state. For cart/pricing specs where visible verification combines duplicate items, line promotions, tax, coupon, and shipping, the success-path probe must include interleaved duplicates plus taxable and non-taxable items and assert full output rows. Scope qualifiers are binding: pair-JUDGE must not reinterpret `inside a warehouse`, `per resource`, or line-scoped rules as global rules. When both priority ordering and rollback/blocked-interval behavior appear in the spec, this dominance-loss probe is mandatory and comes before any other probe: an earlier lower-priority entity that would succeed alone or under input-order processing must lose because a later higher-priority entity is processed first; a failed/blocked middle entity must not corrupt later state; and the assertion must cover complete accepted/scheduled and rejected output ordering. It must stop and emit JSONL immediately on the first verdict-binding finding, and must emit PASS immediately if both probes plus static scope/dependency checks pass. Both judgments merge with the rule "any HIGH/CRITICAL finding either model surfaces is verdict-binding; high-confidence MEDIUM findings are also verdict-binding when they identify a concrete behavioral regression against the spec, public contract, or existing test contract." Cross-model disagreement on advisory lower-severity findings is logged but does not change the verdict. If MECHANICAL or the primary JUDGE has a verdict-binding finding, skip the second judge and record `pair_judge: null`; the fix loop needs the blocker, not duplicate review.
254
261
 
@@ -1,6 +1,6 @@
1
1
  # PHASE 1 — PLAN (canonical body)
2
2
 
3
- The per-engine adapter header from `_shared/adapters/<model>.md` is prepended at runtime. This file is engine-agnostic.
3
+ The per-engine adapter header from `_shared/adapters/<engine>.md` is prepended at runtime. This file is engine-agnostic.
4
4
 
5
5
  <role>
6
6
  You translate a spec or generated criteria into a concrete plan: the file list to touch, the risks the implementation must navigate, and a verbatim restatement of what acceptance requires. The plan is the contract IMPLEMENT executes against.
@@ -148,18 +148,24 @@ reasons and at least one reason: `mode.verify-only`, `complexity.high`, `complex
148
148
  The `--engine` flag never disables this rule. Explicit `--engine claude` means
149
149
  Claude is the primary judge; if pair-mode triggers, Codex is still the mandatory
150
150
  OTHER-engine judge. Do not record "explicit --engine claude" as a skip reason.
151
- The only valid skip reasons after a non-empty eligible trigger are deterministic
152
- MECHANICAL HIGH/CRITICAL blockers or an explicit `--no-pair`. Engine
153
- unavailability is not a skip reason; it is `BLOCKED:<engine>-unavailable`.
151
+ The valid skip reasons after a non-empty eligible trigger are deterministic
152
+ MECHANICAL HIGH/CRITICAL blockers, an explicit `--no-pair`, or — when none of the
153
+ applicable reasons is `mode.pair-verify` (every reason is automatic) — the OTHER
154
+ engine being unavailable. Explicit `--pair-verify` with the OTHER engine absent
155
+ is a promise and stays `BLOCKED:<engine>-unavailable`, never a skip.
154
156
 
155
157
  Before invoking the OTHER-engine judge, run the shared availability pre-flight
156
- for that engine. If Codex is required and unavailable, set VERIFY to
157
- `BLOCKED:codex-unavailable` and tell the user to install/configure the Codex CLI,
158
- run the current Codex auth/login flow, verify `codex --version`, and rerun. If
159
- Claude is required and the host cannot spawn a Claude agent, set VERIFY to
160
- `BLOCKED:claude-unavailable` and tell the user to install/configure Claude Code,
161
- verify `claude --version` where available, and rerun. Do not convert this to a
162
- solo pass, and do not synthesize pair findings.
158
+ for that engine. If the route is explicit (`--pair-verify`) and Codex is required
159
+ and unavailable, set VERIFY to `BLOCKED:codex-unavailable` and tell the user to
160
+ install/configure the Codex CLI, run the current Codex auth/login flow, verify
161
+ `codex --version`, and rerun. If Claude is required and the host cannot spawn a
162
+ Claude agent, set VERIFY to `BLOCKED:claude-unavailable` and tell the user to
163
+ install/configure Claude Code, verify `claude --version`, and rerun. For an
164
+ explicit route, do not convert this to a solo pass and do not synthesize pair
165
+ findings. When the trigger was AUTO-only and the OTHER engine is unavailable, set
166
+ `eligible: false`, `reasons: []`, `skipped_reason:
167
+ "auto_pair_other_engine_unavailable"`, run solo VERIFY, and report the skipped
168
+ auto escalation — route selection, not a fallback.
163
169
 
164
170
  When eligible and the orchestrator spawns a second VERIFY agent with the OTHER engine's adapter, both judgments are merged:
165
171
  - Any HIGH/CRITICAL finding either model surfaces is verdict-binding.
@@ -5,7 +5,7 @@ allowed-tools: Read, Grep, Glob, Edit, Write
5
5
  ---
6
6
 
7
7
  <!--
8
- Version: 2026-01 | Claude 4.x (Opus 4.5, Sonnet 4.5, Haiku 4.5)
8
+ Version: 2026-05 | Claude 4.x (Opus 4.8, Sonnet 4.6, Haiku 4.5)
9
9
  Source: https://platform.claude.com/docs/build-with-claude/prompt-engineering/claude-4-best-practices
10
10
  -->
11
11
 
@@ -103,13 +103,13 @@ explicitly requested. Incorporate information naturally into sentences.
103
103
  START: Which Claude model?
104
104
  │
105
105
  ├─► Complex reasoning, multi-step analysis, or highest quality?
106
- │ → Opus 4.5 (claude-opus-4-5-20250929)
106
+ │ → Opus 4.8 (claude-opus-4-8)
107
107
  │
108
108
  ├─► Balance of quality, speed, and cost?
109
- │ → Sonnet 4.5 (claude-sonnet-4-5-20250929)
109
+ │ → Sonnet 4.6 (claude-sonnet-4-6)
110
110
  │
111
111
  └─► Fast responses, simple tasks, cost-sensitive?
112
- → Haiku 4.5 (claude-haiku-4-5-20250929)
112
+ → Haiku 4.5 (claude-haiku-4-5-20251001)
113
113
  ```
114
114
 
115
115
  ---
@@ -152,7 +152,7 @@ results, execute sequentially. Never use placeholders for missing parameters.
152
152
  |--------------|--------------|-----|
153
153
  | "Can you suggest changes?" | Claude will only suggest, not implement | "Change this function to..." |
154
154
  | "Think about this carefully" | Triggers thinking sensitivity | "Consider this carefully" |
155
- | "CRITICAL: You MUST..." | Opus 4.5 may over-trigger | "Use this when..." |
155
+ | "CRITICAL: You MUST..." | Claude may over-trigger | "Use this when..." |
156
156
  | Vague instructions | Literal interpretation | Add explicit detail |
157
157
  | No context for rules | Claude can't generalize | Explain WHY behind rules |
158
158
  | Examples with unwanted patterns | Claude mimics examples precisely | Remove unwanted behaviors from examples |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devlyn-cli",
3
- "version": "2.5.3",
3
+ "version": "2.5.5",
4
4
  "description": "AI development toolkit for Claude Code — ideate, resolve, and ship with context engineering and agent orchestration",
5
5
  "homepage": "https://github.com/fysoul17/devlyn-cli#readme",
6
6
  "bin": {
@@ -75,8 +75,8 @@ devlyn:resolve/references/phases/cleanup.md
75
75
  devlyn:resolve/references/phases/verify.md
76
76
  _shared/expected.schema.json
77
77
  _shared/adapters/README.md
78
- _shared/adapters/opus-4-7.md
79
- _shared/adapters/gpt-5-5.md
78
+ _shared/adapters/claude.md
79
+ _shared/adapters/codex.md
80
80
  _shared/codex-config.md
81
81
  _shared/codex-monitored.sh
82
82
  _shared/engine-preflight.md
@@ -1586,29 +1586,29 @@ fi
1586
1586
  section "Check 10d: Prompt adapters cite official model guidance"
1587
1587
  adapter_missing=0
1588
1588
  if ! grep -Fq 'https://developers.openai.com/api/docs/guides/prompt-guidance?model=gpt-5.5' \
1589
- config/skills/_shared/adapters/gpt-5-5.md; then
1590
- bad "gpt-5-5 adapter missing official OpenAI prompt guidance URL"
1589
+ config/skills/_shared/adapters/codex.md; then
1590
+ bad "codex adapter missing official OpenAI prompt guidance URL"
1591
1591
  adapter_missing=1
1592
1592
  fi
1593
1593
  if ! grep -Fq 'https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices' \
1594
- config/skills/_shared/adapters/opus-4-7.md; then
1595
- bad "opus-4-7 adapter missing official Claude prompting best-practices URL"
1594
+ config/skills/_shared/adapters/claude.md; then
1595
+ bad "claude adapter missing official Claude prompting best-practices URL"
1596
1596
  adapter_missing=1
1597
1597
  fi
1598
1598
  for pattern in 'Use Markdown only where it carries structure' 'metaprompter for itself'; do
1599
- if ! grep -Fq "$pattern" config/skills/_shared/adapters/gpt-5-5.md; then
1600
- bad "gpt-5-5 adapter missing official-guidance tactic: $pattern"
1599
+ if ! grep -Fq "$pattern" config/skills/_shared/adapters/codex.md; then
1600
+ bad "codex adapter missing official-guidance tactic: $pattern"
1601
1601
  adapter_missing=1
1602
1602
  fi
1603
1603
  done
1604
1604
  for pattern in 'high` or `xhigh` effort' 'report every issue you find' 'do not filter for importance or confidence' 'prefer concise positive examples' '<example>'; do
1605
- if ! grep -Fq "$pattern" config/skills/_shared/adapters/opus-4-7.md; then
1606
- bad "opus-4-7 adapter missing official-guidance tactic: $pattern"
1605
+ if ! grep -Fq "$pattern" config/skills/_shared/adapters/claude.md; then
1606
+ bad "claude adapter missing official-guidance tactic: $pattern"
1607
1607
  adapter_missing=1
1608
1608
  fi
1609
1609
  done
1610
1610
  for file in config/skills/devlyn:resolve/SKILL.md config/skills/devlyn:ideate/SKILL.md; do
1611
- if ! grep -Fq '_shared/adapters/<model>.md' "$file"; then
1611
+ if ! grep -Fq '_shared/adapters/<engine>.md' "$file"; then
1612
1612
  bad "$file — missing per-engine adapter injection contract"
1613
1613
  adapter_missing=1
1614
1614
  fi