Starters: one fill, at the top, and a third of the length - #243
Merged
Merged
Conversation
The starters were too much to fill in. "Lead a team" was ~230 words and asked
for {topic} in four places; filling a template meant hunting the same word
through the paragraphs, and reading one in the picker meant scrolling.
Every starter now obeys one rule, asserted by `theOneFillRule`: **at most one
{token}, appearing once, on the first line** — `Goal: {goal}` — with everything
below it fixed text that refers back ("it", "that branch"). No setting carries a
hole either: a done check with {test_command} in it was a second place to look,
so the brief asks for the command up top and the loop runs it. The composite's
children carry none, because a hole inside a carried graph is nowhere the dialog
can show and reached the child as literal text.
The leader is 98 words; the rest are 20–40. Its topic is now the loop's to
choose from the goal — one thing to fill — and the CLI flags are gone from the
prose; the loop's own instructions carry those. "Port {area} to {target}" became
"Make a change, one file at a time" with a single {task}: names are names, not
fill-in forms.
**Reaching installs that already have the old files.** The seed marker now
records a hash of what this install wrote for each starter. A file whose hash
still matches is ours to refresh when the shipped text changes; one somebody
edited hashes differently and is left alone. beta2/beta3's marker has no hashes,
so there the starter mark standing in the file is what "untouched" means — the
one launch on which an edited beta starter is refreshed too. Deleted ones stay
deleted; new ones still arrive.
That refresh exposed a latent bug: `TemplateSettings.graphJSON(for:)` was not
canonical. Key order followed per-process dictionary seeding and the graph's
project ref carried a "last opened" date minted at encode time, so a composite
template re-encoded differently on every access — every save was a spurious
diff, and the seeder would have rewritten it every launch. Keys are sorted and
the date zeroed now; `everyStarterEncodesIdentically` holds it. The composite's
own node and edge ids are fixed for the same reason (they are re-identified on
apply, so they never reach a real loop).
1501 tests (up from 1491). swiftlint 0 errors, swift-format clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MJR8Wuwc4qnaSBUMcYf7Af
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The starters were too much to fill in. Lead a team was ~230 words and asked for
{topic}in four places — filling a template meant hunting the same word through the paragraphs.One rule, asserted by a test
At most one
{token}, appearing once, on the first line — with everything below it fixed text that refers back:Goal:Test command:Branch:Area:Branch:Symbol:Symptom:Task:Task:No setting carries a hole either — a done check with
{test_command}in it was a second place to look, so the brief asks for the command up top and the loop runs it. The composite's children carry none: a hole inside a carried graph is nowhere the dialog can show, and reached the child as literal text. Port {area} to {target} became Make a change, one file at a time — names are names, not fill-in forms.Reaching installs that already have the old files
The seed marker now records a hash of what this install wrote per starter. A file whose hash still matches is ours to refresh when the shipped text changes; one you edited hashes differently and is left alone. beta2/beta3's marker has no hashes, so there a file still carrying
starter: truecounts as untouched — the one launch on which an edited beta starter is refreshed too. Deleted ones stay deleted; new ones still arrive.A latent bug that surfaced
TemplateSettings.graphJSON(for:)wasn't canonical: key order followed per-process dictionary seeding, and the graph's project ref carried a "last opened" date minted at encode time. So a composite template re-encoded differently on every access — every save was a spurious diff, and the hash-based refresh would have rewritten it every launch. Keys are sorted and the date zeroed;everyStarterEncodesIdenticallyholds it.Verification
swiftlint lint— 0 errors;swift format lint --strict— clean🤖 Generated with Claude Code
https://claude.ai/code/session_01MJR8Wuwc4qnaSBUMcYf7Af