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
35 changes: 12 additions & 23 deletions skills/implementing-tickets/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,37 +27,26 @@ Toolkit:

THE GATE comes before everything. Do not write code until the ticket
passes. Interrogate the brief the way a doperpowers:brainstorming grill
interrogates a human — but every answer must come from the ticket body, the
codebase, or repo docs. The human is a source too — asynchronously: a
human-grade fork parks, and the relayed answers become ticket content
before work resumes. Trivial lookups (docs, grep, an API's actual shape)
interrogates a human. Trivial lookups (docs, grep, an API's actual shape)
are orient work: do them, never park for them.

Check 1 — WELL-DEFINED. Classify every fork the implementation will hit:
- Mechanical/technical with one obvious best answer (internal naming,
idiomatic choice, repo precedent) → YOUR call. Parking these is a
protocol violation, not caution.
- Non-trivial architecture (subsystem boundary, data model, API shape) →
must be answered by ticket + codebase; unanswered → gate-fail.
- Product design or taste, major OR minor (user-facing behavior, wording,
interaction/visual choices — anywhere a reasonable human could prefer
differently on non-technical grounds) → must be answered by the ticket;
unanswered → gate-fail. Even minor taste is never your call.

Check 2 — WELL-SCOPED. The work must fit this ticket as one purpose-unit
(roughly 1–2 ExecPlans — big-but-ATOMIC work that cannot land halfway
still counts as ONE unit; that is what plan-mode execution exists for.
Decompose only work whose children could land on main independently).
Too big? One question decides: can the remainder
be written down as self-contained child pre-specs right now?
- Yes → DECOMPOSE: open the decomposition procedure — read this file and
The two checks — WELL-DEFINED (who owns each fork the implementation
will hit) and WELL-SCOPED (fits this ticket as one purpose-unit) — are
board schema, one copy next to the board scripts. Open the gate file and
run both checks against the ticket:
{{BOARD_SCRIPTS}}/../references/ticket-gate.md
Check-2 outcomes are yours to execute:
- Too big, and the remainder CAN be written down as self-contained child
pre-specs right now → DECOMPOSE: open the decomposition procedure — read
this file and
follow it before registering a single child:
{{DECOMPOSE_DOC}}
It carries the register command with typed edges, the pre-spec bar for
child bodies, honest gate-triage, the Roadmap escape hatch for
contingent phases, and the parent update. You write NO code; end your
turn when the children stand.
- No — the slices need one continuously steered human context →
- Too big and NOT decomposable — the slices need one continuously steered
human context →
{{BOARD_SCRIPTS}}/board-transition.sh {{ISSUE_NUMBER}} interactive-preferred "<which decision areas need steering>"
and end your turn.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ only the PROCEDURE and grants no authority beyond your prompt's.

3. Gate-triage each child HONESTLY per the doperpowers:issue-tracker
ticket contract and park discriminant — `ready-for-agent` only if YOU
believe it passes the Ticket Gate.
believe it passes the Ticket Gate
(`<BOARD_SCRIPTS>/../references/ticket-gate.md`).

4. Register only children you can spec self-contained NOW. Contingent
later phases live as a `## Roadmap` section in the parent body — the
Expand Down
27 changes: 7 additions & 20 deletions skills/implementing-tickets/references/operation-manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,30 +24,17 @@ audit trail, not requests. Full design + rationale:
| `references/spike-worker-protocol.md` | the Spike Worker Protocol — bound as `PROTOCOL_FILE` when the ticket's category is `spike` (the exploration lane below) |
| `references/implement-decompose.md` | runtime-opened decomposition procedure — the protocol carries only a pointer (`{{DECOMPOSE_DOC}}` = absolute path); the worker opens it when Check-2 says decompose. Conditional-large protocol blocks live this way: procedure in a plugin file, instance facts in the prompt |
| `references/engine-blocks/execution.md` | the EXECUTION text — one block for both model routes, since every worker is a Claude-harness session (the engine label picks the model route: `codex` = clodex gateway/GPT, `claude` = plain Claude); keeps interactive-session skills (writing-plans, subagent-driven-development) out of daemon workers; rides the bootstrap's EXECUTION_BLOCK binding (implement lane only — spikes are exploration, not TDD) |
| The Ticket Gate | the pre-code pass/park verdict (below) |
| The Ticket Gate | the pre-code pass/park verdict (below; check definitions in issue-tracker's `references/ticket-gate.md`) |
| board schema + dispatch ritual | owned by doperpowers:issue-tracker (states, scripts, the mechanical ritual, the wake ritual) |
| `scripts/` | empty this phase — the auto-attach trigger (`implement-dispatch.sh` + workflow template) lands here next phase |

## The Ticket Gate

Runs during ORIENT, before any source file opens — brainstorming's grill in
absentia: every answer must come from the ticket body, the codebase, or
repo docs. Trivial lookups are orient work, never a park.

**Check 1 — well-defined.** Every fork the implementation will hit:

| fork class | who answers |
|---|---|
| mechanical/technical, one obvious best answer | the worker — parking these is a protocol violation, not caution |
| non-trivial architecture (subsystem boundary, data model, API shape) | ticket + codebase; unanswered → gate-fail |
| product design or taste, **major or minor** | the ticket; unanswered → gate-fail — even minor taste is never the worker's call |

**Check 2 — well-scoped.** Fits ~1–2 ExecPlans — big-but-atomic work that
cannot land halfway still counts as ONE unit (that is what ExecPlan mode
exists for); decompose only work whose children could land on main
independently. Too big forks on ONE question: *can the remainder be
written as self-contained child pre-specs right now?* Yes → decompose.
No → `interactive-preferred`.
Runs during ORIENT, before any source file opens — brainstorming's grill
in absentia. The two checks' definitions (WELL-DEFINED fork ownership,
WELL-SCOPED sizing) are board schema, owned by doperpowers:issue-tracker
in `references/ticket-gate.md` — one copy for workers and registrars
alike; the worker protocol routes there at gate time.

**The verdict is the worker's first board write.** Dispatch writes nothing;
`in-progress` + a `[gate]` comment = pass, a park state = fail.
Expand Down Expand Up @@ -130,7 +117,7 @@ What changes and what doesn't:
re-parks), or graduates.
- **Graduation** — production work the findings clearly justify is
registered `--spawned-by <spike>` with honest gate-triage against the
IMPLEMENT gate; murkier outcomes stay a Recommendation line for the
Ticket Gate; murkier outcomes stay a Recommendation line for the
human.
- The engine label picks a model route only (web reach is harness-level —
every worker has it); choose per the work's model fit, mechanism
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ Graduation: when the findings clearly warrant production work you can spec
self-contained NOW, register it ({{BOARD_SCRIPTS}}/board-register.sh
"<title>" <bug|enhancement> <P0..P3> --spawned-by {{ISSUE_NUMBER}}
--body-file <spec>), gate-triaged honestly (ready-for-agent only if it
would pass the IMPLEMENT gate; an open taste fork → born needs-human).
would pass the Ticket Gate — {{BOARD_SCRIPTS}}/../references/ticket-gate.md;
an open taste fork → born needs-human).
Per the doperpowers:issue-tracker ticket contract,
author its body at register time — the pre-spec sections filled from your
findings; a skeleton "to fill in later" is not a graduation. Anything
Expand Down
2 changes: 1 addition & 1 deletion skills/issue-tracker/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ the review loop (doperpowers:reviewing-prs) a PR passes through

