@jualopezmo/codeforge 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +368 -0
- package/VERSION +1 -0
- package/bin/codeforge.mjs +64 -0
- package/install.ps1 +317 -0
- package/install.sh +326 -0
- package/package.json +39 -0
- package/src/CLAUDE.md +88 -0
- package/src/CONTINUITY.template.md +16 -0
- package/src/PROJECT.template.md +27 -0
- package/src/configs/claude/settings.json +6 -0
- package/src/configs/codex/config.toml +17 -0
- package/src/configs/opencode.json +14 -0
- package/src/docs/CHANGELOG.md +9 -0
- package/src/docs/adr/.gitkeep +0 -0
- package/src/docs/e2e/reports/.gitkeep +0 -0
- package/src/docs/e2e/use-cases/.gitkeep +0 -0
- package/src/docs/extending.md +134 -0
- package/src/docs/plans/.gitkeep +0 -0
- package/src/docs/prds/.gitkeep +0 -0
- package/src/docs/research/.gitkeep +0 -0
- package/src/docs/solutions/.gitkeep +0 -0
- package/src/shared/rules/approach-comparison.md +29 -0
- package/src/shared/rules/continuity.md +32 -0
- package/src/shared/rules/docs-layout.md +23 -0
- package/src/shared/rules/memory.md +34 -0
- package/src/shared/rules/models.md +59 -0
- package/src/shared/rules/project-rules.md +31 -0
- package/src/shared/rules/research.md +30 -0
- package/src/shared/rules/severity.md +17 -0
- package/src/shared/rules/ship-gates.md +164 -0
- package/src/shared/rules/tdd.md +20 -0
- package/src/shared/rules/workflow.md +38 -0
- package/src/shared/scripts/check-gates.ps1 +197 -0
- package/src/shared/scripts/check-gates.sh +201 -0
- package/src/shared/scripts/claude-gate-hook.ps1 +35 -0
- package/src/shared/scripts/claude-gate-hook.sh +43 -0
- package/src/shared/state.template.md +33 -0
- package/src/skills/adr/SKILL.md +63 -0
- package/src/skills/checkpoint/SKILL.md +50 -0
- package/src/skills/council/SKILL.md +87 -0
- package/src/skills/finish-branch/SKILL.md +85 -0
- package/src/skills/fix-bug/SKILL.md +84 -0
- package/src/skills/index/SKILL.md +52 -0
- package/src/skills/new-feature/SKILL.md +84 -0
- package/src/skills/plan/SKILL.md +63 -0
- package/src/skills/prd/SKILL.md +62 -0
- package/src/skills/quick-fix/SKILL.md +60 -0
- package/src/skills/research/SKILL.md +61 -0
- package/src/skills/review/SKILL.md +66 -0
- package/src/skills/simplify/SKILL.md +59 -0
- package/src/skills/verify-e2e/SKILL.md +102 -0
- package/src/sync.ps1 +69 -0
- package/src/sync.sh +69 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: prd
|
|
3
|
+
description: Write a product requirements doc before designing — the spec for what to build and who it's for: the problem, users, goals/non-goals, requirements, and success criteria, then hand off to plan. Use at the start of a substantial feature to spec out what a system should do, under Claude Code, Codex, or OpenCode.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# prd
|
|
7
|
+
|
|
8
|
+
Define *what* and *why* before *how*. A PRD keeps design and implementation anchored to a
|
|
9
|
+
real user outcome. Feeds the `plan` skill.
|
|
10
|
+
|
|
11
|
+
Use for substantial features; skip for small changes (go straight to `plan` or
|
|
12
|
+
`quick-fix`).
|
|
13
|
+
|
|
14
|
+
## 1. Clarify the problem
|
|
15
|
+
|
|
16
|
+
Establish who has the problem and what outcome they need. Ask the user one question at a
|
|
17
|
+
time only when genuinely ambiguous; otherwise state assumptions. Avoid jumping to a
|
|
18
|
+
solution — this phase is about the need, not the design.
|
|
19
|
+
|
|
20
|
+
## 2. Draft the PRD
|
|
21
|
+
|
|
22
|
+
Write `docs/prds/<feature>.md` with:
|
|
23
|
+
|
|
24
|
+
- **Problem** — what's broken/missing and why it matters.
|
|
25
|
+
- **Users / personas** — who this is for; the situation they're in.
|
|
26
|
+
- **Goals** and **Non-goals** — what success includes, and what it deliberately excludes.
|
|
27
|
+
- **Requirements** — the capabilities the feature must provide (user-facing, not code).
|
|
28
|
+
- **Success criteria** — how you'll know it worked, observably.
|
|
29
|
+
- **Open questions** — what's still undecided.
|
|
30
|
+
|
|
31
|
+
## 3. Review + confirm
|
|
32
|
+
|
|
33
|
+
Sanity-check with the user (and optionally the `review` skill) that the PRD captures the
|
|
34
|
+
real intent. Resolve contradictions and vague requirements now — a gap here misdirects
|
|
35
|
+
everything downstream.
|
|
36
|
+
|
|
37
|
+
## 4. Hand off
|
|
38
|
+
|
|
39
|
+
The PRD feeds `plan` (design) → `new-feature` (build). Reference it from
|
|
40
|
+
`.workflow/state.md`.
|
|
41
|
+
|
|
42
|
+
## Common rationalizations
|
|
43
|
+
|
|
44
|
+
| Rationalization | Reality |
|
|
45
|
+
| --- | --- |
|
|
46
|
+
| "The requirements are obvious — just start designing." | The PRD anchors design to a real user outcome; skipping it lets the build drift from what the user needs. |
|
|
47
|
+
| "I'll write the endpoints and tables as the requirements." | Requirements are user-facing capabilities, not code. A PRD that reads like a design doc has skipped the what/why. |
|
|
48
|
+
| "Non-goals are unnecessary." | Naming what's deliberately excluded is how scope stays bounded. Omit them and scope creeps. |
|
|
49
|
+
| "Success criteria can wait." | Without observable success criteria you can't tell if it worked. Define them up front. |
|
|
50
|
+
|
|
51
|
+
## Red flags
|
|
52
|
+
|
|
53
|
+
- The PRD names components/endpoints/tables as the goal.
|
|
54
|
+
- No users/personas, or no non-goals.
|
|
55
|
+
- No observable success criteria.
|
|
56
|
+
- It reads like a design doc rather than a statement of need.
|
|
57
|
+
|
|
58
|
+
## Verification
|
|
59
|
+
|
|
60
|
+
`docs/prds/<feature>.md` exists and states the problem, users, goals/non-goals,
|
|
61
|
+
requirements, and success criteria in user terms (no endpoints, tables, or code as the
|
|
62
|
+
goal). A PRD that reads like a design doc has skipped the "what/why" — rewrite it.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: quick-fix
|
|
3
|
+
description: Lightweight workflow for trivial changes (fewer than 3 files, no behavior risk) — branch, change, quick check, verify, ship. Use for typos, copy tweaks, small config edits under Claude Code, Codex, or OpenCode. Escalate to new-feature or fix-bug if scope grows.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# quick-fix
|
|
7
|
+
|
|
8
|
+
For genuinely trivial changes only. If the change touches 3+ files, alters behavior, or
|
|
9
|
+
turns out non-obvious, **stop and switch** to `new-feature` or `fix-bug`.
|
|
10
|
+
|
|
11
|
+
## 0. Set up tracking
|
|
12
|
+
|
|
13
|
+
- Confirm you are **not on `main`** — create a branch (`chore/<name>` or `fix/<name>`).
|
|
14
|
+
- A full `.workflow/state.md` is optional here; still record the branch and a one-line
|
|
15
|
+
intent so the ship-gate has context. If you use state.md, set **Profile: light**.
|
|
16
|
+
|
|
17
|
+
## 1. Make the change
|
|
18
|
+
|
|
19
|
+
Apply the small edit. Keep it to the stated scope — no drive-by refactors.
|
|
20
|
+
|
|
21
|
+
## 2. Quick check
|
|
22
|
+
|
|
23
|
+
- If code with a runtime effect: add or run a relevant test.
|
|
24
|
+
- If docs/config: sanity-check syntax and that nothing references the old value.
|
|
25
|
+
|
|
26
|
+
## 3. Verify
|
|
27
|
+
|
|
28
|
+
Exercise the changed path (or render the doc / load the config) and confirm the intended
|
|
29
|
+
result. Trivial does not mean unverified.
|
|
30
|
+
|
|
31
|
+
## 4. Ship
|
|
32
|
+
|
|
33
|
+
Commit, then push / open PR. The native approval prompt on push/PR still applies — approve
|
|
34
|
+
only if the change is truly complete and correct.
|
|
35
|
+
|
|
36
|
+
> Scope guard: the moment this stops feeling trivial, abandon quick-fix and restart under
|
|
37
|
+
> `new-feature` / `fix-bug` with the full discipline.
|
|
38
|
+
|
|
39
|
+
## Common rationalizations
|
|
40
|
+
|
|
41
|
+
| Rationalization | Reality |
|
|
42
|
+
| --- | --- |
|
|
43
|
+
| "It's one line, no need to test or run it." | A one-line change with a runtime effect still needs the changed path exercised. Trivial does not mean unverified. |
|
|
44
|
+
| "It's grown to four files but I'm nearly done — I'll finish here." | 3+ files or a behavior change is the escalation trigger. Stop and restart under `fix-bug` / `new-feature`; don't finish under the light profile. |
|
|
45
|
+
| "While I'm in here I'll tidy up the nearby code." | Drive-by refactors break the no-behavior-risk contract. Keep to the stated scope or escalate. |
|
|
46
|
+
| "It's just a doc — nothing to check." | Confirm the doc renders and nothing still references the old value. |
|
|
47
|
+
|
|
48
|
+
## Red flags
|
|
49
|
+
|
|
50
|
+
- You're editing a third file, or changing behavior rather than copy/config.
|
|
51
|
+
- You skipped exercising the change because it "obviously works."
|
|
52
|
+
- You're reaching for a refactor "while you're here."
|
|
53
|
+
- The change stopped feeling trivial two edits ago and you kept going.
|
|
54
|
+
|
|
55
|
+
## Verification
|
|
56
|
+
|
|
57
|
+
- [ ] Change stayed in scope (<3 files, no behavior change) — otherwise escalated to `fix-bug` / `new-feature`.
|
|
58
|
+
- [ ] Changed path exercised (or doc rendered / config loaded); intended result observed.
|
|
59
|
+
- [ ] Nothing still references the old value.
|
|
60
|
+
- [ ] On a branch, not `main`; ship prompt approved only because the above hold.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: research
|
|
3
|
+
description: Pre-design research — check current docs and prior art for the libraries/APIs/problems a change touches, then write a sourced brief that the plan builds on. Use before designing anything involving unfamiliar or external technology, under Claude Code, Codex, or OpenCode.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# research
|
|
7
|
+
|
|
8
|
+
Don't design on stale, recalled-from-memory assumptions. Model knowledge has a cutoff;
|
|
9
|
+
verify against current sources first. See `shared/rules/research.md` for the full standard.
|
|
10
|
+
|
|
11
|
+
## When to run
|
|
12
|
+
|
|
13
|
+
Before `plan` / `new-feature` design when the change touches a new or external library,
|
|
14
|
+
API, protocol, third-party service, or a well-trodden problem worth learning from. Skip
|
|
15
|
+
for changes fully contained in code you already understand.
|
|
16
|
+
|
|
17
|
+
## 1. Scope the unknowns
|
|
18
|
+
|
|
19
|
+
List exactly what you need to find out: which libraries/APIs/versions, which behaviors or
|
|
20
|
+
constraints, and any "how do others do this" questions. A vague scope yields a useless
|
|
21
|
+
brief.
|
|
22
|
+
|
|
23
|
+
## 2. Consult current sources
|
|
24
|
+
|
|
25
|
+
Use the engine's available tools (web search / fetch / docs lookup) to gather **current,
|
|
26
|
+
versioned** facts. Prefer official docs over blog posts. Note the version and the date
|
|
27
|
+
checked. Also look at how established tools/products solved the same problem. If you
|
|
28
|
+
delegate the research to another engine, use the research model from
|
|
29
|
+
`shared/rules/models.md`.
|
|
30
|
+
|
|
31
|
+
## 3. Write the brief
|
|
32
|
+
|
|
33
|
+
Create `docs/research/<YYYY-MM-DD>-<topic>.md` with: the questions, sourced findings
|
|
34
|
+
(cite URL + date; separate verified from inferred), prior art, implications for the design,
|
|
35
|
+
and open questions. Follow the shape in `shared/rules/research.md`.
|
|
36
|
+
|
|
37
|
+
## 4. Hand off to design
|
|
38
|
+
|
|
39
|
+
The brief feeds `plan` / `new-feature`. The resulting design must be consistent with it.
|
|
40
|
+
If research surfaced a blocker or a changed assumption, say so before designing.
|
|
41
|
+
|
|
42
|
+
## Common rationalizations
|
|
43
|
+
|
|
44
|
+
| Rationalization | Reality |
|
|
45
|
+
| --- | --- |
|
|
46
|
+
| "I already know this library." | Model knowledge has a cutoff and APIs move. Verify the current, versioned docs before designing on memory. |
|
|
47
|
+
| "The blog post is good enough." | Prefer official, versioned docs and note the date checked. A confident blog can be stale or wrong. |
|
|
48
|
+
| "I'll cite the sources later." | Cite as you go, with dates, separating verified from inferred. An unsourced brief is just recalled assumptions. |
|
|
49
|
+
| "No time to research — just build." | Designing on a wrong assumption costs more than the lookup. If it's genuinely known code, skip research *explicitly* — don't fake it. |
|
|
50
|
+
|
|
51
|
+
## Red flags
|
|
52
|
+
|
|
53
|
+
- The brief asserts version-specific behavior with no source or date.
|
|
54
|
+
- Verified facts and your own inferences are mixed together.
|
|
55
|
+
- You're about to design and haven't checked whether the assumption still holds.
|
|
56
|
+
|
|
57
|
+
## Verification
|
|
58
|
+
|
|
59
|
+
The brief exists at `docs/research/<date>-<topic>.md`, every non-obvious claim cites a
|
|
60
|
+
source with a date, and inferences are labeled as such. A brief full of unsourced
|
|
61
|
+
assertions is not research — redo it.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: review
|
|
3
|
+
description: Get a cross-engine second opinion on a plan or a code diff — run the other engine as reviewer, collect severity-tagged findings (P0–P3), and report. Use during the design-review and code-review phases under Claude Code, Codex, or OpenCode.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# review
|
|
7
|
+
|
|
8
|
+
A utility skill for the review phases of other workflows. The point is **model
|
|
9
|
+
diversity**: the reviewer must be a *different* engine than the one driving.
|
|
10
|
+
|
|
11
|
+
## 1. Identify the target
|
|
12
|
+
|
|
13
|
+
- **Plan review** — a written plan/spec before implementation.
|
|
14
|
+
- **Code review** — the current diff (uncommitted, or vs `main`).
|
|
15
|
+
|
|
16
|
+
State which, and the exact scope (file paths, base ref).
|
|
17
|
+
|
|
18
|
+
## 2. Pick the reviewer (must differ from the driver)
|
|
19
|
+
|
|
20
|
+
- Driver Claude Code → reviewer Codex (`codex exec ...`) or OpenCode (`opencode run ...`).
|
|
21
|
+
- Driver Codex → reviewer Claude (`claude -p ...`) or OpenCode.
|
|
22
|
+
- Driver OpenCode → reviewer Claude or Codex.
|
|
23
|
+
|
|
24
|
+
Use the reviewer model + effort from `shared/rules/models.md`. Give the reviewer the
|
|
25
|
+
target + this instruction: report findings tagged by severity (`shared/rules/severity.md`)
|
|
26
|
+
with location and a concrete fix.
|
|
27
|
+
|
|
28
|
+
**Invoke the reviewer read-only.** It judges the diff/plan; it must not change it. Use
|
|
29
|
+
read-only permissions (Codex `--sandbox read-only`; Claude/OpenCode: no write/edit tools)
|
|
30
|
+
and hand it the plan/diff as text. Afterward, confirm the working-tree diff is unchanged.
|
|
31
|
+
|
|
32
|
+
**Single-engine fallback.** If no second engine is available, do a delayed self-review (or
|
|
33
|
+
use a human reviewer) and log a waiver in `.workflow/state.md` — see the fallback in
|
|
34
|
+
`shared/rules/ship-gates.md`. Cross-engine is preferred; the waiver keeps the degradation
|
|
35
|
+
explicit, not silent.
|
|
36
|
+
|
|
37
|
+
## 3. Collect findings
|
|
38
|
+
|
|
39
|
+
Gather the reviewer's output as P0/P1/P2/P3 items. If output is missing or unparseable,
|
|
40
|
+
treat it as a failed review — re-run, do not fabricate a verdict.
|
|
41
|
+
|
|
42
|
+
## 4. Act and record
|
|
43
|
+
|
|
44
|
+
- Resolve all P0/P1/P2 (P3 optional). Re-run the reviewer until a pass is clean.
|
|
45
|
+
- Record each iteration and its result in `.workflow/state.md` (which engine, findings).
|
|
46
|
+
|
|
47
|
+
## Common rationalizations
|
|
48
|
+
|
|
49
|
+
| Rationalization | Reality |
|
|
50
|
+
| --- | --- |
|
|
51
|
+
| "Same-engine review is fine." | The whole point is a *different* model's blind spots. A same-engine pass is an echo, not diversity — use the other engine or log a waiver. |
|
|
52
|
+
| "The reviewer output was empty — I'll just say it passed." | Missing or unparseable output is a *failed* review; re-run it. Never fabricate a verdict. |
|
|
53
|
+
| "P2s aren't worth fixing." | The loop exits only on no P0/P1/P2. P3s are optional; P2s block. |
|
|
54
|
+
| "I'll let the reviewer edit the fix while it's at it." | The reviewer is read-only — it judges, it doesn't touch the diff. Confirm the working tree is unchanged afterward. |
|
|
55
|
+
|
|
56
|
+
## Red flags
|
|
57
|
+
|
|
58
|
+
- Reviewer engine == driver engine, with no waiver logged.
|
|
59
|
+
- A "clean" verdict with no reviewer output behind it.
|
|
60
|
+
- The loop has run many passes without converging — escalate, don't grind.
|
|
61
|
+
- The working-tree diff changed during the review.
|
|
62
|
+
|
|
63
|
+
## Verification
|
|
64
|
+
|
|
65
|
+
The loop exits only when a single pass from the reviewer yields no P0/P1/P2. State that
|
|
66
|
+
explicitly before returning to the calling workflow.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: simplify
|
|
3
|
+
description: Post-implementation cleanup pass that reduces complexity without changing behavior — remove dead code, flatten nesting, de-duplicate, clarify names — with the test suite staying green throughout. Use after a change works (tests pass) and before shipping, under Claude Code, Codex, or OpenCode. Not for adding behavior or fixing bugs.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# simplify
|
|
7
|
+
|
|
8
|
+
Make the code simpler without changing what it does. The refactor step is the first thing
|
|
9
|
+
skipped under pressure, so this is its own pass: start from green, reduce complexity in small
|
|
10
|
+
behavior-preserving steps, end greener. If it changes behavior, it isn't a simplify — it's a
|
|
11
|
+
`fix-bug` or `new-feature`.
|
|
12
|
+
|
|
13
|
+
## 1. Start from green
|
|
14
|
+
|
|
15
|
+
The suite must pass **before** you touch anything. A simplify pass leans entirely on the tests
|
|
16
|
+
to prove behavior didn't change — if they're red (or thin), stop: fix them (or the bug) first.
|
|
17
|
+
|
|
18
|
+
## 2. Find the complexity
|
|
19
|
+
|
|
20
|
+
Look for: dead code, deep nesting (early-return / guard-clause opportunities), duplication
|
|
21
|
+
(rule of three), unclear names, and over-abstraction that costs more than it saves.
|
|
22
|
+
**Chesterton's Fence:** understand *why* a piece of code exists before removing it — the reason
|
|
23
|
+
may not be covered by a test.
|
|
24
|
+
|
|
25
|
+
## 3. Change in small, behavior-preserving steps
|
|
26
|
+
|
|
27
|
+
One simplification at a time; **re-run the tests after each**. Never fold a behavior change into
|
|
28
|
+
a simplify pass — the moment you do, a green suite no longer proves you kept behavior. A
|
|
29
|
+
big-bang refactor hides which step broke something.
|
|
30
|
+
|
|
31
|
+
## 4. Verify behavior is identical
|
|
32
|
+
|
|
33
|
+
Full suite green, and actually exercise the changed path (`shared/rules/tdd.md` refactor
|
|
34
|
+
discipline). The diff should read as *same behavior, less code*: less duplication, shallower
|
|
35
|
+
nesting, clearer names, no dead code.
|
|
36
|
+
|
|
37
|
+
## Common rationalizations
|
|
38
|
+
|
|
39
|
+
| Rationalization | Reality |
|
|
40
|
+
| --- | --- |
|
|
41
|
+
| "While I'm here I'll also fix this small bug / add this tweak." | A simplify pass is behavior-preserving. Mixing in a change means the green suite no longer proves you broke nothing — do it as a separate `fix-bug` / `new-feature`. |
|
|
42
|
+
| "This code looks pointless — I'll just delete it." | Chesterton's Fence: understand why it's there first. Tests may not cover the reason. Delete only once you know it's truly dead. |
|
|
43
|
+
| "I'll do all the simplifications in one commit." | One behavior-preserving step at a time, re-running tests between. A big-bang refactor hides which step regressed. |
|
|
44
|
+
| "Tests pass, so the refactor is done." | Also exercise the path — a passing suite proves the tests pass, not that behavior held where tests are thin. |
|
|
45
|
+
|
|
46
|
+
## Red flags
|
|
47
|
+
|
|
48
|
+
- You started from a red or thin suite.
|
|
49
|
+
- The diff mixes a behavior change into the cleanup.
|
|
50
|
+
- You deleted code without understanding why it existed.
|
|
51
|
+
- Many simplifications landed in one step with no test run between.
|
|
52
|
+
|
|
53
|
+
## Verification
|
|
54
|
+
|
|
55
|
+
Started from green; the suite is green after every step and at the end. The diff is
|
|
56
|
+
behavior-preserving (same inputs → same outputs) and complexity is measurably lower (less
|
|
57
|
+
duplication, shallower nesting, clearer names, dead code gone). The changed path was exercised,
|
|
58
|
+
not just the tests. If behavior changed at all, this was the wrong skill — revert and use
|
|
59
|
+
`fix-bug` / `new-feature`.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: verify-e2e
|
|
3
|
+
description: Execute user-journey use cases (API and CLI in v1) against the running app, classify each, and write a committed evidence report the ship-gate binds to. Use to verify a user-facing change end to end before shipping, under Claude Code, Codex, or OpenCode.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# verify-e2e
|
|
7
|
+
|
|
8
|
+
Run **user journeys** — not unit tests — against real interfaces, then bind the result to
|
|
9
|
+
the ship-gate with an evidence report. API and CLI are executed in v1; UI is deferred
|
|
10
|
+
(record `E2E verified — N/A: UI journey, no v1 adapter`). The driver runs this; it is not a
|
|
11
|
+
cross-engine review.
|
|
12
|
+
|
|
13
|
+
## 0. Locate use cases
|
|
14
|
+
|
|
15
|
+
From the active plan (`new-feature` / `fix-bug`) or, in regression mode, from
|
|
16
|
+
`docs/e2e/use-cases/*.md`.
|
|
17
|
+
|
|
18
|
+
## 1. Validate journey shape (before executing)
|
|
19
|
+
|
|
20
|
+
Each use case MUST carry: **ID, Actor, Scenario, Interface (API|CLI), Intent, Setup, Steps
|
|
21
|
+
(≥2), Verification, Persistence**. Reject a malformed UC with a reason code and stop —
|
|
22
|
+
rewrite it, don't execute it:
|
|
23
|
+
|
|
24
|
+
- `MISSING_ACTOR` · `MISSING_SCENARIO` · `SCENARIO_FLUFF` · `CHEAT_SETUP` (Setup performs the
|
|
25
|
+
action under test) · `THIN_VERIFICATION` (bare status/exit code) · `MISSING_PERSISTENCE` ·
|
|
26
|
+
`TOO_SHALLOW` (<2 meaningful steps) · `NOT_USER_JOURNEY` (reads as a unit/contract test) ·
|
|
27
|
+
`WRONG_INTERFACE`.
|
|
28
|
+
|
|
29
|
+
## 2. ARRANGE — sanctioned setup only
|
|
30
|
+
|
|
31
|
+
Public API, signup/login, app CLI, or documented seed commands. **Forbidden:** raw DB writes
|
|
32
|
+
(`psql -c "INSERT"`, `mysql -e`, `mongosh --eval`), internal/undocumented endpoints,
|
|
33
|
+
file-injection on disk. A broken sanctioned path is a **finding, not a fix-it-here**: report
|
|
34
|
+
it (verify runs read-only) and loop the repair back through `fix-bug` / `new-feature` so the
|
|
35
|
+
app change gets its own tests and review — **never route around it** and never patch app code
|
|
36
|
+
inline during the verify phase. Credentials come from **env vars**, never hard-coded
|
|
37
|
+
(graduated use cases are committed).
|
|
38
|
+
|
|
39
|
+
## 3. Safety
|
|
40
|
+
|
|
41
|
+
- Default to a **non-production** target; require explicit confirmation otherwise.
|
|
42
|
+
- **Redact** secrets/tokens/PII from captured output before writing the report.
|
|
43
|
+
- Quote/escape UC-provided values; never `eval` raw UC text.
|
|
44
|
+
- Clean up resources you created, or note residual state in the report.
|
|
45
|
+
|
|
46
|
+
## 4. ACT + VERIFY per interface
|
|
47
|
+
|
|
48
|
+
- **API** — `curl`/`httpie`: assert status, body, headers, AND a follow-up request (e.g. GET
|
|
49
|
+
the resource a POST created via its `Location`).
|
|
50
|
+
- **CLI** — subprocess: assert stdout/stderr + exit code, AND a second invocation that
|
|
51
|
+
observes the persisted state (e.g. `add` then `list`).
|
|
52
|
+
|
|
53
|
+
No cheating in VERIFY: assert only through the interface under test.
|
|
54
|
+
|
|
55
|
+
## 5. Classify + verdict
|
|
56
|
+
|
|
57
|
+
| Result | Blocks ship? | Retry |
|
|
58
|
+
| --- | --- | --- |
|
|
59
|
+
| `PASS` | no | — |
|
|
60
|
+
| `FAIL_BUG` | yes | no |
|
|
61
|
+
| `FAIL_STALE` (UC references a renamed interface) | yes, until UC updated | no |
|
|
62
|
+
| `FAIL_INFRA` (server down/timeout) | yes if still failing after 1 retry | once |
|
|
63
|
+
| `FAIL_INVALID_UC` | yes | no |
|
|
64
|
+
|
|
65
|
+
**Top-level `VERDICT: PASS` only if every required UC is `PASS`.** Anything else →
|
|
66
|
+
`VERDICT: FAIL`.
|
|
67
|
+
|
|
68
|
+
## 6. Write the evidence report
|
|
69
|
+
|
|
70
|
+
`docs/e2e/reports/<YYYY-MM-DD>-<feature>.md` (committed). Include a header line
|
|
71
|
+
(feature, branch, ISO-8601 timestamp), the top-level `VERDICT: PASS|FAIL`, and one block per
|
|
72
|
+
UC (ID, classification, interface, trimmed+redacted output, persistence re-check).
|
|
73
|
+
|
|
74
|
+
## 7. Graduate passing use cases
|
|
75
|
+
|
|
76
|
+
Upsert each `PASS` UC by its **ID** into `docs/e2e/use-cases/<feature>.md` so later sessions
|
|
77
|
+
re-run it. Then check the `E2E verified` ship-gate box (or record `— N/A: <reason>`).
|
|
78
|
+
|
|
79
|
+
## Common rationalizations
|
|
80
|
+
|
|
81
|
+
| Rationalization | Reality |
|
|
82
|
+
| --- | --- |
|
|
83
|
+
| "Tests pass, that's enough." | Unit tests miss wiring/integration/UX. A journey exercises the real interface. |
|
|
84
|
+
| "I'll assert the status code and move on." | A bare 200/exit-0 is `THIN_VERIFICATION`. Observe a real outcome + a next observable step. |
|
|
85
|
+
| "I'll seed the row straight into the DB." | Raw DB writes are forbidden ARRANGE. Use the sanctioned interface; if it's broken, report it as a finding and loop through `fix-bug`. |
|
|
86
|
+
| "Just check the box — the report can wait." | `check-gates` binds the box to a fresh `VERDICT: PASS` report; an empty claim fails the gate. |
|
|
87
|
+
| "It's a read endpoint, skip Persistence." | Only genuinely stateless reads may use `Persistence: N/A`. |
|
|
88
|
+
|
|
89
|
+
## Red flags
|
|
90
|
+
|
|
91
|
+
- A use case with no Actor/Scenario, or an Intent naming endpoints/tables/components.
|
|
92
|
+
- Setup that performs the very action the UC is meant to test.
|
|
93
|
+
- Checking the `E2E verified` box without a committed `VERDICT: PASS` report on this branch.
|
|
94
|
+
- Verifying through a back channel (DB/logs) instead of the interface under test.
|
|
95
|
+
|
|
96
|
+
## Verification
|
|
97
|
+
|
|
98
|
+
- [ ] Every use case validated for shape before execution.
|
|
99
|
+
- [ ] API/CLI journeys executed; VERIFY only through the interface under test.
|
|
100
|
+
- [ ] Report written to `docs/e2e/reports/` with a top-level verdict; secrets redacted.
|
|
101
|
+
- [ ] Passing UCs graduated to `docs/e2e/use-cases/<feature>.md` by ID.
|
|
102
|
+
- [ ] `E2E verified` gate box checked only with a fresh `VERDICT: PASS` report (or `N/A:`).
|
package/src/sync.ps1
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env pwsh
|
|
2
|
+
#
|
|
3
|
+
# codeforge sync (Windows / PowerShell) — generate each engine's config + skills from the
|
|
4
|
+
# neutral source. No symlinks.
|
|
5
|
+
#
|
|
6
|
+
# pwsh ./sync.ps1 [-Out <dir>]
|
|
7
|
+
#
|
|
8
|
+
# Inputs are read from this script's own project (the neutral source); outputs are written
|
|
9
|
+
# to -Out (default: in place). The installer uses -Out to generate straight into a target
|
|
10
|
+
# project without copying the source or this script there (thin install).
|
|
11
|
+
#
|
|
12
|
+
# Neutral source layout (read from the script's dir):
|
|
13
|
+
# CLAUDE.md -> instructions (also copied to AGENTS.md)
|
|
14
|
+
# skills\<name>\SKILL.md -> skills, copied into each engine's discovery dir
|
|
15
|
+
# configs\claude\settings.json -> .claude\settings.json
|
|
16
|
+
# configs\codex\config.toml -> .codex\config.toml
|
|
17
|
+
# configs\opencode.json -> opencode.json (OpenCode reads it from the root)
|
|
18
|
+
#
|
|
19
|
+
# Skill discovery differs per engine: Claude Code -> .claude\skills; Codex -> .agents\skills;
|
|
20
|
+
# OpenCode -> any of .opencode/.claude/.agents. So .claude\skills + .agents\skills covers all.
|
|
21
|
+
#
|
|
22
|
+
# GENERATED (do NOT hand-edit): AGENTS.md, opencode.json, .claude, .agents, .codex (in the
|
|
23
|
+
# output dir). Edit the neutral source above, then re-run this script.
|
|
24
|
+
#
|
|
25
|
+
param(
|
|
26
|
+
[string]$Out
|
|
27
|
+
)
|
|
28
|
+
$ErrorActionPreference = 'Stop'
|
|
29
|
+
$SrcRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
30
|
+
$OutRoot = if ($Out) { $Out } else { $SrcRoot }
|
|
31
|
+
|
|
32
|
+
# validate required inputs BEFORE mutating anything
|
|
33
|
+
if (-not (Test-Path (Join-Path $SrcRoot 'skills'))) {
|
|
34
|
+
Write-Host "error: no skills\ base found in $SrcRoot"; exit 2
|
|
35
|
+
}
|
|
36
|
+
$claude = Join-Path $SrcRoot 'CLAUDE.md'
|
|
37
|
+
if (-not (Test-Path $claude)) {
|
|
38
|
+
Write-Host "error: no CLAUDE.md found in $SrcRoot"; exit 2
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
New-Item -ItemType Directory -Force -Path $OutRoot | Out-Null
|
|
42
|
+
$OutRoot = (Resolve-Path $OutRoot).Path
|
|
43
|
+
|
|
44
|
+
# instructions: CLAUDE.md -> AGENTS.md
|
|
45
|
+
Copy-Item $claude (Join-Path $OutRoot 'AGENTS.md') -Force
|
|
46
|
+
|
|
47
|
+
# skills -> each engine's discovery dir (full mirror: replace so deletions propagate).
|
|
48
|
+
# .claude\skills = Claude Code (+ OpenCode); .agents\skills = Codex (+ OpenCode).
|
|
49
|
+
foreach ($dir in '.claude', '.agents') {
|
|
50
|
+
$dirPath = Join-Path $OutRoot $dir
|
|
51
|
+
New-Item -ItemType Directory -Force -Path $dirPath | Out-Null
|
|
52
|
+
$skillsPath = Join-Path $dirPath 'skills'
|
|
53
|
+
if (Test-Path $skillsPath) { Remove-Item -Recurse -Force $skillsPath }
|
|
54
|
+
Copy-Item -Recurse (Join-Path $SrcRoot 'skills') $skillsPath
|
|
55
|
+
# ownership marker: lets the installer tell a forge-generated dir from the user's own,
|
|
56
|
+
# so it never wipes a user's skills (even one coincidentally named new-feature).
|
|
57
|
+
Set-Content -Path (Join-Path $skillsPath '.forge-generated') -Value 'generated by codeforge sync — do not edit; edit the codeforge source instead'
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
# per-engine config, placed where each engine looks for it
|
|
61
|
+
New-Item -ItemType Directory -Force -Path (Join-Path $OutRoot '.claude'), (Join-Path $OutRoot '.codex') | Out-Null
|
|
62
|
+
$cClaude = Join-Path $SrcRoot 'configs\claude\settings.json'
|
|
63
|
+
if (Test-Path $cClaude) { Copy-Item $cClaude (Join-Path $OutRoot '.claude\settings.json') -Force }
|
|
64
|
+
$cCodex = Join-Path $SrcRoot 'configs\codex\config.toml'
|
|
65
|
+
if (Test-Path $cCodex) { Copy-Item $cCodex (Join-Path $OutRoot '.codex\config.toml') -Force }
|
|
66
|
+
$cOpen = Join-Path $SrcRoot 'configs\opencode.json'
|
|
67
|
+
if (Test-Path $cOpen) { Copy-Item $cOpen (Join-Path $OutRoot 'opencode.json') -Force }
|
|
68
|
+
|
|
69
|
+
Write-Host "codeforge sync: generated AGENTS.md, opencode.json, .claude/ (settings + skills), .agents/skills, and .codex/config.toml into $OutRoot"
|
package/src/sync.sh
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# codeforge sync — generate each engine's config + skills from the neutral source.
|
|
4
|
+
#
|
|
5
|
+
# ./sync.sh [--out <dir>]
|
|
6
|
+
#
|
|
7
|
+
# No symlinks (Windows-safe; use sync.ps1 on Windows). Inputs are read from this script's
|
|
8
|
+
# own project (the neutral source); outputs are written to --out (default: in place).
|
|
9
|
+
#
|
|
10
|
+
# --out <dir> write the generated engine artifacts into <dir> instead of alongside the
|
|
11
|
+
# source. The installer uses this to generate straight into a target project
|
|
12
|
+
# without copying the source or this script there (thin install).
|
|
13
|
+
#
|
|
14
|
+
# Neutral source layout (read from the script's dir):
|
|
15
|
+
# CLAUDE.md → instructions (also copied to AGENTS.md)
|
|
16
|
+
# skills/<name>/SKILL.md → skills, copied into each engine's discovery dir
|
|
17
|
+
# configs/claude/settings.json → .claude/settings.json
|
|
18
|
+
# configs/codex/config.toml → .codex/config.toml
|
|
19
|
+
# configs/opencode.json → opencode.json (OpenCode reads it from the root)
|
|
20
|
+
# shared/rules/*.md → discipline (read in place by the agent; not copied here)
|
|
21
|
+
#
|
|
22
|
+
# Skill discovery paths differ per engine (verified against each CLI's docs):
|
|
23
|
+
# Claude Code → .claude/skills | Codex → .agents/skills | OpenCode → any of
|
|
24
|
+
# .opencode/.claude/.agents. So .claude/skills + .agents/skills covers all three.
|
|
25
|
+
#
|
|
26
|
+
# GENERATED (do NOT hand-edit — regenerated on every run): AGENTS.md, opencode.json,
|
|
27
|
+
# .claude/, .agents/, .codex/ (in the output dir). Edit the neutral source, then re-run.
|
|
28
|
+
#
|
|
29
|
+
set -euo pipefail
|
|
30
|
+
SRC_ROOT="$(cd "$(dirname "$0")" && pwd)"
|
|
31
|
+
OUT_ROOT="$SRC_ROOT"
|
|
32
|
+
|
|
33
|
+
while [ $# -gt 0 ]; do
|
|
34
|
+
case "$1" in
|
|
35
|
+
--out) shift; OUT_ROOT="${1:-}"; [ -n "$OUT_ROOT" ] || { echo "error: --out requires a directory" >&2; exit 2; } ;;
|
|
36
|
+
--out=*) OUT_ROOT="${1#--out=}" ;;
|
|
37
|
+
*) echo "usage: $0 [--out <dir>] (unknown arg: $1)" >&2; exit 2 ;;
|
|
38
|
+
esac
|
|
39
|
+
shift
|
|
40
|
+
done
|
|
41
|
+
|
|
42
|
+
# validate required inputs BEFORE mutating anything
|
|
43
|
+
[ -d "$SRC_ROOT/skills" ] || { echo "error: no skills/ base found in $SRC_ROOT" >&2; exit 2; }
|
|
44
|
+
[ -f "$SRC_ROOT/CLAUDE.md" ] || { echo "error: no CLAUDE.md found in $SRC_ROOT" >&2; exit 2; }
|
|
45
|
+
|
|
46
|
+
mkdir -p "$OUT_ROOT"
|
|
47
|
+
OUT_ROOT="$(cd "$OUT_ROOT" && pwd)"
|
|
48
|
+
|
|
49
|
+
# instructions: CLAUDE.md -> AGENTS.md (Codex + OpenCode read AGENTS.md)
|
|
50
|
+
cp "$SRC_ROOT/CLAUDE.md" "$OUT_ROOT/AGENTS.md"
|
|
51
|
+
|
|
52
|
+
# skills -> each engine's discovery dir (full mirror: replace so deletions propagate).
|
|
53
|
+
# .claude/skills = Claude Code (+ OpenCode); .agents/skills = Codex (+ OpenCode).
|
|
54
|
+
for dir in .claude .agents; do
|
|
55
|
+
mkdir -p "$OUT_ROOT/$dir"
|
|
56
|
+
rm -rf "$OUT_ROOT/$dir/skills"
|
|
57
|
+
cp -R "$SRC_ROOT/skills" "$OUT_ROOT/$dir/skills"
|
|
58
|
+
# ownership marker: lets the installer tell a forge-generated dir from the user's own,
|
|
59
|
+
# so it never wipes a user's skills (even one coincidentally named new-feature).
|
|
60
|
+
printf 'generated by codeforge sync — do not edit; edit the codeforge source instead\n' > "$OUT_ROOT/$dir/skills/.forge-generated"
|
|
61
|
+
done
|
|
62
|
+
|
|
63
|
+
# per-engine config, placed where each engine looks for it
|
|
64
|
+
mkdir -p "$OUT_ROOT/.claude" "$OUT_ROOT/.codex"
|
|
65
|
+
[ -f "$SRC_ROOT/configs/claude/settings.json" ] && cp "$SRC_ROOT/configs/claude/settings.json" "$OUT_ROOT/.claude/settings.json"
|
|
66
|
+
[ -f "$SRC_ROOT/configs/codex/config.toml" ] && cp "$SRC_ROOT/configs/codex/config.toml" "$OUT_ROOT/.codex/config.toml"
|
|
67
|
+
[ -f "$SRC_ROOT/configs/opencode.json" ] && cp "$SRC_ROOT/configs/opencode.json" "$OUT_ROOT/opencode.json"
|
|
68
|
+
|
|
69
|
+
echo "codeforge sync: generated AGENTS.md, opencode.json, .claude/ (settings + skills), .agents/skills, and .codex/config.toml into $OUT_ROOT"
|