Skip to content

feat(assets): ship a plan-run skill that drives a whole plan group by group - #11

Merged
protonspy merged 1 commit into
mainfrom
feat/plan-run-skill
Aug 3, 2026
Merged

protonspy merged 1 commit into
mainfrom
feat/plan-run-skill

Conversation

@protonspy

Copy link
Copy Markdown
Owner

What changed

scc scaffolds a seventh skill, plan-run, with a /scc-plan-run command wherever the harness has a command surface. It runs a plan in plans/ to the end, one merged PR per group: green main → branch → implement → deliver per delivery.md → CI → merge → pull → next group.

A group is the smallest part of a plan that can merge alone — a leaf under ## Decomposition, or a family of task numbers sharing a major number. Order is the written order unless ## Notes says otherwise.

1. A second skill category

assets.WorkflowSkills sits beside KnowledgeSkills; Skills() is what Workspace() iterates. The skill directory and its command still derive from one list, so they cannot drift apart. KnowledgeSkills' documented rule — one skill per docs/ artifact a validator checks — stays true of that list rather than being quietly widened.

Template version 6 → 7 is what carries this into workspaces that already exist.

2. The loop asks the developer how it should run

Once, after reporting the groups, because the answers are only meaningful to someone who can see what they are agreeing to:

Question Recorded
Straight through, or stop at each group? autonomy: auto | gated
A worktree per group, or the current checkout? worktree: per-group | in-place
Once the PR is open — wait and merge, merge now, or stop? ci + merge: auto | manual

The four answers go into the plan's frontmatter so a resumed session reads them instead of asking twice. plan validates worktree and merge only when present — a plan no loop has run over is not a plan with a defect.

Anything the frontmatter already records is shown as a proposed answer to confirm, not as decided: autonomy/ci were answered for authoring the plan, and agreeing to a loop that opens and merges PRs for hours is a larger thing.

Considered and rejected: having the loop override ci: no-wait, on the argument that every later group branches from an unverified base. The argument is sound and the developer still gets to weigh it — the skill states the cost at the moment of the question instead.

3. Skills name a rule by its path from the workspace root

Pre-existing, and it affected all six knowledge skills. They linked ../../rules/knowledge-base.md; an agent reads files from the root, so the path it can act on is .claude/rules/knowledge-base.md (expanded per harness).

It must be inline code, not a Markdown link: checkSkillReferences resolves a link against the skill's own directory and holds it to the Agent Skills one-level-deep rule, so the same path written as a link produces two findings against scc's own scaffold. Inline code is correct to read and invisible to the link check.

How it was verified

  • gofmt -l clean, go vet, full go test green. -race did not run locally (no cgo on the dev machine) — CI covers it on Linux/macOS.
  • update into a pre-existing workspace, the path this actually ships on: scaffolded a tree with the binary built from b9cd3fc (template v6), ran the new binary's update → exactly create (2), everything else untouched, CLAUDE.md correctly reported as the user's and left alone.
  • scc validate on a freshly scaffolded workspace carrying a plan with all four answers: no findings, exit 0. Invalid values (worktree: yes, merge: whenever) → two plan.loop-invalid, exit 2.
  • Rendered and eyeballed in all three harnesses; the reference reads .claude/, .codex/, .opencode/rules/delivery.md respectively.
  • The new guard was tested by regressing it on purpose: reintroducing ../../rules/ in stack fails TestSkillsNameRulesByTheirHarnessPath across all three harnesses, and restoring it goes green.

Tests added

  • TestApplyUpdateAddsASkillTheWorkspacePredates — a skill new in this version reaches an existing workspace, in every harness, and a second update is a no-op. Reads from WorkflowSkills, so the next workflow skill is covered the day it is added.
  • TestSkillsNameRulesByTheirHarnessPath — catches what no validator can see: a ../.. inside a code span is silently useless to whoever reads it.
  • TestPlanLoopAnswers / TestPlanLoopAnswersAreOptional.

Not done

No review subagents were run on this diff — the author asked for PR → CI → merge directly. design/orchestration.md §6 records the decisions, including the rejected override and why two link forms cannot coexist.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Gcd47SbcukuKzkDawyTjPt

… group

delivery.md ends at one merged pull request, because that is where one unit of
work ends. Running a whole plan is the loop above that, and no rule held it:
picking the next group, branching each one from the merge the last produced, and
recovering the position from `main` when a session dies mid-plan.

Three parts:

- A new skill category. `assets.WorkflowSkills` sits beside `KnowledgeSkills` and
  `Skills()` is what `Workspace()` derives from, so the skill directory and its
  `/scc-plan-run` command still come from one list and cannot drift. The template
  version bump is what carries it into workspaces that already exist — verified
  against a tree scaffolded by the previous build, where `update` reports exactly
  two creates and leaves everything else alone.

- The loop asks the developer how to run, once, after reporting the groups. How a
  plan gets executed is not scc's default to infer: automatic or gated, a worktree
  per group or the current checkout, and what happens once each PR is open. The
  four answers go back into the plan's frontmatter so a resumed session reads them
  instead of asking twice, and `plan` validates the two new keys only when present.
  The alternative considered was overriding `ci: no-wait` inside a loop, since
  every later group inherits that base; rejected, because stating the cost is how a
  tool respects a decision it disagrees with.

- Skills name a rule by its path from the workspace root, not by walking out of
  their own directory. An agent reads from the root, so `.claude/rules/x.md` is the
  path it can act on. It has to be inline code rather than a link, because `skill`
  resolves a link against the skill's own directory and holds it to the Agent
  Skills one-level-deep rule — as a link the same path would fail scc's own
  validator. Both halves are guarded: the existing fresh-artifacts test catches the
  link form, and a new test catches the `../..` a code span would hide.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gcd47SbcukuKzkDawyTjPt
@protonspy
protonspy merged commit 50bfc94 into main Aug 3, 2026
4 checks passed
@protonspy
protonspy deleted the feat/plan-run-skill branch August 3, 2026 03:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant