git/git¶
Source: src/git/git.ts
The git a run is allowed to do - and nothing else.
A prompt is not a permission boundary. An agent given bash and told
“never push” will push the day it decides that is what the user meant. So the
agent writes the commit message - a text, which is what a model is for - and
the irreversible act stays here, in code that can only do what it has
functions for.
What has no function here, on purpose: push, reset, rebase, checkout
of an existing branch, anything --force, anything that rewrites history.
Adding one is a decision someone has to take in a diff, not an argument a
model can produce at runtime.
deleteBranch is the one that looks like an exception and is not: -d makes
git refuse any branch holding commits nothing else reaches, so it can clear
away a name and never work.
branchName¶
function
export function branchName(request: string, prefix = "combo"): string { /* … */ }
A branch name from a request: combo/add-a-cache.
Kept short and free of anything git dislikes. The prefix says who made it, so
a git branch listing shows at a glance what came from a run.
commitAll¶
function
export async function commitAll(cwd: string, message: string): Promise<GitResult<string>> { /* … */ }
Stages everything and commits it, with the message read from stdin.
-F - rather than -m: a message written by a model contains quotes,
backticks and newlines, and none of them should ever reach a shell. There is
no shell here at all, and this keeps it that way for the body too.
Returns the short sha. A clean working tree is an error, not an empty commit.
createBranch¶
function
export async function createBranch(cwd: string, name: string): Promise<GitResult<string>> { /* … */ }
Creates a branch and switches to it.
checkout -b fails when the branch exists, and that failure is kept: landing
on somebody else’s branch is exactly what a dedicated branch is meant to
prevent.
diff¶
function
export async function diff(cwd: string, maxBytes = 60_000): Promise<GitResult<string>> { /* … */ }
The diff itself, truncated to maxBytes.
It is written straight into a prompt, and an agent that receives half a megabyte of diff writes a worse message than one that receives the first pages and is told it was cut.
diffStat¶
function
export async function diffStat(cwd: string): Promise<GitResult<string>> { /* … */ }
git diff --stat over tracked changes, including what is staged.
isRepository¶
function
export async function isRepository(cwd: string): Promise<boolean> { /* … */ }
Whether cwd is inside a git working tree.
status¶
function
export async function status(cwd: string): Promise<GitResult<string>> { /* … */ }
Porcelain status. Empty means a clean working tree - nothing to commit.
untracked¶
function
export async function untracked(cwd: string): Promise<string[]> { /* … */ }
Untracked files, which git diff does not show but git add -A will commit.