Skip to content

epic: customer-tunable Product Brainstormer / PO Master (vision + axes drive every ticket) #121

@hadamrd

Description

@hadamrd

Why

Today forge-loop's PO expands whatever issue you label loop:ready. It has no opinion about whether the ticket should exist. The result: backlogs drift toward cosmetic features (ETag headers, sparklines, theme polish) because anyone can file anything and the loop will ship it.

For paid customer use, every project running forge-loop needs a Product Brainstormer / PO Master that is opinionated about what work matters — and that opinion is tunable per project.

What

A first-class forge-loop feature: each project defines its own product vision + product axes in .forge/. The brainstormer reads them before proposing ANY ticket, fills epics aligned with the axes, dispatches tickets under those epics, and refuses cosmetic work by an explicit rubric.

Customer story

A platform lead drops .forge/product-vision.md + .forge/axes.yaml into their repo. They write 5 sentences about who their customer is and 4-6 named value axes. forge-loop brainstorm reads it, files epics, populates tickets under those epics. The iteration loop picks them up. Cosmetic tickets the team accidentally files get demoted to loop:cold automatically.

Files customers own

.forge/product-vision.md

Free-form. Names the customer, the golden path, the wedge ("what makes this product valuable to a paying user"). The brainstormer quotes from it in every ticket it files (so reviewers can audit alignment).

.forge/axes.yaml

Structured. Each axis: name, customer, "valuable means", acceptable_work, rejected_as_cosmetic. The brainstormer scores every proposed ticket against the rubric — must move at least one axis, must not match the rejected list.

axes:
  - name: golden-path-e2e
    customer: "SRE deploying the product for the first time"
    valuable_means: "...customer-shaped Playwright fixtures..."
    acceptable_work:
      - "Playwright tests against the real rig"
      - "Adversarial paths: failed step, OOM step, secret leak"
    rejected_as_cosmetic:
      - "Pagination on endpoints customers don't poll"
      - "Visual polish without a UX defect"
  - name: scm-depth
    ...

Acceptance

  • .forge/product-vision.md is auto-discovered at brainstormer-start. Missing file = brainstormer refuses to file tickets, emits a clear "no vision file" error.
  • .forge/axes.yaml is auto-discovered with a schema (pydantic). Missing/invalid = same hard refusal.
  • New forge-loop brainstorm CLI command runs the brainstormer once and prints proposed epics/tickets without filing them (dry-run by default). --apply files them on GitHub.
  • The brainstormer fills epics (issues labeled epic + axis:<name>) and tickets under each epic (issues labeled loop:ready + axis:<name> + epic cross-link). Tickets without an axis label are anti-pattern.
  • Every ticket body includes: named customer story, axis citation, epic link, "valuable because" rubric checkmark, "rejected as cosmetic? no because" gate-clearance.
  • Periodic backlog audit: every Nth tick the brainstormer scans existing loop:ready tickets and demotes ones that don't match any axis to loop:cold + comments why.
  • Hard refusals enforced by the brainstormer prompt (issue refactor(events): typed discriminated-union schema for events.jsonl + one emit() helper #88 typed events for "ticket_rejected_cosmetic" outcome).

Sub-tickets (this epic's children)

Filed in this PR as separate issues:

  1. .forge/product-vision.md + .forge/axes.yaml discovery + pydantic schema
  2. Brainstormer skill module (forge_loop/brainstormer.py) — reads vision + axes, fills epics + tickets
  3. forge-loop brainstorm CLI command (dry-run + --apply)
  4. Periodic backlog audit (demote cosmetic tickets to loop:cold)
  5. Per-axis label namespace + axis-aware sort/filter in forge-loop status

NOT in scope

  • The product vision content itself (each customer writes their own)
  • The Titan-specific axes (lives in dashboard-plugin/.forge/product-vision.md as the reference example, NOT in forge-loop core)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions