Phase 2 — Sprint Scoping
Sequential per-project loop. For each active project, surface alternatives via brainstorming, run the adaptive interview from BC-5810 § 2 (5 carry-over Qs + 5 scope Qs), enforce the issue-quality-gate from § 3 with block-with-override, and append a project block to the weekly-planning checkpoint as decisions accumulate. No Linear mutations — those are deferred to Phase 3 (BC-5761).
This skill is inline (model inherits). Phase 2 is interactive Q&A — it cannot run as a dispatched subagent (per BC-5760 issue Notes).
Gate-respect
Every multi-option AskUserQuestion in this skill is bound by the gate-respect contract. Once the planner picks an option — at the enricher-dispatch-error prompt, any CQ/SQ prompt, or the quality-gate failure prompt — execute that exact option. If an internal code path wants to deviate (condense, skip, batch, fast-path under context pressure), re-prompt via a new AskUserQuestion instead of silently self-selecting a lighter variant. Writing to a dogfood-notes, checkpoint, or breadcrumb file is not permission to deviate. Origin: BC-5866 (W17 dogfood of this skill).
§ 1 Inputs (state object)
Reads from the session state object populated by Phases 0–1:
state.team.id— Brite Company UUID, set in Phase 0state.cycle.current— cycle being planned (W+1)state.cycle.previous— cycle being audited (W)state.projects[].audit_card— Phase 1 fan-out output (shipped,carry_over,dropped,quality_gate_flags,by_assignee)state.cross_project_stats— completion rate, shipped totals, standoutsstate.leadership_planning_notes— optional freeform file path the user may pre-load (skill reads if present, ignores if absent)
Populates / mutates:
state.projects[i]._enrichment = { backlog_candidates[], carry_over_enriched[], brainstorming_ranked[], enriched_at, dispatch_error }(produced per-project by the § 2 pre-loop enricher dispatch — BC-5902; authoritative shape lives incommands/weekly.md § Session State Object)state.projects[i].scope_decisions = {q1_headline, q2_ship_ids, q3_reassignments, q4_dependencies, q5_parked, carry_over_answers[], ritual}—ritual: trueset when § 2.3 ritual close-out row fires; SQ2–5 are skipped + logged inskip_logand the narrative renders a Ritual Cadence card variant instead of a Sprint Plans card.state.projects[i].overrides = [{issue_id, check, reason}]state.projects[i].skip_log = [string, ...](one line per skipped question with the audit-card reason)state.bottleneck_warnings = [{assignee, count, issues[]}](populated after the project loop)
§ 2 Per-project loop entry
No project-level triage gate. Do not surface any AskUserQuestion at Phase 2 entry that asks the user to narrow the project set before the interview begins. Every project in state.projects[] (already filtered to status.type == "started" by Phase 0.3) is interviewed. Adaptive-skip is per-question (§ 2.3), never per-project. A quiet prior cycle does NOT imply empty W+1 scope — backlog + Todo may still contain items to promote into the cycle.
Specifically banned improvisation patterns (origin: BC-5864 W17 dogfood):
- "Active projects only (N of M)" — auto-parks quiet-prior-cycle projects. A quiet prior cycle is not the same as empty W+1 scope.
- "Top N by ship count" — filters by ship volume. Ship volume ≠ scope volume.
- "All N, strict spec" presented as one of several options — legitimizes the other options by including them in the menu.
- "Abbreviated form" / "condensed form" / any form that reduces per-project question count as a function of project count.
Do not invent synonyms for the above. If the prompt count feels unsustainable (e.g. 130+ AskUserQuestion calls for 26 projects), that is the planner experience BC-5810 locked in — the right lever is a different spec decision (a new sub-cohort gate amended into BC-5810), not an improvised triage menu here.
Pre-loop (once per Phase 2 invocation):
- Resume parse. Read the current-week checkpoint file (path resolved per § 6) once. Parse every
### N. <project_name>heading and buildstate._scoped_project_names: Set<string>. This is the single source of truth for resume state — § 2 step 1 and § 8 both consult this set. (If the file does not exist, the set is empty.) - Enricher dispatch fan-out (BC-5902). Filter to projects not already scoped:
dispatch_set = [p for p in state.projects if p.status.type == "started" AND p.name ∉ state._scoped_project_names]— on resume, projects already in the set from the Resume-parse step above are skipped entirely (no wasted Sonnet dispatch for work the loop will skip anyway). In a singleAgenttool-call message, dispatchproject-enricheronce per project indispatch_set. Cap 10 concurrent dispatches (mirrors Phase 1 § 1.2 Dispatch percommands/weekly.md); batch sequentially in groups of 10 ifdispatch_set.length > 10. Prompt body per dispatch:project_id,project_name,audit_card(full Phase 1 output for this project),cycle.current,cycle.previous,team_id,cross_project_stats. Parse each returned JSON block intostate.projects[i]._enrichmentkeyed by project id. On any_enrichment.dispatch_error(non-null), halt the pre-loop and surfaceAskUserQuestionwith three options: Retry (re-dispatch only the failed projects with fresh Agent calls), Pause session (do NOT appendphase-2tocompleted_phases; leave state unchanged; write breadcrumbcurrent_phase = "phase-2"; exit cleanly), Proceed without enrichment for failed projects (explicit spec-departure: set_enrichment.backlog_candidates = []+_enrichment.carry_over_enriched = []+_enrichment.brainstorming_ranked = []for that project so downstream.find()/.lengthcalls return empty rather than throwing onundefined, and free-text-prompt the user for SQ2 IDs when that project's turn comes; log understate.projects[i].skip_log). NEVER silent degradation — this is the BC-5896 AC fail-loud contract.
For each state.projects[i] selected in Phase 0.3 (status.type == "started", deduped by id):
- Resume skip. If
state.projects[i].name ∈ state._scoped_project_names, setstate.projects[i].scope_confirmed = trueand continue to the next project. Log:Project <name> already scoped — skipping (resume).If this is the last project and it was already scoped, exit the loop cleanly. - Enrich carry-over — Read
state.projects[i]._enrichment.carry_over_enriched[]populated by the § 2 pre-loop enricher dispatch (this is a flat array of{id, blocker_count, auto_superseded_by, title, priority, assignee, issue_snapshot}, not a map). For each audit-card carry-over issue, look up its enrichment entry via find-by-id:const entry = _enrichment.carry_over_enriched.find(e => e.id === audit_card_issue.id)— if no match (enricher hit an individualget_issueerror for that issue, or Proceed-without-enrichment was chosen), log a one-line skip understate.projects[i].skip_log("carry-over enrichment missing for BC-XXXX — fell through to defaults") and skip hydration for that issue. Ifentryis present, hydrate the matchingaudit_card.carry_over.issues[i]with:enriched.blocker_count = entry.blocker_count,enriched.auto_superseded_by = entry.auto_superseded_by. Populate_fetched_issuesfrom snapshot (BC-5902): ifentry.issue_snapshotis present, write it tostate.projects[i]._fetched_issues[audit_card_issue.id]so Phase 3 § 3 pre-flight's reuse ladder step 1 hits the cache and skips the redundantget_issueper carry-over. No additional MCP reads in Phase 2 — the enricher already did the parallelget_issuefan-out withincludeRelations: true. Bounded cost — work is a dict merge plus N.find()lookups over the enrichment array (N = carry-over count per project, typically <10). - Run § 3 carry-over interview (skipped entirely if
carry_over.count == 0per BC-5810 § 2.3). - Run § 4 scope interview.
- Run § 5 quality gate on every issue ID in
q2_ship_ids(pre-fan-outget_issuefor any ID not already in_fetched_issues). - Run § 6 checkpoint append.
After all projects: § 7 cross-project bottleneck pass.
§ 3 Carry-over interview (5 questions per issue)
For every issue in state.projects[i].audit_card.carry_over.issues[] (not just the highest-priority one — BC-5897), ask the 5 questions from BC-5810 § 2.1 verbatim. Iteration order is carry_over.issues[] array order (Phase 1 audit sorts by priority already). No priority-filter / rank-filter on block entry — only question-level adaptive-skip from § 2.3 applies.
Each question is a separate AskUserQuestion tool call. No batching, condensing, or consolidation — ever. This applies regardless of carry-over count, project count, or context pressure. Specifically banned improvisation patterns (origin: BC-5865 W17 dogfood):
- "condensed-prompt" / "consolidated AskUserQuestion" / "pragmatic condensed pattern" — any phrasing that batches 2+ CQs into one call.
- "batched carry-over block" / "skip the strict interview for projects without carry-over" — any phrasing that groups CQs by issue or selectively batches across issues.
Adaptive-skip (§ 2.3) may drop a question entirely with a skip_log entry — it may never merge a question with another. Hard rule per memory/feedback_one_question_at_a_time.md. Skip rules from BC-5810 § 2.3 are evaluated before each AskUserQuestion call; skipped questions append a one-line entry to skip_log.
Every question carries: issue ID + title, one-line audit summary snippet (e.g. "BC-2690 — MI reply sync. In Progress W15. No PR. Holden. 0 blockers."), recommended default first with (Recommended) suffix, and "Other" as the free-text escape.
| Q-ID | Question | Recommended default | Skip condition |
|---|---|---|---|
| CQ1 | Move <id> to next cycle? |
Move to W+1 | (never skipped) |
| CQ2 | Assignee still correct (<current>)? |
Unchanged | (never skipped) |
| CQ3 | Superseded by a different chain? | Keep as-is (or prefilled with <auto_superseded_by> chain as (Recommended) if set) |
Never skipped. If enriched.auto_superseded_by is set, the chain is prefilled as the recommended default but the question is still asked for confirmation (per BC-5810 § 2.3). |
| CQ4 | Blockers still live? | Yes, keep declared blockers | enriched.blocker_count == 0 → skip + log "CQ4 skipped — 0 blockers per Linear relations" |
| CQ5 | If staying, which cycle/milestone lands it? | Next cycle | Skipped if CQ1 == "Park indefinitely" |
Answers are stored under state.projects[i].scope_decisions.carry_over_answers[] keyed by issue ID.
§ 4 Scope interview (5 questions per project)
Once per project after carry-over completes (or immediately if carry-over was skipped). If state.projects[i].status.type == "parked" (from the Linear project shape captured in Phase 0.3, not from the audit card), only SQ1 is asked (for acknowledgement) and SQ2–SQ5 are skipped + logged.
Scope candidate injection from enricher. Before SQ2, read state.projects[i]._enrichment.brainstorming_ranked[] populated by the § 2 pre-loop project-enricher dispatch. The top-ranked candidate (rank == 1) becomes SQ2's (Recommended) default in the AskUserQuestion call; alternatives at ranks 2–3 become options 2–3. No main-thread workflows:brainstorming Skill call — the enricher already ran the ranker logic with the same inputs (carry-over count, backlog-high count, shipped-pace, owner-load hint). If brainstorming_ranked is empty (e.g. enricher fell back to Proceed without enrichment), SQ2's default becomes "carry-over only — no backlog proposals" and the user escape-path "Other" carries free-text. (Closes BC-5867 — brainstorming ranker moves from spec-misfit inline Skill call to dispatched subagent output consumed as data — BC-5902.)
The 5 questions from BC-5810 § 2.2 verbatim. Each a separate AskUserQuestion call. No batching, condensing, or consolidation — ever. This applies regardless of carry-over status, project count, or context pressure. Specifically banned improvisation patterns (origin: BC-5865 W17 dogfood):
- "one consolidated scope AskUserQuestion per project" — exactly what the agent improvised during W17 for the 16 no-carry-over projects. Do not do this.
- "pragmatic condensed pattern" / "condensed-prompt" / "consolidated" / "batched scope questions" — any phrasing that collapses 2+ SQs into one call.
SQ1's answer constrains SQ2's option set (SQ1's headline drives SQ2's viable issue IDs); asking them simultaneously breaks the decision tree. If the condensed form ever feels justified, file a spec amendment to BC-5810 — do not improvise here.
No-signal SQ1 fallback. When state.projects[i]._enrichment.carry_over_enriched.length == 0 AND state.projects[i]._enrichment.backlog_candidates is empty (or every entry has priority.value >= 3 Medium/Low), SQ1's (Recommended) default switches from an agent-drafted headline to "Owner picks next track — free-text (Recommended)" — the agent does NOT invent a fake default. SQ1 is still asked (no skip_log entry — this is a default-switch, not a skip); the user's free-text answer becomes the headline verbatim. SQ2–SQ5 still ask normally with the brainstorming_ranked empty fallback (see paragraph above) handling SQ2. (Closes BC-5900 — codifies the W17 attempt-2 honest-abstention path as spec-compliant per docs/designs/cadence-orchestration.md § 2.3 no-signal row, rather than rendering a "spec departure noted" annotation.)
Ritual close-out fallback. When state.projects[i].audit_card.shipped.count >= 3 AND state.projects[i].audit_card.carry_over.count == 0 AND state.projects[i].audit_card.dropped.count == 0 AND len(set(state.projects[i].audit_card.shipped.issues[*].assignee)) == 1 AND state.projects[i].audit_card.shipped.issues[0].assignee != "(unassigned)" AND state.projects[i]._enrichment.dispatch_error == null AND state.projects[i]._enrichment.backlog_candidates is empty (or every entry has priority.value >= 3 Medium/Low), SQ1's (Recommended) default switches from an agent-drafted headline to "Defer to offline touch-base with owner (Recommended)" with the 3-option lock from § 4.2 below. SQ1 is still asked (no skip_log entry — this is a default-switch, not a skip). SQ2–SQ5 are SKIPPED for this project and logged: state.projects[i].skip_log gets one entry per skipped question with reason "ritual close-out — single owner consistent shipping, no signal for new scope", and state.projects[i].scope_decisions.ritual = true is set so Phase 4's narrative-writer renders the project as a Ritual Cadence card rather than a Sprint Plans card. (Closes BC-5901 — codifies the W17 attempt-2 skill-invented ritual-project degradation across Meeting Auto / Brite Training / Partnership Management / Comm Infra as spec-compliant per docs/designs/cadence-orchestration.md § 2.3 ritual close-out row, rather than rendering a "spec departure noted" annotation.)
Ritual vs no-signal precedence. Both the BC-5900 no-signal SQ1 fallback (line 108 above) and this BC-5901 ritual close-out fallback can co-fire on the same project — when audit shows zero carry-over AND backlog is empty/Medium-Low, both predicates are true. The ritual rule takes precedence over no-signal: single-owner consistent shipping (3+ shipped, zero dropped, zero enricher error) is a stronger signal than empty-backlog alone, and the ritual path skips SQ2–5 while no-signal still asks them — running both yields contradictory behavior. Evaluation order: check ritual conjuncts first; only if any conjunct fails fall through to the no-signal check.
| Q-ID | Question | Recommended default |
|---|---|---|
| SQ1 | Headline outcome sentence for <project>? |
Agent draft from top-priority carry-over + top backlog (or free-text "Owner picks next track" if both empty — see no-signal fallback above; or 3-option lock when ritual close-out fires — see § 4.2 below) |
| SQ2 | Which issue IDs ship this cycle? | Brainstorming output (top-ranked candidates; quality-gate filtering runs in § 5 on the user's picks, not here) |
| SQ3 | Owner per issue, if different from existing? | Keep existing assignees |
| SQ4 | Dependencies between picked issues? | Agent infers from descriptions + relations.blockedBy |
| SQ5 | Explicitly parked this cycle? | Agent proposes from stale current-cycle items + Low-priority carry-over |
§ 4.1 SQ3 option lock
Origin class: schema-collision. Linear has one assignee field per issue (BC-5872); improvising "co-ownership" (banned — see anti-pattern list below) drops or replaces real data. Future locks of this class also have a concrete data-corruption risk.
SQ3's AskUserQuestion MUST render exactly three options (plus the implicit "Other" free-text escape):
- Keep existing assignees
(Recommended) - Reassign to
<name>— single-assignee change; one target name - Mark unassigned — clears
assigneetonull
Linear has exactly one assignee field per issue. SQ3 maps 1:1 to that field. Specifically banned improvisation patterns (origin: BC-5872 W17 attempt1 dogfood):
- "Add co-owner" / "co-owner on " — no such field in Linear; if picked, Phase 3 silently drops the second assignee or silently replaces the first.
- "co-watcher" / "Add subscriber as co-owner" —
subscribersis a watchers list, not an owners list. Reframing ownership as watching persists a different semantic mismatch. - "multi-assignee" / "multiple assignees" / "Holden + Rainer both on BC-XXXX" — any phrasing that implies a list-valued assignee.
If co-ownership becomes a legitimate weekly pattern, file a spec amendment to BC-5810 § 2.2 — do not improvise here. The escape path for one-off co-lead intent is the Phase 5 manual-ops checklist (the planner writes a freeform row after the run); SQ3 itself stays locked to the three options above.
§ 4.2 SQ1 ritual option lock
Origin class: workflow-clarity. Three downstream narrative renders (Ritual Cadence card / Parked This Week table / Sprint Plans card) need three distinct option signals to disambiguate intent (BC-5901). Future locks of this class trade option-set tightness for render-side disambiguation rather than schema-collision protection.
When the § 2.3 ritual close-out row fires (see "Ritual close-out fallback" prose above), SQ1's AskUserQuestion MUST render exactly three options (plus the implicit "Other" free-text escape):
- Defer to offline touch-base with owner
(Recommended)— setsq1_headline = "Continue cadence — owner picks next track offline"and proceeds to skip SQ2–5 (logged inskip_logper the ritual fallback prose).scope_decisions.ritualstaystrue→ Ritual Cadence card. - Park this cycle — sets
scope_decisions.q5_parked = "<project> — parked this cycle, owner unavailable"and routes to Parked This Week instead of Ritual Cadence in Phase 4.scope_decisions.ritualstaystrue(audit-trail preservation: the ritual signal that fired is recorded; narrative-writer routes via theq5_parkedoverride per its precedence rules). - Specify scope instead — overrides the ritual flag (
scope_decisions.ritual = false), unlocks SQ1 free-text, and runs SQ2–5 normally → Sprint Plans card. Use when the audit signal is correct but the planner has unsurfaced backlog or a deliberate stretch goal.
Specifically banned improvisation patterns (origin: BC-5901 W17 attempt-2 dogfood across 4 ritual-pattern projects):
- "redundant free-text Option N + Other Option N+1 pattern" — exposing a fake "Option 4: free-text" that duplicates the implicit Other escape. Lock the option set to three; planner uses Other to deviate.
- "merge SQ1 and SQ5 into a defer-and-park combo option" — keep park-this-cycle and specify-instead distinct from defer-offline; they map to different downstream renders (Ritual Cadence card vs Parked This Week table vs Sprint Plans card).
§ 5 Quality gate + block-with-override
For every ID in q2_ship_ids (from SQ2), invoke the cadence:issue-quality-gate shared skill via the Skill tool with the issue object (fetched via get_issue if not already enriched). The gate returns 7 {check, status, message} tuples. On any status == "fail":
- Surface the failure to the user — show issue ID, title, the failing check name, and the message.
AskUserQuestionwith 3 options:- Fix the issue now — echo the Linear URL (
https://linear.app/brite-nites/issue/<id>); wait for the user to fix + confirm; re-run the gate; on pass, the issue stays inq2_ship_ids. - Override this check with a reason (Recommended only when the user explicitly opts in) — collect a one-line free-text reason; append
{issue_id, check, reason}tostate.projects[i].overrides. The reason will surface in Phase 4's narrative> **Known gaps this cycle**callout (BC-5762). - Drop from scope — remove the ID from
q2_ship_ids; prompt for a replacement candidate from the brainstorming list.
- Fix the issue now — echo the Linear URL (
No global "skip all gates" escape exists. Per-check override with a reason is the only path. Re-run the gate on any issue the user re-adds.
§ 6 Checkpoint append (per project, after § 5 passes)
Resolve the checkpoint path once at Phase 2 entry and cache under state.checkpoint_path. Both § 6 and § 8 read that cached value — no git rev-parse calls inside the per-project loop.
Resolution algorithm (pseudocode — the skill pre-extracts the numeric and date components from state.cycle.current before calling bash, since cycle.current.name is the cycle title string like "W17" and startsAt is an ISO timestamp):
# Pre-extracted by the skill from state:
# CYCLE_NN = numeric week from state.cycle.current.name (e.g. "W17" → 17)
# CYCLE_DATE = state.cycle.current.startsAt formatted YYYY-MM-DD
# Then in Bash:
WEEK_NN=$(printf "%02d" "$CYCLE_NN")
ROOT=$(git rev-parse --show-toplevel)
CHECKPOINT="$ROOT/../weekly-planning/w${WEEK_NN}-${CYCLE_DATE}/w${WEEK_NN}-planning-checkpoint.md"
Reject CYCLE_DATE if it does not match ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ — fail the phase with a clear error rather than writing a malformed path.
If state.weekly_planning_root is set in the state object, use that as the prefix instead of $ROOT/... Mirrors Phase 1's audit.json resolution (BC-5759 § 1.1).
Append a project block to the file. Atomic — write only after § 5 completes for this project so partial failure leaves the file in a recoverable state.
### N. <Project Name>
**Owner:** <primary assignee or team>
**Headline:** <SQ1 answer>
<freeform body rendered from the scope-Q answers>
- Carry-over summary (one line per issue with the CQ1–CQ5 outcome)
- Ship this cycle (SQ2 IDs grouped by phase or owner per the project's voice)
- Owner reassignments (SQ3)
- Dependencies (SQ4 — list explicit edges or "all parallel")
- Stretch / parked (SQ5 + carry-overs sent past W+1)
- Risks (auto-surface from any `overrides` entries on this project + bottleneck flags from § 7 if pre-computed)
Minimum required headers per AC: ### N. <name>, **Owner:**, **Headline:**. Everything else freeform per W16 ground-truth (weekly-planning/w16-2026-04-13/w16-planning-checkpoint.md) — voice matches docs/designs/cadence-plugin.md § 1.
Ritual close-out checkpoint render (BC-5901). When scope_decisions.ritual == true (the SQ1 § 4.2 lock fired), append a **Ritual close-out:** true line immediately after **Headline:** and skip the per-section bullet list (Carry-over, Ship this cycle, etc.) — render the freeform body as a single one-liner: Ritual cadence — owner picks next track offline. (or the SQ1 free-text answer when the planner picked Other). Required so § 0.5.4 Resume parse can rehydrate scope_decisions.ritual from disk (the parser keys on the **Ritual close-out:** line); without it, a resumed Phase 4 silently demotes ritual-flagged projects back to Sprint Plans cards.
Note: BC-5760 issue AC #6 references literal sub-sections (Ship this week, Stretch, Parked, Risks). The W16 ground truth uses freeform headers per project (e.g. "Devops unblock", "OutboundSync pipeline", "BDR pipeline cleanup"); the plan resolved this in favour of voice-fidelity. Document the departure in the PR description.
§ 7 Cross-project bottleneck detection
Unconditional emit (BC-5899). Always emit the § 7 summary at Phase 2 exit — even when bottleneck_warnings == []. The checkpoint always gets a ## Cross-project flags section; the empty case renders _None this cycle._. Satisfies BC-5760 AC #7 regardless of whether any owner exceeds the threshold, so the planner sees the check ran and reads the result.
After the per-project loop completes, scan every project's scope_decisions.q2_ship_ids and q3_reassignments. Group by primary assignee. Emit a warning under state.bottleneck_warnings[] for any owner with > N primary assignments (default N == 4; configurable via state.bottleneck_threshold). Each warning is {assignee, count, issues: [ids]}.
Append a ## Cross-project flags section to the checkpoint file with one bullet per warning:
## Cross-project flags
- **<assignee>** is primary on <count> issues this cycle: BC-X, BC-Y, BC-Z, ... — review for bottleneck risk.
If bottleneck_warnings == [], append a single line: ## Cross-project flags\n\n_None this cycle._
§ 8 Idempotency + resume
- Resume pass is owned by § 2's pre-loop Resume parse step, which populates
state._scoped_project_namesonce per invocation. § 2 step 1 is an O(1) set-membership check against that cache. Log at the end of the pre-loop parse:Resume: <|_scoped_project_names|> project(s) already scoped from prior session. - Atomic append per project — the block is written only after § 5 completes. Partial failure (e.g. user
Cancelmid-interview, MCP timeout, kernel SIGINT) leaves the checkpoint in a recoverable spot and the next invocation continues from the next unconfirmed project. - Cancel mid-interview: if the user picks "Cancel" inside any
AskUserQuestion, do not append to the checkpoint, do not mutate state for the in-flight project. Exit cleanly withPhase 2 paused at <project_name>. Re-run /cadence:weekly to resume. - Cycle change detection: if a checkpoint file already exists at
state.checkpoint_pathAND its filename'sw<NN>segment does not match the cycle number derived fromstate.cycle.current.name, refuse to append and stop with an error pointing the user at/cadence:weekly --resume-phase 2after they confirm the cycle. Guards against a stalestate.weekly_planning_rootoverride pointing at a prior cycle's folder.
§ 9 References
docs/designs/cadence-orchestration.md§ 2 (interview), § 3 (gate) — BC-5810 authoritative specdocs/designs/cadence-plugin.md§ 1 — voice spec (BC-5757)weekly-planning/w16-2026-04-13/w16-planning-checkpoint.md— ground-truth checkpoint formatplugins/cadence/skills/_shared/issue-quality-gate/SKILL.md— quality gate primitive (BC-5810 § 3)plugins/cadence/agents/project-audit.md— audit_card producer (BC-5759)plugins/cadence/agents/project-enricher.md— enricher agent this skill dispatches (BC-5902)plugins/cadence/commands/weekly.md§ Phase 2 — entry command pointermemory/feedback_one_question_at_a_time.md— hard rule enforcementmemory/feedback_thorough_audits.md— per-item rigor (no batching across projects)memory/feedback_more_checkins_for_infra_issues.md— each project confirmation is one check-in gatememory/gotcha_linear_markdown_mangling.md— applies if Phase 3 ever writes scope decisions back to Linear
Deferred to follow-up issues
- Prior-narrative parser for
state.cycle.previous's sprint narrative — needed to computecross_project_stats.unplanned_ratioand per-assignee planned attribution. Filed as BC-5821 in the Cadence Plugin milestone. Out of scope for BC-5760 to keep the skill atomic. - Configurable
state.bottleneck_thresholdbeyond the defaultN == 4— currently hard-coded; surface as--bottleneck-thresholdflag on/cadence:weeklyif user demand emerges. - Seeded synthetic-25-project fixture test — deferred to follow-up. BC-5874 third dogfood is the end-to-end verification for the BC-5902 hybrid-dispatch fix. If dogfood surfaces gaps, file a separate issue for a synthetic fixture.