Skip to content

feat: scaffold-seeded plan creation and a scaffold receipt contract - #22

Merged
A merged 17 commits into
release/1.0.1from
feat/scaffold-seeded-plans
Aug 10, 2026
Merged

feat: scaffold-seeded plan creation and a scaffold receipt contract#22
A merged 17 commits into
release/1.0.1from
feat/scaffold-seeded-plans

Conversation

@A

@A A commented Aug 9, 2026

Copy link
Copy Markdown
Owner

Groom now seeds a plan directory with one booping scaffold call instead of asking the model to transcribe a literal frontmatter block, and both writers that touch a plan's frontmatter answer with the same receipt.

Changes

  • booping scaffold reports a unified diff per file it writes. A new file diffs against /dev/null; a file whose rendered content matches what is on disk produces no output. A rendered prompt can act on the receipt without reading the file back. difflib from the stdlib — scaffold's primary caller targets a vault that is not a git repository yet.
  • Per-file write semantics replace the dest-is-not-empty precondition. An existing target is skipped and named, --force overwrites the files the tree names, and a destination already holding part of the tree exits 0 instead of erroring.
  • booping frontmatter-update adopts the same stdout contract — the diff of the change it made, silence on a no-op — keeping its updated {path}: {keys} summary and errors on stderr, with arguments, flags and exit codes unchanged.
  • frontmatter-update writes scalars with their YAML type. sp=23 lands as an integer, retro=null as a YAML null; a string whose plain form would reload as another type (yes) keeps its quotes.
  • New core.groom_playbook.scaffold tree seeds index.md and an empty request.md, taking title and type from --set and created / commit from macros — so a plan carries the repo HEAD from the moment it is created rather than staying null until a sprint starts. Both --set variables render through default('') | tojson, so an omitted one cannot produce a null field or a broken document.
  • The frontmatter shape lives in exactly one place. _partials/plan_frontmatter.md, _partials/plan_structure.md and docs/template_plan_frontmatter.md are deleted; the surviving template mechanics fold into _partials/plan_templates.md, which names the frontmatter-update invocation that writes the drafter's sp and summary.
  • Scaffold documentation in documentation/project_config.md covers the third tree, the shared stdout contract, the skip rule and --force's narrowed meaning.

Review follow-ups

  • The scalar-typing, frontmatter-update receipt and scaffold receipt suites are each one parametrized test over an input/expected table instead of one function per case. Assertions got stronger: scalar rows check the reloaded value's exact type, and the append and removal rows assert the full --- / +++ / @@ header. import yaml as pyyaml moved to module level.
  • The code-review artifact and the two lessons the run produced are committed under vault/.
  • The code-review exit hook parsed an inline code_reviews: value knowing only null and ~, so a plan carrying code_reviews: [] had that [] inserted as the list's first element. It now reads the flow form, and the script — previously untested — has a test module driving it as a subprocess.

Plan: vault/plans/202608091310_scaffold-seeded-plan-creation/.

🤖 Generated with Claude Code

A and others added 17 commits August 9, 2026 13:52
…nts the same diff receipt and types its scalars
`type:` rendered raw, so a missing `--set type=` produced a YAML null with no
error and the run continued with a plan carrying no task type. It now goes
through the same `default('') | tojson` seam `title:` already used.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…t suites

Scalar typing, frontmatter-update diff receipts and scaffold stdout receipts
were one function per case. Each block is now a single parametrized test over
an input/expected table, so a new case is a row. Assertions got stronger, not
weaker: scalar rows check the reloaded value's exact type, and the append and
removal rows assert the full `--- / +++ / @@` header.

`import yaml as pyyaml` moves to module level; the eight function-local copies
are gone.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The review artifact, the plan's `code_reviews:` back-link, and two lessons the
run produced — top-level imports over lazy ones, and code-only review scope.

The back-link is hand-corrected: `frontmatter-update --append` into an empty
inline `[]` list emitted the old `[]` as the first element.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… list

The exit hook parses plan frontmatter with a regex — it is stdlib-only by
design — and its inline-value branch knew only `null` and `~`. A plan carrying
`code_reviews: []` had that `[]` inserted as the list's first element; a
populated `[a]` would have landed as one element literally named `[a]`.

`_inline_items()` now reads the flow form: `[]` yields nothing, `[a, b]` yields
its elements, `null`/`~` mean unset, anything else is a lone scalar. The hook
has no tests, so the new module drives it as a subprocess the way
`playbook-transition` does.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`0014` broadens from lazy imports alone to the project's code style practices,
picking up the parametrized-tests preference the same review raised.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@A
A merged commit deb506a into release/1.0.1 Aug 10, 2026
3 checks passed
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