@defrex/autobuild 0.8.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/LICENSE +201 -0
- package/README.md +192 -0
- package/SPEC.md +2269 -0
- package/bin/ab-build-runner.ts +47 -0
- package/bin/ab-dev.ts +27 -0
- package/bin/ab-dispatch-kernel.ts +92 -0
- package/bin/ab-harvest-runner.ts +29 -0
- package/bin/ab-init-probe.ts +19 -0
- package/bin/ab-process-group-reaper.ts +32 -0
- package/bin/ab.ts +6 -0
- package/bin/agent/ab +3 -0
- package/docs/answering-blocked-builds.md +89 -0
- package/docs/architecture.md +726 -0
- package/docs/assets/headline-wide.png +0 -0
- package/docs/configuration.md +1623 -0
- package/docs/hosted-dispatcher-cutover-validation.md +178 -0
- package/docs/hosted-dispatcher.md +204 -0
- package/docs/mcp.md +119 -0
- package/docs/operator-api.md +186 -0
- package/docs/remote-store-protocol.md +972 -0
- package/docs/remote-ticket-protocol.md +79 -0
- package/docs/setup.md +289 -0
- package/docs/spec-standard.md +63 -0
- package/docs/ticket-dependencies.md +59 -0
- package/docs/vercel-sandbox-rollout-probe.md +7 -0
- package/package.json +135 -0
- package/packages/core/src/cli/args.ts +74 -0
- package/packages/core/src/cli/artifact.ts +182 -0
- package/packages/core/src/cli/binary.ts +198 -0
- package/packages/core/src/cli/build-control.ts +789 -0
- package/packages/core/src/cli/build-progress.ts +55 -0
- package/packages/core/src/cli/bulk-control.ts +385 -0
- package/packages/core/src/cli/context.ts +470 -0
- package/packages/core/src/cli/dashboard/actions.ts +59 -0
- package/packages/core/src/cli/dashboard/cells.ts +92 -0
- package/packages/core/src/cli/dashboard/composer.ts +230 -0
- package/packages/core/src/cli/dashboard/detail.ts +100 -0
- package/packages/core/src/cli/dashboard/frame-image.ts +373 -0
- package/packages/core/src/cli/dashboard/live.ts +152 -0
- package/packages/core/src/cli/dashboard/model.ts +1173 -0
- package/packages/core/src/cli/dashboard/poll.ts +196 -0
- package/packages/core/src/cli/dashboard/render.ts +1568 -0
- package/packages/core/src/cli/dashboard/selection.ts +66 -0
- package/packages/core/src/cli/dashboard/session-feed.ts +244 -0
- package/packages/core/src/cli/dashboard/session-view.ts +506 -0
- package/packages/core/src/cli/dashboard/transcript.ts +108 -0
- package/packages/core/src/cli/dev.ts +46 -0
- package/packages/core/src/cli/dispatch-frontend.ts +1045 -0
- package/packages/core/src/cli/dispatch-process.ts +259 -0
- package/packages/core/src/cli/dispatch.ts +3692 -0
- package/packages/core/src/cli/dotenv.ts +48 -0
- package/packages/core/src/cli/env.ts +206 -0
- package/packages/core/src/cli/harvest.ts +698 -0
- package/packages/core/src/cli/help.ts +713 -0
- package/packages/core/src/cli/init-agent.ts +106 -0
- package/packages/core/src/cli/init-validation.ts +583 -0
- package/packages/core/src/cli/init.ts +756 -0
- package/packages/core/src/cli/installation.ts +333 -0
- package/packages/core/src/cli/keyboard.ts +261 -0
- package/packages/core/src/cli/main.ts +1399 -0
- package/packages/core/src/cli/mcp.ts +279 -0
- package/packages/core/src/cli/models.ts +65 -0
- package/packages/core/src/cli/observe.ts +55 -0
- package/packages/core/src/cli/plugin.ts +227 -0
- package/packages/core/src/cli/pr-attachments.ts +138 -0
- package/packages/core/src/cli/pr-summary.ts +124 -0
- package/packages/core/src/cli/publication-settlement.ts +188 -0
- package/packages/core/src/cli/repo-state.ts +213 -0
- package/packages/core/src/cli/repository-status.ts +80 -0
- package/packages/core/src/cli/self-update.ts +443 -0
- package/packages/core/src/cli/status.ts +895 -0
- package/packages/core/src/cli/store-opening.contract.ts +289 -0
- package/packages/core/src/cli/store-opening.ts +167 -0
- package/packages/core/src/cli/store-ref.ts +33 -0
- package/packages/core/src/cli/terminal-restore.ts +174 -0
- package/packages/core/src/cli/terminal.ts +361 -0
- package/packages/core/src/cli/terminals.ts +995 -0
- package/packages/core/src/cli/testkit.ts +194 -0
- package/packages/core/src/cli/ticket.ts +484 -0
- package/packages/core/src/cli/upgrade-agent.ts +180 -0
- package/packages/core/src/cli/upgrade-commit.ts +468 -0
- package/packages/core/src/cli/upgrade-notice.ts +91 -0
- package/packages/core/src/cli/upgrade-progress.ts +110 -0
- package/packages/core/src/cli/upgrade.ts +888 -0
- package/packages/core/src/cli/wait.ts +587 -0
- package/packages/core/src/cli/watch.ts +932 -0
- package/packages/core/src/config/live.ts +255 -0
- package/packages/core/src/config/load.ts +98 -0
- package/packages/core/src/config/roles.ts +438 -0
- package/packages/core/src/config/schema.ts +774 -0
- package/packages/core/src/distribution.ts +24 -0
- package/packages/core/src/events/catalog.ts +201 -0
- package/packages/core/src/events/envelope.ts +59 -0
- package/packages/core/src/events/payloads.ts +618 -0
- package/packages/core/src/events/repository.ts +559 -0
- package/packages/core/src/events/sessions.ts +180 -0
- package/packages/core/src/harvest/schema.ts +147 -0
- package/packages/core/src/ids.ts +45 -0
- package/packages/core/src/integration/harness.ts +681 -0
- package/packages/core/src/kernel/auto-merge.ts +259 -0
- package/packages/core/src/kernel/converge.ts +117 -0
- package/packages/core/src/kernel/dispatch-settings.ts +60 -0
- package/packages/core/src/kernel/dispatch-status.ts +141 -0
- package/packages/core/src/kernel/engine.ts +1047 -0
- package/packages/core/src/kernel/harvest.ts +823 -0
- package/packages/core/src/kernel/origin.ts +69 -0
- package/packages/core/src/kernel/phases.ts +196 -0
- package/packages/core/src/kernel/plan-verify-selection.ts +105 -0
- package/packages/core/src/kernel/pr-attachments.ts +82 -0
- package/packages/core/src/kernel/reducer.ts +752 -0
- package/packages/core/src/kernel/stall.ts +155 -0
- package/packages/core/src/kernel/verify-applicability.ts +52 -0
- package/packages/core/src/markdown.ts +67 -0
- package/packages/core/src/ontology.ts +288 -0
- package/packages/core/src/open-map.ts +203 -0
- package/packages/core/src/operator/annotations.ts +187 -0
- package/packages/core/src/operator/client.ts +311 -0
- package/packages/core/src/operator/control.ts +117 -0
- package/packages/core/src/operator/index.ts +62 -0
- package/packages/core/src/operator/presentation.ts +22 -0
- package/packages/core/src/operator/protocol.ts +98 -0
- package/packages/core/src/operator/query.ts +201 -0
- package/packages/core/src/operator/registry.ts +1043 -0
- package/packages/core/src/operator/requests.ts +138 -0
- package/packages/core/src/operator/sandbox.ts +458 -0
- package/packages/core/src/operator/server.ts +616 -0
- package/packages/core/src/operator/sessions.ts +223 -0
- package/packages/core/src/operator/tickets.ts +177 -0
- package/packages/core/src/plugin-sdk/index.ts +174 -0
- package/packages/core/src/plugins/contract-entry.ts +74 -0
- package/packages/core/src/plugins/contract-env.ts +3 -0
- package/packages/core/src/plugins/load.ts +259 -0
- package/packages/core/src/plugins/manifest.ts +236 -0
- package/packages/core/src/plugins/registry.ts +274 -0
- package/packages/core/src/plugins/runtimes.ts +75 -0
- package/packages/core/src/ports/forge/contract.ts +258 -0
- package/packages/core/src/ports/forge/create.ts +74 -0
- package/packages/core/src/ports/forge/fake.ts +488 -0
- package/packages/core/src/ports/forge/github-pr-attachments.ts +351 -0
- package/packages/core/src/ports/forge/github-transport.ts +352 -0
- package/packages/core/src/ports/forge/github.ts +1162 -0
- package/packages/core/src/ports/forge/local-git.ts +568 -0
- package/packages/core/src/ports/runner/claude.ts +873 -0
- package/packages/core/src/ports/runner/cli-stream.ts +90 -0
- package/packages/core/src/ports/runner/codex.ts +873 -0
- package/packages/core/src/ports/runner/contract.ts +492 -0
- package/packages/core/src/ports/runner/fake.ts +213 -0
- package/packages/core/src/ports/runner/json-record.ts +2 -0
- package/packages/core/src/ports/runner/live-contract-fixture.ts +176 -0
- package/packages/core/src/ports/runner/one-shot.ts +29 -0
- package/packages/core/src/ports/runner/pi-bridge-core.ts +136 -0
- package/packages/core/src/ports/runner/pi-bridge.js +6 -0
- package/packages/core/src/ports/runner/pi-rpc.ts +454 -0
- package/packages/core/src/ports/runner/pi.ts +617 -0
- package/packages/core/src/ports/runner/production.ts +74 -0
- package/packages/core/src/ports/runner/provider-error.ts +121 -0
- package/packages/core/src/ports/runner/routing.ts +234 -0
- package/packages/core/src/ports/runner/runtime.ts +214 -0
- package/packages/core/src/ports/runner/session-env.ts +34 -0
- package/packages/core/src/ports/runner/stream-parts.ts +103 -0
- package/packages/core/src/ports/tickets/contract.ts +570 -0
- package/packages/core/src/ports/tickets/create.ts +135 -0
- package/packages/core/src/ports/tickets/fake.ts +215 -0
- package/packages/core/src/ports/tickets/file.ts +559 -0
- package/packages/core/src/ports/tickets/linear.ts +811 -0
- package/packages/core/src/ports/tickets/operations.ts +161 -0
- package/packages/core/src/ports/tickets/remote-index.ts +13 -0
- package/packages/core/src/ports/tickets/remote-protocol.ts +80 -0
- package/packages/core/src/ports/tickets/remote-server.ts +185 -0
- package/packages/core/src/ports/tickets/remote.ts +130 -0
- package/packages/core/src/ports/tickets/update.ts +51 -0
- package/packages/core/src/ports/types.ts +528 -0
- package/packages/core/src/ports/workspace/build-execution.ts +123 -0
- package/packages/core/src/ports/workspace/contract.ts +136 -0
- package/packages/core/src/ports/workspace/create.ts +132 -0
- package/packages/core/src/ports/workspace/distribution-archive.ts +317 -0
- package/packages/core/src/ports/workspace/fake.ts +432 -0
- package/packages/core/src/ports/workspace/git-worktree.ts +848 -0
- package/packages/core/src/ports/workspace/harvest-execution.ts +111 -0
- package/packages/core/src/ports/workspace/in-process-build-execution.ts +30 -0
- package/packages/core/src/ports/workspace/local-build-execution.ts +88 -0
- package/packages/core/src/ports/workspace/operator-sandbox.ts +142 -0
- package/packages/core/src/ports/workspace/phase-scratch.ts +156 -0
- package/packages/core/src/ports/workspace/vercel-sandbox.ts +2541 -0
- package/packages/core/src/processes/build-child-exit.ts +78 -0
- package/packages/core/src/processes/build-child.ts +119 -0
- package/packages/core/src/processes/build-execution-state.ts +95 -0
- package/packages/core/src/processes/build-parent-watch.ts +35 -0
- package/packages/core/src/processes/build-runner.ts +2614 -0
- package/packages/core/src/processes/dispatcher.ts +2825 -0
- package/packages/core/src/processes/execution-settlement.ts +171 -0
- package/packages/core/src/processes/harvest-child.ts +115 -0
- package/packages/core/src/processes/harvest-execution-state.ts +121 -0
- package/packages/core/src/processes/harvest-runner.ts +1656 -0
- package/packages/core/src/processes/harvest.ts +595 -0
- package/packages/core/src/processes/infrastructure-failure-budget.ts +146 -0
- package/packages/core/src/processes/phase-failure-budget.ts +52 -0
- package/packages/core/src/processes/process-group-reaper.ts +35 -0
- package/packages/core/src/processes/process-group.ts +65 -0
- package/packages/core/src/processes/publication-loss.ts +62 -0
- package/packages/core/src/processes/publication-state.ts +93 -0
- package/packages/core/src/processes/sandbox-state.ts +101 -0
- package/packages/core/src/registry.ts +24 -0
- package/packages/core/src/sessions/reducer.ts +185 -0
- package/packages/core/src/skills.ts +7 -0
- package/packages/core/src/spec-standard.ts +47 -0
- package/packages/core/src/store/adapter.ts +80 -0
- package/packages/core/src/store/build-scope.ts +272 -0
- package/packages/core/src/store/contract.ts +2581 -0
- package/packages/core/src/store/local/blobs.ts +38 -0
- package/packages/core/src/store/local/schema.ts +180 -0
- package/packages/core/src/store/local/store.ts +1713 -0
- package/packages/core/src/store/memory.ts +1138 -0
- package/packages/core/src/store/phase-session.ts +425 -0
- package/packages/core/src/store/remote/client.ts +780 -0
- package/packages/core/src/store/remote/index.ts +12 -0
- package/packages/core/src/store/remote/protocol.ts +348 -0
- package/packages/core/src/store/remote/server.ts +923 -0
- package/packages/core/src/store/remote/token.ts +137 -0
- package/packages/core/src/store/remote/version.ts +10 -0
- package/packages/core/src/store/retention.ts +91 -0
- package/packages/core/src/store/session-handle.ts +265 -0
- package/packages/core/src/store/streams/assemble.ts +79 -0
- package/packages/core/src/store/streams/lock.ts +42 -0
- package/packages/core/src/store/streams/session-writer.ts +306 -0
- package/packages/core/src/store/streams/types.ts +171 -0
- package/packages/core/src/store/streams/wait.ts +127 -0
- package/packages/core/src/store/subscribe.ts +105 -0
- package/packages/core/src/store/types.ts +466 -0
- package/packages/core/src/testing/fixed.ts +44 -0
- package/packages/core/src/testing/store-failures.ts +32 -0
- package/packages/core/src/zod-issues.ts +91 -0
- package/skills/code-review/SKILL.md +100 -0
- package/skills/finalize/SKILL.md +44 -0
- package/skills/guide/SKILL.md +1781 -0
- package/skills/guide/references/operator-api.md +164 -0
- package/skills/guide/references/plugin-authoring.md +354 -0
- package/skills/guide/references/remote-store-protocol.md +972 -0
- package/skills/guide/references/remote-ticket-protocol.md +79 -0
- package/skills/guide/references/setup.md +289 -0
- package/skills/guide/references/spec-standard.md +63 -0
- package/skills/guide/references/ticket-dependencies.md +59 -0
- package/skills/harvest/SKILL.md +66 -0
- package/skills/harvest-review/SKILL.md +63 -0
- package/skills/implement/SKILL.md +82 -0
- package/skills/plan/SKILL.md +123 -0
- package/skills/plan-review/SKILL.md +121 -0
- package/skills/reconcile/SKILL.md +65 -0
- package/skills/spec/SKILL.md +132 -0
- package/skills/tickets/SKILL.md +139 -0
- package/templates/autobuild.toml +36 -0
|
@@ -0,0 +1,726 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
The contributor-facing map: how the codebase is organized and where the
|
|
4
|
+
seams are. `SPEC.md` is the source of truth for the design and terminology;
|
|
5
|
+
this document maps it to the code. For the user journey — install, configure,
|
|
6
|
+
operate — see [`README.md`](../README.md); for the complete declarative surface,
|
|
7
|
+
see [`docs/configuration.md`](configuration.md). The hosted sessionless control
|
|
8
|
+
surface is specified in the [operator API reference](operator-api.md). Behavioral detail beyond what
|
|
9
|
+
a map needs lives with the code and its tests; when this document and the code
|
|
10
|
+
disagree, the code is authoritative.
|
|
11
|
+
|
|
12
|
+
## Constitution
|
|
13
|
+
|
|
14
|
+
1. **Judgment in skills, determinism in code.** Agents never decide phase
|
|
15
|
+
transitions, signal identity, or state. Narrow non-phase judgment such as
|
|
16
|
+
slug naming and skill-conflict proposals remains behind deterministic
|
|
17
|
+
validation and fail-safe fallback.
|
|
18
|
+
2. **Resumability is not a feature.** Re-running `ab dispatch` attempts every
|
|
19
|
+
actionable current build; each phase resumes as a function of durable state.
|
|
20
|
+
Open escalations remain parked until a human answer is recorded, while
|
|
21
|
+
pending operator commands remain actionable.
|
|
22
|
+
3. **Ingesters propose, humans dispatch.** Nothing auto-generated passes
|
|
23
|
+
Triage without a human grooming it to Ready, unless the repository waives
|
|
24
|
+
that gate explicitly with `[tickets].proposalState`.
|
|
25
|
+
4. **Every step leaves a paper trail** — queryable, not carried in the repo.
|
|
26
|
+
|
|
27
|
+
## Pipeline
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
spec → plan ⇄ plan-review → implement ⇄ code-review → verify:* → finalize
|
|
31
|
+
└────────────────── epilogue: (pr.conflicted → reconcile → verify:*)* → merged
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The grammar is fixed; `verify:*` and `finalize:*` are the only extension
|
|
35
|
+
points, declared per-repo in `autobuild.toml`. Observation harvest is
|
|
36
|
+
adjacent, never a build phase:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
K unclaimed observation.recorded events
|
|
40
|
+
→ scan → synthesize ⇄ review → file approved proposals in proposalState
|
|
41
|
+
(Triage by default)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Workspace ownership
|
|
45
|
+
|
|
46
|
+
The repository is a Bun 1.4 workspace. The private root package, `autobuild`, is
|
|
47
|
+
still the sole Git-installed compatibility distribution: it owns the public and
|
|
48
|
+
private `bin/` entries, the `@defrex/autobuild/plugin-sdk` export, and the shipped
|
|
49
|
+
`skills/`, `templates/`, and documentation. Its implementation is included as
|
|
50
|
+
unbundled TypeScript from the private `@defrex/autobuild-core` workspace at
|
|
51
|
+
`packages/core`; the root repeats core's runtime dependencies so a packed or
|
|
52
|
+
Git installation never requires a separately published core package.
|
|
53
|
+
|
|
54
|
+
`packages/core` owns the CLI, kernel, adapters, shared types, dashboard
|
|
55
|
+
projection, plugin SDK, and reusable contract suites. The optional
|
|
56
|
+
`packages/hosted-store-service` workspace composes the public remote-server
|
|
57
|
+
surface with `packages/postgres-store`; neither package enters an ordinary CLI
|
|
58
|
+
installation's runtime dependency closure. `tools/` is repository-only
|
|
59
|
+
maintainer tooling. All workspace manifests share one version because the
|
|
60
|
+
remote-store protocol requires matching client and server versions.
|
|
61
|
+
|
|
62
|
+
## Layout
|
|
63
|
+
|
|
64
|
+
| Path | Contents | SPEC |
|
|
65
|
+
|---|---|---|
|
|
66
|
+
| `package.json` | Private `autobuild` compatibility distribution and Bun workspace orchestrator; owns bins and shipped assets | — |
|
|
67
|
+
| `packages/core/package.json` | Private `@defrex/autobuild-core` implementation workspace | — |
|
|
68
|
+
| `packages/core/src/ontology.ts` | The shared nouns — findings, verdicts, phases, refs, the canonical verify outcome | §4 |
|
|
69
|
+
| `packages/core/src/events/` | Separate build, repository, and operator-session envelopes/catalogs, frozen payload schemas, actor validation, the `via` attribution marker | §15 |
|
|
70
|
+
| `packages/core/src/harvest/` | Structured occurrence, scan packet, proposal, and ledger schemas | §12 |
|
|
71
|
+
| `packages/core/src/sessions/` | The operator-session reducer: status, open turn, pending approval, wake settings and cursors, and the turn list, reduced purely from the session event log | §7.1.1 |
|
|
72
|
+
| `packages/core/src/store/` | BuildStore contract spanning builds, the repository journal, and operator sessions; interface-enforced build, operator-session, and local ambient-session scope wrappers; memory, SQLite/blob, and remote HTTP adapters | §7 |
|
|
73
|
+
| `packages/core/src/store/streams/` | The stream primitive's shared core (§7.6): record/chunk types and the `ai-ui-message-stream/v1` constants, SDK-backed close-time `UIMessage[]` assembly, and the uniform bounded-wait read loop | §7.6 |
|
|
74
|
+
| `packages/hosted-store-service/` | Environment-only hosted Fetch handler, lazy PostgreSQL/blob composition, offline token binary, tests, and deployment guide | §7.2, §18 |
|
|
75
|
+
| `server.ts`, `vercel.json` | One host-neutral Bun listener used locally and by Vercel's Bun preset | §7.2 |
|
|
76
|
+
| `packages/core/src/kernel/` | Phase table, build reducer, engine; pure harvest, dispatcher-settings, dispatcher-status, and PR-attachment selectors; converge, stall detection, verify gating | §5, §7.5, §10, §12, §14, §15.4–15.5 |
|
|
77
|
+
| `packages/core/src/ports/` | TicketSource / Workspace / Forge / AgentRunner / Telemetry interfaces, adapters, and fakes; registry-aware builtin/plugin construction; eager primary/alternate runtime routing and provider-failure classification under `ports/runner/` | §3.2, §9, §13 |
|
|
78
|
+
| `packages/core/src/plugins/` | Strict versioned plugin manifests, dual-root repository/package Bun loading, owner-aware adapter registration, contract/credential metadata, and runtime-factory materialization | §3.2.1, §9 |
|
|
79
|
+
| `packages/core/src/plugin-sdk/` | The sole supported `@defrex/autobuild/plugin-sdk` barrel: port/manifest types, contract suites, and reference fakes | §3.2.1 |
|
|
80
|
+
| `packages/core/src/processes/` | build-runner and standalone child composition, durable execution config/diagnostics, dispatcher (+ janitor duty and harvest trigger), harvest deterministic core + runner | §3.3, §12, §15.7 |
|
|
81
|
+
| `packages/core/src/cli/` and `bin/` | The `ab` CLI — the only agent↔store channel — plus the shared presentation-only durable-progress projection, init/upgrade, the Store-only dispatch frontend, its private supervised kernel entry, and `bin/ab-build-runner.ts` (one child per build) | §8, §14, §16.3 |
|
|
82
|
+
| `packages/core/src/cli/dashboard/` | `ab dispatch`'s fixed live frame: pure projection, renderer, poll cache, and deterministic image renderer | §14 |
|
|
83
|
+
| `bin/agent/ab` | Private launcher placed first on agent-session `PATH`; delegates to the canonical `bin/ab.ts` | §8.1 |
|
|
84
|
+
| `packages/core/src/config/` | `autobuild.toml` parsing and strict validation, plus the pure role-key consumability diagnostics `ab dispatch` reports at startup (`roles.ts`); user reference in `docs/configuration.md` | §9, §16.1 |
|
|
85
|
+
| `packages/core/src/integration/` | End-to-end harness and product scenarios | — |
|
|
86
|
+
| `tools/` | This repository's local maintainer tooling, including verification, dashboard capture, and release cutting; not shipped product behavior | — |
|
|
87
|
+
| `skills/` | Canonical defaults; `ab init` vendors them to `.agents/skills/ab-*` and links `.claude/skills/ab-*` | §16.3 |
|
|
88
|
+
| `skills/guide/` | `ab-guide` — the model-invocable reference for the lifecycle and full config surface; `references/` is the shared installed-documentation seam for every vendored skill. Update it when config or shared guidance changes; `packages/core/src/cli/guide-skill.test.ts` guards schema coverage and `packages/core/src/cli/skill-self-containment.test.ts` guards installed references | §16.3 |
|
|
89
|
+
| `docs/spec-standard.md` | The standalone definition of "buildable" every ticket surface uses; kept byte-identical with `skills/guide/references/spec-standard.md` for installed agents | §6.1 |
|
|
90
|
+
| `templates/` | Valid setup-only config baseline with comment anchors rendered by `ab init` | §16.3 |
|
|
91
|
+
|
|
92
|
+
## Key boundaries
|
|
93
|
+
|
|
94
|
+
**Hosted store service.** `@defrex/autobuild/remote-store` is the supported protocol
|
|
95
|
+
server/client/token export. The hosted workspace validates its environment,
|
|
96
|
+
serves health without touching persistence, and lazily retains one
|
|
97
|
+
`openPostgresBuildStoreFromEnv` promise per warm process. Its Fetch handler has
|
|
98
|
+
no Vercel branch; root `server.ts` is the sole `Bun.serve()` composition point.
|
|
99
|
+
The fixed 1 MiB decoded artifact policy is enforced before backing mutation.
|
|
100
|
+
The `ab-hosted-store` binary signs admin or build/session tokens offline from
|
|
101
|
+
`AB_STORE_SECRET`; the running service exposes no mint endpoint. Machine routes
|
|
102
|
+
and later server-session human routes intentionally share one deployment.
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
Where each mechanism lives, and the one rule worth knowing at the seam. The
|
|
106
|
+
full behavior is specified by each owner's colocated tests.
|
|
107
|
+
|
|
108
|
+
**Events and state.** `packages/core/src/events/payloads.ts`, `packages/core/src/events/repository.ts`,
|
|
109
|
+
and `packages/core/src/events/sessions.ts`
|
|
110
|
+
are the frozen catalogs; every write passes `validateEventWrite` /
|
|
111
|
+
`validateRepositoryEventWrite` / `validateSessionEventWrite`. `packages/core/src/kernel/reducer.ts` derives all build
|
|
112
|
+
status; `packages/core/src/kernel/harvest.ts` and `packages/core/src/kernel/dispatch-settings.ts` reduce
|
|
113
|
+
the repository journal independently of each other; `packages/core/src/sessions/reducer.ts` reduces an operator
|
|
114
|
+
session's status, open turn, pending approval, and wake cursors from its own
|
|
115
|
+
closed catalog. No decision anywhere
|
|
116
|
+
consults a snapshot in place of the append-only log.
|
|
117
|
+
|
|
118
|
+
**Session Store authority.** `packages/core/src/cli/binary.ts` validates a complete build or
|
|
119
|
+
Harvest ambient tuple before opening its phase Store through
|
|
120
|
+
`packages/core/src/cli/store-opening.ts`. `packages/core/src/cli/env.ts` also classifies optional ambient
|
|
121
|
+
identity for the finite `builds`, `build status`, and `artifact download` read
|
|
122
|
+
shells: no identity retains operator authority, while any partial, malformed,
|
|
123
|
+
shared-only, or mixed identity fails closed before Store opening. Remote
|
|
124
|
+
references keep the existing token-backed client unchanged. Local references
|
|
125
|
+
are wrapped by `packages/core/src/store/phase-session.ts`, which permits only the exact
|
|
126
|
+
ambient build or repository resource (this is the phase-session wrapper, not the
|
|
127
|
+
operator-session scope handle in `session-handle.ts`) and rejects
|
|
128
|
+
agent-attributed event writes
|
|
129
|
+
for any session other than `AB_SESSION`. The wrapper deliberately allows
|
|
130
|
+
non-agent actors because phase terminals also run trusted kernel plumbing in
|
|
131
|
+
that CLI process; resource authority still applies to every operation. Generic
|
|
132
|
+
sessionless opening remains unwrapped; only those three reads use the dedicated
|
|
133
|
+
ambient-aware finite opener.
|
|
134
|
+
|
|
135
|
+
**Phase decisions.** `packages/core/src/kernel/phases.ts` owns the phase table,
|
|
136
|
+
`packages/core/src/kernel/engine.ts` the deterministic transitions;
|
|
137
|
+
`packages/core/src/processes/build-runner.ts` executes the decisions. Repeated phase starts
|
|
138
|
+
left by recovery are execution evidence, not policy counters: logical verdict
|
|
139
|
+
rounds, `phase.failed`, failed verify completions, and distinct completed
|
|
140
|
+
reconcile attempts own their respective budgets. Agents reach state only
|
|
141
|
+
through `packages/core/src/cli/` terminals, which convert artifact deposits into event facts
|
|
142
|
+
atomically — the engine never reads blobs. Engine crash-gap and
|
|
143
|
+
exhaustion guards query the event log for a later escalation raise with the
|
|
144
|
+
exact same source/class and target phase; the triggering sequence remains the
|
|
145
|
+
re-arm boundary. `BuildRunner` applies the same independent targeting at the
|
|
146
|
+
setup seam, where only a setup-targeted policy raise can satisfy setup
|
|
147
|
+
exhaustion.
|
|
148
|
+
|
|
149
|
+
**Phase-session budgets.** `packages/core/src/ports/runner/routing.ts` resolves one inherited
|
|
150
|
+
`sessionBudgetSeconds` value for each logical role, with the policy default as
|
|
151
|
+
its final fallback. `BuildRunner` captures it at the session action boundary,
|
|
152
|
+
starts an unref'ed timer after `session.started`, and composes expiry with the
|
|
153
|
+
existing operator `AbortController`. Operator abort and deadline remain
|
|
154
|
+
independent: abort cancels promptly, while the captured deadline still stops
|
|
155
|
+
waiting if the adapter ignores that cancellation. First cause owns
|
|
156
|
+
classification, so an operator-first deadline release returns to abort
|
|
157
|
+
acknowledgement without `phase.failed` or provider substitution. Ordinary
|
|
158
|
+
expiry best-effort ends an available or late-returning handle, drops producer
|
|
159
|
+
continuation state, and reuses retryable `phase.failed`; it does not enter the
|
|
160
|
+
provider-alternate classifier. The event log is checked before failure so a
|
|
161
|
+
typed terminal racing either boundary remains authoritative. Finalize agent
|
|
162
|
+
post-steps reuse the timer but drain expiry through their existing failure-tolerant
|
|
163
|
+
completion and observation path. Harvest and deterministic commands do not use
|
|
164
|
+
this build-phase timer.
|
|
165
|
+
|
|
166
|
+
**Human guidance delivery.** The routing fact is an `escalation.answered`
|
|
167
|
+
event carrying `resolution: "guidance"`; nothing else routes an answer. `ab
|
|
168
|
+
answer` and the dashboard's blocked-build resume control are two surfaces over
|
|
169
|
+
the one `packages/core/src/cli/build-control.ts` operation that appends it, so delivery is
|
|
170
|
+
identical whichever a human used.
|
|
171
|
+
`packages/core/src/kernel/engine.ts` routes answers from `plan` and `plan-review` to the next
|
|
172
|
+
`plan` round, and answers from `implement` and `code-review` to the next
|
|
173
|
+
`implement` round. An agent verifier's own escalation is the deliberate
|
|
174
|
+
exception to producer routing: its answer returns to that same step on
|
|
175
|
+
`verify.started.feedback`, and `PHASE_SPECS.inputs.currentFeedback` makes `ab
|
|
176
|
+
context` the delivery channel. When a failed verify report instead exhausts
|
|
177
|
+
policy, guidance answering that policy escalation takes precedence over the
|
|
178
|
+
pending report as the failure routes to the next `implement` round. For these
|
|
179
|
+
engine-routed destinations, `engine.ts` chooses the newest answered guidance
|
|
180
|
+
for the requested destination before checking whether its durable carrier
|
|
181
|
+
reached a matching session launch. That ordering makes supersession durable:
|
|
182
|
+
delivering the winner cannot reveal an older same-destination answer, while
|
|
183
|
+
plan, code, and exact-verifier destinations remain independent and a new answer
|
|
184
|
+
after delivery remains eligible. The projection uses only event history, so
|
|
185
|
+
restart and decision replay agree.
|
|
186
|
+
`finalize` and `reconcile` have no producer round, so
|
|
187
|
+
`PHASE_SPECS.inputs.answeredGuidance` makes `ab context` their delivery channel
|
|
188
|
+
for the latest answer addressed to that phase. On every receiving path,
|
|
189
|
+
`packages/core/src/cli/context.ts` materializes `.ab/guidance.json` with the escalation id and
|
|
190
|
+
answer text. For producer and verifier feedback routes, `packages/core/src/kernel/engine.ts`
|
|
191
|
+
indexes each guidance-bearing phase start as a durable carrier and pairs only
|
|
192
|
+
the latest carrier for an exact phase plus round/attempt with a subsequent
|
|
193
|
+
matching `session.started`. An unpaired carrier remains deliverable across
|
|
194
|
+
recovery; the matching launch consumes it once without process-local state. A
|
|
195
|
+
producer round's feedback is a discriminated union — findings, a
|
|
196
|
+
failed verify report, or guidance — and a round may carry none, so a round with
|
|
197
|
+
guidance writes no `.ab/findings.json`. The receiving skills document their
|
|
198
|
+
corresponding input, and `packages/core/src/cli/skill-guidance.test.ts` derives that
|
|
199
|
+
requirement from the phase table.
|
|
200
|
+
|
|
201
|
+
**Finalize publication.** Content-producing `finalize:*` checks or agents
|
|
202
|
+
select and commit files locally and leave a clean worktree. `build-runner.ts`
|
|
203
|
+
derives the last published head from event facts, rejects a non-descendant
|
|
204
|
+
`HEAD`, and uses the `Forge.pushBranch` port for a regular kernel-side push
|
|
205
|
+
before checkpointing the new head on `finalize.step-completed`. An unchanged
|
|
206
|
+
head is a no-op; Git/Forge failures stay failure-tolerant observations.
|
|
207
|
+
|
|
208
|
+
**Verify gating.** `packages/core/src/ontology.ts` owns the canonical
|
|
209
|
+
`pass | fail | skipped` outcome (only `fail` routes back to implement or
|
|
210
|
+
consumes attempts; a skip satisfies one step without being passing
|
|
211
|
+
evidence). Two kernel-authored skip sources narrow the configured universe:
|
|
212
|
+
`packages/core/src/kernel/plan-verify-selection.ts` resolves an approved plan's front-matter
|
|
213
|
+
selection (applied at the planner's `ab done` in `packages/core/src/cli/terminals.ts`,
|
|
214
|
+
snapshotted by the engine at approval), and
|
|
215
|
+
`packages/core/src/kernel/verify-applicability.ts` matches changed paths against a step's
|
|
216
|
+
selectors, resolved by the build runner via `git diff` against the initial
|
|
217
|
+
branch-cut base (or the refreshed base promoted by a completed reconcile).
|
|
218
|
+
This verify-only base is deliberately independent from implementation's
|
|
219
|
+
focused review range. Both narrowing mechanisms produce the ordinary
|
|
220
|
+
queryable skipped outcome; Git failure is infrastructure and fails closed,
|
|
221
|
+
never a synthetic skip. Verify escalation routing is also explicit in the
|
|
222
|
+
engine: guidance answering an agent verifier's own `ab escalate` returns to the
|
|
223
|
+
same step on `verify.started.feedback`, which `ab context` materializes as
|
|
224
|
+
`.ab/guidance.json`; that cited start remains recoverable before launch, and the
|
|
225
|
+
matching `session.started` for the same step and attempt consumes the answer
|
|
226
|
+
once. Guidance answering the policy escalation after failed-report exhaustion
|
|
227
|
+
instead routes to `implement` and outranks the pending report. A bare retry carries no
|
|
228
|
+
feedback.
|
|
229
|
+
|
|
230
|
+
**Launch ownership.** `packages/core/src/cli/dispatch.ts` is the kernel owner and
|
|
231
|
+
single-flights supervised build executions per slug within its process. It
|
|
232
|
+
publishes effective config into the build artifact namespace, claims the exact
|
|
233
|
+
execution-instance lease, then calls the workspace-adjacent `BuildExecution`
|
|
234
|
+
capability; it never constructs a `BuildRunner`. The shipped local capability
|
|
235
|
+
starts `bin/ab-build-runner.ts` with ignored stdio as a detached POSIX
|
|
236
|
+
session/process-group leader. That child immediately scopes its Store handle, discovers
|
|
237
|
+
its workspace from durable events, and composes the existing runner. Config and
|
|
238
|
+
instance-correlated diagnostics remain build artifacts. Local completion first
|
|
239
|
+
reaps the complete inherited process group, escalating group-wide from SIGTERM
|
|
240
|
+
through the existing bounded delay to SIGKILL; only then is it a liveness signal
|
|
241
|
+
and only then does the kernel release the exact lease. Interactive `ab dispatch` runs the kernel owner in the
|
|
242
|
+
private `bin/ab-dispatch-kernel.ts` child;
|
|
243
|
+
`dispatch-frontend.ts` owns only terminal/Store adapters and
|
|
244
|
+
`dispatch-process.ts` owns child supervision. SIGINT, SIGHUP, SIGQUIT, and
|
|
245
|
+
SIGTERM restore terminal modes immediately and begin one supervised drain;
|
|
246
|
+
persistent frontend and child handlers keep repeated signals graceful until the
|
|
247
|
+
kernel child is reaped, after which a non-SIGINT terminating signal is replayed
|
|
248
|
+
in the frontend. A parent-liveness watch remains the detached-kernel fallback.
|
|
249
|
+
Timeout escalation is held while a durable `tick-started` fact remains open,
|
|
250
|
+
because force-killing the ticket claim before build creation would not be
|
|
251
|
+
recoverable. After a build child claims a takeover lease, it reduces one
|
|
252
|
+
captured event prefix and appends transcriptless reclaimed `session.ended`
|
|
253
|
+
facts for every session open there before `runner.attached` cites that same
|
|
254
|
+
boundary. Partial closure is retry-safe and an observed attachment therefore
|
|
255
|
+
proves all pre-boundary sessions closed; historical orphan-only logs keep their
|
|
256
|
+
old projection until an actual takeover records those facts. The supervisor
|
|
257
|
+
rechecks kernel-child liveness at the force boundary
|
|
258
|
+
and projects the same normal, forced, or abnormal result (with available
|
|
259
|
+
process/error detail) that the repository run-stopped evidence records. Ordinary
|
|
260
|
+
kernel teardown stops and reaps all build groups. Every build-child terminal
|
|
261
|
+
path — natural completion, failure, SIGINT/SIGTERM, and parent-watch death —
|
|
262
|
+
first starts exactly one detached `bin/ab-process-group-reaper.ts` while the
|
|
263
|
+
leader still pins its process-group identity. The helper targets only that
|
|
264
|
+
negative group id and applies the same bounded TERM-then-KILL teardown, so it
|
|
265
|
+
survives abrupt kernel death. The live local supervisor independently awaits
|
|
266
|
+
full-group disappearance before publishing completion and releasing its exact
|
|
267
|
+
lease; lease expiry remains the durable recovery fallback. The BuildStore lease
|
|
268
|
+
remains the cross-process and workspace-release gate. `packages/core/src/processes/dispatcher.ts`
|
|
269
|
+
counts actual schedules, not suppressed polls. Open session history is never a
|
|
270
|
+
lock: a legacy dead session may remain open, while an actual takeover closes it
|
|
271
|
+
explicitly.
|
|
272
|
+
|
|
273
|
+
**Store authority.** `packages/core/src/store/build-scope.ts` wraps every adapter with one
|
|
274
|
+
build's authority. Own-build record/event/artifact/lease/subscription calls
|
|
275
|
+
delegate; foreign-build, collection/admin, close, and repository-journal calls
|
|
276
|
+
raise `BuildScopeError`. The shared Store suite applies these checks to memory,
|
|
277
|
+
SQLite, and remote clients, while HTTP token scope remains defense in depth.
|
|
278
|
+
|
|
279
|
+
**Live configuration.** `packages/core/src/config/live.ts` owns the running dispatcher's
|
|
280
|
+
immutable last-valid main-checkout snapshot, exhaustive hot/restart field
|
|
281
|
+
classification, and eager role resolver. The watch loop refreshes it before
|
|
282
|
+
each tick and publishes the exact accepted TOML and the composed effective JSON
|
|
283
|
+
atomically with a run-correlated `dispatcher.config-reloaded` repository fact
|
|
284
|
+
before making the snapshot visible. Startup similarly publishes the effective
|
|
285
|
+
artifact before the first tick. Missing, unreadable, malformed, and
|
|
286
|
+
routing-invalid candidates retain that snapshot with a durable deduplicated
|
|
287
|
+
operator notice; restoring a valid file resumes ordinary reload. Dispatcher
|
|
288
|
+
ticks and build/harvest actions capture one snapshot at their own boundary; the
|
|
289
|
+
dashboard validates and projects only the referenced effective artifact, so an in-progress
|
|
290
|
+
turn or command is never interrupted. Scoped phase CLI processes retain their
|
|
291
|
+
separate build-worktree config boundary. Startup-built plugin, forge, ticket,
|
|
292
|
+
and workspace adapter fields stay pinned; changed values are durable restart
|
|
293
|
+
notices rather than partial adapter swaps. `--once` retains static startup
|
|
294
|
+
configuration.
|
|
295
|
+
|
|
296
|
+
**Harvest.** The dispatcher owns the threshold trigger and starts runs
|
|
297
|
+
fire-and-forget; `packages/core/src/processes/harvest.ts` is the deterministic core (scan,
|
|
298
|
+
source-aware originating-ticket lifecycle projection, filing-time blocker
|
|
299
|
+
resolution, occurrence identity, and the exhaustion partition),
|
|
300
|
+
`harvest-runner.ts` executes the staged workflow under the heartbeated
|
|
301
|
+
repository lease, records declared/derived blocker provenance, and
|
|
302
|
+
`packages/core/src/kernel/harvest.ts` reduces runs, claims, recovery history, and the
|
|
303
|
+
committed ledger with ordered parked/exhaustion/open selectors. Its pure
|
|
304
|
+
creation selectors pair reservation/filing facts, bound unmatched keys to
|
|
305
|
+
active runs, and conservatively union reservations first seen between the
|
|
306
|
+
repository snapshots bracketing a ready listing. `packages/core/src/processes/dispatcher.ts`
|
|
307
|
+
correlates those keys before dependency reads or claims, retaining queue depth
|
|
308
|
+
and emitting creation-specific tick diagnostics. The recovery
|
|
309
|
+
invariants are SPEC §12; the mechanics live in the reducer and its tests.
|
|
310
|
+
|
|
311
|
+
**Ticket sources.** `packages/core/src/ports/tickets/`. `listReady` is an explicit
|
|
312
|
+
partial-listing seam: individually malformed records come back as
|
|
313
|
+
diagnostics (surfaced by the dispatcher's tick report and `ab ticket list`
|
|
314
|
+
stderr) while tracker-wide invariant violations stay fatal — one broken
|
|
315
|
+
ticket never blocks unrelated dispatch, but nothing that could permit double
|
|
316
|
+
dispatch is tolerated. `Ticket.creationKey` is the optional stable external
|
|
317
|
+
create/adoption correlation, distinct from `Ticket.ref.id`; Linear projects its
|
|
318
|
+
issue UUID and file/fake preserve their idempotency metadata through create,
|
|
319
|
+
adoption, get, and list paths. Legacy/plugin tickets may omit it and dispatch
|
|
320
|
+
unchanged.
|
|
321
|
+
|
|
322
|
+
**Workspace, execution, and review base selection.**
|
|
323
|
+
`packages/core/src/ports/workspace/create.ts` resolves `[workspace].provider` against the
|
|
324
|
+
builtin-plus-plugin registry once during production wiring and pairs it with a
|
|
325
|
+
`BuildExecution` capability. A provider-supplied capability substitutes at
|
|
326
|
+
that seam; otherwise the shipped local subprocess capability is used. The builtin stays
|
|
327
|
+
store-root-aware; selected plugin factories receive their nested config,
|
|
328
|
+
environment, and absolute repository root. `WorkspaceHandle.ref` remains a
|
|
329
|
+
provider identifier, `path` is absolute inside the execution environment, and
|
|
330
|
+
optional `localPath` explicitly identifies dispatcher reachability. Local Forge
|
|
331
|
+
operations fall back to the main checkout when `localPath` is absent.
|
|
332
|
+
`packages/core/src/ports/workspace/git-worktree.ts` selects the branch-cut base once
|
|
333
|
+
at first creation, fetching into a build-scoped private ref; re-provisioning
|
|
334
|
+
resumes at the branch tip and never re-cuts, so the first provisioning fact
|
|
335
|
+
remains immutable provenance. Separately, each successful implementation terminal in
|
|
336
|
+
`packages/core/src/cli/terminals.ts` asks the Forge to snapshot its authoritative base when
|
|
337
|
+
that optional capability exists; otherwise it privately refreshes the frozen
|
|
338
|
+
target branch from `origin` and records
|
|
339
|
+
the unique merge-base of that snapshot and `HEAD` in `implement.completed`.
|
|
340
|
+
It fails before publication/deposit on fetch, ref, ancestry, or ambiguity
|
|
341
|
+
errors and writes neither `FETCH_HEAD` nor operator refs. Reconcile's
|
|
342
|
+
execution-time target refresh in `packages/core/src/processes/build-runner.ts` remains a
|
|
343
|
+
third, deliberately separate boundary and also fails closed.
|
|
344
|
+
|
|
345
|
+
The builtin `vercel-sandbox` adapter provisions an exact GitHub revision into a
|
|
346
|
+
fixed guest path. Fresh-environment bootstrap scrubs clone authority, installs
|
|
347
|
+
and verifies pinned Bun, serially runs repository-declared named system
|
|
348
|
+
provisioning through `sh -c` with provider root authority, installs the running
|
|
349
|
+
Autobuild distribution and repository dependencies, and only then writes the
|
|
350
|
+
readiness marker. Thus marked environments run the list once, while every new
|
|
351
|
+
replacement generation reproduces it before `[commands].setup` or any phase.
|
|
352
|
+
Step failures retain command/status/stdout/stderr, leave no marker, and flow
|
|
353
|
+
through durable `infrastructure.failed`, its bounded retry budget, shared status
|
|
354
|
+
and dashboard projection, and setup-targeted escalation; nested cleanup failure
|
|
355
|
+
does not erase the original diagnostic. Readiness uses the same bootstrap helper
|
|
356
|
+
in an always-deleted temporary sandbox and reports declared step names before
|
|
357
|
+
guest setup checks. The adapter then starts the same private build child with
|
|
358
|
+
environment supervision. Local children carry a positive parent PID and retain their
|
|
359
|
+
watchdog/process-group reaper; remote children cannot see a meaningful host PID,
|
|
360
|
+
so the detached SDK command plus VM stop owns full teardown. Scoped Store facts
|
|
361
|
+
are the only state channel. Remote terminals append `publication.requested` and
|
|
362
|
+
park. Only confirmed VM teardown plus execution-lease release permits the local
|
|
363
|
+
supervisor to use the provider's exact SHA/branch publication capability; a
|
|
364
|
+
rejected/uncertain executor completion leaves the request pending. The supervisor
|
|
365
|
+
verifies the remote head and records the ordinary completion; PR API operations
|
|
366
|
+
remain on the dispatcher. A failed finalize post-step publication records the
|
|
367
|
+
ordinary failure-tolerant step outcome and follow-up observation rather than
|
|
368
|
+
wedging the green build. Every guest launch first reasserts the normal
|
|
369
|
+
receive-pack-free network policy, so even a failed publication-policy restore
|
|
370
|
+
fails closed before setup or plugin code runs. Normal VM sessions never receive
|
|
371
|
+
Forge credentials.
|
|
372
|
+
|
|
373
|
+
**Forge credentials.** `packages/core/src/ports/forge/github-transport.ts` owns the
|
|
374
|
+
REST transport seam and credential resolution for the builtin GitHub forge:
|
|
375
|
+
`GITHUB_TOKEN`, then `GH_TOKEN`, then the gh CLI's stored login read through
|
|
376
|
+
`gh auth token --hostname github.com` under a bounded deadline. A transport resolves
|
|
377
|
+
lazily on its first request and asks its resolver again at most once per bounded
|
|
378
|
+
interval — after a miss, or after a `401` past that interval (a rotated login) — so a
|
|
379
|
+
miss is never frozen into anonymous access and nothing is re-probed per request. Nothing is probed at construction time; a request that had to
|
|
380
|
+
go out anonymously carries the miss reason (gh missing, not logged in to github.com,
|
|
381
|
+
timed out) in its error, in every process that holds a forge. Origin-mode dispatch — and therefore the hosted
|
|
382
|
+
dispatcher — requires an exported token before any side effect and never consults gh:
|
|
383
|
+
a checkout-less host has neither gh nor a keyring, and `vercel-sandbox` publication
|
|
384
|
+
injects that same token.
|
|
385
|
+
|
|
386
|
+
**Agent runtimes.** `packages/core/src/ports/runner/`: `runtime.ts` (capability-carrying
|
|
387
|
+
registry plus boundary validation), `routing.ts` (eager role resolver),
|
|
388
|
+
`production.ts` (shipped Claude/Codex/Pi registrations), `codex.ts` (direct
|
|
389
|
+
Codex `exec --json` subprocess protocol with native thread resume), `pi.ts` and
|
|
390
|
+
`pi-rpc.ts` (the local pi CLI prerequisite/auth probe and long-lived headless
|
|
391
|
+
RPC protocol, minimum version 0.84.3), `one-shot.ts` (optional tool-free
|
|
392
|
+
non-phase completions — slug naming via `packages/core/src/cli/dispatch.ts`, skill-conflict
|
|
393
|
+
proposals via `packages/core/src/cli/upgrade-agent.ts`), `provider-error.ts` (positive-only
|
|
394
|
+
permanent-failure classifier), and `session-env.ts` (per-turn environment merge
|
|
395
|
+
that fronts `bin/agent/ab` on `PATH`). The pi CLI owns its login and model
|
|
396
|
+
catalog; the shipped bridge limits tools and refreshes each turn's subprocess
|
|
397
|
+
environment without writing session state into the workspace. Adapters own
|
|
398
|
+
native error extraction; processes own durable failure policy — the transcript
|
|
399
|
+
is always deposited, and a turn's typed terminal always beats a late failure
|
|
400
|
+
signal.
|
|
401
|
+
|
|
402
|
+
**Plugin bootstrap and CLI composition.** `packages/core/src/plugins/load.ts` resolves
|
|
403
|
+
repository-path modules from the config-bearing root and bare packages from an
|
|
404
|
+
explicit package root (defaulting to that same root), validates each default
|
|
405
|
+
manifest/API range, and atomically registers normalized factories, provenance,
|
|
406
|
+
ticket credential metadata, and optional contract descriptors before production
|
|
407
|
+
wiring or the first dispatch tick. Its structured single-module attempt feeds
|
|
408
|
+
two policies: `loadPlugins` remains fail-fast for dispatch, while
|
|
409
|
+
`diagnosePlugins` collects ordered failures and retains later healthy
|
|
410
|
+
registrations for `ab plugin doctor`. `packages/core/src/cli/plugin.ts` owns the sessionless
|
|
411
|
+
list/doctor/test grammar and live gate; `packages/core/src/plugins/contract-entry.ts` reloads
|
|
412
|
+
one selected registration inside a real `bun test` process and registers exactly
|
|
413
|
+
one unchanged port suite.
|
|
414
|
+
|
|
415
|
+
`packages/core/src/ports/forge/create.ts` resolves the root `forge` selector, constructs the
|
|
416
|
+
shipped GitHub or local-git adapter, or lazily invokes a registered plugin
|
|
417
|
+
factory, and preserves the returned adapter's optional capabilities. The
|
|
418
|
+
local-git adapter in `packages/core/src/ports/forge/local-git.ts` stores versioned JSON PR
|
|
419
|
+
records as blobs behind private `refs/autobuild/local-git/` refs in the shared
|
|
420
|
+
Git database. It computes mergeability with `git merge-tree`, leaves the build
|
|
421
|
+
branch reachable, and lands a guarded single-parent squash locally. Immediately
|
|
422
|
+
before offering an ungated landing candidate, `git var GIT_AUTHOR_IDENT` and
|
|
423
|
+
`git var GIT_COMMITTER_IDENT` prove that ordinary Git identity resolution can
|
|
424
|
+
succeed; a failure becomes a reason-bearing, retryable consent deferral. The
|
|
425
|
+
`git commit-tree` seam inherits that resolved identity without injecting an
|
|
426
|
+
Autobuild author or committer, while `-c commit.gpgSign=false` keeps the landing
|
|
427
|
+
unsigned. For a checked-out base, dry-run and real
|
|
428
|
+
`git read-tree -m -u <old> <landed>` calls
|
|
429
|
+
let Git carry forward non-overlapping operator changes and report colliding
|
|
430
|
+
paths. The pending landing precedes the guarded ref update; a later poll retries
|
|
431
|
+
the same two-tree checkout transition across the crash window and observes the
|
|
432
|
+
PR as merged only after synchronization succeeds. Forge-native base snapshotting lets
|
|
433
|
+
it pin the current local base without `origin`, while capability-less adapters
|
|
434
|
+
retain the legacy private-ref fetch path. Dispatch constructs one
|
|
435
|
+
selected adapter before opening the store and threads it through runners,
|
|
436
|
+
epilogue, and janitor work. Scoped `packages/core/src/cli/binary.ts` processes independently
|
|
437
|
+
load immutable config and repository-path plugins from the build worktree, use
|
|
438
|
+
`resolveMainRepo` to locate the consuming checkout only for bare-package lookup,
|
|
439
|
+
and resolve the same adapter name for phase terminal plumbing. This keeps
|
|
440
|
+
package availability independent of local-store/worktree placement without
|
|
441
|
+
redirecting branch-owned plugin source or factory `repoRoot` away from the
|
|
442
|
+
worktree. `packages/core/src/ports/workspace/create.ts` similarly resolves
|
|
443
|
+
`[workspace].provider`, retaining host-owned git-worktree construction while
|
|
444
|
+
passing plugin config, environment, and repository root to registered
|
|
445
|
+
factories. Ticket-source selection is registry-backed in
|
|
446
|
+
`packages/core/src/ports/tickets/create.ts`; dispatch and sessionless `ab ticket` commands
|
|
447
|
+
load plugins before constructing it.
|
|
448
|
+
|
|
449
|
+
`packages/core/src/plugins/runtimes.ts` invokes plugin runtime factories in registration
|
|
450
|
+
order, validates their capability-bearing registrations, and returns one fresh
|
|
451
|
+
registry containing builtins and plugins. Dispatch performs that composition
|
|
452
|
+
before eager role resolution and shares the result with build, harvest, and
|
|
453
|
+
slug routing. Upgrade performs the same composition lazily at its first merge
|
|
454
|
+
conflict.
|
|
455
|
+
|
|
456
|
+
`packages/core/src/cli/repo-state.ts` owns repository identity and store precedence
|
|
457
|
+
(`--store` > `AB_STORE` > `.autobuild/`); `packages/core/src/cli/store-opening.ts` is the
|
|
458
|
+
production store composition boundary shared by finite sessionless queries and
|
|
459
|
+
phase sessions. Its shared scoping primitive preserves remote token composition
|
|
460
|
+
and adds local ambient authority only for filesystem stores. The dedicated
|
|
461
|
+
ambient-read opener classifies identity before repository or Store opening and
|
|
462
|
+
is adopted only by `ab builds`, `ab build status`, and `ab artifact download`;
|
|
463
|
+
all other sessionless commands keep the generic unwrapped opener.
|
|
464
|
+
`packages/core/src/cli/repository-status.ts` consumes that boundary and the kernel's
|
|
465
|
+
`reduceDispatchSettings` projection to report journal-backed dispatcher
|
|
466
|
+
controls without ensuring a repository stream or starting dispatcher work.
|
|
467
|
+
`packages/core/src/cli/args.ts` parses command-scoped flag contracts; `packages/core/src/cli/binary.ts`
|
|
468
|
+
classifies build/harvest session tuples and routes sessionless invocations, so
|
|
469
|
+
phase-only commands report their complete runner context when run by hand.
|
|
470
|
+
|
|
471
|
+
**PR attachments.** `packages/core/src/cli/artifact.ts` atomically turns an explicit
|
|
472
|
+
`artifact put --attach` into an exact artifact plus designation fact.
|
|
473
|
+
`packages/core/src/kernel/pr-attachments.ts` selects current designations, hosted
|
|
474
|
+
correlations, and pending cleanup without coupling to a producer or verify-step
|
|
475
|
+
name. `packages/core/src/cli/pr-attachments.ts` performs optional image hosting through the
|
|
476
|
+
narrow Forge capability, while `packages/core/src/cli/pr-summary.ts` renders the same complete
|
|
477
|
+
text projection for finalize and late designations. The GitHub release transport
|
|
478
|
+
lives in `packages/core/src/ports/forge/github-pr-attachments.ts`; terminal-build reclamation
|
|
479
|
+
and retry facts remain dispatcher janitor duty.
|
|
480
|
+
|
|
481
|
+
**Abort control and cleanup.** CLI and dashboard call the same
|
|
482
|
+
`packages/core/src/cli/build-control.ts` service. A confirmed dashboard `a` action appends only
|
|
483
|
+
the durable abort request. After claiming the build lease, `build-runner.ts`
|
|
484
|
+
acknowledges an already-pending pause or abort before workspace setup, without
|
|
485
|
+
appending `runner.attached`; resume and workspace-using decisions stay behind
|
|
486
|
+
successful setup. For a request arriving during an AgentRunner turn, the runner
|
|
487
|
+
observes the BuildStore subscription, forwards an `AbortSignal`, deposits/ends
|
|
488
|
+
the session without a phase failure, and acknowledges abort. The execution
|
|
489
|
+
supervisor keeps the lease until every local descendant is reaped. `dispatcher.ts`
|
|
490
|
+
defers destructive abort, discard, and terminal-PR cleanup while that lease is
|
|
491
|
+
live, then resumes the event-checkpointed janitor saga that closes an unmerged PR,
|
|
492
|
+
releases the workspace, deletes exact remote/local branch
|
|
493
|
+
refs, unions `autobuild:aborted` into current ticket labels, returns the ticket to
|
|
494
|
+
Triage, and appends abandoned completion last. Forge close/delete operations are
|
|
495
|
+
optional API 1.2 capabilities so older plugins load but leave cleanup visibly due.
|
|
496
|
+
AgentRunner failure causes and the exhaustion contract fixture are additive
|
|
497
|
+
plugin API 1.3 surfaces; legacy failures without a cause retain permanent-bit
|
|
498
|
+
behavior.
|
|
499
|
+
|
|
500
|
+
**Dashboard.** `packages/core/src/cli/dispatch-frontend.ts` is a Store-only terminal adapter:
|
|
501
|
+
it has no ticket, forge, workspace-provider, LiveConfig, or runtime dependency.
|
|
502
|
+
It follows one dispatch run's repository facts incrementally through
|
|
503
|
+
`packages/core/src/kernel/dispatch-status.ts`, retaining only low-volume settings/Harvest
|
|
504
|
+
facts for their replay reducers, validates/caches its effective-config artifact,
|
|
505
|
+
and polls build streams independently while elapsed paints continue from cached
|
|
506
|
+
intervals. The same polling path calls the canonical
|
|
507
|
+
`scanUnclaimedObservations` BuildStore reduction for the header's current count
|
|
508
|
+
and pairs it with the effective config's `policy.harvestThreshold`. That sample
|
|
509
|
+
is process-local presentation state: a failed refresh preserves the last
|
|
510
|
+
successful value and adds a local diagnostic, while an initial failure delays
|
|
511
|
+
the complete frame rather than inventing zero. No repository fact transports
|
|
512
|
+
it, and the headless child does not scan for presentation. Navigation is
|
|
513
|
+
synchronous presentation state; only Store reads and writes enter its UI action
|
|
514
|
+
queue. The supervised kernel child owns every slow
|
|
515
|
+
adapter operation, so slug naming, provisioning, runners, and Harvest cannot
|
|
516
|
+
block input.
|
|
517
|
+
|
|
518
|
+
`packages/core/src/cli/build-progress.ts` projects the exact last-event, heartbeat, and lease
|
|
519
|
+
inputs shared by the diagnostic `ab builds` and `ab build status` surfaces. Its
|
|
520
|
+
one-hour `diverged` predicate is presentation-only: reducer status, engine
|
|
521
|
+
routing, and lease health remain independent. `packages/core/src/cli/dashboard/model.ts` is
|
|
522
|
+
the event-derived build-row projection; `poll.ts` reprojects rows for event or
|
|
523
|
+
effective-config changes and reuses them across heartbeat/lease-only renewals
|
|
524
|
+
while retaining the cached log and reduction.
|
|
525
|
+
`detail.ts` projects chronological session history from the same retained log,
|
|
526
|
+
including a distinct transcriptless `reclaimed` ending, and `transcript.ts`
|
|
527
|
+
heuristically presents ordinary opaque transcript artifacts with a raw
|
|
528
|
+
fallback. `render.ts` composes the list, build-detail, and transcript as
|
|
529
|
+
cell-honest Unicode frames; `keyboard.ts` owns Kitty keyboard-protocol
|
|
530
|
+
negotiation and CSI-u decoding, while `live.ts` owns normal teardown and
|
|
531
|
+
sequences its push and pop with the alternate-screen region because the
|
|
532
|
+
terminal's keyboard flag stack is per-screen. Every mode enters and leaves through
|
|
533
|
+
the declarations and active ledger in `terminal-restore.ts`; `binary.ts` installs a dispatch-only synchronous
|
|
534
|
+
process-boundary fallback over that same ledger for faults and terminating
|
|
535
|
+
signals that bypass normal teardown. `poll.ts` is a display-only incremental
|
|
536
|
+
cache (the logs remain authoritative — cache loss just
|
|
537
|
+
rehydrates); `frame-image.ts` renders a deterministic PNG with pinned fonts.
|
|
538
|
+
`composer.ts` owns the text geometry the blocked-resume panel edits against —
|
|
539
|
+
display-cell wrapping and caret layout, plus cursor motions expressed as UTF-16
|
|
540
|
+
string offsets normalized to extended-grapheme boundaries — as pure, ANSI-free
|
|
541
|
+
arithmetic shared by `render.ts` and `dispatch.ts`.
|
|
542
|
+
Nested navigation, session selection, and pinned artifact retrieval are
|
|
543
|
+
read-only process-local UI concerns. Build actions still use the shared control
|
|
544
|
+
service and append human facts; the header shows acknowledged durable state,
|
|
545
|
+
never optimistic intent. Forge mutation stays in dispatcher plumbing.
|
|
546
|
+
|
|
547
|
+
**Agent tool registry.** `packages/core/src/operator/registry.ts` is the agent-facing
|
|
548
|
+
face of the operator services: one closed table of typed tools whose handlers call
|
|
549
|
+
the same control, query, ticket, and artifact services the operator API routes call
|
|
550
|
+
(`operator/control.ts`, `operator/query.ts`, `operator/tickets.ts`), with the
|
|
551
|
+
route-level glue re-derived beside it in `operator/requests.ts` and tool/route parity
|
|
552
|
+
proven per tool by `operator/registry.contract.test.ts`. Every binding is generated
|
|
553
|
+
from the table and never widens beyond the operator services: the shipped one is
|
|
554
|
+
`packages/core/src/cli/mcp.ts` (`ab mcp`, a stdio MCP server over the registry that
|
|
555
|
+
fails closed inside a phase, exactly as repository-wide `ab builds` does); the
|
|
556
|
+
embedded orchestrator and later transports register from the same table. Checked-in
|
|
557
|
+
risk classes live in `operator/annotations.ts` (SPEC §8.9).
|
|
558
|
+
|
|
559
|
+
**Init and upgrade.** `packages/core/src/cli/init.ts` owns deterministic skill vendoring,
|
|
560
|
+
ignore maintenance, runtime probes, and the stack-neutral first config. It then
|
|
561
|
+
launches an interactive agent CLI, or prints the identical short prompt, telling
|
|
562
|
+
the setup agent to read the installed
|
|
563
|
+
`.agents/skills/ab-guide/references/setup.md`; this bypasses all build and
|
|
564
|
+
BuildStore session plumbing. Existing config is never reconciled, even with
|
|
565
|
+
`--force`. `packages/core/src/cli/upgrade.ts` owns the pristine × local × incoming skill merge,
|
|
566
|
+
the provenance-safe fixed retirement of obsolete defaults, and all writes:
|
|
567
|
+
agent output is an untrusted proposal validated before anything touches disk,
|
|
568
|
+
and every failure path leaves live and pristine byte-untouched.
|
|
569
|
+
|
|
570
|
+
## Development
|
|
571
|
+
|
|
572
|
+
```sh
|
|
573
|
+
bun install
|
|
574
|
+
bun run check # Biome lint + format, zero diagnostics
|
|
575
|
+
bun test # unit tests, colocated *.test.ts
|
|
576
|
+
bun typecheck # tsc --noEmit
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
For dashboard presentation work, run the repository-only hot CLI:
|
|
580
|
+
|
|
581
|
+
```sh
|
|
582
|
+
bun run dev -- dispatch
|
|
583
|
+
# Generic form: bun run dev -- <ab arguments>
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
Bun keeps the original CLI promise and its `DispatchLoop` alive while hot
|
|
587
|
+
module evaluation replaces only the renderer used by the next repaint. Edits
|
|
588
|
+
to `packages/core/src/cli/dashboard/render.ts` and presentation-only dependencies imported
|
|
589
|
+
by it appear without restarting runners, releasing leases, or stacking input
|
|
590
|
+
handlers. Changes to dispatcher logic, dashboard model/controller logic,
|
|
591
|
+
keyboard handling, or build-runner code still require a restart. The
|
|
592
|
+
installed `ab` binary remains the non-watching production entry.
|
|
593
|
+
|
|
594
|
+
### Contract suites
|
|
595
|
+
|
|
596
|
+
The seams are the contract. Five reusable contract families run the same
|
|
597
|
+
behavioral assertions against every implementation:
|
|
598
|
+
|
|
599
|
+
- `packages/core/src/store/contract.ts` — `BuildStore` and `BlobStore`, including the streams block (§7.6) every adapter runs;
|
|
600
|
+
- `packages/core/src/ports/tickets/contract.ts` — `TicketSource`;
|
|
601
|
+
- `packages/core/src/ports/workspace/contract.ts` — `WorkspaceProvider`;
|
|
602
|
+
- `packages/core/src/ports/forge/contract.ts` — `Forge`, including idempotent PR close and
|
|
603
|
+
branch deletion with merged-race preservation;
|
|
604
|
+
- `packages/core/src/ports/runner/contract.ts` — `AgentRunner` session/continuation,
|
|
605
|
+
transcript metadata and usage, typed failure permanence/cause, per-turn
|
|
606
|
+
ambient environment refresh and cancellation, distribution-managed `ab`
|
|
607
|
+
resolution, and the optional tool-free one-shot capability.
|
|
608
|
+
|
|
609
|
+
`packages/core/src/ports/runner/routing.ts` eagerly resolves every role's primary, ordered
|
|
610
|
+
alternate targets, and independently inherited build-session budget.
|
|
611
|
+
`build-runner.ts` and `harvest-runner.ts` own the deterministic
|
|
612
|
+
primary-first attempt loop: each substitution opens a new session bracket,
|
|
613
|
+
records provenance on its start, and only complete-chain exhaustion consumes an
|
|
614
|
+
existing phase/session attempt. This keeps runtime availability routing out of
|
|
615
|
+
agent judgment while preserving transcript and artifact actor attribution.
|
|
616
|
+
|
|
617
|
+
A normal `bun test` runs the memory/fake/local registrations, including a fake
|
|
618
|
+
selected through the plugin ticket-source registry, the real filesystem and
|
|
619
|
+
local-git adapters, the injected Claude and Codex CLI subprocess contracts,
|
|
620
|
+
and the injected Pi CLI/RPC contract.
|
|
621
|
+
Both `ab dispatch` and sessionless `ab ticket` load the repository's plugins
|
|
622
|
+
before selecting their TicketSource; dispatch passes that one adapter instance
|
|
623
|
+
through readiness, dependency, harvest, and completion paths. The Linear,
|
|
624
|
+
GitHub, and real-runtime AgentRunner registrations are present in the same run
|
|
625
|
+
but reported as skipped: live provider access requires credentials/resources
|
|
626
|
+
and an explicit opt-in. When
|
|
627
|
+
adding an adapter, start from its contract suite, not only the interface.
|
|
628
|
+
|
|
629
|
+
To run the Linear contract manually against a destructive scratch target:
|
|
630
|
+
|
|
631
|
+
```sh
|
|
632
|
+
AB_RUN_LIVE_PORT_CONTRACTS=1 \
|
|
633
|
+
LINEAR_API_KEY=… \
|
|
634
|
+
AB_LINEAR_CONTRACT_TEAM_KEY=SCRATCH \
|
|
635
|
+
AB_LINEAR_CONTRACT_PROJECT_ID=… \
|
|
636
|
+
bun test packages/core/src/ports/tickets/linear.live.test.ts
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
The token must be able to create, update, relate, and archive issues in the
|
|
640
|
+
configured project, and to create and delete issue labels in the configured
|
|
641
|
+
team. The team needs a claimable `unstarted` or `backlog` state, a `started`
|
|
642
|
+
state, a `completed` or `canceled` state, and at least one issue label the
|
|
643
|
+
contract can replace/clear. Every issue gets a reserved UUID and is attached to
|
|
644
|
+
that project. Cleanup archives those issues and deletes the fresh team labels
|
|
645
|
+
created by the unknown-label contract cases; failures are reported so leaked
|
|
646
|
+
fixtures can be removed manually. Use a project with no real work in it.
|
|
647
|
+
|
|
648
|
+
To run the GitHub contract manually:
|
|
649
|
+
|
|
650
|
+
```sh
|
|
651
|
+
AB_RUN_LIVE_PORT_CONTRACTS=1 \
|
|
652
|
+
GH_TOKEN=… \
|
|
653
|
+
AB_GITHUB_CONTRACT_REPO=owner/destructive-scratch-repo \
|
|
654
|
+
bun test packages/core/src/ports/forge/github.live.test.ts
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
`GITHUB_TOKEN` may be used instead of `GH_TOKEN`. The repository must have
|
|
658
|
+
native auto-merge enabled, an initialized default branch, no inherited
|
|
659
|
+
merge-blocking rule that catches the UUID-namespaced contract branches, and a
|
|
660
|
+
token with repository admin, contents, pull-request, comment, and branch
|
|
661
|
+
protection permissions. The fixture creates and deletes temporary branches,
|
|
662
|
+
PRs, comments, and a required-check protection rule; it never pushes to or
|
|
663
|
+
merges into the default branch. Use a dedicated scratch repository only.
|
|
664
|
+
|
|
665
|
+
The deterministic Claude, Codex, and Pi adapter contracts run offline in every
|
|
666
|
+
normal test run. Their live registrations add real transport/authentication smoke
|
|
667
|
+
coverage for successful start, continue, end, environment refresh, managed CLI
|
|
668
|
+
execution, and one-shot completion:
|
|
669
|
+
|
|
670
|
+
```sh
|
|
671
|
+
AB_RUN_LIVE_PORT_CONTRACTS=1 \
|
|
672
|
+
AB_CLAUDE_CONTRACT_MODEL=claude-sonnet-4-… \
|
|
673
|
+
bun test packages/core/src/ports/runner/claude.live.test.ts
|
|
674
|
+
|
|
675
|
+
AB_RUN_LIVE_PORT_CONTRACTS=1 \
|
|
676
|
+
AB_CODEX_CONTRACT_MODEL=gpt-… \
|
|
677
|
+
bun test packages/core/src/ports/runner/codex.live.test.ts
|
|
678
|
+
|
|
679
|
+
AB_RUN_LIVE_PORT_CONTRACTS=1 \
|
|
680
|
+
AB_PI_CONTRACT_MODEL=openai/gpt-… \
|
|
681
|
+
bun test packages/core/src/ports/runner/pi.live.test.ts
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
Claude uses the locally installed Claude Code CLI and its configured login; the
|
|
685
|
+
live command therefore requires an installed `claude` executable whose browser
|
|
686
|
+
login has already completed. Its offline suite injects a subprocess executor
|
|
687
|
+
and covers direct argv, native resume, stream-json parsing, usage, transcripts,
|
|
688
|
+
and failure classification without launching the CLI. The one-shot argument
|
|
689
|
+
set was checked against Claude Code 2.1.245 `--help` and [Anthropic's CLI
|
|
690
|
+
reference](https://code.claude.com/docs/en/cli-reference): `-p` produces one
|
|
691
|
+
non-interactive result, `--no-session-persistence` prevents resumable storage,
|
|
692
|
+
`--tools ""` disables built-in tools, and `--disallowedTools "mcp__*"` denies
|
|
693
|
+
MCP tools. This is compatibility evidence, not a repository-wide minimum
|
|
694
|
+
version. Codex similarly uses the locally installed `codex` executable after
|
|
695
|
+
`codex login`; its offline suite
|
|
696
|
+
pins direct argv, `$skill` invocation, JSONL parsing, native thread resume,
|
|
697
|
+
startup diagnostics, and tool-free one-shot rejection.
|
|
698
|
+
|
|
699
|
+
Pi requires a locally installed `pi` executable at version 0.84.3 or newer. The
|
|
700
|
+
full AgentRunner smoke uses that installation's login and model catalog for the
|
|
701
|
+
authenticated provider named in `AB_PI_CONTRACT_MODEL`. The same live file also
|
|
702
|
+
checks production extension gating against two packages installed and enabled
|
|
703
|
+
in the operator's user-visible Pi settings:
|
|
704
|
+
|
|
705
|
+
```sh
|
|
706
|
+
pi install npm:pi-subagents
|
|
707
|
+
pi install npm:pi-web-access
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
That package probe does not invoke a provider and can be selected without
|
|
711
|
+
`AB_PI_CONTRACT_MODEL`:
|
|
712
|
+
|
|
713
|
+
```sh
|
|
714
|
+
AB_RUN_LIVE_PORT_CONTRACTS=1 \
|
|
715
|
+
bun test packages/core/src/ports/runner/pi.live.test.ts -t 'gates tools discovered'
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
Once opted in, the probe fails with the missing expected tool and its exact
|
|
719
|
+
`pi install` remediation if either package is not discoverable; it never skips
|
|
720
|
+
and implies package coverage ran. The live fixtures create isolated temporary
|
|
721
|
+
project skills, extensions, and probe files and remove them after each run;
|
|
722
|
+
provider failures remain in the deterministic injected adapter contracts
|
|
723
|
+
because they cannot be manufactured safely against a live account.
|
|
724
|
+
|
|
725
|
+
Provisioning or scheduling these credentials/resources in CI is deliberately
|
|
726
|
+
out of scope; live runs remain explicit.
|