feat(v2): skills overhaul - shadow paths and init migration#168
feat(v2): skills overhaul - shadow paths and init migration#168
Conversation
…Phase 0) Rename input-validation → boundary-validation and upgrade to V2 format: - Iron Law cites Alexis King's "Parse, don't validate" [1] - New sources.md with 25-source bibliography (books, standards, papers) - Boundary taxonomy table with trust levels per boundary type - Design by Contract connection (Meyer/Minsky) - All patterns.md and violations.md entries cite sources with [n] format - detection.md kept unchanged (grep patterns, no literature to cite) This establishes the template format for all V2 skill upgrades.
Directory renames: security-patterns → security test-patterns → testing performance-patterns → performance core-patterns → software-design input-validation → boundary-validation (Phase 0) architecture-patterns → architecture frontend-design → ui-design Cross-codebase reference updates (63 files): - plugins.ts: DEVFLOW_PLUGINS skill arrays + 7 prefixed legacy entries - 7 plugin.json manifests: skill arrays synced - 7 agent .md files: frontmatter skills + body references - reviewer.md: Focus Areas table paths + focus keys + Conditional Activation - ambient-router SKILL.md + skill-catalog.md: all intent tables - review-orchestration, review-methodology, TDD: cross-refs - 4 command files: code-review, code-review-teams, implement-teams, ambient-prompt - 7 test files: fixtures updated to new names - CLAUDE.md + README.md: documentation paths and names
Upgrade the Go language skill to V2 format with 25 literature-backed sources. Every pattern and violation section now cites specific Go team docs, Rob Pike's blog, Dave Cheney's articles, and Hoare's CSP paper. Key additions: - references/sources.md: full bibliography (25 sources, all free URLs) - SKILL.md: Iron Law cites Pike [5][7], boundary taxonomy removed to keep file ≤150 lines, citations on every section heading - references/patterns.md: citations on all 8 extended patterns - references/violations.md: citations on all 9 violation categories - references/concurrency.md: enriched with CSP lineage [9][10] and errgroup structured concurrency [22][13]
Add references/sources.md with 25 annotated sources (PEPs 20/484/544/557/695, Fluent Python, Effective Python, Cosmic Python, Pydantic, pytest, mypy, asyncio docs, structlog, Dropbox case study, Google Style Guide). Update SKILL.md (≤156 lines) with [n] inline citations for all patterns. Update references/patterns.md, violations.md, and async.md with source-backed explanations: Protocol vs ABC decision, dataclass/Pydantic split, structured concurrency with TaskGroup, Dropbox typing migration evidence. Co-Authored-By: Claude <noreply@anthropic.com>
Add references/sources.md with 30 curated sources (The Book, Rust API Guidelines, Rustonomicon, Effective Rust, RustBelt, Stacked Borrows, thiserror/anyhow docs, tokio docs, etc.). Update SKILL.md with [n] citations on every pattern and the Iron Law. Enrich ownership.md with Stacked Borrows model citations. Add citations throughout patterns.md and violations.md covering API design (C-NEWTYPE, C-BUILDER, C-BORROW), error handling philosophy, concurrency safety, and unsafe soundness. SKILL.md kept at 148 lines (within 150-line limit).
Upgrades the TypeScript skill to V2 literature-backed format with 25 primary sources including Effective TypeScript Items 43, 28, 33, 37, and the TypeScript Handbook, Zod, and academic references. - SKILL.md: rewritten at exactly 150 lines with [n] citations throughout; adds branded types and conditional/mapped types sections - references/sources.md: new file with 25 annotated sources across primary, branded typing, and type system theory categories - references/patterns.md: rebuilt with section-level citations; adds branded types, conditional types, template literal utilities, schema guards - references/violations.md: rebuilt with citations per violation; adds branded type omission section and async anti-patterns with source attribution - references/utility-types.md: new — covers built-ins, deep transforms, key manipulation, function/tuple/template literal utilities, branded types - references/type-guards.md: new — covers built-in narrowing, primitive guards, object shape guards, discriminated union guards, assertion functions, composable guards, schema-backed guards, and guard violations - references/async.md: new — covers Result-based async, Promise utilities, controlled concurrency, cancellation, debounce/throttle, lazy initialization, async generators, and anti-patterns with citations Iron Law citation: "Prefer unknown to any" — Effective TypeScript Item 43 [1]
Rewrites the React skill to V2 format: SKILL.md trimmed from 277→143 lines (below 150-line target) with inline [n] citations. Three new reference files (hooks.md, forms.md, error-handling.md) extract depth that was previously missing. sources.md adds 24 entries covering react.dev, Abramov's essays, RFC 188, Fiber architecture, Patterns.dev, React Compiler, WCAG 2.2, and Core Web Vitals. All patterns and violations in existing references updated with [n] citations.
Upgrade ui-design skill to V2 format with 30-source bibliography covering Material Design 3, Laws of UX, Norman's affordance theory, Bringhurst/Butterick typography, Müller-Brockmann grid mathematics, W3C design tokens, and WCAG 2.2. - SKILL.md trimmed to 144 lines with [n] citations throughout - references/sources.md created (30 sources: 20 primary + 10 standards) - references/patterns.md updated with citations for all patterns - references/violations.md updated with citations for all violations - Iron Law anchored to Norman [11] and Laws of UX [4] - Three-layer token architecture cited to Material Design 3 [1] + W3C [9] - 4px/8px grid cited to Müller-Brockmann [13] + Material Design [1] - Gestalt proximity principles cited to IxDF [5] throughout spacing section - AI slop detection table cites Hick's Law [4] and Refactoring UI [15]
Add sources.md bibliography (20 sources) and update SKILL.md, patterns.md, and violations.md with [n] citations. Key additions: - Test doubles taxonomy from Meszaros [1] and Fowler [9] - Testing shapes debate: pyramid [6] vs trophy [7] vs Google [4] - Property-based testing from QuickCheck [5] + fast-check [14] - Flaky test root causes from Google research [11][18] - Characterization tests from Feathers [16] - SKILL.md trimmed to 139 lines with progressive disclosure to references/
Add references/sources.md with 25 sources spanning Railway Oriented Programming (Wlaschin), Functional Core/Imperative Shell (Bernhardt), DI (Fowler), immutability (Hickey/SICP), monad theory (Moggi/Wadler), and type-driven design (Minsky/King). Update SKILL.md Iron Law to cite [1][11], every pattern now carries inline citations. Update patterns.md, violations.md, checklist.md, and code-smell-violations.md with [n] references throughout. Co-Authored-By: Claude <noreply@anthropic.com>
Add references/sources.md with 25 curated sources (OWASP Top 10, OWASP API Top 10, NIST 800-63, CWE Top 25, RFC 8725, CSP Level 3, SLSA, Sigstore, Argon2, and 16 others). Update SKILL.md with [n] citations per vulnerability category, add API security (OWASP API Top 10) and supply chain (SLSA/Sigstore/SRI) sections. Update patterns.md and violations.md with inline citations. Trim SKILL.md to 115 lines (within 145-line limit). Co-Authored-By: Claude <noreply@anthropic.com>
Add sources.md bibliography (20 sources) and update SKILL.md, patterns.md, and violations.md with [n] citations. Key additions: - Test doubles taxonomy from Meszaros [1] and Fowler [9] - Testing shapes debate: pyramid [6] vs trophy [7] vs Google [4] - Property-based testing from QuickCheck [5] + fast-check [14] - Flaky test root causes from Google research [11][18] - Characterization tests from Feathers [16] - SKILL.md trimmed to 139 lines with progressive disclosure to references/
Validates that all devflow:NAME references across plugin manifests, agent frontmatter, install paths, source dir paths, the ambient hook, command files, documentation tables, and skill cross-references are consistent with the canonical getAllSkillNames() registry. Rename-proof: the valid skill set is derived at runtime, never hardcoded.
Add 3 new test categories to catch reference patterns the original 8 formats missed: - Format 9: Bare backtick-quoted names in README "Skills" sections - Format 10: Bare backtick names in skills-architecture.md tables - Format 11: Relative skill-directory cross-references (name/references/) Also expand Format 5 to scan ALL hook scripts (not just ambient-prompt). Fix stale `commit` → `git-workflow` in devflow-resolve README caught by Format 9. 18 skill reference tests, 556 total tests passing.
The V2 rename of `test-patterns` → `testing` accidentally changed the reviewer Focus Areas table from `tests` to `testing`. But all orchestrators (code-review command, review-orchestration skill) send focus=`tests`. - reviewer.md: Focus Areas `testing` → `tests`, Conditional Activation same - skill-references.test.ts: Update completeness test focus area mapping
Add 8 new tests validating runtime agreement between components:
- Reviewer Focus Areas ↔ code-review command focus names
- Reviewer Focus Areas ↔ code-review command skill mappings
- Review-orchestration core reviewers ↔ reviewer Focus Areas
- Review-orchestration conditional reviewers ↔ reviewer Focus Areas
- Stale devflow:{focus}-patterns template detection
- Code-review-teams install paths are canonical
- Coder domain skill paths cover all language/ecosystem skills
Fix code-review.md: remove stale `Apply devflow:{focus}-patterns`
template that generated wrong skill names after V2 renames (e.g.,
`devflow:security-patterns` instead of `devflow:security`). Replaced
with Focus Areas table reference.
26 skill reference tests, 564 total tests passing.
…and old-name detection - Recursive scan of tests/**/*.ts (was flat tests/*.ts only) - New PREAMBLE ↔ hook alignment test catches drift between tests/integration/helpers.ts and scripts/hooks/ambient-prompt - Old V2-renamed skill name detection across all test files with allowlists for intentional migration test data
If a user had `devflow skills shadow core-patterns`, the override at ~/.devflow/skills/core-patterns/ would be orphaned after V2 rename. Now init detects old shadow dirs and renames them to V2 names. Warns without overwriting when both old and new shadows exist.
Format 3 now scans ALL shared agents and ALL command files for ~/.claude/skills/devflow:NAME/ install paths (was reviewer.md + coder.md only). New Format 3b validates ~/.devflow/skills/NAME/ shadow path references in docs against canonical skill names.
Update init command and tests to support backward compatibility with shadow skill path structure, allowing users to override installed skills without rebuilding the full distribution. Co-Authored-By: Claude <noreply@anthropic.com>
| | `security` | devflow:security | | ||
| | `performance` | devflow:performance | | ||
| | `architecture` | devflow:architecture | | ||
| | `testing` | devflow:testing | |
There was a problem hiding this comment.
CRITICAL: Focus name mismatch
The review-methodology SKILL.md Integration table was changed to use testing as the focus name (line 110), but the canonical focus name used by the reviewer agent, code-review commands, and review-orchestration skill is tests. This creates a dispatch mismatch.
Fix: Change line 110 from:
| `testing` | devflow:testing |
to:
| `tests` | devflow:testing |
This matches the pattern used everywhere else: the Focus column uses the focus identifier (tests), the Pattern Skill column uses the skill reference (devflow:testing).
Confidence: 95% (Consistency review)
Category: Blocking
Claude Code Review • /code-review
tests/skill-references.test.ts
Outdated
|
|
||
| import { describe, it, expect } from 'vitest'; | ||
| import { readFileSync, readdirSync, statSync } from 'fs'; | ||
| import { promises as fs } from 'fs'; |
There was a problem hiding this comment.
Should Fix: Unused import
The import { promises as fs } on line 11 is never used. All file operations in this file use the sync imports from line 10 (readFileSync, readdirSync, statSync). This is dead code that should be removed.
Fix: Remove this entire line:
import { promises as fs } from 'fs';Confidence: 95% (TypeScript review)
Category: Should Fix
Claude Code Review • /code-review
src/cli/commands/init.ts
Outdated
| const oldShadow = path.join(shadowsRoot, oldName); | ||
| const newShadow = path.join(shadowsRoot, newName); | ||
| try { | ||
| await fs.access(oldShadow); |
There was a problem hiding this comment.
Should Fix: Nested try/catch control flow complexity
The migrateShadowOverrides function uses nested try/catch blocks with fs.access to determine file existence. The catch blocks carry semantic meaning but are empty, which inverts the reader's expectations. The nesting depth and inverted control flow reduce readability.
Fix: Extract an explicit existence check helper:
async function exists(p: string): Promise<boolean> {
try { await fs.access(p); return true; } catch { return false; }
}
export async function migrateShadowOverrides(devflowDir: string): Promise<{ migrated: number; warnings: string[] }> {
const shadowsRoot = path.join(devflowDir, 'skills');
let migrated = 0;
const warnings: string[] = [];
for (const [oldName, newName] of SHADOW_RENAMES) {
const oldShadow = path.join(shadowsRoot, oldName);
const newShadow = path.join(shadowsRoot, newName);
if (!await exists(oldShadow)) continue;
if (await exists(newShadow)) {
warnings.push(`Shadow '${oldName}' found alongside '${newName}' -- keeping '${newName}', old shadow at ${oldShadow}`);
continue;
}
await fs.rename(oldShadow, newShadow);
migrated++;
}
return { migrated, warnings };
}Confidence: 85% (Complexity review)
Category: Should Fix
Claude Code Review • /code-review
src/cli/commands/init.ts
Outdated
| let migrated = 0; | ||
| const warnings: string[] = []; | ||
|
|
||
| for (const [oldName, newName] of SHADOW_RENAMES) { |
There was a problem hiding this comment.
Blocking: Sequential I/O in migrateShadowOverrides
The function performs sequential fs.access and fs.rename calls inside a for...of loop over SHADOW_RENAMES (7 entries). Each iteration issues 1-2 filesystem calls sequentially, totaling up to 14 sequential I/O operations. These are independent per rename entry and should be parallelized.
Fix: Use Promise.all with map:
export async function migrateShadowOverrides(devflowDir: string): Promise<{ migrated: number; warnings: string[] }> {
const shadowsRoot = path.join(devflowDir, 'skills');
const warnings: string[] = [];
const results = await Promise.all(
SHADOW_RENAMES.map(async ([oldName, newName]) => {
const oldShadow = path.join(shadowsRoot, oldName);
const newShadow = path.join(shadowsRoot, newName);
try {
await fs.access(oldShadow);
try {
await fs.access(newShadow);
warnings.push(`Shadow '${oldName}' found alongside '${newName}' — keeping '${newName}', old shadow at ${oldShadow}`);
return 0;
} catch {
await fs.rename(oldShadow, newShadow);
return 1;
}
} catch {
return 0;
}
})
);
return { migrated: results.reduce((sum, n) => sum + n, 0), warnings };
}This eliminates ~7-14ms of sequential filesystem latency from every init run.
Confidence: 82% (Performance review)
Category: Blocking
Claude Code Review • /code-review
| */ | ||
|
|
||
| import { describe, it, expect } from 'vitest'; | ||
| import { readFileSync, readdirSync, statSync } from 'fs'; |
There was a problem hiding this comment.
Should Fix: Test I/O consistency — sync vs async pattern
This new test file uses readFileSync, readdirSync, and statSync throughout (~30 call sites), while all other test files in the codebase (init-logic.test.ts, skill-namespace.test.ts, skills.test.ts) use async patterns with fs.promises.
While the file does import promises as fs on line 11, it's never used. Sync I/O blocks the Node.js event loop and can cause slower test execution, particularly on network mounts or slow storage. More importantly, this breaks test suite consistency.
Fix: Replace sync calls with async equivalents to match the project's test convention:
readFileSync(path)→await fs.readFile(path, 'utf-8')readdirSync(path)→await fs.readdir(path)statSync(path)→await fs.stat(path)
This also allows removal of the unused line 11 import.
Confidence: 80% (Tests review)
Category: Should Fix
Claude Code Review • /code-review
tests/skill-references.test.ts
Outdated
| const coreMatch = orchContent.match(/^\*\*7 core reviewers\*\*[^:]*:\s*\n-\s*(.+)$/m); | ||
| expect(coreMatch, 'review-orchestration should list 7 core reviewers').toBeTruthy(); | ||
|
|
||
| const coreReviewers = coreMatch![1].split(',').map(s => s.trim()); |
There was a problem hiding this comment.
Should Fix: Non-null assertions after expect
Two locations in this test use the pattern expect(match).toBeTruthy() followed by match![1], which uses TypeScript non-null assertion (!). While the preceding expect guarantees truthy at test time, this is an anti-pattern — prefer type narrowing over assertions. If the regex changes and match becomes null, the ! would cause a runtime crash rather than a clear test failure on the expect line.
Fix: Use a guarded narrowing or helper function:
// Option 1: Guarded check
if (!coreMatch) {
expect.unreachable('review-orchestration should list 7 core reviewers');
}
const coreReviewers = coreMatch[1].split(',').map(s => s.trim());
// Option 2: Helper function
function expectMatch(value: RegExpMatchArray | null, msg: string): RegExpMatchArray {
expect(value, msg).toBeTruthy();
return value!; // Single point of assertion
}Confidence: 82% (TypeScript review)
Category: Should Fix
Claude Code Review • /code-review
Code Review Summary: feat/v2-skills-overhaul (PR #168)Inline Comments CreatedI've created 7 inline comments with issues ≥80% confidence: BLOCKING (Must fix before merge):
SHOULD FIX (Address before merge): Lower Confidence Findings (60-79%)Summary comment only, no inline comments:
Overall AssessmentScores:
Verdict: CHANGES_REQUESTED This PR executes an excellent large-scale skill rename with robust testing (950-line new test file with 29 tests, all passing). The architecture is sound. Once the 7 blocking/should-fix comments are addressed, this is ready to merge. Key Strengths:
Claude Code Review • /code-review |
Empty catch was swallowing all errors silently, including non-transient ones like SyntaxError from JSON.parse. Rethrow on the last attempt so failures surface rather than returning a silent fallback result. Co-Authored-By: Claude <noreply@anthropic.com>
…nd Promise.all Replace 3-level nested try/catch (using empty catch bodies to signal existence) with an explicit shadowExists() boolean helper. Parallelize the 7 independent rename checks using Promise.all + map, cutting down on sequential I/O stalls at startup. Co-Authored-By: Claude <noreply@anthropic.com>
- Remove unused `promises as fs` import (all I/O is intentionally sync) - Add comment explaining the sync I/O design choice - Extract findStaleNameOccurrences() helper to reduce triple-nested loop complexity in old-name detection test - Replace non-null assertions at lines 871/892 with type-narrowing `if (!match)` guards using expect.unreachable() Co-Authored-By: Claude <noreply@anthropic.com>
…e scanner - Add 2 tests in plugins.test.ts verifying SHADOW_RENAMES old names appear in LEGACY_SKILL_NAMES and new names are valid skills - Hoist devflow-prefix regex out of inner loop in findStaleNameOccurrences
… name Rename 6 skill directories that still had -patterns suffix: - complexity-patterns → complexity - consistency-patterns → consistency - regression-patterns → regression - database-patterns → database - dependencies-patterns → dependencies - documentation-patterns → documentation Align reviewer focus name: tests → testing (skill name and focus name now match 1:1 across all focuses). Update all external references: reviewer.md, code-review.md, code-review-teams.md, review-methodology SKILL.md, review-orchestration SKILL.md, ambient-router SKILL.md + catalog, plugin.json manifests, plugins.ts (DEVFLOW_PLUGINS, LEGACY_SKILL_NAMES, SHADOW_RENAMES), docs/reference/skills-architecture.md, and plugin README. Simplify test focusName logic: was testing == 'testing' ? 'tests' : skill.replace(/-patterns$/, ''); now just skill (all focus names equal their skill name directly). Co-Authored-By: Claude <noreply@anthropic.com>
- Update frontmatter name: field in 6 renamed SKILL.md files to match directory names (complexity, consistency, database, dependencies, documentation, regression) - Fix stale `tests` focus name in README focus table -> `testing` - Remove duplicate bare old names from LEGACY_SKILL_NAMES - Simplify skill-references test by inlining focusName variable - Add frontmatter name-matches-directory guard test in build.test.ts
…o unified git skill Three overlapping git-related skills merged into one `git` skill with progressive disclosure via references/. Reduces skill count 39→37, eliminates cross-linking complexity, aligns with language skill convention. - Created shared/skills/git/ (SKILL.md + 5 reference files) - Deleted git-safety/, git-workflow/, github-patterns/ (12 files) - Updated agent frontmatter (git.md, coder.md, resolver.md) - Updated ambient-router, implement commands, plugin manifests - Added 3 SHADOW_RENAMES entries for shadow override migration - Updated docs and tests
devflow:git-safety, devflow:git-workflow, devflow:github-patterns were left behind after init because LEGACY_SKILL_NAMES only had bare names.
…nstall" This reverts commit 9045464.
Code Review Summary: PR #168Blocking Issues (≥80% Confidence) — Require Fixes Before Merge1. Race Condition in
|
| Severity | Count | Status |
|---|---|---|
| BLOCKING | 4 | Require fixes |
| SHOULD-FIX | 3 | Recommended before merge |
Overall recommendation: CHANGES_REQUESTED
All findings are from comprehensive multi-reviewer analysis (security, architecture, performance, complexity, consistency, regression, testing, TypeScript, documentation reviewers). The race condition in migrateShadowOverrides is the most critical — it causes silent data loss when multiple old shadow names compete for the same target.
Review comments generated from 9 reviewer reports with 80%+ confidence findings only. Lower-confidence suggestions (60-79%) available in individual review reports.
…entries to LEGACY_SKILL_NAMES devflow-git-workflow was absent from the bare devflow- prefixed entries, leaving orphaned ~/.claude/skills/devflow-git-workflow/ for users upgrading from pre-namespace installs. devflow:git-safety, devflow:git-workflow, and devflow:github-patterns were missing from the prefixed section, leaving orphaned dirs for users who installed after namespace migration but before git consolidation. Restores the intent of the reverted commit 9045464 while also adding the missing bare entry.
…ttern - README.md: rename 'tests' reviewer focus to 'testing' (lines 19, 31) to match the canonical name used in reviewer.md, code-review.md, plugin.json, and review-orchestration everywhere else - docs/reference/file-organization.md: update skill count from 31 to 37 to reflect current shared/skills/ directory count - tests/build.test.ts: replace toBeTruthy()+non-null-assertion (match!) with if (!match) expect.unreachable(...) for proper TypeScript control-flow narrowing, consistent with the pattern used throughout skill-references.test.ts
migrateShadowOverrides used Promise.all over all SHADOW_RENAMES entries,
causing a race condition when multiple old names (git-safety, git-workflow,
github-patterns) mapped to the same target ('git'). All three branches would
concurrently pass the shadowExists check on the target, then each call
fs.rename — the last writer won and the earlier user overrides were silently
lost.
Fix: group entries by target name, run distinct-target groups in parallel
(preserving throughput), but process entries within each group sequentially
so the check-then-rename is effectively atomic per target. Adds a regression
test covering the many-to-one scenario.
Change git skill's Iron Law from "NEVER RUN GIT COMMANDS IN PARALLEL" to "EVERY COMMIT TELLS AN HONEST, ATOMIC STORY" — commit quality is the principle that compounds value; sequential ops stays as a safety rule. Also includes Simplifier cleanup of migrateShadowOverrides (removed intermediate accumulator objects, direct counters per group).
Summary
Complete V2 skills overhaul with shadow path support and init system migration. Enables users to override installed skills without full rebuild while maintaining backward compatibility with old naming schemes.
Changes
~/.devflow/skills/{name}/path allows user overrides of installed skills (~/.claude/skills/devflow:{name}/)Breaking Changes
None — fully backward compatible with existing shadow skill overrides.
Testing
Related Issues
Implements V2 skills infrastructure from project roadmap.
Created by Claude Code