marketplace/bundles/plan-marshall/skills/plan-marshall/SKILL.md
Unified plan lifecycle management - create, outline, execute, verify, and finalize plans
npx skillsauth add cuioss/plan-marshall plan-marshallInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Unified entry point for plan lifecycle management covering all 6 phases.
Execution mode: Route action to workflow document, then follow workflow instructions step-by-step.
Prohibited actions:
.plan/ files directly — all access must go through python3 .plan/execute-script.py manage-* scriptsTask: general-purpose) for any work inside a phase (1-init through 6-finalize). Use plan-marshall:execution-context-{level} with a workflow: notation pointing at the workflow doc, or inline main-context execution. A generic subagent has no plan-marshall enforcement context, inherits broad tool access, and will violate workflow hard rules. Subagent rules propagate through the agent definition, not through the caller's prompt.Constraints:
python3 .plan/execute-script.py commandinit_without_asking, plan_without_asking, execute_without_asking) must be respected — never skip when config is falseAskUserQuestion tool with proper YAML structuremanage-status transition — never set phase status directlyCRITICAL: USE ONLY THIS SKILL'S PLAN SYSTEM
This skill implements its OWN plan system. You must:
plan-marshall:manage-* skills1-init -> 2-refine -> 3-outline -> 4-plan -> 5-execute -> 6-finalize
| Parameter | Type | Description |
|-----------|------|-------------|
| action | optional | Explicit action: list, init, outline, execute, finalize, cleanup, lessons, lessons-aggregate, recipe. When omitted, the action is inferred from other parameters — see Action Resolution. |
| task | optional | Task description for creating new plan. Implies action=init when no explicit action is given. |
| issue | optional | GitHub issue URL for creating new plan. Implies action=init when no explicit action is given. |
| lesson | optional | Lesson ID to convert to plan. Implies action=lessons when no explicit action is given. |
| recipe | optional | Recipe key for creating plan from predefined recipe. Implies action=recipe when no explicit action is given. |
| plan | optional | Plan name for specific operations (e.g., jwt-auth, not path). When supplied without an explicit action, the action is auto-detected from the plan's current phase. |
Note: The plan parameter accepts the plan name (plan_id) only, not the full path.
Load foundational development practices before any phase work:
Skill: plan-marshall:dev-agent-behavior-rules
Resolve the effective action in the following order. The first matching rule wins; stop at the first match.
action= parameter — use it as-is. If the value is not in the action table below, return status: error with a remediation message naming the valid actions.plan= without action= — auto-detect from the plan's current phase (see Auto-Detect from Phase below).task= or issue= without action= — imply action=init. The supplied value becomes the plan source (task or issue respectively).lesson= without action= — imply action=lessons. The supplied lesson ID seeds the lessons workflow.recipe= without action= — imply action=recipe. The supplied recipe key seeds the recipe workflow.action=list (interactive menu).Ambiguity guard: if two or more source-providing parameters from {task, issue, lesson, recipe, plan} are supplied without an explicit action=, return status: error with a message naming the conflicting parameters and asking the user to either pass an explicit action= or remove one of the conflicting values.
Once the action is resolved, load the appropriate workflow document and follow its instructions:
| Action | Workflow Document | Description |
|--------|-------------------|-------------|
| list (default) | Read workflow/planning.md | List all plans |
| init | Read workflow/planning.md | Create new plan, auto-continue to refine |
| outline | Read workflow/planning-outline.md | Run outline and plan phases |
| cleanup | Read workflow/planning.md | Remove completed plans |
| lessons | Read workflow/planning.md | List and convert lessons |
| lessons-aggregate | Read workflow/planning-lessons-aggregate.md | Aggressive cross-lesson aggregation + superseded-stub prune in a single command |
| execute | Read workflow/execution.md | Execute implementation tasks + verification |
| finalize | Read workflow/execution.md | Commit, push, PR |
| recipe | Read workflow/recipe.md | Create plan from predefined recipe |
When plan is specified but no action, auto-detect from plan phase.
Cross-session re-entry preflight (re-anchor to worktree). A fresh session that enters with plan={plan_id} from the main checkout may be targeting a phase-5+ plan whose directory was MOVED into its worktree at phase-5 move-in (ADR-002 move-based model). In that state the plan dir is no longer on main, so a get-routing-context --plan-id {plan_id} run from main resolves nothing and fails with plan_not_found. Before the routing call, resolve where the plan dir currently lives and re-anchor cwd into the worktree when needed:
python3 .plan/execute-script.py plan-marshall:workflow-integration-git:git-workflow locate-plan-checkout \
--plan-id {plan_id}
(See workflow-integration-git SKILL.md Canonical invocations → locate-plan-checkout for the verb's argparse surface and the three-state output contract.) Branch on the returned location:
location == worktree — the plan dir was moved into the worktree carried in worktree_path. Log a [STATUS] re-anchor decision, then issue a STANDALONE cd {worktree_path} Bash call (exactly one command — no &&, no chaining), and re-run get-routing-context from inside the worktree. After the cd, cwd is pinned to the worktree and the single uniform cwd-relative rule resolves every subsequent .plan/ lookup to the worktree-resident copy.location == current — the plan dir is on the current checkout (a main-checkout plan, or an already-cwd-pinned worktree). Proceed unchanged to the routing call below; do NOT cd.location == not_found — neither the current checkout nor any registered worktree holds the plan dir. Emit the existing plan_not_found error.The preflight is idempotent: a session already cwd-pinned inside the worktree resolves current (the verb's on-disk probe finds the plan dir on the current checkout), so there is no double-cd. It runs from the main checkout using main's present executor — main's .plan/execute-script.py stays present and untouched throughout phase-5+ (per PR-558, the executor is per-tree derived state generated into the worktree at move-in, never removed from main).
python3 .plan/execute-script.py plan-marshall:manage-status:manage-status get-routing-context \
--plan-id {plan_id}
| Current Phase | Workflow Document | Action |
|---------------|-------------------|--------|
| 1-init | Read workflow/planning.md | init |
| 2-refine | Read workflow/planning.md | init (continues refine) |
| 3-outline | Read workflow/planning-outline.md | outline |
| 4-plan | Read workflow/planning-outline.md | outline (continues plan) |
| 5-execute | Read workflow/execution.md | execute |
| 6-finalize | Read workflow/execution.md | finalize |
After determining the action and workflow document:
workflow/planning.md or workflow/execution.md)# List all plans (interactive selection)
/plan-marshall
# Create new plan from task description (action=init implied by task=)
/plan-marshall task="Add user authentication"
# Create new plan from GitHub issue (action=init implied by issue=)
/plan-marshall issue="https://github.com/org/repo/issues/42"
# Outline specific plan
/plan-marshall action=outline plan="user-auth"
# Execute specific plan
/plan-marshall action=execute plan="jwt-auth"
# Finalize (commit, PR)
/plan-marshall action=finalize plan="jwt-auth"
# Auto-detect: continues from current phase
/plan-marshall plan="jwt-auth"
# Cleanup completed plans
/plan-marshall action=cleanup
# List lessons and convert to plan
/plan-marshall action=lessons
# Convert specific lesson to plan (action=lessons implied by lesson=)
/plan-marshall lesson="2026-05-18-11-001"
# Aggressive cross-lesson aggregation + superseded-stub prune in one batch
/plan-marshall action=lessons-aggregate
# Create plan from predefined recipe — lists available recipes for selection
/plan-marshall action=recipe
# Create plan from specific recipe (action=recipe implied by recipe=)
/plan-marshall recipe="refactor-to-standards"
# Explicit action= always wins over implicit inference
/plan-marshall action=init task="Add user authentication"
If you discover issues or improvements during execution, record them:
Skill: plan-marshall:manage-lessonsbug, improvement, or anti-pattern and component in {bundle}:{skill} notation (e.g., plan-marshall:manage-tasks)The plan-marshall hooks can drive a live session-tab title (plan + phase + status icon). The writer side publishes {plan_dir}/title-body.txt on every status mutation — no user configuration is required. The reader side is implemented per-target by the platform runtime (session render-title operation); see plan-marshall:platform-runtime for the reader contract.
Main-context skill calls that need the current session ID (e.g., phase-6-finalize forwarding it to manage-metrics enrich) capture it via the platform-runtime session capture operation, which stores it in status.json at plan-init time. Retrieval: manage-status metadata --get --field session_id.
Phase transitions are guarded by a registry of invariants captured at every phase boundary; see references/phase-handshake.md for the full narrative, the registry table, and the resolution rules. Two registry rows drive the blocking-finding gate:
| Row | Behavior at every boundary | Behavior at guarded boundaries |
|-----|----------------------------|--------------------------------|
| pending_findings_by_type | per-type breakdown of pending findings (passive — never raises) | identical (passive) |
| pending_findings_blocking_count | sum of pending counts across the per-phase blocking partition | raises BlockingFindingsPresent when the count is non-zero — capture refuses to persist a row, gating the boundary |
The blocking partition is configured per-phase in marshal.json at plan.phase-{phase}.blocking_finding_types (a list of finding-type strings). marshall-steward seeds a default partition on first wizard run; see marshall-steward/SKILL.md for the seed step.
Guarded boundaries (the only points where the strict-verify check refuses to advance):
5-execute → 6-finalize (covers the phase-level transition)automated-review → branch-cleanup (intra-finalize)sonar-roundtrip → next (intra-finalize)Every other capture point — phases 1-init through 5-execute and any other finalize sub-step — captures the rows passively for retrospective analysis without blocking the transition.
The resolutions counted as resolved (and therefore non-blocking) are: fixed, suppressed, accepted, taken_into_account. Only pending contributes to the count.
The canonical argparse surface for phase_handshake.py (the skill's CLI entry-point; effort_presets.py is an imported library, not an executor-callable CLI). The plugin-doctor analyzer (_analyze_manage_invocation.py) reads this section as source-of-truth for the manage-invocation-invalid and missing-canonical-block rules. Consuming docs xref this section by name instead of restating the command inline. See pm-plugin-development:plugin-script-architecture cross-skill-integration.md § "Script invocation in documentation".
python3 .plan/execute-script.py plan-marshall:plan-marshall:phase_handshake capture \
--plan-id PLAN_ID --phase {1-init,2-refine,3-outline,4-plan,5-execute,6-finalize} \
[--override] [--reason REASON]
--reason is required when --override is set.
python3 .plan/execute-script.py plan-marshall:plan-marshall:phase_handshake verify \
--plan-id PLAN_ID --phase {1-init,2-refine,3-outline,4-plan,5-execute,6-finalize} [--strict]
python3 .plan/execute-script.py plan-marshall:plan-marshall:phase_handshake list --plan-id PLAN_ID
python3 .plan/execute-script.py plan-marshall:plan-marshall:phase_handshake clear \
--plan-id PLAN_ID --phase {1-init,2-refine,3-outline,4-plan,5-execute,6-finalize}
| Skill | Purpose |
|-------|---------|
| plan-marshall:manage-status | Status storage (phases, metadata) |
| plan-marshall:phase-1-init | Init phase implementation |
| plan-marshall:phase-3-outline | Outline phase implementation |
| plan-marshall:phase-6-finalize | Finalize phase implementation |
| plan-marshall:extension-api | Extension API and extension points for domain customization |
| Agent | Purpose |
|-------|---------|
| plan-marshall:execution-context | Generic dispatcher: loads caller-specified skills + workflow doc and follows it |
tools
Plan-marshall-domain implementor of the ext-self-review-{domain} extension point. Surfaces deterministic candidates (regexes, user-facing strings, markdown sections, symmetric-pair functions, flag-guard pairs, contract sources, schema-bearing files) for pre-submission structural self-review.
development
The single shared contract every untrusted-external-content ingestion surface loads — reader/orchestrator/writer isolation, the deterministic validator script as the containment boundary, and the output-schema discipline for candidate structs parsed from web pages, GitHub issue/PR/comment bodies, and Sonar issue messages
development
Domain-invariant recipe for deliberate wide-scope simplification campaigns across a scope x thoroughness cell, with a T4+ relation-graph pre-deliverable
testing
A test skill for README generation