Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,74 @@ Placeholders the loader fills: `{n}`, `{issue_title}`, `{body}`, `{worktree}`,

---

## Manifestos & the brainstormer (axis-aligned tickets)

`forge-loop` does NOT just ship whatever you label. To produce *valuable* work the loop reads four customer-owned manifestos under `.forge/` and refuses cosmetic tickets.

### The four files you own

```
.forge/
├── product-vision.md # free-form prose: who you serve, the wedge, what's NOT valuable
├── axes.yaml # structured: the 4-6 value axes the loop must move
├── quality-manifesto.md # how code MUST be written (critic enforces, sev1 blocks merge)
└── testing-manifesto.md # how tests MUST be written (consulted by worker post-impl)
```

Every shipped ticket cites the axis it serves; every PR is gated by the quality + testing manifestos via the critic.

### Example `axes.yaml`

```yaml
axes:
- name: golden-path-e2e
customer: "SRE running their first pipeline on day zero"
valuable_means: "Playwright tests driving the real rig — golden path survives every release"
acceptable_work:
- "Customer-shaped pipeline fixtures (Node, Java, polyglot)"
- "Adversarial paths: failed step, OOM step, secret-needing step"
rejected_as_cosmetic:
- "304 responses to polls customers don't notice"
- "Pretty timestamps, sparklines, theme polish"

- name: scm-depth
customer: "Team migrating from GitLab self-hosted / Bitbucket Cloud"
...
```

### Brainstormer workflow

```bash
# 1. Drop manifestos in .forge/ (see above)

# 2. Dry-run — propose axis-aligned epics + tickets, print them
GH_TOKEN=$(gh auth token) forge-loop brainstorm

# 3. Apply — file them on GitHub with axis labels
forge-loop brainstorm --apply

# 4. The loop dispatches on the new loop:ready tickets normally
forge-loop run
```

Each filed ticket carries `axis:<name>` + `loop:ready` (or `epic` for parent rollups), plus a customer-story quote pulled from your vision.

### The feedback loop

Every bug → quality manifesto update → permanent gate.

```bash
# 1. A bug ships and gets fixed in PR #N
# 2. Generate a manifesto delta proposal based on the failure shape
forge-loop manifesto suggest --from-pr <N>

# 3. Review + commit. From the next worker run, the critic enforces it.
```

Real example: PR #147 hot-fixed a stringly-typed event-boundary bug. The quality manifesto gained a `No stringly-typed cross-module discriminators` rule. The critic now blocks any future PR that compares `event["kind"] == "literal"` across module boundaries.

---

## CLI reference

```
Expand All @@ -236,6 +304,9 @@ forge-loop record-session # capture a real SDK session as a test fixture
forge-loop replay --tick N # dry-run replay of a past tick
forge-loop brief --kind worker --issue 42 # render the brief the loop would send
forge-loop config [models] # print resolved config (or per-role model table)
forge-loop brainstorm # propose axis-aligned epics + tickets (dry-run)
forge-loop brainstorm --apply # file the proposed tickets on GitHub
forge-loop manifesto suggest --from-pr N # propose manifesto deltas from a bug fix
forge-loop pipeline show # render the .forge/pipeline.yaml DAG
forge-loop repos list/disable/enable # multirepo state
forge-loop roles list # pluggable role definitions
Expand Down
90 changes: 84 additions & 6 deletions docs/GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,85 @@ You can run the loop overnight and wake up to either (a) merged PRs, or

---

## 4. The brief is your contract
## 4. Manifestos: drive what gets built (not just how)

Out of the box, the loop will ship whatever ticket you label `loop:ready`. That's fine for a hobbyist run — but it's also how backlogs drift toward cosmetic features (sparklines, ETag headers, theme polish) that ship effortlessly and add zero customer value.

Manifestos are how you tell the loop **what should exist**, not just how to build it.

### The four files

Drop these in your repo at `.forge/`:

| File | Owns |
|---|---|
| `product-vision.md` | Prose: who you serve, the golden path, the wedge, what's NOT valuable |
| `axes.yaml` | Structured: 4-6 value axes with customer, acceptable_work, rejected_as_cosmetic |
| `quality-manifesto.md` | Hard rules: how code MUST be written. **Critic enforces — sev1 blocks auto-merge.** |
| `testing-manifesto.md` | Hard rules: how tests MUST be written. Worker reads after impl, before push. |

Every shipped ticket cites its axis. Every PR is gated by the manifestos.

### Bootstrapping a project

```bash
# 1. Author the four files (steal from the seed examples in this repo)
$EDITOR .forge/product-vision.md
$EDITOR .forge/axes.yaml
$EDITOR .forge/quality-manifesto.md
$EDITOR .forge/testing-manifesto.md