| state | GitHub encoding | meaning | note |
|---|---|---|---|
| `ready-for-agent` | open + `status:ready-for-agent` | pre-spec complete (the bar: it would pass the implement gate — well-defined + well-scoped, doperpowers:implementing-tickets; the next worker re-runs that gate, so this claim is a recommendation, never inherited trust); dispatchable once blockers are done | — |
| `ready-for-agent` | open + `status:ready-for-agent` | pre-spec complete (the bar: the Ticket Gate`references/ticket-gate.md`, well-defined + well-scoped; the next worker re-runs it, so a registrar's claim is a recommendation, never inherited trust); dispatchable once blockers are done | — |
| `in-progress` | open + `status:in-progress` | a worker passed the gate and is driving it (an epic stays here while children run) | optional |
| `needs-human` | open + `status:needs-human` | parked for the human **as themselves**: a decision only they can make, or a real-world input only they possess (credentials, auth, production data) | **required** |
| `needs-info` | open + `status:needs-info` | rare: the spec is unambiguous but lacks depth for a sophisticated result, or core decisions need substantial research first | **required** |
Expand Down
39 changes: 39 additions & 0 deletions skills/issue-tracker/references/ticket-gate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# The Ticket Gate — what `ready-for-agent` means

The bar a ticket must pass before implement work begins — board schema,
one copy, owned by doperpowers:issue-tracker. Consumed everywhere a
readiness judgment is made: the implement worker re-runs both checks at
every dispatch (a registrar's verdict is a
recommendation, never inherited trust), and every registrar — follow-ups,
decompose children, spike graduations, feedback triage, sprint
materialization — triages honestly against it: `ready-for-agent` only if
the ticket would pass.

Every answer must come from the ticket body, the codebase, or repo docs.
The human is a source too — asynchronously: a human-grade fork parks the
ticket, and the relayed answers become ticket content before work
resumes.

## Check 1 — WELL-DEFINED

Classify every fork the implementation will hit:

- Mechanical/technical with one obvious best answer (internal naming,
idiomatic choice, repo precedent) → the worker's call. Parking these is
a protocol violation, not caution.
- Non-trivial architecture (subsystem boundary, data model, API shape) →
must be answered by ticket + codebase; unanswered → gate-fail.
- Product design or taste, major OR minor (user-facing behavior, wording,
interaction/visual choices — anywhere a reasonable human could prefer
differently on non-technical grounds) → must be answered by the ticket;
unanswered → gate-fail. Even minor taste is never the worker's call.

## Check 2 — WELL-SCOPED

The work must fit the ticket as one purpose-unit: roughly 1–2 ExecPlans —
big-but-ATOMIC work that cannot land halfway still counts as ONE unit
(that is what plan-mode execution exists for). Decompose only work whose
children could land on main independently. Too big? One question decides:
can the remainder be written down as self-contained child pre-specs right
now? Yes → decompose. No → the work needs one continuously steered human
context: `interactive-preferred`.
5 changes: 3 additions & 2 deletions skills/triaging-feedback/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ launchd-cron'd) claims pending rows, drives a read-only Codex-SDK worker
through the Triage Worker Protocol (`references/triage-worker-protocol.md`)
in a disposable detached worktree, and registers the ticket the worker
authored — born `ready-for-agent` when the diagnosis is grounded and the
ticket honestly passes the implement-side gate definitions, else parked
ticket honestly passes the Ticket Gate (the board schema's
`references/ticket-gate.md` in doperpowers:issue-tracker), else parked
(`needs-human`/`needs-info`) with an explicit note saying what is unclear.

**The worker is a translator, not a fixer.** It writes no code and opens no
Expand Down Expand Up @@ -147,7 +148,7 @@ network. It cannot register a ticket or write to the `feedback` table — it
can only emit a diagnosis and a structured verdict (the fenced JSON block)
that the dispatcher parses. But *within* that verdict the worker has full
editorial voice: it authors the ticket's title and body to the board's
standard (the implement-side well-defined + well-scoped gate is the
standard (the board's well-defined + well-scoped Ticket Gate is the
authoring bar) and recommends the birth state.

The dispatcher (`dispatch.ts`, running with real credentials) is the only
Expand Down
29 changes: 24 additions & 5 deletions tests/implementing-tickets/test-protocol-content.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@ echo "protocol content:"
[ -f "$PROTO" ] || { echo "missing $PROTO"; exit 1; }
proto="$(cat "$PROTO")"
assert_contains "$proto" "THE GATE comes before everything" "gate precedes everything"
assert_contains "$proto" "WELL-DEFINED" "check 1 present"
assert_contains "$proto" "WELL-SCOPED" "check 2 present"
assert_contains "$proto" "Even minor taste is never your call" "minor-taste rule present"
assert_contains "$proto" "WELL-DEFINED" "check 1 named"
assert_contains "$proto" "WELL-SCOPED" "check 2 named"
assert_contains "$proto" "/../references/ticket-gate.md" "gate definitions route to the schema file (BOARD_SCRIPTS-relative)"
assert_not_contains "$proto" "internal naming" "fork taxonomy not re-vendored in the protocol"
assert_contains "$proto" "VERDICT IS YOUR FIRST BOARD WRITE" "verdict-first-write present"
assert_contains "$proto" "WHO UNPARKS IT" "park discriminant present"
assert_contains "$proto" "{{DECOMPOSE_DOC}}" "decompose procedure pointer present (runtime-opened)"
Expand All @@ -55,8 +56,7 @@ assert_contains "$proto" "## Validation Evidence" "validation-evidence section m
assert_contains "$proto" "## Confusions" "confusions section (conditional) mandated"
assert_contains "$proto" "ORIENTATION SUMMARY" "park orientation summary mandated"
assert_contains "$proto" "no live progress mirror" "no-mirror doctrine stated in the protocol"
assert_contains "$proto" "big-but-ATOMIC" "atomic-counts-as-one-unit scoping clause present"
assert_contains "$proto" "land on main independently" "landability decompose criterion present"
assert_not_contains "$proto" "land on main independently" "landability criterion lives in the gate file, not the protocol"
assert_contains "$proto" "single home" "park discriminant routes to issue-tracker (single-source)"
assert_not_contains "$proto" "Knowledge work anyone could do" "needs-info definition not re-vendored in the protocol"
assert_contains "$proto" "doperpowers:reviewing-prs" "handoff to the review loop named"
Expand Down Expand Up @@ -179,6 +179,25 @@ assert_contains "$tracker" "worker-bootstrap.md" "ritual: renders the bootstrap,
assert_not_contains "$tracker" "embedded verbatim" "ritual: verbatim-embed spawn retired"
assert_not_contains "$tracker" "implement-worker-protocol.md" "ritual: no reference to the retired protocol file"

echo "ticket gate (schema file, single copy):"
GATE="$REPO_ROOT/skills/issue-tracker/references/ticket-gate.md"
[ -f "$GATE" ] || { echo "missing $GATE"; exit 1; }
gate="$(cat "$GATE")"
assert_contains "$gate" "WELL-DEFINED" "gate: check 1 canonical here"
assert_contains "$gate" "WELL-SCOPED" "gate: check 2 canonical here"
assert_contains "$gate" "protocol violation, not caution" "gate: mechanical forks are the worker's (parking them is the violation)"
assert_contains "$gate" "never the worker's call" "gate: minor-taste rule canonical here"
assert_contains "$gate" "big-but-ATOMIC" "gate: atomic-counts-as-one-unit sizing canonical here"
assert_contains "$gate" "land on main independently" "gate: landability decompose criterion canonical here"
assert_contains "$gate" "recommendation, never inherited trust" "gate: registrar verdicts are recommendations (gate re-runs)"
assert_contains "$gate" "The human is a source too" "gate: human-as-async-answer-source clause carried over"
assert_not_contains "$gate" "{{" "gate: placeholder-free (opened at runtime, never rendered)"
assert_contains "$tracker" "ticket-gate.md" "tracker: ready-for-agent row names its bar (the gate file)"
assert_contains "$manual" "ticket-gate.md" "manual: gate section routes to the schema file"
assert_not_contains "$manual" "one obvious best answer" "manual: fork table not re-vendored"
assert_contains "$spike" "ticket-gate.md" "spike: graduation bar routes to the gate file"
assert_contains "$decomp" "ticket-gate.md" "decompose doc: child triage bar routes to the gate file"

echo "board schema single-source (issue-tracker owns the discriminant):"
assert_contains "$tracker" "Park discriminant — who unparks it?" "tracker: canonical discriminant lives here"
assert_contains "$tracker" "recommended answer" "tracker: needs-human note contract (question list with recommendations)"
Expand Down