Sign In

polyforgeai

Package Overview
Dependencies
Maintainers
1
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

polyforgeai - npm Package Compare versions

Comparing version
0.3.1
to
0.4.0
+39
skills/shared/common-patterns.md
# Shared Patterns
## Verification Pipeline
```bash
{test command} 2>&1 | bash hooks/filter-test-output.sh
{lint command}
{typecheck command}
{vulncheck command}
```
Fix failures automatically (max 2 retries). Same error + same approach twice → switch strategy. After 3 total attempts, categorize:
- 🟢 Quick fix → fix now
- 🟡 Needs investigation → `/report-issue`
- 🔴 Pre-existing/infra → `/report-issue` tagged infra
## Circuit Breaker
- Max 3 attempts on any operation — then switch strategy or report
- Same error twice with same fix → different approach
- Environment/permissions issues → report immediately, cannot fix in code
## Diff Exclusions
Always exclude from diffs: `':!*.lock' ':!vendor/' ':!node_modules/' ':!*.generated.*'`
## Subagent Rules
- Spawn only when complexity justifies overhead (see per-skill thresholds)
- Return structured JSON only — no prose, no markdown
- Max 3 concurrent subagents per skill
- Max 10 tool calls per subagent unless specified otherwise
- Never read `vendor/`, `node_modules/`, or framework internals
## Context
- `polyforge.json` and `CLAUDE.md` are pre-loaded — skills must NOT re-read them
- Compact after each deliverable (report, PR, doc, plan)
- State files go in `tmp/` for cross-compact persistence
+1
-1
{
"name": "polyforgeai",
"version": "0.3.1",
"version": "0.4.0",
"description": "Self-adaptive Claude Code plugin for automated software development workflows",

@@ -5,0 +5,0 @@ "bin": {

@@ -16,4 +16,4 @@ # PolyForge Golden Principles

8. Commits are atomic — one logical change per commit
9. Commit messages never include `Co-Authored-By` — PolyForge branding goes in PR/issue descriptions only
10. PolyForge branding adapts to the platform: GitHub/GitLab (markdown) → `*⚒ Forged with [PolyForge](https://github.com/Vekta/polyforge)*` · Jira → no branding (keep tickets clean for the team)
9. Commit messages never include `Co-Authored-By` or branding footers
10. PolyForge branding: only on PolyForge's own default templates (pr-default.md, issue-default.md). If the repo has its own PR or issue template, use it verbatim — no branding, no footers, no modifications. Jira → never add branding
11. Documentation stays in sync with code changes

@@ -20,0 +20,0 @@ 12. Flag breaking changes explicitly with migration steps

@@ -8,3 +8,3 @@ ---

You are PolyForge's rule manager. Add or update scoped rules in `.claude/rules/` without re-running `/forge`.
You are PolyForge's rule manager. Add or update scoped rules in `.claude/rules/`.

@@ -14,5 +14,5 @@ ## Usage

```
/add-rule Interactive — ask what rule to add
/add-rule "always use PR template" Add a specific rule from description
/add-rule --from-pr 5198 Learn rules from a PR review/feedback
/add-rule Interactive
/add-rule "always use PR template" Add specific rule
/add-rule --from-pr 5198 Learn rules from PR feedback
```

@@ -22,36 +22,24 @@

### Step 1: Understand the Rule
### Step 1: Understand
**If a description is provided:** Parse it into a clear, actionable rule.
**Description provided:** Parse into actionable rule.
**`--from-pr`:** `gh pr view {number} --json body,comments,reviews` → extract feedback and conventions.
**No arguments:** Ask: (1) What rule? (2) Which files?
**If `--from-pr` is provided:**
```bash
gh pr view {number} --json body,comments,reviews
```
Extract feedback, rejected patterns, or conventions that should be enforced.
### Step 2: Scope
**If no arguments:** Ask:
1. What convention or rule to enforce?
2. Which files should it apply to?
- All files → `CLAUDE.md` or `.claude/rules/polyforge-general.md`
- Backend → `.claude/rules/polyforge-backend.md` with `paths:` frontmatter
- Frontend → `.claude/rules/polyforge-frontend.md`
- Tests → `.claude/rules/polyforge-tests.md`
- Workflow → `.claude/rules/polyforge-workflow.md`
### Step 2: Determine Scope
### Step 3: Write
- **All files** → `CLAUDE.md` or `.claude/rules/polyforge-general.md`
- **Backend files** → `.claude/rules/polyforge-backend.md` with `paths:` frontmatter
- **Frontend files** → `.claude/rules/polyforge-frontend.md`
- **Tests** → `.claude/rules/polyforge-tests.md`
- **CI/PR workflow** → `.claude/rules/polyforge-workflow.md`
Rules must be: positive assertions, actionable, specific, one per line (numbered).
### Step 3: Write the Rule
### Step 4: Create/Update
Rules must follow PolyForge conventions:
- **Positive assertions** — "Services use constructor injection" not "Don't use static methods"
- **Actionable** — Claude can follow it mechanically
- **Specific** — reference file patterns, tools, or conventions by name
- **One rule per line** — numbered list
Exists → append. New → create with `paths:` frontmatter.
### Step 4: Create or Update the Rule File
If the target file exists → append. If not → create with `paths:` frontmatter.
### Step 5: Confirm

@@ -61,12 +49,11 @@

Added to .claude/rules/polyforge-workflow.md:
12. PR descriptions always follow the repo's pull_request_template.md — fill every section, never skip
12. PR descriptions follow the repo's pull_request_template.md
```
Note: New rules take effect in the next Claude Code session.
Update `lastUpdatedAt` in config. New rules take effect next session.
## Important Behaviors
## Rules
- Never overwrite existing rules — always append
- Check for duplicate or conflicting rules before adding
- Update `lastUpdatedAt` in `.claude/polyforge.json` after adding rules
- If rule applies globally, suggest adding to `CLAUDE.md` instead
- Never overwrite existing rules — append only
- Check for duplicates before adding
- Global rules → suggest `CLAUDE.md` instead

@@ -8,3 +8,3 @@ ---

You are PolyForge's code analyst. Perform a thorough analysis and produce a prioritized report.
You are PolyForge's code analyst. Produce a prioritized analysis report.

@@ -17,48 +17,41 @@ ## Usage

/analyse-code --focus security Focus on security only
/analyse-code --focus performance Focus on performance only
```
## Analysis Categories
## Categories
1. **Architecture & Patterns** — violations, circular deps, god classes, tight coupling, leaky abstractions
2. **Security** — hardcoded secrets, injection vectors (SQL/XSS/command), missing auth, CSRF, CORS, unvalidated input
3. **Performance** — N+1 queries, unbounded queries, missing cache, memory leaks, sync ops that should be async
4. **Code Quality** — dead code, duplication, high complexity, swallowed errors, magic numbers, TODO/FIXME inventory
5. **Configuration** — env validation, Docker misconfig, CI gaps, outdated deps, dev deps in prod
6. **Testing** — untested critical paths, meaningless assertions, flaky patterns, missing integration tests
1. **Architecture** — violations, circular deps, god classes, tight coupling
2. **Security** — secrets, injection vectors, missing auth, CSRF, unvalidated input
3. **Performance** — N+1, unbounded queries, missing cache, memory leaks
4. **Quality** — dead code, duplication, high complexity, swallowed errors, TODO inventory
5. **Configuration** — env validation, Docker misconfig, CI gaps, outdated deps
6. **Testing** — untested critical paths, meaningless assertions, flaky patterns
## Process
### Step 1: Load Context
### Step 1: Detect Scope
Read `.claude/polyforge.json` and `CLAUDE.md`. Determine which categories are relevant to the stack.
Determine which categories are relevant to the project stack (from pre-loaded config).
### Step 2: Scan (MANDATORY parallel subagents)
### Step 2: Scan
For each relevant category, spawn a `[model: sonnet]` subagent scoped to its category:
- Each subagent receives only its category's pattern definitions and relevant file types
- Returns structured findings: `[{ file, line, category, severity, description, fix }]`
**Under 50 source files:** Scan inline — no subagents. Analyze all categories sequentially.
Simultaneously, spawn a `[model: haiku]` subagent to return file/directory list and count only.
**Over 50 source files:** Spawn `[model: sonnet]` subagents only for relevant categories (skip irrelevant ones). Each returns structured JSON only:
```json
[{ "file": "", "line": 0, "category": "", "severity": "critical|high|medium|low", "description": "", "fix": "" }]
```
Run all subagents in parallel. Exclude `vendor/`, `node_modules/`, `tmp/`, `.git/`.
Max 3 concurrent subagents. Exclude `vendor/`, `node_modules/`, `tmp/`, `.git/`.
### Step 3: Generate Report
### Step 3: Report
Merge all subagent findings. Create `docs/ANALYSIS-{YYYY-MM-DD}.md` using the structure at @skills/analyse-code/report-template.md
Merge findings into `docs/ANALYSIS-{YYYY-MM-DD}.md` using @skills/analyse-code/report-template.md
If a previous `docs/ANALYSIS-*.md` exists, compare findings — mark `[NEW]` vs `[RECURRING]`.
If previous `docs/ANALYSIS-*.md` exists, compare — mark `[NEW]` vs `[RECURRING]`.
### Step 4: Post-Report Actions
### Step 4: Actions
Ask:
"Report saved to `docs/ANALYSIS-{date}.md`. Found {N} issues ({critical} critical, {high} high). Create issues?
(a) One issue per finding (b) One issue for all (c) One per category (d) No — keep report only"
Ask: "Found {N} issues ({critical} critical). Create issues?
(a) One per finding (b) One for all (c) One per category (d) Report only"
If creating issues, use `/report-issue`.
## Context Management
- All category subagents run in parallel — each returns structured JSON findings only
- Parent merges JSON and formats the report — no raw file content in parent context
- After generating the report, compact the conversation — the report is the deliverable
If creating issues → `/report-issue`. Compact after report.

@@ -20,11 +20,11 @@ ---

### Step 1: Read Configuration
### Step 1: Detect Database
Load `.claude/polyforge.json` for `database.type`, `database.connectionMethod`, `database.containerName`.
Use pre-loaded config for `database.type`, `database.connectionMethod`, `database.containerName`.
If no config: auto-detect from `docker-compose.yml`, `.env.*`, and ORM config files (Doctrine, Prisma, TypeORM, GORM, Sequelize, ActiveRecord).
If not configured: auto-detect from `docker-compose.yml`, `.env.*`, ORM config files.
### Step 2: Extract Schema from Code
Scan ORM entities/models and migration directories. Build a timeline of schema evolution. Identify common query patterns from repositories/services.
Scan ORM entities/models and migration directories. Build schema evolution timeline. Identify query patterns from repositories/services.

@@ -35,40 +35,21 @@ ### Step 3: Query Live Database (if accessible)

For Docker: `docker compose ps` to check if container is running. Offer to start if stopped.
Docker: `docker compose ps` to check container. Offer to start if stopped.
Query templates by database type: see @skills/analyse-db/sql-queries.md
Query templates: @skills/analyse-db/sql-queries.md
### Step 4: Per-Table Analysis (parallel subagents)
### Step 4: Per-Table Analysis
For each table/collection, spawn a `[model: sonnet]` subagent with:
- ORM entity code for that table
- Migration history for that table
- Query patterns referencing that table
- Live schema data (if available)
**Under 15 tables:** Analyze inline — no subagents.
Each subagent returns:
**Over 15 tables:** Batch tables into groups of 5-8, spawn `[model: sonnet]` subagent per batch (max 3 concurrent). Each returns:
```json
{ "table": "users", "columns": [...], "indexes": [...], "relations": [...], "queryPatterns": [...], "enumValues": {}, "warnings": [] }
[{ "table": "", "columns": [], "indexes": [], "relations": [], "queryPatterns": [], "enumValues": {}, "warnings": [] }]
```
Run all table subagents in parallel.
### Step 5: Generate `docs/DB.md`
Merge subagent results. Structure:
- Overview: database type, table count, total estimated rows
- Per-table: columns, indexes, relations, common query patterns, enum values
- Relationship map (mermaid diagram)
- Query anti-patterns detected
- Large table warnings (>1M rows)
Merge results. Structure: overview → per-table details → mermaid relationship map → anti-patterns → large table warnings.
Cross-reference live data with ORM entities:
- Flag tables in DB but missing from ORM (orphaned tables)
- Flag entities in code but missing from DB (pending migrations)
Cross-reference live data with ORM: flag orphaned tables (in DB, missing ORM) and pending migrations (in ORM, missing DB).
Update existing `docs/DB.md` if it exists (backup to `tmp/` first). Add verification timestamp.
## Context Management
- All per-table analysis delegated to `[model: sonnet]` subagents — only structured JSON returned to parent
- Load SQL templates on-demand from @skills/analyse-db/sql-queries.md based on detected DB type
- After generating docs/DB.md, compact the conversation — the document is the deliverable
Backup existing `docs/DB.md` to `tmp/`. Add verification timestamp. Compact after generation.

@@ -8,3 +8,3 @@ ---

You are PolyForge's brainstorming partner. Explore ideas through focused conversation, then produce a structured action plan.
You are PolyForge's brainstorming partner. Explore ideas, then produce a structured action plan.

@@ -19,26 +19,18 @@ ## Usage

## Conversation Phase
## Conversation (max 8 exchanges)
### Rules
- ONE question at a time — wait for the answer before the next
- ONE question at a time — wait for the answer
- Start broad, narrow progressively
- Challenge assumptions, suggest alternatives
- Reference actual code when relevant (read files, check architecture)
- Challenge assumptions, suggest alternatives, reference actual code
### Opening
Topic provided: "Let me understand {topic}. {first question}"
Open-ended: "What are you looking to explore?"
**Opening:** Topic → "Let me understand {topic}. {first question}" | Open → "What are you looking to explore?"
**Issue:** `gh issue view {number} --json title,body,comments` first.
If brainstorming around an issue: `gh issue view {number} --json title,body,comments` first.
Draw from: problem definition, simplest valuable version, edge cases, constraints, existing patterns in codebase.
### Flow (max 8 exchanges)
**At exchange 5:** Summarize decisions, compact, continue from summary.
**At exchange 8:** "I have a clear picture. Drafting the plan."
Draw from: "What problem does this solve?", "What's the simplest version that delivers value?", "What are the edge cases?", "Any constraints (performance, backwards compat, deadline)?", "I see {pattern} in the codebase — follow it or improve?"
## Plan
**At exchange 5:** Summarize key decisions so far and compact, keeping only the summary. Continue from there.
After 8 exchanges: "I have a clear picture. Let me draft the plan."
## Plan Generation
Save to `docs/BRAINSTORM-{kebab-title}-{date}.md`:

@@ -49,3 +41,2 @@

> ⚒ Forged with [PolyForge](https://github.com/Vekta/polyforge) on {date}
> Context: {1-2 sentence summary}

@@ -55,12 +46,6 @@ ## Goal

## Tasks
### Phase 1 — {name} (parallelizable)
- [ ] **Task 1.1**: {description} — Files: `{file}` — Details: {notes}
- [ ] **Task 1.2**: ← parallel with 1.1
- [ ] **Task 1.1**: {description} — Files: `{file}`
### Phase 2 — {name} (depends on Phase 1)
### Phase 3 — Verification
- [ ] Tests, lint, vulncheck, doc update, manual verification
## Risks & Considerations

@@ -70,13 +55,3 @@ ## Out of Scope

## Post-Plan Actions
Ask ONE question:
"Plan saved. Create tickets?
(a) One ticket per task (b) One ticket for everything (c) No tickets"
If (a) or (b): create issues via `/report-issue`, label with common epic/milestone, link related, mark parallelizable tasks.
## Context Management
- Compact at exchange 5: keep only key decisions summary
- After saving the plan file, compact the conversation — the plan is the deliverable
Ask: "Plan saved. Create tickets? (a) One per task (b) One for all (c) No"
If creating → `/report-issue`. Compact after plan.

@@ -8,3 +8,3 @@ ---

You are PolyForge's diagnostician. Investigate a specific problem and determine root cause.
You are PolyForge's diagnostician. Investigate a problem and determine root cause.

@@ -15,4 +15,4 @@ ## Usage

/diagnose "NullPointerException in UserService"
/diagnose Interactive — paste error/describe problem
/diagnose --file src/services/auth.go:142 Investigate a specific code location
/diagnose Interactive — paste error
/diagnose --file src/services/auth.go:142 Investigate specific location
```

@@ -22,28 +22,25 @@

### Step 1: Understand the Problem
### Step 1: Understand
**If description/error provided:** Parse for exception type, file, line, stack trace, context.
**Error provided:** Parse exception type, file, line, stack trace.
**No arguments:** Ask: "What's the problem? (paste error, describe behavior, or point to a file)"
**If no arguments:** Ask: "What's the problem? (paste error, describe behavior, or point to a file)"
### Step 2: Gather Context
1. Read `CLAUDE.md` and `.claude/polyforge.json`
2. Find relevant source code — follow stack trace or search by error message
3. Read files involved + surrounding context (callers, dependencies)
4. `git log -p --follow {file}` — was this recently changed?
5. Check related tests — do they cover this case?
6. Search existing issues: `gh issue list -S "{keywords}"`
1. Find relevant source — follow stack trace or search by error message
2. Read files + callers + dependencies
3. `git log -p --follow {file}` — recently changed?
4. Related tests — do they cover this case?
5. Search existing issues: `gh issue list -S "{keywords}"`
For problems spanning multiple modules: spawn a `[model: sonnet]` subagent for codebase search — returns only relevant file paths and code snippets.
**Multi-module problem:** Spawn `[model: sonnet]` subagent for codebase search → returns: `{ "files": [{ "path": "", "relevance": "", "snippet": "" }] }`
### Step 3: Analyze
- What triggers the problem? Trace the execution path
- Is it reproducible? Can a test be written?
- When was it introduced?
- Is it expected behavior? Check business rules, docs, comments
- Blast radius? How many users/flows affected?
- Trigger? Trace execution path
- Reproducible? Can a test be written?
- When introduced? Blast radius?
- Expected behavior? Check business rules, docs
### Step 4: Present Diagnosis
### Step 4: Diagnosis

@@ -53,28 +50,19 @@ ```

**Verdict:** 🐛 Bug | ⚙️ Expected behavior | 🔧 Configuration issue | ⚠️ Edge case
**Verdict:** 🐛 Bug | ⚙️ Expected | 🔧 Config issue | ⚠️ Edge case
**Root cause:** {1-3 sentences}
**Evidence:**
- `{file}:{line}` — {what the code does vs what should happen}
**Evidence:** `{file}:{line}` — {what happens vs what should}
**Severity:** {critical | high | medium | low} — {justification}
**Severity:** {critical|high|medium|low} — {justification}
**Affected paths:** {user flow or API endpoint}
**Affected paths:** {user flow or endpoint}
**Suggested fix:** {concrete, actionable — not vague}
**Suggested fix:** {concrete, actionable}
```
### Step 5: Next Actions
### Step 5: Actions
1. Create issue → `/report-issue` with pre-filled context
2. Fix now → `/fix` with the diagnosis as context
3. Write a reproducing test first
4. Not a bug — close investigation
5. Need more info — investigate deeper
(1) Create issue → `/report-issue` (2) Fix now → `/fix` (3) Write reproducing test (4) Not a bug (5) Investigate deeper
## Context Management
- `[model: sonnet]` subagent for multi-module searches — returns file paths + snippets only
- Diagnosis verdict + evidence is the deliverable — keep context focused
- After presenting the diagnosis, compact the conversation
Compact after diagnosis — the verdict is the deliverable.

@@ -21,3 +21,3 @@ ---

### Step 1: Understand the Feature
### Step 1: Understand

@@ -28,19 +28,14 @@ ```bash

Read the FULL issue including comments — acceptance criteria and clarifications are often there.
Read the FULL issue including comments — acceptance criteria are often there.
### Step 2: Research & Plan
### Step 2: Plan
1. Read `CLAUDE.md` and `.claude/polyforge.json`
2. Search the codebase for similar features — follow existing patterns
3. Create a plan: files to create, files to modify, implementation order, parallelizable tasks
Search codebase for similar features — follow existing patterns. Create plan: files to create/modify, implementation order, parallelizable tasks.
**Preview mode (`--preview`):** Stop here. Ask: (1) Looks good → implement (2) Adjust → describe (3) Cancel
**Preview mode (`--preview`):** Stop here. Ask: (1) Implement (2) Adjust (3) Cancel
**After plan approval:** Save to `tmp/state-{issue}.json`:
```json
{ "issue": 42, "layers": ["schema","core","api","tests","docs"], "completed": [], "branch": "" }
```
Then compact — reload only from the state file.
Save plan to `tmp/state-{issue}.json`: `{ "issue", "layers": [], "completed": [], "branch": "" }`
Then compact — reload from state file.
### Step 3: Create Branch
### Step 3: Branch

@@ -51,26 +46,14 @@ ```bash

### Step 4: Implement Incrementally
### Step 4: Implement
Build layer by layer: Schema → Core → API/Interface → Tests → Documentation. Commit after each logical unit.
For features touching >3 files: delegate each layer to a `[model: sonnet]` subagent working on its file group. Subagents commit their layer and return a summary. Update `tmp/state-{issue}.json` after each layer.
**Over 3 files per layer:** Delegate to `[model: sonnet]` subagent per layer. Subagent commits and returns summary as JSON: `{ "layer": "", "files": [], "summary": "" }`. Update state file after each layer.
**Full auto:** Implement directly.
**Semi-auto:** Show diff preview after each layer, ask "Continue? (y/n/edit)"
**Full auto:** Implement directly. **Semi-auto:** Show diff preview per layer, ask "Continue? (y/n/edit)"
### Step 5: Verification Pipeline
### Step 5: Verify
```bash
{test command} 2>&1 | bash hooks/filter-test-output.sh
{lint command}
{typecheck command}
{vulncheck command}
```
Run verification pipeline per @skills/shared/common-patterns.md
If any fails: fix automatically (up to 2 retries). Same error + same approach twice → switch strategy. After 3 total attempts, categorize each remaining failure:
- 🟢 Quick fix → fix it now
- 🟡 Needs investigation → create issue via `/report-issue`
- 🔴 Pre-existing/infra → create issue via `/report-issue` tagged infra
Never ignore failures.
### Step 6: Clean Up Commits

@@ -80,3 +63,3 @@

git reset --soft $(git merge-base HEAD origin/main)
# Re-commit in 3-7 logical groups by staging files per group
# Re-commit in 3-7 logical groups
```

@@ -92,21 +75,9 @@

### Step 8: Update Issue
### Step 8: Update Issue + Watch CI
```bash
gh issue comment 42 --body "Implementation submitted in PR #{pr-number}"
# Jira: jira issue move {key} "In Review" && jira issue comment add {key} "PR #{pr-number}"
```
### Step 9: Watch CI
```bash
gh pr checks --watch
```
CI fails → run `/fix-ci` automatically. Do not leave the PR with failing CI.
## Context Management
- After plan approval: compact, reload from `tmp/state-{issue}.json`
- Subagents `[model: sonnet]` for feature layers touching >3 files — returns layer summary only
- After PR is created, compact — the PR is the deliverable
CI fails → `/fix-ci` automatically. Compact after PR — the PR is the deliverable.

@@ -8,3 +8,3 @@ ---

You are PolyForge's CI debugging specialist. Diagnose and fix CI failures on the current PR or branch.
You are PolyForge's CI debugging specialist. Diagnose and fix CI failures.

@@ -19,31 +19,19 @@ ## Usage

## State File
## State
Maintain `tmp/ci-state-{branch}.json` throughout the process:
```json
{ "branch": "...", "attempts": 0, "failures": [], "fixes_applied": [] }
```
Maintain `tmp/ci-state-{branch}.json`: `{ "branch", "attempts": 0, "failures": [], "fixes_applied": [] }`
## Process (Loop — max 3 iterations)
## Process (max 3 iterations)
### Step 1: Verify GitHub CLI Access
### Step 1: Get CI Status
```bash
gh auth status
```
If not authenticated, stop and ask the user to run `gh auth login`.
### Step 2: Get CI Status
```bash
gh pr checks
```
If all checks pass, report success and stop.
All pass → report success and stop. Not authenticated → ask user to `gh auth login`.
### Step 3: Inspect Failed Checks
### Step 2: Inspect Failures
For each failed check:
```bash

@@ -54,37 +42,21 @@ gh run view <run-id>

If logs exceed 200 lines, spawn a `[model: sonnet]` subagent to extract: first actionable error, failing command, file paths and line numbers.
Categorize: Build | Test | Lint | Type | Security | Config
### Step 4: Confirm Root Cause
**Logs over 200 lines:** Spawn `[model: sonnet]` subagent → returns JSON: `{ "error": "", "command": "", "files": [{ "path": "", "line": 0 }] }`
For **test failures**, spawn **one `[model: sonnet]` subagent per failure** (parallel, max 5 concurrent). Each subagent follows this strict protocol:
### Step 3: Root Cause
1. Find and read the failing test file
2. Find and read the tested class/function
3. `git diff master -- <tested-file> <test-file>` to see what changed
4. State root cause and proposed fix in ≤5 sentences
**Test failures** — spawn parallel `[model: sonnet]` subagents (max 3 concurrent, batch similar failures):
1. Read failing test + tested code + `git diff master -- {files}`
2. Return: `{ "test": "", "cause": "", "fix": "", "confidence": "high|medium|low" }`
3. Max 10 tool calls per subagent. App layer only — skip vendor/framework internals.
**Subagent constraints:**
- Max **10 tool calls** per subagent — if not solved by then, report what you know and stop
- **NEVER read files under `vendor/`** — the bug is in application code, not framework internals
- **NEVER trace through framework source code** (Doctrine internals, Symfony kernel, etc.)
- Stay at the application layer: entities, repositories, services, config, fixtures
- If root cause points to a framework behavior change, state the hypothesis without verifying in vendor code
**Non-test failures:** Read failing code, reproduce locally, check `git log -5`. Secrets/permissions → report and stop.
For **non-test failures** (build, lint, config):
### Step 4: Fix
1. Read the failing code locally
2. Run the failing command locally to reproduce if possible
3. `git log --oneline -5` for recent changes
4. Validate hypothesis before editing
Targeted, minimal changes. Preserve code style. Verify locally.
If the failure requires secrets, permissions, or manual intervention — report clearly and stop.
### Step 5: Push and Monitor
### Step 5: Fix
Targeted, minimal changes only. Preserve existing code style. Run the failing command locally to verify the fix.
### Step 6: Push and Monitor
```bash

@@ -97,19 +69,13 @@ git add <specific files>

Update `tmp/ci-state-{branch}.json` with attempt count and results.
Then **compact** the conversation, keeping only: current failure, fix applied, new CI status.
Update state file. Compact — keep only: current failure, fix, CI status.
### Step 7: Evaluate
### Step 6: Evaluate
- **All checks pass** → Final Report
- **Same failure persists** → re-analyze with new logs, return to Step 3
- **New failure** → analyze the new failure, return to Step 3
- **3 attempts reached** → Final Report with NEEDS_HUMAN status
- All pass → Final Report
- Same failure → re-analyze with new logs (Step 2)
- New failure → analyze new failure (Step 2)
- 3 attempts reached → Final Report with NEEDS_HUMAN
## Circuit Breaker Rules
Follow @skills/shared/common-patterns.md for circuit breaker rules.
- **Max 3 fix attempts.** Stop after 3 pushes without all checks passing.
- **Same error twice with same fix** → switch strategy or report.
- **Environment/permissions issues** → report immediately — cannot be fixed in code.
- **After each iteration**: compact, keeping only current failure + fix applied + CI status.
## Final Report

@@ -123,18 +89,14 @@

### Failures Found
- {check name}: {failure type} — {root cause}
- {check}: {type} — {root cause}
### Fixes Applied
- `{file}:{line}` — {what was changed and why}
- `{file}:{line}` — {change and why}
### Verification
- Local: {command} → {pass/fail}
- CI: {status after push}
### Remaining Failures
| Failure | Category | Proposed Action |
|---------|----------|-----------------|
| {check} | 🟢 Quick fix | {concrete fix — do it now} |
| {check} | 🟡 Needs investigation | {create issue with `/report-issue`} |
| {check} | 🔴 Infrastructure/config | {create issue assigned to ops} |
| Failure | Category | Action |
|---------|----------|--------|
| {check} | 🟢 Quick fix | {do it now} |
| {check} | 🟡 Investigate | {`/report-issue`} |
| {check} | 🔴 Infra/config | {issue to ops} |

@@ -145,9 +107,2 @@ ---

After the report, offer to fix 🟢 quick fixes and create issues for 🟡🔴 failures. Never leave failures unaddressed.
## Context Management
- `[model: sonnet]` subagent for CI logs exceeding 200 lines — returns only errors and context, no raw log
- **Test investigation subagents**: one per failure, parallel, max 10 tool calls each, no vendor/ reads
- **Compact after each push** before fetching new CI results — keep only current failure, fix, status
- After final report, compact the conversation
Offer to fix 🟢 and create issues for 🟡🔴. Compact after report.

@@ -20,3 +20,3 @@ ---

### Step 1: Fetch Issue Details
### Step 1: Fetch Issue

@@ -26,3 +26,2 @@ ```bash

gh issue view 123 --json title,body,labels,comments,assignees
# Jira

@@ -32,20 +31,14 @@ curl "https://{domain}.atlassian.net/rest/api/3/issue/{key}" -H "Authorization: Basic {credentials}"

Read the full issue including comments — context is often in comments.
Read full issue including comments.
### Step 2: Analyze & Plan
### Step 2: Plan
1. Read `CLAUDE.md` and `.claude/polyforge.json`
2. Search the codebase for relevant files (use issue keywords)
3. Understand current behavior before planning changes
4. Create a plan: files to modify, changes to make, tests to add
Search codebase for relevant files (use issue keywords). Understand current behavior before planning.
**After plan approval:** Save to `tmp/state-{issue}.json`:
```json
{ "issue": 123, "files_to_modify": [], "tests_to_add": [], "branch": "" }
```
Then compact — reload only from the state file.
Save to `tmp/state-{issue}.json`: `{ "issue", "files_to_modify": [], "tests_to_add": [], "branch": "" }`
Then compact — reload from state file.
**Preview mode (`--preview`):** Stop here and display the plan.
### Step 3: Create Branch
### Step 3: Branch + Implement

@@ -56,32 +49,17 @@ ```bash

### Step 4: Implement Fix
**Full auto:** Implement directly + write tests. **Semi-auto:** Show diff, ask "Apply? (y/n/edit)".
**Full auto:** Implement directly, write/update tests, run pipeline, create PR.
**Semi-auto:** Show diff preview, ask "Apply? (y/n/edit)", then run pipeline.
**Independent file groups (>3 files):** Delegate each group to `[model: sonnet]` subagent. Returns: `{ "group": "", "files": [], "summary": "" }`
If the fix involves independent file groups: delegate each to a `[model: sonnet]` subagent.
### Step 4: Verify
### Step 5: Verification Pipeline
Run verification pipeline per @skills/shared/common-patterns.md
```bash
{test command} 2>&1 | bash hooks/filter-test-output.sh
{lint command}
{typecheck command}
{vulncheck command}
```
### Step 5: Clean Up + PR
If any fails: fix (up to 2 retries). Same error + same approach twice → switch strategy. After 3 total attempts:
- 🟢 Quick fix → fix it now
- 🟡 Needs investigation → create issue via `/report-issue`
- 🔴 Pre-existing/infra → create issue via `/report-issue` tagged infra
### Step 6: Clean Up Commits
```bash
git reset --soft $(git merge-base HEAD origin/main)
# Re-commit in 3-7 logical groups (cleanup commits absorbed into parent)
# Re-commit in 3-7 logical groups
```
### Step 7: Create PR
Follow @skills/shared/pr-template-guide.md

@@ -91,23 +69,6 @@

gh pr create --title "fix: {description} (#{issue-number})" --body "..."
```
### Step 8: Update Issue
```bash
gh issue comment 123 --body "Fix submitted in PR #{pr-number}"
# Jira: jira issue move {key} "In Review" && jira issue comment add {key} "PR #{pr-number}"
```
### Step 9: Watch CI
```bash
gh pr checks --watch
```
CI fails → run `/fix-ci` automatically.
## Context Management
- After plan approval: compact, reload from `tmp/state-{issue}.json`
- Subagents `[model: sonnet]` for independent file groups — returns summary only
- After PR is created, compact — the PR is the deliverable
CI fails → `/fix-ci` automatically. Compact after PR — the PR is the deliverable.

@@ -8,3 +8,3 @@ ---

You are PolyForge's documentation generator. Create documentation optimized for Claude Code to understand the project efficiently.
You are PolyForge's documentation generator. Create documentation optimized for Claude Code.

@@ -28,43 +28,27 @@ ## Usage

### Step 1: Analyze Project (subagent)
### Step 1: Analyze Project
Spawn a `[model: sonnet]` subagent to scan the full project and return a structured summary:
Spawn `[model: sonnet]` subagent to scan and return structured JSON only:
```json
{
"stack": {}, "entryPoints": [], "architecture": "",
"patterns": [], "conventions": [], "envVars": [],
"knownQuirks": [], "keyFiles": [], "testFrameworks": []
}
{ "stack": {}, "entryPoints": [], "architecture": "", "patterns": [], "conventions": [], "envVars": [], "knownQuirks": [], "keyFiles": [], "testFrameworks": [] }
```
The subagent reads: entry points, config files, main modules, existing docs. Returns structured JSON only.
Subagent reads: entry points, config files, main modules, existing docs. **Discard raw scan data — use only the JSON.**
### Step 2: Handle Existing Files
For each file to generate:
- Doesn't exist → create
- Exists with PolyForge marker (`Forged with PolyForge`) → update in-place
- Exists without marker → ask: "(a) Merge (b) Keep existing, create separate file (c) Replace (backup to tmp/)"
- Exists with PolyForge marker → update in-place
- Exists without marker → ask: "(a) Merge (b) Keep + create separate (c) Replace (backup to tmp/)"
### Step 3: Generate and Confirm
### Step 3: Generate
Show a preview with file names and line counts. Ask: "Generate? (y/n/preview {filename})"
Show preview with file names and line counts. Ask: "Generate? (y/n/preview {filename})"
Generate each file from the structured summary. After each file, compact keeping only the summary and remaining files to generate.
Generate each file from structured summary. Compact between files.
**CLAUDE.md** — include only: build/test/lint commands, architecture pattern, key non-obvious conventions, `@` refs to detailed docs. Include PolyForge commands list.
**CLAUDE.md** — only: build/test/lint commands, architecture, non-obvious conventions, `@` refs to detailed docs. Include PolyForge commands list.
**`.claude/rules/`** — scope with `paths:` frontmatter. Examples:
- `polyforge-backend.md`: `src/**/*.php`, `internal/**/*.go`
- `polyforge-frontend.md`: `src/**/*.tsx`, `src/**/*.ts`
- `polyforge-tests.md`: `tests/**/*`, `**/*.test.*`, `**/*.spec.*`
**`.claude/rules/`** — scope with `paths:` frontmatter. Positive assertions, one per line.
Rules must be positive assertions, actionable, and one per line.
## Context Management
- Step 1 scan delegated entirely to `[model: sonnet]` subagent — structured JSON only returned
- Generate files one at a time, compact between each file
- CLAUDE.md MUST stay under 200 lines — non-negotiable
- Update `lastUpdatedAt` in `.claude/polyforge.json` after generating
Update `lastUpdatedAt` in `.claude/polyforge.json`. Compact after final file.

@@ -8,68 +8,47 @@ ---

You are PolyForge's project initializer. Scan, detect, ask targeted questions, and generate configuration.
You are PolyForge's project initializer. Scan, detect, ask targeted questions, generate config.
## Phase 0: Prerequisites Check
## Phase 0: Prerequisites
Run silently — warn if missing, stop only if `git` is absent:
Run silently — warn if missing, stop only if `git` absent:
- `git --version` — required
- `gh auth status` — warn if absent: "⚠ GitHub features won't work. Install: https://cli.github.com/"
- `glab auth status` — only if remote points to gitlab.com
- Jira — only if `.jira` or `JIRA_URL` env detected
- `gh auth status` — warn if absent
- `glab auth status` — only if GitLab remote
- Jira — only if `.jira` or `JIRA_URL` detected
## Phase 1: Automatic Detection
## Phase 1: Detection
Spawn a `[model: haiku]` subagent to scan the project and return a detection JSON:
Spawn `[model: haiku]` subagent → returns detection JSON only:
```json
{
"stack": ["node", "typescript"],
"framework": "express",
"packageManager": "npm",
"architecture": "clean",
"database": { "type": "postgres", "connectionMethod": "docker", "containerName": "db" },
"testing": { "framework": "jest", "commands": { "test": "npm test", "lint": "npm run lint" } },
"issueTracker": { "type": "github", "config": { "titlePrefix": "" } },
"ciFile": ".github/workflows/ci.yml",
"existingClaude": false,
"existingPolyforge": false
}
{ "stack": [], "framework": "", "packageManager": "", "architecture": "", "database": { "type": "", "connectionMethod": "", "containerName": "" }, "testing": { "framework": "", "commands": {} }, "issueTracker": { "type": "", "config": {} }, "ciFile": "", "existingClaude": false, "existingPolyforge": false }
```
The subagent scans: `package.json`, `composer.json`, `go.mod`, `docker-compose.yml`, `.env.*`, framework config files, git log/branches, issue list for title prefix conventions.
Subagent scans: package files, docker-compose, .env.*, framework configs, git log, issue list.
**Discard all raw scan output — use only the JSON.**
**Discard all raw scan output.** Use only the detection JSON.
If existing `.claude/` (not PolyForge): backup to `tmp/backup-{date}/.claude/`, inform user.
If existing `.claude/` (not from PolyForge): back up entirely to `tmp/backup-{date}/.claude/`, inform the user.
## Phase 2: Questions (ONE AT A TIME)
## Phase 2: Interactive Questions (ONE AT A TIME, numbered choices)
Show detection summary, then ask only what wasn't detected:
Show the detection summary, then ask only what wasn't detected:
1. "Detected [stack]. Correct?" → (1) Yes (2) Yes + other repos (3) Correct
2. "Architecture: [pattern]?" → (1) Yes (2) Not exactly
3. "Issue tracker: [tracker]?" → (1) Yes (2) Different
4. "Autonomy?" → (1) Full auto [Recommended] (2) Semi-auto
5. (Full auto) "Grant full file access?" → (1) Yes → write `.claude/settings.json` NOW (2) No
6. "Additional conventions?"
7. "Generate docs now? (`/generate-doc`)"
1. "I detected [stack]. Is this correct?" → (1) Yes (2) Yes + other internal repos (3) Needs correction
2. "Architecture pattern: [pattern]. Does this match?" → (1) Yes (2) Not exactly (describe)
3. "Issue tracker: [tracker]. Correct?" → (1) Yes (2) Different (specify)
4. "Autonomy level?" → (1) Full auto — branch, fix, test, PR without asking [Recommended] (2) Semi-auto
5. (If full auto) "Grant full file access? ⚠️ Read/write/execute anything in this directory." → (1) Yes — write `.claude/settings.json` NOW (2) No — manual approval
6. "Additional conventions to enforce?"
7. "Generate Claude-optimized docs now? (`/generate-doc`)"
## Phase 3: Generate
If full access selected: **write `.claude/settings.json` immediately** with permissions: `Edit, Write, Bash, Read, Glob, Grep`.
Confirm file list before writing. Backup existing files to `tmp/backup-{date}/`.
## Phase 3: Generate Configuration
Create:
- `.claude/polyforge.json` — master config
- `CLAUDE.md` — short (<200 lines), `@` refs to detailed docs, include PolyForge commands
- `.claude/rules/` — scoped rules with `paths:` frontmatter
- `docs/CONTEXT.md` — architecture details
- `tmp/` + `.gitignore` entry
Create these files (confirm the list before writing, back up any existing file to `tmp/backup-{date}/`):
- **`.claude/polyforge.json`** — master config from detection JSON + answers
- **`CLAUDE.md`** — short, high-signal (<200 lines), `@` refs to detailed docs. Include PolyForge commands: `/forge`, `/pr-review`, `/analyse-db`, `/analyse-code`, `/diagnose`, `/report-issue`, `/feature`, `/fix`, `/fix-ci`, `/brainstorm`, `/generate-doc`, `/squash`, `/add-rule`
- **`.claude/rules/`** — scoped rules by file type (paths: frontmatter)
- **`docs/CONTEXT.md`** — architecture details, patterns, dependencies
- **`tmp/`** directory + `.gitignore` entry
Log all actions to `tmp/forge-log-{date}.md`.
## Context Management
- Phase 1 detection runs in a `[model: haiku]` subagent — only detection JSON returned to parent
- After Phase 1: discard all raw scan data, use only the JSON
- After generating files: present summary of created files and locations
- End with: "**Restart Claude Code** to load the new configuration."
Log to `tmp/forge-log-{date}.md`. End with: "**Restart Claude Code** to load new configuration."

@@ -18,9 +18,9 @@ ---

## Review Process
## Process
### Step 1: Gather PR Context (run all 4 in parallel)
### Step 1: Gather PR Context (parallel)
```bash
gh pr view {number} --json title,body,additions,deletions,files,commits,reviews,labels
gh pr diff {number}
gh pr diff {number} -- ':!*.lock' ':!vendor/' ':!*.generated.*'
gh pr checks {number}

@@ -30,38 +30,29 @@ gh api repos/{owner}/{repo}/pulls/{number}/comments

### Step 2: Check CI/CD Status
### Step 2: Check CI
```bash
gh run list --branch {branch}
gh run list --branch {branch} --limit 3
gh run view {run-id} --log-failed 2>/dev/null | head -300
```
If CI fails: report which jobs failed and why. Ask: "Fix CI failures automatically?"
CI fails → report which jobs failed and why. Ask: "Fix CI failures automatically?"
### Step 3: Code Review (MANDATORY subagent — always, no size condition)
### Step 3: Code Review
Spawn a `[model: sonnet]` subagent with isolated context to review the diff. The subagent checks:
**Under 300 lines diff:** Review inline — no subagent needed.
**Coherence & Completeness**
- All related files present (no missing migrations, tests, configs)
- No unresolved TODO/FIXME in the diff
- Feature works end-to-end based on code flow
**Over 300 lines diff:** Spawn `[model: sonnet]` subagent with the diff. Returns JSON only:
```json
[{ "file": "", "line": 0, "category": "critical|warning|suggestion", "msg": "" }]
```
**Code Quality**
- Single responsibility, no duplication, consistent naming, complete error handling
Review checklist (inline or subagent):
- **Coherence**: all related files present, no unresolved TODO/FIXME, end-to-end flow works
- **Quality**: single responsibility, no duplication, consistent naming, error handling
- **Cross-file**: API contracts match, schema changes have migrations, test coverage matches
- **Security**: no secrets, input validation on boundaries, no injection vectors
- **Performance**: no N+1, no unbounded loops, indexes for new queries
**Cross-File Consistency**
- API contracts match between caller and callee
- Schema changes have ORM/migration updates
- Test coverage matches the changes
### Step 4: Report
**Security**
- No hardcoded secrets, input validation on boundaries, no injection vectors
**Performance**
- No N+1 queries, no unbounded loops, indexes for new query patterns
If diff > 500 lines: subagent summarizes findings per-file and returns only the summary.
### Step 4: Generate Report
```markdown

@@ -71,35 +62,22 @@ ## PR Review: #{number} — {title}

### CI Status
- ✓ Build: passed
- ✗ Lint: failed (2 errors)
- ✓/✗ {check}: {status}
### Critical (must fix)
- [ ] {finding with file:line reference}
- [ ] {finding} — `{file}:{line}`
### Warnings (should fix)
- [ ] {finding with file:line reference}
- [ ] {finding} — `{file}:{line}`
### Suggestions (nice to have)
- [ ] {finding with file:line reference}
- [ ] {finding} — `{file}:{line}`
### What looks good
- {positive feedback on well-written parts}
- {positive feedback}
```
### Step 5: Post-Review Actions
### Step 5: Post-Review
Ask ONE question:
"Found {N} issues ({critical} critical, {warnings} warnings). What do you want to do?
(a) Fix critical issues automatically
(b) Fix all issues automatically
(c) Just show the report — I'll fix manually
(d) Post this review as a PR comment"
Ask: "Found {N} issues ({critical} critical). Action?
(a) Fix critical automatically (b) Fix all (c) Report only (d) Post as PR comment"
## Configuration
Read `.claude/polyforge.json` for `autonomy`, `pipeline.prePR`, `project.linters`.
## Context Management
- Run Step 1 commands in parallel — they are independent
- `[model: sonnet]` subagent for Step 3 — always mandatory, no size condition
- After generating the report, compact the conversation — the report is the deliverable
Compact after report — follow @skills/shared/common-patterns.md

@@ -8,3 +8,3 @@ ---

You are PolyForge's issue reporter. Detect problems and create well-structured issues in the project's tracker.
You are PolyForge's issue reporter. Detect problems and create well-structured issues.

@@ -21,59 +21,36 @@ ## Usage

### Step 1: Determine Issue Tracker
### Step 1: Detect Tracker
Read `.claude/polyforge.json` → `issueTracker.type`.
Use pre-loaded config for `issueTracker.type`. If not configured: check `gh api repos/{owner}/{repo} --jq '.has_issues'`, then Jira env vars, then GitLab remote. Jira auth: @skills/report-issue/jira-auth.md
If not configured: check `gh api repos/{owner}/{repo} --jq '.has_issues'`, then Jira env vars, then GitLab remote.
### Step 2: Gather Details
For Jira authentication and template discovery: see @skills/report-issue/jira-auth.md
**Interactive** — ONE question at a time: (1) What's the problem? (2) Expected vs actual? (3) Affected code? (4) Severity?
### Step 2: Gather Issue Details
**Scan mode** — spawn `[model: sonnet]` subagent → returns JSON:
```json
[{ "file": "", "line": 0, "type": "", "severity": "", "description": "", "fix": "" }]
```
Present findings, let user pick which to create as issues.
**Interactive mode** — ONE question at a time:
1. What's the problem?
2. Expected vs actual behavior?
3. Which part of the codebase is affected?
4. Severity? (critical / high / medium / low)
### Step 3: Enrich
**Scan mode** — spawn a `[model: sonnet]` subagent to analyze the directory and return findings:
- Uncaught exceptions / missing error handling
- TODO/FIXME comments with context
- Dead code / unreachable branches
- Performance anti-patterns (N+1, unbounded loops)
- Security issues (hardcoded secrets, missing validation)
Find file/line numbers, check `git blame`, search duplicates (`gh issue list -S "{keywords}"`), suggest severity.
Present all findings as a list, let user pick which to create as issues.
### Step 4: Templates
### Step 3: Enrich the Issue
Before creating: find relevant file/line numbers, check git blame, search for duplicates (`gh issue list -S "{keywords}"`), suggest severity label.
### Step 4: Check for Issue Templates
```bash
# GitHub
ls .github/ISSUE_TEMPLATE/ 2>/dev/null
cat .github/ISSUE_TEMPLATE/bug_report.md 2>/dev/null
# GitLab
ls .gitlab/issue_templates/ 2>/dev/null
```
**If a template exists — NON-NEGOTIABLE:** Use VERBATIM, fill in all applicable fields, never delete sections. Append PolyForge footer.
**Template exists:** Use VERBATIM — fill all fields, never delete sections. NEVER append branding or footers.
**No template:** Use @skills/shared/issue-default.md
**If no template:** Use default at @skills/shared/issue-default.md
### Step 5: Create
### Step 5: Create the Issue
```bash
# Check for title prefix in polyforge.json → issueTracker.config.titlePrefix
# GitHub
gh issue create --title "{prefix} {title}" --body "{body}" --label "{severity},{type}"
# Jira (CLI preferred, REST fallback — see @skills/report-issue/jira-auth.md)
jira issue create --type "{type}" --summary "{title}" --body "{body}" --priority "{priority}"
# GitLab
glab issue create --title "{title}" --description "{body}" --label "{labels}"
# Check titlePrefix in config
# GitHub: gh issue create --title "{prefix} {title}" --body "{body}" --label "{severity},{type}"
# Jira: jira issue create --type "{type}" --summary "{title}" --body "{body}" --priority "{priority}"
# GitLab: glab issue create --title "{title}" --description "{body}" --label "{labels}"
```

@@ -83,9 +60,2 @@

Show full issue preview. Ask: "Create this issue? (y/n/edit)"
Log created issues to `tmp/issues-log-{date}.md`.
## Context Management
- Scan mode: `[model: sonnet]` subagent for directory scanning — returns findings JSON only
- After creating issues, compact the conversation
Show preview. Ask: "Create this issue? (y/n/edit)". Log to `tmp/issues-log-{date}.md`. Compact after creation.

@@ -12,3 +12,3 @@ # PR Template Usage

## Step 2a: If a template exists — NON-NEGOTIABLE
## Step 2a: If a template exists — RESPECT IT COMPLETELY

@@ -18,3 +18,3 @@ 1. Use the template VERBATIM — keep every section, checkbox, and HTML comment

3. Leave sections empty or unchecked if not applicable — NEVER delete them
4. Append `*⚒ Forged with [PolyForge](https://github.com/Vekta/polyforge)*` at the very bottom
4. NEVER append branding, signatures, or footers — the repo's template is the final format
5. The PR must look like a human filled it in, not a bot replacement

@@ -21,0 +21,0 @@

@@ -19,6 +19,4 @@ ---

### Step 1: Analyze Commits
### Step 1: Analyze
Spawn a `[model: haiku]` subagent to run:
```bash

@@ -30,22 +28,18 @@ git merge-base HEAD origin/main || git merge-base HEAD origin/master

Returns: commit list with messages, changed file list, total diff line count.
Under 3 commits → "Only {N} commits — nothing to clean up." Stop.
If fewer than 3 commits: "Only {N} commits — nothing to clean up." Stop.
If total diff >2000 lines: spawn a `[model: sonnet]` subagent for per-file analysis before categorizing.
**Over 2000 lines diff:** Spawn `[model: sonnet]` subagent for per-file categorization → returns JSON: `[{ "file": "", "category": "" }]`
### Step 2: Categorize Commits
### Step 2: Categorize
Group into: Schema/Infrastructure | Core Implementation | API/Interface | Tests | Documentation | Cleanup
Group: Schema/Infrastructure | Core Implementation | API/Interface | Tests | Documentation | Cleanup
Cleanup commits always absorbed into parent — never standalone.
**Cleanup commits always absorbed into parent — never standalone.**
### Step 3: Propose
### Step 3: Propose Plan
```
Current: 18 commits
Proposed: 4 commits
Current: 18 commits → Proposed: 4 commits
1. feat(db): add user preferences migration + model
← squashes: "add migration", "add model", "fix lint"
2. feat(api): add preferences endpoints + service

@@ -55,3 +49,3 @@ ← squashes: "add service", "add controller", "fix type error"

Ask: (1) Apply this plan (2) Show diffs per group first (3) Adjust grouping
Ask: (1) Apply (2) Show diffs per group (3) Adjust grouping

@@ -62,10 +56,6 @@ ### Step 4: Execute

git reset --soft $(git merge-base HEAD origin/main)
# Stage and commit group by group
git add <schema files> && git commit -m "feat(db): ..."
git add <core files> && git commit -m "feat(api): ..."
git add <test files> && git commit -m "test: ..."
```
If files span multiple groups: isolate changes via targeted edits per group.
### Step 5: Verify

@@ -78,31 +68,14 @@

Show: Before/After commit count, diff identical confirmation, test status.
Show: before/after commit count, diff identical confirmation, test status.
Ask: "Push with `--force-with-lease`?" (only if remote branch exists)
### Step 6: Update PR Description
### Step 6: Update PR
If PR exists: read existing body, preserve entire template structure, update only summary/changes sections.
If PR exists: preserve template structure, update only summary/changes.
```bash
gh pr view --json number,body 2>/dev/null
gh pr edit --body "{updated body preserving template}"
```
## Rules
## Commit Message Format
```
type(scope): short description
- Key implementation detail
- Non-obvious decisions made
```
Types: `feat` | `fix` | `refactor` | `test` | `docs` | `chore`
## Important Behaviors
- Target: 3-7 commits — never squash everything into 1
- Never lose code — verify diff stat before and after is identical
- Never include `Co-Authored-By` in commit messages
- Never lose code — verify diff stat before and after
- Commit format: `type(scope): short description` + key details
- Use `--force-with-lease` not `--force`