@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.
Files changed (151) hide show
  1. package/README.md +1 -1
  2. package/SPEC.md +138 -16
  3. package/bin/ab-dispatch-kernel.ts +4 -6
  4. package/docs/architecture.md +155 -73
  5. package/docs/configuration.md +41 -9
  6. package/docs/hosted-service.md +31 -5
  7. package/docs/operator-api.md +8 -1
  8. package/docs/remote-store-protocol.md +94 -2
  9. package/docs/remote-ticket-protocol.md +151 -9
  10. package/docs/setup.md +33 -7
  11. package/docs/ticket-migration.md +64 -0
  12. package/package.json +4 -3
  13. package/packages/core/src/cli/attention.ts +18 -164
  14. package/packages/core/src/cli/build-control.ts +23 -16
  15. package/packages/core/src/cli/bulk-control.ts +3 -2
  16. package/packages/core/src/cli/connect.ts +141 -38
  17. package/packages/core/src/cli/context.ts +23 -79
  18. package/packages/core/src/cli/dashboard/model.ts +36 -22
  19. package/packages/core/src/cli/dashboard/poll.ts +1 -1
  20. package/packages/core/src/cli/dispatch-frontend.ts +24 -67
  21. package/packages/core/src/cli/dispatch-process.ts +14 -7
  22. package/packages/core/src/cli/dispatch-repository-feed.ts +196 -0
  23. package/packages/core/src/cli/dispatch.ts +304 -82
  24. package/packages/core/src/cli/dispatcher-liveness.ts +26 -19
  25. package/packages/core/src/cli/harvest.ts +84 -42
  26. package/packages/core/src/cli/help.ts +14 -8
  27. package/packages/core/src/cli/historical-build-state.ts +27 -0
  28. package/packages/core/src/cli/installation.ts +67 -13
  29. package/packages/core/src/cli/main.ts +23 -5
  30. package/packages/core/src/cli/mcp.ts +2 -1
  31. package/packages/core/src/cli/pr-attachments.ts +10 -13
  32. package/packages/core/src/cli/pr-summary-publication.ts +27 -60
  33. package/packages/core/src/cli/pr-summary.ts +43 -13
  34. package/packages/core/src/cli/publication-settlement.ts +10 -20
  35. package/packages/core/src/cli/repository-status.ts +38 -2
  36. package/packages/core/src/cli/self-update.ts +5 -1
  37. package/packages/core/src/cli/status.ts +62 -32
  38. package/packages/core/src/cli/terminals.ts +25 -142
  39. package/packages/core/src/cli/ticket-assets.ts +7 -2
  40. package/packages/core/src/cli/ticket-editor.ts +82 -0
  41. package/packages/core/src/cli/ticket.ts +166 -36
  42. package/packages/core/src/cli/wait.ts +91 -84
  43. package/packages/core/src/cli/watch.ts +60 -97
  44. package/packages/core/src/config/pipeline-source.ts +4 -3
  45. package/packages/core/src/config/schema.ts +35 -3
  46. package/packages/core/src/connection.ts +3 -3
  47. package/packages/core/src/events/catalog.ts +3 -2
  48. package/packages/core/src/events/payloads.ts +6 -0
  49. package/packages/core/src/events/repository.ts +7 -3
  50. package/packages/core/src/integration/harness.ts +38 -4
  51. package/packages/core/src/kernel/__snapshots__/reducer-registry.test.ts.snap +2444 -9
  52. package/packages/core/src/kernel/auto-merge.ts +19 -3
  53. package/packages/core/src/kernel/dispatcher-liveness.ts +10 -4
  54. package/packages/core/src/kernel/generators/build-log.ts +1 -1
  55. package/packages/core/src/kernel/generators/repository-journals.ts +14 -3
  56. package/packages/core/src/kernel/harvest.ts +25 -23
  57. package/packages/core/src/kernel/incremental-fixtures.ts +13 -2
  58. package/packages/core/src/kernel/log-index-value.ts +38 -0
  59. package/packages/core/src/kernel/read-facts.ts +637 -0
  60. package/packages/core/src/kernel/reducer-registry.ts +139 -3
  61. package/packages/core/src/kernel/repository-attention.ts +179 -0
  62. package/packages/core/src/kernel/service-facts.ts +135 -0
  63. package/packages/core/src/kernel/terminal-guard.ts +133 -0
  64. package/packages/core/src/ontology.ts +1 -0
  65. package/packages/core/src/operator/annotations.ts +12 -0
  66. package/packages/core/src/operator/control.ts +5 -6
  67. package/packages/core/src/operator/index.ts +7 -0
  68. package/packages/core/src/operator/protocol.ts +19 -2
  69. package/packages/core/src/operator/query.ts +37 -20
  70. package/packages/core/src/operator/read-view.ts +4 -13
  71. package/packages/core/src/operator/registry.ts +61 -8
  72. package/packages/core/src/operator/requests.ts +2 -14
  73. package/packages/core/src/operator/sandbox.ts +10 -9
  74. package/packages/core/src/operator/ticket-source-backend.ts +17 -21
  75. package/packages/core/src/operator/tickets.ts +132 -22
  76. package/packages/core/src/plugin-sdk/index.ts +19 -0
  77. package/packages/core/src/plugins/runtimes.ts +5 -1
  78. package/packages/core/src/ports/runner/session-env.ts +2 -0
  79. package/packages/core/src/ports/tickets/contract.ts +66 -1
  80. package/packages/core/src/ports/tickets/create.ts +48 -12
  81. package/packages/core/src/ports/tickets/fake.ts +30 -1
  82. package/packages/core/src/ports/tickets/file-assets.ts +159 -0
  83. package/packages/core/src/ports/tickets/file-codec.ts +90 -0
  84. package/packages/core/src/ports/tickets/file.ts +114 -120
  85. package/packages/core/src/ports/tickets/grants.ts +47 -0
  86. package/packages/core/src/ports/tickets/hosted-index.ts +17 -0
  87. package/packages/core/src/ports/tickets/identity.ts +20 -0
  88. package/packages/core/src/ports/tickets/lifecycle.ts +18 -0
  89. package/packages/core/src/ports/tickets/linear.ts +74 -9
  90. package/packages/core/src/ports/tickets/migration.ts +336 -0
  91. package/packages/core/src/ports/tickets/operations.ts +38 -7
  92. package/packages/core/src/ports/tickets/portable-assets.ts +54 -0
  93. package/packages/core/src/ports/tickets/remote-protocol.ts +95 -0
  94. package/packages/core/src/ports/tickets/remote.ts +60 -3
  95. package/packages/core/src/ports/tickets/requested-id.ts +46 -0
  96. package/packages/core/src/ports/tickets/revision.ts +62 -0
  97. package/packages/core/src/ports/tickets/states.ts +61 -0
  98. package/packages/core/src/ports/types.ts +40 -3
  99. package/packages/core/src/ports/workspace/build-execution.ts +1 -0
  100. package/packages/core/src/ports/workspace/create.ts +5 -1
  101. package/packages/core/src/ports/workspace/operator-sandbox.ts +2 -0
  102. package/packages/core/src/ports/workspace/vercel-sandbox.ts +8 -4
  103. package/packages/core/src/processes/build-child.ts +6 -6
  104. package/packages/core/src/processes/build-runner.ts +62 -70
  105. package/packages/core/src/processes/dispatch-failure-budget.ts +5 -4
  106. package/packages/core/src/processes/dispatcher.ts +223 -205
  107. package/packages/core/src/processes/execution-no-progress.ts +176 -0
  108. package/packages/core/src/processes/harvest-child.ts +30 -4
  109. package/packages/core/src/processes/harvest-execution-state.ts +15 -9
  110. package/packages/core/src/processes/harvest-runner.ts +58 -74
  111. package/packages/core/src/processes/harvest.ts +72 -29
  112. package/packages/core/src/processes/infrastructure-failure-budget.ts +13 -15
  113. package/packages/core/src/processes/orchestrator-tick.ts +2 -2
  114. package/packages/core/src/processes/phase-failure-budget.ts +1 -0
  115. package/packages/core/src/processes/publication-loss.ts +35 -21
  116. package/packages/core/src/processes/repo-view.ts +229 -1099
  117. package/packages/core/src/processes/tick-publication.ts +110 -0
  118. package/packages/core/src/store/adapter.ts +23 -0
  119. package/packages/core/src/store/build-scope.ts +17 -0
  120. package/packages/core/src/store/contract.ts +283 -1
  121. package/packages/core/src/store/local/schema.ts +1 -0
  122. package/packages/core/src/store/local/store.ts +180 -55
  123. package/packages/core/src/store/memory.ts +119 -29
  124. package/packages/core/src/store/phase-session.ts +17 -0
  125. package/packages/core/src/store/reduced-reads.ts +239 -0
  126. package/packages/core/src/store/reducer-value-shapes.json +14056 -0
  127. package/packages/core/src/store/reducer-value-validation.ts +96 -0
  128. package/packages/core/src/store/reducer-values.ts +145 -0
  129. package/packages/core/src/store/remote/client.ts +41 -0
  130. package/packages/core/src/store/remote/compatibility.ts +2 -0
  131. package/packages/core/src/store/remote/index.ts +19 -0
  132. package/packages/core/src/store/remote/protocol.ts +16 -0
  133. package/packages/core/src/store/remote/version.ts +3 -1
  134. package/packages/core/src/store/repo-state-events.ts +1 -1
  135. package/packages/core/src/store/repo-tick.ts +72 -0
  136. package/packages/core/src/store/session-handle.ts +19 -0
  137. package/packages/core/src/store/snapshots.ts +10 -0
  138. package/packages/core/src/store/ticket-asset-snapshots.ts +192 -0
  139. package/packages/core/src/store/ticket-assets.ts +86 -8
  140. package/packages/core/src/store/types.ts +40 -3
  141. package/packages/core/src/testing/dispatch-read-budget.ts +215 -0
  142. package/packages/core/src/testing/index.ts +8 -0
  143. package/packages/core/src/testing/reduced-read-budget.ts +462 -0
  144. package/skills/guide/SKILL.md +97 -12
  145. package/skills/guide/references/operator-api.md +8 -1
  146. package/skills/guide/references/remote-store-protocol.md +94 -2
  147. package/skills/guide/references/remote-ticket-protocol.md +151 -9
  148. package/skills/guide/references/setup.md +33 -7
  149. package/skills/guide/references/ticket-migration.md +64 -0
  150. package/skills/tickets/SKILL.md +71 -0
  151. package/templates/hosted-service/package.json +2 -2
