@agentskit/harness 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -3
- package/README.md +8 -0
- package/capabilities/public-surface.json +465 -48
- package/compatibility/report.json +3 -3
- package/compatibility/report.md +1 -1
- package/dist/cli.js +2981 -71
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1494 -4
- package/dist/index.js +2876 -137
- package/dist/index.js.map +1 -1
- package/docs/ADR-0027-keep-pushing-loop.md +41 -0
- package/docs/LOOP.md +195 -0
- package/docs/MODULE-BOUNDARIES.md +29 -1
- package/docs/PRD-0.4.0.md +639 -0
- package/loop.config.example.yaml +121 -0
- package/package.json +38 -7
- package/release/manifest.json +29 -7
- package/release/notes.md +18 -3
- package/release/qualification.json +4 -4
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# ADR-0027: Keep-pushing loop as composition over Orca
|
|
2
|
+
|
|
3
|
+
- Status: Accepted
|
|
4
|
+
- Date: 2026-09-11
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
|
|
8
|
+
Teams want a coding-agent loop that drains one person's Linear queue around the clock: pick a ticket, freeze a
|
|
9
|
+
verifiable contract, run a worker in an isolated worktree, review, merge, repeat — while never exceeding the
|
|
10
|
+
machine, never guessing when acceptance criteria are missing, and surviving provider usage limits. The harness already
|
|
11
|
+
owns the deterministic pieces (dispatch ledger, machine pressure, delivery gates, evidence). Orca already owns
|
|
12
|
+
scheduling, worktrees, terminals, Linear access and the visibility surface. Nothing owned the composition.
|
|
13
|
+
|
|
14
|
+
## Decision
|
|
15
|
+
|
|
16
|
+
1. The loop lives in this package as **Adapter + Composition** (`src/adapters/{command,orca-cli,providers,linear-orca,
|
|
17
|
+
github-cli,code-review}.ts`, `src/loop/*`). The kernel is unchanged and never imports it (`pnpm test:boundaries`).
|
|
18
|
+
2. Every project-specific value lives in `loop.config.yaml` (zod-validated). The code carries no repository, person,
|
|
19
|
+
path or model id. Env variable **names** may appear in config; values never do.
|
|
20
|
+
3. External systems are reached only through argv-based, timeout-bounded process execution injected as a
|
|
21
|
+
`CommandRunner`. Adapters never spawn a shell; composition supplies the real runner; tests supply fakes.
|
|
22
|
+
4. Orca is the single scheduler and visibility surface: two automations (`<prefix>-tick`, `<prefix>-deliver`), each
|
|
23
|
+
gated by a read-only `--precheck` that exits 0 only when work exists, run an agent prompt whose sole job is to
|
|
24
|
+
invoke `ak-harness loop <stage>`. No cron, launchd or daemon of our own.
|
|
25
|
+
5. Model routing is tiered per role (`orchestrator`, `reviewer`, `builder`, `watcher`); within a tier the first
|
|
26
|
+
provider with usage available wins. Usage comes from `orca account list`; an auth/quota failure marks the provider
|
|
27
|
+
cooling down (exponential, never before the reset Orca reports) and the next candidate is tried.
|
|
28
|
+
6. Autonomy envelope: the loop may claim tickets, freeze contracts, dispatch workers, nudge them, review, squash-merge on
|
|
29
|
+
a clean review plus green checks, move Linear states and clean worktrees. It must not merge PRs touching
|
|
30
|
+
`selfEditPaths`, must not force-push or bypass approvals, must not recover leases (human only, ADR-0021), and must
|
|
31
|
+
escalate with one deduplicated comment when a contract has no executable acceptance criterion or when fix rounds
|
|
32
|
+
are exhausted.
|
|
33
|
+
|
|
34
|
+
## Consequences
|
|
35
|
+
|
|
36
|
+
- `yaml` and `zod` become runtime dependencies of the package.
|
|
37
|
+
- The loop is verifiable offline: every stage has fixture-driven tests and `--dry-run` prints the exact argv.
|
|
38
|
+
- Provider CLIs (`claude`, `codex`, `grok`, `opencode`) are configuration, not code; adding one is a YAML entry with a
|
|
39
|
+
TUI template, an optional headless template and an `agentskit-review` provider id.
|
|
40
|
+
- Windows is supported through Node's process model; WSL is detected and capped to one worker because host
|
|
41
|
+
antivirus load is invisible from the distro.
|
package/docs/LOOP.md
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Keep-pushing loop (`ak-harness loop`)
|
|
2
|
+
|
|
3
|
+
The loop drains one person's Linear queue through Orca worktrees, 24/7, with role-based model routing and
|
|
4
|
+
usage-aware fallback. The harness supplies the deterministic parts (claims, machine pressure, gates, evidence);
|
|
5
|
+
Orca supplies scheduling, worktrees, terminals, Linear access and visibility. Everything project-specific lives in
|
|
6
|
+
`loop.config.yaml` — switching project or person is a config change, never a code change.
|
|
7
|
+
|
|
8
|
+
Status: **complete (phases 1–5).** Config, doctor, adapters, the dispatch tick, the deliver stage and the Orca
|
|
9
|
+
automation installer are in place. See [ADR-0027](ADR-0027-keep-pushing-loop.md).
|
|
10
|
+
|
|
11
|
+
## Commands
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
ak-harness loop validate -f loop.config.yaml # schema check + effective config + hash
|
|
15
|
+
ak-harness loop doctor -f loop.config.yaml --json # readiness report (exit 1 when a blocking check fails)
|
|
16
|
+
ak-harness loop doctor --no-probe # skip provider probe commands
|
|
17
|
+
ak-harness loop precheck tick # exit 0 when a slot, a builder and a candidate exist (Orca --precheck)
|
|
18
|
+
ak-harness loop tick --dry-run --max 1 # plan the next dispatch, print the exact orca argv, write nothing
|
|
19
|
+
ak-harness loop tick # dispatch up to <free slots> workers
|
|
20
|
+
ak-harness loop contract ENG-123 [--refresh|--dry-run] # freeze or show the orchestrator contract for one issue
|
|
21
|
+
ak-harness loop precheck deliver # exit 0 when a dispatched issue is in flight
|
|
22
|
+
ak-harness loop deliver [--dry-run] [--issue ENG-123] # drive dispatched workers to merge
|
|
23
|
+
ak-harness loop install [--yes|--force|--skip-rehearsal|--skip-local-config|--dry-run|--plain] # guided: overlay → checks → rehearsal → confirm
|
|
24
|
+
ak-harness loop uninstall [--dry-run] # remove them
|
|
25
|
+
ak-harness loop status # what Orca knows: enabled, trigger, provider, latest run
|
|
26
|
+
ak-harness loop hook # one status line for a SessionStart hook; never mutates
|
|
27
|
+
ak-harness loop debrief [--issue ENG-123] [--since 24h] # human-facing: what is in flight, held, escalated
|
|
28
|
+
ak-harness loop watch [--issue ENG-123] [--once] [--interval 30] # poll delivery/PR; DONE|FAILED|ACTION_REQUIRED
|
|
29
|
+
ak-harness loop retro [--since 7d] [--json|--learnings] # weekly digest + calibration suggestions
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Debrief and watch
|
|
33
|
+
|
|
34
|
+
`loop debrief` is the human companion to the automations: a read-only Markdown (or `--json`) snapshot of
|
|
35
|
+
in-flight dispatches, delivery phase (waiting for PR / review / fix round / ready to merge), holds that need a
|
|
36
|
+
person, recent escalations and provider cooldowns. It does not call Orca or `gh` — only the loop state directory —
|
|
37
|
+
so it is safe to run from a SessionStart hook or a chat agent that needs context before acting.
|
|
38
|
+
|
|
39
|
+
`loop watch` polls `delivery.json` (and optionally the live PR via `gh`) and prints line-oriented events:
|
|
40
|
+
|
|
41
|
+
| Event | Meaning |
|
|
42
|
+
|---|---|
|
|
43
|
+
| `DONE` | Delivery finished as merged (or the PR is MERGED) |
|
|
44
|
+
| `FAILED` | stuck / abandoned / failed / PR closed without merge |
|
|
45
|
+
| `ACTION_REQUIRED` | held for a human, incomplete review twice, or fix-round findings |
|
|
46
|
+
| `PROGRESS` | still moving (waiting for PR, review pending, …) |
|
|
47
|
+
|
|
48
|
+
Use `--once` for a single snapshot; omit it to block until a terminal outcome (or `--timeout <seconds>`).
|
|
49
|
+
|
|
50
|
+
## Running 24/7 with Orca
|
|
51
|
+
|
|
52
|
+
`loop install` is guided and rendered with Ink when stdin/stdout are terminals (plain lines otherwise). When no
|
|
53
|
+
`loop.config.local.yaml` exists next to the config it first offers to create one: it lists the Linear team members from
|
|
54
|
+
Orca, asks whose queue this machine drains and, optionally, how much RAM to keep free and the worker ceiling, then
|
|
55
|
+
writes the gitignored overlay and reloads. It then runs the doctor and the automation-environment checks (harness and review CLIs on
|
|
56
|
+
PATH, `gh auth status`, checkout registered in Orca, queue owner), stops on any failed check unless `--force`,
|
|
57
|
+
offers a dry-run tick rehearsal (one orchestrator call, nothing written), lists the exact automations it will
|
|
58
|
+
create, and asks for confirmation before touching Orca. `--yes` accepts every prompt for scripted setups; without
|
|
59
|
+
a TTY the command refuses unless `--yes` or `--dry-run` is given; `--plain` keeps the old check-free behaviour.
|
|
60
|
+
|
|
61
|
+
It creates two automations in the Orca runtime, each bound to the main checkout as an existing workspace
|
|
62
|
+
with session reuse:
|
|
63
|
+
|
|
64
|
+
| Automation | Trigger | Precheck (plain command, exit 0 = run) | Prompt |
|
|
65
|
+
|---|---|---|---|
|
|
66
|
+
| `<prefix>-tick` | `schedule.tick` | `<harnessCommand> loop stage tick -f <config>` (runs the tick, exits 1) | never reached under `runner: precheck` |
|
|
67
|
+
| `<prefix>-deliver` | `schedule.deliver` | `<harnessCommand> loop stage deliver -f <config>` (runs deliver, exits 1) | never reached under `runner: precheck` |
|
|
68
|
+
|
|
69
|
+
With the default `schedule.runner: precheck` the **precheck command is the stage itself** (`ak-harness loop stage
|
|
70
|
+
tick|deliver`): it runs the harness, prints the JSON report and always exits 1, so Orca records every run as
|
|
71
|
+
`skipped_precheck` with the report in `precheckResult.stdout` and never opens an agent session. This is deliberate:
|
|
72
|
+
Orca caps a precheck at 600 s, so `contract.timeoutMs` (default 300 s) plus dispatch must fit one run; an Orca-launched agent starts in bypass-permissions mode and waits for a human to accept the warning, which leaks one
|
|
73
|
+
stuck session per run. `schedule.runner: agent` keeps the legacy behaviour for providers that run unattended.
|
|
74
|
+
Runs and their output are visible in Orca's Automations view and via `loop status`.
|
|
75
|
+
|
|
76
|
+
`schedule.harnessCommand` must resolve inside Orca's environment: install the harness globally
|
|
77
|
+
(`npm i -g @agentskit/harness`) or set an absolute command. `loop install` warns when it cannot find it on this shell's PATH.
|
|
78
|
+
|
|
79
|
+
Optional SessionStart hook for Claude Code (`.claude/settings.json` of the target project):
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{ "hooks": { "SessionStart": [{ "hooks": [{ "type": "command", "command": "ak-harness loop hook -f loop.config.yaml", "timeout": 10 }] }] } }
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
It prints `loop: installed (2/2, last run …)` or the install command; it never installs or changes anything.
|
|
86
|
+
|
|
87
|
+
## Deliver
|
|
88
|
+
|
|
89
|
+
For every issue the loop dispatched (`<stateDir>/issues/<id>/dispatch.json`) and has not finished:
|
|
90
|
+
|
|
91
|
+
| Situation | Action |
|
|
92
|
+
|---|---|
|
|
93
|
+
| No PR, worker terminal alive and active | wait |
|
|
94
|
+
| No PR, idle ≥ `workerIdleTimeoutMin` | one check-in via `terminal send`; idle again after that → **stuck**: lease released, issue → `returnState` + `blocked`, worktree kept |
|
|
95
|
+
| No PR, terminal gone (> 5 min after dispatch) | **stuck** as above |
|
|
96
|
+
| PR touches `selfEditPaths` | **held**: one PR comment, no review, no merge |
|
|
97
|
+
| PR conflicting | rebase instruction to the worker, once per head (does not count as a fix round) |
|
|
98
|
+
| CI red | failing check names to the worker; counts as a fix round |
|
|
99
|
+
| CI pending / required check missing | wait |
|
|
100
|
+
| CI green, head not reviewed | `agentskit-review --pr … --block <minSeverity> --result … [--post]` with the first available reviewer candidate |
|
|
101
|
+
| Review findings ≥ floor | findings to the worker; counts as a fix round; same head is never re-reviewed |
|
|
102
|
+
| Fix rounds exhausted (`maxFixRounds`) | **blocked**: Linear comment + label + `returnState`, PR comment, lease released, worktree and PR kept |
|
|
103
|
+
| Review clean, `merge.auto` | `gh api PUT …/merge` with `sha=<reviewed head>` (GitHub refuses if the head moved) → Linear attach + comment + `doneState`, worktree removed when `cleanupWorktree` |
|
|
104
|
+
| PR merged outside the loop | same completion path |
|
|
105
|
+
| PR closed without merge | **abandoned**: lease released, issue → `returnState`, worktree kept |
|
|
106
|
+
|
|
107
|
+
State lives in `<stateDir>/issues/<id>/delivery.json` (reviews per head, fix rounds, nudges) and every decision is
|
|
108
|
+
appended to `<stateDir>/events.ndjson`. `--dry-run` reports the decision for each issue without touching anything.
|
|
109
|
+
|
|
110
|
+
## One tick
|
|
111
|
+
|
|
112
|
+
1. **Intake** — `orca linear list-issues` once per configured state, filtered and ordered locally; issues already
|
|
113
|
+
leased, linked to a live worktree or sitting on their branch are *busy* and skipped.
|
|
114
|
+
2. **Admit** — `assessSlots` (machine) and the harness dispatch ledger (`<stateDir>/coordination`) decide how many
|
|
115
|
+
workers may start; a claim is atomic per issue/worktree/branch.
|
|
116
|
+
3. **Contract** — the orchestrator (first available candidate across `models.orchestrator` tiers) reads the issue and
|
|
117
|
+
the repository read-only and returns a JSON contract between `<<<LOOP_CONTRACT … LOOP_CONTRACT>>>`. Issue text is
|
|
118
|
+
wrapped as untrusted data. An auth/quota failure on one candidate marks it cooling down and the next is tried.
|
|
119
|
+
Contracts are cached under `<stateDir>/issues/<id>/contract.json` while the issue is unchanged.
|
|
120
|
+
4. **Dispatch or escalate** — a contract with at least one executable outcome and no blocking ambiguity becomes a
|
|
121
|
+
worker: `orca worktree create --linear-issue <url> --base-branch <base> --no-parent` (no `--agent`: Orca's agent
|
|
122
|
+
launcher runs Claude in bypass-permissions mode and waits for a human), then `orca terminal create --command
|
|
123
|
+
"<providers.<id>.tui>"`, `terminal wait --for tui-idle`, and the brief goes in through `terminal send`. The issue
|
|
124
|
+
moves to `In Progress` and one dedicated comment is posted. Otherwise the loop posts one
|
|
125
|
+
`needs-info` comment (deduped by contract digest), adds the label, and moves on without consuming a slot.
|
|
126
|
+
|
|
127
|
+
Every side effect is recorded in `<stateDir>/events.ndjson`; `dispatch.json` per issue links the worktree,
|
|
128
|
+
terminal handle, provider/model and lease for the deliver stage.
|
|
129
|
+
|
|
130
|
+
Start from [`loop.config.example.yaml`](../loop.config.example.yaml) at the package root.
|
|
131
|
+
|
|
132
|
+
## What the doctor checks
|
|
133
|
+
|
|
134
|
+
| Check | Source | Blocking |
|
|
135
|
+
|---|---|---|
|
|
136
|
+
| `orca.version` / `orca.runtime` | `orca --version`, `orca status --json` | yes — the loop cannot run without a reachable Orca runtime at or above `orca.minVersion` |
|
|
137
|
+
| `provider.<id>` | PATH lookup, `orca account list` usage windows, `orca agent hooks status`, env key names, optional probe, cooldown store | no — reported per provider |
|
|
138
|
+
| `routing.<role>` | tiers from `models.<role>` filtered by provider availability | yes — a role with no available provider blocks |
|
|
139
|
+
| `machine.slots` | `sampleMachine` + `adaptiveConcurrency`, free RAM reserve, WSL cap, running worktrees | no — 0 free slots is a warning, not a failure |
|
|
140
|
+
| `linear.queue` | `orca linear list-issues` per configured state, filtered and ordered locally | yes — an unreachable Linear blocks |
|
|
141
|
+
|
|
142
|
+
## Model routing
|
|
143
|
+
|
|
144
|
+
`models.<role>` is a list of tiers; each tier is a list of `provider/model`. Tiers are tried in order and, inside a
|
|
145
|
+
tier, providers in declaration order. The first provider that is **available** wins. A provider is available when
|
|
146
|
+
its binary is on PATH, its auth is not known to be missing, no Orca usage window is at or above
|
|
147
|
+
`cooldown.exhaustedPercent`, it is not cooling down, and its optional probe passed.
|
|
148
|
+
|
|
149
|
+
Providers authenticate through their own CLI login (`claude login`, `codex login`, `grok login`); only providers
|
|
150
|
+
declared `auth: api-key` need an environment variable, and the loop never reads its value. Orca has no per-run model flag; the chosen model is rendered into `providers.<id>.tui` (for example
|
|
151
|
+
`codex -m {model} --full-auto`) and launched in the worker terminal.
|
|
152
|
+
|
|
153
|
+
When a provider runs out of usage the loop records a cooldown in `<stateDir>/provider-cooldowns.json`:
|
|
154
|
+
`initialMin` doubling up to `maxMin`, never earlier than the reset instant Orca reported.
|
|
155
|
+
|
|
156
|
+
## Machine slots
|
|
157
|
+
|
|
158
|
+
`maxAgents = max(floor, min(adaptiveConcurrency(ceiling), ramBound, wslCap?))` where `ceiling` defaults to
|
|
159
|
+
`cpus / 2`, `ramBound` fits `agentRssMb` agents into free RAM minus `minFreeRamGb`, and the WSL cap applies only
|
|
160
|
+
inside a WSL distro (host Defender load is invisible there). The loop never lowers a running worker; it only
|
|
161
|
+
decides whether to start another.
|
|
162
|
+
|
|
163
|
+
## Boundaries
|
|
164
|
+
|
|
165
|
+
Adapters (`src/adapters/command.ts`, `orca-cli.ts`, `providers.ts`, `linear-orca.ts`) depend on kernel contracts
|
|
166
|
+
only and receive a `CommandRunner`; they never spawn a shell. Composition (`src/loop/*`) supplies the real
|
|
167
|
+
runner and wires adapters together. See `docs/MODULE-BOUNDARIES.md`.
|
|
168
|
+
|
|
169
|
+
## Security notes
|
|
170
|
+
|
|
171
|
+
- `loop.config.yaml` holds env variable **names**, never values.
|
|
172
|
+
- Every external call is argv-based with a timeout; `ok: false` envelopes fail closed.
|
|
173
|
+
- Linear text is data. Later phases render it into worker briefs inside delimiters and never execute it.
|
|
174
|
+
|
|
175
|
+
## Continuous improvement: `loop retro`
|
|
176
|
+
|
|
177
|
+
`ak-harness loop retro --since 7d` reads `<stateDir>/events.ndjson`, every `issues/<id>/{contract,dispatch,delivery}.json`,
|
|
178
|
+
`provider-cooldowns.json` and (unless `--no-orca`) the Orca run records of the two automations, and prints a Markdown
|
|
179
|
+
digest:
|
|
180
|
+
|
|
181
|
+
- **Numbers** — contracts frozen, escalation rate, dispatches by provider, merged/blocked/stuck/abandoned/in flight,
|
|
182
|
+
review outcomes, fix rounds, median dispatch→merge, cooldowns, Orca runs (idle/work/timed out, durations).
|
|
183
|
+
- **Problems** — escalation reasons grouped by shape, blocked/stuck/abandoned issues.
|
|
184
|
+
- **What worked** — merged issues with worker, lead time and fix rounds.
|
|
185
|
+
- **Adjustments — project** — rule-based suggestions about the target project, each with its evidence and the
|
|
186
|
+
`loop.config.yaml` knob to turn (`escalation-rate`, `review-floor`, `fix-rounds`, `stuck-workers`, `review-incomplete`,
|
|
187
|
+
`provider-cooldowns`, `idle-loop`, `lead-time`, or `steady`).
|
|
188
|
+
- **Adjustments — harness** — defects or limitations of the library itself, derived from events the loop only emits
|
|
189
|
+
when its own machinery misbehaved (`worker-relaunch`, `dispatch-failures`, `contract-failures`, `merge-refusals`,
|
|
190
|
+
`review-tool-errors`, `stage-timeout`), with a pointer to the harness issue tracker. `--target project|harness`
|
|
191
|
+
filters one side.
|
|
192
|
+
|
|
193
|
+
The headings follow the harness retro grammar, so `--learnings` prints `LearningRecord`s in `proposed` state; a human
|
|
194
|
+
promotes them with `promoteLearnings` (ADR-0019 keeps that decision human). The calibration loop is: read the digest →
|
|
195
|
+
change one knob in `loop.config.yaml` → next digest measures the effect.
|
|
@@ -9,7 +9,7 @@ does not claim that the proposed 0.4.0 boundary has already been accepted.
|
|
|
9
9
|
|
|
10
10
|
| Class | Meaning | Dependency rule |
|
|
11
11
|
| --- | --- | --- |
|
|
12
|
-
| Kernel | Deterministic contracts, state transitions, policy and metric projections | May use Node standard library and other kernel modules; must not import adapters, provider SDKs, CLI composition, or
|
|
12
|
+
| Kernel | Deterministic contracts, state transitions, policy and metric projections | May use Node standard library and other kernel modules; must not import adapters, provider SDKs, CLI composition, credentials, or UI libraries (`ink`/`react` are composition-only). |
|
|
13
13
|
| Execution support | Local process, filesystem, event, evidence, and run lifecycle plumbing | May depend on the kernel; must expose provenance and fail closed at trust boundaries. |
|
|
14
14
|
| Adapter | Provider-specific or external-system integration | May depend on kernel contracts; must not be imported by kernel modules. |
|
|
15
15
|
| Composition | Package and CLI entry points | May compose kernel, execution support, and adapters; consumers use `src/index.ts`. |
|
|
@@ -73,6 +73,30 @@ modules, not a provider dependency.
|
|
|
73
73
|
| `src/adapters/agent.ts` | Adapter | Structured coding-agent execution with bounded timeout and failure classification | `errors`, `resilience`, `adapter-contract` | Agent/provider callback supplied by caller |
|
|
74
74
|
| `src/adapters/orca.ts` | Adapter | Safe, idempotent Orca dispatch plan | `errors`, `hash`, `preflight` | Orca CLI arguments; no execution |
|
|
75
75
|
| `src/adapters/tracking.ts` | Adapter | Idempotent provider-neutral tracking transition | `errors`, `hash` | User-supplied Linear/GitHub/etc. handler |
|
|
76
|
+
| `src/adapters/command.ts` | Adapter | Shell-free command runner seam, PATH executable lookup, Orca JSON envelope parsing | stdlib | Command runner supplied by composition or tests |
|
|
77
|
+
| `src/adapters/orca-cli.ts` | Adapter | Typed `orca … --json` calls: version/status/account/agent hooks, worktree ps/create/set/rm, terminal list/send/wait/read, automations list/create/edit/remove/run | `errors`, `command` | Orca CLI via the injected runner |
|
|
78
|
+
| `src/adapters/providers.ts` | Adapter | Coding-agent CLI availability: binary, auth, Orca usage windows, exhaustion, cooldown, optional probe | `command` | PATH, env var names, `orca account list` payload |
|
|
79
|
+
| `src/adapters/linear-orca.ts` | Adapter | Linear queue via `orca linear list-issues`, issue detail, status/comment/label/attach writes with deterministic `--write-id`, `TrackingAdapter` over Orca | `errors`, `hash`, `orca-cli`, `tracking`, `command` | Linear through the Orca CLI |
|
|
80
|
+
| `src/adapters/github-cli.ts` | Adapter | Pull request snapshots, check classification, self-edit path guard, optimistic squash-merge and comments via `gh` | `errors`, `command` | GitHub through the `gh` CLI |
|
|
81
|
+
| `src/adapters/code-review.ts` | Adapter | `agentskit-review` argv, `--result` parsing, severity floor, worker-facing findings | `command` (type-only) | AgentsKit code review CLI via runner |
|
|
82
|
+
| `src/loop/config.ts` | Composition | `loop.config.yaml` schema (zod), loading, model reference parsing | `errors`, `hash`, `model-policy`, `yaml`, `zod` | Project config file |
|
|
83
|
+
| `src/loop/process.ts` | Composition | Real shell-free `CommandRunner` with timeout and output caps | stdlib, `command` (type-only) | Child processes |
|
|
84
|
+
| `src/loop/slots.ts` | Composition | Machine slot assessment: adaptive concurrency, RAM reserve, WSL cap, floor | stdlib, `machine`, `config` | Host CPU/memory |
|
|
85
|
+
| `src/loop/routing.ts` | Composition | Tiered role → provider/model selection over provider availability | `model-policy`, `providers` (type-only), `config` | None |
|
|
86
|
+
| `src/loop/cooldown.ts` | Composition | Provider cooldown store with exponential backoff | stdlib, `providers` | `<stateDir>/provider-cooldowns.json` |
|
|
87
|
+
| `src/loop/doctor.ts` | Composition | Loop readiness report: Orca, providers, routing, slots, workers, queue | adapters, `config`, `cooldown`, `routing`, `slots` | Orca CLI via runner |
|
|
88
|
+
| `src/loop/contract.ts` | Composition | Task contract schema, orchestrator prompt (issue text as untrusted data), marked-JSON parsing, dispatchability assessment, candidate fallback with auth/quota classification, contract cache | `errors`, `hash`, `resilience`, `doc-bridge`, `config`, `routing` (type-only), `zod` | Headless coding-agent CLI via runner |
|
|
89
|
+
| `src/loop/brief.ts` | Composition | Worker prompt: frozen contract + repository rules + protected paths + done signal | `contract`, `config`, `linear-orca` (type-only) | None |
|
|
90
|
+
| `src/loop/tick.ts` | Composition | One keep-pushing tick: intake, admit (slots + dispatch ledger claim), contract, dispatch into an Orca worktree, Linear transition, escalation, precheck | adapters, `coordination`, `errors`, `hash`, `brief`, `config`, `contract`, `cooldown`, `doctor`, `routing`, `slots` | Orca CLI + Linear via runner; `<stateDir>` files |
|
|
91
|
+
| `src/loop/deliver.ts` | Composition | Deliver stage per dispatched issue: PR detection, self-edit hold, conflict/CI/review fix rounds via terminal, review at head, optimistic squash-merge, Linear Done, cleanup, stuck/abandoned escalation | adapters, `coordination`, `errors`, `config`, `cooldown`, `doctor`, `routing`, `tick` | Orca, Linear, GitHub, agentskit-review via runner; `<stateDir>` files |
|
|
92
|
+
| `src/loop/install.ts` | Composition | Orca automation specs (`<prefix>-tick`, `<prefix>-deliver`) with read-only prechecks, idempotent create/edit by name, uninstall, status and the SessionStart hook line | `command`, `orca-cli`, `providers`, `errors`, `config`, `cooldown`, `doctor`, `routing` | Orca automations via runner |
|
|
93
|
+
| `src/loop/guided-install.ts` | Composition | Interactive install: doctor + environment preflight, dry-run rehearsal, confirmation, install, status; readline IO injected | `command`, `orca-cli`, `config`, `doctor`, `install`, `tick`, stdlib readline | Terminal prompts; Orca via runner |
|
|
94
|
+
| `src/loop/local-config.ts` | Composition | Per-machine overlay wizard: Linear team members via Orca, queue owner and machine tuning answers, YAML rendering and reload | `orca-cli`, `config`, `yaml` | Orca via runner; writes `loop.config.local.yaml` |
|
|
95
|
+
| `src/loop/retro.ts` | Composition | Retro digest over `events.ndjson`, per-issue state, cooldowns and Orca runs; rule-based calibration suggestions; Markdown that `parseRetro` can lift into learnings | `orca-cli`, `hash`, `learning`, `config`, `contract`, `cooldown`, `deliver`, `install`, `tick` | Orca via runner (optional); `<stateDir>` files |
|
|
96
|
+
| `src/loop/debrief.ts` | Composition | Human-facing read-only snapshot of what the loop is working on (in-flight, holds, escalations, cooldowns) | `config`, `contract`, `cooldown`, `deliver`, `retro`, `tick` | `<stateDir>` files only |
|
|
97
|
+
| `src/loop/watch.ts` | Composition | Poll delivery (+ optional live PR) and emit DONE/FAILED/ACTION_REQUIRED/PROGRESS for agents or humans | `command`, `github-cli`, `config`, `deliver`, `tick` | optional `gh` via runner; `<stateDir>` files |
|
|
98
|
+
| `src/loop/ui/components.tsx` | Composition | Ink components: check rows, sections, banner, spinner, select/confirm/text prompts | `ink`, `react`, `doctor` (type-only) | Terminal |
|
|
99
|
+
| `src/loop/ui/terminal.tsx` | Composition | `createRichIO`: Ink-backed IO for TTYs with a plain-text fallback | `ink`, `react`, `components`, `guided-install` (type-only) | Terminal |
|
|
76
100
|
|
|
77
101
|
## Allowed dependency directions and exceptions
|
|
78
102
|
|
|
@@ -130,6 +154,10 @@ Orca, and tracking. No adapter implementation is re-exported wholesale.
|
|
|
130
154
|
| Doc Bridge | `src/adapters/doc-bridge.ts` | Reads a local index | Keep behind `ContextProvider`; measure context hit/quality separately. |
|
|
131
155
|
| Orca | `src/adapters/orca.ts` | None; produces argv and lifecycle projections only | Keep lease/worktree/issue-lock/SHA planning provider-neutral; execution belongs to the orchestrator. |
|
|
132
156
|
| Linear/GitHub/other tracker | `src/adapters/tracking.ts` callback | Caller-owned network mutation | Require idempotency key and explicit tracking authorization. |
|
|
157
|
+
| Orca CLI (loop) | `src/adapters/orca-cli.ts`, `src/adapters/linear-orca.ts` via `CommandRunner` | Read-only `--json` calls in the doctor; dispatch/mutation arrive in later loop phases | Argv only, never a shell string; every call bounded by a timeout; envelope `ok:false` fails closed. |
|
|
158
|
+
| Coding-agent CLIs | `src/adapters/providers.ts` | PATH lookup and optional probe command | Env keys are names only; usage comes from Orca, never from provider SDKs. |
|
|
159
|
+
| GitHub | `src/adapters/github-cli.ts` via `CommandRunner` | `gh pr view/list`, `gh api PUT …/merge` with `sha=<reviewed head>`, `gh pr comment` | Merge is refused by GitHub when the head moved; every call argv-based and bounded. |
|
|
160
|
+
| AgentsKit code review | `src/adapters/code-review.ts` via `CommandRunner` | `agentskit-review --pr … --result <file> [--post]` | Exit codes 0/1/2 plus the private result file decide clean/findings/incomplete; the floor is `--block`. |
|
|
133
161
|
| Process runtime | `src/execution/runtime.ts` | Starts child processes | Execution support; policy and evidence gates remain kernel decisions. |
|
|
134
162
|
| Docker runtime | `src/execution/runtime.ts` | Starts Docker containers | Optional sandbox selected by config, never a mandatory kernel dependency. |
|
|
135
163
|
| LLM provider/model | Caller/plugin | Provider call and token spend | Bind provider/model in experiment metadata; do not embed SDKs in kernel. |
|