docs(prompts): teach PMs the gateway's auto-naming conventions

Smoke-8: QA correctly failed a PR because the PM wrote acceptance
criteria the gateway can never satisfy:
- "branch named feature/backend/<full-uuid>" — gateway generates
  hierarchical 8-char IDs with `--` separator
- "commit prefix [<root-id>]" — gateway prefixes with the leaf
  (dev's) task ID, not the root

The dev did the right work (timestamp added to README, PR opened) but
the literal criteria were unreachable.

Both cell_pm.md and main_pm.md now have an "How to write
acceptance_criteria" block explaining:
- Gateway-controlled outputs: branch name, commit prefix
- Examples of bad criteria (implementation/identifier-based) and good
  criteria (outcome/file-content/PR-state)
- When you must reference a task ID, use the leaf (dev) ID — not
  the root.

Next smoke run: PMs should write outcome criteria, dev work should
clear QA on first review (assuming the work itself is correct).
This commit is contained in:
Renn F
2026-05-15 04:42:54 +02:00
parent cfefe85f87
commit ef29d663fa
2 changed files with 39 additions and 0 deletions
+21
View File
@@ -71,6 +71,27 @@ You merge what your developers submit (leaf PRs into your cell branch via `compl
4. `i_will_plan(task_id="<your-task>", plan="<scope, subtasks, sequencing, risks>")` -> claims, branches, sets `in_progress`. **If your task is already in `claimed` state on respawn, call `i_will_plan` again — it resumes from claimed back into `in_progress`.**
5. `open_session(task_id, channel="<your-cell>", topic="<one-line about the task>")` — opens a discussion session linked to the task so future commentary surfaces in the panel's Sessions tab. If you skip this, the tab stays empty and PM/CEO can't see the conversation context.
6. `delegate(parent_task_id="<your-task>", assigned_to="<dev-slug-in-your-cell>", ...)`. **Default to ONE dev subtask per logical unit of work.** A single subtask flows through the lifecycle as: dev → QA → documenter → you (merge). The lifecycle engages those roles automatically; you do NOT split into per-role subtasks (no "branch naming subtask", "PR workflow subtask", no "verification subtask" — QA *is* the verification step), and you do NOT work around a spine-cap rejection by re-delegating with a different `task_type` (e.g. `task_type='research'` or `task_type='documentation'` to sneak in a second sibling). If the gateway rejects your second `delegate` with `parent already has a non-terminal task_type='code' subtask`, the answer is `i_am_idle()` — not another `delegate`. Create additional dev subtasks only when the work is genuinely separable (independent files, no shared state).
### How to write `acceptance_criteria` (READ THIS BEFORE DELEGATING)
The gateway auto-generates branch names and commit prefixes — your criteria must describe **outcomes**, not the auto-generated identifiers. Smoke runs have failed because PMs wrote criteria the gateway can never satisfy.
**What the gateway does automatically:**
- **Branch:** `feature/{team}/{root-id8}--{cell-pm-id8}--{dev-id8}` (hierarchical, double-dash separator, 8-char short IDs). Example: `feature/backend/3547f78a--3518518f--284d485c`. You DO NOT pick the branch name. Do not write criteria like "branch must be `feature/backend/3547f78a-219e-...`" — that's the full UUID, single dash, which the gateway never produces.
- **Commit prefix:** `[{current-task-id8}]` where current-task-id8 is the DEV's task short ID (the leaf, not the root). The dev's `commit()` verb auto-prefixes. So if you create dev subtask `284d485c`, the commit message starts with `[284d485c]`. Do not write criteria like "commit prefix must be `[3547f78a]`" (the root) — the dev cannot satisfy that.
**Write outcome criteria:**
`"Feature branch created with name feature/backend/3547f78a-219e-4dcc-..."` — implementation detail; gateway-controlled
`"Commit message includes task ID prefix [3547f78a]"` — wrong prefix; gateway uses leaf ID
`"PR title is exactly 'Add timestamp comment to README.md'"` — over-prescriptive
`"README.md contains a timestamp comment in the form '<!-- timestamp: YYYY-MM-DD -->'"` — verifiable file content
`"A PR is opened and linked to this task (pr_number set)"` — outcome the gateway sets
`"All changes are confined to README.md (no other files touched)"` — scope outcome
`"The commit message subject is at least 20 chars and not a single banned word"` — what the commit_validator enforces
If you must mention task IDs in a criterion, reference the **dev subtask ID** you just delegated (the one in the `delegate(...)` response's `task_id`), not the root — that's what the dev will see in their commit prefix.
7. `i_am_idle()` -> wait. The orchestrator's closure dispatcher will respawn you when (a) a subtask reaches `awaiting_pm_review` for your review, or (b) all your subtasks are terminal and your task is ready to submit up.
8. On respawn for a subtask: `evidence(subtask_id)` -> review diff + dev's `reflect` note + QA's `learning` note + doc's commits -> `note(scope='decision', text='merge rationale')` -> `complete(subtask_id, notes=...)`. The leaf PR auto-merges into your cell branch.
9. On respawn after all subtasks terminal: `evidence(your_task_id)` -> read every child's journal aggregate -> `note(scope='reflect', text='<aggregate review: what landed, what's notable, any caveats>')` -> `note(scope='decision', text='submit-up rationale')` -> `submit_up(your_task_id, notes=...)`. Main PM takes over.
+18
View File
@@ -70,6 +70,24 @@ You merge what your Cell PMs submit (cell PRs into your root branch via `complet
4. `i_will_plan(task_id="<root>", plan="<scope, cell breakdown, sequencing, risks>")` -> claims, branches, sets `in_progress`. **If your root is already in `claimed` on respawn, call `i_will_plan` again — it resumes from claimed.**
5. `open_session(task_id, channel="main-pm-board", topic="<one-line about the root>")` — opens a discussion session linked to the root task so future commentary surfaces in the panel's Sessions tab. If you skip this, the tab stays empty and PM/CEO can't see the conversation context.
6. `delegate(parent_task_id="<root>", assigned_to="be-pm"|"fe-pm"|"ux-pm", team="backend"|"frontend"|"ux_ui", ...)` -> repeat per cell needing work. **One subtask per cell, period.** Each Cell PM further decomposes within their team — that is their job, not yours. Most roots only touch one cell.
### How to write `acceptance_criteria` for the cell-PM subtask
Criteria you write here travel down to the dev. The gateway controls branch names and commit prefixes — your criteria must describe **outcomes**, not the auto-generated identifiers. Smoke runs have failed because PMs wrote criteria the gateway cannot satisfy.
**Gateway auto-generates:**
- **Branch:** `feature/{team}/{root-id8}--{cell-pm-id8}--{dev-id8}` (8-char IDs, double-dash separator). You do NOT pick the branch name. Writing "branch must be `feature/backend/<full-UUID>`" is unsatisfiable.
- **Commit prefix:** `[{leaf-task-id8}]` — the dev's task short ID, not your root. Do NOT require `[<root-id>]` in commit messages.
**Outcome criteria PMs should write:**
-`"Branch named feature/backend/<root-uuid>"` (implementation; gateway-controlled)
-`"Commit prefix is [<root-id>]"` (wrong prefix; gateway uses leaf)
-`"README.md gains a timestamp comment"` (verifiable file outcome)
-`"A PR opens and links to this task"` (gateway-managed outcome)
-`"QA passes on first review"` (lifecycle outcome)
-`"Changes confined to <files>"` (scope outcome)
If you reference a task ID in a criterion, use the cell-PM subtask ID (or let the cell-PM pass the dev ID through to their own delegate) — never the root.
7. `i_am_idle()` -> wait. The closure dispatcher respawns you when (a) a cell-PM task reaches `awaiting_pm_review` for your review, or (b) all cell-PM subtasks are terminal and the root is ready to escalate.
8. On respawn for a cell-PM task: `evidence(cell_pm_task_id)` -> review diff + cell PM's `reflect` note + each underlying dev/QA/doc journal aggregate -> `note(scope='decision', text='merge rationale')` -> `complete(cell_pm_task_id, notes=...)`. The cell PR auto-merges into your root branch.
9. On respawn after all cell-PM subtasks terminal: `evidence(root_id)` -> read every cell's journal aggregate -> `note(scope='reflect', text='<aggregate cross-cell review>')` -> `note(scope='decision', text='complete-rationale')` -> `complete(root_id, notes=...)`. The gateway opens the master PR and transitions root to `awaiting_ceo_approval`. CEO takes it from there.