ge.run¶
Autonomous-execution runner — Layer 3.
Launches claude in headless mode in a loop, one invocation per work
unit. State persists between iterations only through GitHub-backed
memory (ge.memory); each session starts with a fresh context
window and rehydrates from the roadmap / triage backlog.
Two entry points:
run_roadmap()— drive a roadmap issue end to end.run_triage()— drive a cross-repo triage backlog (Phase A or B).
The permission-mode choice (auto vs bypass) lives here because
SKILL.md files cannot set --permission-mode — that is a launch-time
flag on claude.
What a spawned session can see is decided here too (SessionScope):
the cwd picks which CLAUDE.md files load (the cwd’s and its ancestors’), an
--add-dir contributes its skills but never its CLAUDE.md, and each one
widens the skill listing toward the budget past which descriptions are dropped
silently. So the runner warns when the cwd is outside every package checkout,
adds directories only when asked, puts any add-dir’s CLAUDE.md and the requested routing
documents into the prompt as the first Read, names the skills to load, and
returns the scope with the run so a later diagnosis can see it.
Token / context exhaustion is not a failure: it ends the current session; the loop’s next iteration just rehydrates and continues. A session terminated by the permission-denial cap is a failure: the runner retries once and then escalates.
Functions
|
The git checkout holding path (default: the current directory), or |
|
Drive a roadmap issue to completion. |
|
Drive a cross-repo triage backlog. |
Classes
|
Outcome of a single |
|
What one spawned |
- class ge.run.SessionResult(iteration, returncode, stdout, stderr, duration_sec)[source]¶
Bases:
objectOutcome of a single
claudeinvocation.
- class ge.run.SessionScope(cwd, add_dirs=(), read_first=(), skills=(), model=None, effort=None, warnings=())[source]¶
Bases:
objectWhat one spawned
claudesession can see, decided by the runner.cwd: where the session starts, so whoseCLAUDE.mdloads.add_dirs: further directories the run must edit, passed as--add-dir. Each one adds its skills to the listing; none adds itsCLAUDE.md, which is why those become first Reads.read_first: routing documents the prompt tells the session to Read before anything else (absolute paths).skills: skills to load by name, beyond the runner’s own. A skill named in the prompt is invocable even when the listing shows it name-only.model/effort:claude --model/--effort, when set.warnings: why this scope may not load the work’s instructions.
>>> scope = SessionScope(cwd=Path("/w/pkg"), add_dirs=(Path("/w/lib"),), model="opus") >>> scope.cli_args() ('--add-dir', '/w/lib', '--model', 'opus')- classmethod build(*, cwd=None, add_dirs=(), read_first=(), skills=(), model=None, effort=None)[source]¶
A scope from loose arguments, checked before anything is spawned.
cwddefaults to the current directory. Directories must exist; relative add-dirs resolve against the current directory, relativeread_firstpaths against the scope’s cwd (both become absolute). Every add-dir’s instruction file is added toread_first. A cwd outside every git checkout is kept, with a warning (OUTSIDE_A_CHECKOUT).- Return type:
- ge.run.package_root(path=None)[source]¶
The git checkout holding path (default: the current directory), or
None.A session’s
CLAUDE.mdcomes from its cwd and the cwd’s ancestors, so any directory inside a package checkout loads the package’s instructions (and a subdirectory adds its own). A directory outside every checkout, such as a projects root or a scratch folder, loads none of the work’s.
- ge.run.run_roadmap(repo, roadmap_issue, *, mode='auto', decisions_target=None, max_sessions=50, cwd=None, add_dirs=(), read_first=(), skills=(), model=None, effort=None, on_session=None)[source]¶
Drive a roadmap issue to completion.
Each iteration is one headless
claudeinvocation that performs exactly one roadmap step. The loop terminates when:no todo tasks remain (
status='completed'),two consecutive sessions hit the denial cap (
status='escalated_denial_cap'),a session exits non-zero for another reason (
status='escalated_error'),or
max_sessionsis reached.
- Parameters:
repo (
str) –"owner/repo"containing the roadmap issue.roadmap_issue (
int) – the roadmap issue number.mode (
str) –"auto"(default) or"bypass".decisions_target (
Optional[int]) – issue/PR number to log decisions on. Defaults toroadmap_issue.max_sessions (
int) – safety ceiling on total iterations.cwd (
Union[str,Path,None]) – where the spawnedclaudestarts, so whoseCLAUDE.mdit loads. Defaults to the current directory. A cwd outside every git checkout (a projects root, a scratch folder) loads no package’s instructions: it is kept, and named in the scope’swarnings.add_dirs (
Iterable[str|Path]) – directories the run must edit besidescwd(--add-dir); theirCLAUDE.mdfiles become first Reads, since an add-dir’s never loads.read_first (
Iterable[str]) – routing documents the session must Read first.skills (
Iterable[str]) – skills to load by name, beyondge-autonomous-executionandge-roadmap-execution.on_session – optional callable invoked with each
SessionResult.
- Return type:
The result carries
scope(SessionScope.as_dict()), so a later diagnosis can see what the sessions could see.
- ge.run.run_triage(repos, *, tracking_repo, tracking_issue, phase='analyze', mode='auto', max_sessions=50, cwd=None, add_dirs=(), read_first=(), skills=(), model=None, effort=None, on_session=None)[source]¶
Drive a cross-repo triage backlog.
phase='analyze'runs Phase A (classify + order); a single iteration is normally enough.phase='execute'runs Phase B (one fix-and-PR per iteration); the loop terminates when no unactionedfixableentries remain.The triage backlog lives in
tracking_repo#tracking_issue(seege.memory.TriageBacklog).cwd,add_dirs,read_first,skills,modelandeffortscope each spawned session, as forrun_roadmap(); the result carriesscope.- Return type: