From 75756372093bdd3d4da7b299ef67046e2631cedd Mon Sep 17 00:00:00 2001 From: graysurf <10785178+graysurf@users.noreply.github.com> Date: Sun, 8 Mar 2026 12:05:29 +0800 Subject: [PATCH] feat(skills): align plan workflow baselines and template - Extract shared plan authoring baseline for create-plan skills. - Align the shared plan template with base and rigorous execution metadata. - Reuse shared plan test helpers to reduce duplicated assertions. --- .../plan/_shared/assets/plan-template.md | 13 ++- .../workflows/plan/_shared/python/__init__.py | 5 ++ .../plan/_shared/python/plan_skill_testing.py | 27 ++++++ .../references/PLAN_AUTHORING_BASELINE.md | 87 +++++++++++++++++++ .../plan/create-plan-rigorous/SKILL.md | 52 ++++------- ...est_workflows_plan_create_plan_rigorous.py | 38 +++++--- skills/workflows/plan/create-plan/SKILL.md | 60 +++---------- .../tests/test_workflows_plan_create_plan.py | 48 ++++++---- 8 files changed, 216 insertions(+), 114 deletions(-) create mode 100644 skills/workflows/plan/_shared/python/__init__.py create mode 100644 skills/workflows/plan/_shared/python/plan_skill_testing.py create mode 100644 skills/workflows/plan/_shared/references/PLAN_AUTHORING_BASELINE.md diff --git a/skills/workflows/plan/_shared/assets/plan-template.md b/skills/workflows/plan/_shared/assets/plan-template.md index 4ad604ab..345c6477 100644 --- a/skills/workflows/plan/_shared/assets/plan-template.md +++ b/skills/workflows/plan/_shared/assets/plan-template.md @@ -2,7 +2,7 @@ ## Overview -`<2–5 sentences: what changes, what stays the same, approach>` +`<2-5 sentences: what changes, what stays the same, approach>` ## Scope @@ -15,11 +15,19 @@ ## Sprint 1: `` -**Goal**: ... **Demo/Validation**: +**Goal**: ... +**Demo/Validation**: - Command(s): ... - Verify: ... +**PR grouping intent**: `` +**Execution Profile**: `` +**TotalComplexity**: `` +**CriticalPathComplexity**: `` +**MaxBatchWidth**: `` +**OverlapHotspots**: `` + ### Task 1.1: `` - **Location**: @@ -28,6 +36,7 @@ - **Dependencies**: - `` - **Complexity**: + - `` - **Acceptance criteria**: - ... - **Validation**: diff --git a/skills/workflows/plan/_shared/python/__init__.py b/skills/workflows/plan/_shared/python/__init__.py new file mode 100644 index 00000000..056e467a --- /dev/null +++ b/skills/workflows/plan/_shared/python/__init__.py @@ -0,0 +1,5 @@ +"""Shared pytest helpers for plan workflow skills.""" + +from .plan_skill_testing import shared_plan_baseline_text, shared_plan_template_text, skill_md_text, skill_root + +__all__ = ["shared_plan_baseline_text", "shared_plan_template_text", "skill_md_text", "skill_root"] diff --git a/skills/workflows/plan/_shared/python/plan_skill_testing.py b/skills/workflows/plan/_shared/python/plan_skill_testing.py new file mode 100644 index 00000000..4be4fcd5 --- /dev/null +++ b/skills/workflows/plan/_shared/python/plan_skill_testing.py @@ -0,0 +1,27 @@ +from __future__ import annotations + +from pathlib import Path + + +def _test_file_path(test_file: str | Path) -> Path: + return Path(test_file).resolve() + + +def skill_root(test_file: str | Path) -> Path: + return _test_file_path(test_file).parents[1] + + +def skill_md_text(test_file: str | Path) -> str: + return (skill_root(test_file) / "SKILL.md").read_text(encoding="utf-8") + + +def _plan_shared_root(test_file: str | Path) -> Path: + return _test_file_path(test_file).parents[2] / "_shared" + + +def shared_plan_baseline_text(test_file: str | Path) -> str: + return (_plan_shared_root(test_file) / "references" / "PLAN_AUTHORING_BASELINE.md").read_text(encoding="utf-8") + + +def shared_plan_template_text(test_file: str | Path) -> str: + return (_plan_shared_root(test_file) / "assets" / "plan-template.md").read_text(encoding="utf-8") diff --git a/skills/workflows/plan/_shared/references/PLAN_AUTHORING_BASELINE.md b/skills/workflows/plan/_shared/references/PLAN_AUTHORING_BASELINE.md new file mode 100644 index 00000000..d4e95169 --- /dev/null +++ b/skills/workflows/plan/_shared/references/PLAN_AUTHORING_BASELINE.md @@ -0,0 +1,87 @@ +# Plan Authoring Baseline + +Shared baseline guidance for `create-plan` and `create-plan-rigorous`. + +Use this doc for the common plan-writing and executability rules. The shared +markdown template is a scaffold, not the full source of truth for workflow +policy. + +## Authoring baseline + +- Use sprints/phases that each produce a demoable or testable increment. +- Treat sprints as sequential integration gates; do not imply cross-sprint + execution parallelism. +- Break work into atomic, independently testable tasks with explicit + dependencies when execution order matters. +- Prefer within-sprint parallel lanes only when file overlap and validation + scope stay manageable. +- Include file paths whenever you can be specific. +- Include a validation step per sprint with commands, checks, and expected + outcomes. +- Include a `Risks & gotchas` section that covers ambiguity, dependency + bottlenecks, same-batch overlap hotspots, migrations, rollout, backwards + compatibility, and rollback. +- The shared template includes a `Complexity` field: + - `create-plan`: fill it when complexity materially affects + batching/splitting or when a task looks oversized. + - `create-plan-rigorous`: fill it for every task. +- The shared template also includes sprint execution placeholders: + - Grouping metadata (`PR grouping intent`, `Execution Profile`) for plans + that need explicit execution modeling. + - Rigorous scorecard fields (`TotalComplexity`, `CriticalPathComplexity`, + `MaxBatchWidth`, `OverlapHotspots`) for sizing-heavy plans. + +## Save and lint + +- Save plans to `docs/plans/-plan.md`. +- Slug rules: lowercase kebab-case, 3-6 words, end with `-plan.md`. +- Lint with: + + ```bash + plan-tooling validate --file docs/plans/-plan.md + ``` + +- Tighten the plan until validation passes. + +## Executability and grouping pass + +- Default grouping policy when the user does not request one explicitly: + metadata-first auto with `--strategy auto --default-pr-grouping group`. +- For each sprint, run: + + ```bash + plan-tooling to-json --file docs/plans/-plan.md --sprint + plan-tooling batches --file docs/plans/-plan.md --sprint + plan-tooling split-prs --file docs/plans/-plan.md --scope sprint \ + --sprint --strategy auto --default-pr-grouping group --format json + ``` + +- If the user explicitly requests deterministic/manual grouping: + - Provide explicit mapping for every task: + `--pr-group =` (repeatable). + - Validate with: + + ```bash + plan-tooling split-prs --file docs/plans/-plan.md --scope sprint --sprint --pr-grouping group --strategy deterministic --pr-group ... --format json + ``` + +- If the user explicitly requests one shared lane per sprint: + - Validate with: + + ```bash + plan-tooling split-prs --file docs/plans/-plan.md --scope sprint --sprint --pr-grouping per-sprint --strategy deterministic --format json + ``` + +- After each adjustment, rerun `plan-tooling validate` and the relevant + `split-prs` command until the plan is stable and executable. + +## Metadata guardrails + +- Metadata labels are exact and case-sensitive: + - `**PR grouping intent**: per-sprint|group` + - `**Execution Profile**: serial|parallel-xN` +- Keep metadata coherent: + - If `PR grouping intent` is `per-sprint`, do not declare parallel width + `>1`. + - If planning multi-lane parallel execution, set `PR grouping intent` to + `group`. diff --git a/skills/workflows/plan/create-plan-rigorous/SKILL.md b/skills/workflows/plan/create-plan-rigorous/SKILL.md index 74fc08c6..12ce3b0d 100644 --- a/skills/workflows/plan/create-plan-rigorous/SKILL.md +++ b/skills/workflows/plan/create-plan-rigorous/SKILL.md @@ -7,8 +7,8 @@ description: # Create Plan (Rigorous) -Same as `create-plan`, but more rigorous: add per-task complexity notes, explicitly track dependencies, and get a subagent review before -finalizing. +Build on the `create-plan` baseline, but require explicit execution modeling: +per-task complexity, per-sprint scorecards, tighter sizing guardrails, and subagent review before finalizing. ## Contract @@ -59,57 +59,35 @@ Failure modes: 1. Draft the plan (do not implement) -- Same structure as `create-plan`, plus: +- Follow the shared baseline in `skills/workflows/plan/_shared/references/PLAN_AUTHORING_BASELINE.md`. +- Rigorous deltas: - Fill a per-task **Complexity** score (1–10). - - Explicitly list dependencies and parallelizable tasks. + - Make dependencies explicit for every task and call out parallelizable work when it helps execution planning. - Treat each sprint as an integration gate; do not plan cross-sprint execution parallelism. - Focus parallelization design inside each sprint (task/PR dependency graph), not across sprints. - - Add sprint metadata lines with exact case-sensitive labels: + - Record sprint metadata for every sprint with these exact labels: - `**PR grouping intent**: per-sprint|group` - `**Execution Profile**: serial|parallel-xN` - - Keep grouping/profile metadata coherent: - - If `PR grouping intent` is `per-sprint`, do not declare parallel width `>1`. - - If planning multi-lane parallel PR execution, set `PR grouping intent` to `group`. - Add a “Rollback plan” that is operationally plausible. 1. Save the plan -- Path: `docs/plans/-plan.md` (kebab-case, end with `-plan.md`). +- Use the shared save rules from `skills/workflows/plan/_shared/references/PLAN_AUTHORING_BASELINE.md`. 1. Lint the plan (format + executability) -- Run: `plan-tooling validate --file docs/plans/-plan.md` +- Use the shared lint flow from `skills/workflows/plan/_shared/references/PLAN_AUTHORING_BASELINE.md`. - Fix until it passes (no placeholders in required fields; explicit validation commands; dependency IDs exist). +1. Run the shared executability + grouping pass (mandatory) + +- Use the shared executability + grouping workflow in `skills/workflows/plan/_shared/references/PLAN_AUTHORING_BASELINE.md`. + 1. Run a sizing + parallelization pass (mandatory) - Parallelization policy for this skill: - `Sprint` is an integration/decision gate. Do not schedule cross-sprint execution parallelism. - Optimize for parallel execution inside a sprint by improving the task DAG (dependencies, file overlap, PR grouping). -- For each sprint, run: - - ```bash - plan-tooling to-json --file docs/plans/-plan.md --sprint - plan-tooling batches --file docs/plans/-plan.md --sprint - plan-tooling split-prs --file docs/plans/-plan.md --scope sprint \ - --sprint --strategy auto --default-pr-grouping group --format json - ``` - -- If planning explicit deterministic/manual grouping for a sprint: - - Provide explicit mapping for every task: `--pr-group =` (repeatable). - - Validate with: - - ```bash - plan-tooling split-prs --file docs/plans/-plan.md --scope sprint --sprint --pr-grouping group --strategy deterministic --pr-group ... --format json - ``` - -- If planning explicit single-lane-per-sprint behavior: - - Validate with: - - ```bash - plan-tooling split-prs --file docs/plans/-plan.md --scope sprint --sprint --pr-grouping per-sprint --strategy deterministic --format json - ``` - - Metadata guardrails: - Metadata field names are strict; do not use variants such as `PR Grouping Intent`. - `plan-tooling validate` now blocks metadata mismatch by default (`per-sprint` cannot pair with parallel width `>1`). @@ -183,10 +161,14 @@ Failure modes: ## Plan Template -Shared template (single source of truth): +Shared markdown scaffold: - `skills/workflows/plan/_shared/assets/plan-template.md` +Canonical shared authoring and validation rules: + +- `skills/workflows/plan/_shared/references/PLAN_AUTHORING_BASELINE.md` + Rigorous requirement: - Fill `Complexity` for every task (int 1–10). diff --git a/skills/workflows/plan/create-plan-rigorous/tests/test_workflows_plan_create_plan_rigorous.py b/skills/workflows/plan/create-plan-rigorous/tests/test_workflows_plan_create_plan_rigorous.py index 298059a3..9d877737 100644 --- a/skills/workflows/plan/create-plan-rigorous/tests/test_workflows_plan_create_plan_rigorous.py +++ b/skills/workflows/plan/create-plan-rigorous/tests/test_workflows_plan_create_plan_rigorous.py @@ -2,7 +2,8 @@ from pathlib import Path -from skills._shared.python.skill_testing import assert_entrypoints_exist, assert_skill_contract +from skills._shared.python.skill_testing import assert_skill_contract +from skills.workflows.plan._shared.python import shared_plan_baseline_text, shared_plan_template_text, skill_md_text def test_workflows_plan_create_plan_rigorous_contract() -> None: @@ -10,19 +11,27 @@ def test_workflows_plan_create_plan_rigorous_contract() -> None: assert_skill_contract(skill_root) -def _skill_md_text() -> str: - return (Path(__file__).resolve().parents[1] / "SKILL.md").read_text(encoding="utf-8") - - def test_create_plan_rigorous_forbids_cross_sprint_parallel_execution() -> None: - text = _skill_md_text() - assert "do not plan cross-sprint execution parallelism." in text.lower() + text = skill_md_text(__file__) + shared = shared_plan_baseline_text(__file__) + + assert "PLAN_AUTHORING_BASELINE.md" in text + assert "Treat sprints as sequential integration gates" in shared + assert "do not imply cross-sprint" in shared.lower() assert "Do not schedule cross-sprint execution parallelism." in text - assert "Treat sprints as sequential integration gates" in text + assert "Build on the `create-plan` baseline" in text + + +def test_create_plan_rigorous_requires_metadata_for_every_sprint() -> None: + text = skill_md_text(__file__) + + assert "Record sprint metadata for every sprint" in text + assert "`**PR grouping intent**: per-sprint|group`" in text + assert "`**Execution Profile**: serial|parallel-xN`" in text def test_create_plan_rigorous_defines_pr_and_sprint_complexity_guardrails() -> None: - text = _skill_md_text() + text = skill_md_text(__file__) assert "PR complexity target is `2-5`; preferred max is `6`." in text assert "PR complexity `7-8` is an exception and requires explicit justification" in text assert "PR complexity `>8` should be split before execution planning." in text @@ -33,8 +42,17 @@ def test_create_plan_rigorous_defines_pr_and_sprint_complexity_guardrails() -> N assert "`parallel-x3`: target `4-6` tasks, `TotalComplexity 16-24`" in text +def test_shared_plan_template_includes_rigorous_scorecard_placeholders() -> None: + shared = shared_plan_template_text(__file__) + + assert "**TotalComplexity**: ``" in shared + assert "**CriticalPathComplexity**: ``" in shared + assert "**MaxBatchWidth**: ``" in shared + assert "**OverlapHotspots**: ``" in shared + + def test_create_plan_rigorous_high_complexity_task_policy_requires_split_or_dedicated_lane() -> None: - text = _skill_md_text() + text = skill_md_text(__file__) assert "For a task with complexity `>=7`, try to split first" in text assert "keep it as a dedicated lane and dedicated PR" in text assert "at most one task with complexity `>=7` per sprint" in text diff --git a/skills/workflows/plan/create-plan/SKILL.md b/skills/workflows/plan/create-plan/SKILL.md index 4ec5ce61..9a9a879f 100644 --- a/skills/workflows/plan/create-plan/SKILL.md +++ b/skills/workflows/plan/create-plan/SKILL.md @@ -57,76 +57,36 @@ Failure modes: 1. Write the plan (do not implement) -- Use sprints/phases that each produce a demoable/testable increment. -- Treat sprints as sequential integration gates; do not imply cross-sprint execution parallelism. -- Break work into atomic, independently testable tasks with explicit dependencies when execution order matters. -- Prefer within-sprint parallel lanes only when file overlap and validation scope stay manageable. -- Include file paths whenever you can be specific. -- Include a validation step per sprint (commands, checks, expected outcomes). +- Follow the shared baseline in `skills/workflows/plan/_shared/references/PLAN_AUTHORING_BASELINE.md`. - Fill `Complexity` when it materially affects batching/splitting or when a task looks oversized. +- You may omit sprint scorecards unless the user explicitly wants deeper sizing analysis or execution modeling. 1. Save the plan file -- Path: `docs/plans/-plan.md` -- Slug rules: lowercase kebab-case, 3–6 words, end with `-plan.md`. +- Use the shared save rules from `skills/workflows/plan/_shared/references/PLAN_AUTHORING_BASELINE.md`. 1. Lint the plan (format + executability) -- Run: `plan-tooling validate --file docs/plans/-plan.md` -- If it fails: tighten tasks (missing fields, placeholders, unclear validations) until it passes. +- Use the shared lint flow from `skills/workflows/plan/_shared/references/PLAN_AUTHORING_BASELINE.md`. 1. Run an executability + grouping pass (mandatory) -- Default grouping policy for this skill: - - If the user did not explicitly request grouping behavior, validate with metadata-first auto - (`--strategy auto --default-pr-grouping group`). -- For each sprint, run: - - ```bash - plan-tooling to-json --file docs/plans/-plan.md --sprint - plan-tooling batches --file docs/plans/-plan.md --sprint - plan-tooling split-prs --file docs/plans/-plan.md --scope sprint \ - --sprint --strategy auto --default-pr-grouping group --format json - ``` - -- If the user explicitly requests deterministic/manual grouping: - - Provide explicit mapping for every task: `--pr-group =` (repeatable). - - Validate with: - - ```bash - plan-tooling split-prs --file docs/plans/-plan.md --scope sprint --sprint --pr-grouping group --strategy deterministic --pr-group ... --format json - ``` - -- If the user explicitly requests one shared lane per sprint: - - Validate with: - - ```bash - plan-tooling split-prs --file docs/plans/-plan.md --scope sprint --sprint --pr-grouping per-sprint --strategy deterministic --format json - ``` - -- When you add sprint metadata for grouping/parallelism, use exact case-sensitive labels: - - `**PR grouping intent**: per-sprint|group` - - `**Execution Profile**: serial|parallel-xN` -- Keep metadata coherent: - - If `PR grouping intent` is `per-sprint`, do not declare parallel width `>1`. - - If planning multi-lane parallel execution, set `PR grouping intent` to `group`. -- After each adjustment, rerun `plan-tooling validate` and the relevant `split-prs` command until the plan is stable and executable. +- Use the shared executability + grouping workflow in `skills/workflows/plan/_shared/references/PLAN_AUTHORING_BASELINE.md`. +- Add sprint metadata only when the plan needs explicit grouping/parallelism metadata or the user asks for that level of execution detail. 1. Review “gotchas” -- After saving, add/adjust a “Risks & gotchas” section: ambiguity, dependency bottlenecks, same-batch overlap hotspots, migrations, rollout, - backwards compatibility, and rollback. +- Use the shared `Risks & gotchas` guidance from `skills/workflows/plan/_shared/references/PLAN_AUTHORING_BASELINE.md`. ## Plan Template -Shared template (single source of truth): +Shared markdown scaffold: - `skills/workflows/plan/_shared/assets/plan-template.md` -When a plan needs explicit grouping/parallelism metadata, extend each sprint with these exact labels: +Canonical shared authoring and validation rules: -- `**PR grouping intent**: per-sprint|group` -- `**Execution Profile**: serial|parallel-xN` +- `skills/workflows/plan/_shared/references/PLAN_AUTHORING_BASELINE.md` Optional scaffold helper (creates a placeholder plan; fill it before linting): diff --git a/skills/workflows/plan/create-plan/tests/test_workflows_plan_create_plan.py b/skills/workflows/plan/create-plan/tests/test_workflows_plan_create_plan.py index b4518d9d..e77d7c6e 100644 --- a/skills/workflows/plan/create-plan/tests/test_workflows_plan_create_plan.py +++ b/skills/workflows/plan/create-plan/tests/test_workflows_plan_create_plan.py @@ -2,7 +2,8 @@ from pathlib import Path -from skills._shared.python.skill_testing import assert_entrypoints_exist, assert_skill_contract +from skills._shared.python.skill_testing import assert_skill_contract +from skills.workflows.plan._shared.python import shared_plan_baseline_text, shared_plan_template_text, skill_md_text def test_workflows_plan_create_plan_contract() -> None: @@ -10,23 +11,36 @@ def test_workflows_plan_create_plan_contract() -> None: assert_skill_contract(skill_root) -def _skill_md_text() -> str: - return (Path(__file__).resolve().parents[1] / "SKILL.md").read_text(encoding="utf-8") +def test_create_plan_references_shared_plan_baseline_for_executability_rules() -> None: + text = skill_md_text(__file__) + shared = shared_plan_baseline_text(__file__) + assert "PLAN_AUTHORING_BASELINE.md" in text + assert "plan-tooling to-json --file docs/plans/-plan.md --sprint " in shared + assert "plan-tooling batches --file docs/plans/-plan.md --sprint " in shared + assert "--strategy auto --default-pr-grouping group --format json" in shared + assert "--pr-grouping group --strategy deterministic --pr-group ... --format json" in shared + assert "--pr-grouping per-sprint --strategy deterministic --format json" in shared -def test_create_plan_requires_plan_tooling_executability_pass() -> None: - text = _skill_md_text() - assert "plan-tooling to-json --file docs/plans/-plan.md --sprint " in text - assert "plan-tooling batches --file docs/plans/-plan.md --sprint " in text - assert "--strategy auto --default-pr-grouping group --format json" in text - assert "--pr-grouping group --strategy deterministic --pr-group ... --format json" in text - assert "--pr-grouping per-sprint --strategy deterministic --format json" in text +def test_create_plan_keeps_base_skill_policies_local_while_using_shared_cross_sprint_rules() -> None: + text = skill_md_text(__file__) + shared = shared_plan_baseline_text(__file__) -def test_create_plan_documents_grouping_metadata_and_cross_sprint_policy() -> None: - text = _skill_md_text() - assert "Treat sprints as sequential integration gates" in text - assert "do not imply cross-sprint execution parallelism." in text.lower() - assert "`**PR grouping intent**: per-sprint|group`" in text - assert "`**Execution Profile**: serial|parallel-xN`" in text - assert "If `PR grouping intent` is `per-sprint`, do not declare parallel width `>1`." in text + assert "Treat sprints as sequential integration gates" in shared + assert "do not imply cross-sprint" in shared.lower() + assert "execution parallelism" in shared.lower() + assert "`**PR grouping intent**: per-sprint|group`" in shared + assert "`**Execution Profile**: serial|parallel-xN`" in shared + assert "If `PR grouping intent` is `per-sprint`, do not declare parallel width" in shared + assert "`>1`." in shared + assert "Add sprint metadata only when the plan needs explicit grouping/parallelism metadata" in text + assert "You may omit sprint scorecards unless the user explicitly wants deeper sizing analysis" in text + + +def test_shared_plan_template_includes_optional_base_execution_metadata() -> None: + shared = shared_plan_template_text(__file__) + + assert "**PR grouping intent**: ``" in shared + assert "**Execution Profile**: ``" in shared + assert "" in shared