@defrex/autobuild 0.12.0 → 0.14.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 +1 -1
- package/SPEC.md +138 -16
- package/bin/ab-dispatch-kernel.ts +4 -6
- package/docs/architecture.md +155 -73
- package/docs/configuration.md +41 -9
- package/docs/hosted-service.md +31 -5
- package/docs/operator-api.md +8 -1
- package/docs/remote-store-protocol.md +94 -2
- package/docs/remote-ticket-protocol.md +151 -9
- package/docs/setup.md +33 -7
- package/docs/ticket-migration.md +64 -0
- package/package.json +4 -3
- package/packages/core/src/cli/attention.ts +18 -164
- package/packages/core/src/cli/build-control.ts +23 -16
- package/packages/core/src/cli/bulk-control.ts +3 -2
- package/packages/core/src/cli/connect.ts +141 -38
- package/packages/core/src/cli/context.ts +23 -79
- package/packages/core/src/cli/dashboard/model.ts +36 -22
- package/packages/core/src/cli/dashboard/poll.ts +1 -1
- package/packages/core/src/cli/dispatch-frontend.ts +24 -67
- package/packages/core/src/cli/dispatch-process.ts +14 -7
- package/packages/core/src/cli/dispatch-repository-feed.ts +196 -0
- package/packages/core/src/cli/dispatch.ts +304 -82
- package/packages/core/src/cli/dispatcher-liveness.ts +26 -19
- package/packages/core/src/cli/harvest.ts +84 -42
- package/packages/core/src/cli/help.ts +14 -8
- package/packages/core/src/cli/historical-build-state.ts +27 -0
- package/packages/core/src/cli/installation.ts +67 -13
- package/packages/core/src/cli/main.ts +23 -5
- package/packages/core/src/cli/mcp.ts +2 -1
- package/packages/core/src/cli/pr-attachments.ts +10 -13
- package/packages/core/src/cli/pr-summary-publication.ts +27 -60
- package/packages/core/src/cli/pr-summary.ts +43 -13
- package/packages/core/src/cli/publication-settlement.ts +10 -20
- package/packages/core/src/cli/repository-status.ts +38 -2
- package/packages/core/src/cli/self-update.ts +5 -1
- package/packages/core/src/cli/status.ts +62 -32
- package/packages/core/src/cli/terminals.ts +25 -142
- package/packages/core/src/cli/ticket-assets.ts +7 -2
- package/packages/core/src/cli/ticket-editor.ts +82 -0
- package/packages/core/src/cli/ticket.ts +166 -36
- package/packages/core/src/cli/wait.ts +91 -84
- package/packages/core/src/cli/watch.ts +60 -97
- package/packages/core/src/config/pipeline-source.ts +4 -3
- package/packages/core/src/config/schema.ts +35 -3
- package/packages/core/src/connection.ts +3 -3
- package/packages/core/src/events/catalog.ts +3 -2
- package/packages/core/src/events/payloads.ts +6 -0
- package/packages/core/src/events/repository.ts +7 -3
- package/packages/core/src/integration/harness.ts +38 -4
- package/packages/core/src/kernel/__snapshots__/reducer-registry.test.ts.snap +2444 -9
- package/packages/core/src/kernel/auto-merge.ts +19 -3
- package/packages/core/src/kernel/dispatcher-liveness.ts +10 -4
- package/packages/core/src/kernel/generators/build-log.ts +1 -1
- package/packages/core/src/kernel/generators/repository-journals.ts +14 -3
- package/packages/core/src/kernel/harvest.ts +25 -23
- package/packages/core/src/kernel/incremental-fixtures.ts +13 -2
- package/packages/core/src/kernel/log-index-value.ts +38 -0
- package/packages/core/src/kernel/read-facts.ts +637 -0
- package/packages/core/src/kernel/reducer-registry.ts +139 -3
- package/packages/core/src/kernel/repository-attention.ts +179 -0
- package/packages/core/src/kernel/service-facts.ts +135 -0
- package/packages/core/src/kernel/terminal-guard.ts +133 -0
- package/packages/core/src/ontology.ts +1 -0
- package/packages/core/src/operator/annotations.ts +12 -0
- package/packages/core/src/operator/control.ts +5 -6
- package/packages/core/src/operator/index.ts +7 -0
- package/packages/core/src/operator/protocol.ts +19 -2
- package/packages/core/src/operator/query.ts +37 -20
- package/packages/core/src/operator/read-view.ts +4 -13
- package/packages/core/src/operator/registry.ts +61 -8
- package/packages/core/src/operator/requests.ts +2 -14
- package/packages/core/src/operator/sandbox.ts +10 -9
- package/packages/core/src/operator/ticket-source-backend.ts +17 -21
- package/packages/core/src/operator/tickets.ts +132 -22
- package/packages/core/src/plugin-sdk/index.ts +19 -0
- package/packages/core/src/plugins/runtimes.ts +5 -1
- package/packages/core/src/ports/runner/session-env.ts +2 -0
- package/packages/core/src/ports/tickets/contract.ts +66 -1
- package/packages/core/src/ports/tickets/create.ts +48 -12
- package/packages/core/src/ports/tickets/fake.ts +30 -1
- package/packages/core/src/ports/tickets/file-assets.ts +159 -0
- package/packages/core/src/ports/tickets/file-codec.ts +90 -0
- package/packages/core/src/ports/tickets/file.ts +114 -120
- package/packages/core/src/ports/tickets/grants.ts +47 -0
- package/packages/core/src/ports/tickets/hosted-index.ts +17 -0
- package/packages/core/src/ports/tickets/identity.ts +20 -0
- package/packages/core/src/ports/tickets/lifecycle.ts +18 -0
- package/packages/core/src/ports/tickets/linear.ts +74 -9
- package/packages/core/src/ports/tickets/migration.ts +336 -0
- package/packages/core/src/ports/tickets/operations.ts +38 -7
- package/packages/core/src/ports/tickets/portable-assets.ts +54 -0
- package/packages/core/src/ports/tickets/remote-protocol.ts +95 -0
- package/packages/core/src/ports/tickets/remote.ts +60 -3
- package/packages/core/src/ports/tickets/requested-id.ts +46 -0
- package/packages/core/src/ports/tickets/revision.ts +62 -0
- package/packages/core/src/ports/tickets/states.ts +61 -0
- package/packages/core/src/ports/types.ts +40 -3
- package/packages/core/src/ports/workspace/build-execution.ts +1 -0
- package/packages/core/src/ports/workspace/create.ts +5 -1
- package/packages/core/src/ports/workspace/operator-sandbox.ts +2 -0
- package/packages/core/src/ports/workspace/vercel-sandbox.ts +8 -4
- package/packages/core/src/processes/build-child.ts +6 -6
- package/packages/core/src/processes/build-runner.ts +62 -70
- package/packages/core/src/processes/dispatch-failure-budget.ts +5 -4
- package/packages/core/src/processes/dispatcher.ts +223 -205
- package/packages/core/src/processes/execution-no-progress.ts +176 -0
- package/packages/core/src/processes/harvest-child.ts +30 -4
- package/packages/core/src/processes/harvest-execution-state.ts +15 -9
- package/packages/core/src/processes/harvest-runner.ts +58 -74
- package/packages/core/src/processes/harvest.ts +72 -29
- package/packages/core/src/processes/infrastructure-failure-budget.ts +13 -15
- package/packages/core/src/processes/orchestrator-tick.ts +2 -2
- package/packages/core/src/processes/phase-failure-budget.ts +1 -0
- package/packages/core/src/processes/publication-loss.ts +35 -21
- package/packages/core/src/processes/repo-view.ts +229 -1099
- package/packages/core/src/processes/tick-publication.ts +110 -0
- package/packages/core/src/store/adapter.ts +23 -0
- package/packages/core/src/store/build-scope.ts +17 -0
- package/packages/core/src/store/contract.ts +283 -1
- package/packages/core/src/store/local/schema.ts +1 -0
- package/packages/core/src/store/local/store.ts +180 -55
- package/packages/core/src/store/memory.ts +119 -29
- package/packages/core/src/store/phase-session.ts +17 -0
- package/packages/core/src/store/reduced-reads.ts +239 -0
- package/packages/core/src/store/reducer-value-shapes.json +14056 -0
- package/packages/core/src/store/reducer-value-validation.ts +96 -0
- package/packages/core/src/store/reducer-values.ts +145 -0
- package/packages/core/src/store/remote/client.ts +41 -0
- package/packages/core/src/store/remote/compatibility.ts +2 -0
- package/packages/core/src/store/remote/index.ts +19 -0
- package/packages/core/src/store/remote/protocol.ts +16 -0
- package/packages/core/src/store/remote/version.ts +3 -1
- package/packages/core/src/store/repo-state-events.ts +1 -1
- package/packages/core/src/store/repo-tick.ts +72 -0
- package/packages/core/src/store/session-handle.ts +19 -0
- package/packages/core/src/store/snapshots.ts +10 -0
- package/packages/core/src/store/ticket-asset-snapshots.ts +192 -0
- package/packages/core/src/store/ticket-assets.ts +86 -8
- package/packages/core/src/store/types.ts +40 -3
- package/packages/core/src/testing/dispatch-read-budget.ts +215 -0
- package/packages/core/src/testing/index.ts +8 -0
- package/packages/core/src/testing/reduced-read-budget.ts +462 -0
- package/skills/guide/SKILL.md +97 -12
- package/skills/guide/references/operator-api.md +8 -1
- package/skills/guide/references/remote-store-protocol.md +94 -2
- package/skills/guide/references/remote-ticket-protocol.md +151 -9
- package/skills/guide/references/setup.md +33 -7
- package/skills/guide/references/ticket-migration.md +64 -0
- package/skills/tickets/SKILL.md +71 -0
- package/templates/hosted-service/package.json +2 -2
package/docs/configuration.md
CHANGED
|
@@ -202,6 +202,10 @@ dashboard notice row or on plain-mode stderr, and suppresses repeats while the
|
|
|
202
202
|
same failure remains. Restoring `autobuild.toml` with valid configuration clears
|
|
203
203
|
the rejection and ordinary live reload resumes without a dispatcher restart.
|
|
204
204
|
|
|
205
|
+
Dispatcher merge readiness, startup resume, and execution recovery use the same pinned
|
|
206
|
+
commands, verify, and finalize configuration as the build runner. Missing pins retain
|
|
207
|
+
the legacy live-configuration fallback.
|
|
208
|
+
|
|
205
209
|
These fields hot-reload:
|
|
206
210
|
|
|
207
211
|
| Field or table | Boundary where a new value applies |
|
|
@@ -210,8 +214,8 @@ These fields hot-reload:
|
|
|
210
214
|
| `ticketScanIntervalSeconds` | Next tick; evaluates elapsed time against the new interval. |
|
|
211
215
|
| `capacity` | Next dispatcher tick. |
|
|
212
216
|
| `[pr]` | Next build creation. |
|
|
213
|
-
| `[commands]` | Next setup, verify check, or finalize check selected for a build whose OWN branch carries it. A base-branch reload does not retarget an in-flight build. |
|
|
214
|
-
| `[verify]` and `[finalize]` | Next engine step selection for a build whose OWN branch carries it. An approved plan's stored verify selection remains authoritative, and a base-branch reload does not retarget an in-flight build. |
|
|
217
|
+
| `[commands]` | Next setup, verify check, or finalize check selected for a build whose OWN branch carries it. Dispatcher readiness, resume, and recovery use the same pin. A base-branch reload does not retarget an in-flight build. |
|
|
218
|
+
| `[verify]` and `[finalize]` | Next engine step selection for a build whose OWN branch carries it. Dispatcher readiness, resume, and recovery use the same pin. An approved plan's stored verify selection remains authoritative, and a base-branch reload does not retarget an in-flight build. |
|
|
215
219
|
| `[workspace]` provider and config (including `provisioning`) | Next launch of a build whose OWN branch carries it. A base-branch reload never re-provisions an in-flight build. |
|
|
216
220
|
| `[roles]` | Next agent invocation for that role. Runtime, model, args, alternates, and the session budget are captured together and delivered live. |
|
|
217
221
|
| `[policy]` | Next policy, convergence, or agent-session boundary, delivered live. A running session keeps its captured budget. |
|
|
@@ -1185,6 +1189,21 @@ clears the streak. Recovery-provider workspace failures belong exclusively to
|
|
|
1185
1189
|
the infrastructure budget. Exhaustion is repaired from durable facts on restart
|
|
1186
1190
|
before further dispatch work.
|
|
1187
1191
|
|
|
1192
|
+
The dispatcher also applies a fixed, non-configurable limit of three consecutive
|
|
1193
|
+
executions that complete normally with exit code zero and no durable build
|
|
1194
|
+
progress. Execution start/end, runner attachment and workspace lifecycle
|
|
1195
|
+
bookkeeping do not count as progress. Pipeline, session, spec, publication/PR,
|
|
1196
|
+
observation and acknowledged operator facts reset the streak; infrastructure,
|
|
1197
|
+
budget and provider failures do not consume the allowance and retain their own
|
|
1198
|
+
retry limits. Before a fourth actionable launch, the dispatcher raises one
|
|
1199
|
+
setup-targeted `execution-no-progress` policy escalation naming the count and
|
|
1200
|
+
the next action it expected the runner to take. Waiting, paused and terminal
|
|
1201
|
+
builds are left parked, and pending operator commands remain executable.
|
|
1202
|
+
Answering that escalation with guidance or a bare `ab answer <slug>` retry grants
|
|
1203
|
+
three fresh executions. The guard is derived from durable facts, including on
|
|
1204
|
+
supervisor restart, and uses the ordinary watch, dashboard and operator API
|
|
1205
|
+
attention paths.
|
|
1206
|
+
|
|
1188
1207
|
For each repeat conflict, Autobuild compares the base merged by the most recent
|
|
1189
1208
|
completed reconcile with a fresh authoritative base snapshot. An advanced base
|
|
1190
1209
|
proves the attempt lost a race and permits another reconcile regardless of the
|
|
@@ -1224,21 +1243,25 @@ invariants, not additional configuration fields.
|
|
|
1224
1243
|
|
|
1225
1244
|
## `[tickets]`
|
|
1226
1245
|
|
|
1246
|
+
To move an existing project between sources, follow the
|
|
1247
|
+
[ticket migration procedure](ticket-migration.md).
|
|
1248
|
+
|
|
1227
1249
|
Required in practice: `readyState` deliberately has no default, so omitting the
|
|
1228
1250
|
table fails at `tickets.readyState` rather than allowing tickets from every
|
|
1229
|
-
state. Within a present table, `source`
|
|
1251
|
+
state. Within a present table, `source` is required; hosted tickets default `readyState` to `ready`. Other sources require it.
|
|
1230
1252
|
|
|
1231
1253
|
| Field | Default | Constraints | Purpose |
|
|
1232
1254
|
|---|---:|---|---|
|
|
1233
1255
|
| `source` | — | required nonblank builtin or plugin registration name | Select the ticket adapter after configured plugins load. |
|
|
1234
1256
|
| `readyLabels` | source-aware | optional array of nonempty strings; `[]` allowed | Require every listed label in addition to the state gate. |
|
|
1235
|
-
| `
|
|
1257
|
+
| `url` | selected build service | HTTPS service URL; HTTP allowed on loopback; no credentials, query or fragment; hosted only | Ticket service independent of [store] url and AB_STORE. Required with local builds. |
|
|
1258
|
+
| `readyState` | hosted: `"ready"` | nonblank string; required for other sources | The one workflow state eligible for dispatch. |
|
|
1236
1259
|
| `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. |
|
|
1237
1260
|
| `teamKey` | — | required for Linear and hosted; forbidden for file; optional for plugins | Backend team key such as `"ENG"`, or an existing plugin config field. |
|
|
1238
|
-
| `claimedState` | `"In Progress"` for direct Linear; `"
|
|
1239
|
-
| `doneState` | `"
|
|
1261
|
+
| `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. |
|
|
1262
|
+
| `doneState` | hosted: `"done"` | optional nonblank string; hosted | Project completion state and merged-ticket transition. |
|
|
1240
1263
|
| `createState` | provider default | optional nonempty string | Default state for newly created tickets when `ab ticket create` omits `--state`. |
|
|
1241
|
-
| `triageState` | Linear
|
|
1264
|
+
| `triageState` | Linear: `"Backlog"`; hosted: `"triage"`; file/plugin: `"Triage"` | optional nonempty string | State used for spec-gate bounces, aborts, and closed-unmerged PRs. |
|
|
1242
1265
|
| `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. |
|
|
1243
1266
|
| `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. |
|
|
1244
1267
|
|
|
@@ -1257,7 +1280,7 @@ When `readyLabels` is absent, direct Linear uses `["autobuild"]`; hosted, file,
|
|
|
1257
1280
|
and plugin sources use `[]`, meaning no host-imposed label gate. An explicit value always
|
|
1258
1281
|
wins. A nonempty list is
|
|
1259
1282
|
conjunctive: every configured label must be present. `readyState` remains
|
|
1260
|
-
mandatory regardless of labels. Linear compares state and label names exactly
|
|
1283
|
+
mandatory regardless of labels (hosted defaults to `ready`). Linear compares state and label names exactly
|
|
1261
1284
|
and case-sensitively. The file source matches state names case-insensitively against the directories
|
|
1262
1285
|
under the tracker root: the four lifecycle directories (`triage/`, `ready/`,
|
|
1263
1286
|
`doing/`, `done/`, always present) plus any directory the repository adds, such
|
|
@@ -1279,6 +1302,15 @@ Source-specific validation is strict:
|
|
|
1279
1302
|
- Plugin sources receive the existing fields in this table unchanged and own
|
|
1280
1303
|
any additional semantic validation. No untyped plugin-options table exists.
|
|
1281
1304
|
|
|
1305
|
+
Hosted states are durable service data scoped to a project. `ab ticket states`
|
|
1306
|
+
lists configured lifecycle roles first, then custom states alphabetically, with
|
|
1307
|
+
counts and optional purposes. `ab ticket state create <name> [--about <text>]`
|
|
1308
|
+
adds a state using the file source's lowercase name grammar. Hosted duplicates
|
|
1309
|
+
in any letter case are refused; file creation remains idempotent. Configured
|
|
1310
|
+
names always exist, preserve their spelling, and remain custom states after
|
|
1311
|
+
removal from config. Any existing state supports ticket create, move, and list;
|
|
1312
|
+
unknown names report the available states. Purposes must be one nonblank line.
|
|
1313
|
+
|
|
1282
1314
|
For Linear, omitting `createState` lets the team's default state apply. For the
|
|
1283
1315
|
file source it defaults to `Triage`. A caller may override that default for one
|
|
1284
1316
|
create with `ab ticket create --state <state>`; the value is passed unchanged to
|
|
@@ -1703,7 +1735,7 @@ Secrets and store selection accompany the file through environment variables:
|
|
|
1703
1735
|
| Variable | Used for | Notes |
|
|
1704
1736
|
|---|---|---|
|
|
1705
1737
|
| `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
|
|
1738
|
+
| `AB_STORE` | BuildStore and hosted ticket selection | A local path or HTTP(S) remote-store URL. Hosted tickets use this only when `[tickets] url` is absent; local builds with hosted tickets require `[tickets] 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
1739
|
| `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. |
|
|
1708
1740
|
|
|
1709
1741
|
A local store selection relocates the state database, blobs, worktrees, and the
|
package/docs/hosted-service.md
CHANGED
|
@@ -17,8 +17,8 @@ package's `deployment/` directory and in `templates/hosted-service/`).
|
|
|
17
17
|
"build": "ab-hosted-service-build"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@defrex/autobuild-hosted-store-service": "0.
|
|
21
|
-
"@defrex/autobuild": "0.
|
|
20
|
+
"@defrex/autobuild-hosted-store-service": "0.14.0",
|
|
21
|
+
"@defrex/autobuild": "0.14.0",
|
|
22
22
|
"next": "16.1.6",
|
|
23
23
|
"react": "19.2.4",
|
|
24
24
|
"react-dom": "19.2.4"
|
|
@@ -153,9 +153,9 @@ or manual production deployment is required.
|
|
|
153
153
|
## Hosted ticket projects and v1 migration
|
|
154
154
|
|
|
155
155
|
Hosted queues are partitioned by registered repository. Credentials select the
|
|
156
|
-
project
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
project. Independent ticket policy selects lifecycle; `ab connect --tickets URL`
|
|
157
|
+
publishes it before dispatch. Older clients retain uploaded dispatcher configuration
|
|
158
|
+
as a fallback. See the [ticket protocol](remote-ticket-protocol.md). Projects using file,
|
|
159
159
|
Linear or another external source continue to access it directly through their
|
|
160
160
|
dispatcher. Service ticket surfaces refuse those projects with source feedback.
|
|
161
161
|
The service never connects to Linear.
|
|
@@ -212,3 +212,29 @@ Missing blob configuration or denied reads stop deployment before Next builds;
|
|
|
212
212
|
diagnostics never print credentials. SQL-only fresh installs, empty-v1 upgrades
|
|
213
213
|
and already-v2 reruns do not open blob storage and keep their existing database
|
|
214
214
|
requirements. Migration reruns are idempotent.
|
|
215
|
+
|
|
216
|
+
## Local builds with hosted tickets
|
|
217
|
+
|
|
218
|
+
Hosted tickets do not require hosted builds. Set `[tickets] source = "hosted"`
|
|
219
|
+
and `teamKey = "ENG"`, then run `ab connect --tickets https://your-service.example`.
|
|
220
|
+
Approve the project in the browser. This saves a service-scoped credential and
|
|
221
|
+
`[tickets] url` while leaving `[store]` unchanged. Ticket commands work immediately,
|
|
222
|
+
before any dispatcher runs. `ab connect` reports every service and whether it serves
|
|
223
|
+
builds, tickets, or both. Use `ab disconnect --tickets` to revoke ticket access;
|
|
224
|
+
when services differ use `--builds` to select build access. Shared uses share one
|
|
225
|
+
credential, so disconnecting either shared use affects both.
|
|
226
|
+
|
|
227
|
+
Ticket URL selection is `[tickets] url`, then the selected build service (including
|
|
228
|
+
AB_STORE or a supported --store override). With local builds, `[tickets] url` is
|
|
229
|
+
required. Builds, events, artifacts, and harvest journals remain in the local store.
|
|
230
|
+
The service stores ticket records, project ticket policy, and restricted ticket
|
|
231
|
+
grants. Normal project clients synchronize current `[tickets]` policy before use;
|
|
232
|
+
failed synchronization fails the operation. Harvest grants can read and create;
|
|
233
|
+
phase grants can only read. Neither can change policy or access BuildStore routes.
|
|
234
|
+
|
|
235
|
+
New hosted policy defaults to `triage`, `ready`, `doing`, `done`, with creation and
|
|
236
|
+
harvest proposals in `triage`. Explicit state names preserve their spelling.
|
|
237
|
+
To retain earlier names configure `triageState = "Backlog"`,
|
|
238
|
+
`claimedState = "Doing"`, `doneState = "Done"`, and the desired `readyState`.
|
|
239
|
+
Existing ticket rows are never renamed. Older combined-service clients continue
|
|
240
|
+
using the uploaded dispatcher configuration until independent policy is published.
|
package/docs/operator-api.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Operator API v1
|
|
2
2
|
|
|
3
3
|
The hosted service exposes the polling-oriented operator surface at
|
|
4
|
-
`/operator/v1/repos/{repo}`. It is versioned with remote store protocol **
|
|
4
|
+
`/operator/v1/repos/{repo}`. It is versioned with remote store protocol **4**.
|
|
5
5
|
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.
|
|
@@ -87,6 +87,7 @@ turn runner (a later ticket) is the only producer of turn facts.
|
|
|
87
87
|
| `GET …/harvest/status` | Harvest gate, runs, steps, recovery, and attention projection. |
|
|
88
88
|
| `GET …/builds/{slug}/artifacts/{kind}?rev=N` | Raw bytes (`application/octet-stream`) plus content-disposition and `X-Autobuild-Artifact-*` metadata headers. Omit `rev` for latest. |
|
|
89
89
|
| `GET …/tickets?state=S&label=L` | `{states,tickets,diagnostics,criteria,triageState,readyState}`. The two lifecycle names come from effective repository configuration (including provider fallback). With no `state`, `criteria.state` is `triageState`; repeated `label` parameters narrow that state with AND filters. An explicit `state` selects that exact backend workflow state. |
|
|
90
|
+
| `GET …/tickets/states` | Full state metadata `{name,tickets,about?}[]`, including empty states (`tickets.states` in MCP). |
|
|
90
91
|
| `GET …/tickets/{id}` | `{ticket,blockers,build}`. Blockers include native `exists`/`resolved` status; `build` prefers an active matching repository build, otherwise the most recently updated one. |
|
|
91
92
|
|
|
92
93
|
For artifact reads, an absent `rev` selects the latest revision. A supplied value
|
|
@@ -119,6 +120,7 @@ JSON bodies are strict: unknown fields are rejected.
|
|
|
119
120
|
| `POST …/settings/auto-merge-default/toggle` | Empty body. |
|
|
120
121
|
| `POST …/bulk-control` | `{"action":"pause"\|"resume"}`. The hold fact, intake fact, then eligible build events are written in that order. |
|
|
121
122
|
| `POST …/harvest/control` | `{"action":"toggle-gate"}` or `{"action":"run","run":"…"}`. A run action is bound to that concrete projected run. |
|
|
123
|
+
| `POST …/tickets/states` | `{name,about?}` → `{state,created}`; requires attributed operator identity (`tickets.state.create` in MCP). Hosted duplicate names are refused case-insensitively. |
|
|
122
124
|
| `POST …/tickets` | `{"title":"…","body":"…","labels"?:[],"state"?:"…","blockedBy"?:[]}`; omitted state preserves the backend default. |
|
|
123
125
|
| `PATCH …/tickets/{id}` | Any nonempty subset of `title`, `body`, and complete-replacement `labels`. Body bytes are not normalized. |
|
|
124
126
|
| `POST …/tickets/{id}/move` | `{"state":"backend state name"}`. |
|
|
@@ -284,3 +286,8 @@ even with `--since`; live and backlog matches ignore routine outcomes and
|
|
|
284
286
|
self-healing failures. A merge match uses the watch observation with
|
|
285
287
|
`condition: "attention"`. Explicit `--event` globs remain event-only.
|
|
286
288
|
Watch and wait preserve each other's cursor notification metadata.
|
|
289
|
+
|
|
290
|
+
Hosted ticket tools resolve independent project ticket policy before legacy uploaded
|
|
291
|
+
configuration. Queue, detail, state discovery and mutations work before any build
|
|
292
|
+
or dispatcher run; detail reports a null matching build. Ticket policy publication
|
|
293
|
+
never creates synthetic build or repository history.
|
|
@@ -37,7 +37,7 @@ headers, or available backend.
|
|
|
37
37
|
`[store] url` (in that precedence order, before the local default); the shipped client appends the routes below.
|
|
38
38
|
- Every `/builds`, `/repos`, and `/sessions` request sends
|
|
39
39
|
`X-Autobuild-Version` with the exact client package version and
|
|
40
|
-
`X-Autobuild-Protocol-Version` with the remote protocol version (`
|
|
40
|
+
`X-Autobuild-Protocol-Version` with the remote protocol version (`4` in this
|
|
41
41
|
distribution). Before authentication,
|
|
42
42
|
body parsing, or resource lookup, the server validates the release-line window and known protocol identity.
|
|
43
43
|
Unsupported or missing values receive `409 {"kind":"conflict","error":"…"}`;
|
|
@@ -355,6 +355,74 @@ part of this protocol. Retention is enforced server-side inside the store at
|
|
|
355
355
|
deposit time (bounded pruning of dispatcher run/config artifact revisions),
|
|
356
356
|
not through any endpoint.
|
|
357
357
|
|
|
358
|
+
### Named reducer values
|
|
359
|
+
|
|
360
|
+
`POST /builds/{slug}/reducer-values` and
|
|
361
|
+
`POST /repos/{repo}/reducer-values` accept at most 4 KiB of JSON:
|
|
362
|
+
|
|
363
|
+
```json
|
|
364
|
+
{"reducer":"dispatchStatus","args":{"run":"run-a"}}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
The response is `200 {"version":2,"cursor":123,"value":{...}}`. Only the
|
|
368
|
+
finished JSON answer is returned, with no accumulator or raw-log bundle. `cursor`
|
|
369
|
+
is the authoritative prefix included in the answer, not a guarantee to include
|
|
370
|
+
appends concurrent with the request. Every call checks durable progress and
|
|
371
|
+
persisted state; parallel instances may safely advance the same checkpoint.
|
|
372
|
+
Snapshots are disposable caches: deletion, corruption, wrong versions and
|
|
373
|
+
unreadable cache storage cause replay. Log read failures remain errors.
|
|
374
|
+
|
|
375
|
+
The executable catalog is `kernel/reducer-registry.ts`. All requests reject
|
|
376
|
+
unknown names, excluded reducers, wrong scopes and invalid/extra arguments with
|
|
377
|
+
`400 validation`. A missing resource is `404`, project and delegated authority
|
|
378
|
+
checks are the same as other reads, and unsupported methods remain unavailable.
|
|
379
|
+
The operation is read-only authority even though its HTTP verb is POST and its
|
|
380
|
+
internal cache may advance. It does not accept caller-supplied state. This is an
|
|
381
|
+
additive protocol route: historical snapshot and event handlers and the supported
|
|
382
|
+
client version window are unchanged.
|
|
383
|
+
|
|
384
|
+
| Scope | Reducers with no arguments |
|
|
385
|
+
| --- | --- |
|
|
386
|
+
| Build | `executionNoProgress`, `summaryRequests`, `build`, `buildDigest`, `currentPrAttachments`, `pendingPrAttachmentReclaims`, `openExecution`, `lastExecutionOutcome`, `infrastructureFailureReset`, `openWorkspace`, `setupStreak`, `openBuildWorkspace`, `currentDeferralObservation`, `dashboardFacts`, `pinnedAssets`, `buildDelegation` |
|
|
387
|
+
| Repository | `harvest`, `dispatchSettings`, `sandboxStates`, `openHarvestExecutions`, `autoMergeDefault`, `effectiveConfig`, `harvestDelegation` |
|
|
388
|
+
|
|
389
|
+
| Reducer | Scope | Required arguments |
|
|
390
|
+
| --- | --- | --- |
|
|
391
|
+
| `dispatchStatus`, `openTick` | Repository | `run`: nonempty string |
|
|
392
|
+
| `dispatchFailureBudget` | Build | `infrastructureOwnsWorkspace`: boolean |
|
|
393
|
+
| `phaseFailures` | Build | `phase`: valid phase name; `round`: nonnegative integer |
|
|
394
|
+
|
|
395
|
+
Arguments are canonicalized into the cache identity; variants never reuse one
|
|
396
|
+
another's accumulator. `effectiveConfig` returns an object with optional `run`
|
|
397
|
+
and `reference: {kind, rev}`. Absence is distinct from an unreadable referenced
|
|
398
|
+
artifact. Delegation values contain semantic lifecycle facts indexed by prefixed
|
|
399
|
+
identifiers, not authorization decisions; request time and grace expiry are
|
|
400
|
+
always evaluated against those facts on the service.
|
|
401
|
+
|
|
402
|
+
Each remaining registered reducer is explicitly excluded:
|
|
403
|
+
|
|
404
|
+
| Reducers | Reason |
|
|
405
|
+
| --- | --- |
|
|
406
|
+
| `journalView`, `repositoryStateEvents`, `dispatchFrontend` | Raw repository event lists |
|
|
407
|
+
| `session` | Operator-session log scope |
|
|
408
|
+
| `publicationState` | Selector functions in finished value |
|
|
409
|
+
| `logIndex` | Maps and Sets in finished value |
|
|
410
|
+
| `hostedPrAttachments` | Map as finished value |
|
|
411
|
+
| `summaryBoundary`, `ticketSourceHealth`, `frozenPrImageHost`, `publishedBranchHead`, `verifyDiffBase`, `recordedBaseSha`, `baseBranch`, `provisionMarker`, `recoveryCheckpoint` | Existing finished contract can return top-level `undefined`, which is not JSON |
|
|
412
|
+
|
|
413
|
+
`GET /repos/{repo}/state-events` is **deprecated**. Its response remains unchanged
|
|
414
|
+
for supported clients, including the current dispatcher run's event tail. It is
|
|
415
|
+
the compatibility exception to flat event-row reads; new callers should request
|
|
416
|
+
named values. The current product no longer loads or writes raw-tail snapshots.
|
|
417
|
+
|
|
418
|
+
The `value.*` snapshot namespace is reserved for the adapter's private value
|
|
419
|
+
checkpoint hooks. Public snapshot GET and PUT requests for this prefix return
|
|
420
|
+
`400 validation`, including requests made with delegated or administrator
|
|
421
|
+
credentials. Adapter snapshot APIs reject the same names. Ordinary snapshot
|
|
422
|
+
names retain their existing behavior. The value cache key format is versioned;
|
|
423
|
+
checkpoints from the former publicly writable format are ignored and rebuilt
|
|
424
|
+
from the log after upgrading.
|
|
425
|
+
|
|
358
426
|
### Reducer snapshots
|
|
359
427
|
|
|
360
428
|
A reducer snapshot is one registered reducer's serialized state as of a log
|
|
@@ -485,6 +553,16 @@ does not apply. `{repo}` and `{id}` are percent-encoded path segments. Token
|
|
|
485
553
|
authorization requires a credential for that registered project, or owner admin.
|
|
486
554
|
The family is additive, so `REMOTE_STORE_PROTOCOL_VERSION` did not change.
|
|
487
555
|
|
|
556
|
+
Hosted ticket attachments use the ticket service's existing repository-keyed
|
|
557
|
+
asset routes with the ticket connection's URL and credential, independently
|
|
558
|
+
of the build store. Names, revisions, tombstones and service limits are
|
|
559
|
+
unchanged. Existing service attachments need no migration; old local
|
|
560
|
+
attachments are not moved or used as a fallback. A claim or ticket spec re-pin
|
|
561
|
+
copies exact revisions into immutable chunked repository artifacts in the
|
|
562
|
+
destination build store. Build pins reference explicit snapshot manifests;
|
|
563
|
+
build-scoped asset reads need no ticket credentials. Old pins without snapshot
|
|
564
|
+
references keep their existing ticket-row lookup.
|
|
565
|
+
|
|
488
566
|
A build also reads the assets it froze at its claim through its own build-scoped
|
|
489
567
|
routes, authorized against the build's actual project. The
|
|
490
568
|
server reduces the build's events to find the pinned revision, then returns that
|
|
@@ -1126,7 +1204,7 @@ Four shipped behaviors do not add `BuildStore` routes:
|
|
|
1126
1204
|
store lifecycle; there is no close endpoint.
|
|
1127
1205
|
- `GET /health` is outside the `BuildStore` interface. It is always open and
|
|
1128
1206
|
returns exactly `200 {"ok":true,"autobuildVersion":"<package>",
|
|
1129
|
-
"protocolVersion":"
|
|
1207
|
+
"protocolVersion":"4", "supportedClientRange":{"minVersion":"0.9.0",
|
|
1130
1208
|
"maxVersionExclusive":"0.12.0"}}`. It reports HTTP-process availability and identity,
|
|
1131
1209
|
not a deeper backing-store transaction or migration check.
|
|
1132
1210
|
|
|
@@ -1203,3 +1281,17 @@ require a project credential and operate only on its own identity; admin and
|
|
|
1203
1281
|
internal operator credentials cannot impersonate self-service. All protocol
|
|
1204
1282
|
responses are no-store/no-referrer. Connection commands are unavailable in
|
|
1205
1283
|
build/harvest sessions.
|
|
1284
|
+
|
|
1285
|
+
### Repository tick telemetry (protocol 4)
|
|
1286
|
+
|
|
1287
|
+
`POST /repos/:repo/tick/begin` accepts `{holder}` and returns the actual start
|
|
1288
|
+
timestamp, or null when the unexpired repository lease does not match.
|
|
1289
|
+
`POST /repos/:repo/tick/finish` accepts `{holder, completion, events}`. Completion
|
|
1290
|
+
is `{outcome:"completed", counters}` or `{outcome:"failed", error}`; events is
|
|
1291
|
+
empty for a quiet success or a matching dispatcher start/terminal pair for that
|
|
1292
|
+
holder. The validated batch and finished telemetry commit atomically. The reply
|
|
1293
|
+
is `{observation, events}` with assigned envelopes, or null on fencing failure.
|
|
1294
|
+
These operations never renew the lease. Repository records optionally expose
|
|
1295
|
+
`tick: {run, open?: {startedAt}, finished?: {run, startedAt, completedAt, ...completion}}`.
|
|
1296
|
+
They retain the previous completion while a new tick is open and after lease
|
|
1297
|
+
release. Build and session credentials cannot mutate repository ticks.
|
|
@@ -67,6 +67,16 @@ must match the credential's project; mismatches are 403. Owner admin requests
|
|
|
67
67
|
require this selector and registration is checked before configuration is read.
|
|
68
68
|
Internal operator credentials remain forbidden on machine ticket routes.
|
|
69
69
|
|
|
70
|
+
Hosted ticket attachments use the ticket service's existing repository-keyed
|
|
71
|
+
asset routes with the ticket connection's URL and credential, independently
|
|
72
|
+
of the build store. Names, revisions, tombstones and service limits are
|
|
73
|
+
unchanged. Existing service attachments need no migration; old local
|
|
74
|
+
attachments are not moved or used as a fallback. A claim or ticket spec re-pin
|
|
75
|
+
copies exact revisions into immutable chunked repository artifacts in the
|
|
76
|
+
destination build store. Build pins reference explicit snapshot manifests;
|
|
77
|
+
build-scoped asset reads need no ticket credentials. Old pins without snapshot
|
|
78
|
+
references keep their existing ticket-row lookup.
|
|
79
|
+
|
|
70
80
|
The strict request envelope is:
|
|
71
81
|
|
|
72
82
|
```json
|
|
@@ -82,16 +92,37 @@ The strict request envelope is:
|
|
|
82
92
|
|
|
83
93
|
`teamKey` remains required for older client compatibility. It and the optional
|
|
84
94
|
`claimedState` / `createState` fields are ignored as policy inputs. The service
|
|
85
|
-
loads the project's
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
95
|
+
loads the project's durable independent ticket policy. Project authority publishes
|
|
96
|
+
version 1 policy through `POST /tickets/policy`, using the usual context/input
|
|
97
|
+
envelope. The input contains only `version` and `tickets`: source, teamKey,
|
|
98
|
+
readyState, triageState, claimedState, doneState, createState, proposalState and
|
|
99
|
+
optional readyLabels. URL, secrets, and pipeline configuration are rejected.
|
|
100
|
+
Only project or owner authority can publish. This does not append BuildStore
|
|
101
|
+
history. Registration removal invalidates policy and grants from that registration.
|
|
102
|
+
|
|
103
|
+
For compatibility, projects without independent policy use their latest uploaded
|
|
104
|
+
dispatcher configuration with the old `Backlog`, `Doing`, `Done` defaults.
|
|
105
|
+
New policy defaults are `triage`, `ready`, `doing`, `done`; create/proposal follow
|
|
106
|
+
triage. States are persistent project data, including empty states and optional
|
|
107
|
+
one-line purposes. Configured role names always exist; removed roles remain as
|
|
108
|
+
custom states and keep their tickets. Explicit settings preserve state spelling.
|
|
109
|
+
State lookup prefers an exact match, then a unique case-insensitive match;
|
|
110
|
+
unknown or ambiguous names are refused. Lists order configured triage, ready,
|
|
111
|
+
doing, done first (deduplicated), then other names alphabetically.
|
|
112
|
+
|
|
113
|
+
`[tickets] url` selects the ticket service independently of the build store;
|
|
114
|
+
otherwise the selected remote build store is used. A local build store requires
|
|
115
|
+
an explicit ticket URL. Credentials are resolved for that selected service.
|
|
116
|
+
`ab connect --tickets URL` registers and publishes policy before any dispatcher run.
|
|
89
117
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
118
|
+
`POST /tickets/grants` issues, renews or revokes short-lived, digest-stored ticket
|
|
119
|
+
grants. Project authority issues runner grants scoped to project and execution;
|
|
120
|
+
runners may issue only read-only phase children bound to themselves. Runner grants
|
|
121
|
+
allow read and create; phase grants allow read only. Policy, claim, moves, comments,
|
|
122
|
+
updates, blocker changes, BuildStore, and credential administration are denied.
|
|
123
|
+
AB_TICKET_URL and AB_TICKET_TOKEN carry this authority separately from AB_STORE and
|
|
124
|
+
AB_TOKEN. Revocation, expiry, parent revocation and registration changes invalidate
|
|
125
|
+
grants. Existing combined-service BuildStore delegation remains supported.
|
|
95
126
|
|
|
96
127
|
The service never contacts Linear or relays external trackers. If the project's
|
|
97
128
|
source is Linear, file or another non-hosted source, machine HTTP, operator and
|
|
@@ -111,6 +142,8 @@ The operation names and `input` values are:
|
|
|
111
142
|
|
|
112
143
|
| Operation | Input | Successful response |
|
|
113
144
|
|---|---|---|
|
|
145
|
+
| `states` | `{}` | `{name, tickets, about?}[]`, including empty states |
|
|
146
|
+
| `add-state` | `{name, about?: string}` | `{state: {name,tickets,about?}, created: boolean}` |
|
|
114
147
|
| `list-ready` | `{labels?: string[], state?: string}` | `TicketListing` |
|
|
115
148
|
| `get` | `{id}` | `Ticket \| null` |
|
|
116
149
|
| `claim` | `{id}` | `{claimed: boolean}` |
|
|
@@ -132,6 +165,35 @@ Ticket body strings are opaque. Clients, JSON handling, the service, and the
|
|
|
132
165
|
database backend must not trim or normalize bytes, newlines, Unicode, blank
|
|
133
166
|
lines, or trailing whitespace.
|
|
134
167
|
|
|
168
|
+
## Readable ticket identity
|
|
169
|
+
|
|
170
|
+
New hosted tickets use `<teamKey>-<n>`, for example `ENG-1`. The effective
|
|
171
|
+
project configuration supplies the literal prefix; the request's `teamKey`
|
|
172
|
+
does not choose it. Numbers start at 1 in each project, increase atomically
|
|
173
|
+
across concurrent creates, and are never reused after deletion. Projects sharing
|
|
174
|
+
a team key have independent counters. Changing `teamKey` affects only future
|
|
175
|
+
ids and continues the same numbering; existing ids retain their captured prefix.
|
|
176
|
+
|
|
177
|
+
Every ticket operation, CLI command, MCP tool and blocker input accepts readable
|
|
178
|
+
ids in any letter case. Legacy storage ids (such as `ticket-<uuid>`) remain
|
|
179
|
+
aliases, including references in existing builds, harvest records and assets.
|
|
180
|
+
Current ticket and blocker output uses the canonical readable id. The exception
|
|
181
|
+
is `dependency-states`: each result's `id` echoes the requested id for correlation,
|
|
182
|
+
while its `blockedBy` edges are canonical. Raw historical events and artifacts
|
|
183
|
+
remain unchanged. These rules apply only to hosted tickets, not file or Linear ids.
|
|
184
|
+
|
|
185
|
+
Upgrade the service with its environment-aware migration command before serving
|
|
186
|
+
requests. The transactional migration preserves storage keys and assigns existing
|
|
187
|
+
tickets numbers in `(created_at, id)` order within each project. It first resolves
|
|
188
|
+
legacy team ownership, then reads each populated project's current independent
|
|
189
|
+
ticket policy. Projects without that policy use their selected effective
|
|
190
|
+
configuration through the configured blob backend. Independent-policy projects
|
|
191
|
+
need no uploaded config or blob access. Missing or invalid fallback config,
|
|
192
|
+
missing `teamKey`, or inaccessible required blobs abort the entire migration
|
|
193
|
+
unchanged with a project diagnostic. Restore that config/blob access and rerun;
|
|
194
|
+
an ownership assignment alone cannot supply a readable prefix. Empty projects
|
|
195
|
+
need no config lookup. Re-running a completed migration does not renumber tickets.
|
|
196
|
+
|
|
135
197
|
## Errors and conformance
|
|
136
198
|
|
|
137
199
|
Errors are JSON `{ "error": string, "kind": "validation" | "not-found" |
|
|
@@ -170,3 +232,83 @@ project removal are also checked before parsing or source construction.
|
|
|
170
232
|
|
|
171
233
|
Ticket admission and assets use the authenticated project, including for
|
|
172
234
|
delegated harvest grants.
|
|
235
|
+
|
|
236
|
+
Custom state creation uses `/^[a-z][a-z0-9-]{0,39}$/`; an optional purpose must
|
|
237
|
+
be one nonblank line. A duplicate in any letter case is refused without
|
|
238
|
+
changing purpose. `add-state` requires project or owner machine authority;
|
|
239
|
+
ticket grants and harvest delegations can read states but cannot create them.
|
|
240
|
+
Request context cannot supply lifecycle policy or insert another project's
|
|
241
|
+
states. These operations use the existing wire version and strict envelopes.
|
|
242
|
+
|
|
243
|
+
## Revision-checked ticket writes
|
|
244
|
+
|
|
245
|
+
Every ticket read includes an opaque `revision`. Pass it as `expectedRevision`
|
|
246
|
+
(on MCP/operator requests) or `--expected-revision <opaque>` on `ab ticket update`,
|
|
247
|
+
`move`, `block` and `unblock`. A stale write fails without changing anything and
|
|
248
|
+
reports the current revision. Omission preserves unguarded behavior. Blocker
|
|
249
|
+
checks cover the entire batch. Dispatcher moves remain unguarded and change the
|
|
250
|
+
revision. Sources without guarded writes, including Linear, refuse supplied
|
|
251
|
+
revisions rather than ignoring them.
|
|
252
|
+
|
|
253
|
+
`ab ticket edit <id>` opens `$VISUAL`, falling back to `$EDITOR`, using TOML
|
|
254
|
+
frontmatter and a Markdown body. Only title, body and labels are editable;
|
|
255
|
+
id, blockers, creation key and reference comments are read-only. It saves only
|
|
256
|
+
changed fields with the opening revision. Unchanged or formatting-only edits
|
|
257
|
+
write nothing. On conflict, invalid input or editor failure, the error names an
|
|
258
|
+
absolute file path containing the edited text. Read the current ticket and
|
|
259
|
+
reapply the intended changes before retrying; conflicts are never merged.
|
|
260
|
+
|
|
261
|
+
File and Linear revisions fingerprint title, body, canonical label/blocker sets
|
|
262
|
+
and state; reverting identical content restores its fingerprint. File checks
|
|
263
|
+
re-read immediately before writing, with the existing no-lock race window.
|
|
264
|
+
Direct file edits and state-directory moves change revisions. File revisions also
|
|
265
|
+
cover structured comments and portable attachments. Legacy file comments change
|
|
266
|
+
the body; structured comments preserve it. Separate hosted comments do not change
|
|
267
|
+
ticket revisions. Hosted revisions
|
|
268
|
+
are monotonic decimal bigint strings, and checks run under the same row lock
|
|
269
|
+
and transaction as all requested changes. Hosted reads return a coherent
|
|
270
|
+
snapshot of fields, blockers and revision.
|
|
271
|
+
|
|
272
|
+
### Guarded mutation transport
|
|
273
|
+
|
|
274
|
+
`POST /tickets/mutate-if-revision` accepts the usual authenticated context and
|
|
275
|
+
`input: { id, expectedRevision, mutation }`. Mutation is one of
|
|
276
|
+
`{ kind: "update", patch: { title?, body?, labels? } }`,
|
|
277
|
+
`{ kind: "transition", state }`, or
|
|
278
|
+
`{ kind: "blockers", operation: "block" | "unblock", ids: string[] }`.
|
|
279
|
+
Unknown keys and empty patches are refused. Success returns `{ ok: true }`.
|
|
280
|
+
A revision conflict returns HTTP 409 with `kind: "conflict"`, `error`, `id`,
|
|
281
|
+
`expectedRevision` and `currentRevision`. Delegated credentials retain existing
|
|
282
|
+
permissions: none of the guarded mutation variants grants additional access.
|
|
283
|
+
Ticket responses include `revision` only when the request advertises
|
|
284
|
+
`x-autobuild-ticket-revisions: 1`. The current hosted client sends this header
|
|
285
|
+
on every request and requires revision-bearing responses. Released clients
|
|
286
|
+
through 0.12.x omit the header and retain their strict decoder's original
|
|
287
|
+
response shape on get, list-ready and create. This explicit capability also
|
|
288
|
+
supports new source checkouts that still report version 0.12.0; version alone
|
|
289
|
+
cannot distinguish them from released clients. Unknown capability values do
|
|
290
|
+
not opt in. Clients before 0.11 also omit the existing resolution projections.
|
|
291
|
+
The capability does not change authentication, authorization or the remote
|
|
292
|
+
BuildStore protocol version.
|
|
293
|
+
|
|
294
|
+
## Requested ids for migration
|
|
295
|
+
|
|
296
|
+
Create options accept optional `requestedId: string` alongside `state` and
|
|
297
|
+
`idempotencyKey`. Older clients omit it and responses are unchanged. Unsupported
|
|
298
|
+
sources reject supplied ids; Linear is not an import target. File sources keep
|
|
299
|
+
filesystem-safe ids exactly and never overwrite an occupied id.
|
|
300
|
+
|
|
301
|
+
Hosted sources preserve only literal own-team `<teamKey>-<n>` ids, where `n` is a
|
|
302
|
+
positive canonical decimal within PostgreSQL bigint bounds. For example,
|
|
303
|
+
`AUT-706` in team `AUT` keeps 706; `OTHER-706`, `AUT-01` and `AUT-0` use ordinary
|
|
304
|
+
allocation. Overflow canonical numbers are rejected. A matching creation key is
|
|
305
|
+
adopted before occupancy checks. A kept number belonging to a different ticket
|
|
306
|
+
fails without replacing it. Creation and counter advancement share the existing
|
|
307
|
+
project transaction and counter lock. Later automatic numbers exceed both the
|
|
308
|
+
counter and highest occupied number; importing a lower number never lowers the
|
|
309
|
+
counter. Requested ids require project or owner authority. Ticket grants and
|
|
310
|
+
delegated credentials receive 403 for create options containing `requestedId`,
|
|
311
|
+
before source construction. Their ordinary create grants remain unchanged.
|
|
312
|
+
|
|
313
|
+
See the [migration procedure](ticket-migration.md) for preflight, state mapping,
|
|
314
|
+
resumption and portable file records.
|
package/docs/setup.md
CHANGED
|
@@ -398,13 +398,13 @@ the verifier does not fix it.
|
|
|
398
398
|
### Project-scoped hosted tickets
|
|
399
399
|
|
|
400
400
|
Hosted ticket queues belong to the credential's registered repository, even
|
|
401
|
-
when projects share a team key.
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
401
|
+
when projects share a team key. Independent project ticket policy owns lifecycle:
|
|
402
|
+
new defaults are triage / ready / doing / done, with create/proposal following
|
|
403
|
+
triage. Explicit names retain their spelling; doneState customizes completion.
|
|
404
|
+
`ab connect --tickets URL` publishes policy before dispatch. Older clients without
|
|
405
|
+
independent policy retain their uploaded dispatcher configuration and legacy defaults.
|
|
406
|
+
Owner admin requests require an explicit registered context.repo; project credentials
|
|
407
|
+
cannot select another project. See [local builds with hosted tickets](#local-builds-with-hosted-tickets).
|
|
408
408
|
|
|
409
409
|
The service never contacts Linear. Projects with external sources (including
|
|
410
410
|
file and Linear) keep using those sources directly through their dispatcher;
|
|
@@ -447,3 +447,29 @@ require the running service's blob backend, access mode, credentials and prefix
|
|
|
447
447
|
(`AB_BLOB_PREFIX`), not just PostgreSQL access. `deploy:build` inherits this
|
|
448
448
|
environment and migration failure stops Next build. Fresh databases, empty v1
|
|
449
449
|
queues and v2 reruns stay SQL-only and do not initialize blob storage.
|
|
450
|
+
|
|
451
|
+
## Local builds with hosted tickets
|
|
452
|
+
|
|
453
|
+
Hosted tickets do not require hosted builds. Set `[tickets] source = "hosted"`
|
|
454
|
+
and `teamKey = "ENG"`, then run `ab connect --tickets https://your-service.example`.
|
|
455
|
+
Approve the project in the browser. This saves a service-scoped credential and
|
|
456
|
+
`[tickets] url` while leaving `[store]` unchanged. Ticket commands work immediately,
|
|
457
|
+
before any dispatcher runs. `ab connect` reports every service and whether it serves
|
|
458
|
+
builds, tickets, or both. Use `ab disconnect --tickets` to revoke ticket access;
|
|
459
|
+
when services differ use `--builds` to select build access. Shared uses share one
|
|
460
|
+
credential, so disconnecting either shared use affects both.
|
|
461
|
+
|
|
462
|
+
Ticket URL selection is `[tickets] url`, then the selected build service (including
|
|
463
|
+
AB_STORE or a supported --store override). With local builds, `[tickets] url` is
|
|
464
|
+
required. Builds, events, artifacts, and harvest journals remain in the local store.
|
|
465
|
+
The service stores ticket records, project ticket policy, and restricted ticket
|
|
466
|
+
grants. Normal project clients synchronize current `[tickets]` policy before use;
|
|
467
|
+
failed synchronization fails the operation. Harvest grants can read and create;
|
|
468
|
+
phase grants can only read. Neither can change policy or access BuildStore routes.
|
|
469
|
+
|
|
470
|
+
New hosted policy defaults to `triage`, `ready`, `doing`, `done`, with creation and
|
|
471
|
+
harvest proposals in `triage`. Explicit state names preserve their spelling.
|
|
472
|
+
To retain earlier names configure `triageState = "Backlog"`,
|
|
473
|
+
`claimedState = "Doing"`, `doneState = "Done"`, and the desired `readyState`.
|
|
474
|
+
Existing ticket rows are never renamed. Older combined-service clients continue
|
|
475
|
+
using the uploaded dispatcher configuration until independent policy is published.
|