@defrex/autobuild 0.11.0 → 0.13.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.
Files changed (136) hide show
  1. package/README.md +3 -1
  2. package/SPEC.md +335 -31
  3. package/docs/architecture.md +125 -7
  4. package/docs/configuration.md +142 -21
  5. package/docs/hosted-dispatcher.md +17 -2
  6. package/docs/hosted-service.md +240 -0
  7. package/docs/mcp.md +8 -2
  8. package/docs/operator-api.md +97 -7
  9. package/docs/remote-store-protocol.md +199 -144
  10. package/docs/remote-ticket-protocol.md +249 -19
  11. package/docs/setup.md +199 -16
  12. package/docs/ticket-dependencies.md +1 -1
  13. package/docs/ticket-migration.md +64 -0
  14. package/package.json +7 -6
  15. package/packages/core/src/cli/attention.ts +209 -0
  16. package/packages/core/src/cli/build-control.ts +12 -1
  17. package/packages/core/src/cli/configured-store.ts +17 -0
  18. package/packages/core/src/cli/connect.ts +364 -0
  19. package/packages/core/src/cli/context.ts +7 -1
  20. package/packages/core/src/cli/dashboard/model.ts +4 -5
  21. package/packages/core/src/cli/dashboard/poll.ts +1 -1
  22. package/packages/core/src/cli/dispatch.ts +336 -41
  23. package/packages/core/src/cli/harvest.ts +13 -3
  24. package/packages/core/src/cli/help.ts +51 -16
  25. package/packages/core/src/cli/init-validation.ts +27 -2
  26. package/packages/core/src/cli/installation.ts +67 -13
  27. package/packages/core/src/cli/main.ts +60 -16
  28. package/packages/core/src/cli/mcp.ts +9 -2
  29. package/packages/core/src/cli/pr-summary-publication.ts +220 -0
  30. package/packages/core/src/cli/pr-summary.ts +2 -0
  31. package/packages/core/src/cli/project-credentials.ts +132 -0
  32. package/packages/core/src/cli/repo-state.ts +15 -2
  33. package/packages/core/src/cli/self-update.ts +15 -1
  34. package/packages/core/src/cli/store-opening.ts +22 -14
  35. package/packages/core/src/cli/terminals.ts +0 -10
  36. package/packages/core/src/cli/ticket-assets.ts +7 -2
  37. package/packages/core/src/cli/ticket-editor.ts +82 -0
  38. package/packages/core/src/cli/ticket.ts +172 -35
  39. package/packages/core/src/cli/upgrade-compatibility.ts +80 -0
  40. package/packages/core/src/cli/wait.ts +84 -17
  41. package/packages/core/src/cli/watch.ts +197 -60
  42. package/packages/core/src/config/live.ts +3 -0
  43. package/packages/core/src/config/schema.ts +90 -11
  44. package/packages/core/src/connection.ts +86 -0
  45. package/packages/core/src/events/catalog.ts +11 -2
  46. package/packages/core/src/events/payloads.ts +50 -0
  47. package/packages/core/src/events/repository.ts +13 -0
  48. package/packages/core/src/integration/harness.ts +37 -2
  49. package/packages/core/src/kernel/__snapshots__/reducer-registry.test.ts.snap +145 -83
  50. package/packages/core/src/kernel/engine.ts +24 -0
  51. package/packages/core/src/kernel/generators/build-log.ts +11 -1
  52. package/packages/core/src/kernel/incremental-fixtures.ts +13 -2
  53. package/packages/core/src/kernel/log-index.ts +17 -0
  54. package/packages/core/src/kernel/pr-summary.ts +89 -0
  55. package/packages/core/src/kernel/reducer-registry.ts +10 -0
  56. package/packages/core/src/kernel/reducer.ts +8 -0
  57. package/packages/core/src/ontology.ts +2 -0
  58. package/packages/core/src/operator/annotations.ts +12 -0
  59. package/packages/core/src/operator/index.ts +12 -0
  60. package/packages/core/src/operator/protocol.ts +19 -2
  61. package/packages/core/src/operator/query.ts +38 -16
  62. package/packages/core/src/operator/registry.ts +61 -8
  63. package/packages/core/src/operator/ticket-source-backend.ts +17 -20
  64. package/packages/core/src/operator/tickets.ts +136 -28
  65. package/packages/core/src/plugin-sdk/index.ts +7 -0
  66. package/packages/core/src/plugins/manifest.ts +5 -3
  67. package/packages/core/src/plugins/runtimes.ts +7 -1
  68. package/packages/core/src/ports/forge/fake.ts +13 -1
  69. package/packages/core/src/ports/forge/github-transport.ts +36 -1
  70. package/packages/core/src/ports/forge/github.ts +29 -5
  71. package/packages/core/src/ports/forge/local-git.ts +12 -4
  72. package/packages/core/src/ports/forge/summary-marker.ts +8 -0
  73. package/packages/core/src/ports/runner/session-env.ts +3 -0
  74. package/packages/core/src/ports/tickets/contract.ts +66 -1
  75. package/packages/core/src/ports/tickets/create.ts +54 -10
  76. package/packages/core/src/ports/tickets/fake.ts +30 -1
  77. package/packages/core/src/ports/tickets/file-assets.ts +159 -0
  78. package/packages/core/src/ports/tickets/file-codec.ts +90 -0
  79. package/packages/core/src/ports/tickets/file.ts +114 -120
  80. package/packages/core/src/ports/tickets/grants.ts +47 -0
  81. package/packages/core/src/ports/tickets/hosted-index.ts +17 -3
  82. package/packages/core/src/ports/tickets/identity.ts +20 -0
  83. package/packages/core/src/ports/tickets/lifecycle.ts +18 -0
  84. package/packages/core/src/ports/tickets/linear.ts +74 -9
  85. package/packages/core/src/ports/tickets/migration.ts +336 -0
  86. package/packages/core/src/ports/tickets/operations.ts +38 -7
  87. package/packages/core/src/ports/tickets/portable-assets.ts +54 -0
  88. package/packages/core/src/ports/tickets/remote-protocol.ts +96 -0
  89. package/packages/core/src/ports/tickets/remote.ts +61 -3
  90. package/packages/core/src/ports/tickets/requested-id.ts +46 -0
  91. package/packages/core/src/ports/tickets/revision.ts +62 -0
  92. package/packages/core/src/ports/tickets/states.ts +61 -0
  93. package/packages/core/src/ports/types.ts +40 -3
  94. package/packages/core/src/ports/workspace/build-execution.ts +6 -1
  95. package/packages/core/src/ports/workspace/create.ts +15 -2
  96. package/packages/core/src/ports/workspace/distribution-archive.ts +3 -5
  97. package/packages/core/src/ports/workspace/harvest-execution.ts +3 -1
  98. package/packages/core/src/ports/workspace/local-build-execution.ts +8 -1
  99. package/packages/core/src/ports/workspace/operator-sandbox.ts +2 -0
  100. package/packages/core/src/ports/workspace/vercel-sandbox.ts +51 -19
  101. package/packages/core/src/processes/build-execution-state.ts +1 -1
  102. package/packages/core/src/processes/build-runner.ts +87 -26
  103. package/packages/core/src/processes/dispatch-failure-budget.ts +83 -0
  104. package/packages/core/src/processes/dispatcher.ts +168 -41
  105. package/packages/core/src/processes/execution-no-progress.ts +176 -0
  106. package/packages/core/src/processes/harvest-child.ts +31 -4
  107. package/packages/core/src/processes/harvest-execution-state.ts +19 -2
  108. package/packages/core/src/processes/harvest-runner.ts +166 -104
  109. package/packages/core/src/processes/harvest.ts +34 -14
  110. package/packages/core/src/processes/phase-failure-budget.ts +2 -0
  111. package/packages/core/src/processes/publication-loss.ts +18 -1
  112. package/packages/core/src/processes/repo-view.ts +35 -0
  113. package/packages/core/src/store/contract.ts +32 -1
  114. package/packages/core/src/store/local/store.ts +1 -1
  115. package/packages/core/src/store/remote/client.ts +1 -1
  116. package/packages/core/src/store/remote/compatibility.ts +90 -0
  117. package/packages/core/src/store/remote/credentials.ts +28 -0
  118. package/packages/core/src/store/remote/index.ts +14 -1
  119. package/packages/core/src/store/remote/protocol.ts +25 -0
  120. package/packages/core/src/store/remote/token.ts +74 -13
  121. package/packages/core/src/store/ticket-asset-snapshots.ts +192 -0
  122. package/packages/core/src/store/ticket-assets.ts +86 -8
  123. package/packages/core/src/store/types.ts +1 -1
  124. package/packages/core/src/testing/index.ts +7 -0
  125. package/skills/guide/SKILL.md +232 -34
  126. package/skills/guide/references/operator-api.md +142 -13
  127. package/skills/guide/references/plugin-authoring.md +10 -2
  128. package/skills/guide/references/remote-store-protocol.md +199 -144
  129. package/skills/guide/references/remote-ticket-protocol.md +253 -18
  130. package/skills/guide/references/setup.md +199 -16
  131. package/skills/guide/references/ticket-dependencies.md +1 -1
  132. package/skills/guide/references/ticket-migration.md +64 -0
  133. package/skills/operate/SKILL.md +126 -36
  134. package/skills/tickets/SKILL.md +71 -0
  135. package/templates/hosted-service/package.json +13 -0
  136. package/templates/hosted-service/vercel.json +7 -0
