@defrex/autobuild 0.8.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/LICENSE +201 -0
- package/README.md +192 -0
- package/SPEC.md +2269 -0
- package/bin/ab-build-runner.ts +47 -0
- package/bin/ab-dev.ts +27 -0
- package/bin/ab-dispatch-kernel.ts +92 -0
- package/bin/ab-harvest-runner.ts +29 -0
- package/bin/ab-init-probe.ts +19 -0
- package/bin/ab-process-group-reaper.ts +32 -0
- package/bin/ab.ts +6 -0
- package/bin/agent/ab +3 -0
- package/docs/answering-blocked-builds.md +89 -0
- package/docs/architecture.md +726 -0
- package/docs/assets/headline-wide.png +0 -0
- package/docs/configuration.md +1623 -0
- package/docs/hosted-dispatcher-cutover-validation.md +178 -0
- package/docs/hosted-dispatcher.md +204 -0
- package/docs/mcp.md +119 -0
- package/docs/operator-api.md +186 -0
- package/docs/remote-store-protocol.md +972 -0
- package/docs/remote-ticket-protocol.md +79 -0
- package/docs/setup.md +289 -0
- package/docs/spec-standard.md +63 -0
- package/docs/ticket-dependencies.md +59 -0
- package/docs/vercel-sandbox-rollout-probe.md +7 -0
- package/package.json +135 -0
- package/packages/core/src/cli/args.ts +74 -0
- package/packages/core/src/cli/artifact.ts +182 -0
- package/packages/core/src/cli/binary.ts +198 -0
- package/packages/core/src/cli/build-control.ts +789 -0
- package/packages/core/src/cli/build-progress.ts +55 -0
- package/packages/core/src/cli/bulk-control.ts +385 -0
- package/packages/core/src/cli/context.ts +470 -0
- package/packages/core/src/cli/dashboard/actions.ts +59 -0
- package/packages/core/src/cli/dashboard/cells.ts +92 -0
- package/packages/core/src/cli/dashboard/composer.ts +230 -0
- package/packages/core/src/cli/dashboard/detail.ts +100 -0
- package/packages/core/src/cli/dashboard/frame-image.ts +373 -0
- package/packages/core/src/cli/dashboard/live.ts +152 -0
- package/packages/core/src/cli/dashboard/model.ts +1173 -0
- package/packages/core/src/cli/dashboard/poll.ts +196 -0
- package/packages/core/src/cli/dashboard/render.ts +1568 -0
- package/packages/core/src/cli/dashboard/selection.ts +66 -0
- package/packages/core/src/cli/dashboard/session-feed.ts +244 -0
- package/packages/core/src/cli/dashboard/session-view.ts +506 -0
- package/packages/core/src/cli/dashboard/transcript.ts +108 -0
- package/packages/core/src/cli/dev.ts +46 -0
- package/packages/core/src/cli/dispatch-frontend.ts +1045 -0
- package/packages/core/src/cli/dispatch-process.ts +259 -0
- package/packages/core/src/cli/dispatch.ts +3692 -0
- package/packages/core/src/cli/dotenv.ts +48 -0
- package/packages/core/src/cli/env.ts +206 -0
- package/packages/core/src/cli/harvest.ts +698 -0
- package/packages/core/src/cli/help.ts +713 -0
- package/packages/core/src/cli/init-agent.ts +106 -0
- package/packages/core/src/cli/init-validation.ts +583 -0
- package/packages/core/src/cli/init.ts +756 -0
- package/packages/core/src/cli/installation.ts +333 -0
- package/packages/core/src/cli/keyboard.ts +261 -0
- package/packages/core/src/cli/main.ts +1399 -0
- package/packages/core/src/cli/mcp.ts +279 -0
- package/packages/core/src/cli/models.ts +65 -0
- package/packages/core/src/cli/observe.ts +55 -0
- package/packages/core/src/cli/plugin.ts +227 -0
- package/packages/core/src/cli/pr-attachments.ts +138 -0
- package/packages/core/src/cli/pr-summary.ts +124 -0
- package/packages/core/src/cli/publication-settlement.ts +188 -0
- package/packages/core/src/cli/repo-state.ts +213 -0
- package/packages/core/src/cli/repository-status.ts +80 -0
- package/packages/core/src/cli/self-update.ts +443 -0
- package/packages/core/src/cli/status.ts +895 -0
- package/packages/core/src/cli/store-opening.contract.ts +289 -0
- package/packages/core/src/cli/store-opening.ts +167 -0
- package/packages/core/src/cli/store-ref.ts +33 -0
- package/packages/core/src/cli/terminal-restore.ts +174 -0
- package/packages/core/src/cli/terminal.ts +361 -0
- package/packages/core/src/cli/terminals.ts +995 -0
- package/packages/core/src/cli/testkit.ts +194 -0
- package/packages/core/src/cli/ticket.ts +484 -0
- package/packages/core/src/cli/upgrade-agent.ts +180 -0
- package/packages/core/src/cli/upgrade-commit.ts +468 -0
- package/packages/core/src/cli/upgrade-notice.ts +91 -0
- package/packages/core/src/cli/upgrade-progress.ts +110 -0
- package/packages/core/src/cli/upgrade.ts +888 -0
- package/packages/core/src/cli/wait.ts +587 -0
- package/packages/core/src/cli/watch.ts +932 -0
- package/packages/core/src/config/live.ts +255 -0
- package/packages/core/src/config/load.ts +98 -0
- package/packages/core/src/config/roles.ts +438 -0
- package/packages/core/src/config/schema.ts +774 -0
- package/packages/core/src/distribution.ts +24 -0
- package/packages/core/src/events/catalog.ts +201 -0
- package/packages/core/src/events/envelope.ts +59 -0
- package/packages/core/src/events/payloads.ts +618 -0
- package/packages/core/src/events/repository.ts +559 -0
- package/packages/core/src/events/sessions.ts +180 -0
- package/packages/core/src/harvest/schema.ts +147 -0
- package/packages/core/src/ids.ts +45 -0
- package/packages/core/src/integration/harness.ts +681 -0
- package/packages/core/src/kernel/auto-merge.ts +259 -0
- package/packages/core/src/kernel/converge.ts +117 -0
- package/packages/core/src/kernel/dispatch-settings.ts +60 -0
- package/packages/core/src/kernel/dispatch-status.ts +141 -0
- package/packages/core/src/kernel/engine.ts +1047 -0
- package/packages/core/src/kernel/harvest.ts +823 -0
- package/packages/core/src/kernel/origin.ts +69 -0
- package/packages/core/src/kernel/phases.ts +196 -0
- package/packages/core/src/kernel/plan-verify-selection.ts +105 -0
- package/packages/core/src/kernel/pr-attachments.ts +82 -0
- package/packages/core/src/kernel/reducer.ts +752 -0
- package/packages/core/src/kernel/stall.ts +155 -0
- package/packages/core/src/kernel/verify-applicability.ts +52 -0
- package/packages/core/src/markdown.ts +67 -0
- package/packages/core/src/ontology.ts +288 -0
- package/packages/core/src/open-map.ts +203 -0
- package/packages/core/src/operator/annotations.ts +187 -0
- package/packages/core/src/operator/client.ts +311 -0
- package/packages/core/src/operator/control.ts +117 -0
- package/packages/core/src/operator/index.ts +62 -0
- package/packages/core/src/operator/presentation.ts +22 -0
- package/packages/core/src/operator/protocol.ts +98 -0
- package/packages/core/src/operator/query.ts +201 -0
- package/packages/core/src/operator/registry.ts +1043 -0
- package/packages/core/src/operator/requests.ts +138 -0
- package/packages/core/src/operator/sandbox.ts +458 -0
- package/packages/core/src/operator/server.ts +616 -0
- package/packages/core/src/operator/sessions.ts +223 -0
- package/packages/core/src/operator/tickets.ts +177 -0
- package/packages/core/src/plugin-sdk/index.ts +174 -0
- package/packages/core/src/plugins/contract-entry.ts +74 -0
- package/packages/core/src/plugins/contract-env.ts +3 -0
- package/packages/core/src/plugins/load.ts +259 -0
- package/packages/core/src/plugins/manifest.ts +236 -0
- package/packages/core/src/plugins/registry.ts +274 -0
- package/packages/core/src/plugins/runtimes.ts +75 -0
- package/packages/core/src/ports/forge/contract.ts +258 -0
- package/packages/core/src/ports/forge/create.ts +74 -0
- package/packages/core/src/ports/forge/fake.ts +488 -0
- package/packages/core/src/ports/forge/github-pr-attachments.ts +351 -0
- package/packages/core/src/ports/forge/github-transport.ts +352 -0
- package/packages/core/src/ports/forge/github.ts +1162 -0
- package/packages/core/src/ports/forge/local-git.ts +568 -0
- package/packages/core/src/ports/runner/claude.ts +873 -0
- package/packages/core/src/ports/runner/cli-stream.ts +90 -0
- package/packages/core/src/ports/runner/codex.ts +873 -0
- package/packages/core/src/ports/runner/contract.ts +492 -0
- package/packages/core/src/ports/runner/fake.ts +213 -0
- package/packages/core/src/ports/runner/json-record.ts +2 -0
- package/packages/core/src/ports/runner/live-contract-fixture.ts +176 -0
- package/packages/core/src/ports/runner/one-shot.ts +29 -0
- package/packages/core/src/ports/runner/pi-bridge-core.ts +136 -0
- package/packages/core/src/ports/runner/pi-bridge.js +6 -0
- package/packages/core/src/ports/runner/pi-rpc.ts +454 -0
- package/packages/core/src/ports/runner/pi.ts +617 -0
- package/packages/core/src/ports/runner/production.ts +74 -0
- package/packages/core/src/ports/runner/provider-error.ts +121 -0
- package/packages/core/src/ports/runner/routing.ts +234 -0
- package/packages/core/src/ports/runner/runtime.ts +214 -0
- package/packages/core/src/ports/runner/session-env.ts +34 -0
- package/packages/core/src/ports/runner/stream-parts.ts +103 -0
- package/packages/core/src/ports/tickets/contract.ts +570 -0
- package/packages/core/src/ports/tickets/create.ts +135 -0
- package/packages/core/src/ports/tickets/fake.ts +215 -0
- package/packages/core/src/ports/tickets/file.ts +559 -0
- package/packages/core/src/ports/tickets/linear.ts +811 -0
- package/packages/core/src/ports/tickets/operations.ts +161 -0
- package/packages/core/src/ports/tickets/remote-index.ts +13 -0
- package/packages/core/src/ports/tickets/remote-protocol.ts +80 -0
- package/packages/core/src/ports/tickets/remote-server.ts +185 -0
- package/packages/core/src/ports/tickets/remote.ts +130 -0
- package/packages/core/src/ports/tickets/update.ts +51 -0
- package/packages/core/src/ports/types.ts +528 -0
- package/packages/core/src/ports/workspace/build-execution.ts +123 -0
- package/packages/core/src/ports/workspace/contract.ts +136 -0
- package/packages/core/src/ports/workspace/create.ts +132 -0
- package/packages/core/src/ports/workspace/distribution-archive.ts +317 -0
- package/packages/core/src/ports/workspace/fake.ts +432 -0
- package/packages/core/src/ports/workspace/git-worktree.ts +848 -0
- package/packages/core/src/ports/workspace/harvest-execution.ts +111 -0
- package/packages/core/src/ports/workspace/in-process-build-execution.ts +30 -0
- package/packages/core/src/ports/workspace/local-build-execution.ts +88 -0
- package/packages/core/src/ports/workspace/operator-sandbox.ts +142 -0
- package/packages/core/src/ports/workspace/phase-scratch.ts +156 -0
- package/packages/core/src/ports/workspace/vercel-sandbox.ts +2541 -0
- package/packages/core/src/processes/build-child-exit.ts +78 -0
- package/packages/core/src/processes/build-child.ts +119 -0
- package/packages/core/src/processes/build-execution-state.ts +95 -0
- package/packages/core/src/processes/build-parent-watch.ts +35 -0
- package/packages/core/src/processes/build-runner.ts +2614 -0
- package/packages/core/src/processes/dispatcher.ts +2825 -0
- package/packages/core/src/processes/execution-settlement.ts +171 -0
- package/packages/core/src/processes/harvest-child.ts +115 -0
- package/packages/core/src/processes/harvest-execution-state.ts +121 -0
- package/packages/core/src/processes/harvest-runner.ts +1656 -0
- package/packages/core/src/processes/harvest.ts +595 -0
- package/packages/core/src/processes/infrastructure-failure-budget.ts +146 -0
- package/packages/core/src/processes/phase-failure-budget.ts +52 -0
- package/packages/core/src/processes/process-group-reaper.ts +35 -0
- package/packages/core/src/processes/process-group.ts +65 -0
- package/packages/core/src/processes/publication-loss.ts +62 -0
- package/packages/core/src/processes/publication-state.ts +93 -0
- package/packages/core/src/processes/sandbox-state.ts +101 -0
- package/packages/core/src/registry.ts +24 -0
- package/packages/core/src/sessions/reducer.ts +185 -0
- package/packages/core/src/skills.ts +7 -0
- package/packages/core/src/spec-standard.ts +47 -0
- package/packages/core/src/store/adapter.ts +80 -0
- package/packages/core/src/store/build-scope.ts +272 -0
- package/packages/core/src/store/contract.ts +2581 -0
- package/packages/core/src/store/local/blobs.ts +38 -0
- package/packages/core/src/store/local/schema.ts +180 -0
- package/packages/core/src/store/local/store.ts +1713 -0
- package/packages/core/src/store/memory.ts +1138 -0
- package/packages/core/src/store/phase-session.ts +425 -0
- package/packages/core/src/store/remote/client.ts +780 -0
- package/packages/core/src/store/remote/index.ts +12 -0
- package/packages/core/src/store/remote/protocol.ts +348 -0
- package/packages/core/src/store/remote/server.ts +923 -0
- package/packages/core/src/store/remote/token.ts +137 -0
- package/packages/core/src/store/remote/version.ts +10 -0
- package/packages/core/src/store/retention.ts +91 -0
- package/packages/core/src/store/session-handle.ts +265 -0
- package/packages/core/src/store/streams/assemble.ts +79 -0
- package/packages/core/src/store/streams/lock.ts +42 -0
- package/packages/core/src/store/streams/session-writer.ts +306 -0
- package/packages/core/src/store/streams/types.ts +171 -0
- package/packages/core/src/store/streams/wait.ts +127 -0
- package/packages/core/src/store/subscribe.ts +105 -0
- package/packages/core/src/store/types.ts +466 -0
- package/packages/core/src/testing/fixed.ts +44 -0
- package/packages/core/src/testing/store-failures.ts +32 -0
- package/packages/core/src/zod-issues.ts +91 -0
- package/skills/code-review/SKILL.md +100 -0
- package/skills/finalize/SKILL.md +44 -0
- package/skills/guide/SKILL.md +1781 -0
- package/skills/guide/references/operator-api.md +164 -0
- package/skills/guide/references/plugin-authoring.md +354 -0
- package/skills/guide/references/remote-store-protocol.md +972 -0
- package/skills/guide/references/remote-ticket-protocol.md +79 -0
- package/skills/guide/references/setup.md +289 -0
- package/skills/guide/references/spec-standard.md +63 -0
- package/skills/guide/references/ticket-dependencies.md +59 -0
- package/skills/harvest/SKILL.md +66 -0
- package/skills/harvest-review/SKILL.md +63 -0
- package/skills/implement/SKILL.md +82 -0
- package/skills/plan/SKILL.md +123 -0
- package/skills/plan-review/SKILL.md +121 -0
- package/skills/reconcile/SKILL.md +65 -0
- package/skills/spec/SKILL.md +132 -0
- package/skills/tickets/SKILL.md +139 -0
- package/templates/autobuild.toml +36 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import type { Config } from '../../config/schema'
|
|
2
|
+
import type { AbEvent } from '../../events/catalog'
|
|
3
|
+
import { reduceBuild, type BuildState } from '../../kernel/reducer'
|
|
4
|
+
import type { BuildRecord, StreamRecord, StreamScope } from '../../store/types'
|
|
5
|
+
import { projectBuild, type DashboardBuild } from './model'
|
|
6
|
+
|
|
7
|
+
/** The read-only BuildStore surface needed to construct dashboard build rows.
|
|
8
|
+
* `listStreams` is optional: when present, build-scope records enrich each
|
|
9
|
+
* row's session history with authoritative stream ids and statuses (SPEC §9). */
|
|
10
|
+
export interface DashboardBuildReader {
|
|
11
|
+
listBuilds(): Promise<BuildRecord[]>
|
|
12
|
+
getEvents(slug: string, sinceSeq?: number): Promise<AbEvent[]>
|
|
13
|
+
listStreams?(scope: StreamScope): Promise<StreamRecord[]>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface DashboardPollSnapshot {
|
|
17
|
+
/** Monotonic process-local cache revision. */
|
|
18
|
+
revision: number
|
|
19
|
+
/** Every dashboard-visible row, including acknowledged abort cleanup. Objects
|
|
20
|
+
* are reused while their streams are unchanged. */
|
|
21
|
+
builds: DashboardBuild[]
|
|
22
|
+
/** Every dashboard-visible reduction; this map and `builds` have matching
|
|
23
|
+
* membership. `aborted` entries are visible but do not consume capacity. */
|
|
24
|
+
states: ReadonlyMap<string, BuildState>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface LiveEntry {
|
|
28
|
+
kind: 'live'
|
|
29
|
+
events: AbEvent[]
|
|
30
|
+
state: BuildState
|
|
31
|
+
build: DashboardBuild | null
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** A fully completed build can never become visible again, so its log is discarded. */
|
|
35
|
+
interface TerminalEntry {
|
|
36
|
+
kind: 'terminal'
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
type PollEntry = LiveEntry | TerminalEntry
|
|
40
|
+
|
|
41
|
+
function isTerminal(state: BuildState): boolean {
|
|
42
|
+
// `build.aborted` acknowledges cancellation but begins the checkpointed
|
|
43
|
+
// cleanup saga. Keep polling until its final `build.completed` fact.
|
|
44
|
+
return state.status === 'done'
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Fail closed if a reader violates BuildStore's ordered, contiguous stream
|
|
49
|
+
* contract. Advancing past a gap would make every later incremental read
|
|
50
|
+
* permanently unable to recover the missing event.
|
|
51
|
+
*/
|
|
52
|
+
function validateDelta(slug: string, sinceSeq: number, events: AbEvent[]): void {
|
|
53
|
+
let expected = sinceSeq + 1
|
|
54
|
+
for (const event of events) {
|
|
55
|
+
if (event.build !== slug) {
|
|
56
|
+
throw new Error(`dashboard poll for "${slug}" received an event for "${event.build}"`)
|
|
57
|
+
}
|
|
58
|
+
if (event.seq !== expected) {
|
|
59
|
+
throw new Error(
|
|
60
|
+
`dashboard poll for "${slug}" expected event seq ${expected}, got ${event.seq}`,
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
expected += 1
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Process-local, display-only acceleration for the interactive dispatch frame.
|
|
69
|
+
*
|
|
70
|
+
* Every refresh still discovers records with `listBuilds()`. A first-seen
|
|
71
|
+
* stream is hydrated from seq 0; a cached dashboard-visible stream is read only
|
|
72
|
+
* after its reduced `lastSeq`. Empty deltas preserve the exact reduction and
|
|
73
|
+
* projected row, so phase timing is not recomputed. Only fully completed
|
|
74
|
+
* streams compact to tombstones; acknowledged aborts remain live through their
|
|
75
|
+
* cleanup checkpoints and final completion.
|
|
76
|
+
*
|
|
77
|
+
* Refreshes are serialized and committed transactionally. A failed refresh
|
|
78
|
+
* leaves every entry at its last successful sequence, while concurrent callers
|
|
79
|
+
* cannot publish an older snapshot after a newer one. The append-only event log
|
|
80
|
+
* remains authoritative: constructing a new cache simply rehydrates it.
|
|
81
|
+
*/
|
|
82
|
+
export class DashboardBuildPollCache {
|
|
83
|
+
private entries = new Map<string, PollEntry>()
|
|
84
|
+
private committedRevision = 0
|
|
85
|
+
private refreshTail: Promise<void> = Promise.resolve()
|
|
86
|
+
|
|
87
|
+
private configRevision = 0
|
|
88
|
+
|
|
89
|
+
constructor(
|
|
90
|
+
private readonly reader: DashboardBuildReader,
|
|
91
|
+
private readonly repo: string,
|
|
92
|
+
private config: Config,
|
|
93
|
+
) {}
|
|
94
|
+
|
|
95
|
+
/** Authoritative stream records for one build, when the reader supports
|
|
96
|
+
* the stream primitive (SPEC §9). Failures are display-only: an absent
|
|
97
|
+
* enrichment degrades to the pairing-derived status. */
|
|
98
|
+
private async readStreams(slug: string): Promise<StreamRecord[] | undefined> {
|
|
99
|
+
if (this.reader.listStreams === undefined) return undefined
|
|
100
|
+
try {
|
|
101
|
+
return await this.reader.listStreams({ kind: 'build', build: slug })
|
|
102
|
+
} catch {
|
|
103
|
+
return undefined
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** True only while no later refresh has committed. */
|
|
108
|
+
isCurrent(snapshot: DashboardPollSnapshot): boolean {
|
|
109
|
+
return snapshot.revision === this.committedRevision
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
refresh(
|
|
113
|
+
config: Config = this.config,
|
|
114
|
+
configRevision = this.configRevision,
|
|
115
|
+
): Promise<DashboardPollSnapshot> {
|
|
116
|
+
const result = this.refreshTail.then(() => this.refreshNow(config, configRevision))
|
|
117
|
+
this.refreshTail = result.then(
|
|
118
|
+
() => undefined,
|
|
119
|
+
() => undefined,
|
|
120
|
+
)
|
|
121
|
+
return result
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private async refreshNow(config: Config, configRevision: number): Promise<DashboardPollSnapshot> {
|
|
125
|
+
const configChanged = configRevision !== this.configRevision || config !== this.config
|
|
126
|
+
const records = (await this.reader.listBuilds()).filter((record) => record.repo === this.repo)
|
|
127
|
+
const next = new Map<string, PollEntry>()
|
|
128
|
+
|
|
129
|
+
for (const record of records) {
|
|
130
|
+
const current = this.entries.get(record.slug)
|
|
131
|
+
if (current?.kind === 'terminal') {
|
|
132
|
+
next.set(record.slug, current)
|
|
133
|
+
continue
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const sinceSeq = current?.state.lastSeq ?? 0
|
|
137
|
+
const delta = await this.reader.getEvents(record.slug, sinceSeq)
|
|
138
|
+
validateDelta(record.slug, sinceSeq, delta)
|
|
139
|
+
|
|
140
|
+
if (current !== undefined && delta.length === 0) {
|
|
141
|
+
// Dashboard rows derive from event streams and effective config only.
|
|
142
|
+
// Heartbeat and lease renewals are mutable record facts, so they leave
|
|
143
|
+
// both the cached reduction and projected row untouched.
|
|
144
|
+
next.set(
|
|
145
|
+
record.slug,
|
|
146
|
+
configChanged
|
|
147
|
+
? {
|
|
148
|
+
...current,
|
|
149
|
+
build: projectBuild(
|
|
150
|
+
record,
|
|
151
|
+
current.state,
|
|
152
|
+
config,
|
|
153
|
+
current.events,
|
|
154
|
+
await this.readStreams(record.slug),
|
|
155
|
+
),
|
|
156
|
+
}
|
|
157
|
+
: current,
|
|
158
|
+
)
|
|
159
|
+
continue
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const events = current === undefined ? delta : [...current.events, ...delta]
|
|
163
|
+
const state = reduceBuild(events)
|
|
164
|
+
if (isTerminal(state)) {
|
|
165
|
+
next.set(record.slug, { kind: 'terminal' })
|
|
166
|
+
continue
|
|
167
|
+
}
|
|
168
|
+
next.set(record.slug, {
|
|
169
|
+
kind: 'live',
|
|
170
|
+
events,
|
|
171
|
+
state,
|
|
172
|
+
build: projectBuild(record, state, config, events, await this.readStreams(record.slug)),
|
|
173
|
+
})
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Constructing `next` only from the latest listing also prunes records that
|
|
177
|
+
// disappeared. Publish once, after every read/reduction succeeded.
|
|
178
|
+
this.entries = next
|
|
179
|
+
this.config = config
|
|
180
|
+
this.configRevision = configRevision
|
|
181
|
+
this.committedRevision += 1
|
|
182
|
+
return this.snapshot()
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private snapshot(): DashboardPollSnapshot {
|
|
186
|
+
const builds: DashboardBuild[] = []
|
|
187
|
+
const states = new Map<string, BuildState>()
|
|
188
|
+
for (const [slug, entry] of this.entries) {
|
|
189
|
+
if (entry.kind === 'terminal') continue
|
|
190
|
+
states.set(slug, entry.state)
|
|
191
|
+
if (entry.build !== null) builds.push(entry.build)
|
|
192
|
+
}
|
|
193
|
+
builds.sort((a, b) => a.slug.localeCompare(b.slug))
|
|
194
|
+
return { revision: this.committedRevision, builds, states }
|
|
195
|
+
}
|
|
196
|
+
}
|