devlyn-cli 2.6.0 → 2.7.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 +1 -71
- package/CLAUDE.md +2 -2
- package/README.md +7 -5
- package/bin/devlyn.js +29 -82
- package/config/skills/_shared/adapters/claude.md +2 -2
- package/config/skills/_shared/pair-plan-schema.md +2 -2
- package/config/skills/devlyn:resolve/SKILL.md +5 -4
- package/config/skills/devlyn:resolve/references/free-form-mode.md +1 -1
- package/config/skills/devlyn:resolve/references/state-schema.md +1 -1
- package/package.json +1 -2
- package/scripts/lint-skills.sh +7 -5
- package/agents-config/evaluator.md +0 -64
package/AGENTS.md
CHANGED
|
@@ -85,6 +85,7 @@ Every finding cites concrete evidence:
|
|
|
85
85
|
- Browser: route/URL + screenshot or observed evidence.
|
|
86
86
|
- Benchmark: run id, fixture id, metric, raw result path.
|
|
87
87
|
- Negative existence ("X lacks Y", "X cannot Z", "X is Y-specific"): highest-risk claim shape — fails to any single counter-example. Active search required at write time, not absence-of-memory. Applies to chat responses and trade-off tables, not only formal findings.
|
|
88
|
+
- Position reversal in an oracle-less debate (design, strategy, trade-off): a reversal is itself a claim. Cite the NAMED DELTA — the specific prior claim, evidence, or criterion that changed — before flipping. Flipping to the last speaker without a cited delta is capitulation, not reasoning; genuinely unresolved disagreement escalates to the user.
|
|
88
89
|
|
|
89
90
|
Exclude vague claims. They produce vague fixes.
|
|
90
91
|
|
|
@@ -103,74 +104,3 @@ Exclude vague claims. They produce vague fixes.
|
|
|
103
104
|
- Be concise and specific.
|
|
104
105
|
- State blockers plainly.
|
|
105
106
|
- Separate completed work, verification, and remaining risks.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
---
|
|
109
|
-
|
|
110
|
-
# Devlyn Agent Instructions
|
|
111
|
-
|
|
112
|
-
# Evaluator Agent
|
|
113
|
-
|
|
114
|
-
You are a code quality evaluator. Your job is to audit work produced by another session, PR, or changeset and provide evidence-based findings with exact file:line references.
|
|
115
|
-
|
|
116
|
-
## Before You Start
|
|
117
|
-
|
|
118
|
-
1. **Check for done criteria**: Read `.devlyn/done-criteria.md` if it exists. When present, this is your primary grading rubric — every criterion must be verified with evidence. When absent, fall back to the checklists below.
|
|
119
|
-
|
|
120
|
-
## Calibration
|
|
121
|
-
|
|
122
|
-
You will be too lenient by default. You will identify real issues, then talk yourself into deciding they aren't a big deal. Fight this tendency.
|
|
123
|
-
|
|
124
|
-
**Rule**: When in doubt, score DOWN. A false negative ships broken code. A false positive costs minutes of review. The cost is asymmetric.
|
|
125
|
-
|
|
126
|
-
- A catch block that logs but doesn't surface error to user = HIGH (not MEDIUM). Logging is not error handling.
|
|
127
|
-
- A `let` that could be `const` = LOW note only. Linters catch this.
|
|
128
|
-
- "The error handling is generally quite good" = WRONG. Count the instances. Name the files.
|
|
129
|
-
|
|
130
|
-
## Evaluation Process
|
|
131
|
-
|
|
132
|
-
1. **Discover scope**: Read the changeset (git diff, PR diff, or specified files)
|
|
133
|
-
2. **Assess correctness**: Find bugs, logic errors, silent failures, missing error handling
|
|
134
|
-
3. **Check architecture**: Verify patterns match existing codebase, no type duplication, proper wiring
|
|
135
|
-
4. **Verify spec compliance**: If a spec exists (HANDOFF.md, RFC, issue, done-criteria.md), compare requirements vs implementation
|
|
136
|
-
5. **Check error handling**: Every async operation needs loading, error, and empty states in UI. No silent catches.
|
|
137
|
-
6. **Review API contracts**: New endpoints must follow existing conventions for naming, validation, error envelopes
|
|
138
|
-
7. **Assess test coverage**: New modules need tests. Run the test suite and report results.
|
|
139
|
-
8. **Evaluate product quality**: Does this feel like a real feature or a demo stub? Are workflows complete end-to-end? Is the UI coherent?
|
|
140
|
-
|
|
141
|
-
## Rules
|
|
142
|
-
|
|
143
|
-
- Every finding must have a file:line reference. No guesswork.
|
|
144
|
-
- Classify by severity: CRITICAL (must fix), HIGH (should fix), MEDIUM (fix or justify), LOW (note)
|
|
145
|
-
- Call out what's done well, not just problems
|
|
146
|
-
- Look for cross-cutting patterns (e.g., same mistake repeated in multiple files)
|
|
147
|
-
|
|
148
|
-
## Output
|
|
149
|
-
|
|
150
|
-
Write findings to `.devlyn/EVAL-FINDINGS.md` for downstream consumption:
|
|
151
|
-
|
|
152
|
-
```markdown
|
|
153
|
-
# Evaluation Findings
|
|
154
|
-
|
|
155
|
-
## Verdict: [PASS / PASS WITH ISSUES / NEEDS WORK / BLOCKED]
|
|
156
|
-
|
|
157
|
-
## Done Criteria Results (if done-criteria.md existed)
|
|
158
|
-
- [x] [criterion] — VERIFIED: [evidence]
|
|
159
|
-
- [ ] [criterion] — FAILED: [what's wrong, file:line]
|
|
160
|
-
|
|
161
|
-
## Findings Requiring Action
|
|
162
|
-
### CRITICAL
|
|
163
|
-
- `file:line` — [description] — Fix: [suggested approach]
|
|
164
|
-
|
|
165
|
-
### HIGH
|
|
166
|
-
- `file:line` — [description] — Fix: [suggested approach]
|
|
167
|
-
|
|
168
|
-
## Cross-Cutting Patterns
|
|
169
|
-
- [pattern description]
|
|
170
|
-
|
|
171
|
-
## What's Good
|
|
172
|
-
- [positive observations]
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
Do NOT delete `.devlyn/done-criteria.md` or `.devlyn/EVAL-FINDINGS.md` — the orchestrator or user is responsible for cleanup.
|
|
176
|
-
|
package/CLAUDE.md
CHANGED
|
@@ -24,7 +24,7 @@ The runtime sub-agent contract below (Subtractive-first / Goal-locked / No-worka
|
|
|
24
24
|
|
|
25
25
|
## Quick Start
|
|
26
26
|
|
|
27
|
-
Two skills cover the full cycle
|
|
27
|
+
Two skills cover the full cycle. `/devlyn:ideate` is OPTIONAL; `/devlyn:resolve` is REQUIRED; `/devlyn:design-ui` is also REQUIRED as the creative UI exploration surface. **Both pipeline skills default to `--engine claude`** for PLAN/IMPLEMENT. Codex BUILD/IMPLEMENT and PLAN-pair remain research-only, but `/devlyn:resolve` VERIFY has conditional-default pair-JUDGE when its `SKILL.md` trigger policy fires. Pass `--engine codex` explicitly to opt into the broader research path. If a selected or conditionally required engine is unavailable, the run stops with `BLOCKED:<engine>-unavailable` and setup guidance.
|
|
28
28
|
|
|
29
29
|
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`.
|
|
30
30
|
2. `/devlyn:resolve` — hands-free pipeline for any coding task. Free-form goal, `--spec <path>`, or `--verify-only <diff> --spec <path>`. Phases: PLAN → IMPLEMENT → BUILD_GATE → CLEANUP → VERIFY (fresh subagent, findings-only).
|
|
@@ -135,7 +135,7 @@ A finding without one of these forms is excluded. Vague findings produce vague f
|
|
|
135
135
|
|
|
136
136
|
## Codex invocation
|
|
137
137
|
|
|
138
|
-
When `/devlyn:resolve` or `/devlyn:ideate` route a phase to Codex (`--engine codex
|
|
138
|
+
When `/devlyn:resolve` or `/devlyn:ideate` route a phase to Codex (`--engine codex` or conditional VERIFY pair/risk-probe routing), the wrapper-form contract lives in `config/skills/_shared/codex-config.md` (or `.claude/skills/_shared/codex-config.md` once installed). Omit `-m <model>` — the CLI's current flagship is used automatically. MCP is not in the loop. If Codex is required and unavailable, stop with `BLOCKED:codex-unavailable` and setup guidance.
|
|
139
139
|
|
|
140
140
|
## Working Mode
|
|
141
141
|
|
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ 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**,
|
|
30
|
+
That's it. The installer opens with a single **agent selector** — pick any combination of **Claude Code**, **Codex CLI**, **oh-my-pi (omp)**, or **Pi**, 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 in the directory each one loads from: Codex → `~/.codex/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 they're slash commands (`/devlyn:resolve`). Run it again anytime to update. (`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
|
|
|
@@ -101,10 +101,10 @@ that, `/devlyn:resolve` stops with `BLOCKED:solo-ceiling-avoidance-required`.
|
|
|
101
101
|
|
|
102
102
|
`--engine claude` (default) is the canonical implementation surface for PLAN, IMPLEMENT, BUILD_GATE, and CLEANUP. VERIFY/JUDGE conditionally runs pair mode for verify-only runs, high-risk specs, risk probes, mechanical warnings, coverage gaps, or explicit `--pair-verify`.
|
|
103
103
|
|
|
104
|
-
`--engine codex` routes IMPLEMENT to Codex
|
|
104
|
+
`--engine codex` routes IMPLEMENT to Codex — research-only at HEAD: 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); iter-0033g + iter-0034 closed PLAN-pair as research-only 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:
|
|
105
105
|
|
|
106
106
|
```
|
|
107
|
-
/devlyn:resolve "fix the auth bug" --engine
|
|
107
|
+
/devlyn:resolve "fix the auth bug" --engine codex # research-only
|
|
108
108
|
```
|
|
109
109
|
|
|
110
110
|
If Codex or Claude is absent when explicitly selected or conditionally required, the harness stops with `BLOCKED:codex-unavailable` or `BLOCKED:claude-unavailable` and prints setup guidance. Use `--no-pair` only when intentionally accepting solo VERIFY; use `--no-risk-probes` only when intentionally disabling automatic high-risk probes.
|
|
@@ -179,6 +179,7 @@ ids.
|
|
|
179
179
|
|
|
180
180
|
### Migration from earlier versions
|
|
181
181
|
|
|
182
|
+
<!-- legacy-surface-map:begin — retired command names below are documented as OLD, not current; lint Check 10c skips this block -->
|
|
182
183
|
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/`.
|
|
183
184
|
|
|
184
185
|
| Old command | Now use |
|
|
@@ -187,6 +188,7 @@ Earlier versions of devlyn-cli shipped 16+ slash commands. The iter-0034 Phase 4
|
|
|
187
188
|
| `/devlyn:product-spec`, `/devlyn:feature-spec`, `/devlyn:recommend-features`, `/devlyn:discover-product` | `/devlyn:ideate` |
|
|
188
189
|
| `/devlyn:team-design-ui` | `/devlyn:design-ui` (now always spawns the 5-specialist team — Creative Director, Product Designer, Visual Designer, Interaction Designer, Accessibility Designer) |
|
|
189
190
|
| `/devlyn:design-system` | Removed 2026-05-14 — no replacement |
|
|
191
|
+
<!-- legacy-surface-map:end -->
|
|
190
192
|
|
|
191
193
|
---
|
|
192
194
|
|
|
@@ -215,7 +217,7 @@ Selected during install. Run `npx devlyn-cli` again to add more.
|
|
|
215
217
|
| `asset-creator` | AI pixel art game asset pipeline — generate, chroma-key, catalog |
|
|
216
218
|
| `cloudflare-nextjs-setup` | Cloudflare Workers + Next.js with OpenNext |
|
|
217
219
|
| `generate-skill` | Create Claude Code skills following Anthropic best practices |
|
|
218
|
-
| `prompt-engineering` | Claude
|
|
220
|
+
| `prompt-engineering` | Claude prompt optimization |
|
|
219
221
|
| `better-auth-setup` | Better Auth + Hono + Drizzle + PostgreSQL |
|
|
220
222
|
| `pyx-scan` | Check if an AI agent skill is safe before installing |
|
|
221
223
|
| `dokkit` | Document template filling for DOCX/HWPX |
|
|
@@ -245,7 +247,7 @@ Selected during install. Run `npx devlyn-cli` again to add more.
|
|
|
245
247
|
|---|---|
|
|
246
248
|
| `playwright` | Playwright MCP — powers `/devlyn:resolve` BUILD_GATE browser tier (Chrome MCP → Playwright → curl fallback) |
|
|
247
249
|
|
|
248
|
-
> `--engine
|
|
250
|
+
> `--engine codex` and conditional VERIFY pair mode use the local `codex` CLI binary, not MCP. Install from https://platform.openai.com/docs/codex, run the current Codex auth/login flow, verify `codex --version`, then rerun.
|
|
249
251
|
|
|
250
252
|
</details>
|
|
251
253
|
|
package/bin/devlyn.js
CHANGED
|
@@ -7,7 +7,6 @@ const readline = require('readline');
|
|
|
7
7
|
const { execSync } = require('child_process');
|
|
8
8
|
|
|
9
9
|
const CONFIG_SOURCE = path.join(__dirname, '..', 'config');
|
|
10
|
-
const AGENTS_SOURCE = path.join(__dirname, '..', 'agents-config');
|
|
11
10
|
const OPTIONAL_SKILLS_SOURCE = path.join(__dirname, '..', 'optional-skills');
|
|
12
11
|
const PKG = require('../package.json');
|
|
13
12
|
|
|
@@ -31,7 +30,6 @@ const CLI_TARGETS = {
|
|
|
31
30
|
name: 'Codex CLI (OpenAI)',
|
|
32
31
|
instructionsFile: 'AGENTS.md',
|
|
33
32
|
baseInstructionsFile: 'AGENTS.md',
|
|
34
|
-
configDir: null, // Codex uses AGENTS.md at project root
|
|
35
33
|
// Codex auto-loads skills from ~/.codex/skills/ (user-global). Same
|
|
36
34
|
// SKILL.md format as Claude Code; descriptions must stay ≤1024 chars.
|
|
37
35
|
skillsDir: path.join(os.homedir(), '.codex', 'skills'),
|
|
@@ -42,7 +40,6 @@ const CLI_TARGETS = {
|
|
|
42
40
|
name: 'oh-my-pi (omp)',
|
|
43
41
|
instructionsFile: 'AGENTS.md',
|
|
44
42
|
baseInstructionsFile: 'AGENTS.md',
|
|
45
|
-
configDir: null, // omp discovers AGENTS.md at project root + user home
|
|
46
43
|
// omp loads skills from ~/.agents/skills (user home) — shared with Pi.
|
|
47
44
|
skillsDir: SHARED_AGENTS_SKILLS_DIR,
|
|
48
45
|
skillsToInstall: DEVLYN_CORE_SKILLS,
|
|
@@ -54,37 +51,12 @@ const CLI_TARGETS = {
|
|
|
54
51
|
name: 'Pi (earendil-works)',
|
|
55
52
|
instructionsFile: 'AGENTS.md',
|
|
56
53
|
baseInstructionsFile: 'AGENTS.md',
|
|
57
|
-
configDir: null, // Pi reads AGENTS.md / CLAUDE.md walking up from cwd
|
|
58
54
|
// Pi loads skills from ~/.agents/skills — shared with oh-my-pi.
|
|
59
55
|
skillsDir: SHARED_AGENTS_SKILLS_DIR,
|
|
60
56
|
skillsToInstall: DEVLYN_CORE_SKILLS,
|
|
61
57
|
// Project-scoped only (see omp): machine-level ~/.pi must not auto-trigger.
|
|
62
58
|
detect: () => fs.existsSync(path.join(process.cwd(), '.pi')) || fs.existsSync(path.join(process.cwd(), '.agents')),
|
|
63
59
|
},
|
|
64
|
-
gemini: {
|
|
65
|
-
name: 'Gemini CLI (Google)',
|
|
66
|
-
instructionsFile: 'GEMINI.md',
|
|
67
|
-
configDir: null, // Gemini uses GEMINI.md at project root
|
|
68
|
-
detect: () => fs.existsSync(path.join(process.cwd(), 'GEMINI.md')) || fs.existsSync(path.join(process.cwd(), '.gemini')),
|
|
69
|
-
},
|
|
70
|
-
cursor: {
|
|
71
|
-
name: 'Cursor',
|
|
72
|
-
instructionsFile: '.cursorrules',
|
|
73
|
-
configDir: '.cursor/rules',
|
|
74
|
-
detect: () => fs.existsSync(path.join(process.cwd(), '.cursorrules')) || fs.existsSync(path.join(process.cwd(), '.cursor')),
|
|
75
|
-
},
|
|
76
|
-
copilot: {
|
|
77
|
-
name: 'GitHub Copilot',
|
|
78
|
-
instructionsFile: '.github/copilot-instructions.md',
|
|
79
|
-
configDir: '.github/copilot/agents',
|
|
80
|
-
detect: () => fs.existsSync(path.join(process.cwd(), '.github', 'copilot-instructions.md')) || fs.existsSync(path.join(process.cwd(), '.github', 'copilot')),
|
|
81
|
-
},
|
|
82
|
-
windsurf: {
|
|
83
|
-
name: 'Windsurf',
|
|
84
|
-
instructionsFile: '.windsurfrules',
|
|
85
|
-
configDir: '.windsurf/rules',
|
|
86
|
-
detect: () => fs.existsSync(path.join(process.cwd(), '.windsurfrules')) || fs.existsSync(path.join(process.cwd(), '.windsurf')),
|
|
87
|
-
},
|
|
88
60
|
};
|
|
89
61
|
|
|
90
62
|
// Files removed in previous versions that should be cleaned up on upgrade
|
|
@@ -214,7 +186,7 @@ const OPTIONAL_ADDONS = [
|
|
|
214
186
|
{ name: 'asset-creator', desc: 'AI pixel art game asset pipeline — generate, chroma-key, catalog', type: 'local' },
|
|
215
187
|
{ name: 'cloudflare-nextjs-setup', desc: 'Cloudflare Workers + Next.js deployment with OpenNext', type: 'local' },
|
|
216
188
|
{ name: 'generate-skill', desc: 'Create well-structured Claude Code skills following Anthropic best practices', type: 'local' },
|
|
217
|
-
{ name: 'prompt-engineering', desc: 'Claude
|
|
189
|
+
{ name: 'prompt-engineering', desc: 'Claude prompt optimization using Anthropic best practices', type: 'local' },
|
|
218
190
|
{ name: 'better-auth-setup', desc: 'Production-ready Better Auth + Hono + Drizzle + PostgreSQL auth setup', type: 'local' },
|
|
219
191
|
{ name: 'polar-billing-setup', desc: 'Polar usage-based / metered billing — correct setup + diagnose silent $0-billing failures', type: 'local' },
|
|
220
192
|
{ name: 'pyx-scan', desc: 'Check whether an AI agent skill is safe before installing', type: 'local' },
|
|
@@ -596,15 +568,13 @@ function installSkillsForCLI(cliKey) {
|
|
|
596
568
|
return copied;
|
|
597
569
|
}
|
|
598
570
|
|
|
599
|
-
// Strip
|
|
600
|
-
//
|
|
601
|
-
//
|
|
602
|
-
//
|
|
603
|
-
|
|
604
|
-
// devlyn-appended block (always last) and preserves everything above it.
|
|
571
|
+
// Strip the legacy "# Devlyn Agent Instructions" block (the retired evaluator
|
|
572
|
+
// agent) that earlier installs appended to instruction files, so upgrades scrub
|
|
573
|
+
// it instead of carrying it forever. Anchors on the LAST marker so user content
|
|
574
|
+
// above a stray copy of the block is preserved.
|
|
575
|
+
const DEVLYN_AGENTS_MARKER = '# Devlyn Agent Instructions';
|
|
605
576
|
function stripManagedBlock(content) {
|
|
606
|
-
const
|
|
607
|
-
const markerIdx = content.lastIndexOf(marker);
|
|
577
|
+
const markerIdx = content.lastIndexOf(DEVLYN_AGENTS_MARKER);
|
|
608
578
|
if (markerIdx > 0) {
|
|
609
579
|
const sepIdx = content.lastIndexOf('\n---', markerIdx);
|
|
610
580
|
return content.slice(0, sepIdx > 0 ? sepIdx : markerIdx).trimEnd();
|
|
@@ -613,63 +583,40 @@ function stripManagedBlock(content) {
|
|
|
613
583
|
}
|
|
614
584
|
|
|
615
585
|
// One-line description of exactly what selecting a CLI target installs, so the
|
|
616
|
-
// unified selector stays honest
|
|
617
|
-
// identical to "Codex" (instructions + skills).
|
|
586
|
+
// unified selector stays honest.
|
|
618
587
|
function targetDesc(cli) {
|
|
619
588
|
if (cli.skillsDir) {
|
|
620
589
|
return `${cli.instructionsFile} + devlyn skills → ${cli.skillsDir.replace(os.homedir(), '~')}`;
|
|
621
590
|
}
|
|
622
|
-
if (cli.configDir) return `Agent instructions → ${cli.configDir}/`;
|
|
623
591
|
return `${cli.instructionsFile} instructions only`;
|
|
624
592
|
}
|
|
625
593
|
|
|
626
|
-
// Install
|
|
627
|
-
//
|
|
628
|
-
//
|
|
594
|
+
// Install the packaged base instruction file for a CLI (project AGENTS.md for
|
|
595
|
+
// codex/omp/pi). Creates it from the packaged base when missing; on existing
|
|
596
|
+
// files, scrubs the legacy appended block and otherwise leaves user content
|
|
597
|
+
// untouched. Returns true when the destination was written.
|
|
629
598
|
function installInstructionsForCLI(cliKey) {
|
|
630
599
|
const cli = CLI_TARGETS[cliKey];
|
|
631
|
-
if (!cli) return false;
|
|
632
|
-
|
|
633
|
-
const
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
if (cli.configDir) {
|
|
641
|
-
// CLI supports an agents directory — copy agent files there
|
|
642
|
-
const destDir = path.join(process.cwd(), cli.configDir);
|
|
643
|
-
if (!fs.existsSync(destDir)) {
|
|
644
|
-
fs.mkdirSync(destDir, { recursive: true });
|
|
645
|
-
}
|
|
646
|
-
for (const file of agents) {
|
|
647
|
-
const src = path.join(AGENTS_SOURCE, file);
|
|
648
|
-
const dest = path.join(destDir, file);
|
|
649
|
-
fs.copyFileSync(src, dest);
|
|
650
|
-
log(` → ${cli.configDir}/${file}`, 'dim');
|
|
600
|
+
if (!cli || !cli.baseInstructionsFile) return false;
|
|
601
|
+
|
|
602
|
+
const destFile = path.join(process.cwd(), cli.instructionsFile);
|
|
603
|
+
let content = null;
|
|
604
|
+
if (fs.existsSync(destFile)) {
|
|
605
|
+
const current = fs.readFileSync(destFile, 'utf8');
|
|
606
|
+
if (current.includes(DEVLYN_AGENTS_MARKER)) {
|
|
607
|
+
content = stripManagedBlock(current) + '\n';
|
|
651
608
|
}
|
|
652
609
|
} else {
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
const agentContent = agents.map((file) => {
|
|
657
|
-
return fs.readFileSync(path.join(AGENTS_SOURCE, file), 'utf8');
|
|
658
|
-
}).join('\n\n---\n\n');
|
|
659
|
-
|
|
660
|
-
let existing = '';
|
|
661
|
-
if (fs.existsSync(destFile)) {
|
|
662
|
-
existing = stripManagedBlock(fs.readFileSync(destFile, 'utf8'));
|
|
663
|
-
} else if (cli.baseInstructionsFile) {
|
|
664
|
-
const baseInstructionsSrc = path.join(__dirname, '..', cli.baseInstructionsFile);
|
|
665
|
-
if (fs.existsSync(baseInstructionsSrc)) {
|
|
666
|
-
existing = stripManagedBlock(fs.readFileSync(baseInstructionsSrc, 'utf8'));
|
|
667
|
-
}
|
|
610
|
+
const baseInstructionsSrc = path.join(__dirname, '..', cli.baseInstructionsFile);
|
|
611
|
+
if (fs.existsSync(baseInstructionsSrc)) {
|
|
612
|
+
content = fs.readFileSync(baseInstructionsSrc, 'utf8');
|
|
668
613
|
}
|
|
669
|
-
|
|
670
|
-
fs.writeFileSync(destFile, existing + separator + agentContent + '\n');
|
|
671
|
-
log(` → ${cli.instructionsFile} (agent instructions appended)`, 'dim');
|
|
672
614
|
}
|
|
615
|
+
if (content === null) return false;
|
|
616
|
+
|
|
617
|
+
log(`\n🤖 Installing instructions for ${cli.name}...`, 'cyan');
|
|
618
|
+
fs.writeFileSync(destFile, content);
|
|
619
|
+
log(` → ${cli.instructionsFile}`, 'dim');
|
|
673
620
|
return true;
|
|
674
621
|
}
|
|
675
622
|
|
|
@@ -696,7 +643,7 @@ function installSelectedCLITargets(cliKeys) {
|
|
|
696
643
|
for (const cliKey of cliKeys) {
|
|
697
644
|
const cli = CLI_TARGETS[cliKey];
|
|
698
645
|
if (!cli) continue;
|
|
699
|
-
const instrKey = cli.
|
|
646
|
+
const instrKey = cli.instructionsFile;
|
|
700
647
|
if (!instrDone.has(instrKey)) {
|
|
701
648
|
installInstructionsForCLI(cliKey);
|
|
702
649
|
instrDone.add(instrKey);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# Claude
|
|
1
|
+
# Claude 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
|
|
7
|
+
You are Claude 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
|
|
|
@@ -125,14 +125,14 @@ Top-level wrapper:
|
|
|
125
125
|
"status": "sign | block",
|
|
126
126
|
"blocked_ids": [],
|
|
127
127
|
"signed_plan_sha256": "...", // canonical pre-stamp sha (see below)
|
|
128
|
-
"model": "claude
|
|
128
|
+
"model": "<exact claude model id>",
|
|
129
129
|
"timestamp": "2026-04-29T..."
|
|
130
130
|
},
|
|
131
131
|
"codex": {
|
|
132
132
|
"status": "sign | block",
|
|
133
133
|
"blocked_ids": [],
|
|
134
134
|
"signed_plan_sha256": "...",
|
|
135
|
-
"model": "
|
|
135
|
+
"model": "<exact codex model id>",
|
|
136
136
|
"timestamp": "..."
|
|
137
137
|
}
|
|
138
138
|
}
|
|
@@ -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/<engine>.md` (e.g. `claude.md`, `codex.md`) to the canonical phase body. Adapter is the per-model delta (Anthropic's
|
|
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 prompt-engineering guide for Claude, OpenAI's prompt guidance 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.
|
|
@@ -39,7 +39,7 @@ Each phase routes to an engine and prepends the per-engine adapter header from `
|
|
|
39
39
|
<modes>
|
|
40
40
|
Three input shapes:
|
|
41
41
|
|
|
42
|
-
1. **Free-form**: `/devlyn:resolve "fix the login bug"
|
|
42
|
+
1. **Free-form**: `/devlyn:resolve "fix the login bug"` (inline goal) or `/devlyn:resolve --goal-file <path>` (goal text read from a file — the devlynd `ResolveAdapter` launcher path, injection-safe). PHASE 0 runs the complexity classifier and either proceeds with an internal mini-spec (trivial), drafts focused questions for in-prompt resolution (medium), or escalates to `/devlyn:ideate` (large/ambiguous). No mid-pipeline prompts in any branch.
|
|
43
43
|
2. **Spec**: `/devlyn:resolve --spec docs/roadmap/phase-N/X.md`. Spec is read-only. Stage verification commands from sibling `spec.expected.json`; if absent, use the legacy `## Verification` JSON block.
|
|
44
44
|
3. **Verify-only**: `/devlyn:resolve --verify-only <diff-or-PR-ref> --spec <path>`. Skips PHASE 1-4. Runs PHASE 5 (VERIFY) on the supplied diff against the spec.
|
|
45
45
|
</modes>
|
|
@@ -58,6 +58,7 @@ Once `state.implement_passed_sha` is non-null (PHASE 2 returned and produced a d
|
|
|
58
58
|
- `--engine MODE` (default `claude`) — picks the adapter for IMPLEMENT, CLEANUP, and the primary VERIFY judge. It does not disable VERIFY pair-mode; when a VERIFY pair trigger fires, the second judge uses the OTHER engine.
|
|
59
59
|
- `--spec <path>` — switches to spec mode.
|
|
60
60
|
- `--verify-only <ref>` — switches to verify-only mode. Requires `--spec`.
|
|
61
|
+
- `--goal-file <path>` — free-form mode: read the goal text from `<path>` (relative to cwd) instead of an inline positional goal. Used by the devlynd `ResolveAdapter` launcher (goal written to `.devlyn/goal.txt`, referenced by path — never inlined as argv). The file content is opaque goal text fed to the complexity classifier, **never re-parsed as flags**. Mutually exclusive with `--spec`, `--verify-only`, and an inline positional goal.
|
|
61
62
|
- `--pair-verify` — force pair-mode JUDGE in PHASE 5 even when not auto-triggered.
|
|
62
63
|
- `--no-pair` — disable conditional VERIFY pair-JUDGE for this run. Record `pair_trigger.skipped_reason: "user_no_pair"` whenever a trigger would otherwise fire.
|
|
63
64
|
- `--risk-probes` — insert PHASE 1.5 cross-engine probe derivation. The OTHER engine converts visible `## Verification` bullets into bounded executable probes before IMPLEMENT; BUILD_GATE and VERIFY replay them mechanically.
|
|
@@ -67,12 +68,12 @@ Once `state.implement_passed_sha` is non-null (PHASE 2 returned and produced a d
|
|
|
67
68
|
|
|
68
69
|
2. Engine pre-flight: follow `_shared/engine-preflight.md`. If a required engine is unavailable, halt with a BLOCKED verdict and setup instructions instead of downgrading.
|
|
69
70
|
|
|
70
|
-
`--pair-verify` and `--no-pair` are mutually exclusive; if both are present, stop with `BLOCKED:invalid-flags`.
|
|
71
|
+
`--pair-verify` and `--no-pair` are mutually exclusive; if both are present, stop with `BLOCKED:invalid-flags`. Likewise `--goal-file` combined with `--spec`, `--verify-only`, or an inline positional goal — or a missing/repeated `--goal-file` value — stops with `BLOCKED:invalid-flags`. (These `BLOCKED:<reason>` strings are report-level only; the JSON `phases.*.verdict` carrier in `pipeline.state.json` always stays the bare enum `"BLOCKED"`.)
|
|
71
72
|
|
|
72
73
|
3. Initialize `.devlyn/pipeline.state.json` per `references/state-schema.md`. Set `state.run_id`, `started_at`, `engine`, `pair_verify: true` only when `--pair-verify` was passed and `false` otherwise, `base_ref.{branch, sha}`, `rounds.{max_rounds, global: 0}`, `bypasses`, empty `phases`, empty `criteria`, and `risk_profile: { high_risk: false, reasons: [], risk_probes_enabled: false, pair_default_enabled: true }`. `risk_profile` is strict typed state: keep it an object, keep the three flags as JSON booleans, and keep `reasons` as a string array; never serialize booleans as strings.
|
|
73
74
|
|
|
74
75
|
4. **Mode-specific init**:
|
|
75
|
-
- **Free-form**: read `references/free-form-mode.md
|
|
76
|
+
- **Free-form**: first resolve `goal_text` — the inline positional goal, OR (when `--goal-file <path>` was passed) the raw UTF-8 content of `<path>`, read as opaque goal text (never re-parsed as flags). Fail closed before classifying: empty/whitespace-only file → `BLOCKED:goal-file-empty`; missing/unreadable/not-a-regular-file/invalid-UTF-8 → `BLOCKED:goal-file-unreadable`; an absolute path, a `..` segment, or a path that canonicalizes outside cwd → `BLOCKED:goal-file-invalid-path`. (Like all PHASE-0 halts these are report-level `BLOCKED:<reason>` strings — no `phases.*.verdict` is written, so the bare-enum carrier rule is never violated.) Then read `references/free-form-mode.md` and run the complexity classifier deterministically on `goal_text` (rules over keyword density / file count / spec-shape signals, plus pair-evidence intent). Set `state.complexity ∈ {trivial, medium, large}`. Trivial: write internal mini-spec to `.devlyn/criteria.generated.md` and proceed. Medium: synthesize a minimal spec from the goal + add 1-2 context anchors from the codebase, write to `.devlyn/criteria.generated.md`, proceed. Every free-form branch that writes criteria must set `state.source.type = "generated"`, `state.source.criteria_path = ".devlyn/criteria.generated.md"`, and `state.source.criteria_sha256` from the raw file bytes. Large: log `recommend: /devlyn:ideate first` in the final report and either halt (default) or proceed with assumed defaults if `--continue-on-large` flag set, except pair-evidence intent without an actionable solo-headroom hypothesis must halt with `BLOCKED:solo-headroom-hypothesis-required`, and unmeasured pair-candidate intent without solo ceiling avoidance must halt with `BLOCKED:solo-ceiling-avoidance-required`.
|
|
76
77
|
- **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
78
|
- **Verify-only**: skip to PHASE 5 with `state.source.spec_path` set, the supplied diff captured at `.devlyn/external-diff.patch`.
|
|
78
79
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Free-form mode — complexity classifier
|
|
2
2
|
|
|
3
|
-
When `/devlyn:resolve` is invoked with a free-form goal (no `--spec`)
|
|
3
|
+
When `/devlyn:resolve` is invoked with a free-form goal (no `--spec`) — whether the goal is the inline positional text or the content of `--goal-file <path>` (PHASE 0 resolves `goal_text` from either source before classifying) — PHASE 0 runs this classifier to set `state.complexity ∈ {trivial, medium, large}` and either proceeds with an internal mini-spec, drafts focused questions for in-prompt resolution, or recommends `/devlyn:ideate` first.
|
|
4
4
|
|
|
5
5
|
The classifier is rules-based / deterministic — not an LLM judgment call. Decision rules below.
|
|
6
6
|
|
|
@@ -71,7 +71,7 @@ Each entry under `phases.<name>` (for `plan`, `probe_derive`, `implement`, `buil
|
|
|
71
71
|
"triggered_by": null,
|
|
72
72
|
"verdict": "PASS",
|
|
73
73
|
"engine": "claude",
|
|
74
|
-
"model": "
|
|
74
|
+
"model": "<exact model id that ran this phase>",
|
|
75
75
|
"pre_sha": null,
|
|
76
76
|
"artifacts": { "findings_file": null, "log_file": null },
|
|
77
77
|
"sub_verdicts": null
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "devlyn-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
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": {
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
"!config/skills/devlyn:auto-resolve-workspace/**",
|
|
18
18
|
"!config/skills/roadmap-archival-workspace",
|
|
19
19
|
"!config/skills/roadmap-archival-workspace/**",
|
|
20
|
-
"agents-config",
|
|
21
20
|
"optional-skills",
|
|
22
21
|
"benchmark/auto-resolve/BENCHMARK-DESIGN.md",
|
|
23
22
|
"benchmark/auto-resolve/BENCHMARK-RESULTS.md",
|
package/scripts/lint-skills.sh
CHANGED
|
@@ -196,10 +196,11 @@ else
|
|
|
196
196
|
fi
|
|
197
197
|
|
|
198
198
|
# ---------------------------------------------------------------------------
|
|
199
|
-
# 4. No
|
|
199
|
+
# 4. No model-pinned Claude references, any generation. Engine-scope docs say
|
|
200
|
+
# "Claude"; exact model ids belong in run metadata only.
|
|
200
201
|
# ---------------------------------------------------------------------------
|
|
201
|
-
section "Check 4: No
|
|
202
|
-
offenders=$(grep -
|
|
202
|
+
section "Check 4: No model-pinned Claude references"
|
|
203
|
+
offenders=$(grep -RIlnE 'Claude (Opus|Sonnet|Haiku|Fable)|claude-(opus|sonnet|haiku|fable)-[0-9]' \
|
|
203
204
|
config/skills 2>/dev/null \
|
|
204
205
|
| grep -v 'config/skills/roadmap-archival-workspace/' \
|
|
205
206
|
| grep -v 'config/skills/devlyn:auto-resolve-workspace/' \
|
|
@@ -207,7 +208,7 @@ offenders=$(grep -RIln 'Claude Opus 4\.6' \
|
|
|
207
208
|
| grep -v 'config/skills/preflight-workspace/' \
|
|
208
209
|
|| true)
|
|
209
210
|
if [ -z "$offenders" ]; then
|
|
210
|
-
ok "
|
|
211
|
+
ok "no model-pinned Claude references"
|
|
211
212
|
else
|
|
212
213
|
while IFS= read -r f; do bad "$f"; done <<< "$offenders"
|
|
213
214
|
fi
|
|
@@ -1566,7 +1567,8 @@ fi
|
|
|
1566
1567
|
section "Check 10c: User-facing current docs avoid retired skill surfaces"
|
|
1567
1568
|
offenders=$(
|
|
1568
1569
|
{
|
|
1569
|
-
|
|
1570
|
+
sed '/<!-- legacy-surface-map:begin/,/<!-- legacy-surface-map:end/s/.*//' README.md 2>/dev/null \
|
|
1571
|
+
| grep -nE '/devlyn:auto-resolve|ideate CHALLENGE|--with-codex|Quick Start pointing to ideate → auto-resolve → preflight|auto-resolve'\''s build agent|Core pipeline skills \(`ideate`, `auto-resolve`, `preflight`\)' || true
|
|
1570
1572
|
grep -nE '"description": .*auto-resolve|"description": .*preflight' package.json 2>/dev/null || true
|
|
1571
1573
|
grep -nE 'so auto-resolve doesn'\''t prompt' bin/devlyn.js 2>/dev/null || true
|
|
1572
1574
|
grep -nE 'devlyn:auto-resolve|phase-1-build\.md|phase-2-evaluate\.md|phase-3-critic\.md' scripts/static-ab.sh 2>/dev/null || true
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
# Evaluator Agent
|
|
2
|
-
|
|
3
|
-
You are a code quality evaluator. Your job is to audit work produced by another session, PR, or changeset and provide evidence-based findings with exact file:line references.
|
|
4
|
-
|
|
5
|
-
## Before You Start
|
|
6
|
-
|
|
7
|
-
1. **Check for done criteria**: Read `.devlyn/runs/<run_id>/spec/expected.json` if a structured done-criteria source exists for the current run. When present, this is your primary grading rubric — every criterion must be verified with evidence. When absent, fall back to the checklists below.
|
|
8
|
-
|
|
9
|
-
## Calibration
|
|
10
|
-
|
|
11
|
-
You will be too lenient by default. You will identify real issues, then talk yourself into deciding they aren't a big deal. Fight this tendency.
|
|
12
|
-
|
|
13
|
-
**Rule**: When in doubt, score DOWN. A false negative ships broken code. A false positive costs minutes of review. The cost is asymmetric.
|
|
14
|
-
|
|
15
|
-
- A catch block that logs but doesn't surface error to user = HIGH (not MEDIUM). Logging is not error handling.
|
|
16
|
-
- A `let` that could be `const` = LOW note only. Linters catch this.
|
|
17
|
-
- "The error handling is generally quite good" = WRONG. Count the instances. Name the files.
|
|
18
|
-
|
|
19
|
-
## Evaluation Process
|
|
20
|
-
|
|
21
|
-
1. **Discover scope**: Read the changeset (git diff, PR diff, or specified files)
|
|
22
|
-
2. **Assess correctness**: Find bugs, logic errors, silent failures, missing error handling
|
|
23
|
-
3. **Check architecture**: Verify patterns match existing codebase, no type duplication, proper wiring
|
|
24
|
-
4. **Verify spec compliance**: If a spec exists (HANDOFF.md, RFC, issue, done-criteria.md), compare requirements vs implementation
|
|
25
|
-
5. **Check error handling**: Every async operation needs loading, error, and empty states in UI. No silent catches.
|
|
26
|
-
6. **Review API contracts**: New endpoints must follow existing conventions for naming, validation, error envelopes
|
|
27
|
-
7. **Assess test coverage**: New modules need tests. Run the test suite and report results.
|
|
28
|
-
8. **Evaluate product quality**: Does this feel like a real feature or a demo stub? Are workflows complete end-to-end? Is the UI coherent?
|
|
29
|
-
|
|
30
|
-
## Rules
|
|
31
|
-
|
|
32
|
-
- Every finding must have a file:line reference. No guesswork.
|
|
33
|
-
- Classify by severity: CRITICAL (must fix), HIGH (should fix), MEDIUM (fix or justify), LOW (note)
|
|
34
|
-
- Call out what's done well, not just problems
|
|
35
|
-
- Look for cross-cutting patterns (e.g., same mistake repeated in multiple files)
|
|
36
|
-
|
|
37
|
-
## Output
|
|
38
|
-
|
|
39
|
-
Write findings to `.devlyn/runs/<run_id>/eval-findings.md` for downstream consumption:
|
|
40
|
-
|
|
41
|
-
```markdown
|
|
42
|
-
# Evaluation Findings
|
|
43
|
-
|
|
44
|
-
## Verdict: [PASS / PASS WITH ISSUES / NEEDS WORK / BLOCKED]
|
|
45
|
-
|
|
46
|
-
## Done Criteria Results (if a done-criteria source existed)
|
|
47
|
-
- [x] [criterion] — VERIFIED: [evidence]
|
|
48
|
-
- [ ] [criterion] — FAILED: [what's wrong, file:line]
|
|
49
|
-
|
|
50
|
-
## Findings Requiring Action
|
|
51
|
-
### CRITICAL
|
|
52
|
-
- `file:line` — [description] — Fix: [suggested approach]
|
|
53
|
-
|
|
54
|
-
### HIGH
|
|
55
|
-
- `file:line` — [description] — Fix: [suggested approach]
|
|
56
|
-
|
|
57
|
-
## Cross-Cutting Patterns
|
|
58
|
-
- [pattern description]
|
|
59
|
-
|
|
60
|
-
## What's Good
|
|
61
|
-
- [positive observations]
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
Do NOT delete the run-directory artifacts (`spec/expected.json`, `eval-findings.md`) — the orchestrator or user is responsible for cleanup.
|