Skip to content

Starters: one fill, at the top, and a third of the length - #243

Merged
scgopi merged 1 commit into
mainfrom
fix/short-starters
Sep 1, 2026
Merged

scgopi merged 1 commit into
mainfrom
fix/short-starters

Conversation

@scgopi

@scgopi scgopi commented Sep 1, 2026

Copy link
Copy Markdown
Owner

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: {goal}

Lead this rather than doing it all yourself. Work out what done looks like and where the work splits; give each independent piece its own goal loop, and anything that needs watching rather than finishing a timed loop. Keep the integration for yourself.

The Artifactory is the team's inbox. Post your plan there under one topic named for this goal, have every child post its result there, watch that topic, and sync whenever you come back. Finish by checking the assembled result against the goal and posting a closing note.

Starter Fill Words
Lead a team toward a goal Goal: 98
Get the build green Test command: 33
Review the diff on this branch Branch: 36
Raise test coverage Area: 38
Nightly dependency review 30
Watch the build Branch: 33
Where does this live? Symbol: 34
Why did this break? Symptom: 31
Make a change, one file at a time Task: 21
Pair on this Task: 31
Review, fix, verify 23

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: true counts 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; everyStarterEncodesIdentically holds it.

Verification

  • Build succeeds; 1501 tests in 155 suites pass (10 new)
  • swiftlint lint0 errors; swift format lint --strict — clean

🤖 Generated with Claude Code

https://claude.ai/code/session_01MJR8Wuwc4qnaSBUMcYf7Af

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
@scgopi
scgopi merged commit dbd045d into main Sep 1, 2026
1 check 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