@defrex/autobuild 0.11.0 → 0.12.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/README.md +3 -1
- package/SPEC.md +222 -22
- package/docs/architecture.md +66 -4
- package/docs/configuration.md +105 -16
- package/docs/hosted-dispatcher.md +17 -2
- package/docs/hosted-service.md +214 -0
- package/docs/mcp.md +8 -2
- package/docs/operator-api.md +90 -7
- package/docs/remote-store-protocol.md +189 -144
- package/docs/remote-ticket-protocol.md +107 -19
- package/docs/setup.md +173 -16
- package/docs/ticket-dependencies.md +1 -1
- package/package.json +7 -6
- package/packages/core/src/cli/attention.ts +209 -0
- package/packages/core/src/cli/configured-store.ts +17 -0
- package/packages/core/src/cli/connect.ts +261 -0
- package/packages/core/src/cli/dashboard/model.ts +4 -5
- package/packages/core/src/cli/dispatch.ts +183 -41
- package/packages/core/src/cli/help.ts +39 -10
- package/packages/core/src/cli/init-validation.ts +27 -2
- package/packages/core/src/cli/main.ts +41 -15
- package/packages/core/src/cli/mcp.ts +7 -1
- package/packages/core/src/cli/pr-summary-publication.ts +220 -0
- package/packages/core/src/cli/pr-summary.ts +2 -0
- package/packages/core/src/cli/project-credentials.ts +132 -0
- package/packages/core/src/cli/repo-state.ts +15 -2
- package/packages/core/src/cli/self-update.ts +10 -0
- package/packages/core/src/cli/store-opening.ts +22 -14
- package/packages/core/src/cli/terminals.ts +0 -10
- package/packages/core/src/cli/ticket.ts +8 -1
- package/packages/core/src/cli/upgrade-compatibility.ts +80 -0
- package/packages/core/src/cli/wait.ts +84 -17
- package/packages/core/src/cli/watch.ts +197 -60
- package/packages/core/src/config/live.ts +3 -0
- package/packages/core/src/config/schema.ts +56 -9
- package/packages/core/src/connection.ts +86 -0
- package/packages/core/src/events/catalog.ts +10 -2
- package/packages/core/src/events/payloads.ts +44 -0
- package/packages/core/src/events/repository.ts +13 -0
- package/packages/core/src/kernel/__snapshots__/reducer-registry.test.ts.snap +130 -83
- package/packages/core/src/kernel/engine.ts +24 -0
- package/packages/core/src/kernel/generators/build-log.ts +10 -0
- package/packages/core/src/kernel/log-index.ts +17 -0
- package/packages/core/src/kernel/pr-summary.ts +89 -0
- package/packages/core/src/kernel/reducer-registry.ts +8 -0
- package/packages/core/src/kernel/reducer.ts +8 -0
- package/packages/core/src/ontology.ts +1 -0
- package/packages/core/src/operator/index.ts +7 -0
- package/packages/core/src/operator/query.ts +38 -16
- package/packages/core/src/operator/ticket-source-backend.ts +1 -0
- package/packages/core/src/operator/tickets.ts +6 -8
- package/packages/core/src/plugin-sdk/index.ts +1 -0
- package/packages/core/src/plugins/manifest.ts +5 -3
- package/packages/core/src/plugins/runtimes.ts +3 -1
- package/packages/core/src/ports/forge/fake.ts +13 -1
- package/packages/core/src/ports/forge/github-transport.ts +36 -1
- package/packages/core/src/ports/forge/github.ts +29 -5
- package/packages/core/src/ports/forge/local-git.ts +12 -4
- package/packages/core/src/ports/forge/summary-marker.ts +8 -0
- package/packages/core/src/ports/runner/session-env.ts +1 -0
- package/packages/core/src/ports/tickets/create.ts +11 -3
- package/packages/core/src/ports/tickets/hosted-index.ts +0 -3
- package/packages/core/src/ports/tickets/remote-protocol.ts +1 -0
- package/packages/core/src/ports/tickets/remote.ts +1 -0
- package/packages/core/src/ports/workspace/build-execution.ts +5 -1
- package/packages/core/src/ports/workspace/create.ts +11 -2
- package/packages/core/src/ports/workspace/distribution-archive.ts +3 -5
- package/packages/core/src/ports/workspace/harvest-execution.ts +3 -1
- package/packages/core/src/ports/workspace/local-build-execution.ts +8 -1
- package/packages/core/src/ports/workspace/vercel-sandbox.ts +47 -19
- package/packages/core/src/processes/build-execution-state.ts +1 -1
- package/packages/core/src/processes/build-runner.ts +87 -26
- package/packages/core/src/processes/dispatch-failure-budget.ts +83 -0
- package/packages/core/src/processes/dispatcher.ts +59 -10
- package/packages/core/src/processes/harvest-child.ts +1 -0
- package/packages/core/src/processes/harvest-execution-state.ts +19 -2
- package/packages/core/src/processes/harvest-runner.ts +142 -100
- package/packages/core/src/processes/phase-failure-budget.ts +1 -0
- package/packages/core/src/processes/publication-loss.ts +18 -1
- package/packages/core/src/store/remote/client.ts +1 -1
- package/packages/core/src/store/remote/compatibility.ts +90 -0
- package/packages/core/src/store/remote/credentials.ts +28 -0
- package/packages/core/src/store/remote/index.ts +14 -1
- package/packages/core/src/store/remote/protocol.ts +25 -0
- package/packages/core/src/store/remote/token.ts +74 -13
- package/packages/core/src/testing/index.ts +7 -0
- package/skills/guide/SKILL.md +144 -26
- package/skills/guide/references/operator-api.md +135 -13
- package/skills/guide/references/plugin-authoring.md +10 -2
- package/skills/guide/references/remote-store-protocol.md +189 -144
- package/skills/guide/references/remote-ticket-protocol.md +111 -18
- package/skills/guide/references/setup.md +173 -16
- package/skills/guide/references/ticket-dependencies.md +1 -1
- package/skills/operate/SKILL.md +126 -36
- package/templates/hosted-service/package.json +13 -0
- package/templates/hosted-service/vercel.json +7 -0
package/docs/configuration.md
CHANGED
|
@@ -14,6 +14,18 @@ and sessionless `ab init --validate` readiness check. Examples labelled as
|
|
|
14
14
|
fragments are intended to be added to an existing file; the [complete
|
|
15
15
|
example](#complete-example) is valid on its own.
|
|
16
16
|
|
|
17
|
+
## `[store]`
|
|
18
|
+
|
|
19
|
+
| Key | Required | Values / purpose |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| `url` | When `[store]` exists | Absolute HTTPS service base URL; loopback HTTP is allowed for development. No credentials, query or fragment. Trailing slashes are normalized. |
|
|
22
|
+
|
|
23
|
+
Selection is explicit `--store` > nonblank `AB_STORE` > `[store] url` > the main
|
|
24
|
+
checkout's `.autobuild/`. A configured service without a user credential fails
|
|
25
|
+
with `ab connect` guidance. `AB_TOKEN` overrides the saved service/project
|
|
26
|
+
credential. See [connecting a project](hosted-service.md#connect-a-project).
|
|
27
|
+
Changing the store requires restarting dispatch.
|
|
28
|
+
|
|
17
29
|
## Hosted service and PostgreSQL BuildStore environment
|
|
18
30
|
|
|
19
31
|
The optional `@defrex/autobuild-hosted-store-service` and its
|
|
@@ -59,14 +71,14 @@ separate signed-user token described by the [operator API](operator-api.md).
|
|
|
59
71
|
| `AB_HOST` | Optional, ordinary Bun host | Bind hostname; defaults to `0.0.0.0`. Vercel supplies its own listener. |
|
|
60
72
|
| `PORT` | Optional, ordinary Bun host | Integer 1–65535; defaults to `3000`. Vercel supplies its own listener. |
|
|
61
73
|
| `AB_STORE` | Remote client | Hosted service base URL used by the kernel, phase commands, and dashboard. |
|
|
62
|
-
| `AB_TOKEN` | Authenticated remote client |
|
|
74
|
+
| `AB_TOKEN` | Authenticated remote client | Explicit project bearer credential override for CI; otherwise use ab connect. This is not the signing secret. |
|
|
63
75
|
| `BETTER_AUTH_SECRET` | Web dashboard | Independent server-only session secret with at least 32 high-entropy characters. |
|
|
64
76
|
| `BETTER_AUTH_URL` | Web dashboard | Exact HTTP(S) origin, without credentials or a path; HTTPS is mandatory in production. |
|
|
65
77
|
| `GITHUB_CLIENT_ID` | GitHub sign-in | OAuth application client id. |
|
|
66
78
|
| `GITHUB_CLIENT_SECRET` | GitHub sign-in | Server-only OAuth application secret. |
|
|
67
79
|
| `AB_WEB_AUTH_PROVIDERS` | Web dashboard | Comma-separated provider set; currently exactly `github`. |
|
|
68
80
|
| `AB_WEB_ALLOWED_EMAILS` | Web dashboard | Nonempty comma-separated operator email allowlist; matching is case-insensitive. |
|
|
69
|
-
| `AB_WEB_REPOSITORIES` |
|
|
81
|
+
| `AB_WEB_REPOSITORIES` | Hosted service | Deprecated once-per-database bootstrap CSV for the durable project registry. Use owner commands thereafter; see [connected projects](setup.md#connected-projects). |
|
|
70
82
|
|
|
71
83
|
GitHub's callback is `{BETTER_AUTH_URL}/api/auth/callback/github`; the app needs
|
|
72
84
|
the `user:email` scope (or GitHub App read-only email permission). Sessions are
|
|
@@ -212,6 +224,7 @@ remain pinned to their startup values and are reported explicitly:
|
|
|
212
224
|
|
|
213
225
|
| Restart-required field | Reason |
|
|
214
226
|
|---|---|
|
|
227
|
+
| `store` | Store selection and project authority are fixed when dispatch starts. |
|
|
215
228
|
| `plugins` | Plugin modules and registration catalogs load before wiring. |
|
|
216
229
|
| `forge` | Selects the constructed Forge adapter. |
|
|
217
230
|
| `workspace.provider`, `workspace.config` | Select and configure the constructed workspace provider. |
|
|
@@ -357,7 +370,7 @@ manifest parse), and each `capabilities.requiredEnv` group must declare at
|
|
|
357
370
|
least one of `dispatchMessage` / `validationMessage` — a group with neither is
|
|
358
371
|
rejected at manifest parse, because the host would silently skip it at both
|
|
359
372
|
enforcement sites. API 1.7 extends the workspace-provider factory context with
|
|
360
|
-
the host-derived seams: `storeRef` and `
|
|
373
|
+
the host-derived seams: `storeRef` and `delegateCredential` (guaranteed present under
|
|
361
374
|
`capabilities.storeRequirements`), `runtimeReferences`, and the checkout-less
|
|
362
375
|
`origin` and `remoteBranchHead` readers, all optional and ignored by factories
|
|
363
376
|
that do not read them. A plugin reading the new seams should require `^1.7.0`.
|
|
@@ -631,7 +644,7 @@ no longer matches the identity the current system would deliver is refreshed
|
|
|
631
644
|
by reinstalling the archive before reuse, so an upgraded dispatcher retrofits
|
|
632
645
|
its persistent guests (see "Guest distribution version selection and delivery"
|
|
633
646
|
in docs/setup.md for the release-and-upgrade delivery path and the hosted
|
|
634
|
-
store's
|
|
647
|
+
store's supported client window). Immediately
|
|
635
648
|
before every build-child launch, the adapter verifies the
|
|
636
649
|
provisioned absolute Bun executable and every referenced runtime again. A
|
|
637
650
|
failure names the runtime, selecting role/alternate, stage, and provisioning
|
|
@@ -757,6 +770,28 @@ as written.
|
|
|
757
770
|
|
|
758
771
|
## `[verify]` and `[verify.<step>]`
|
|
759
772
|
|
|
773
|
+
Post-reconcile verification defaults to enabled: `[verify].afterReconcile = true`.
|
|
774
|
+
Set it to `false` to retain pre-reconcile verification and skip all steps after
|
|
775
|
+
reconciliation. An optional boolean `[verify.<step>].afterReconcile` overrides
|
|
776
|
+
the repository setting in either direction; overrides require a configured step.
|
|
777
|
+
For example, set `afterReconcile = false` in `[verify]` and
|
|
778
|
+
`afterReconcile = true` in `[verify.types]` to keep only that step re-running.
|
|
779
|
+
|
|
780
|
+
The kernel freezes the resolved ordered policy in
|
|
781
|
+
`verify.reconcile-policy-captured` at the next engine action after reconcile
|
|
782
|
+
completion. Live configuration changes apply at that boundary; a cycle already
|
|
783
|
+
started keeps its policy through recovery. Historical cycles already started
|
|
784
|
+
without a captured policy retain the rerun-all behavior. Initial verification
|
|
785
|
+
and verification after subsequent code review always use ordinary applicability.
|
|
786
|
+
Policy exclusion precedes plan selection and paths, including `always = true`.
|
|
787
|
+
Enabled steps still follow plan selection and path rules. Excluded steps record
|
|
788
|
+
`verify.completed` with outcome `skipped`, `skipCause = "post-reconcile-policy"`,
|
|
789
|
+
and a reason naming the setting. Dashboards and PR summaries call this
|
|
790
|
+
"skipped by post-reconcile policy"; it is never a pass. Forge-side required
|
|
791
|
+
checks and branch protections still gate merge. For excluded steps, merged code
|
|
792
|
+
is not re-verified, so breakage that only exists in the combination can land.
|
|
793
|
+
|
|
794
|
+
|
|
760
795
|
`[verify].steps` defines the configured universe and execution order. It is
|
|
761
796
|
optional and defaults to no verify phases. Every listed name needs one matching
|
|
762
797
|
subtable, and every named subtable must be listed; a defined-but-unlisted step
|
|
@@ -776,6 +811,7 @@ There are two strict step variants:
|
|
|
776
811
|
| `command` | — | required for check; nonempty key in `[commands]` | Deterministic shell verb to run. Forbidden for agent steps. |
|
|
777
812
|
| `skill` | — | required for agent; nonempty string | Exact installed verifier skill. Forbidden for check steps. |
|
|
778
813
|
| `paths` | omitted (unconditional) | optional nonempty array of positive repository-relative globs | Apply only when at least one changed path matches. Available to both variants. |
|
|
814
|
+
| `afterReconcile` | repository: `true`; step: inherited | boolean | Step override wins over `[verify].afterReconcile`; false skips this step after reconciliation only. |
|
|
779
815
|
| `always` | omitted (`false`) | optional boolean | `true` makes the step mandatory in plan selection and bypasses path gating. Available to both variants. |
|
|
780
816
|
|
|
781
817
|
<!-- config-fragment:verify -->
|
|
@@ -1132,6 +1168,7 @@ Optional. Every field receives its own default. All are positive integers except
|
|
|
1132
1168
|
| `sessionBudgetSeconds` | `3600` | positive integer | Wall-clock bound for each build agent session unless its logical role overrides it. |
|
|
1133
1169
|
| `stallRounds` | `3` | positive integer | Escalate when the same review finding survives this many rounds. |
|
|
1134
1170
|
| `maxVerifyAttempts` | `3` | positive integer | Bound failure-driven verify → implement retry cycles. |
|
|
1171
|
+
| `maxDispatchAttempts` | `3` | positive integer | Bound consecutive dispatch failures before human escalation. |
|
|
1135
1172
|
| `maxSetupAttempts` | `3` | positive integer | Bound consecutive workspace setup failures before human escalation. |
|
|
1136
1173
|
| `maxInfrastructureAttempts` | `3` | positive integer | Bound consecutive provision/start/wait/cleanup failures before a setup-targeted policy escalation; a human `retry` answer re-arms this budget. |
|
|
1137
1174
|
| `maxReconcileAttempts` | `3` | positive integer | Bound completed reconciles that leave the PR conflicted against an unchanged authoritative base. Moving-base races do not consume the bound. |
|
|
@@ -1139,6 +1176,15 @@ Optional. Every field receives its own default. All are positive integers except
|
|
|
1139
1176
|
| `harvestThreshold` | `5` | positive integer | New unclaimed observation occurrences needed to start one harvest run. |
|
|
1140
1177
|
| `harvestMaxDrift` | `3` | nonnegative integer | Other builds merged after the oldest unclaimed observation needed to start a run; `0` disables drift. |
|
|
1141
1178
|
|
|
1179
|
+
Dispatch failures share a `[policy].maxDispatchAttempts` budget (default 3) across
|
|
1180
|
+
create, workspace, spec, comment, and launch stages. Exhaustion raises one
|
|
1181
|
+
`dispatch-failure-limit` policy escalation naming the latest stage and error,
|
|
1182
|
+
and parks dispatch until answered. Both bare `ab answer <slug>` retries and
|
|
1183
|
+
text guidance grant a fresh budget; abort does not. Confirmed runner attachment
|
|
1184
|
+
clears the streak. Recovery-provider workspace failures belong exclusively to
|
|
1185
|
+
the infrastructure budget. Exhaustion is repaired from durable facts on restart
|
|
1186
|
+
before further dispatch work.
|
|
1187
|
+
|
|
1142
1188
|
For each repeat conflict, Autobuild compares the base merged by the most recent
|
|
1143
1189
|
completed reconcile with a fresh authoritative base snapshot. An advanced base
|
|
1144
1190
|
proves the attempt lost a race and permits another reconcile regardless of the
|
|
@@ -1189,9 +1235,10 @@ state. Within a present table, `source` and `readyState` are required.
|
|
|
1189
1235
|
| `readyState` | — | required nonblank string | The one workflow state eligible for dispatch. |
|
|
1190
1236
|
| `readyAssignee` | — | optional; `"me"` or an email address; Linear only (rejected for file, hosted, and plugin sources) | Require the ticket to be assigned to one Linear user, in addition to the state and label gates. |
|
|
1191
1237
|
| `teamKey` | — | required for Linear and hosted; forbidden for file; optional for plugins | Backend team key such as `"ENG"`, or an existing plugin config field. |
|
|
1192
|
-
| `claimedState` | `"In Progress"` for direct Linear;
|
|
1238
|
+
| `claimedState` | `"In Progress"` for direct Linear; `"Doing"` for hosted | optional nonempty string; forbidden for file; allowed for plugins | Workflow state entered when a ticket is claimed. |
|
|
1239
|
+
| `doneState` | `"Done"` | optional nonblank string; hosted | Project completion state and merged-ticket transition. |
|
|
1193
1240
|
| `createState` | provider default | optional nonempty string | Default state for newly created tickets when `ab ticket create` omits `--state`. |
|
|
1194
|
-
| `triageState` | Linear: `"Backlog"`; file/plugin: `"Triage"` | optional nonempty string | State used for spec-gate bounces, aborts, and closed-unmerged PRs. |
|
|
1241
|
+
| `triageState` | Linear/hosted: `"Backlog"`; file/plugin: `"Triage"` | optional nonempty string | State used for spec-gate bounces, aborts, and closed-unmerged PRs. |
|
|
1195
1242
|
| `proposalState` | the resolved `triageState` | optional nonempty string | State harvest files its synthesized proposals into. Setting it to `readyState` waives the human grooming gate, not dependency eligibility. |
|
|
1196
1243
|
| `dir` | file: selected local state root's `tickets/`; plugin: omitted | optional nonempty path; forbidden for Linear; allowed for plugins | Root containing file-source state directories, or an existing plugin config field. Relative file paths resolve from the repository. |
|
|
1197
1244
|
|
|
@@ -1303,17 +1350,18 @@ createState = "Triage"
|
|
|
1303
1350
|
triageState = "Triage"
|
|
1304
1351
|
```
|
|
1305
1352
|
|
|
1306
|
-
Set `AB_STORE` to the service's HTTP(S) URL and `AB_TOKEN` to a
|
|
1307
|
-
|
|
1353
|
+
Set `AB_STORE` to the service's HTTP(S) URL and `AB_TOKEN` to a stored credential
|
|
1354
|
+
for that registered project (`credentials issue REPOSITORY --user IDENTITY`). The same source-agnostic wiring powers dispatch, harvest, ticket-aware
|
|
1308
1355
|
skills, and all seven command families: `ab ticket create`, `update`, `block`,
|
|
1309
1356
|
`unblock`, `list`, `show`, and `move`. See the
|
|
1310
|
-
[hosted ticket protocol](remote-ticket-protocol.md).
|
|
1311
|
-
|
|
1312
|
-
|
|
1357
|
+
[hosted ticket protocol](remote-ticket-protocol.md). Tickets are partitioned by
|
|
1358
|
+
the credential's registered project; lifecycle comes from its latest effective
|
|
1359
|
+
configuration. The service has no Linear backend and refuses ticket operations
|
|
1360
|
+
for projects using external sources. Direct Linear remains dispatcher-side.
|
|
1313
1361
|
|
|
1314
1362
|
When filing dependent tickets into the ready state, follow the
|
|
1315
|
-
[safe blocker-filing workflow](ticket-dependencies.md). Direct
|
|
1316
|
-
|
|
1363
|
+
[safe blocker-filing workflow](ticket-dependencies.md). Direct Linear
|
|
1364
|
+
creates the issue before recording its blockers, so `create --blocked-by` is not
|
|
1317
1365
|
an atomic publication guarantee. Stage outside ready, verify the relationships,
|
|
1318
1366
|
then move to the intended ready state last.
|
|
1319
1367
|
|
|
@@ -1494,6 +1542,7 @@ sessionBudgetSeconds = 7200
|
|
|
1494
1542
|
sessionBudgetSeconds = 3600
|
|
1495
1543
|
stallRounds = 3
|
|
1496
1544
|
maxVerifyAttempts = 3
|
|
1545
|
+
maxDispatchAttempts = 3
|
|
1497
1546
|
maxSetupAttempts = 3
|
|
1498
1547
|
maxInfrastructureAttempts = 3
|
|
1499
1548
|
maxReconcileAttempts = 3
|
|
@@ -1653,9 +1702,9 @@ Secrets and store selection accompany the file through environment variables:
|
|
|
1653
1702
|
|
|
1654
1703
|
| Variable | Used for | Notes |
|
|
1655
1704
|
|---|---|---|
|
|
1656
|
-
| `LINEAR_API_KEY` | Direct Linear ticket source | Required and nonempty when `tickets.source = "linear"`;
|
|
1657
|
-
| `AB_STORE` | BuildStore and hosted ticket selection | A local path or HTTP(S) remote-store URL. `tickets.source = "hosted"` requires a nonblank HTTP(S) URL. A command's explicit `--store` wins for BuildStore selection, then nonblank `AB_STORE`, then the main checkout's `.autobuild/`. Relative local paths resolve from the main checkout. |
|
|
1658
|
-
| `AB_TOKEN` | Protected remote BuildStore and hosted tickets | Bearer credential forwarded to the service. Hosted tickets require
|
|
1705
|
+
| `LINEAR_API_KEY` | Direct Linear ticket source | Required and nonempty when `tickets.source = "linear"`; never used by the hosted service. |
|
|
1706
|
+
| `AB_STORE` | BuildStore and hosted ticket selection | A local path or HTTP(S) remote-store URL. `tickets.source = "hosted"` requires a nonblank HTTP(S) URL. A command's explicit `--store` wins for BuildStore selection, then nonblank `AB_STORE`, then `[store] url`, then the main checkout's `.autobuild/`. Relative local paths resolve from the main checkout. |
|
|
1707
|
+
| `AB_TOKEN` | Protected remote BuildStore and hosted tickets | Bearer credential forwarded to the service. Hosted tickets require a stored credential for a registered project. Owner admin is an explicit break-glass exception. Empty means no token; nonempty token bytes are treated as opaque. |
|
|
1659
1708
|
|
|
1660
1709
|
A local store selection relocates the state database, blobs, worktrees, and the
|
|
1661
1710
|
default file-ticket directory together. With a remote store, Git worktrees and
|
|
@@ -1795,3 +1844,43 @@ progress is not shown. Harvest does not consume build capacity.
|
|
|
1795
1844
|
- **Remote BuildStore:** confirm the effective `AB_STORE` URL and `AB_TOKEN`.
|
|
1796
1845
|
A protected store reports 401 for a missing, invalid, or expired token and
|
|
1797
1846
|
403 when the token is valid but scoped to another build/session.
|
|
1847
|
+
|
|
1848
|
+
### Hosted project selection
|
|
1849
|
+
|
|
1850
|
+
The durable PostgreSQL project registry controls dashboard, MCP and operator
|
|
1851
|
+
API access. Every allowlisted user sees every active entry. Administer it with
|
|
1852
|
+
`ab-hosted-store projects list|add|remove` using deployment database credentials;
|
|
1853
|
+
mutations require `--user IDENTITY` for declared attribution. See
|
|
1854
|
+
[connected projects](setup.md#connected-projects) for migration and retention.
|
|
1855
|
+
`AB_DISPATCHER_REPOSITORIES` optionally selects an ordered subset of current
|
|
1856
|
+
registrations. When unset, each authorized tick queries all active entries.
|
|
1857
|
+
Removed credential override keys are inert in dynamic mode; explicit-list
|
|
1858
|
+
configuration still rejects unknown override keys.
|
|
1859
|
+
|
|
1860
|
+
## Hosted service client compatibility
|
|
1861
|
+
|
|
1862
|
+
A service accepts stable clients from its own `major.minor` release line and
|
|
1863
|
+
the two preceding minor lines in the same major. A major starts a new family:
|
|
1864
|
+
X.0 accepts only X.0, X.1 accepts X.0/X.1, and X.2 onward accepts three lines.
|
|
1865
|
+
Patch versions are interchangeable in both directions and must never change
|
|
1866
|
+
the protocol. Upgrade the service first, then projects independently within
|
|
1867
|
+
its window. Supported release lines retain their wire handlers and known
|
|
1868
|
+
protocol identities; an unknown protocol is refused independently of version.
|
|
1869
|
+
Malformed, missing, and prerelease identities are refused with HTTP 409.
|
|
1870
|
+
A newer client is told to upgrade the service; a client below the window is
|
|
1871
|
+
told to upgrade the project's Autobuild. Diagnostics name the service version
|
|
1872
|
+
and supported range.
|
|
1873
|
+
|
|
1874
|
+
Unauthenticated `GET /health` publishes `ok`, `autobuildVersion`,
|
|
1875
|
+
`protocolVersion`, and `supportedClientRange: { minVersion, maxVersionExclusive }`.
|
|
1876
|
+
The range is inclusive at the minimum and exclusive at the maximum; a 0.11.x
|
|
1877
|
+
service publishes `>=0.9.0 <0.12.0`. Health needs no credentials, version
|
|
1878
|
+
headers, or available backend.
|
|
1879
|
+
|
|
1880
|
+
Remote workspace factories must use `delegateCredential(storeRef, undefined,
|
|
1881
|
+
target)` to obtain per-resource grants before provisioning or launching guests.
|
|
1882
|
+
The callback keeps parent authority in host composition. `storeToken` is retired
|
|
1883
|
+
and is never supplied; factory environments also exclude `AB_TOKEN`. Launch
|
|
1884
|
+
credentials travel through the separate transient execution-auth argument, never
|
|
1885
|
+
through serialized execution identity. Existing plugins that forwarded
|
|
1886
|
+
`storeToken` must migrate to this callback and fail closed if it is unavailable.
|
|
@@ -14,6 +14,16 @@ it once a minute by default), so builds no longer depend on a maintainer's
|
|
|
14
14
|
machine. A deployment that does not install the package serves the hosted
|
|
15
15
|
store, ticket, operator, and web endpoints and never attempts a dispatch tick.
|
|
16
16
|
|
|
17
|
+
The [minimal hosted service deployment](hosted-service.md) defaults to store-only
|
|
18
|
+
mode and supplies no cron. The source-checkout deployment below retains the
|
|
19
|
+
opt-in dispatcher packing and shipping pipeline.
|
|
20
|
+
|
|
21
|
+
For a dispatcher running as a local user or service manager, first
|
|
22
|
+
[connect the project](hosted-service.md#connect-a-project). Origin-mode dispatch
|
|
23
|
+
can read the committed `[store] url` and the same user credential by origin.
|
|
24
|
+
A deployment running under another identity needs its own project credential;
|
|
25
|
+
`AB_TOKEN` remains the explicit CI override.
|
|
26
|
+
|
|
17
27
|
## Enabling the schedule
|
|
18
28
|
|
|
19
29
|
1. Deploy the hosted service with the dispatcher package installed and the
|
|
@@ -255,6 +265,11 @@ presents (`sandboxAuth=oidc-header`, `oidc-env`, `token`, or `none`); `none`
|
|
|
255
265
|
means the project has OIDC federation disabled (Settings → Security). No
|
|
256
266
|
long-lived `VERCEL_TOKEN` belongs on the service. Guests never receive a Vercel
|
|
257
267
|
token or forge credential; they authenticate to the Store with the short-TTL
|
|
258
|
-
|
|
268
|
+
stored project credential the dispatcher issues for each repository tick
|
|
259
269
|
(`AB_DISPATCHER_TOKEN_TTL_SECONDS`, default 7 days — keep it longer than your
|
|
260
|
-
largest `timeoutSeconds` guest lifetime).
|
|
270
|
+
largest `timeoutSeconds` guest lifetime). Its immutable dispatcher purpose
|
|
271
|
+
permits raw Store and hosted tickets only, never operator controls. The service
|
|
272
|
+
checks registration and revocation on each request. Tick return does not revoke
|
|
273
|
+
it; spawned builds may outlive the tick. Owner-issued project credentials and
|
|
274
|
+
the owner-only break-glass admin are documented in the
|
|
275
|
+
[remote Store protocol](remote-store-protocol.md#7-authentication-and-project-authority).
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# Deploy a hosted service
|
|
2
|
+
|
|
3
|
+
A service hosts the BuildStore, tickets, dashboard, sign-in, and MCP endpoint.
|
|
4
|
+
The default deployment stores state while dispatch runs on another machine.
|
|
5
|
+
You need Bun 1.4.x, a Git repository, a Vercel project, PostgreSQL, a blob
|
|
6
|
+
backend, and a GitHub OAuth application.
|
|
7
|
+
|
|
8
|
+
Create a new directory containing these two files (also shipped in the hosted
|
|
9
|
+
package's `deployment/` directory and in `templates/hosted-service/`).
|
|
10
|
+
|
|
11
|
+
`package.json`:
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"private": true,
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "ab-hosted-service-build"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@defrex/autobuild-hosted-store-service": "0.12.0",
|
|
21
|
+
"@defrex/autobuild": "0.12.0",
|
|
22
|
+
"next": "16.1.6",
|
|
23
|
+
"react": "19.2.4",
|
|
24
|
+
"react-dom": "19.2.4"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`vercel.json`:
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"$schema": "https://openapi.vercel.sh/vercel.json",
|
|
34
|
+
"framework": "nextjs",
|
|
35
|
+
"installCommand": "bun install --frozen-lockfile",
|
|
36
|
+
"buildCommand": "bun run build",
|
|
37
|
+
"bunVersion": "1.4.x"
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Run `bun install`, then commit both files and `bun.lock`. Add `.gitignore`
|
|
42
|
+
entries for `node_modules/`, `.next/`, `.vercel/`, `app/`, `next.config.ts`,
|
|
43
|
+
`next-env.d.ts`, `tsconfig.json`, and `.autobuild-service-assets.json`.
|
|
44
|
+
These application assets are generated during each build. Keep your own files
|
|
45
|
+
outside those names; the builder refuses to overwrite consumer-owned files.
|
|
46
|
+
Do not commit generated application sources or edit them to customize deployment.
|
|
47
|
+
|
|
48
|
+
Push the directory to your Git host. Import it in Vercel with the repository
|
|
49
|
+
root as Root Directory and Next.js as the framework. The checked-in platform
|
|
50
|
+
configuration installs the lockfile and runs `bun run build`. Each build stages
|
|
51
|
+
the installed package, runs its idempotent database migrations against the
|
|
52
|
+
configured database, then builds Next into the root `.next/`. Missing database
|
|
53
|
+
configuration, incompatible schema, or a failed migration stops the build.
|
|
54
|
+
Provide database access from the build environment as well as runtime.
|
|
55
|
+
|
|
56
|
+
## Connect a project
|
|
57
|
+
|
|
58
|
+
From a checkout with an origin remote, run `ab connect https://YOUR_ORIGIN`.
|
|
59
|
+
The CLI prints a verification URL and short code and attempts to open a browser.
|
|
60
|
+
Sign in as an allowed owner, check the full repository identity and code, and
|
|
61
|
+
approve or deny. Another device can open the printed URL, or visit `/connect`
|
|
62
|
+
and enter the code. Approval requires the web-enabled service origin; a
|
|
63
|
+
standalone machine-only listener cannot present browser consent. Requests
|
|
64
|
+
expire after ten minutes. Denial and timeout leave local configuration unchanged.
|
|
65
|
+
|
|
66
|
+
On approval the service registers the project and issues a project credential.
|
|
67
|
+
The CLI keeps it in `$XDG_CONFIG_HOME/autobuild/credentials` (or
|
|
68
|
+
`~/.config/autobuild/credentials`), keyed by normalized service and origin,
|
|
69
|
+
with directory mode 0700 and file mode 0600. Credentials never belong in the
|
|
70
|
+
repository. It adds the non-secret `[store] url` to `autobuild.toml` when
|
|
71
|
+
absent; review and commit that change yourself. An existing different URL
|
|
72
|
+
must be changed explicitly before connecting. Reconnecting replaces the saved
|
|
73
|
+
credential only after approval and revokes the previous credential.
|
|
74
|
+
|
|
75
|
+
All worktrees share the main checkout's configuration and the user's saved
|
|
76
|
+
credential. A service manager running as that user uses the same HOME and
|
|
77
|
+
XDG_CONFIG_HOME, with no AB_STORE or AB_TOKEN exports. A fresh clone with
|
|
78
|
+
committed store configuration but no saved credential fails with `ab connect`
|
|
79
|
+
guidance; it never silently creates local state. Run connect on each host/user.
|
|
80
|
+
|
|
81
|
+
`ab connect` without a URL reports service, project, and credential status:
|
|
82
|
+
accepted, rejected, missing, or unreachable. `ab disconnect` revokes the saved
|
|
83
|
+
credential remotely before removing it locally, keeping the project registered,
|
|
84
|
+
its data, and store configuration. A network/server failure retains the local
|
|
85
|
+
entry for retry; an already revoked credential can be removed. If saving a new
|
|
86
|
+
connection fails, the CLI cancels/revokes it and retains the previous entry.
|
|
87
|
+
If remote cleanup cannot be confirmed, check the printed credential id with
|
|
88
|
+
the owner's administrative tools before retrying.
|
|
89
|
+
|
|
90
|
+
Store selection is `--store` > nonblank `AB_STORE` > `[store] url` > the
|
|
91
|
+
main checkout's `.autobuild/`. `AB_TOKEN` overrides the exact service/project's
|
|
92
|
+
saved credential for CI and other non-interactive hosts. A service override
|
|
93
|
+
never borrows another service's credential. Build and harvest sessions keep
|
|
94
|
+
their explicit scoped authority.
|
|
95
|
+
|
|
96
|
+
## Environment
|
|
97
|
+
|
|
98
|
+
Set these server-side variables in every Vercel environment you deploy:
|
|
99
|
+
|
|
100
|
+
- `AB_POSTGRES_URL` or `DATABASE_URL`: PostgreSQL connection URL. The explicit
|
|
101
|
+
`AB_POSTGRES_URL` takes precedence; use the same database at build and runtime.
|
|
102
|
+
- `AB_STORE_SECRET`: a high-entropy secret for machine token signing.
|
|
103
|
+
- `AB_BLOB_BACKEND=vercel` with `BLOB_READ_WRITE_TOKEN`, or `AB_BLOB_BACKEND=s3`
|
|
104
|
+
with `AB_S3_BUCKET`, `AB_S3_REGION`, `AB_S3_ACCESS_KEY_ID`, and
|
|
105
|
+
`AB_S3_SECRET_ACCESS_KEY` (and optional endpoint for compatible storage).
|
|
106
|
+
- `BETTER_AUTH_SECRET`: an independent high-entropy secret of at least 32 characters.
|
|
107
|
+
- `BETTER_AUTH_URL`: the exact production HTTPS origin, with no path.
|
|
108
|
+
- `GITHUB_CLIENT_ID`, `GITHUB_CLIENT_SECRET`: GitHub OAuth application credentials.
|
|
109
|
+
- `AB_WEB_AUTH_PROVIDERS=github`.
|
|
110
|
+
- `AB_WEB_ALLOWED_EMAILS`: comma-separated operator email allowlist.
|
|
111
|
+
- `AB_WEB_REPOSITORIES`: comma-separated repository origins visible to operators.
|
|
112
|
+
|
|
113
|
+
Register `https://YOUR_ORIGIN/api/auth/callback/github` as the GitHub callback
|
|
114
|
+
and allow read-only email access (`user:email`). Sign-in must use the configured
|
|
115
|
+
production origin. Do not expose secrets through `NEXT_PUBLIC_` variables.
|
|
116
|
+
See the [complete environment reference](configuration.md) for storage,
|
|
117
|
+
project ticket lifecycle, credential administration, and optional MCP resource configuration.
|
|
118
|
+
|
|
119
|
+
## Check the deployment
|
|
120
|
+
|
|
121
|
+
`GET /health` returns service and protocol versions. Open `/sign-in` and sign
|
|
122
|
+
in; `/` redirects unauthenticated browsers to sign-in. Machine routes
|
|
123
|
+
require a machine token; `/mcp` challenges an unauthenticated client with OAuth
|
|
124
|
+
resource metadata. Check both discovery documents:
|
|
125
|
+
|
|
126
|
+
```sh
|
|
127
|
+
curl https://YOUR_ORIGIN/.well-known/oauth-protected-resource
|
|
128
|
+
curl https://YOUR_ORIGIN/.well-known/oauth-authorization-server
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The authorization-server document advertises a reachable `/api/auth/jwks`
|
|
132
|
+
URI and `/api/auth/mcp/register` dynamic registration endpoint. MCP clients
|
|
133
|
+
register with `redirect_uris` as an array of strings and
|
|
134
|
+
`token_endpoint_auth_method: "none"`; treat the returned `client_id` as opaque.
|
|
135
|
+
See [MCP](mcp.md) for authorization and client setup.
|
|
136
|
+
|
|
137
|
+
Without the optional hosted dispatcher installed, `GET /api/dispatch` returns
|
|
138
|
+
503 JSON: `{"error":"dispatch runs elsewhere for this deployment"}`. The
|
|
139
|
+
template has no cron and installs no dispatcher/provider package. Run dispatch
|
|
140
|
+
from a connected project or follow the separate, opt-in
|
|
141
|
+
[hosted dispatcher procedure](hosted-dispatcher.md), which retains its
|
|
142
|
+
source-checkout packaging and cron setup.
|
|
143
|
+
|
|
144
|
+
## Upgrade
|
|
145
|
+
|
|
146
|
+
Bump the exact hosted-service and core package pins in `package.json` to the
|
|
147
|
+
same new release, run `bun install` to refresh `bun.lock`, commit, and push.
|
|
148
|
+
Vercel's Git integration migrates and builds the pinned package automatically.
|
|
149
|
+
Upgrade the service **before connected projects**: that is the order expected
|
|
150
|
+
by the protocol compatibility window. No source extraction, patch application,
|
|
151
|
+
or manual production deployment is required.
|
|
152
|
+
|
|
153
|
+
## Hosted ticket projects and v1 migration
|
|
154
|
+
|
|
155
|
+
Hosted queues are partitioned by registered repository. Credentials select the
|
|
156
|
+
project, and its latest uploaded effective `[tickets]` configuration selects the
|
|
157
|
+
lifecycle; see the [ticket protocol](remote-ticket-protocol.md). If configuration
|
|
158
|
+
is unavailable, run that project's dispatcher to publish it. Projects using file,
|
|
159
|
+
Linear or another external source continue to access it directly through their
|
|
160
|
+
dispatcher. Service ticket surfaces refuse those projects with source feedback.
|
|
161
|
+
The service never connects to Linear.
|
|
162
|
+
|
|
163
|
+
The removed `AB_TICKET_BACKEND` and `LINEAR_API_KEY` settings are ignored for
|
|
164
|
+
all values, including blanks, with one startup message asking for removal.
|
|
165
|
+
The removed `AB_TICKET_TRIAGE_STATE`, `AB_TICKET_READY_STATE`,
|
|
166
|
+
`AB_TICKET_DOING_STATE` and `AB_TICKET_DONE_STATE` settings are ignored even if
|
|
167
|
+
malformed. Lifecycle now comes only from project configuration.
|
|
168
|
+
|
|
169
|
+
The environment-aware migration first imports `AB_WEB_REPOSITORIES` into the
|
|
170
|
+
registry once, including upgrades from released main schema v9 where registry
|
|
171
|
+
tables do not yet exist. This import and the main-schema promotion share the
|
|
172
|
+
ticket transaction: a stopped ticket migration rolls them back too. The owner
|
|
173
|
+
`projects add` and `tickets assign-team` commands can independently bootstrap
|
|
174
|
+
the registry while that old main marker remains, so recovery does not require
|
|
175
|
+
a successful ticket migration. If the retired environment is unavailable,
|
|
176
|
+
register the intended project with `ab-hosted-store projects add REPOSITORY
|
|
177
|
+
--user IDENTITY` before assigning its legacy team. Once the import succeeds,
|
|
178
|
+
later changes to the retired environment are ignored.
|
|
179
|
+
|
|
180
|
+
Fresh databases install ticket schema v2 directly. Existing team-keyed v1
|
|
181
|
+
queues migrate in one transaction. For each registered project, migration reads
|
|
182
|
+
the effective configuration selected by its latest dispatcher run and reloads,
|
|
183
|
+
including the actual immutable artifact bytes in blob storage. A legacy team
|
|
184
|
+
must have one claimant, or an explicit owner assignment. A registered project
|
|
185
|
+
with no dispatcher run or no selected effective-config reference makes no team
|
|
186
|
+
claim and does not block other projects. Unclaimed teams still stop unchanged.
|
|
187
|
+
When ownership must be inferred, a selected but missing, inaccessible or invalid
|
|
188
|
+
configuration fails closed with the project and remaining teams in the message.
|
|
189
|
+
Restore those bytes or explicitly assign every remaining legacy team, then
|
|
190
|
+
rerun; complete assignments to registered projects settle ownership without
|
|
191
|
+
reading unrelated configurations. Conflicting claimants and asset ownership
|
|
192
|
+
conflicts also stop without changing schema markers or tickets.
|
|
193
|
+
Historical ids, states, timestamps, blockers, comments and asset rows remain
|
|
194
|
+
unchanged. Review the named projects and resolve a shared legacy team locally:
|
|
195
|
+
|
|
196
|
+
```sh
|
|
197
|
+
ab-hosted-store tickets assign-team ENG https://github.com/acme/app --user owner@example.com
|
|
198
|
+
ab-postgres-store migrate
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
The assignment command works before the v2 migration succeeds and records the
|
|
202
|
+
actor in an append-only journal. The latest assignment moves the whole legacy
|
|
203
|
+
team once; it grants no future cross-project access. It must name a registered
|
|
204
|
+
project. Rerun migration after resolving every named team or configuration error.
|
|
205
|
+
|
|
206
|
+
For populated-v1 upgrades, both the owner migration CLI and `deploy:build` need
|
|
207
|
+
the same blob backend, access, credentials and `AB_BLOB_PREFIX` as the running
|
|
208
|
+
service: S3 bucket/region/credentials (and endpoint/path style when configured),
|
|
209
|
+
or Vercel access mode and token/OIDC store identity. The deployment build inherits
|
|
210
|
+
these variables and runs the environment-aware migration before Next build.
|
|
211
|
+
Missing blob configuration or denied reads stop deployment before Next builds;
|
|
212
|
+
diagnostics never print credentials. SQL-only fresh installs, empty-v1 upgrades
|
|
213
|
+
and already-v2 reruns do not open blob storage and keep their existing database
|
|
214
|
+
requirements. Migration reruns are idempotent.
|
package/docs/mcp.md
CHANGED
|
@@ -110,8 +110,14 @@ the standard surface the endpoint serves.
|
|
|
110
110
|
the default MCP resource's base.
|
|
111
111
|
- `AB_WEB_ALLOWED_EMAILS`: the operator allowlist. Sign-in admission and every
|
|
112
112
|
MCP tool call are checked against it.
|
|
113
|
-
- `AB_WEB_REPOSITORIES
|
|
114
|
-
|
|
113
|
+
- `AB_WEB_REPOSITORIES` (deprecated): optional once-per-database registry
|
|
114
|
+
bootstrap, never an ongoing allowlist. `repositories.list` queries current
|
|
115
|
+
active registrations on every call, and every tool checks current membership.
|
|
116
|
+
|
|
117
|
+
Every allowlisted user sees every registered project. Database-authorized
|
|
118
|
+
owners use the [project commands](setup.md#connected-projects) to add or remove
|
|
119
|
+
projects without redeploying. Removal hides retained data until re-registration;
|
|
120
|
+
registry failures never authorize a call.
|
|
115
121
|
|
|
116
122
|
The endpoint requires no additional variables beyond the hosted service's
|
|
117
123
|
existing web/auth set. Note that consent renders when the client sends
|
package/docs/operator-api.md
CHANGED
|
@@ -6,17 +6,48 @@ Every request must send `X-Autobuild-Version`,
|
|
|
6
6
|
`X-Autobuild-Protocol-Version: 3`, and `Authorization: Bearer …`. Identity is
|
|
7
7
|
checked before authentication or resource lookup.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Project credentials are opaque `abp_1_<id>_<secret>` bearer values bound to one
|
|
10
|
+
registered normalized repository. The service stores only a SHA-256 digest of
|
|
11
|
+
the random secret, plus project, creator, creation time, last use, expiry and
|
|
12
|
+
revocation metadata. It checks credential status and project registration on
|
|
13
|
+
every request. Revocation takes effect on the next request without affecting
|
|
14
|
+
other credentials. Unknown, expired or revoked credentials receive `401 auth`;
|
|
15
|
+
removed projects receive `403 auth` with `project not registered`.
|
|
16
|
+
|
|
17
|
+
The deployment owner runs these commands locally with database access:
|
|
10
18
|
|
|
11
19
|
```sh
|
|
12
|
-
|
|
13
|
-
|
|
20
|
+
ab-hosted-store credentials issue https://github.com/acme/app --user owner@example.com
|
|
21
|
+
ab-hosted-store credentials list https://github.com/acme/app
|
|
22
|
+
ab-hosted-store credentials revoke https://github.com/acme/app --id ID --user owner@example.com
|
|
14
23
|
```
|
|
15
24
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
25
|
+
Issue prints the secret once; list contains metadata only. Issue optionally
|
|
26
|
+
accepts `--ttl-seconds N` or `--expires-at ISO-8601`. For administrative/non-interactive issuance, set the returned token as
|
|
27
|
+
`AB_TOKEN`. Interactive project onboarding uses `ab connect <service-url>`;
|
|
28
|
+
it saves the credential outside the repository and commits no secret. Previous `AB_TOKEN` values and `mint operator` / `mint build` are
|
|
29
|
+
retired: the service responds that the credential format changed and points
|
|
30
|
+
to `credentials issue`. Supported old protocol shapes still work with a new
|
|
31
|
+
credential; protocol compatibility does not restore retired authentication.
|
|
32
|
+
|
|
33
|
+
`mint admin --ttl-seconds N` creates an explicit versioned, attributed owner
|
|
34
|
+
break-glass credential. It can cross project boundaries. Keep it owner-only:
|
|
35
|
+
never give it or `AB_STORE_SECRET` to a dispatcher or build agent.
|
|
36
|
+
|
|
37
|
+
Owner-purpose project credentials attribute every write to their recorded creator.
|
|
38
|
+
Dispatcher-purpose credentials are refused. Signed-in owners in the dashboard
|
|
39
|
+
and MCP receive short-lived internal signatures with an explicit version,
|
|
40
|
+
selected repository, signed user, expiry and MCP `via`. Only the service holds
|
|
41
|
+
the signing key. These signatures authorize operator routes only and require a
|
|
42
|
+
registered project; replay against another project is refused.
|
|
43
|
+
|
|
44
|
+
The path project is checked before registry lookup, body parsing and generic
|
|
45
|
+
tool execution. Body repositories and secondary build/session identifiers are
|
|
46
|
+
also checked inside that project. Explicit project mismatches return `403 auth:
|
|
47
|
+
wrong project`; removal returns `403 auth: project not registered`. Encode each
|
|
48
|
+
repository, build, session and artifact kind as a separate URL path segment.
|
|
49
|
+
Registration changes use the database-local `projects list|add|remove` owner
|
|
50
|
+
commands; see [owner workflow](setup.md#connected-projects).
|
|
20
51
|
|
|
21
52
|
## Operator sessions
|
|
22
53
|
|
|
@@ -201,3 +232,55 @@ identity, plus the usual repo/build/state/cursor fields. It invents no durable
|
|
|
201
232
|
sequence or actor. Retain the cursor to avoid repeat reports across invocations.
|
|
202
233
|
No lease alone is not evidence of death. SIGINT, SIGHUP and SIGTERM drain dispatch,
|
|
203
234
|
record the first signal in the stop fact, and release its lease before exit.
|
|
235
|
+
|
|
236
|
+
### CLI attention monitoring
|
|
237
|
+
|
|
238
|
+
The default watch reports actionable conditions only:
|
|
239
|
+
|
|
240
|
+
- Build `escalation.raised`, or `build.merge-decision`: a finalized open PR
|
|
241
|
+
with auto-merge off or a current actionable merge-gate deferral. Armed consent
|
|
242
|
+
awaiting application is silent. One merge decision is reported per build/PR.
|
|
243
|
+
- Repository `harvest.escalated`, `harvest.recovery-exhausted`,
|
|
244
|
+
`dispatcher.config-rejected`, `dispatcher.config-reloaded` with nonempty
|
|
245
|
+
`restartRequired`, abnormal `dispatcher.run-stopped`, and `dispatcher.lost`.
|
|
246
|
+
- `dispatcher.ticket-source-persistent`: degradation past its advertised
|
|
247
|
+
reset time, once a tick started at or after reset has completed or failed
|
|
248
|
+
with the episode still open; crossing reset alone is silent. Without a reset,
|
|
249
|
+
the deadline is 15 minutes after onset. Repeated evidence never postpones
|
|
250
|
+
the deadline; recovery ends the episode.
|
|
251
|
+
- `dispatcher.tick-failure-persistent`: continuously failing completed ticks
|
|
252
|
+
for five minutes in one run. A successful tick, new run, or matching stop
|
|
253
|
+
ends the episode. Source grace and cooldown-driven failures do not start
|
|
254
|
+
this clock; after grace, the first qualifying failure starts a new five-minute
|
|
255
|
+
interval. Each persistence episode is reported once.
|
|
256
|
+
|
|
257
|
+
Repository conditions are included with no slugs or with `--repository`.
|
|
258
|
+
Routine outcomes and self-healing failures are silent. Repeatable
|
|
259
|
+
`--event <glob>` replaces the default and selects exactly matching catalog
|
|
260
|
+
events (plus the existing `dispatcher.lost` observation); use explicit globs
|
|
261
|
+
to opt into failures, finalize, merge, or completion events.
|
|
262
|
+
|
|
263
|
+
Derived records use `observation` instead of `event`, without inventing a
|
|
264
|
+
durable sequence or actor. Merge observations carry `type`, `pr`, `reason`,
|
|
265
|
+
and `observedAt`, plus the build slug and normal reduced state. Persistence
|
|
266
|
+
observations carry source/cause/message/resetAt when advertised (or
|
|
267
|
+
run/firstFailure/error), `episodeSeq`, and `observedAt`; repository records
|
|
268
|
+
have `repo` and null build/state. Source observations also report
|
|
269
|
+
`dependencyLimited`.
|
|
270
|
+
|
|
271
|
+
Every record carries a cursor, including timer-only records. Resuming suppresses
|
|
272
|
+
delivered merge decisions and persistence episodes even when stream positions
|
|
273
|
+
did not advance. Old v1 cursors remain valid: historical eligible merge
|
|
274
|
+
decisions are treated as consumed; active overdue repository episodes may
|
|
275
|
+
report because old watches had no persistence notification. Fresh attachment
|
|
276
|
+
silently baselines historical direct events and merge decisions, but retains
|
|
277
|
+
active repository timers. Reconcile existing conditions through status after
|
|
278
|
+
arming the watch. Named watches still end when every named build is terminal;
|
|
279
|
+
learn their outcomes from status reconciliation at exit.
|
|
280
|
+
|
|
281
|
+
`ab wait --for attention` is build-only and uses the same build conditions:
|
|
282
|
+
an open escalation or a merge decision. Existing conditions return immediately,
|
|
283
|
+
even with `--since`; live and backlog matches ignore routine outcomes and
|
|
284
|
+
self-healing failures. A merge match uses the watch observation with
|
|
285
|
+
`condition: "attention"`. Explicit `--event` globs remain event-only.
|
|
286
|
+
Watch and wait preserve each other's cursor notification metadata.
|