Skip to content

Init clone repos (spec 37) - #69

Merged
llima merged 25 commits into
mainfrom
feat/init-clone-repos
Oct 18, 2026
Merged

llima merged 25 commits into
mainfrom
feat/init-clone-repos

Conversation

@llima

@llima llima commented Oct 18, 2026

Copy link
Copy Markdown
Owner

Summary

  • Version bumped to 0.33.0 (a minor, Ruling 15). Merging publishes craftar@0.33.0 to npm after approval in the npm environment.
  • craftar init --clone clones every entry of the profile's repos into the workspace after the first sync (or after writing craftar.yaml under --no-sync): one git clone --no-recurse-submodules [--branch=<ref>] -- <url> <path> per entry, sequential, git by the absolute path found on PATH, GIT_ALLOW_PROTOCOL=https:ssh set last, git's output and prompt on the terminal. --no-clone; in a terminal the interactive init lists the repositories and asks (default no). Refusals C1–C6 before anything is written; a failed clone exits 1 with the workspace kept and the by-hand command printed; a refused first sync clones nothing.
  • craftar repos lists the entries as present / missing / blocked (no program but the Forge load, nothing written; --json is a new tooling contract) and craftar repos clone [<name>…] clones the missing ones (R1–R4; refuses a remote Forge that cannot be fetched).
  • repos is read by one function, profileRepos (ProfileSchema.repos stays open): name / url / path / ref in plain ASCII classes, https / ssh only, no credentials, refusals by index and key, never a value. Destinations are checked on real paths (realpathOfNearest, moved to the core) and again before each clone.
  • No emitted byte, lock, registry entry or existing --json key changes.

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

§13.1 items 5 (real-path destination check), 6 (absolute git, workspace root as cwd), 15 (repos open in the schema, checked on read); §13.2 items 17–24; §13.3 items 29–37 and 39.

Departures from spec 37's text (to record at the spec refresh)

  • The clone's environment is the process's own minus every variable git rev-parse --local-env-vars lists (git 2.53) and any inherited GIT_ALLOW_PROTOCOL (case-insensitive on win32), plus GIT_ALLOW_PROTOCOL=https:ssh (and GIT_TERMINAL_PROMPT=0 off a terminal) — so inherited git -c settings (GIT_CONFIG_PARAMETERS/COUNT) do not reach the clone; credential variables (GIT_ASKPASS, GIT_SSH_COMMAND) do.
  • init reads a leftover craftar.lock (N1 refuses only craftar.yaml): its paths refuse a destination as in craftar repos.
  • An unrecognized repos key, and an R1 name, are printed only when shaped like a name and not a token (the 0.30.1 nameShaped check, shared).
  • The listing is craftar repos itself (no repos list); padded columns; craftar repos prints the plan's warnings on stdout, also with no entry; --json with no entry prints repos: [].

Test plan

  • npm run typecheck — exit 0 (fce5e80, after the bump)
  • npm run build — exit 0 (fce5e80); craftar --version prints 0.33.0
  • npm test (vitest --maxWorkers=6, without test/ci.test.ts) on 4fa855b — 129 files passed, 1 skipped; 3274 tests passed, 10 skipped. Oracle skipped (no fixture) — no emitter, plan or status byte path changed; three pins committed first (test/init-clone-pins.test.ts).
  • Every new test seen failing first against unchanged src/; a mutation check removed each security control (GIT_ALLOW_PROTOCOL, --, --no-recurse-submodules, real-path containment, the Forge check, the re-check, credentialFault, the scheme check, the host's leading dash, GIT_TERMINAL_PROMPT=0) and each made a test fail.
  • No test runs a real git clone or reaches the network: the CLI tests use a fake git (test/helpers/fake-git.ts).
  • CI green on Linux and Windows — the two runIf(win32) tests (Git_Dir, an other-case git_allow_protocol) run there only.
  • The interactive mode with --clone is not run by the suite and was not tested by hand: the list, the question, a typed --clone (the path the review's two blockers were on, fixed by reading — 0b95d8e and a core test composing askInit → planInit), and --no-sync --clone with a refused sync. The suite cannot drive the interactive mode (spec 28's declared gap).
  • By hand, not run: one real --clone over https and over ssh in a terminal and piped; Ctrl-C during a clone; on Windows the git.exe found on PATH and a pasted by-hand line in bash, zsh, cmd.exe and PowerShell (a destination 1.10, a ref v1.2).

llima added 25 commits October 18, 2026 15:33
…l and init's stdout before spec 37

Written first, as spec 37 §5.2 and §10 ask: realpathOfNearest moves to the core, the load gains a
fetchHint, and init gains --clone — none of the three may change these bytes.
…reader, every refusal by index and key (spec 37)
…, one copy for the output gate and the clone (spec 37)
…es and asks, the confirmation names the clone (spec 37)
… sync, reports each, exits 1 on a failed clone (spec 37)
…ries planInit checked are taken in either mode

The interactive branch kept no entries for a typed --clone, so its confirmation named no clone and
nothing was cloned; the suite cannot drive that mode (spec 28's declared gap), so this is read, not run.
…mmand (spec 37 §13.3 item 29)

repos clone reads --workspace from its parent when commander hands the value there.
…hanges, and spec 37's own README pins

craftar ui stays listed as shipped and never as unbuilt or under Later; the Next: after it and the
"not built yet" sentence are gone by design.
…ctive mode checks C3–C5, names the clone and clones (review)
…it — they would move the checkout out of the checked destination (review)
…aped — one copy of the 0.30.1 check (review)
…ars) are not handed to the clone's git (review)
… run; repos keeps its warnings with no entry (review)
…ne can no longer widen the transports (review)
…k on Windows CI

NODE_OPTIONS read the hook's backslashes as escapes, so the craftar child failed to start; and a
temp dir on another drive has no relative spelling. Both were test defects, not product ones.
@llima
llima merged commit 3faa0b4 into main Oct 18, 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