@@ -0,0 +1,239 @@
1
+ import { decodeLog } from '../kernel/log-index-value'
2
+ /** The consumer boundary for current reductions. Raw event reads are for event output. */
3
+ import type { BuildStore } from './types'
4
+ import { validateReducerValue } from './reducer-value-validation'
5
+ import type {
6
+ buildReadFactsReducer,
7
+ buildStreamSeedReducer,
8
+ repositoryReadFactsReducer,
9
+ } from '../kernel/read-facts'
10
+ import { publicationStateReducer } from '../processes/publication-state'
11
+ import type { SnapshotScope } from './snapshots'
12
+
13
+ type Reader = Pick<BuildStore, 'getReducerValue'>
14
+ export async function readBuildStreamSeed(store: Reader, slug: string) {
15
+ return readValue<ReturnType<typeof buildStreamSeedReducer.finish>>(
16
+ store,
17
+ { kind: 'build', slug },
18
+ 'buildStreamSeed',
19
+ )
20
+ }
21
+ export async function readBuildFacts(store: Reader, slug: string) {
22
+ const result = await readValue<ReturnType<typeof buildReadFactsReducer.finish>>(
23
+ store,
24
+ { kind: 'build', slug },
25
+ 'buildReadFacts',
26
+ )
27
+ const value = result.value
28
+ return {
29
+ cursor: result.cursor,
30
+ value: {
31
+ ...value,
32
+ log: decodeLog(value.log),
33
+ publication: publicationStateReducer.finish(value.publication),
34
+ },
35
+ }
36
+ }
37
+ async function readValue<T>(
38
+ store: Reader,
39
+ scope: SnapshotScope,
40
+ reducer: string,
41
+ ): Promise<{ cursor: number; value: T }> {
42
+ const result = await store.getReducerValue(scope, { reducer })
43
+ if (!validateReducerValue(reducer, result.value))
44
+ throw new Error(`invalid persisted value for ${reducer}`)
45
+ // The generated validator checks the complete finished contract before decoding.
46
+ return { cursor: result.cursor, value: result.value as T }
47
+ }
48
+
49
+ export type RepositoryReadFacts = ReturnType<typeof repositoryReadFactsReducer.finish>
50
+ export async function readRepositoryFacts(
51
+ store: Reader & Pick<BuildStore, 'getRepo'>,
52
+ repo: string,
53
+ ) {
54
+ let absent = false
55
+ try {
56
+ absent = (await store.getRepo(repo)) === null
57
+ } catch {
58
+ // Lease/record metadata can be unavailable while durable values remain readable.
59
+ return readValue<RepositoryReadFacts>(store, { kind: 'repo', repo }, 'repositoryReadFacts')
60
+ }
61
+ if (!absent)
62
+ return readValue<RepositoryReadFacts>(store, { kind: 'repo', repo }, 'repositoryReadFacts')
63
+ const { repositoryReadFactsReducer } = await import('../kernel/read-facts')
64
+ return {
65
+ cursor: 0,
66
+ value: repositoryReadFactsReducer.finish(repositoryReadFactsReducer.initial()),
67
+ }
68
+ }
69
+
70
+ type Selectors = {
71
+ setupStreak: ReturnType<typeof import('../processes/build-runner').setupStreakReducer.finish>
72
+ baseBranch: ReturnType<
73
+ typeof import('../processes/dispatcher-selectors').baseBranchReducer.finish
74
+ >
75
+ publishedBranchHead: ReturnType<
76
+ typeof import('../processes/build-runner').publishedBranchHeadReducer.finish
77
+ >
78
+ verifyDiffBase: ReturnType<
79
+ typeof import('../processes/build-runner').verifyDiffBaseReducer.finish
80
+ >
81
+ recordedBaseSha: ReturnType<
82
+ typeof import('../config/pipeline-source').recordedBaseShaReducer.finish
83
+ >
84
+ }
85
+ export async function readBuildSelector<N extends keyof Selectors>(
86
+ store: Reader,
87
+ slug: string,
88
+ name: N,
89
+ ): Promise<Selectors[N]> {
90
+ if (name === 'setupStreak')
91
+ return (await readValue<Selectors[N]>(store, { kind: 'build', slug }, name)).value
92
+ return (await readValue<{ value?: Selectors[N] }>(store, { kind: 'build', slug }, `${name}Value`))
93
+ .value.value as Selectors[N]
94
+ }
95
+
96
+ export async function readPhaseFailures(
97
+ store: Reader,
98
+ slug: string,
99
+ phase: import('../ontology').Phase,
100
+ round: number,
101
+ ) {
102
+ const result = await store.getReducerValue(
103
+ { kind: 'build', slug },
104
+ { reducer: 'phaseFailures', args: { phase, round } },
105
+ )
106
+ if (!validateReducerValue('phaseFailures', result.value))
107
+ throw new Error('invalid phaseFailures value')
108
+ return result.value as unknown as ReturnType<
109
+ ReturnType<typeof import('../processes/build-runner').phaseFailuresReducer>['finish']
110
+ >
111
+ }
112
+
113
+ export async function readDispatchBudget(
114
+ store: Reader,
115
+ slug: string,
116
+ infrastructureOwnsWorkspace: boolean,
117
+ ) {
118
+ const result = await store.getReducerValue(
119
+ { kind: 'build', slug },
120
+ { reducer: 'dispatchFailureBudget', args: { infrastructureOwnsWorkspace } },
121
+ )
122
+ if (!validateReducerValue('dispatchFailureBudget', result.value))
123
+ throw new Error('invalid dispatchFailureBudget value')
124
+ return {
125
+ cursor: result.cursor,
126
+ value: result.value as unknown as ReturnType<
127
+ ReturnType<
128
+ typeof import('../processes/dispatch-failure-budget').dispatchFailureBudgetReducer
129
+ >['finish']
130
+ >,
131
+ }
132
+ }
133
+
134
+ export async function readDeferralLedger(store: Reader, slug: string) {
135
+ return readValue<import('../kernel/auto-merge').DeferralLedger>(
136
+ store,
137
+ { kind: 'build', slug },
138
+ 'currentDeferralObservation',
139
+ )
140
+ }
141
+
142
+ export async function readRepositoryAttention(store: Reader, repo: string) {
143
+ return readValue<import('../kernel/repository-attention').RepositoryAttentionState>(
144
+ store,
145
+ { kind: 'repo', repo },
146
+ 'repositoryAttention',
147
+ )
148
+ }
149
+
150
+ export type CurrentBuildFacts = Awaited<ReturnType<typeof readBuildFacts>>['value']
151
+
152
+ export async function readTerminalGuard(
153
+ store: Reader,
154
+ slug: string,
155
+ phase: import('../ontology').Phase,
156
+ round: number,
157
+ session: string,
158
+ ) {
159
+ const result = await store.getReducerValue(
160
+ { kind: 'build', slug },
161
+ { reducer: 'terminalGuard', args: { phase, round, session } },
162
+ )
163
+ if (!validateReducerValue('terminalGuard', result.value))
164
+ throw new Error('invalid terminalGuard value')
165
+ return result.value as { diagnostic?: string }
166
+ }
167
+
168
+ export async function readOpenTick(store: Reader, repo: string, run: string, historical = true) {
169
+ return (
170
+ (await readDispatcherRunFacts(store, repo, run, historical)).value.boundary ===
171
+ 'dispatcher.tick-started'
172
+ )
173
+ }
174
+ export async function readPinnedAssets(store: Reader, slug: string) {
175
+ return readValue<ReturnType<typeof import('./ticket-assets').pinnedAssetsReducer.finish>>(
176
+ store,
177
+ { kind: 'build', slug },
178
+ 'pinnedAssets',
179
+ )
180
+ }
181
+
182
+ /** Digests are reductions too. Read persisted per-build digests so repeated
183
+ * discovery never transfers all historical digest-relevant event rows. */
184
+ export async function readPersistedBuildDigests(
185
+ store: Reader & Pick<BuildStore, 'listBuilds'>,
186
+ repo: string,
187
+ records?: import('./types').BuildRecord[],
188
+ ) {
189
+ const entries = await Promise.all(
190
+ (records ?? (await store.listBuilds()))
191
+ .filter((record) => record.repo === repo)
192
+ .map(async (record) => {
193
+ const result = await readValue<
194
+ ReturnType<typeof import('./digest').buildDigestReducer.finish>
195
+ >(store, { kind: 'build', slug: record.slug }, 'buildDigest')
196
+ return [record.slug, { slug: record.slug, ...result.value }] as const
197
+ }),
198
+ )
199
+ return new Map(entries)
200
+ }
201
+
202
+ /** Keep the batch boundary for hosted callers; adapter implementations use
203
+ * readPersistedBuildDigests so each digest still comes from a persisted value. */
204
+ export function readBuildDigests(store: Pick<BuildStore, 'getRepoBuildDigests'>, repo: string) {
205
+ return store.getRepoBuildDigests(repo)
206
+ }
207
+
208
+ /** Current/recent runs use the shared cache. Set historical=false only when
209
+ * checking this process's fresh invocation, whose missing start means no prior
210
+ * lifecycle facts; arbitrary older holder IDs must retain historical recovery. */
211
+ export async function readDispatcherRunFacts(
212
+ store: Reader,
213
+ repo: string,
214
+ run: string,
215
+ historical = true,
216
+ ) {
217
+ const repository = await readValue<RepositoryReadFacts>(
218
+ store,
219
+ { kind: 'repo', repo },
220
+ 'repositoryReadFacts',
221
+ )
222
+ const recent = repository.value.recentRuns.find(([id]) => id === run)
223
+ if ((recent && recent[1].start !== undefined) || !historical)
224
+ return {
225
+ cursor: repository.cursor,
226
+ value: recent?.[1] ?? ({} as import('../kernel/read-facts').DispatcherRunFacts),
227
+ }
228
+
229
+ const result = await store.getReducerValue(
230
+ { kind: 'repo', repo },
231
+ { reducer: 'dispatcherRunFacts', args: { run } },
232
+ )
233
+ if (!validateReducerValue('dispatcherRunFacts', result.value))
234
+ throw new Error('invalid dispatcherRunFacts value')
235
+ return {
236
+ cursor: result.cursor,
237
+ value: result.value as import('../kernel/read-facts').DispatcherRunFacts,
238
+ }
239
+ }