Skip to main content

Overview

This is a reusable A2A (agent-to-agent) operational pattern for executing large, cross-cutting identifier renames in monorepos with strict layering. Emerged from SKILL → DOCTRINE rename across STRATT (39 files, ~2,000 identifiers, 228 tests, 7 commits). Use case: Renaming a concept/type that cascades across multiple layers (schema → package → graph/CLI → app → docs). Time savings: ~60% vs. ad-hoc approach (4 hrs → 1.5 hrs for similar-sized project).

Workflow Steps

Phase 1: Discovery & Mapping (15 min)

Prompt to agent:
Map the monorepo’s dependency layers. For each layer, list:
  • Package/directory name
  • What it depends on (lower layers only)
  • Key files affected by the rename: types, imports, exports, config
  • Test count per layer
Verification: Agent should produce a table showing L0→L5 order with no circular deps. Example output:
L1: @stratt/schema
  - Depends on: none
  - Files: types/council.ts, types/index.ts
  - Tests: 20

L2.5: @stratt/doctrines
  - Depends on: @stratt/schema
  - Files: src/parser.ts, src/registry.ts, src/resolver.ts
  - Tests: 18
  
L3: @stratt/graph
  - Depends on: @stratt/schema, @stratt/doctrines
  - Files: src/types.ts, tests/fixtures.ts
  - Tests: 88
Stop if: Circular dependency detected. Refactor architecture first.

Phase 2: Search & Count (20 min)

Prompt to agent:
For each identifier to rename (e.g., “Skill” → “Doctrine”):
  • Count occurrences in code (exclude comments, strings, and docs)
  • List all files that contain the identifier
  • Categorize: type definitions, imports, exports, function names, config keys
  • Identify hard-cut boundaries (file extensions, config keys that need fallback)
Verification: Agent should produce grep results with line counts and file categories. Example:
Identifier: "SkillRef"
- Code occurrences: 47
- Files: schema/types.ts (12), doctrines/parser.ts (8), graph/tests/fixtures.ts (27)
- Type definitions: 3
- Imports: 12
- Exports: 2
- Config keys: 0

Identifier: ".skill.md"
- File occurrences: 39
- Locations: .opencode/doctrines/ (21), docs/atlas/doctrines/ (18)
- Recommendation: Hard-cut extension (rename all at once)

Phase 3: Dependency-Order Commit Planning (10 min)

Prompt to agent:
Based on the dependency layers from Phase 1:
  • Group the renaming work into commits that follow L0→L5 order
  • Each commit should touch one or two adjacent layers
  • After each commit, all tests in affected layers should pass
  • Generate commit messages describing what changed and why
Verification: Agent should produce ordered commit list with test targets. Example plan:
Commit 1: L1 + L2.5 (Schema + Doctrines Package)
  - Rename: SkillRefSchema → DoctrineRefSchema in schema/types.ts
  - Rename: .skill.md → .doctrine.md (all 39 files)
  - Update: packages/doctrines/src/parser.ts (extension glob)
  - Test targets: packages/schema (20), packages/doctrines (18)

Commit 2: L3 + L5 (Graph + CLI)
  - Rename: SkillBinding → DoctrineBinding in graph/src/types.ts
  - Update: graph/tests/fixtures.ts (all 26 fixtures)
  - Rename: CLI command validate-skills → validate-doctrines
  - Test targets: packages/graph (88), packages/cli (122)

Commit 3-5: L6 (App Layer)
  - Rename: components SkillCard → DoctrineCard
  - Update: routes, styles, API endpoints
  - Test target: App build (184 pages)

Commit 6: Content + Docs
  - Update: CLAUDE.md, architecture docs
  - Verify: link integrity, grep scan

Commit 7: Cleanup
  - Delete: packages/skills/ (legacy directory)
  - Delete: .skill.md files in docs/
  - Final: git status clean
Stop if: More than 8 commits needed. Consider splitting into 2 sessions.

Phase 4: Execute Commits in Order (90 min actual work)

