This skill should be used when transforming feature descriptions into well-structured project plans following conventions.
Installation
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt.Auf GitHub ansehen
name
plan
description
This skill should be used when transforming feature descriptions into well-structured project plans following conventions.
Anti-bypass protocol (load-bearing — especially Grok Build)
You are the planning orchestrator. Whether entered from /brainstorm, /one-shot Step 1, or direct /plan:
FORBIDDEN: Implementing product code (Write/Edit/Shell) before the plan artifact and tasks are written.
FORBIDDEN: Ending after saving plans/ + tasks.md without invoking /work — the plan is a checkpoint, not a deliverable.
REQUIRED (Grok Build): Invoke /work <plan-path> (or /deepen-plan when the plan requests it) via slash command — never substitute ad-hoc implementation.
See plugins/soleur/lib/workflow-fidelity.ts (HANDOFF_SKILLS, mandatorySuccessors('plan')).
Create a plan for a new feature or bug fix
Introduction
Note: The current year is 2026. Use this when dating plans and searching for recent documentation.
Transform feature descriptions, bug reports, or improvement ideas into well-structured markdown files issues that follow project conventions and best practices. This command provides flexible detail levels to match your needs.
If the feature description above is empty, ask the user: "What would you like to plan? Please describe the feature, bug fix, or improvement you have in mind."
Do not proceed until you have a clear feature description from the user.
Branch safety check (defense-in-depth): Run git branch --show-current. If the result is main or master, abort immediately with: "Error: plan cannot run on main/master. Checkout a feature branch first." This check fires in all modes as defense-in-depth alongside PreToolUse hooks -- it fires even if hooks are unavailable (e.g., in CI).
Check for knowledge-base directory and load context:
Check if knowledge-base/ directory exists. If it does:
Run git branch --show-current to get the current branch name
If the branch starts with feat-, read knowledge-base/project/specs/<branch-name>/spec.md if it exists
If knowledge-base/ exists:
Read CLAUDE.md if it exists - apply project conventions during planning
If # Project Constitution heading is NOT already in context, read knowledge-base/project/constitution.md - use principles to guide planning decisions. Skip if already loaded (e.g., from a preceding /soleur:brainstorm).
Detect feature from current branch (feat-<name> pattern)
Read knowledge-base/project/specs/feat-<name>/spec.md if it exists - use as planning input
Announce: "Loaded constitution and spec for feat-<name>"
If knowledge-base/ does NOT exist:
Continue with standard planning flow
0.5. Idea Refinement
Check for brainstorm output first:
Before asking questions, look for recent brainstorm documents in knowledge-base/project/brainstorms/ that match this feature:
ls -la knowledge-base/project/brainstorms/*.md 2>/dev/null | head -10
Relevance criteria: A brainstorm is relevant if:
The topic (from filename or YAML frontmatter) semantically matches the feature description
Created within the last 14 days
If multiple candidates match, use the most recent one
If a relevant brainstorm exists:
Read the brainstorm document
Announce: "Found brainstorm from [date]: [topic]. Using as context for planning."
Extract key decisions, chosen approach, and open questions
Skip the idea refinement questions below - the brainstorm already answered WHAT to build
Proceed to Phase 1 -- all sub-phases still apply (1, 1.5, 1.5b, 1.6). Having a brainstorm skips idea refinement only, not community discovery or research.
If multiple brainstorms could match:
Use AskUserQuestion tool to ask which brainstorm to use, or whether to proceed without one.
If no brainstorm found (or not relevant), run idea refinement:
Refine the idea through collaborative dialogue using the AskUserQuestion tool:
Ask questions one at a time to understand the idea fully
Prefer multiple choice questions when natural options exist
Focus on understanding: purpose, constraints and success criteria
Directional ambiguity gate: If the task involves merging, moving, or restructuring (A into B vs B into A), explicitly confirm the direction with the user before proceeding -- even in pipeline mode. Code evidence can be wrong (see learning: 2026-03-17-planning-direction-confirmation-required)
Continue until the idea is clear OR user says "proceed"
Gather signals for research decision. During refinement, note:
User's familiarity: Do they know the codebase patterns? Are they pointing to examples?
User's intent: Speed vs thoroughness? Exploration vs execution?
Topic risk: Security, payments, external APIs warrant more caution
Uncertainty level: Is the approach clear or open-ended?
Skip option: If the feature description is already detailed, offer:
"Your description is clear. Should I proceed with research, or would you like to refine it further?"
0.6. Pre-Research Premise Validation (Always)
Run BEFORE spawning any research (Phase 1) — research and downstream phases are expensive, and building a plan atop a stale premise wastes all of it. brainstorm Phase 1.1 does this validation when a brainstorm precedes plan, but plan is frequently entered directly (including the one-shot → plan path that skips brainstorm), so the cheap probe must also live here. This is distinct from Phase 1.7 reconciliation (which checks spec claims AFTER research returns) — this gate fires before research is even dispatched.
This also covers your own option-bounding capability claims — not just cited references. Before asserting that a repo tool/skill/script "only does X" or "can't do Y" to bound the plan's options, grep/read it first or phrase it as a question (hr-verify-repo-capability-claim-before-assert).
For every issue, blocker, dependency, or prior-art artifact the feature description cites by reference, verify it still holds:
Cited GitHub issues / PRs (#N, Closes #N, "blocked by #N", "follow-up to #N"): run gh issue view <N> --json state,title,closedByPullRequestsReferences and gh pr view <N> --json state,merged where applicable. If a blocker is already closed/merged, or the issue this plan targets is already closed by a merged PR, the premise is stale — surface via AskUserQuestion ("Issue #N appears already resolved by PR #M. Re-scope, or close as done?") rather than planning against it.
Cited file/symbol/migration paths (a function, route, component, or migration the plan assumes exists): confirm with git show origin/main:<path> or git grep -n "<symbol>" origin/main. If the cited artifact does not exist on origin/main, the premise ("fix the bug in X") may really be "X was never built" — flag it; the plan's shape changes from fix to build.
"UI exists but is broken" claims: distinguish broken behavior from never-built. If the description asserts a UI/endpoint misbehaves, confirm the route/component is actually present (git grep) before planning a behavioral fix — a silently-absent feature needs a build plan, not a patch.
Proposed mechanism vs. the ADR corpus (the feature names HOW to do it — a frontmatter flip, a new table, a polling cron, a config tier): grep knowledge-base/engineering/architecture/decisions/ for the mechanism's keywords (not the cited issue number — issues don't know what an ADR decided) and read any hit's ## Decision + ## Alternatives Considered. A mechanism sitting in an ADR's rejected-alternatives table is not an unconsidered idea — it is an explicitly-rejected one; re-scope to "did the ADR leave a gap this still addresses?" rather than planning the rejected approach. Corollary: when the feature pins an absolute value (a fixed model/tier/limit), check its interaction with the most capable end of the range, not just the cheap end (an absolute opus reviewer pin is a downgrade on a Fable session). Why: #5087 — the issue's frontmatter-tiering approach matched the exact alternative ADR-053 rejected the day before (#5096); caught only at deepen-plan, three phases deep. See knowledge-base/project/learnings/2026-06-11-brainstorm-grep-adr-corpus-for-proposed-mechanism-not-just-issue-refs.md.
Emit a one-paragraph Premise Validation note (what was checked, what held, what was stale) into the research-insights scratch so Phase 1.7 and the plan's "Research Reconciliation" section can carry it forward. If nothing is cited by reference, state "no external premises to validate" and proceed.
Main Tasks
1. Local Research (Always Runs - Parallel)
First, I need to understand the project's conventions, existing patterns, and any documented learnings. This is fast and local - it informs whether external research is needed.
Run these agents in parallel to gather local context:
If the feature description matches any of the patterns SSH, connection reset, kex, firewall, unreachable, timeout, 502, 503, 504, handshake, EHOSTUNREACH, ECONNRESET (case-insensitive substring match on the feature description), read plan-network-outage-checklist.md and require its output in the ## Hypotheses section of the final plan.
Also fire this gate when the feature description names terraform apply (with or without -target=) against a resource whose definition contains provisioner "file", provisioner "remote-exec", or a connection { type = "ssh" ... } block. The provisioner block makes SSH a hard apply-time dependency that the prose-only keyword scan won't detect. Why: #3061 — apply on terraform_data.deploy_pipeline_fix hit ssh: handshake failed: connection reset by peer despite zero SSH keywords in the plan, because the firewall allowlist had drifted out from under the operator's egress IP.
The checklist enforces an L3->L7 diagnostic order: firewall allow-list and DNS/routing MUST be verified before sshd/fail2ban/service-layer hypotheses. Per AGENTS.md hr-ssh-diagnosis-verify-firewall, this is a hard rule -- plans that propose sshd or fail2ban fixes without first verifying firewall + egress IP are workflow violations.
When a trigger pattern matches, emit rule-application telemetry so the weekly aggregator records this gate fired (see AGENTS.md hr-ssh-diagnosis-verify-firewall):
source"$(git rev-parse --show-toplevel)/.claude/hooks/lib/incidents.sh" && \
emit_incident hr-ssh-diagnosis-verify-firewall applied \
"When a plan addresses an SSH/network-connectivity s"
This step is a single file read, not a subagent spawn. If the feature description does not match any trigger pattern, skip this step silently.
1.5. Community Discovery Check (Conditional)
Read plugins/soleur/skills/plan/references/plan-community-discovery.md now for the full community discovery procedure (stack detection, coverage gap check, agent-finder). Skip if no uncovered stacks detected.
1.5b. Functional Overlap Check
Read plugins/soleur/skills/plan/references/plan-functional-overlap.md now for the functional overlap check procedure (always runs, spawns functional-discovery agent).
1.6. Research Decision
Based on signals from Step 0 and findings from Step 1, decide on external research.
High-risk topics → always research. Security, payments, external APIs, data privacy. The cost of missing something is too high. This takes precedence over speed signals.
Strong local context → skip external research. Codebase has good patterns, CLAUDE.md has guidance, user knows what they want. External research adds little value.
Uncertainty or unfamiliar territory → research. User is exploring, codebase has no examples, new technology. External perspective is valuable.
Announce the decision and proceed. Brief explanation, then continue. User can redirect if needed.
Examples:
"Your codebase has solid patterns for this. Proceeding without external research."
"This involves payment processing, so I'll research current best practices first."
1.6b. External Research (Conditional)
Only run if Step 1.6 indicates external research is valuable.
After all research steps complete, consolidate findings:
Document relevant file paths from repo research (e.g., app/services/example_service.rb:42)
Include relevant institutional learnings from knowledge-base/project/learnings/ (key insights, gotchas to avoid)
Note external documentation URLs and best practices (if external research was done)
List related issues or PRs discovered
Capture CLAUDE.md conventions
Reconcile spec claims against codebase reality. If the repo-research-analyst returned any "Gap callouts" or equivalent mismatches, the plan MUST include a "Research Reconciliation — Spec vs. Codebase" section (3-column table: spec claim / reality / plan response) placed between "Overview" and "Implementation Phases". This prevents the plan from inheriting spec fiction (e.g., claimed infrastructure that doesn't exist) as phase estimates. See knowledge-base/project/learnings/best-practices/2026-04-15-plan-skill-reconcile-spec-vs-codebase.md.
Optional validation: Briefly summarize findings and ask if anything looks off or missing before proceeding to planning.
1.7.5. Code-Review Overlap Check
After the plan draft has enumerated its ## Files to Edit and ## Files to Create sections (i.e., run this check AFTER Step 2 Issue Planning produces the file list, and BEFORE Step 4 Detail Level selection), verify whether any open code-review issues touch files the plan intends to modify. This prevents two failure modes:
Rework: a pre-existing scope-out names a file the plan will rewrite — if unnoticed, the plan ships, then the scope-out surfaces and drives a second refactor PR that could have been folded in.
Double-counting: the review phase files a new scope-out for a concern a still-open issue already tracks.
Procedure:
Read the plan's ## Files to Edit and ## Files to Create sections (the plan draft exists by this point). Extract every file path. If the plan is still being drafted and those sections are not yet written, defer this check until they exist rather than guessing from the feature description — guessing produces false negatives.
Query open code-review issues. Use two-stage piping (--json then a standalone jq --arg), not single-stage gh --jq with --arg. The gh CLI does NOT forward --arg to its embedded jq; a single-stage form produces unknown arguments at runtime. See learning knowledge-base/project/learnings/2026-04-15-gh-jq-does-not-forward-arg-to-jq.md.
ISSUES_JSON=$(mktemp -t open-review-issues.XXXXXXXX.json)
gh issue list --label code-review --state open \
--json number,title,body --limit 200 > "$ISSUES_JSON"echo"ISSUES_JSON=$ISSUES_JSON"
For each planned file path, search the issue bodies using standalone jq with --arg (safe against regex metacharacters in paths):
A later Bash call does not inherit ISSUES_JSON, so carry the echoed path forward (or
re-derive it in the same call). Do not substitute a fixed name: a concurrent /plan
would overwrite the file between the write and this read.
If any matches are returned, write a ## Open Code-Review Overlap section to the plan file with a one-line bullet per match and an explicit disposition for each:
X open scope-outs touch these files: #2466 (Range cache), #2483 (helper extraction). Fold in / acknowledge / defer: …
For each match, the planner MUST explicitly choose one of:
Fold in: plan extends to close the scope-out in the same PR. Add the scope-out's file paths to ## Files to edit and note Closes #<N> in the PR-body reminder.
Acknowledge: plan deliberately does NOT fix the scope-out (e.g., different concern, needs its own cycle). Record a 1-sentence rationale. The scope-out remains open.
Defer: plan is not the right place; update the scope-out issue with a re-evaluation note (e.g., "revisit after feat-X lands"). Do NOT silently leave the overlap unaddressed — the reviewer will re-surface it.
If no matches, still record ## Open Code-Review Overlap with None so the next planner can see the check ran.
Why this matters: In the 2026-04-17 window, PR #2486 closed three scope-outs (#2467 + #2468 + #2469) because the planner noticed the overlap. PRs #2463 and #2477 grew the backlog instead because no overlap check ran. This phase makes the #2486 pattern the default, not the exception. See knowledge-base/project/learnings/best-practices/2026-04-17-review-backlog-net-positive-filing.md.
Step 2 re-check. Once ## Files to Edit is finalized in Step 2 (Issue Planning), re-run the one-liner if any candidate description: edit landed in the file list — including candidates the planner introduced in Step 2 that Phase 1 did not surface. The check fires on the final list, not the Phase 1 candidate set.
Headroom failure action. If either check reports < 10 words remaining against the 1800-word cumulative cap (enforced by plugins/soleur/test/components.test.ts), include exact sibling-trim text (before/after) in ## Files to Edit before proceeding. Skip silently if no SKILL.md description: edit is ever candidate or finalized.
2. Issue Planning & Structure
Think like a product manager - what would make this issue clear and actionable? Consider multiple perspectives
Title & Categorization:
Draft clear, searchable issue title using conventional format (e.g., feat: Add user authentication, fix: Cart total calculation)
Determine issue type: enhancement, bug, refactor
Convert title to filename: add today's date prefix, strip prefix colon, kebab-case, add -plan suffix
Example: feat: Add User Authentication → 2026-01-21-feat-add-user-authentication-plan.md
Keep it descriptive (3-5 words after prefix) so plans are findable by context
Stakeholder Analysis:
Identify who will be affected by this issue (end users, developers, operations)
Consider implementation complexity and required expertise
Content Planning:
Choose appropriate detail level based on issue complexity and audience
List all necessary sections for the chosen template
Prepare code examples or reproduction steps if applicable, name the mock filenames in the lists
When planning a directory rename, enumerate ALL files in the target directory as potential self-reference holders -- directory trees and conceptual prose derived from the directory name don't match path-pattern greps
When the rename plan also sweeps every reference to the old path, exclude the feature's OWN planning artifacts (plans/<this-plan>.md, specs/feat-<branch>/tasks.md, specs/feat-<branch>/session-state.md) from BOTH the sweep file-list AND the residual-zero AC, exactly like **/archive/** -- they are point-in-time migration records that must cite the old path. A residual-zero AC and a "plan retains old path" AC are mutually contradictory unless the carve-out covers all three artifacts, not just the plan file. See learning 2026-06-03-path-rename-sweep-exclude-own-migration-artifacts.md.
When the plan prescribes scoping a helper function by a new column/predicate, rg the codebase for every other inline query on the same table that BYPASSES the helper (id-based lookups, pre-helper historical queries, WS-handler inline SELECTs) and list each as a Files to Edit entry -- sibling queries are the most common silent backdoor after a tenant-scope change. See learning 2026-04-22-scope-by-new-column-audit-every-query-not-just-the-helper.md.
When the plan prescribes any path glob (e.g., apps/foo/**, **/doppler*.{yml,yaml,sh}, .github/workflows/*foo*.yml), verify each glob matches ≥1 real file via git ls-files | grep -E '<translated-glob>' AND for negative-coverage gates (security gates, denylist filters, sensitive-path detectors) enumerate sibling files at the same architectural depth — globs constructed from a plan miss files the plan never inventoried. See AGENTS.md hr-when-a-plan-specifies-relative-paths-e-g and learning 2026-04-28-plan-globs-must-be-verified-against-repo-structure.md.
Wrapper-vs-curl check before adopting a workflow wrapper. Before prescribing claude-code-action, peter-evans/create-pull-request, or any wrapper that constrains workflow architecture (token-revoking post-steps, hardcoded auto-merge, mandated job ordering), ask: "what does this look like as 5 lines of curl + jq?" If the answer is "fine," skip the wrapper. The wrapper's value is in agent tool-use loops or PR-creation generality; a single-shot LLM call or single-PR workflow doesn't need it. Why: 2026-05-11 #2720 v1 plan adopted claude-code-action and contorted into a two-job split + matrix to dodge its post-step token revocation; v2 dropped the wrapper and 4 P0 issues dissolved. See knowledge-base/project/learnings/2026-05-11-five-agent-plan-review-panel-and-architectural-false-trails.md.
Paper-resolution lint. Every FR/AC added to fold a review finding MUST cite the implementation location — e.g., <script-file>:<line>, <workflow-file>:<section>, or prompt:step-N. Without the pointer, the FR is paper — the planner could not encode the fix in code, only in prose, and the implementer will discover the gap at /work time. Why: 2026-05-11 #2720 v1 plan folded 6 spec-flow P0s as FRs/ACs; spec-flow re-validation against the plan caught 4 as "RESOLVED in spec, NOT IMPLEMENTED in code." Same learning file.
2.5. Domain Review Gate
After generating the plan structure, assess which business domains this plan has implications for. This gate enforces constitution line 122: plans must receive cross-domain review before implementation.
Step 1 — Domain Sweep:
Brainstorm carry-forward check: If the brainstorm document (loaded in Phase 0.5) contains a ## Domain Assessments section, carry forward the findings. Extract relevant domains and their summaries. Skip fresh assessment.
Fresh assessment (if no brainstorm or no ## Domain Assessments section): Read plugins/soleur/skills/brainstorm/references/brainstorm-domain-config.md. Assess all 8 domains against the plan content in a single LLM pass using each domain's Assessment Question. Use semantic assessment — not keyword matching.
Spawn domain leaders: For each domain assessed as relevant except Product (handled in Step 2), spawn the domain leader as a blocking Task using the Task Prompt from brainstorm-domain-config.md, substituting {desc} with the plan summary. Spawn in parallel if multiple are relevant.
Collect findings: Wait for all domain leader Tasks to complete. Each returns a brief structured assessment. If a domain leader Task fails (timeout, error), write partial findings for that domain with Status: error and continue with remaining domains.
After domain sweep, scan the brainstorm document's ## Domain Assessments section (and any ## Capability Gaps section) for domain leaders that recommended specific specialists by name (e.g., "delegates to conversion-optimizer", "recommends copywriter for cancellation copy", "invoke ux-design-lead for wireframes"). Build a REQUIRED_SPECIALISTS list from these recommendations.
For each specialist in REQUIRED_SPECIALISTS:
If the specialist will be invoked by the Product/UX Gate pipeline below (ux-design-lead, copywriter, spec-flow-analyzer), mark it as "covered by UX Gate" — it will run in Step 2.
If the specialist is NOT covered by the UX Gate pipeline (e.g., conversion-optimizer, retention-strategist, pricing-strategist), invoke it as a Task now with a scoped prompt derived from the recommendation context. Spawn in parallel if multiple.
Record all brainstorm-recommended specialists in the Domain Review section under **Brainstorm-recommended specialists:**.
Enforcement: Specialists recommended by name in brainstorm domain assessments MUST be either invoked or explicitly declined by the user via AskUserQuestion ("Domain leader recommended [specialist] for [reason]. Run now / Skip with acknowledgment"). Silent skipping is a workflow violation. Why: In #1078, the CMO recommended conversion-optimizer and copywriter for the cancellation flow, but the plan skill silently wrote them into Skipped specialists: without asking, producing UX artifacts that lacked brand review.
Step 2 — Product/UX Gate:
Mechanical UI-surface override (runs FIRST, before the subjective relevance check). Scan the plan's ## Files to Create AND ## Files to Edit against the shared UI-surface term list + glob superset (plugins/soleur/skills/brainstorm/references/ui-surface-terms.md). If any path matches, force Product-relevant = true AND tier = BLOCKING, regardless of what the Step-1 semantic sweep concluded. This closes the silent-skip hole where a UI feature whose sweep judged Product NONE would skip the gate entirely (a UI feature must never reach ## NONE by subjective judgment alone). A plan that only discusses UI but implements orchestration/docs (no UI-surface file in its Files lists) is exempt and may be NONE.
After Steps 1 and 1.5 complete, if Product domain was flagged as relevant (by the sweep OR the mechanical override above), run the three-tier classification:
BLOCKING: Creates new user-facing pages, multi-step user flows, or significant new UI components — including modals, dialogs, confirmation flows, and interstitials with emotional or persuasive copy (e.g., signup flows, dashboards, onboarding wizards, chat interfaces, retention modals, cancel confirmation screens, prompts, banners)
ADVISORY: Modifies existing user-facing pages or components without adding new interactive surfaces (e.g., layout changes, form updates, adding fields to existing screens)
NONE: No user-facing impact
A plan that discusses UI concepts but implements orchestration changes (e.g., adding a UX gate to a skill) is NONE.
Mechanical escalation (overrides subjective assessment): Scan the plan's "Files to create" list. If any new file path matches components/**/*.tsx, app/**/page.tsx, or app/**/layout.tsx, the tier is BLOCKING regardless of subjective assessment. Creating a new component file = new user-facing surface = UX review required. Why: In #1049, a notification prompt component was classified as ADVISORY because the agent judged it "not significant enough." The user had to manually trigger the UX gate post-plan.
On BLOCKING:
Run spec-flow-analyzer via Task with UI-flow-aware prompt: "Analyze the user flows in this plan. Map each screen, identify entry/exit points, dead ends, missing error states, and flows that drop the user. Focus on user journey completeness, not technical implementation."
Run CPO via Task with scoped prompt: "Assess the product implications of this plan: {plan summary}. Cross-reference against brand-guide.md and constitution.md. Identify product strategy concerns, flow gaps, and positioning issues. Output a structured advisory — do not use AskUserQuestion."
Brainstorm carry-forward check. Before invoking ux-design-lead, check the UX signal source. If the only UX validation is brainstorm carry-forward (brainstorm assessed the idea, not the page design), reject it: "Brainstorm validated the idea, not the page design. Proceeding to wireframes." Then continue to step 4. This check applies to BLOCKING tier only — ADVISORY and NONE tiers may still carry forward brainstorm UX findings.
Invoke ux-design-lead via Task with scoped prompt: "Create wireframes for these user flows: {flow list}. Platform: desktop. Fidelity: wireframe." On the one-shot/pipeline path (no brainstorm ran), plan Phase 2.5 is the SOLE PRODUCER of wireframes — it must GENERATE the .pen, not defer. If the agent self-stops because Pencil is unavailable, do NOT record a skip: run bash ${CLAUDE_PLUGIN_ROOT:-plugins/soleur}/skills/pencil-setup/scripts/check_deps.sh --auto (installs @pencil.dev/cli; auth via PENCIL_CLI_KEY from Doppler soleur/dev) and re-invoke. Hard-block (do not proceed, do not write to Skipped specialists:) only if auth is genuinely unsatisfiable or Node < 22.9.0, with a single instruction: "Provision PENCIL_CLI_KEY in Doppler soleur/dev (or pencil login), or install Node ≥ 22.9.0, then re-run plan." The two permitted outcomes are a committed .pen or this hard-block — ux-design-lead may never appear in Skipped specialists: for a UI feature (wg-ui-feature-requires-pen-wireframe). Verifier asserts the invariant, not the proxy: confirm the .pen exists on disk (non-empty) under knowledge-base/product/design/{domain}/ and is referenced in the spec FRs — not "specialist reported done"; set Pencil available: yes.
4b. Wireframe review pause. ux-design-lead ends by running xdg-open <screenshots-directory>, so the wireframes are already open when it returns here. A Task subagent cannot collect operator input (2026-05-12-task-subagent-prompt-text-only.md), so the review pause lives in this orchestrator, right after the step-4 invocation. Mode-branch gate (2026-03-27-skill-defense-in-depth-gate-pattern.md): always run, branch on mode.
Interactive arm (interactive plan session): AskUserQuestion — "Wireframes are open for review at <screenshots-dir>. Approve and continue, or request changes?" Options: Approve → record the approved design's aesthetic direction to the taste-profile (the agent surface's write path — ux-design-lead never writes taste itself; #5990/ADR-090): bash ${CLAUDE_PLUGIN_ROOT:-plugins/soleur}/scripts/taste-profile-update.sh knowledge-base/product/design/taste-profile.md <context> aesthetic-direction <approved-direction> "$(date -u +%F)" (<context> = the design's surface enum, <approved-direction> = a sanitized lowercase-hyphen token); then continue to step 5 (Content Review Gate). Request changes → collect a free-text note, re-invoke ux-design-lead with feedback: <note> plus the existing .pen path, let it re-export + re-open, then re-ask. Loop until Approve — the Approve branch is the only exit (no dead end).
Headless / pipeline arm: mirror the auto-accept in the On ADVISORY: block below (step 1 — "If in pipeline/subagent context … auto-accept … proceed silently"). When plan runs in any non-interactive context — HEADLESS_MODE=true, no TTY, /soleur:one-shot, /soleur:go --headless, OR invoked with a plan-file-path argument (the one-shot path chains plan inside a Task subagent, one-shot/SKILL.md:70) — do NOT pause. Record wireframes ready for async review at <dir> and continue to step 5. Load-bearing: the subagent / file-path context is inherently non-interactive — the headless arm MUST fire there or the autonomous pipeline hangs on AskUserQuestion.
Why: wireframes are a visual artifact the operator must eyeball before the design freezes into the spec; the headless suppression honors one-shot/SKILL.md:11 ("no per-phase approval gates"). Keep this mode predicate in sync with brainstorm Phase 3.55b and the canonical Phase 0.4 mode-detection block (brainstorm/SKILL.md:101) — the four context terms (HEADLESS_MODE, no-TTY, /soleur:one-shot, --headless) must stay aligned across all copies; the plan-file-path term is a plan-specific addition.
Content Review Gate. Check if any domain leader (CMO, CRO, CPO, or other) recommended a copywriter or content specialist in their Step 1 assessment. If yes: invoke copywriter agent via Task with prompt: "Review the planned page content for brand voice compliance, value proposition clarity, and messaging effectiveness. Reference brand-guide.md." If copywriter ran successfully, add copywriter to **Agents invoked:**. If user declines, add copywriter to **Skipped specialists:** with the user's reason. If copywriter agent fails (timeout, error), add copywriter to **Skipped specialists:** with note (agent error — review manually) and set **Decision:** reviewed (partial). If no domain leader recommended a copywriter, skip this step silently. This gate also fires on ADVISORY tier when a domain leader recommended a copywriter — the recommendation is the signal, not the tier.
Phase 3 SpecFlow is skipped (spec-flow-analyzer already ran in step 1 with UI-aware prompt — avoids duplicate invocation).
If any agent in the pipeline fails (timeout, error), write partial findings with Decision: reviewed (partial). BLOCKING gate enforcement: If the tier is BLOCKING and a required specialist failed, do NOT silently proceed. For ux-design-lead specifically there is NO "skip" option — it is a non-skippable producer (step 4): retry via pencil-setup --auto, or hard-block until Pencil is provisioned. For copywriter / spec-flow-analyzer failures, use AskUserQuestion: "BLOCKING Product/UX Gate: [specialist] failed ([reason]). How to proceed?" Options: (a) Retry now, (b) Skip with acknowledgment (copywriter/spec-flow only — never ux-design-lead), (c) Defer to next session. Record the choice in the Domain Review section. For ADVISORY tier or non-specialist agents, proceed silently with partial findings as before.
On ADVISORY:
If in pipeline/subagent context (plan file path was provided as argument, not interactive): auto-accept, write Product/UX Gate subsection with Tier: advisory, Decision: auto-accepted (pipeline), proceed silently.
If interactive: display notice via AskUserQuestion: "This plan modifies existing UI. Run UX review?" Options: "Yes, run full review" / "Skip — I'll handle UX manually". Record choice.
If user chooses full review, run the BLOCKING pipeline above.
Content Review Gate (ADVISORY). Regardless of the UX review choice, if any domain leader recommended a copywriter or content specialist, run step 5 from the BLOCKING pipeline (Content Review Gate). The recommendation is the signal, not the tier — modifying existing copy still benefits from content review.
On NONE: Skip — no Product/UX Gate subsection needed beyond the domain sweep finding.
If Product domain was NOT flagged as relevant in the sweep AND the mechanical UI-surface override did not fire, skip Step 2 entirely. If the override fired, Step 2 runs at BLOCKING tier regardless of the sweep.
Writing the ## Domain Review section:
After both steps complete, write the ## Domain Review section to the plan file using the heading contract below.
## Domain Review Heading Contract:
## Domain Review**Domains relevant:** [comma-separated list] | none
### [Domain Name] (one subsection per relevant non-Product domain)**Status:** reviewed | error
**Assessment:** [leader's structured assessment summary]
### Product/UX Gate (only if Product domain relevant and tier is BLOCKING or ADVISORY)**Tier:** blocking | advisory
**Decision:** reviewed | reviewed (partial) | skipped | auto-accepted (pipeline)
**Agents invoked:** spec-flow-analyzer, cpo, ux-design-lead, copywriter | [subset] | none
**Skipped specialists:** copywriter (<reason>) | none — `ux-design-lead` is NEVER valid here for a UI feature (non-skippable: `.pen` committed or hard-block per `wg-ui-feature-requires-pen-wireframe`)
**Pencil available:** yes | hard-blocked (auth/Node) | N/A (no UI surface)
#### Findings
[Agent findings summary]
Place after Acceptance Criteria, before Test Scenarios (or before the last major section). If the plan lacks an Acceptance Criteria heading, place before the last major section or at the end of the plan.
2.6. User-Brand Impact Section (Always)
Every plan MUST include a ## User-Brand Impact section. This is the framing-time enforcement of AGENTS.md hr-weigh-every-decision-against-target-user-impact and the gate that catches the #2887-class blind spot — decisions weighed on technical and convenience axes only, with no question asked about what one user's breach would cost the brand.
Step 1 — Insert the section. If the plan draft does not yet contain a ## User-Brand Impact heading, insert one using the template from plugins/soleur/skills/plan/references/plan-issue-templates.md. The section MUST appear between the description and the Acceptance Criteria. The three required lines:
**If this lands broken, the user experiences:** — name a concrete, user-facing artifact.
**If this leaks, the user's [data / workflow / money] is exposed via:** — name a concrete exposure vector.
Step 2 — Brainstorm carry-forward. If the brainstorm document loaded in Phase 0.5 contains a ## User-Brand Impact framing (which it should when brainstorm Phase 0.1 set USER_BRAND_CRITICAL=true), import the threshold and the artifact/vector declarations directly rather than re-authoring. Carry-forward is preferred — re-authoring at plan time risks drift from the brainstormed framing.
Step 3 — Threshold-driven sign-off requirement. If the threshold resolves to single-user incident:
Add requires_cpo_signoff: true to the plan's YAML frontmatter.
Display: "CPO sign-off required at plan time before /work begins. Invoke CPO domain leader if not already covered by Phase 2.5 carry-forward, or confirm CPO has reviewed the brainstorm."
Note in the plan that user-impact-reviewer will be invoked at review-time (handled by plugins/soleur/skills/review/SKILL.md conditional-agent block).
Sign-off lifecycle staging — who participates at which phase:
The set of mandatory leaders changes by lifecycle phase, and that is by design — different leaders weigh in at different decision points:
Brainstorm phase (framing time): CPO + CLO + CTO are spawned in parallel when USER_BRAND_CRITICAL=true. Rationale: the approach has not been chosen yet, so all three lenses (product blast-radius framing, legal/compliance, architectural blast-radius) need to land before the plan exists. See plugins/soleur/skills/brainstorm/references/brainstorm-domain-config.md## User-Brand-Critical Tag Processing.
Plan phase (this gate): CPO sign-off only. Rationale: the plan implements the approach already framed by all three brainstorm leaders; the plan-time sign-off is the single product-owner ack on the technical approach. CLO and CTO concerns from brainstorm should be reflected in the plan body (Risks section, Sharp Edges, Domain Review carry-forward) — they do not re-sign here.
Review phase (PR time): CPO is not re-invoked; instead the user-impact-reviewer agent enumerates failure modes against the diff. Rationale: review-time concerns are diff-shaped, not approach-shaped.
Ship phase (preflight Check 6): No human sign-off; mechanical gate that the section exists and the threshold is valid.
This tiered model is intentional — re-asking CPO/CLO/CTO at every phase would dilute the framing into ceremony. The framing question is asked once (brainstorm), the answer is locked in (plan), the diff is checked against the answer (review), the gate verifies the answer was given (ship).
If the threshold resolves to aggregate pattern, no per-PR sign-off is added but the section must still be present.
If the threshold resolves to none AND the diff touches a sensitive path (canonical regex defined in plugins/soleur/skills/preflight/SKILL.md Check 6 Step 6.1), the section MUST contain a threshold: none, reason: <one-sentence non-empty reason> scope-out bullet. Without it, preflight will FAIL at ship time.
Step 4 — Sharp-edge note. When emitting the final plan output, add a Sharp Edges entry:
A plan whose ## User-Brand Impact section is empty, contains only TBD/TODO/placeholder text, or omits the threshold will fail deepen-plan Phase 4.6. Fill it before requesting deepen-plan or /work.
Why: Triggered by #2887 — the dev/prd Doppler-config collapse shipped for months because every existing gate weighed the decision on technical and convenience axes only. The framing-time enforcement here, combined with deepen-plan Phase 4.6 (halt on missing section), preflight Check 6 (ship-time gate), and the user-impact-reviewer conditional agent, closes the workflow-level loop.
2.7. GDPR / Compliance Gate
[skill-enforced: gdpr-gate at plan Phase 2.7]
If the plan touches regulated-data surfaces (per the hr-gdpr-gate-on-regulated-data-surfaces canonical regex — schemas, migrations, auth flows, API routes, .sql files), invoke /soleur:gdpr-gate against the plan doc + the FR/TR sections being authored. Output is advisory-only with mandatory disclaimer; Critical findings (Art. 9 special-category, missing lawful basis, Art. 30 trigger) prompt operator-acknowledged write to compliance-posture.md Active Items + GitHub issue with label compliance/critical.
Also invoke when canonical regex misses but ANY of these hold: (a) new processing activity using LLM/external API on operator-session-derived data, (b) brand-survival threshold single-user incident declared in the plan, (c) new cron/workflow that READS from knowledge-base/project/learnings/ or knowledge-base/project/specs/, (d) new artifact distribution surface (plugin update, public PR body, package release). The canonical regex covers schema/auth/API code surfaces; these four expand coverage to cross-controller data-movement surfaces. Why: 2026-05-11 #2720 — plan touched none of the regex surfaces but added Anthropic-bound LLM-summarization of operator-session learnings + draft PRs to public repo; gate-time invocation surfaced a pre-existing Anthropic-DPA gap that no other gate caught. See knowledge-base/project/learnings/2026-05-11-five-agent-plan-review-panel-and-architectural-false-trails.md.
Skip silently if no regulated-data surface is touched AND none of the (a)-(d) triggers fire.
2.8. Infrastructure-as-Code Routing Gate
[skill-enforced: terraform-architect at plan Phase 2.8]
If the plan introduces infrastructure that needs to live somewhere — a server, a systemd service, a cron job, a vendor account, a DNS record, a TLS cert, a secret, a firewall rule, a monitoring webhook — route the implementation through Terraform (or another IaC mechanism already in the repo) at plan time. Do NOT bake "operator runs ssh root@host && ...", "operator runs doppler secrets set X=...", or "operator clicks through the vendor dashboard" into the plan's Implementation Phases. Per hr-all-infrastructure-provisioning-servers, manual provisioning is not an acceptable phase output.
Detection (case-insensitive substring scan of the plan draft + the feature description):
systemctl enable, systemctl start, systemd unit, /etc/systemd/system/
doppler secrets set (vs reading via doppler secrets get which is read-only)
terraform import of a resource that should have been created by Terraform
vendor-dashboard wording: "go to the [Cloudflare|Hetzner|Stripe|Doppler|Better Stack|Sentry|R2|Supabase] dashboard and …", "in the … console click …"
cron/crontab -e, at <time>, journalctl (when used for state, not diagnosis)
new vendor account signups not already routed through service-automator or ops-provisioner
If detected, invoke terraform-architect with the plan draft and the detected phrases. The agent's job is to reshape the affected Implementation Phases so the new resource lives in apps/<app>/infra/*.tf (extending the existing root, or creating a new one with the R2 backend per hr-every-new-terraform-root-must-include-an), with cloud-init/runcmd for first-boot config and an idempotent bootstrap script (e.g. apps/<app>/infra/<resource>-bootstrap.sh) for applying the change to already-running hosts without re-provisioning.
Required output: ## Infrastructure (IaC) section in the plan. Mirror the ## Domain Review heading contract. Required subsections:
### Terraform changes — listed files (existing TF root + new resources), required providers + version pins, sensitive variable list (TF_VAR_<name> plus where the value comes from — Doppler service token, etc.).
### Apply path — one of: (a) cloud-init-only (acceptable when the resource has not yet been provisioned), (b) cloud-init + idempotent bootstrap script (the default for existing infra), (c) taint + terraform apply -replace (only when the resource cannot be patched in place). State the chosen path and the expected downtime/blast-radius.
### Distinctness / drift safeguards — dev != prd preconditions, lifecycle.ignore_changes callouts, state-storage notes (encrypted backend, secret values land in terraform.tfstate).
### Vendor-tier reality check — when the chosen provider has free-tier limits that affect resource creation (e.g., Better Stack free tier rejects betteruptime_policy), document the tier gate (count = var.<provider>_paid_tier ? 1 : 0) before apply time.
Why: PR-F (#3940) plan baked in "operator installs inngest-cli + systemd unit via SSH" and "operator sets Doppler keys via CLI" as Phase X items. Both violate hr-all-infrastructure-provisioning-servers. The rule existed; no plan-time gate consulted it. The cost was a post-merge realisation that the entire operator checklist had to be redone as Terraform. See knowledge-base/project/learnings/2026-05-18-plan-baked-in-operator-ssh-violated-iac-rule.md.
Skip silently if the plan introduces no new infrastructure (pure code change against an already-provisioned surface). A plan that only edits files under apps/<app>/src/ or apps/<app>/server/ typically skips. A plan that introduces a new service, a new secret, a new vendor, or a new persistent runtime process does not.
2.9. Observability Quality Gate
[skill-enforced: plan Phase 2.9 + deepen-plan Phase 4.7]
Every plan whose Files-to-Edit includes a code-class file under apps/*/server/, apps/*/src/, apps/*/infra/, plugins/*/scripts/, or that introduces any new infrastructure surface (per Phase 2.8 trigger set), MUST emit a ## Observability section using the 5-field schema. A feature that requires SSH to verify observability is a feature without observability.
Required schema (verbatim from plan-issue-templates.md):
liveness_signal:# what / cadence / alert_target / configured_inerror_reporting:# destination / fail_loudfailure_modes:# list of {mode, detection, alert_route}logs:# where / retentiondiscoverability_test:# command (NO ssh) / expected_output
Reject conditions (enforced at deepen-plan Phase 4.7 — see deepen-plan/SKILL.md):
Section missing entirely.
Any required field contains the substring TODO, TBD, placeholder, or manual operator check AS THE FIELD VALUE (a fallback note in surrounding prose mentioning TBD is allowed; the canonical "field is empty" reject regex is ^\s*<field>:\s*(TODO|TBD|placeholder|manual operator check)\s*$).
discoverability_test.command contains ssh (with trailing space — distinguish "ssh " the verb from "ssh-free" in docs).
Skip silently when:
Plan is pure-docs (no Files-to-Edit under code/infra paths above).
Plan deletes-only (no new code/infra surface; revert PRs).
Why: #4116 — inngest-heartbeat.service was silently broken for 16+ hours. The plan that introduced it (PR-F #3940) passed every other plan-time gate but had no observability declaration; the operator-blind-zone aggregated across the substrate cascade (#4017 → #4111) until issue #4116 surfaced the gap. Codifying the gate at plan-time prevents the next feature from shipping a dark observability surface.
If any Acceptance Criterion or the liveness_signal declares a post-deploy soak / time-gated close criterion — a signal that must hold for N days/hours before an issue closes or an ADR/amendment status flips (adopting → accepted), e.g. "op:founder-ambiguous stays at ~0 for 7 days post-deploy" — the plan MUST add a Follow-Through Enrollment deliverable so the closure is automated, not left to human memory (the recurring rot the daily follow-through sweeper exists to prevent — see followthrough-convention.md, §Soak trigger shape).
The deliverable names:
the verification script path under scripts/followthroughs/ (named <short-name>-<issue>.sh) — exit 0 when the soak holds; for Sentry-rate soaks, mirror reconcile-ff-only-sentry-4977.sh with start= pinned strictly after deploy;
the tracker's <!-- soleur:followthrough script=… earliest=<deploy+Nd> secrets=… --> directive + the follow-through label;
any new secrets= to wire into .github/workflows/scheduled-followthrough-sweeper.yml.
This is enforced at ship time (fail-closed) by /ship Phase 5.5's Soak-Gated Follow-Through Enrollment Gate + the ship-soak-followthrough-gate.sh PreToolUse hook; declaring it here means the work phase builds the probe instead of /ship blocking PR-ready on a missing one. Why: 2026-06-29 — PR #5671 (#5673) and PR #5675 (#5689) both shipped soak-gated closures in prose with no enrollment; both trackers were left to rot until caught manually.
If the plan's Files-to-Edit touch a surface the operator/agent CANNOT directly inspect — an agent bwrap sandbox (server/agent-runner-sandbox-config.ts, server/sandbox*.ts, server/bash-sandbox.ts), a container dispatch/readiness gate (server/cc-dispatcher.ts, server/agent-runner.ts, *agent-on-spawn*, any *readiness*/*self-stop* path), or a cron worker — the ## Observability block's failure_modes MUST additionally satisfy:
Each detection names an in-surface probe (a signal emitted FROM the sandbox/container/worker), not only a host-side layer. A host gate cannot observe a sandbox's internal state.
The probe's structured fields discriminate ALL competing root-cause hypotheses in one event (e.g. source / gitKind / gitRevParseValid for a host-vs-sandbox-mount split) — not a single boolean that emits for only one failure shape.
This is the affected-surface extension of hr-observability-as-plan-quality-gate — the diagnosis-first discipline for blind surfaces, enforced at review by observability-coverage-reviewer §Step 4.6. Why: #5733 — 6 blind server-side fixes over ~2 weeks because the failing agent-sandbox surface emitted no discriminating telemetry; one in-sandbox event decided the root cause the moment it shipped. See knowledge-base/project/learnings/best-practices/2026-07-01-blind-surface-needs-structured-probe-before-nth-fix.md.
2.10. Architecture Decision (ADR / C4) Gate
[skill-enforced: plan Phase 2.10 — wg-architecture-decision-is-a-plan-deliverable]
If the plan makes or changes an architectural decision, the ADR write and the C4 diagram update are deliverables of THIS plan — never a deferred follow-up issue. Phase 0.6 / line 112 already make you read the ADR corpus; this gate makes you produce the decision record when the plan creates one. Deferring an ADR/C4 update to "later" ships a system whose recorded architecture lies about its real one until someone reopens the issue (usually never).
Detection (the plan introduces or changes any of):
A data-model ownership / tenancy boundary move (user-keyed → workspace-keyed, per-row → per-tenant, a new "X owns Y" relationship).
A new substrate or integration pattern (a new queue, cron substrate, auth/credential boundary, external-service edge).
A resolver / dispatch / trust boundary change (who resolves what, fail-closed semantics, a new cross-cutting invariant every consumer must honor).
A reversal or extension of an existing ADR (you read it in Phase 0.6 and the plan diverges from or supersedes its Decision).
Any change a future engineer would be surprised to find undocumented in knowledge-base/engineering/architecture/.
If detected, the plan MUST emit an ## Architecture Decision (ADR/C4) section naming, as in-scope plan tasks:
### ADR — the ADR to create or amend via /soleur:architecture (number + one-line decision). New decision → new ADR; divergence from an existing one → amend that ADR's ## Decision + add to its ## Alternatives Considered. This is a task in the implementation phases, not a "see also." The chosen ordinal for a NEW ADR is provisional — a sibling PR can claim it during the pipeline (they only surface together post-squash on main, since adr-ordinals is not a required check). /ship's "ADR-Ordinal Collision Gate" re-verifies the next-free ordinal against origin/main before merge and after every Phase 7 sync; do not treat the plan-time number as final. When you DO renumber, sweep the whole feature's artifact set for the old ordinal in the same edit — grep -rn 'ADR-<old>' knowledge-base/project/{plans,specs}/feat-<slug>/ — because the renumber otherwise reaches only the ADR body/seed/code while the plan + tasks + any AC that names the ordinal keep the stale number (a `ADR-<old>-*.md` exists AC then verifies a nonexistent file). Why: #5945 chose ADR-081 → renumber to ADR-082 (#5952); #5990 collided TWICE in one ~2h pipeline (087→089 at rebase, 089→090 at ship as siblings claimed each free ordinal) and the first renumber left AC12 asserting a nonexistent ADR-087-*.md until review caught it (2026-07-05-adr-renumber-must-sweep-planning-docs-and-scripts-glob-orphan.md).
### C4 views — which C4 view(s) (Context / Container / Component) change and how (e.g., "Container: repo connection edge moves from User to Workspace"). The workflow edits the .c4 model files DIRECTLY (via the architecture skill / Edit tool, committed in THIS feature's lifecycle — not a separate issue). The c4-edit flag (commit 3c8849655) gates ONLY direct end-user edits in the in-browser webapp editor (PUT /api/kb/c4, default OFF); it does not gate a workflow and the workflow never routes through that path. Concierge and the Claude Code plugin terminal are equally-trusted agent contexts that edit .c4 on the filesystem and commit — do NOT instruct the implementer to "route the C4 edit through the Concierge."
C4 completeness mandate (load-bearing — no narrow-grep escape hatch). Before writing the ### C4 views task (INCLUDING a "no C4 impact" conclusion), you MUST actually READ all three model files — knowledge-base/engineering/architecture/diagrams/{model.c4,views.c4,spec.c4} — not a single keyword grep. A grep for the feature's own noun (e.g. grep email-triage) returning zero is NOT evidence of "no C4 impact": the relevant elements are frequently the feature's external actors and systems (a human role like an inbound email sender; an integration like Resend/Stripe/Twilio; a new data store), which are named by the vendor/role, not the feature. Enumerate, for the feature, EVERY: (a) external human actor (who sends/receives data — correspondents, reviewers, end recipients), (b) external system / vendor (inbound webhook, outbound API, third-party store), (c) container/data-store touched, (d) actor↔surface access relationship that changes (e.g. single-owner → workspace-Owner-shared). For each, confirm it is already modeled; if NOT, the .c4 edit that adds it (element + #external tag if outside the boundary + the relationship edges + the view … include line in views.c4 so it RENDERS) is an in-scope plan task. Reviewing all three .c4 files for correctness also means fixing any element description the change falsifies (e.g. a "Solo founder" actor description when the change adds multi-Owner sharing). After editing, run the C4 validation tests (apps/web-platform/test/c4-code-syntax.test.ts + c4-render.test.ts) — a view include that references an undefined element fails there, not at tsc. A "no C4 impact" line in the plan MUST cite which actors/systems/relationships were checked and found already-modeled; an unsupported "None" is a reject condition.
### Sequencing — if the decision is only true after a later slice (e.g. a soak-gated migration), the ADR is authored now describing the target state with a "status: adopting" note; it is not postponed to its own issue.
Reject condition (enforced at deepen-plan): an architectural decision is detected but the plan defers the ADR/C4 update to a follow-up issue, OR the ## Architecture Decision (ADR/C4) section is missing while detection fires, OR the ### C4 views task concludes "no C4 impact" without citing the external-actor / external-system / access-relationship enumeration it checked against all three .c4 files (the C4 completeness mandate above).
Skip silently when the plan makes no architectural decision — a bug fix on an existing surface, a copy/UI tweak, a dependency bump, a pure-docs change. The test: would a competent engineer reading only the existing ADRs + C4 be misled about the system after this plan ships? If no, skip.
Why: 2026-06-16 ADR-044 workspace-connection brainstorm (#5437) — the always-enforce-workspace decision and its C4 connection-owner edge were initially filed as a deferred follow-up issue (#5440) instead of being part of the plan. The operator corrected it: the ADR/C4 update is intrinsic to the architectural change and must ship with it. No prior plan-time gate required producing (vs reading) an ADR. See knowledge-base/project/learnings/2026-06-16-adr-c4-update-is-a-plan-deliverable-not-a-deferred-issue.md.
2.11. Encryption Posture Gate
[skill-enforced: plan Phase 2.11 + deepen-plan Phase 4.10]
Every plan that introduces a persistent data store (a Hetzner volume, an R2 bucket, a Supabase table, a queue, a cache, a backup target, a log sink) or a new cross-component/network connection MUST emit a ## Encryption Posture section using the field set below. "The provider handles it" and "the provider supports TLS" are not postures — they are the absence of one.
Detection (the plan's Files-to-Create/Edit match, OR the prose names a store class / a new cross-component connection):
\.tf$
supabase/migrations/.*\.sql$
cloud-init.*\.ya?ml$
docker-compose.*\.ya?ml$
Required schema (verbatim from plan-issue-templates.md):
at_rest:# per store: mechanism / evidence / defends_against / does_not_defend / disclosed_as / live_verificationin_transit:# per connection: tls / cert_verification (on|off) / does_not_defend / disclosed_asexception:# present ONLY when mechanism is plaintext-exception OR cert_verification is off — justification / tracking_issue / reevaluate_when / expires_on
Reject conditions (enforced at deepen-plan Phase 4.10 — see deepen-plan/SKILL.md): section missing entirely while detection fires; a required field empty or matching the placeholder ban-list; mechanism or at_rest prose reading "the provider handles it" / "encrypted by default" with no named attestation / "supports TLS"; does_not_defend empty or "none"/"n/a"; a plaintext-exception or cert_verification: off row with no exception block, or one missing tracking_issue / expires_on.
Skip silently when the plan introduces no persistent store and no new cross-component connection — pure UI/docs/dependency-bump plans, or a change confined to an already-provisioned surface.
Why: ADR-140 and knowledge-base/project/plans/2026-07-23-feat-encryption-posture-design-time-default-plan.md (Plan Review Revisions R1-R11) — a new store or connection shipped with no declared encryption posture is undetectable at review time by name-similarity alone (a plaintext hcloud_volume.workspaces reads identically to its LUKS-backed sibling hcloud_volume.workspaces_luks until the device-binding chain is actually walked). Codifying the posture as a plan deliverable, resolved against real code by lint-encryption-posture.py (repo-root scripts/), closes the gap at design time instead of at incident time.
3. SpecFlow Analysis
If spec-flow-analyzer was already invoked in Phase 2.5, skip this phase and proceed to Phase 4.
After planning the issue structure, run SpecFlow Analyzer to validate and refine the feature specification. SpecFlow is especially valuable for CI/workflow and infrastructure changes where bash conditional logic can silently drop edge cases that human review misses.
Incorporate any identified gaps or edge cases into the issue
Update acceptance criteria based on SpecFlow findings
4. Choose Implementation Detail Level
Read plugins/soleur/skills/plan/references/plan-issue-templates.md now to load the three issue templates (MINIMAL, MORE, A LOT). Select the appropriate detail level based on complexity -- simpler is mostly better. Use the template structure from the reference file for the chosen level.
4.5. Scoped Advisor Consult (token-frugal)
Before finalizing the plan into issues, get one strong-model second opinion at the highest-leverage decision point — but pay only for a curated payload, not the whole session.
Spawn a Task subagent with model: fable (the top advisor tier; if that spawn is rejected because the org lacks Fable access, retry once with model: opus) and a curated prompt — pass only the plan's ## Overview, ## Implementation Phases, and the phase you judge riskiest. Do NOT pass the conversation: a Task subagent receives prompt text only (knowledge-base/project/learnings/best-practices/2026-05-12-task-subagent-prompt-text-only.md), so curation is the token lever that makes this far cheaper than Claude Code's built-in advisor (which re-sends the full transcript, uncached, every call). Prompt shape:
Review this implementation plan's approach and its riskiest phase. Name the one or two changes most likely to prevent rework or a wrong-architecture commit. Be concise — assume you see only what is quoted. PLAN:\n<overview + phases + riskiest phase>
Apply the returned guidance before Step 5. Advisory only — do not block, loop, or re-consult. Skip silently in a resource-constrained run only if the plan is trivially mechanical (single-file, no architecture choice). Rationale + the model: fable upgrade-pin justification: ADR-083 (knowledge-base/engineering/architecture/decisions/ADR-083-scoped-strong-model-consult-at-decision-gates.md).
When the consult and the session model agree the operator's stated direction should change (drop/merge/split/add scope the operator specified), that is a User-Challenge per decision-principles.md (ADR-084), not guidance to silently apply — the operator's direction is the default. Operator-attached: surface it at the post-plan-review confirmation gate with the 5-line frame. Headless (this Step runs inside a Task subagent under one-shot): do NOT ask — persist it to knowledge-base/project/specs/<branch>/decision-challenges.md for ship to render + file as an action-required issue.
5. Issue Creation & Formatting
Apply best practices for clarity and actionability, making the issue easy to scan and understand
Content Formatting:
Use clear, descriptive headings with proper hierarchy (##, ###)
Include code examples in triple backticks with language syntax highlighting
Add screenshots/mockups if UI-related (drag & drop or use image hosting)
Use task lists (- [ ]) for trackable items that can be checked off
Add collapsible sections for lengthy logs or optional details using <details> tags
Reference specific commits with SHA hashes when relevant
Link to code using GitHub's permalink feature (press 'y' for permanent link)
Mention relevant team members with @username if needed
Add links to external resources with descriptive text
Code & Examples:
# Good example with syntax highlighting and line references```ruby
# app/services/user_service.rb:42
def process_user(user)
# Implementation here
end
```# Collapsible error logs<details><summary>Full error stacktrace</summary>`Error details here...`</details>
AI-Era Considerations:
Account for accelerated development with AI pair programming
Include prompts or instructions that worked well during research
Note which AI tools were used for initial exploration (Claude, Copilot, etc.)
Emphasize comprehensive testing given rapid implementation
Document any AI-generated code that needs human review
6. Final Review & Submission
Pre-submission Checklist:
Title is searchable and descriptive
Labels accurately categorize the issue
All template sections are complete
Links and references are working
Acceptance criteria are measurable
Add names of files in pseudo code examples and todo lists
Add an ERD mermaid diagram if applicable for new model changes
Browser task automation check: Scan all tasks for steps labeled "manual", "browser", or "user must". If any task involves browser interaction (account creation, form submission, settings configuration, credential generation), rewrite it as a Playwright MCP automation step. The only genuinely manual browser steps are CAPTCHA solving and interactive OAuth consent -- and even those should be automated up to the CAPTCHA/consent gate, then handed to the user for that single interaction.
Deferral tracking check: Scan the plan's "Alternative Approaches Considered" table and any "Non-Goals" or "Out of Scope" sections for items explicitly deferred to a later phase. For each deferred item, create a GitHub issue with: what was deferred, why, re-evaluation criteria, and milestone from knowledge-base/product/roadmap.md. A deferral without a tracking issue is invisible.
CLI-verification gate (#2566): For every CLI invocation the plan prescribes to land in user-facing docs (*.njk, *.md, README, apps/**), verify the tokens exist. One of: (a) run <tool> --help or <tool> <subcommand> --help locally and paste the relevant line into Research Insights; (b) cite the tool's official command reference URL; (c) annotate the plan snippet with <!-- verified: YYYY-MM-DD source: <url> -->. A plan that embeds a CLI invocation without ONE of the three MUST NOT ship -- silence (omit the snippet) beats fabrication. tsc and Eleventy build do NOT catch fabricated tokens. Why: #1810/#2550 shipped ollama launch claude --model gemma4:31b-cloud -- every token fabricated, caught 8 days later.
Output Format
Filename: Use the date and kebab-case filename from Step 2 Title & Categorization.
❌ knowledge-base/project/plans/2026-01-15-feat-thing-plan.md (not descriptive - what "thing"?)
❌ knowledge-base/project/plans/2026-01-15-feat-new-feature-plan.md (too vague - what feature?)
❌ knowledge-base/project/plans/2026-01-15-feat: user auth-plan.md (invalid characters - colon and space)
❌ knowledge-base/project/plans/feat-user-auth-plan.md (missing date prefix)
Plan Review (Always Runs)
After writing the plan file, automatically run /plan_review <plan_file_path> to get feedback from the reviewer panel in parallel:
Eng panel (always): DHH Rails Reviewer (challenges overengineering), Kieran Rails Reviewer (correctness, convention), Code Simplicity Reviewer (YAGNI) — escalating to +architecture-strategist +spec-flow-analyzer at the single-user-incident threshold.
Named CEO/design/devex panel (relevance-gated):cpo/cmo (business), ux-design-lead (design), cto (devex) — spawned only when the plan is relevant to the lens, by an independent content scan (see plan-review/SKILL.md). Their findings are frequently taste, so plan-review tags each consolidated decision decisionClass ∈ {mechanical, taste, user-challenge} per decision-principles.md (ADR-084).
After review completes, present the consolidated feedback (agreements first, then disagreements), then apply by class:
Mechanical findings → auto-apply to the plan file (both modes). Fail-closed default: auto-apply only a decision explicitly tagged mechanical. Treat any decision that is unclassified, ambiguous, or sourced from a named-panel (product/market/design/devex) finding as Taste — surface it, never silently auto-apply. (The producer defaults named findings to Taste, but the consumer must not depend on producer-side tagging fidelity: an untagged decision on the prose path routes to surfacing, not to auto-apply.)
Taste / User-Challenge findings →
Operator-attached (real TTY): present at the "Apply these changes?" gate below (Yes / Partially / Skip); a User-Challenge uses the 5-line frame (the operator's stated direction is the default).
Headless (reuse the mode predicate at [plan/SKILL.md §Product/UX Gate step 4b, ":330"] — HEADLESS_MODE, no-TTY, /soleur:one-shot, --headless, OR a plan-file-path arg): do NOT pause. Persist each Taste / User-Challenge to knowledge-base/project/specs/<branch>/decision-challenges.md (append), which ship Phase 6 renders into the PR body + files as an action-required issue. This converges with the Step 4.5 decision-challenges.md wiring (:574) onto one artifact.
Ask: "Apply these changes?" (Yes / Partially / Skip)
If Yes: apply all remaining (Taste/User-Challenge) changes to the plan file
If Partially: ask which changes to apply, then apply selected changes
If Skip: continue unchanged
Why Plan Review runs BEFORE Save Tasks:tasks.md is a derivative breakdown of the plan's phases. If review prompts material changes (phase cuts, deliverable rewrites), generating tasks.md beforehand would immediately go stale and require regeneration. Running review first → applying changes → then deriving tasks ensures tasks.md reflects the final plan as a single source of truth, and the commit below covers both files in one atomic history entry.
Save Tasks to Knowledge Base (if exists)
After Plan Review has applied any requested changes, generate tasks.md from the finalized plan and commit all artifacts together:
Check if knowledge-base/ exists. If so, run git branch --show-current to get the current branch. If on a feat-* branch, create the spec directory with mkdir -p knowledge-base/project/specs/<branch-name>.
If knowledge-base/ exists and on a feature branch:
Carry forward lane: from spec.md. Extract using the canonical gsub awk pattern (matches skill-security-scan/scripts/run-scan.sh:34):
Validate LANE against the 3-value enum (single-domain, cross-domain, procedural). If empty (legacy spec lacks lane:) or invalid (any other value), set LANE=cross-domain and echo to the operator terminal: plan: spec lacks valid lane: — defaulted to cross-domain (fail-closed). Add a one-line note to the plan body: Spec lacks valid lane: — defaulted to cross-domain (TR2 fail-closed). The plan file's YAML frontmatter MUST include lane: <value>.
Generate tasks.md using spec-templates skill template, derived from the finalized (post-review) plan:
Extract actionable tasks from the plan
Organize into phases (Setup, Core Implementation, Testing)
Use hierarchical numbering (1.1, 2.1, 2.1.1, etc.)
Save tasks.md to knowledge-base/project/specs/feat-<name>/tasks.md
Announce: "Tasks saved to knowledge-base/project/specs/feat-<name>/tasks.md. Use skill: soleur:work to implement."
Commit and push plan artifacts:
Both the plan file and tasks.md are committed together so the final plan and its task breakdown land in the same history entry:
git add knowledge-base/project/plans/ knowledge-base/project/specs/feat-<name>/tasks.md
git commit -m "docs: create plan and tasks for feat-<name>"
git push
If the push fails (no network), print a warning but continue.
If knowledge-base/ does NOT exist or not on feature branch:
Plan saved to knowledge-base/project/plans/ only (current behavior)
Exit Gate (direct invocation only)
Pipeline detection: If this skill is running inside a Task subagent (the conversation
contains a RETURN CONTRACT section from a Task delegation), skip the exit gate entirely.
Return the plan file path per the return contract. The calling pipeline handles compound
and lifecycle progression.
If invoked directly by the user:
Run skill: soleur:compound to capture learnings from the planning session.
If compound finds nothing to capture, it will skip gracefully — do not block on this.
Verify all plan artifacts are committed and pushed. The Save Tasks section already
committed the plan file and tasks.md. Run git status --short to check for any
remaining uncommitted changes. If found:
git add knowledge-base/project/plans/ knowledge-base/project/specs/feat-<name>/
git commit -m "docs: plan artifacts for feat-<name>"
git push
If there are no uncommitted changes, skip the commit. If push fails (no network),
warn and continue.
Display the resume prompt (per AGENTS.md Communication rule). Format:
All artifacts are on disk. Run `/clear` then paste this to resume:
/soleur:work <plan-file-path>
Context: branch <branch>, worktree <worktree-path>, PR #<N>, issue #<N>.
<one-line summary of what was already done>
Replace placeholders with actual values from the session. The user must be
able to paste the command and go without re-explaining context.
Resume prompt (MANDATORY): After the display message above, always output a copy-pasteable resume prompt block. This is required by AGENTS.md whenever /clear is mentioned. Format:
Resume prompt (copy-paste after /clear):
/soleur:work <plan-path>. Branch: feat-<name>. Worktree: .worktrees/feat-<name>/. Issue: #<number>. PR: #<pr-number>. Plan reviewed, implementation next.
Post-Generation Options
After plan review, use the AskUserQuestion tool to present these options:
Resume prompt (MANDATORY — AGENTS.md Communication): Before presenting the question, generate a copy-pasteable resume prompt containing: skill to run (/soleur:work), plan file path, branch name, worktree path, PR number, issue number, and a one-line summary of what was already done. Display it in a fenced code block so the user can paste it into a fresh session after /clear. This is the single most important output of the post-generation phase — without it, the user cannot resume in a new session without re-explaining context.
Question: "Plan reviewed and ready at knowledge-base/project/plans/YYYY-MM-DD-<type>-<name>-plan.md. Context is saved to disk — run /clear before /soleur:work for maximum headroom. What would you like to do next?"
Options:
Open plan in editor - Open the plan file for review
Run /deepen-plan - Enhance each section with parallel research agents (best practices, performance, UI)
Start soleur:work - Begin implementing this plan locally
Start soleur:work on remote - Begin implementing in Claude Code on the web (use & to run in background)
Create Issue - Create issue in project tracker (GitHub/Linear)
Simplify - Reduce detail level
Based on selection:
Open plan in editor → Run open knowledge-base/project/plans/<plan_filename>.md to open the file in the user's default editor
/deepen-plan → Call the /deepen-plan command with the plan file path to enhance with research
soleur:work → Use skill: soleur:work with the plan file path
soleur:work on remote → Use skill: soleur:work with knowledge-base/project/plans/<plan_filename>.md to start work in background for Claude Code web
Create Issue → See "Issue Creation" section below
Simplify → Ask "What should I simplify?" then regenerate simpler version
Other (automatically provided) → Accept free text for rework or specific changes