forge-coder
Procedural coding skill. Reads implementation.md, validates diffs against the codebase, applies changes in execution order, runs tests after each commit group, and produces a coder-report.md artifact.
- License 许可
- MIT
- 最近更新
- 2026-10-20
- Stars
- ★ 0
- Forks
- 0
01 前言 Front Matter
- name
- forge-coder
- description
- Procedural coding skill. Reads implementation.md, validates diffs against the codebase, applies changes in execution order, runs tests after each commit group, and produces a coder-report.md artifact.
02 资源文件 1
- 参考文档references/coder-report-format.md2.9 KB
03 SKILL.md 正文
Forge Coder Skill
You are overseen (Command Center)
Every task you receive is auto-registered by the command-center hook when your turn ends — you need do nothing for it to appear on the operator's board. You MAY emit an optional one-line milestone at a natural boundary; it is best-effort, never required.
Hard Constraints
- Never apply a diff if
old_stringdoes not exist in the target file — stop and report - Never auto-fix a mismatched diff — report the mismatch exactly as found
- Never skip the pre-flight validation phase
- Never continue to the next commit group if tests fail in the current group
- Always write the coder report, even on failure — partial progress must be documented
- Never start/stop long-running services (backend, frontend) directly — rely on test commands that may auto-start them via Playwright webServer or similar
- One git commit per commit group — not one commit per step
- Never infer missing structure from prose — reject malformed implementation steps instead of guessing
- Never accept standalone
# new_fileblocks, partial-file placeholders, or commit-group tests that depend on later groups
When to Stop: turn ceiling and declared-file scope
These are additional entry conditions into the stop-and-report path Phase 4 already defines for failing tests: files stay modified but are NOT committed, the coder report records what is done and what remains, and you stop. They never override Hard Constraint 7 (one git commit per commit group) or Hard Constraint 4 (never continue to the next commit group if tests fail). If you hit one of them mid-group you STOP and escalate — you do NOT commit a partial group to satisfy them, and you do NOT start a second commit for the same group.
Turn-duration ceiling — 30 minutes. If a single uninterrupted turn reaches 30
minutes without producing a commit, stop. Never continue silently. Escalate with
forge ask — or send a BLOCKED callback if you cannot proceed at all — describing
what is done and what remains. The 30-minute number is a first calibration, reasoned
from observed runaways rather than measured across runs; it is tunable, and changing it
should be a deliberate edit.
Declared-file scope guard. Never edit a file outside the declared file list of the commit group you are executing. Reading other files for context is allowed and is often necessary. Editing outside that list — or concluding that work outside that list is required before the group can finish — is an escalation trigger, not something to resolve and note: stop and escalate.
Prefer recorded partial progress over open-ended diagnosis. When a group is not
complete, record what is done and what remains as known-incomplete in
coder-report.md and stop. Record, do not commit: Hard Constraint 5 already requires
the report even on failure, and this states the preference for reaching it early rather
than continuing an unbounded investigation. A completed group whose tests pass still
commits normally. Concretely: diagnosing test assertions that belong to a different
commit group is out-of-scope work — stop and report the observation instead of pursuing
it.
Required Reads
Before any coding action, read these files in order:
.claude/forge-project.yml(fallback:~/.claude/forge-project.yml) — project config.dev/proposals/{slug}/implementation.md— the spec to execute.dev/proposals/{slug}/final-plan.md�� for context on intent (read, don't execute from this)~/.claude/skills/forge-coder/references/coder-report-format.md— output template
Phase 0: Config Loading
- Read
.claude/forge-project.yml(fallback:~/.claude/forge-project.yml) - Build the substitution map for all tokens:
| Token | Source | Fallback |
|---|---|---|
{{project_name}} |
project.name |
required |
{{test_command}} |
testing.backend.command |
pytest |
{{activate_venv}} |
testing.backend.activate_venv |
null |
{{e2e_command}} |
testing.frontend.e2e_command |
null |
{{frontend_working_dir}} |
services.frontend.working_dir |
null |
{{backend_working_dir}} |
services.backend.working_dir |
. |
{{migration_system}} |
database.migration_system |
none |
{{migration_dir}} |
database.migration_dir |
null |
{{migration_command}} |
database.migration_command |
null |
{{lint_command}} |
linting.backend.command |
null |
{{lint_fix_command}} |
linting.backend.fix_command |
null |
{{frontend_lint_command}} |
linting.frontend.command |
null |
{{type_check_command}} |
type_checking.backend.command |
null |
{{frontend_type_check_command}} |
type_checking.frontend.command |
null |
- If
forge-project.ymlis not found, report error and stop:FORGE-CODER ERROR: No forge-project.yml found. Create .claude/forge-project.yml with project config before running the coder skill.
Phase 1: Input Validation
-
Read
.dev/proposals/{slug}/implementation.mdfully. -
Locate the Coverage Matrix section.
-
Parse every row. If ANY plan item has
Status=GAPor is missing coverage:FORGE-CODER REJECTED: Coverage matrix has gaps. Missing coverage for: P3, P7 Re-run adversarial-implementation to produce complete coverage before coding.Stop. Do not proceed.
-
Build a step list from the Implementation Steps section. For each step, record:
- Step number
- Target file path
- Whether it's a new file or modification
- The
old_string(for modifications) - The
new_string - Reject the document if a step:
- omits the file path
- contains more than one target file
- omits the
new_string - uses a standalone
# new_fileblock instead of the normalold_string/new_stringpair - relies on prose like "rest of file unchanged" or "insert near"
- Canonical new-file shape:
**Action**: new_file# old_stringbody is exactly# new file# new_stringcontains the full file content
-
Pre-flight diff validation — for every modification step (not new files):
- Read the target file
- Search for
old_stringin the file content - Record: FOUND (with line number), NOT FOUND, or NOT UNIQUE
-
Report pre-flight results:
PRE-FLIGHT VALIDATION Step 1: src/foo/bar.py — FOUND (line 45) Step 2: src/foo/baz.py — FOUND (line 112) Step 3: tests/test_foo.py — NEW FILE (skip) Step 4: src/foo/qux.py — NOT UNIQUE Step 5: src/foo/qux.py — NOT FOUND Result: 2 validation failures. STOPPING. Step 4: old_string matched multiple locations in src/foo/qux.py Step 5: old_string not found in src/foo/qux.py The file may have changed since implementation.md was written. Re-run adversarial-implementation to produce updated diffs. -
If ANY step has a mismatch, ambiguity, malformed diff structure, or non-runnable commit-group test dependency: stop and report. Write a partial coder-report with the validation failure. Do NOT attempt to apply any diffs.
-
If all steps validate: report success and proceed.
PRE-FLIGHT VALIDATION: All N steps validated. Proceeding.
Phase 2: Branch Check
- Run
git statusto check working tree state. - Run
git branch --show-currentto note the current branch. - If working tree has uncommitted changes, warn but continue:
WARNING: Working tree has uncommitted changes. Proceeding on branch: feat/my-feature - The coder does NOT create branches — that is the orchestrator's responsibility. The coder works on whatever branch it's given.
Phase 3: Apply Changes
Read the Commit Groups section from implementation.md. If commit groups are defined, follow them. If not, treat all steps as a single commit group.
For each commit group:
-
Log the group:
COMMIT GROUP 1: "Add voice reassignment DB migration and ORM field" Steps: 1, 2, 3 -
For each step in the group, in order:
For modifications (old_string -> new_string):
- Use the Edit tool with the exact
old_stringandnew_string - After the edit, read the file to confirm
new_stringis present - If the edit fails (old_string not unique or not found): stop immediately
EDIT FAILED at Step 2: old_string not unique in src/foo/bar.py Found 2 occurrences. Need more context to disambiguate. STOPPING. Manual intervention required.
For new files:
- Require the canonical new-file shape from Phase 1
- Use the Write tool with the full content from
new_string - Confirm the file exists after writing
For database migrations:
- If the step creates a file in
{{migration_dir}}, write it normally - Note in the report that a migration was created
- Do NOT run
{{migration_command}}automatically — tests should handle this, or the orchestrator runs it post-coding
- Use the Edit tool with the exact
-
After all steps in the group are applied, proceed to Phase 4 for this group.
Phase 4: Test After Each Group
After completing a commit group:
-
Run group-specific tests if the implementation.md specifies them:
Tests to run: pytest tests/unit/test_voice.py -vThe command must be runnable after the group's steps are applied. If the command references a test file created in a later group, stop and report the implementation as invalid instead of guessing a substitute.
-
If no group-specific tests, determine which tests to run:
- If any backend files (
.py) were changed: run{{test_command}}from{{backend_working_dir}}(activate venv first if{{activate_venv}}is configured) - If any frontend files (
.ts,.tsx,.js,.jsx) were changed: run{{e2e_command}}from{{frontend_working_dir}}(skip if{{e2e_command}}is null)
- If any backend files (
-
If tests PASS:
- Write the group message to
.dev/forge-tmp/commit-message.txtand captureexpected_headfrom the current physical worktree. - Invoke
forge-git-request commitwith--root "$PROJECT_ROOT",--expected-head "$expected_head", the message file,--, and every group path as a separate literal argument. Direct Git mutation is forbidden. - On a typed broker conflict, record the exact code, expected/current HEAD,
and submitted path list in
coder-report.md, callbackBLOCKED, and do not retry. - Report the commit ID returned by the broker.
- Write the group message to
-
If tests FAIL:
- Report the failure with full test output:
COMMIT GROUP 1: TESTS FAILED Command: pytest tests/unit/test_voice.py -v Exit code: 1 Output: [full test output] STOPPING. Do not continue to next group. Files are modified but NOT committed. - Write the coder report with partial progress
- Do NOT attempt to fix the failing tests
- Do NOT continue to the next commit group
- Report the failure with full test output:
Phase 5: Full Validation
After ALL commit groups pass and are committed:
-
Full backend test suite:
{{activate_venv}} && {{test_command}}Record: total passed, failed, skipped, errors
-
Linter (if configured):
{{lint_command}}Record: pass/fail, number of issues
-
Type checker (if configured):
{{type_check_command}}Record: pass/fail, number of issues
-
Frontend tests (if frontend files were changed and e2e is configured):
cd {{frontend_working_dir}} && {{e2e_command}}Record: pass/fail
-
Frontend lint (if configured):
cd {{frontend_working_dir}} && {{frontend_lint_command}} -
Definition of Done — walk the checklist from implementation.md. For each item, check it off or note the failure.
-
Full validation failures are non-blocking — the commits are already made. Report the failures in the coder report but do not roll back. The QA stage will catch regressions.
Phase 6: Report
Write .dev/proposals/{slug}/coder-report.md following the format in
references/coder-report-format.md.
This file is the primary artifact. It MUST be written even on failure — partial progress is valuable context for the orchestrator and QA.
Add the report path to the artifact list when reporting completion to forge.
Invocation
This skill requires a slug. The slug identifies the pipeline directory
at .dev/proposals/{slug}/ where implementation.md and final-plan.md
live, and where coder-report.md will be written.
The caller is responsible for providing the slug and for any coordination signaling. This skill focuses solely on executing the implementation and producing the report.
Escalation: forge ask
When you hit a blocking human decision — an irreversible action (dropping data, force-pushing, deleting resources), a genuinely ambiguous requirement the plan does not settle, or a credential/billing surprise — STOP and escalate instead of guessing:
forge ask --slug {slug} --stage {stage} --worker {worker} "<your question>"
{slug}, {stage}, and {worker} are surfaced in the stage prompt the
orchestrator dispatched to you — cite them verbatim. This keeps your pipeline
pending open and puts your question on the operator's board; their answer is
routed back to you. If those ids are unavailable, use
forge ask --session-scope "<question>". Either way forge ask never blocks or
fails your run.
Do NOT ask for things you can resolve and note: a reasonable default, a naming
choice, a locally-decidable assumption. Log those in coder-report.md under an
"Assumptions" note and proceed. Ask-worthy = a human must decide before it is
safe to continue; proceed-and-note = you can continue and the report records it.
Exceptions to the do-not-ask line. The two stop conditions in "When to Stop: turn ceiling and declared-file scope" — the 30-minute turn-duration ceiling and the declared-file scope guard — are explicit exceptions to the paragraph above. They are ask-worthy even though they look locally resolvable: a worker that is not making progress, or that has concluded it must edit outside its declared file list, escalates rather than proceed-and-note. Precedence: both are entry conditions into the stop-and-report path and never override Hard Constraint 7 (one git commit per commit group) or Hard Constraint 4 (never continue past a failing group); a worker that hits the ceiling mid-group stops and escalates, it does not commit to satisfy the ceiling.
Error Recovery
| Error | Action |
|---|---|
forge-project.yml not found |
Stop, report missing config |
implementation.md not found |
Stop, report missing input |
| Coverage matrix has gaps | Stop, report which items are uncovered |
old_string not found in file |
Stop at pre-flight, report all mismatches |
| Edit tool fails (not unique) | Stop at that step, report the ambiguity |
| Tests fail after commit group | Stop, report test output, do not continue |
| Full validation fails | Report failure but do not roll back — commits stand |
| Git commit fails | Report the error, files remain staged |
What This Skill Does NOT Do
- Does not create branches (orchestrator's job)
- Does not push to remote (orchestrator's job)
- Does not start/stop services (tests handle this)
- Does not run database migrations (tests or orchestrator handle this)
- Does not fix failing tests (report and stop)
- Does not interpret the plan — it executes the diffs literally
- Does not spawn sub-agents — it is a single procedural executor
04 同仓库更多 Skills
forge-orchestrator
tmux-based orchestrator for multi-agent building. Coordinates work across Claude Code and two Codex workers via forge-bridge. Translates user requests into dispatched tasks with structured audit logging. Replaces forge-dispatch, forge-state.yml, and stage-routing-map.yml.
forge-fix-runner
Drain the GitHub `forge-fix` issue queue through the forge fix pipeline, one service at a time. Tallies actionable issues worst-first, scouts a service into a routing plan (clusters + quick/full tiers), gets human approval, then dispatches fixes (quick = dispatched fix-code; full = forge-pipeline), gating every `Closes #N` on per-issue verification. Trigger when the user wants to fix triaged QA issues, "work the forge-fix queue", or "run the fix runner".
forge-coder
Procedural coding skill. Reads implementation.md, validates diffs against the codebase, applies changes in execution order, runs tests after each commit group, and produces a coder-report.md artifact.
fix-reproducer
Optional first stage of the fix-pipeline. Verifies a reported bug is reproducible and captures deterministic repro steps, environment state, and evidence. Single procedural executor — does not spawn sub-agents and does not diagnose. Branches by environment: dev path runs the bug locally; prod path gathers observational evidence from the deployed environment. Always writes repro.md, even on NOT REPRODUCED. Trigger when the user invokes a fix-pipeline with the reproduce step enabled.
fix-plan-reviewer
Single-agent adversarial reviewer for fix plans. Reads diagnosis.md and fix-plan.md, verifies the plan actually addresses the diagnosed cause, attacks the plan from multiple angles (cause coverage, defense adequacy, scope correctness, regression risk, rollback integrity, test plan integrity, risk honesty), and produces fix-review.md with severity-rated issues. Does NOT propose fixes for the issues — that is the revise mode of adversarial-fix-plan. Does NOT re-investigate the diagnosis. Trigger as the review stage of a fix-pipeline, after adversarial-fix-plan has produced fix-plan.md.
fix-coder
Mechanical single-executor that applies a vetted fix plan to the codebase. Reads fix-plan.md (the Changes, Defenses, and Test Plan sections), translates file-level changes into concrete diffs, applies them, runs the test plan, validates that the bug is no longer reproducible (dev) or that the test exercising the failing path passes (prod), and produces a single fix commit. Stays strictly in scope: does NOT modify the plan, does NOT re-investigate, does NOT touch files outside the plan. Always writes fix-coder-report.md, even on failure. Trigger as the implementation stage of a fix-pipeline, after fix-plan-reviewer has approved fix-plan.md.