# 2. Dry-run the brainstormer — it proposes axis-aligned epics + tickets
GH_TOKEN=$(gh auth token) forge-loop brainstorm

# 3. Apply: file them on GitHub with axis labels + customer-story citations
forge-loop brainstorm --apply

# 4. Dispatch — the loop only picks tickets that carry an axis label
forge-loop run
```

The brainstormer **refuses** to file a ticket that doesn't move an axis or that matches a `rejected_as_cosmetic` pattern. Example output:

```
brainstorm: filed:
+ #1114: EPIC: Real RBAC — role model, per-action gates, SSO mapping, audit
+ #1116: test(e2e): adversarial golden-path fixtures — failed step, secret-needing, OOM
+ #1117: feat(scm): Bitbucket Cloud — PR-comment status + line-level review parity
+ #1118: feat(scm): webhook reconcile loop — catch missed events on transient SCM outage
+ #1119: feat(pdl): real-shaped fixture — Node app with lint+test+build+deploy
+ #1121: feat(rbac): permission check helper + enforce on /api/v1/builds re-run (smallest enforceable slice)
```

Notice the brainstormer split RBAC into an epic plus a "smallest enforceable slice" — it knows multi-day work is unshippable in one tick.

### The feedback loop

Every bug → manifesto update → permanent gate.

```bash
# A bug shipped and got fixed in PR #N.
# Propose what manifesto rule would have prevented it:
forge-loop manifesto suggest --from-pr <N>

# Review the proposal, commit if good. The critic enforces it from
# the next worker run.
```

Real example: PR #147 hot-fixed a stringly-typed event-boundary bug (a four-PR train of identical-shape bugs preceded it). The quality manifesto gained `No stringly-typed cross-module discriminators — sev1`. Any future PR that compares `event["kind"] == "literal"` across module boundaries now gets auto-blocked by the critic.

### What the worker sees

Before writing code, every worker dispatch loads:
- The product vision (so the worker writes value-aligned commits + PR descriptions)
- The quality manifesto (so the impl follows project conventions)
- The testing manifesto (consulted POST-implementation, BEFORE push)

The critic loads the same set + the proposed diff. Sev1 manifesto violations are blocking review comments, not nits.

---

## 5. The brief is your contract

Out of the box, the worker brief tells Claude to:

Expand All @@ -205,7 +283,7 @@ Same for `.forge-loop/briefs/po.md.tmpl`. A Titan-grade PO brief looks like

---

## 5. Cost and economics
## 6. Cost and economics

Observed on Opus 4.7 with subscription billing (Max plan, no per-token charge):

Expand All @@ -227,7 +305,7 @@ discipline (close obvious duplicates as soon as you see them) matters.

---

## 6. When things go wrong
## 7. When things go wrong

### Loop self-halted with a `loop:halt` issue

Expand Down Expand Up @@ -281,7 +359,7 @@ path. Manual close is the firm path when the worker doesn't notice.

---

## 7. Patterns observed across many runs
## 8. Patterns observed across many runs

These come from dogfooding the loop on its own codebase + on the Titan
engine. They are real, not theoretical.
Expand Down Expand Up @@ -311,7 +389,7 @@ worker's branch name is derived from the issue title at dispatch time.

---

## 8. Going further
## 9. Going further

- [README.md](../README.md) — the reference
- `forge-loop --help` — every subcommand
Expand All @@ -326,7 +404,7 @@ worker's branch name is derived from the issue title at dispatch time.

---

## 9. Final piece of advice
## 10. Final piece of advice

The loop is patient. It will tick idle for hours waiting for work.
There is no rush to "use up" your subscription quota or fill the queue.
Expand Down
Loading