@@ -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
- Mint a token offline; the signed user is used as the human actor on every write:
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
- AB_STORE_SECRET='…' bun packages/hosted-store-service/src/bin.ts mint operator \
13
- --user 'Ada Lovelace' --ttl-seconds 3600
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
- Admin, build, repository, and deployment (`{ "operator": true, … }`) tokens
17
- have no attributed operator authority. Human-operator tokens have no raw
18
- `/builds`, `/repos`, `/sessions`, or `/tickets` authority. Encode repository,
19
- build, session, and artifact kind as separate URL path segments.
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
 
@@ -56,6 +87,7 @@ turn runner (a later ticket) is the only producer of turn facts.
56
87
  | `GET …/harvest/status` | Harvest gate, runs, steps, recovery, and attention projection. |
57
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. |
58
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). |
59
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. |
60
92
 
61
93
  For artifact reads, an absent `rev` selects the latest revision. A supplied value
@@ -66,7 +98,11 @@ supplied forms return `400 validation`.
66
98
  Dashboard reads use the latest durable, run-correlated `effectiveConfig`
67
99
  repository artifact. Missing, corrupt, or invalid configuration returns a typed
68
100
  `409 effective-config-unavailable`; the service never guesses from a checkout.
69
- Clients poll these reads; streaming is not provided. `triageState`, `readyState`,
101
+ Clients poll these reads — the operator HTTP API exposes no push or long-poll
102
+ event transport. Streaming is provided as a CLI read surface: `ab watch`
103
+ streams build and repository events by polling the same event logs client-side
104
+ (the store protocol's `GET /builds/{slug}/events` and `GET /repos/{repo}/events`
105
+ reads), not as a transport on this API. `triageState`, `readyState`,
70
106
  and every entry in `states` are backend state names and must be sent back verbatim
