@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
|
@@ -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
|
+
}
|