Story
As someone starting a Git repository, I want <Git.Add> and <Git.Commit> in an ordinary xmd run document to create its first commit, so I do not need a separate native Git bootstrap step.
Example
Given a directory containing README.md:
git init --initial-branch=main
xmd run -e '# Commit README.md with the initial commit messageStage `README.md` for the commit.<Git.Add paths="README.md" />Commit the staged file with the message `Initial commit`.<Git.Commit message="Initial commit" as="commitId" />'
The run stages README.md, creates a zero-parent commit on main, and binds that commit's full object ID to commitId.
An unborn repository is a valid Git checkout whose initial branch exists symbolically but does not have a HEAD commit yet.
Current gap
Ambient repository discovery finds the checkout root and common Git directory, but treats failure to resolve HEAD as if the invocation were outside Git:
this element needs a repository, and it is written outside a <Repository> in a directory that is not inside a Git checkout.
The live Git operation contract also assumes that every checkout has a commit and HEAD tree, and that every new commit has exactly one parent. Relaxing discovery alone therefore cannot support an initial commit safely.
Contract
Where ordinary repository operations are supported—the Deno source CLI and compiled xmd—a valid unborn checkout is selected as the ambient Repository.
<Git.Add> keeps its existing path validation, index behavior, output, and failure semantics.
When the index contains staged changes, <Git.Commit> in an unborn checkout:
- creates a commit with zero parents;
- updates the checkout's symbolic branch to that commit;
- binds the full object ID through
as; - preserves the existing author, committer, signing, hook, index, and read-back behavior.
An empty index retains the existing no-empty-commit refusal and creates no commit.
The live ordinary-run state represents unavailable pre-commit values with null, never a sentinel or invented object ID:
- the ambient
RepositoryIdentity.creationCommit is null when the checkout is selected before its first commit; - the pre-operation checkout
commit and headTree are null; - the initial commit's
parent is null; - successful post-operation state contains the real commit and tree object IDs.
Repository selection and identity remain stable for the whole execution. The identity's creationCommit therefore stays null; it is not rewritten after <Git.Commit>. Operations later in the same execution read the repository's live state and observe the newly created commit.
Before the initial commit, an operation that requires an existing commit—such as creating a worktree or pushing a branch—refuses with an actionable unborn-repository diagnosis. After <Git.Commit> succeeds, the same operation uses the new commit under the already selected Repository. With the usual origin and Git-host configuration, this includes <Git.Push> and <PullRequest>.
A directory that is not a Git checkout retains the existing outside-a-repository refusal.
Ordinary --journal behavior does not change: ordinary repository effects remain live and are not retained or replayed as workflow effects.
Workflow <Repositories> behavior also does not change:
- every workflow Repository still has a real pinned
creationCommit; - retained workflow checkout and commit records still require real commit, HEAD-tree, and parent object IDs;
- replay rejects a retained record that substitutes
null for those required workflow values; - an empty remote or unborn checkout does not become a valid workflow base.
This issue does not add ordinary repository-operation providers to the Node or Bun source CLIs.
Acceptance
- In a fresh
git init --initial-branch=main checkout, <Git.Add paths="README.md" /> followed by <Git.Commit message="Initial commit" as="commitId" /> creates a zero-parent commit containing README.md. commitId equals the resulting HEAD object ID.- Live pre-operation results use
null for the absent commit, HEAD tree, and parent; successful post-operation results contain valid object IDs. - The ambient Repository selection does not change after the commit.
- A later
<Git.Push> in the same execution can push the new branch to a configured empty origin, and subsequent Git-host composition consumes that pushed commit without reselecting the Repository. - Attempting
<Git.Commit> with an empty index refuses and leaves the checkout unborn. - An operation requiring an existing commit refuses actionably before the initial commit and succeeds under its existing contract after the commit.
- A file-backed document and an inline
xmd run -e document resolve the same ambient checkout. - A non-Git directory retains the existing outside-a-repository error, while an unborn checkout does not receive it.
- Ordinary diagnostic journals continue to contain no repository effects.
- Retained workflow parsers reject absent creation commits, checkout commits, HEAD trees, and commit parents.
- Existing ordinary, linked-worktree, managed-worktree, and workflow Repository behavior remains unchanged.
architecture.md, specs/workflow-workspace-spec.md, and the ordinary-run requirements in specs/executable-mdx-spec.md describe the resulting boundary.
Evidence
Run the focused integration and contract suites:
deno task test packages/workflow/tests/run-composition-ambient.test.ts packages/workflow/tests/run-composition-remote.test.ts packages/workflow/tests/git-add.test.ts packages/workflow/tests/git-commit.test.ts packages/cli/tests/run-composition-deno.test.ts packages/cli/tests/inline-cli.test.ts
The evidence includes the successful initial-commit path, empty-index refusal, pre-commit refusal for operations that need HEAD, same-execution post-commit behavior, outside-Git behavior, unchanged ordinary journaling, and strict workflow parsing.
Related
Story
As someone starting a Git repository, I want
<Git.Add>and<Git.Commit>in an ordinaryxmd rundocument to create its first commit, so I do not need a separate native Git bootstrap step.Example
Given a directory containing
README.md:The run stages
README.md, creates a zero-parent commit onmain, and binds that commit's full object ID tocommitId.An unborn repository is a valid Git checkout whose initial branch exists symbolically but does not have a
HEADcommit yet.Current gap
Ambient repository discovery finds the checkout root and common Git directory, but treats failure to resolve
HEADas if the invocation were outside Git:The live Git operation contract also assumes that every checkout has a commit and HEAD tree, and that every new commit has exactly one parent. Relaxing discovery alone therefore cannot support an initial commit safely.
Contract
Where ordinary repository operations are supported—the Deno source CLI and compiled
xmd—a valid unborn checkout is selected as the ambient Repository.<Git.Add>keeps its existing path validation, index behavior, output, and failure semantics.When the index contains staged changes,
<Git.Commit>in an unborn checkout:as;An empty index retains the existing no-empty-commit refusal and creates no commit.
The live ordinary-run state represents unavailable pre-commit values with
null, never a sentinel or invented object ID:RepositoryIdentity.creationCommitisnullwhen the checkout is selected before its first commit;commitandheadTreearenull;parentisnull;Repository selection and identity remain stable for the whole execution. The identity's
creationCommittherefore staysnull; it is not rewritten after<Git.Commit>. Operations later in the same execution read the repository's live state and observe the newly created commit.Before the initial commit, an operation that requires an existing commit—such as creating a worktree or pushing a branch—refuses with an actionable unborn-repository diagnosis. After
<Git.Commit>succeeds, the same operation uses the new commit under the already selected Repository. With the usual origin and Git-host configuration, this includes<Git.Push>and<PullRequest>.A directory that is not a Git checkout retains the existing outside-a-repository refusal.
Ordinary
--journalbehavior does not change: ordinary repository effects remain live and are not retained or replayed as workflow effects.Workflow
<Repositories>behavior also does not change:creationCommit;nullfor those required workflow values;This issue does not add ordinary repository-operation providers to the Node or Bun source CLIs.
Acceptance
git init --initial-branch=maincheckout,<Git.Add paths="README.md" />followed by<Git.Commit message="Initial commit" as="commitId" />creates a zero-parent commit containingREADME.md.commitIdequals the resultingHEADobject ID.nullfor the absent commit, HEAD tree, and parent; successful post-operation results contain valid object IDs.<Git.Push>in the same execution can push the new branch to a configured empty origin, and subsequent Git-host composition consumes that pushed commit without reselecting the Repository.<Git.Commit>with an empty index refuses and leaves the checkout unborn.xmd run -edocument resolve the same ambient checkout.architecture.md,specs/workflow-workspace-spec.md, and the ordinary-run requirements inspecs/executable-mdx-spec.mddescribe the resulting boundary.Evidence
Run the focused integration and contract suites:
deno task test packages/workflow/tests/run-composition-ambient.test.ts packages/workflow/tests/run-composition-remote.test.ts packages/workflow/tests/git-add.test.ts packages/workflow/tests/git-commit.test.ts packages/cli/tests/run-composition-deno.test.ts packages/cli/tests/inline-cli.test.tsThe evidence includes the successful initial-commit path, empty-index refusal, pre-commit refusal for operations that need
HEAD, same-execution post-commit behavior, outside-Git behavior, unchanged ordinary journaling, and strict workflow parsing.Related
<Repository>,<Worktree>,<Issue>, and<PullRequest>toxmd run#643