71
107
  when used with the move control.
72
108
 
@@ -84,6 +120,7 @@ JSON bodies are strict: unknown fields are rejected.
84
120
  | `POST …/settings/auto-merge-default/toggle` | Empty body. |
85
121
  | `POST …/bulk-control` | `{"action":"pause"\|"resume"}`. The hold fact, intake fact, then eligible build events are written in that order. |
86
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. |
87
124
  | `POST …/tickets` | `{"title":"…","body":"…","labels"?:[],"state"?:"…","blockedBy"?:[]}`; omitted state preserves the backend default. |
88
125
  | `PATCH …/tickets/{id}` | Any nonempty subset of `title`, `body`, and complete-replacement `labels`. Body bytes are not normalized. |
89
126
  | `POST …/tickets/{id}/move` | `{"state":"backend state name"}`. |
@@ -105,12 +142,25 @@ The retry object is deliberately bare: adding `text` is a `400 validation`
105
142
  rather than silently changing the resolution to guidance. A revision object may
106
143
  also carry `ceiling` only to receive the shared `incompatible-answer-options`
107
144
  refusal; a ceiling and spec revision cannot be performed together.
108
-
109
145
  The hosted service has no ticket-provider credentials. For ticket-origin
110
146
  revision, a trusted caller fetches the current ticket body and supplies it; the
111
147
  build must still have a recorded ticket. Revision conformance, lazy retry,
112
148
  artifact metadata, event ordering, and refusal rules are the same as the CLI.
113
149
 
