framework
Version:
The (AI) Framework: turnkey, zero-config AI orchestration that wraps a coding-agent CLI (Claude Code) as a black box and takes you from an idea to a running app. Vite for AI.
70 lines • 3.88 kB
TypeScript
import type { GitRunner } from './project.js';
/**
* Promoting the agent queue out of a finished agent's branch and into the project checkout (#852).
*
* Runs happen in their own git worktree (#736), which is right for code and wrong for the queue:
* `TODO_AGENTS.md` is shared mutable state, and a worktree forks it. So a quick-wins agent (#773)
* wrote a perfectly good queue onto a branch nobody reads, auto PM kept seeing an empty checkout,
* and it re-derived the same entries every cooldown, forever, spending real quota each time.
*
* Rom settled the destination on #624: the queue is a durable global `TODO_AGENTS.md` the session
* writes directly, unlike a *proposal* (a ticket), which is a PR for a human to accept. So the
* queue belongs in the checkout, and nothing should have to be merged by hand for the loop to turn.
*
* The daemon does this, not the agent. The agent stays sandboxed in its worktree with no write
* access to the project checkout; the daemon copies one known file across, and commits only that
* pathspec. Narrow enough to audit in a single log line.
*
* Conservative everywhere it is not certain: anything unexpected skips with a reason and leaves the
* checkout untouched. A skipped promotion costs one idle cycle; a wrong one touches a repo a human
* is working in.
*/
/** Why a promotion did not happen, or that it did. */
export type QueuePromotion = {
promoted: true;
branch: string;
} | {
promoted: false;
reason: string;
/**
* Worth trying again next tick: the queue file is mid-edit in the checkout, and the human's
* work outranks an unattended tidy-up only until they commit it. Every other skip is final
* for this agent. The callee owns this call — the daemon used to decide it by string-matching
* the prose `reason`, where a one-word copyedit would have silently turned "retry next
* tick" into "settled forever".
*/
retry?: true;
};
/**
* Copy `TODO_AGENTS.md` from a finished agent's branch into the project checkout and commit it.
*
* Skips, rather than forcing, when:
* - the agent recorded no branch (nothing to read from)
* - the branch has no queue file, or it matches the checkout already (nothing to do)
* - the checkout has uncommitted changes to the queue file — a human is mid-edit, and their work
* outranks an unattended tidy-up
*
* Never throws: this runs on a background tick with nothing to catch it.
*/
export declare function promoteQueue(projectCwd: string, agent: {
id: string;
branch?: string | undefined;
entry?: string | undefined;
}, git?: GitRunner, write?: (path: string, content: string) => Promise<void>): Promise<QueuePromotion>;
/**
* Land what a drain agent pinned to one entry actually did (#1204): retire that entry, and keep any
* follow-ups it queued.
*
* Additive by construction, which is what makes it safe to run concurrently: it only ever checks a
* box or appends a line. It never unchecks, never removes, and never reorders, so two drains
* landing in either order compose, and the worst a wrong guess can do is leave a duplicate line
* for a human to delete rather than silently send an agent to redo finished work.
*
* A follow-up is an entry the agent's branch has that `atBase` did not: written during the agent. The
* fork point is what tells that from an entry somebody *removed* meanwhile, which looks identical
* from the branch alone and which `todo_format.md` makes the ordinary way to retire an entry. With
* no fork point to compare against, nothing is added -- resurrecting struck-off work is worse than
* leaving a follow-up on the branch, and the check-off still lands either way.
*/
export declare function landPinnedEntry(inCheckout: string, fromBranch: string, entry: string, atBase: string | undefined): string;
//# sourceMappingURL=queue-promote.d.ts.map