For each commit (template):
  1. Identify files to change
    # Example for Commit 1
    rg "SkillRef" packages/schema packages/doctrines --files-with-matches
    
  2. Perform bulk replacements
    # Use sed or similar; verify with dry-run first
    rg --replace "DoctrineRef" "SkillRef" packages/schema/ -A | head
    rg "SkillRef" packages/schema/ --replace "DoctrineRef" -l | xargs sed -i 's/SkillRef/DoctrineRef/g'
    
  3. Run layer tests (BLOCKING)
    cd packages/schema && bun run test
    cd packages/doctrines && bun run test
    # Must pass 100% before proceeding
    
  4. Type check (BLOCKING)
    cd packages/schema && bun run typecheck
    
  5. Commit with message
    git add .
    git commit -m "Rename: SkillRef → DoctrineRef (L1+L2.5 Schema + Doctrines package)
    
    - Updated types in packages/schema/src/types/council.ts
    - Renamed package from @stratt/skills → @stratt/doctrines
    - Hard-cut extension: all .skill.md → .doctrine.md (39 files)
    - Updated parser glob pattern in packages/doctrines/src/parser.ts
    - Tests: 20 + 18 passing
    
    Dependency order: L1→L2.5 (no downstream impact)"
    
  6. Verify no regressions
    # Grep scan: should find only fallback/legacy references
    rg "SkillRef|SkillBinding" packages/schema packages/doctrines
    # Should return: 0 matches in functional code
    
  7. Mark complete, move to next commit
Key discipline:
  • Stop and fix if tests fail (don’t skip)
  • If blocked, revert commit, debug, re-commit
  • Use consistent commit message format (Layer + concept)

Phase 5: Final Verification (15 min)

Prompt to agent:
After all commits merged:
  • Run full test suite across all layers
  • Type check all packages
  • Grep scan for remaining old identifiers (should be 0 in code)
  • Build app (if applicable)
  • Verify git log shows 7 commits in expected order
Example verification script:
# Full test suite
cd packages/schema && bun run test && \
cd packages/doctrines && bun run test && \
cd packages/graph && bun run test && \
cd packages/cli && bun run test

# Type check
bun run typecheck

# Grep scan (should be clean)
rg "SkillRef|SkillBinding" packages/ apps/ --type ts | grep -v "legacy\|fallback\|TODO"

# App build
cd apps/meridian && bun run build

# Commit history
git log --oneline -7
Exit criteria:
  • ✅ All tests passing
  • ✅ No type errors
  • ✅ Grep scan clean (0 old identifiers)
  • ✅ App builds successfully
  • ✅ All 7 commits in log with clear messages

Anti-Patterns to Avoid

Renaming files and code in separate commits
  • Causes intermediate breakage (imports can’t find files)
  • Use: File rename + code update in same commit
Skipping tests between commits
  • Debt accumulates; hard to debug which commit broke things
  • Use: Run full layer tests after every commit
Renaming without grep verification
  • Old identifiers lurk in comments, strings, config defaults
  • Use: Grep scan before final cleanup commit
Attempting all layers in one commit
  • 200+ files changed = impossible to review/debug
  • Use: Max 2 adjacent layers per commit
No backward-compatibility fallback for config
  • Existing users’ configs break on update
  • Use: Optional chaining (e.g., doctrines ?? skills) in config layer only

Adapting to Your Monorepo

Questions to ask before starting:
  1. How many layers does your monorepo have? (Identify L0→Ln)
  2. Are there circular dependencies? (Fix first; hard cut won’t help)
  3. What percentage of changes are in tests vs. production code? (Expect ~30% test updates)
  4. Do any external repos depend on your package? (If yes, need soft migration + deprecation warnings)
  5. Is there config that references the old name? (If yes, add fallback layer)
Scaling guide:
ScopeEstimated TimeLayersCommits
Small (1–5 files, 50 IDs)30 min22
Medium (10–50 files, 500 IDs)1.5 hrs3–43–4
Large (50–100+ files, 2000+ IDs)3–4 hrs4–66–8
Extra-large (200+ files, 5000+ IDs)6–8 hrs6+8–12
STRATT was Large (39 files, ~2,000 IDs, 4 hours end-to-end).

Output Template for Documentation

After executing, document in your repo:
# Refactor: [OLD_NAME] → [NEW_NAME]

## Overview
- Scope: [X] files, [Y] identifiers
- Layers affected: [L1, L2.5, L3, L5]
- Tests: [Z] total, all passing
- Time: [X] hours
- Git commits: [N]

## Dependency Order
1. L1 (schema) — 20 tests
2. L2.5 (doctrines package) — 18 tests
3. L3+L5 (graph+CLI) — 88+122 tests
4. L6 (app) — build success
5. Content + docs
6. Cleanup

## Verification Checklist
- ✅ All tests passing
- ✅ Type check clean
- ✅ Grep scan: 0 old identifiers in code
- ✅ Build successful
  • Learnings: devarno-cloud/atlas/learnings/2026-04-03-skill-doctrine-rename-execution.md
  • STRATT implementation: stratt-hq/.opencode/doctrines/
  • Commit history: stratt-hq (commits 1–7, Phase 1)