150
+ ## The registry's protocol face: `POST …/tools/{tool}`
151
+
152
+ One generic route executes any entry of the agent tool registry (the same
153
+ closed table `ab mcp` serves over stdio and the hosted `/mcp` endpoint serves
154
+ over Streamable HTTP): the body is the tool's validated input — `repo`
155
+ included and required to equal the URL's repository — and the response is the
156
+ registry result verbatim. The verified operator token supplies the acting
157
+ identity and, when minted with one, the `via` attribution marker; the body
158
+ never does. Failures keep the shared `{kind,error,code?,progress?}` shape:
159
+ validation is `400`, auth `403`, not-found `404`, conflict and refusal `409`,
160
+ internal `500`. The route adds no authority of its own — it is the registry
161
+ behind the token check — so a tool available here is exactly the tool table,
162
+ and the table's contract suite is the single gate.
163
+
114
164
  ### Success results
115
165
 
116
166
  Build control returns one of:
@@ -157,8 +207,87 @@ headers with a server-minted token that expires after 30 seconds and carries
157
207
  the normalized signed-in email. Consequently every durable control event has
158
208
  the browser user's human actor while no token or signing secret reaches client
159
209
  code. Responses are private/no-store; a 401 sends the application back to sign
160
- in. Browser clients poll the visible dashboard every two seconds; live transcript
161
- streaming is not provided. Delegated bearer tokens remain server-side.
210
+ in. Browser clients poll the visible dashboard every two seconds; the browser
211
+ surface offers no streaming of its own — live transcript streaming remains
212
+ absent here, and the streaming read surface is the CLI's `ab watch`, which
213
+ polls the store's event reads client-side. Delegated bearer tokens remain
214
+ server-side.
215
+
216
+ The API does not expose phase-session commands, runner startup, a push or
217
+ long-poll streaming transport, or a generic event-append operation; event
218
+ streaming is composed client-side by `ab watch`, which polls the store's
219
+ event reads.
220
+
221
+
222
+ Dispatcher liveness is also visible through `ab repository status --json`:
223
+ `dispatcher.holder` identifies the unexpired repository lease owner, independently
224
+ of `latestRun`. Heartbeat age measures attributable renewals; tick age measures
225
+ durable progress. Missing historical evidence is null. The liveness query uses
226
+ bounded repository facts first, with a full-history fallback when a later
227
+ invocation hides the holder start or the latest stop. Other state reads retain
228
+ their bounded semantics.
229
+
230
+ Repository-following `ab watch` additionally emits a read-only `dispatcher.lost`
231
+ observation when an observed lease expires without a matching stop. JSON carries
232
+ `observation` instead of `event`, with run, observedAt, leaseExpiresAt and available
233
+ identity, plus the usual repo/build/state/cursor fields. It invents no durable
234
+ sequence or actor. Retain the cursor to avoid repeat reports across invocations.
235
+ No lease alone is not evidence of death. SIGINT, SIGHUP and SIGTERM drain dispatch,
236
+ record the first signal in the stop fact, and release its lease before exit.
237
+
238
+ ### CLI attention monitoring
239
+
240
+ The default watch reports actionable conditions only:
241
+
242
+ - Build `escalation.raised`, or `build.merge-decision`: a finalized open PR
243
+ with auto-merge off or a current actionable merge-gate deferral. Armed consent
244
+ awaiting application is silent. One merge decision is reported per build/PR.
245
+ - Repository `harvest.escalated`, `harvest.recovery-exhausted`,
246
+ `dispatcher.config-rejected`, `dispatcher.config-reloaded` with nonempty
247
+ `restartRequired`, abnormal `dispatcher.run-stopped`, and `dispatcher.lost`.
248
+ - `dispatcher.ticket-source-persistent`: degradation past its advertised
249
+ reset time, once a tick started at or after reset has completed or failed
250
+ with the episode still open; crossing reset alone is silent. Without a reset,
251
+ the deadline is 15 minutes after onset. Repeated evidence never postpones
252
+ the deadline; recovery ends the episode.
253
+ - `dispatcher.tick-failure-persistent`: continuously failing completed ticks
254
+ for five minutes in one run. A successful tick, new run, or matching stop
255
+ ends the episode. Source grace and cooldown-driven failures do not start
256
+ this clock; after grace, the first qualifying failure starts a new five-minute
257
+ interval. Each persistence episode is reported once.
258
+
259
+ Repository conditions are included with no slugs or with `--repository`.
260
+ Routine outcomes and self-healing failures are silent. Repeatable
261
+ `--event <glob>` replaces the default and selects exactly matching catalog
262
+ events (plus the existing `dispatcher.lost` observation); use explicit globs
263
+ to opt into failures, finalize, merge, or completion events.
264
+
265
+ Derived records use `observation` instead of `event`, without inventing a
266
+ durable sequence or actor. Merge observations carry `type`, `pr`, `reason`,
267
+ and `observedAt`, plus the build slug and normal reduced state. Persistence
268
+ observations carry source/cause/message/resetAt when advertised (or
269
+ run/firstFailure/error), `episodeSeq`, and `observedAt`; repository records
270
+ have `repo` and null build/state. Source observations also report
271
+ `dependencyLimited`.
272
+
273
+ Every record carries a cursor, including timer-only records. Resuming suppresses
274
+ delivered merge decisions and persistence episodes even when stream positions
275
+ did not advance. Old v1 cursors remain valid: historical eligible merge
276
+ decisions are treated as consumed; active overdue repository episodes may
277
+ report because old watches had no persistence notification. Fresh attachment
278
+ silently baselines historical direct events and merge decisions, but retains
279
+ active repository timers. Reconcile existing conditions through status after
280
+ arming the watch. Named watches still end when every named build is terminal;
281
+ learn their outcomes from status reconciliation at exit.
282
+
283
+ `ab wait --for attention` is build-only and uses the same build conditions:
284
+ an open escalation or a merge decision. Existing conditions return immediately,
285
+ even with `--since`; live and backlog matches ignore routine outcomes and
286
+ self-healing failures. A merge match uses the watch observation with
287
+ `condition: "attention"`. Explicit `--event` globs remain event-only.
288
+ Watch and wait preserve each other's cursor notification metadata.
162
289
 
