Skip to content

Init new profile (spec 38) - #71

Merged
llima merged 26 commits into
mainfrom
feat/init-new-profile
Oct 19, 2026
Merged

llima merged 26 commits into
mainfrom
feat/init-new-profile

Conversation

@llima

@llima llima commented Oct 19, 2026

Copy link
Copy Markdown
Owner

Summary

  • Version bumped to 0.34.0 (a minor, spec 38 Ruling 6). Merging publishes craftar@0.34.0 to npm after approval in the npm environment.
  • craftar init --new-profile <name> [--like <profile>] creates the profile first — one new file, profiles/<name>/profile.yaml, in the Forge's working tree, holding name, recipes and targets only — then starts the workspace on it. Nothing is committed, no branch is made and nothing is pushed (Ruling 1). With --new-profile, --add-recipe, --remove-recipe, --replace and --targets shape the profile, and craftar.yaml gets no recipes and no targets.
  • --like copies the template's written recipes and targets only (Ruling 2). In a Forge at schema 3 or above, recipes that only the template's integrations block selects are left behind with one note (Ruling 3). A recipe named for another profile is refused (P10, Ruling 4).
  • init becomes a gated Forge writer of one path. The gate (P5–P8) refuses a cache tree, a directory that is not a git repository with a commit, a name or profiles/<name> that exists, a path git ignores, and a symbolic link on the way. The profile directory is journalled, created with a non-recursive mkdir, and the file is written wx. The Forge is then read back from disk and must plan the same bytes before craftar.yaml is written. A late failure prints git -C <forge> clean -fd -- profiles/<name>.
  • In a terminal, the profile list offers 0) a new profile, and a Forge directory with no profile goes straight to the new profile's questions (Ruling 5).
  • No emitted byte, lock, registry entry or --json shape changes. No Upgrading block.

Built as spec 38 recommends, not yet ruled (§13)

  • §13.1 items 2, 3, 4, 5, 9 and 10.
  • §13.2 items 11–21.
  • Item 4 is the second plan from disk: one more load-by-source, on purpose. The workspace rule node-cli.md and its reviewer agent gain that sentence after this PR, together with init as a gated writer.

Departures from spec 38's text (recorded at the spec refresh)

  • The writes of §5.3 live in a core module (src/core/new-profile-write.ts) with injected seams (WriteHooks), so the race and the second proof are tested in-process. There is no environment back door.
  • P12 is the resolver's own refusal; a missing ingredient stays a warning.
  • P5 fails closed on any error except a missing forges/.
  • Names YAML would misread (123, null, true) are quoted in the file, and the file is read back through ProfileSchema before any write.
  • A local recipes or targets is said, not asked, and stays a workspace layer.
  • Every refusal in the interactive recipes step is re-asked. The one exception is a template that brings an owned recipe while craftar.local.yaml sets recipes: that ends on P10, as the flags mode does.

Test plan

  • npm run typecheck — exit 0 (0f7e031, after the bump and a rebase onto 6eeaeae — the 25 commits identical by range-diff)
  • npm run build — exit 0; craftar --version prints 0.34.0
  • npm test (vitest --maxWorkers=6, without test/ci.test.ts) on 0f7e031 — 136 files passed, 1 skipped; 3366 tests passed, 10 skipped. Oracle skipped (no fixture); no emitter, plan or status byte path changed.
  • Pins written first (test/init-new-profile-pins.test.ts): init's both-flags stdout byte for byte, and today's re-ask on the answer 0.
  • Every new test was seen failing first against unchanged src/.
  • The late failures at the CLI were produced with read-only directories (Linux only, skipIf(win32)).
  • CI green on Linux and Windows.
  • Coded, not tested: craftar.yaml losing its wx race to N1 after the profile was written. There is no seam between the two writes.
  • Not run by the suite, and not tested by hand: the interactive mode in a real terminal (spec 28's gap) — the 0) entry, the questions, the re-asks, the confirmation.
  • By hand, not run: two real processes racing on one name; the link-to-a-file case on Windows; P8 on a case-insensitive disk.

llima added 26 commits October 18, 2026 21:34
…0` re-ask before spec 38

Written first, as spec 38 §10 asks: --new-profile and the `0)` entry must leave both as they are.
…lds it, no recipes or targets in craftar.yaml (spec 38)
… one; --targets stays out of the workspace layer

A missing ingredient is a warning for every profile; the test now uses a recipe extending one the
Forge does not have, which the resolver refuses. --targets shapes the new profile only (spec 38 §4.1).
… its questions, an empty Forge directory, the confirmation (spec 38)
…rectory, then start the workspace on it — nothing committed (spec 38)
… copy of the check and its message (spec 38 §4.2)
… is a late failure with the undo (review)

The merged ref held a craftar.local.yaml ref: a path Forge then refused it after the profile was
written, with no recover lines — and a local-only ref would have reached craftar.yaml.
…res after the profile print the undo (review)

The second plan has no recipe flag or template, so its notes were always empty; spec 22's notes and
the integrations note were lost. N1's text now has one spelling, and EEXIST/mkdir after the profile
write print N1 then the late-failure lines. The --add/--remove-recipe help reads as the spec words it.
… Forge it cannot write, asks replace, refuses an unknown --like up front (review)

The draft goes through ProfileSchema (a schema 3 Forge no longer throws a raw TypeError); P10 is
found with ownedBy and worded once (ownedRecipeRefusal). test/init-flow.test.ts case 9 now expects
the re-ask spec 38 §4.3 asks for.
…README status line names --new-profile (review)
…d says spec 22's notes; a refused URL is not offered again (review)
…t the question; a local recipes or targets is said, not asked (review)
@llima
llima merged commit 7b20da3 into main Oct 19, 2026
8 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