devlyn-cli 3.1.2 → 3.2.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 +6 -6
- package/CLAUDE.md +7 -7
- package/README.md +34 -13
- package/bin/devlyn.js +44 -65
- package/bin/instruction-templates.json +82 -0
- package/bin/instructions.js +187 -0
- package/config/skills/_shared/adapters/claude.md +1 -5
- package/config/skills/_shared/adapters/codex.md +1 -5
- package/config/skills/_shared/adapters/omp.md +0 -4
- package/config/skills/_shared/archive_run.py +5 -1
- package/config/skills/_shared/codex-config.md +3 -14
- package/config/skills/_shared/engine-preflight.md +3 -3
- package/config/skills/_shared/expected.schema.json +2 -2
- package/config/skills/_shared/platform-support.py +4 -1
- package/config/skills/_shared/resolve-bootstrap.py +22 -2
- package/config/skills/_shared/role-config.py +14 -2
- package/config/skills/_shared/spec-verify-check.py +427 -101
- package/config/skills/_shared/state-phase-write.py +497 -49
- package/config/skills/_shared/task-complete.py +46 -5
- package/config/skills/_shared/terminal-claim-check.py +2 -2
- package/config/skills/devlyn:ideate/SKILL.md +1 -1
- package/config/skills/devlyn:ideate/references/from-spec-mode.md +1 -1
- package/config/skills/devlyn:ideate/references/spec-template.md +2 -2
- package/config/skills/devlyn:resolve/SKILL.md +29 -51
- package/config/skills/devlyn:resolve/references/free-form-mode.md +2 -2
- package/config/skills/devlyn:resolve/references/phases/build-gate.md +8 -7
- package/config/skills/devlyn:resolve/references/phases/cleanup.md +5 -11
- package/config/skills/devlyn:resolve/references/phases/implement.md +1 -0
- package/config/skills/devlyn:resolve/references/phases/plan.md +3 -3
- package/config/skills/devlyn:resolve/references/state-schema.md +10 -9
- package/package.json +2 -1
- package/scripts/lint-skills.sh +14 -4
- package/scripts/test-owner-phases.py +193 -0
package/AGENTS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Codex Project Instructions
|
|
2
2
|
|
|
3
|
-
devlyn-cli installs
|
|
3
|
+
devlyn-cli installs planning and full-pipeline skills alongside the execution contract below. Codex CLI reads this file when invoked inside a project that has it. The principles are non-negotiable on every change.
|
|
4
4
|
|
|
5
5
|
## North Star
|
|
6
6
|
|
|
@@ -27,22 +27,22 @@ Three discipline rules govern HOW the principles are applied:
|
|
|
27
27
|
## Quick Start
|
|
28
28
|
|
|
29
29
|
```text
|
|
30
|
-
|
|
30
|
+
inspect intent -> direct work or full resolve -> ship
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
- `/devlyn:ideate` (optional) — unstructured idea → `docs/specs/<id>/spec.md` + `spec.expected.json`. Modes: default Q&A, `--quick` (autonomous-pipeline-safe), `--from-spec <path>`, `--project` (multi-feature).
|
|
34
|
-
- `/devlyn:resolve` —
|
|
34
|
+
- `/devlyn:resolve` — full pipeline for work selected by the conversational-entry rules below. Free-form goal, `--spec <path>`, or `--verify-only <ref> --spec <path>`. Phases: PLAN → IMPLEMENT → BUILD_GATE → CLEANUP → VERIFY (fresh-subagent, findings-only).
|
|
35
35
|
- `/devlyn:design-ui` — required creative UI exploration surface. Spawns a 5-specialist design team (Creative Director, Product Designer, Visual Designer, Interaction Designer, Accessibility Designer) to generate N (default 5) portfolio-worthy HTML/CSS samples. The optional `/devlyn:reap` companion lives in `optional-skills/` and installs only when the user opts in.
|
|
36
36
|
|
|
37
37
|
Each skill's `SKILL.md` is the source of truth for flags and workflow. Do not duplicate.
|
|
38
38
|
|
|
39
39
|
Engine roles: orchestrator = whichever CLI the user opened (this contract is symmetric with CLAUDE.md. If you are Codex orchestrating `/devlyn:resolve`, the phase machinery is mandatory regardless of task size; if you will not run it, say so explicitly and stop — do not silently degrade to ad-hoc execution); legacy executor (with optional separate worker/primary/pair profiles) uses the canonical skill's orchestrator-supported default, overridable per run with `--engine <name>` or durably via machine-local `.devlyn/engines.json` `{"executor": "<name>", "pair_judge_priority": ["<name>", ...]}`; PLAN is orchestrator-fixed and never inherits `--engine` or the executor pin; pair judge = first available OTHER engine, default for VERIFY whenever available; risk probes remain conditional and --no-pair opts out. Pins fail closed (`BLOCKED:<engine>-unavailable` / `BLOCKED:invalid-engine-config`); new engines plug in by shipping `_shared/adapters/<name>.md`. `/devlyn:engines` (no args) shows the role table + detected engines; `executor <name>` / `pair <name>,...` / `clear` manage the pins. The executor pin binds the orchestrator in plain conversation too, not only inside a skill run: when you would implement directly and executor is pinned to a non-default engine, route that work through the pin — via `/devlyn:resolve` (reads it at PHASE 0) or by delegating to that engine; no pin / no file → use the canonical skill's orchestrator-supported default. The pair-judge pin stays pipeline-scoped. `/devlyn:engines role` configures explicit engine/model/effort for supported worker and judge routes; `/devlyn:resolve --role-config <path>` overrides roles for one run. Canonical skills define precedence, evidence and unsupported-route errors; absent profiles preserve existing defaults.
|
|
40
40
|
|
|
41
|
-
Conversational entry: Before
|
|
41
|
+
Conversational entry: Before loading a workflow or writing files, inspect the requested change and relevant callers/tests. Quoted phase names, past logs and skill-file paths are context, not an instruction to invoke that workflow; follow the current user request. Default to direct execution when inspection makes the requested behavior, affected boundaries and verification tractable in the current context, including bounded multi-file work. Preserve requested behavior, scope, explicit constraints and the executor pin; make scoped edits, run required checks, review the final diff, and report changes with evidence. One concise route/check explanation suffices; ordinary direct work needs no spec, pipeline state, phase workers or extra approval. For direct/full/queue work, the outer owner reads `references/task-completion.md` relative to the installed `devlyn:resolve` skill's directory: prospective task-branch ownership (linked worktree optional), scoped commit acceptance, then PR/merge and recoverable owned-resource cleanup after required archive/queue commits. Local-only/no-push wins; delivery pending/failure stays separate from product verification.
|
|
42
42
|
|
|
43
|
-
Use full `/devlyn:resolve`
|
|
43
|
+
Use full `/devlyn:resolve` automatically only when inspection identifies interacting requirements or verification work too complex to manage reliably in the current context, such as coupled durable state, concurrent ownership and failure recovery across boundaries. Name the concrete interaction or verification gap. Domain labels (security/auth/payment/persistence/concurrency/API), file count and a spec document alone do not trigger it. Investigate or clarify missing intent/access first; a pipeline cannot supply them. Direct work still requires risk-proportionate checks and independent review for consequential changes. Explicit resolve (even small), explicit spec-mode workflows and queue drains retain all canonical phases, independent verification, pins and failure handling. If the full-route condition emerges mid-edit, carry the existing delta into its scope/evidence; do not reset the baseline or reconfirm existing authorization.
|
|
44
44
|
|
|
45
|
-
Full-route handoff + loop engineering: the orchestrating model — not the user — invokes the skills. `/devlyn:queue` fronts the intent queue (`docs/specs/queue.md`): no args = status, `add <intent>`, `drain` = serial unattended drain per the contract below.
|
|
45
|
+
Full-route handoff + loop engineering: the orchestrating model — not the user — invokes the skills. `/devlyn:queue` fronts the intent queue (`docs/specs/queue.md`): no args = status, `add <intent>`, `drain` = serial unattended drain per the contract below. Work selected for full resolve is written to `docs/specs/<id>/spec.md` (always a spec file — the user's reviewed contract; free-form large assumes-and-logs instead of halting, zero-scope-signal goals still halt to ideate), summarized once for user review, then run hands-free via `--spec`. Outer loop per task: before the first full run, commit the scoped queue-item delta (when applicable) and linked spec bundle; findings-backed verdicts (NEEDS_WORK, verify/build-gate exhaustion) get a committed spec amendment before re-run, max 3 iterations; infrastructure / invalid-input / engine-availability / implement-empty BLOCKED verdicts surface immediately. Unattended queue drain (`docs/specs/queue.md`, strictly serial): assumptions may only take scope-narrowing, reversible, non-user-visible defaults — material ambiguity marks the item `[F] needs-review`; commit every terminal `[x]` / `[F]` transition before advancing. The canonical commit order is `config/skills/devlyn:resolve/references/outer-loop.md`.
|
|
46
46
|
|
|
47
47
|
## Subtractive-First Editing
|
|
48
48
|
|
package/CLAUDE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Project Instructions
|
|
2
2
|
|
|
3
|
-
devlyn-cli installs
|
|
3
|
+
devlyn-cli installs planning and full-pipeline skills alongside the execution contract below. These principles are non-negotiable on every change — yours and any sub-agent's.
|
|
4
4
|
|
|
5
5
|
## North Star
|
|
6
6
|
|
|
@@ -28,10 +28,10 @@ The runtime sub-agent contract below (Subtractive-first / Goal-locked / No-worka
|
|
|
28
28
|
|
|
29
29
|
## Quick Start
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
Choose direct work or full resolve using the conversational-entry rules below; engine selection follows the role map.
|
|
32
32
|
|
|
33
33
|
1. `/devlyn:ideate` (optional) — unstructured idea → `docs/specs/<id>/spec.md` + `spec.expected.json`. Modes: default Q&A, `--quick` (autonomous-pipeline-safe), `--from-spec <path>`, `--project`.
|
|
34
|
-
2. `/devlyn:resolve` —
|
|
34
|
+
2. `/devlyn:resolve` — full pipeline for work selected by the conversational-entry rules below. Free-form goal, `--spec <path>`, or `--verify-only <diff> --spec <path>`. Phases: PLAN → IMPLEMENT → BUILD_GATE → CLEANUP → VERIFY (fresh subagent, findings-only).
|
|
35
35
|
|
|
36
36
|
Each skill's `SKILL.md` is the source of truth for its flags and workflow — don't duplicate them here.
|
|
37
37
|
|
|
@@ -51,13 +51,13 @@ Each skill's `SKILL.md` is the source of truth for its flags and workflow — do
|
|
|
51
51
|
|
|
52
52
|
### Conversational entry + full-route handoff
|
|
53
53
|
|
|
54
|
-
Before
|
|
54
|
+
Before loading a workflow or writing files, inspect the requested change and relevant callers/tests. Quoted phase names, past logs and skill-file paths are context, not an instruction to invoke that workflow; follow the current user request. Default to direct execution when inspection makes the requested behavior, affected boundaries and verification tractable in the current context, including bounded multi-file work. Preserve requested behavior, scope, explicit constraints and the executor pin; make scoped edits, run required checks, review the final diff, and report changes with evidence. One concise route/check explanation suffices; ordinary direct work needs no spec, pipeline state, phase workers or extra approval. For direct/full/queue work, the outer owner reads `references/task-completion.md` relative to the installed `devlyn:resolve` skill's directory: prospective task-branch ownership (linked worktree optional), scoped commit acceptance, then PR/merge and recoverable owned-resource cleanup after required archive/queue commits. Local-only/no-push wins; delivery pending/failure stays separate from product verification.
|
|
55
55
|
|
|
56
|
-
Use full `/devlyn:resolve`
|
|
56
|
+
Use full `/devlyn:resolve` automatically only when inspection identifies interacting requirements or verification work too complex to manage reliably in the current context, such as coupled durable state, concurrent ownership and failure recovery across boundaries. Name the concrete interaction or verification gap. Domain labels (security/auth/payment/persistence/concurrency/API), file count and a spec document alone do not trigger it. Investigate or clarify missing intent/access first; a pipeline cannot supply them. Direct work still requires risk-proportionate checks and independent review for consequential changes. Explicit resolve (even small), explicit spec-mode workflows and queue drains retain all canonical phases, independent verification, pins and failure handling. If the full-route condition emerges mid-edit, carry the existing delta into its scope/evidence; do not reset the baseline or reconfirm existing authorization.
|
|
57
57
|
|
|
58
|
-
The user does not invoke skills manually; the orchestrating model does.
|
|
58
|
+
The user does not invoke skills manually; the orchestrating model does. For work selected for full resolve:
|
|
59
59
|
|
|
60
|
-
1. Write the agreed contract to `docs/specs/<id>/spec.md` (+ `spec.expected.json` when mechanical verifications exist).
|
|
60
|
+
1. Write the agreed contract to `docs/specs/<id>/spec.md` (+ `spec.expected.json` when mechanical verifications exist). Use a spec file for the selected work — a written spec is the user's reviewed contract; free-form large now assumes-and-logs instead of halting (zero-scope-signal goals still halt to ideate).
|
|
61
61
|
2. Present a one-screen plan-contract summary — the user's single review checkpoint, BEFORE the pipeline starts.
|
|
62
62
|
3. On go-ahead, commit the scoped queue-item delta (when applicable) and linked spec bundle, then invoke `/devlyn:resolve --spec <path>` hands-free to completion.
|
|
63
63
|
4. **Per-task outer loop**: read the terminal verdict. Successful normal-run archive → outer-owner completion per the canonical task-completion reference, after any terminal queue commit. Verdicts backed by spec/verification findings (NEEDS_WORK, verify/build-gate exhaustion) → adjudicate the findings, amend the spec (recorded in the spec file; spec stays read-only inside a run), commit that scoped amendment, then re-invoke — at most 3 outer iterations, then surface with the findings trail. Infrastructure, invalid-input, engine-availability, and implement-empty BLOCKED verdicts are not spec-amendable: surface immediately. Every iteration re-enters through committed durable artifacts (spec, findings, run archive), never conversation memory.
|
package/README.md
CHANGED
|
@@ -27,16 +27,16 @@ If devlyn-cli saved you time, [give it a star](https://github.com/fysoul17/devly
|
|
|
27
27
|
npx devlyn-cli
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
That's it. The installer opens with a single **agent selector** — pick any combination of **Claude Code**, **Codex CLI**, **oh-my-pi (omp)**, **Pi**, or **Grok Build CLI**, and devlyn installs into every one you choose in a single pass. Claude Code and any agent already present on your machine are pre-checked, so the common case is just Enter. Skill-capable agents receive the `devlyn:resolve`, `devlyn:ideate`, and `devlyn:design-ui` skills — plus the `devlyn:engines` and `devlyn:queue` utilities — in the directory each one loads from: Codex → `~/.codex/skills/`, Grok → `~/.grok/skills/`, while **omp and Pi share `~/.agents/skills/`** — the cross-agent standard both read — so the bundle is written there once, not duplicated per agent. In Codex / omp / Pi, invoke them as skills (`$devlyn:resolve`, `$devlyn:ideate`, `$devlyn:design-ui`); in Claude Code and Grok Build CLI they're slash commands (`/devlyn:resolve`). Rerunning refreshes skills
|
|
30
|
+
That's it. The installer opens with a single **agent selector** — pick any combination of **Claude Code**, **Codex CLI**, **oh-my-pi (omp)**, **Pi**, or **Grok Build CLI**, and devlyn installs into every one you choose in a single pass. Claude Code and any agent already present on your machine are pre-checked, so the common case is just Enter. Skill-capable agents receive the `devlyn:resolve`, `devlyn:ideate`, and `devlyn:design-ui` skills — plus the `devlyn:engines` and `devlyn:queue` utilities — in the directory each one loads from: Codex → `~/.codex/skills/`, Grok → `~/.grok/skills/`, while **omp and Pi share `~/.agents/skills/`** — the cross-agent standard both read — so the bundle is written there once, not duplicated per agent. In Codex / omp / Pi, invoke them as skills (`$devlyn:resolve`, `$devlyn:ideate`, `$devlyn:design-ui`); in Claude Code and Grok Build CLI they're slash commands (`/devlyn:resolve`). Rerunning refreshes skills and the managed instruction block for selected agents while preserving project rules outside it. See [Migration from earlier versions](#migration-from-earlier-versions) for legacy migration and merge recovery. (`npx devlyn-cli -y` installs the Claude core non-interactively; `npx devlyn-cli agents <cli>` adds one agent later.)
|
|
31
31
|
|
|
32
32
|
---
|
|
33
33
|
|
|
34
|
-
## How It Works —
|
|
34
|
+
## How It Works — Direct Work or Full Pipeline
|
|
35
35
|
|
|
36
|
-
devlyn-cli
|
|
36
|
+
devlyn-cli supports direct execution for clear, low-risk work with decisive checks and a full pipeline for work that needs it. The pipeline surface is two skills, with `/devlyn:design-ui` installed as the required creative UI surface:
|
|
37
37
|
|
|
38
38
|
```
|
|
39
|
-
|
|
39
|
+
inspect intent → direct work or full resolve → ship
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
Non-Claude agents (Codex / omp / Pi / Grok): when one of these is selected, the workflows install as that agent's skills. In Codex / omp / Pi, use `$devlyn:ideate`, `$devlyn:resolve`, or `$devlyn:design-ui`; in Grok, use `/devlyn:ideate`, `/devlyn:resolve`, or `/devlyn:design-ui`, the same slash-command form as Claude Code.
|
|
@@ -60,9 +60,9 @@ Default mode produces a `docs/specs/<id>-<slug>/spec.md` plus `spec.expected.jso
|
|
|
60
60
|
|
|
61
61
|
Skip ideate entirely if you have a spec or just want to describe the work — `/devlyn:resolve` accepts free-form goals too.
|
|
62
62
|
|
|
63
|
-
###
|
|
63
|
+
### Choose direct execution or `/devlyn:resolve`
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
Inspect the requested behavior, affected callers and tests first. Default to direct work when its scope and verification are tractable, including bounded multi-file changes; honor constraints and executor pins, run risk-proportionate checks and independent review for consequential changes, then review the diff and deliver. Automatically use full `/devlyn:resolve` only for concrete interacting requirements or verification too complex to manage reliably in the current context, such as coupled durable state, concurrent ownership and failure recovery. Domain labels, file count and a spec document alone do not trigger it. Investigate or clarify missing intent/access first. Explicit resolve (including small tasks), explicit spec-mode workflows and queue drains keep the full workflow below.
|
|
66
66
|
|
|
67
67
|
```
|
|
68
68
|
/devlyn:resolve "fix the login bug" # free-form
|
|
@@ -76,10 +76,10 @@ Internal phases run sequentially with file-based handoff via `.devlyn/pipeline.s
|
|
|
76
76
|
PLAN → IMPLEMENT → BUILD_GATE → CLEANUP → VERIFY (fresh subagent, findings-only)
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
-
- **PLAN**
|
|
80
|
-
- **BUILD_GATE** runs your project's real compilers, typecheckers, linters, and `python3 .claude/skills/_shared/spec-verify-check.py` (verification commands literal-match). Auto-detects Next.js, Rust, Go, Solidity, Expo, Swift, and Dockerfiles. Browser flows route through Chrome MCP → Playwright → curl tier.
|
|
79
|
+
- **PLAN** runs in the owner context and freezes requirements, verification and the authorized file surface before implementation.
|
|
80
|
+
- **BUILD_GATE** runs commands in the owner context without another model invocation, using your project's real compilers, typecheckers, linters, and `python3 .claude/skills/_shared/spec-verify-check.py` (verification commands literal-match). Auto-detects Next.js, Rust, Go, Solidity, Expo, Swift, and Dockerfiles. Browser flows route through Chrome MCP → Playwright → curl tier.
|
|
81
81
|
- **VERIFY** runs in a fresh subagent context with no code-mutation tools — findings only, structurally independent.
|
|
82
|
-
- Git checkpoints at every phase for safe rollback. Fix-loop budget shared across BUILD_GATE and VERIFY (`--max-rounds N`, default 4).
|
|
82
|
+
- Git checkpoints at every phase for safe rollback. Fix-loop budget shared across BUILD_GATE, CLEANUP and VERIFY (`--max-rounds N`, default 4).
|
|
83
83
|
|
|
84
84
|
Common flags: `--engine claude|codex|omp` (default: the orchestrator-supported default), `--role-config <path>` (one-run worker/judge profiles, see below), `--bypass build-gate,cleanup`, `--pair-verify` (force pair-mode JUDGE in VERIFY), `--no-pair` (intentional solo VERIFY), `--risk-probes` / `--no-risk-probes`, `--perf` (per-phase timing).
|
|
85
85
|
`--pair-verify` and `--no-pair` are mutually exclusive; using both stops with `BLOCKED:invalid-flags`.
|
|
@@ -118,10 +118,10 @@ Stack tasks to run back-to-back without supervision. `/devlyn:queue add "<intent
|
|
|
118
118
|
devlyn separates three engine roles:
|
|
119
119
|
|
|
120
120
|
- **Orchestrator** — the CLI you opened (Claude Code, Codex, or omp) that drives the conversation and loop. The contract is symmetric (`CLAUDE.md` ↔ `AGENTS.md`), so the same phase-gated pipeline runs whichever you launch; the file artifacts (spec, queue, state) carry over if you switch.
|
|
121
|
-
- **Executor** (legacy) — the worker for IMPLEMENT /
|
|
121
|
+
- **Executor** (legacy) — the worker for IMPLEMENT, its included code/doc cleanup, and their repair rounds, and the primary VERIFY judge, unless either is separately profiled (below). Defaults to the orchestrator-supported default. PLAN is orchestrator-fixed and never inherits `--engine` or an executor pin. An absent primary profile follows the legacy executor, not an opt-in worker profile.
|
|
122
122
|
- **Pair judge** — the first available *other* engine, default for VERIFY and conditional for risk probes.
|
|
123
123
|
|
|
124
|
-
`--engine <name>` sets the legacy executor for one run as an engine-only entry (it clears any lower-precedence profile's model/effort).
|
|
124
|
+
`--engine <name>` sets the legacy executor for one run as an engine-only entry (it clears any lower-precedence profile's model/effort). PLAN stays in the owner context; BUILD_GATE/CLEANUP run owner commands; risk-probe derivation keeps its existing route. VERIFY/JUDGE runs pair mode by default when the OTHER engine is available.
|
|
125
125
|
|
|
126
126
|
Pin roles durably with `/devlyn:engines` (no args shows the role table + detected engines; `executor <name>` / `pair <name>,...` / `role <worker|primary_judge|pair_judge> <JSON object>` / `role <name> clear` manage the pins, stored machine-local in `.devlyn/engines.json`; `clear` removes all legacy and role pins, preserves unrelated keys, and deletes an empty file). Pins fail closed: an unavailable pinned engine stops with `BLOCKED:<engine>-unavailable`, and a name with no `_shared/adapters/<name>.md` adapter stops with `BLOCKED:invalid-engine-config`. New engines plug in by shipping an adapter file — no skill changes.
|
|
127
127
|
|
|
@@ -144,12 +144,12 @@ Pin roles durably with `/devlyn:engines` (no args shows the role table + detecte
|
|
|
144
144
|
`--role-config <path>` supplies the same `{"roles": {...}}` object for one run only, with no other top-level keys; the flag may appear once.
|
|
145
145
|
|
|
146
146
|
- **Precedence** — an entry replaces the lower one as a whole; model/effort never merge across engines. Worker and primary judge: run `--role-config` entry > `--engine` (engine-only) > project role entry > legacy executor/default. Pair judge: run entry > project entry > `pair_judge_priority` / the OTHER-engine complement. A missing `model`/`effort` keeps that route's current default and is shown as inherited/unresolved.
|
|
147
|
-
- **Boundaries** — `worker` covers IMPLEMENT /
|
|
147
|
+
- **Boundaries** — `worker` covers IMPLEMENT, its included code/doc cleanup, and their repair rounds; `primary_judge` and `pair_judge` cover VERIFY only. PLAN stays orchestrator-fixed, BUILD_GATE/CLEANUP run owner commands, and risk-probe derivation stays outside these controls. OTHER must differ from the primary by engine: an explicit same-engine pair is `BLOCKED:invalid-engine-config`. `--no-pair` is unchanged — explicit solo VERIFY; an unused pair entry is neither dispatched nor availability-checked.
|
|
148
148
|
- **Initial explicit routes** — Codex worker/primary/pair accept exact `model` + `effort` (dispatched as `-m` / `-c model_reasoning_effort=`, validated against the installed Codex CLI's native model metadata for its version). Claude primary/pair judges pass an exact `model` as `--model` and validate native result identity; model-only selection needs no source update for a new ID. Explicit `effort` separately requires the adapter's version/model support declaration. The Claude worker stays the native `Agent` route and is engine-only: explicit `model`/`effort` on a Claude worker is `BLOCKED:unsupported-role-option` — a supported-route boundary, not a claim that Claude cannot implement. Other adapters (omp, grok) are engine-only for their eligible roles.
|
|
149
149
|
- **Errors** — `BLOCKED:unsupported-role-option` names the role, engine and field with guidance; there is no clamp, fallback, substituted model, or weaker retry. An explicitly selected engine (flag, pin, or profile) that is unavailable stops with `BLOCKED:<engine>-unavailable`. A native warning that a requested option was ignored is a failed promise even at exit 0.
|
|
150
150
|
- **Requested vs observed** — `/devlyn:engines` status prints each role's requested engine/model/effort, source and dispatch channel before dispatch; it describes a request and does not prove a native invocation happened. Effective model is reported only with native evidence; a Codex worker receipt binds requested dispatch and leaves effective model unknown. A reported worker model reroute blocks completion even at exit 0. SURFACE_CLOSE inherits native Claude model settings and records the model from its required JSON result. Effective effort stays unknown unless native evidence establishes it — invocation arguments prove dispatch, not provider-internal reasoning.
|
|
151
151
|
|
|
152
|
-
`--engine codex` routes IMPLEMENT /
|
|
152
|
+
`--engine codex` routes IMPLEMENT and its included code/doc cleanup to Codex as a supported engine-only route (exact model/effort via the profiles above). Historical record: iter-0020 closed Codex BUILD/IMPLEMENT below the quality floor on the 9-fixture suite (L2 vs L1 = −3.6, 3/8 gated fixtures cleared the +5 margin floor — release-readiness FAIL). Separately, PLAN-pair remains research-only: iter-0033g + iter-0034 closed it with explicit unblock conditions (container/sandbox infra OR production telemetry capturing positive evidence of subagent introspection). Install the Codex CLI (https://platform.openai.com/docs/codex) and pass the flag explicitly to opt in:
|
|
153
153
|
|
|
154
154
|
```
|
|
155
155
|
/devlyn:resolve "fix the auth bug" --engine codex
|
|
@@ -227,6 +227,27 @@ ids.
|
|
|
227
227
|
|
|
228
228
|
### Migration from earlier versions
|
|
229
229
|
|
|
230
|
+
Reinstall with the new version to refresh instructions and skills for the selected
|
|
231
|
+
CLIs. Claude uses `CLAUDE.md`; Codex, Grok, omp and Pi share `AGENTS.md`.
|
|
232
|
+
Devlyn updates its checksum-marked instruction block and preserves project-specific
|
|
233
|
+
rules outside it. Keep custom rules outside the block; they take precedence over
|
|
234
|
+
its defaults. Exact pre-update backups are saved in `.devlyn/instructions/`.
|
|
235
|
+
When recovery is needed, pre-existing symlinks or non-directory entries at `.devlyn/` or
|
|
236
|
+
`.devlyn/instructions/` stop installation without replacing the instruction file.
|
|
237
|
+
|
|
238
|
+
Templates from versions 3.0.0–3.1.2 migrate automatically, including custom
|
|
239
|
+
text before or after the template. Replaced or extended introductions under the
|
|
240
|
+
original project heading also migrate when the entire body from `## North Star`
|
|
241
|
+
onward matches a known template hash. Replacement project rules are preserved
|
|
242
|
+
outside the managed block; only an exact original introduction is removed.
|
|
243
|
+
Recognizable leftover Devlyn text, changed bodies and ambiguous templates stop
|
|
244
|
+
with a concise recovery message and leave the original unchanged. The message
|
|
245
|
+
links an exact `.backup`, new defaults in `.incoming`, and a `.merge.md` guide.
|
|
246
|
+
Compare the two files, preserve all project rules outside one new managed block,
|
|
247
|
+
and rerun the same install command. Earlier selected agents may already be updated.
|
|
248
|
+
Plain custom instruction files retain their contents and gain a managed block.
|
|
249
|
+
Use 3.1.3 or newer consistently: older installers still overwrite `CLAUDE.md`.
|
|
250
|
+
|
|
230
251
|
<!-- legacy-surface-map:begin — retired command names below are documented as OLD, not current; lint Check 10c skips this block -->
|
|
231
252
|
Earlier versions of devlyn-cli shipped 16+ slash commands. The iter-0034 Phase 4 cutover (2026-05-04) and the 2026-05-14 follow-up consolidated them down to the three current commands. Upgrades automatically purge the legacy skill directories from `~/.claude/skills/`.
|
|
232
253
|
|
package/bin/devlyn.js
CHANGED
|
@@ -9,6 +9,7 @@ const { execSync } = require('child_process');
|
|
|
9
9
|
const CONFIG_SOURCE = path.join(__dirname, '..', 'config');
|
|
10
10
|
const OPTIONAL_SKILLS_SOURCE = path.join(__dirname, '..', 'optional-skills');
|
|
11
11
|
const PKG = require('../package.json');
|
|
12
|
+
const { updateInstructions, InstructionError } = require('./instructions');
|
|
12
13
|
|
|
13
14
|
// The devlyn skill bundle installed into every skill-capable agent's loader
|
|
14
15
|
// directory. Single source of truth so codex/omp/pi stay in lockstep — adding a
|
|
@@ -700,20 +701,6 @@ function installSkillsForCLI(cliKey) {
|
|
|
700
701
|
return copied;
|
|
701
702
|
}
|
|
702
703
|
|
|
703
|
-
// Strip the legacy "# Devlyn Agent Instructions" block (the retired evaluator
|
|
704
|
-
// agent) that earlier installs appended to instruction files, so upgrades scrub
|
|
705
|
-
// it instead of carrying it forever. Anchors on the LAST marker so user content
|
|
706
|
-
// above a stray copy of the block is preserved.
|
|
707
|
-
const DEVLYN_AGENTS_MARKER = '# Devlyn Agent Instructions';
|
|
708
|
-
function stripManagedBlock(content) {
|
|
709
|
-
const markerIdx = content.lastIndexOf(DEVLYN_AGENTS_MARKER);
|
|
710
|
-
if (markerIdx > 0) {
|
|
711
|
-
const sepIdx = content.lastIndexOf('\n---', markerIdx);
|
|
712
|
-
return content.slice(0, sepIdx > 0 ? sepIdx : markerIdx).trimEnd();
|
|
713
|
-
}
|
|
714
|
-
return content.trimEnd();
|
|
715
|
-
}
|
|
716
|
-
|
|
717
704
|
// One-line description of exactly what selecting a CLI target installs, so the
|
|
718
705
|
// unified selector stays honest.
|
|
719
706
|
function targetDesc(cli) {
|
|
@@ -723,35 +710,10 @@ function targetDesc(cli) {
|
|
|
723
710
|
return `${cli.instructionsFile} instructions only`;
|
|
724
711
|
}
|
|
725
712
|
|
|
726
|
-
//
|
|
727
|
-
// codex/omp/pi). Creates it from the packaged base when missing; on existing
|
|
728
|
-
// files, scrubs the legacy appended block and otherwise leaves user content
|
|
729
|
-
// untouched. Returns true when the destination was written.
|
|
713
|
+
// Shared instruction ownership and preservation rules apply to every CLI.
|
|
730
714
|
function installInstructionsForCLI(cliKey) {
|
|
731
715
|
const cli = CLI_TARGETS[cliKey];
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
const destFile = path.join(process.cwd(), cli.instructionsFile);
|
|
735
|
-
const baseInstructionsSrc = path.join(__dirname, '..', cli.baseInstructionsFile);
|
|
736
|
-
let content = null;
|
|
737
|
-
if (fs.existsSync(destFile)) {
|
|
738
|
-
const current = fs.readFileSync(destFile, 'utf8');
|
|
739
|
-
if (current.includes(DEVLYN_AGENTS_MARKER)) {
|
|
740
|
-
content = stripManagedBlock(current) + '\n';
|
|
741
|
-
} else {
|
|
742
|
-
log(` → Preserved existing ${cli.instructionsFile}. Compare with the bundled template at ${baseInstructionsSrc} and merge relevant instructions.`, 'dim');
|
|
743
|
-
}
|
|
744
|
-
} else {
|
|
745
|
-
if (fs.existsSync(baseInstructionsSrc)) {
|
|
746
|
-
content = fs.readFileSync(baseInstructionsSrc, 'utf8');
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
if (content === null) return false;
|
|
750
|
-
|
|
751
|
-
log(`\n🤖 Installing instructions for ${cli.name}...`, 'cyan');
|
|
752
|
-
fs.writeFileSync(destFile, content);
|
|
753
|
-
log(` → ${cli.instructionsFile}`, 'dim');
|
|
754
|
-
return true;
|
|
716
|
+
return cli?.baseInstructionsFile ? updateInstructions(cli.baseInstructionsFile) : false;
|
|
755
717
|
}
|
|
756
718
|
|
|
757
719
|
// Install both instructions and skills for a single CLI. Used by the
|
|
@@ -803,8 +765,31 @@ function installAgentsForAllDetected() {
|
|
|
803
765
|
// Install the Claude Code core config: project .claude/ (skills, templates,
|
|
804
766
|
// settings, CLAUDE.md, .gitignore) plus global ~/.claude/settings.json tweaks.
|
|
805
767
|
// Extracted so the unified target selector installs it only when "Claude Code"
|
|
806
|
-
// is chosen.
|
|
768
|
+
// is chosen. Check global settings and instruction conflicts before writes.
|
|
807
769
|
function installClaudeCore() {
|
|
770
|
+
const globalClaudeDir = path.join(os.homedir(), '.claude');
|
|
771
|
+
const globalSettingsPath = path.join(globalClaudeDir, 'settings.json');
|
|
772
|
+
function readGlobalSettings() {
|
|
773
|
+
let settings = {};
|
|
774
|
+
try {
|
|
775
|
+
if (fs.lstatSync(globalSettingsPath, { throwIfNoEntry: false })) {
|
|
776
|
+
settings = JSON.parse(fs.readFileSync(globalSettingsPath, 'utf8'));
|
|
777
|
+
}
|
|
778
|
+
} catch (error) {
|
|
779
|
+
const reason = error instanceof SyntaxError ? 'invalid JSON' : error.message;
|
|
780
|
+
throw new Error(`Cannot merge ${globalSettingsPath}: ${reason}. Original preserved; correct the file or its access and rerun installation.`);
|
|
781
|
+
}
|
|
782
|
+
if (!settings || typeof settings !== 'object' || Array.isArray(settings)) {
|
|
783
|
+
throw new Error(`Cannot merge ${globalSettingsPath}: root must be a JSON object. Original preserved; correct it and rerun installation.`);
|
|
784
|
+
}
|
|
785
|
+
if (!Object.prototype.hasOwnProperty.call(settings, 'env')) settings.env = {};
|
|
786
|
+
if (!settings.env || typeof settings.env !== 'object' || Array.isArray(settings.env)) {
|
|
787
|
+
throw new Error(`Cannot merge ${globalSettingsPath}: env must be a JSON object. Original preserved; correct it and rerun installation.`);
|
|
788
|
+
}
|
|
789
|
+
return settings;
|
|
790
|
+
}
|
|
791
|
+
readGlobalSettings();
|
|
792
|
+
updateInstructions('CLAUDE.md');
|
|
808
793
|
const targetDir = getTargetDir();
|
|
809
794
|
const skillsDir = path.join(targetDir, 'skills');
|
|
810
795
|
log('\n📁 Installing Claude Code config to .claude/', 'green');
|
|
@@ -831,15 +816,6 @@ function installClaudeCore() {
|
|
|
831
816
|
log(`\n🧹 Cleaned up ${removed} deprecated file${removed > 1 ? 's' : ''}`, 'yellow');
|
|
832
817
|
}
|
|
833
818
|
|
|
834
|
-
// Copy Claude project instructions to project root. Other CLI instruction
|
|
835
|
-
// files are installed only when explicitly selected below or via `agents`.
|
|
836
|
-
const claudeMdSrc = path.join(__dirname, '..', 'CLAUDE.md');
|
|
837
|
-
const claudeMdDest = path.join(process.cwd(), 'CLAUDE.md');
|
|
838
|
-
if (fs.existsSync(claudeMdSrc)) {
|
|
839
|
-
fs.copyFileSync(claudeMdSrc, claudeMdDest);
|
|
840
|
-
log(' → CLAUDE.md', 'dim');
|
|
841
|
-
}
|
|
842
|
-
|
|
843
819
|
// Keep installer-managed pipeline state and install metadata out of git.
|
|
844
820
|
const gitignorePath = path.join(process.cwd(), '.gitignore');
|
|
845
821
|
const gitignoreEntries = ['.devlyn/', '.claude/skills/.devlyn-install.json'];
|
|
@@ -950,17 +926,8 @@ function installClaudeCore() {
|
|
|
950
926
|
}
|
|
951
927
|
|
|
952
928
|
// Configure global Claude Code settings (~/.claude/settings.json)
|
|
953
|
-
|
|
954
|
-
const
|
|
955
|
-
let globalSettings = {};
|
|
956
|
-
if (fs.existsSync(globalSettingsPath)) {
|
|
957
|
-
try {
|
|
958
|
-
globalSettings = JSON.parse(fs.readFileSync(globalSettingsPath, 'utf8'));
|
|
959
|
-
} catch {
|
|
960
|
-
globalSettings = {};
|
|
961
|
-
}
|
|
962
|
-
}
|
|
963
|
-
if (!globalSettings.env) globalSettings.env = {};
|
|
929
|
+
// Project settings may refer to this same file; merge the latest bytes.
|
|
930
|
+
const globalSettings = readGlobalSettings();
|
|
964
931
|
let globalSettingsChanged = false;
|
|
965
932
|
if (!globalSettings.env.CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING) {
|
|
966
933
|
globalSettings.env.CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING = '1';
|
|
@@ -1250,6 +1217,8 @@ function showBenchmarkModeHelp(mode) {
|
|
|
1250
1217
|
|
|
1251
1218
|
// Main
|
|
1252
1219
|
const args = process.argv.slice(2);
|
|
1220
|
+
|
|
1221
|
+
async function main() {
|
|
1253
1222
|
const command = args[0];
|
|
1254
1223
|
|
|
1255
1224
|
switch (command) {
|
|
@@ -1259,7 +1228,7 @@ switch (command) {
|
|
|
1259
1228
|
break;
|
|
1260
1229
|
case '-y':
|
|
1261
1230
|
case '--yes':
|
|
1262
|
-
init(true);
|
|
1231
|
+
await init(true);
|
|
1263
1232
|
break;
|
|
1264
1233
|
case 'list':
|
|
1265
1234
|
case 'ls':
|
|
@@ -1314,10 +1283,14 @@ switch (command) {
|
|
|
1314
1283
|
log('\n🤖 Installing agents for all supported CLIs...', 'blue');
|
|
1315
1284
|
const count = installSelectedCLITargets(Object.keys(CLI_TARGETS));
|
|
1316
1285
|
log(`\n✅ Agents installed for ${count} CLI${count !== 1 ? 's' : ''}`, 'green');
|
|
1317
|
-
} else if (
|
|
1286
|
+
} else if (Object.keys(CLI_TARGETS).includes(subArg)) {
|
|
1318
1287
|
// Install for a specific CLI
|
|
1319
1288
|
installAgentsForCLI(subArg);
|
|
1320
1289
|
log('\n✅ Done!', 'green');
|
|
1290
|
+
} else if (subArg !== undefined) {
|
|
1291
|
+
log(`Unknown CLI target: ${JSON.stringify(subArg)}`, 'yellow');
|
|
1292
|
+
log(`Supported: ${Object.keys(CLI_TARGETS).join(', ')}, all`, 'dim');
|
|
1293
|
+
process.exit(1);
|
|
1321
1294
|
} else {
|
|
1322
1295
|
// Auto-detect and install
|
|
1323
1296
|
const detected = detectOtherCLIs();
|
|
@@ -1336,10 +1309,16 @@ switch (command) {
|
|
|
1336
1309
|
}
|
|
1337
1310
|
case 'init':
|
|
1338
1311
|
case undefined:
|
|
1339
|
-
init(false);
|
|
1312
|
+
await init(false);
|
|
1340
1313
|
break;
|
|
1341
1314
|
default:
|
|
1342
1315
|
log(`Unknown command: ${command}`, 'yellow');
|
|
1343
1316
|
showHelp();
|
|
1344
1317
|
process.exit(1);
|
|
1345
1318
|
}
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
main().catch((error) => {
|
|
1322
|
+
console.error(error instanceof InstructionError ? `\n${error.message}` : error);
|
|
1323
|
+
process.exitCode = 1;
|
|
1324
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"AGENTS.md": [
|
|
3
|
+
{
|
|
4
|
+
"versions": [
|
|
5
|
+
"3.0.0"
|
|
6
|
+
],
|
|
7
|
+
"length": 11091,
|
|
8
|
+
"sha256": "099e68f3e203fa735bb1ebcd780a0e18bde462ea7de5f74fb3d17cee5e64b63a",
|
|
9
|
+
"preamble": "# Codex Project Instructions\n\ndevlyn-cli installs `/devlyn:ideate` (optional) and `/devlyn:resolve` (required) into Claude Code, plus the contract below. Codex CLI reads this file when invoked inside a project that has it. The principles are non-negotiable on every change.\n\n",
|
|
10
|
+
"body": {
|
|
11
|
+
"length": 10816,
|
|
12
|
+
"sha256": "8b972c2c379e5ff8411bf1214f926a3b9904bdf857ac6b30a8c79ce0e32182e3"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"versions": [
|
|
17
|
+
"3.0.1"
|
|
18
|
+
],
|
|
19
|
+
"length": 12166,
|
|
20
|
+
"sha256": "33fbd5b01c8e65f4c663f95423a45b16dcf5bb28f1fd0c6791079abd20c267ae",
|
|
21
|
+
"preamble": "# Codex Project Instructions\n\ndevlyn-cli installs `/devlyn:ideate` (optional) and `/devlyn:resolve` (required) into Claude Code, plus the contract below. Codex CLI reads this file when invoked inside a project that has it. The principles are non-negotiable on every change.\n\n",
|
|
22
|
+
"body": {
|
|
23
|
+
"length": 11891,
|
|
24
|
+
"sha256": "52326a832df6d5ab13bddca5a1a01ad338a3db71d172c70d3eaed806668db4d8"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"versions": [
|
|
29
|
+
"3.1.0",
|
|
30
|
+
"3.1.1",
|
|
31
|
+
"3.1.2"
|
|
32
|
+
],
|
|
33
|
+
"length": 12581,
|
|
34
|
+
"sha256": "acd3672efaa33e75455f8530a7425e950c01c822c6f5d85d7dbc9d7ff1958028",
|
|
35
|
+
"preamble": "# Codex Project Instructions\n\ndevlyn-cli installs `/devlyn:ideate` (optional) and `/devlyn:resolve` (required) into Claude Code, plus the contract below. Codex CLI reads this file when invoked inside a project that has it. The principles are non-negotiable on every change.\n\n",
|
|
36
|
+
"body": {
|
|
37
|
+
"length": 12306,
|
|
38
|
+
"sha256": "0de6061f9dff8e88964e542bb8a5e113996e480bef597774fb15eaa766472129"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"CLAUDE.md": [
|
|
43
|
+
{
|
|
44
|
+
"versions": [
|
|
45
|
+
"3.0.0"
|
|
46
|
+
],
|
|
47
|
+
"length": 24434,
|
|
48
|
+
"sha256": "29ddcc5ef4d5b44b2ba6aae22bd3c0c033ceaa47b240bd647aaefbe00f2a6e4e",
|
|
49
|
+
"preamble": "# Project Instructions\n\ndevlyn-cli installs `/devlyn:ideate` (optional) and `/devlyn:resolve` (required) into Claude Code, plus the contract below. These principles are non-negotiable on every change \u2014 yours and any sub-agent's.\n\n",
|
|
50
|
+
"body": {
|
|
51
|
+
"length": 24204,
|
|
52
|
+
"sha256": "555d8b9a4c154ec5225105919836a4d9831c76c1b1c7ee4c19fecac8fbd1c948"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"versions": [
|
|
57
|
+
"3.0.1"
|
|
58
|
+
],
|
|
59
|
+
"length": 25417,
|
|
60
|
+
"sha256": "50301bf98507c83da1576be7f443885236e7d421ff2e40fd077ed9652ea3a2e0",
|
|
61
|
+
"preamble": "# Project Instructions\n\ndevlyn-cli installs `/devlyn:ideate` (optional) and `/devlyn:resolve` (required) into Claude Code, plus the contract below. These principles are non-negotiable on every change \u2014 yours and any sub-agent's.\n\n",
|
|
62
|
+
"body": {
|
|
63
|
+
"length": 25187,
|
|
64
|
+
"sha256": "53a933e22369438a5d9dd7aa5f778909aeba5a38d5e2e68b8a36dab5c874d84d"
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"versions": [
|
|
69
|
+
"3.1.0",
|
|
70
|
+
"3.1.1",
|
|
71
|
+
"3.1.2"
|
|
72
|
+
],
|
|
73
|
+
"length": 26152,
|
|
74
|
+
"sha256": "d11a863907dabdf827063df7133a8a46a14e018f608884f08c601bf36e0f3f0c",
|
|
75
|
+
"preamble": "# Project Instructions\n\ndevlyn-cli installs `/devlyn:ideate` (optional) and `/devlyn:resolve` (required) into Claude Code, plus the contract below. These principles are non-negotiable on every change \u2014 yours and any sub-agent's.\n\n",
|
|
76
|
+
"body": {
|
|
77
|
+
"length": 25922,
|
|
78
|
+
"sha256": "dd9f0f63f559a3b9a6e2bbf102045b01f6b73bce684dd27124ee6d6af3641b91"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
}
|