163
- The API does not expose phase-session commands, runner startup, live streaming,
164
- or a generic event-append operation.
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.
@@ -40,7 +40,7 @@ should declare an API range containing `^1.5.0`.
40
40
 
41
41
  Plugin API 1.7 extends the workspace-provider factory context with the
42
42
  host-derived seams a store-requiring remote provider needs. Workspace-provider
43
- factories additionally receive `storeRef` and `storeToken` (guaranteed present
43
+ factories additionally receive `storeRef` and `delegateCredential` (guaranteed present
44
44
  when the registration declares `capabilities.storeRequirements`),
45
45
  `runtimeReferences` (the host's effective runtime routes; absent at call sites
46
46
  that reference no runtimes), and the checkout-less `origin` and
@@ -125,7 +125,7 @@ Every module must default-export one strict `AutobuildPluginManifest`:
125
125
  `[tickets]` fields, workspace providers receive `[workspace.config]`, and
126
126
  runtime and forge factories currently receive an empty `config` object.
127
127
  Workspace providers additionally receive the host-derived seams (API 1.7):
128
- `storeRef` and `storeToken` — guaranteed strings when the registration
128
+ `storeRef` and `delegateCredential` — guaranteed URL and exchange callback when the registration
129
129
  declares `capabilities.storeRequirements` — plus `runtimeReferences`,
130
130
  `origin`, and `remoteBranchHead`. Each seam is optional and absent when the
131
131
  host call site supplies no such value; absent `origin`/`remoteBranchHead`
@@ -369,3 +369,11 @@ policy says otherwise.
369
369
  Official npm references: [`package.json` fields](https://docs.npmjs.com/cli/v11/configuring-npm/package-json),
370
370
  [`npm pack`](https://docs.npmjs.com/cli/v11/commands/npm-pack), and
371
371
  [`npm publish`](https://docs.npmjs.com/cli/v11/commands/npm-publish).
372
+
373
+ Remote workspace factories must use `delegateCredential(storeRef, undefined,
374
+ target)` to obtain per-resource grants before provisioning or launching guests.
375
+ The callback keeps parent authority in host composition. `storeToken` is retired
376
+ and is never supplied; factory environments also exclude `AB_TOKEN`. Launch
377
+ credentials travel through the separate transient execution-auth argument, never
378
+ through serialized execution identity. Existing plugins that forwarded
379
+ `storeToken` must migrate to this callback and fail closed if it is unavailable.