@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,12 @@
|
|
|
1
|
+
export { AuthError, RemoteBuildStore } from './client'
|
|
2
|
+
export type { RemoteBuildStoreOptions, RemoteStoreIdentity } from './client'
|
|
3
|
+
export { createStoreServer, startStoreServer } from './server'
|
|
4
|
+
export type { StartStoreServerOptions, StoreServer, StoreServerOptions } from './server'
|
|
5
|
+
export { mintToken, tokenResource, verifyToken } from './token'
|
|
6
|
+
export type { OperatorTokenScope, TokenScope } from './token'
|
|
7
|
+
export {
|
|
8
|
+
AUTOBUILD_VERSION,
|
|
9
|
+
AUTOBUILD_VERSION_HEADER,
|
|
10
|
+
REMOTE_STORE_PROTOCOL_VERSION,
|
|
11
|
+
REMOTE_STORE_PROTOCOL_VERSION_HEADER,
|
|
12
|
+
} from './version'
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The wire protocol of the remote BuildStore (SPEC §7.2 adapter 2): JSON
|
|
3
|
+
* bodies, artifact content as base64, errors as `{error, kind}`. Server
|
|
4
|
+
* (server.ts) and client (client.ts) parse the exact same schemas, so the
|
|
5
|
+
* wire can never drift between the two halves.
|
|
6
|
+
*
|
|
7
|
+
* ── Atomic deposits over the wire (D6, §8.5) ─────────────────────────────
|
|
8
|
+
* `BuildStore.appendWithArtifacts` takes a `makeEvent` callback — not
|
|
9
|
+
* serializable. The wire convention:
|
|
10
|
+
*
|
|
11
|
+
* client sends { artifacts: [{kind, contentBase64, metadata?}, …],
|
|
12
|
+
* event: { actor, type, payload } }
|
|
13
|
+
*
|
|
14
|
+
* where the payload may embed placeholder refs `{kind, rev: -(index+1)}`
|
|
15
|
+
* pointing at the request's artifacts array (the client runs `makeEvent`
|
|
16
|
+
* against sentinel metas carrying those negative revisions). The server
|
|
17
|
+
* calls the backing store's `appendWithArtifacts` and, inside its
|
|
18
|
+
* `makeEvent`, walks the payload substituting the really-assigned revisions
|
|
19
|
+
* for the negative placeholders — so deposit + event stay one atomic
|
|
20
|
+
* operation server-side.
|
|
21
|
+
*
|
|
22
|
+
* This covers the system's only usage pattern: payloads embed deposited
|
|
23
|
+
* refs as `{kind, rev}` objects (§15.2 — events carry facts and refs).
|
|
24
|
+
* Arbitrary computation over the assigned revisions inside `makeEvent`
|
|
25
|
+
* (e.g. `rev + 1`, string interpolation) is unsupported by design.
|
|
26
|
+
*/
|
|
27
|
+
import { z } from 'zod'
|
|
28
|
+
import { actorSchema } from '../../events/envelope'
|
|
29
|
+
import { ticketRefSchema } from '../../ontology'
|
|
30
|
+
import type { ArtifactMeta, RepositoryArtifactMeta, SessionArtifactMeta } from '../types'
|
|
31
|
+
|
|
32
|
+
// ── Errors (D6: errors as feedback over the wire) ────────────────────────────
|
|
33
|
+
|
|
34
|
+
export const errorKindSchema = z.enum(['validation', 'not-found', 'auth', 'conflict', 'internal'])
|
|
35
|
+
export type ErrorKind = z.infer<typeof errorKindSchema>
|
|
36
|
+
|
|
37
|
+
export const errorBodySchema = z.object({
|
|
38
|
+
error: z.string(),
|
|
39
|
+
kind: errorKindSchema,
|
|
40
|
+
})
|
|
41
|
+
export type ErrorBody = z.infer<typeof errorBodySchema>
|
|
42
|
+
|
|
43
|
+
// ── Builds ───────────────────────────────────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
export const newBuildBodySchema = z.object({
|
|
46
|
+
slug: z.string().min(1),
|
|
47
|
+
repo: z.string().min(1),
|
|
48
|
+
// Additive optional identity: the build repository's normalized git origin.
|
|
49
|
+
// Old servers strip it on create (path-only fallback) and never return it;
|
|
50
|
+
// old clients never send it. No protocol-version bump.
|
|
51
|
+
repoOrigin: z.string().optional(),
|
|
52
|
+
ticket: ticketRefSchema.optional(),
|
|
53
|
+
branch: z.string().min(1).optional(),
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
export const buildRecordWireSchema = z.object({
|
|
57
|
+
slug: z.string(),
|
|
58
|
+
repo: z.string(),
|
|
59
|
+
repoOrigin: z.string().optional(),
|
|
60
|
+
ticket: ticketRefSchema.optional(),
|
|
61
|
+
branch: z.string().optional(),
|
|
62
|
+
createdAt: z.string(),
|
|
63
|
+
updatedAt: z.string(),
|
|
64
|
+
lease: z.object({ holder: z.string(), expiresAt: z.string() }).optional(),
|
|
65
|
+
heartbeatAt: z.string().optional(),
|
|
66
|
+
})
|
|
67
|
+
export const buildRecordListSchema = z.array(buildRecordWireSchema)
|
|
68
|
+
|
|
69
|
+
// ── Events ───────────────────────────────────────────────────────────────────
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Deliberately loose: the ontology is enforced by `validateEventWrite` in
|
|
73
|
+
* the *backing store* (§8), so its precise EventValidationError message —
|
|
74
|
+
* the agent feedback D6 exists for — survives the wire instead of being
|
|
75
|
+
* shadowed by a duplicate wire-schema error.
|
|
76
|
+
*/
|
|
77
|
+
export const eventWriteWireSchema = z.object({
|
|
78
|
+
actor: z.unknown(),
|
|
79
|
+
type: z.string().min(1),
|
|
80
|
+
payload: z.unknown(),
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
export const eventEnvelopeWireSchema = z.object({
|
|
84
|
+
build: z.string(),
|
|
85
|
+
seq: z.number().int().positive(),
|
|
86
|
+
ts: z.string(),
|
|
87
|
+
actor: actorSchema,
|
|
88
|
+
type: z.string(),
|
|
89
|
+
payload: z.unknown(),
|
|
90
|
+
})
|
|
91
|
+
export const eventListSchema = z.array(eventEnvelopeWireSchema)
|
|
92
|
+
|
|
93
|
+
export const conditionalEventBodySchema = z.object({
|
|
94
|
+
expectedSeq: z.number().int().nonnegative(),
|
|
95
|
+
event: eventWriteWireSchema,
|
|
96
|
+
})
|
|
97
|
+
export const conditionalEventResponseSchema = eventEnvelopeWireSchema.nullable()
|
|
98
|
+
|
|
99
|
+
// ── Repository journals ─────────────────────────────────────────────────────
|
|
100
|
+
|
|
101
|
+
export const ensureRepoBodySchema = z.object({ repo: z.string().min(1) })
|
|
102
|
+
export const repositoryRecordWireSchema = z.object({
|
|
103
|
+
repo: z.string().min(1),
|
|
104
|
+
createdAt: z.string(),
|
|
105
|
+
updatedAt: z.string(),
|
|
106
|
+
lease: z.object({ holder: z.string(), expiresAt: z.string() }).optional(),
|
|
107
|
+
heartbeatAt: z.string().optional(),
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
export const repositoryEventEnvelopeWireSchema = z.object({
|
|
111
|
+
repo: z.string(),
|
|
112
|
+
seq: z.number().int().positive(),
|
|
113
|
+
ts: z.string(),
|
|
114
|
+
actor: actorSchema,
|
|
115
|
+
type: z.string(),
|
|
116
|
+
payload: z.unknown(),
|
|
117
|
+
})
|
|
118
|
+
export const repositoryEventListSchema = z.array(repositoryEventEnvelopeWireSchema)
|
|
119
|
+
|
|
120
|
+
export const repositoryArtifactMetaWireSchema = z.object({
|
|
121
|
+
repo: z.string(),
|
|
122
|
+
kind: z.string(),
|
|
123
|
+
revision: z.number().int().nonnegative(),
|
|
124
|
+
blobRef: z.string(),
|
|
125
|
+
metadata: z.record(z.string(), z.unknown()),
|
|
126
|
+
createdAt: z.string(),
|
|
127
|
+
})
|
|
128
|
+
export const repositoryArtifactMetaListSchema = z.array(repositoryArtifactMetaWireSchema)
|
|
129
|
+
export const repositoryArtifactGetResponseSchema = z.union([
|
|
130
|
+
z.null(),
|
|
131
|
+
z.object({
|
|
132
|
+
meta: repositoryArtifactMetaWireSchema,
|
|
133
|
+
contentBase64: z.string(),
|
|
134
|
+
}),
|
|
135
|
+
])
|
|
136
|
+
export const repoDepositsResponseSchema = z.object({
|
|
137
|
+
event: repositoryEventEnvelopeWireSchema,
|
|
138
|
+
artifacts: repositoryArtifactMetaListSchema,
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
// ── Operator sessions (SPEC §7.1.1) ─────────────────────────────────────────
|
|
142
|
+
|
|
143
|
+
export const newSessionBodySchema = z.object({
|
|
144
|
+
repo: z.string().min(1),
|
|
145
|
+
operator: z.string().min(1),
|
|
146
|
+
title: z.string().optional(),
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
export const sessionRecordWireSchema = z.object({
|
|
150
|
+
id: z.string(),
|
|
151
|
+
repo: z.string(),
|
|
152
|
+
operator: z.string(),
|
|
153
|
+
title: z.string().optional(),
|
|
154
|
+
createdAt: z.string(),
|
|
155
|
+
updatedAt: z.string(),
|
|
156
|
+
})
|
|
157
|
+
export const sessionRecordListSchema = z.array(sessionRecordWireSchema)
|
|
158
|
+
|
|
159
|
+
export const sessionEventEnvelopeWireSchema = z.object({
|
|
160
|
+
session: z.string(),
|
|
161
|
+
seq: z.number().int().positive(),
|
|
162
|
+
ts: z.string(),
|
|
163
|
+
actor: actorSchema,
|
|
164
|
+
type: z.string(),
|
|
165
|
+
payload: z.unknown(),
|
|
166
|
+
})
|
|
167
|
+
export const sessionEventListSchema = z.array(sessionEventEnvelopeWireSchema)
|
|
168
|
+
|
|
169
|
+
export const sessionArtifactMetaWireSchema = z.object({
|
|
170
|
+
session: z.string(),
|
|
171
|
+
kind: z.string(),
|
|
172
|
+
revision: z.number().int().nonnegative(),
|
|
173
|
+
blobRef: z.string(),
|
|
174
|
+
metadata: z.record(z.string(), z.unknown()),
|
|
175
|
+
createdAt: z.string(),
|
|
176
|
+
})
|
|
177
|
+
export const sessionArtifactMetaListSchema = z.array(sessionArtifactMetaWireSchema)
|
|
178
|
+
export const sessionArtifactGetResponseSchema = z.union([
|
|
179
|
+
z.null(),
|
|
180
|
+
z.object({
|
|
181
|
+
meta: sessionArtifactMetaWireSchema,
|
|
182
|
+
contentBase64: z.string(),
|
|
183
|
+
}),
|
|
184
|
+
])
|
|
185
|
+
export const sessionDepositsResponseSchema = z.object({
|
|
186
|
+
event: sessionEventEnvelopeWireSchema,
|
|
187
|
+
artifacts: sessionArtifactMetaListSchema,
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
// ── Artifacts ────────────────────────────────────────────────────────────────
|
|
191
|
+
|
|
192
|
+
export const artifactMetaWireSchema = z.object({
|
|
193
|
+
build: z.string(),
|
|
194
|
+
kind: z.string(),
|
|
195
|
+
revision: z.number().int().nonnegative(),
|
|
196
|
+
blobRef: z.string(),
|
|
197
|
+
metadata: z.record(z.string(), z.unknown()),
|
|
198
|
+
createdAt: z.string(),
|
|
199
|
+
})
|
|
200
|
+
export const artifactMetaListSchema = z.array(artifactMetaWireSchema)
|
|
201
|
+
|
|
202
|
+
export const putArtifactBodySchema = z.object({
|
|
203
|
+
kind: z.string().min(1),
|
|
204
|
+
contentBase64: z.string(),
|
|
205
|
+
metadata: z.record(z.string(), z.unknown()).optional(),
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
/** GET …/artifacts: JSON `null` when the kind (or rev) is absent (§7.2). */
|
|
209
|
+
export const artifactGetResponseSchema = z.union([
|
|
210
|
+
z.null(),
|
|
211
|
+
z.object({
|
|
212
|
+
meta: artifactMetaWireSchema,
|
|
213
|
+
contentBase64: z.string(),
|
|
214
|
+
}),
|
|
215
|
+
])
|
|
216
|
+
|
|
217
|
+
// ── Atomic deposits (see module header) ──────────────────────────────────────
|
|
218
|
+
|
|
219
|
+
export const depositsBodySchema = z.object({
|
|
220
|
+
artifacts: z.array(putArtifactBodySchema),
|
|
221
|
+
event: eventWriteWireSchema,
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
export const depositsResponseSchema = z.object({
|
|
225
|
+
event: eventEnvelopeWireSchema,
|
|
226
|
+
artifacts: artifactMetaListSchema,
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
// ── Leases (§7.4, §15.2.6) ───────────────────────────────────────────────────
|
|
230
|
+
|
|
231
|
+
export const leaseClaimBodySchema = z.object({
|
|
232
|
+
holder: z.string().min(1),
|
|
233
|
+
ttlMs: z.number().int().nonnegative(),
|
|
234
|
+
})
|
|
235
|
+
export const leaseHolderBodySchema = z.object({ holder: z.string().min(1) })
|
|
236
|
+
export const okResponseSchema = z.object({ ok: z.boolean() })
|
|
237
|
+
|
|
238
|
+
// ── Streams (SPEC §7.6 — the third primitive) ────────────────────────────
|
|
239
|
+
//
|
|
240
|
+
// Deliberately loose on part contents: the store performs no protocol
|
|
241
|
+
// validation on append (assembly at close does that), and `looseObject` —
|
|
242
|
+
// not `z.object` — so unknown part keys survive the wire untouched.
|
|
243
|
+
|
|
244
|
+
export const streamScopeWireSchema = z.discriminatedUnion('kind', [
|
|
245
|
+
z.object({ kind: z.literal('build'), build: z.string().min(1) }),
|
|
246
|
+
z.object({ kind: z.literal('repo'), repo: z.string().min(1) }),
|
|
247
|
+
z.object({ kind: z.literal('session'), session: z.string().min(1) }),
|
|
248
|
+
])
|
|
249
|
+
|
|
250
|
+
export const streamArtifactRefWireSchema = z.object({
|
|
251
|
+
kind: z.string(),
|
|
252
|
+
revision: z.number().int().nonnegative(),
|
|
253
|
+
blobRef: z.string(),
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
export const streamRecordWireSchema = z.object({
|
|
257
|
+
id: z.string(),
|
|
258
|
+
scope: streamScopeWireSchema,
|
|
259
|
+
label: z.string(),
|
|
260
|
+
format: z.string(),
|
|
261
|
+
status: z.enum(['open', 'closed']),
|
|
262
|
+
createdAt: z.string(),
|
|
263
|
+
closedAt: z.string().optional(),
|
|
264
|
+
outcome: z.enum(['completed', 'aborted']).optional(),
|
|
265
|
+
artifact: streamArtifactRefWireSchema.optional(),
|
|
266
|
+
})
|
|
267
|
+
export const streamRecordListSchema = z.array(streamRecordWireSchema)
|
|
268
|
+
|
|
269
|
+
export const createStreamBodySchema = z.object({ label: z.string().min(1) })
|
|
270
|
+
export const closeStreamBodySchema = z.object({ outcome: z.enum(['completed', 'aborted']) })
|
|
271
|
+
|
|
272
|
+
export const streamPartWireSchema = z.looseObject({ type: z.string().min(1) })
|
|
273
|
+
export const appendStreamBodySchema = z.object({
|
|
274
|
+
parts: z.array(streamPartWireSchema).min(1),
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
export const streamChunkWireSchema = z.object({
|
|
278
|
+
stream: z.string(),
|
|
279
|
+
seq: z.number().int().positive(),
|
|
280
|
+
ts: z.string(),
|
|
281
|
+
parts: z.array(z.record(z.string(), z.unknown())),
|
|
282
|
+
})
|
|
283
|
+
export const streamReadWireSchema = z.object({
|
|
284
|
+
chunks: z.array(streamChunkWireSchema),
|
|
285
|
+
status: z.enum(['open', 'closed']),
|
|
286
|
+
outcome: z.enum(['completed', 'aborted']).optional(),
|
|
287
|
+
artifact: streamArtifactRefWireSchema.optional(),
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
// ── Base64 content encoding ──────────────────────────────────────────────────
|
|
291
|
+
|
|
292
|
+
export function encodeBase64(bytes: Uint8Array): string {
|
|
293
|
+
return Buffer.from(bytes).toString('base64')
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
export function decodeBase64(text: string): Uint8Array {
|
|
297
|
+
if (
|
|
298
|
+
text.length % 4 !== 0 ||
|
|
299
|
+
!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(text)
|
|
300
|
+
) {
|
|
301
|
+
throw new Error('artifact content is not valid base64')
|
|
302
|
+
}
|
|
303
|
+
const bytes = new Uint8Array(Buffer.from(text, 'base64'))
|
|
304
|
+
if (encodeBase64(bytes) !== text) throw new Error('artifact content is not valid base64')
|
|
305
|
+
return bytes
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// ── Placeholder refs for atomic deposits ─────────────────────────────────────
|
|
309
|
+
|
|
310
|
+
/** The negative sentinel revision for the deposit at `index`: -(index+1). */
|
|
311
|
+
export function placeholderRev(index: number): number {
|
|
312
|
+
return -(index + 1)
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function isPlaceholderRef(value: unknown): value is { kind: string; rev: number } {
|
|
316
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
317
|
+
return false
|
|
318
|
+
}
|
|
319
|
+
if (Object.keys(value).length !== 2) return false
|
|
320
|
+
const { kind, rev } = value as { kind?: unknown; rev?: unknown }
|
|
321
|
+
return typeof kind === 'string' && typeof rev === 'number' && Number.isInteger(rev) && rev < 0
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Walk a JSON payload, replacing every placeholder ref `{kind, rev: -(i+1)}`
|
|
326
|
+
* with the deposited artifact's real `{kind, rev}`. An out-of-range
|
|
327
|
+
* placeholder is left untouched — event validation then rejects the negative
|
|
328
|
+
* rev (artifact refs are nonnegative, §15.2), rolling the deposit back.
|
|
329
|
+
*/
|
|
330
|
+
export function substitutePlaceholderRefs(
|
|
331
|
+
value: unknown,
|
|
332
|
+
deposited: Array<ArtifactMeta | RepositoryArtifactMeta | SessionArtifactMeta>,
|
|
333
|
+
): unknown {
|
|
334
|
+
if (isPlaceholderRef(value)) {
|
|
335
|
+
const meta = deposited[-value.rev - 1]
|
|
336
|
+
if (meta === undefined) return value
|
|
337
|
+
return { kind: meta.kind, rev: meta.revision }
|
|
338
|
+
}
|
|
339
|
+
if (Array.isArray(value)) {
|
|
340
|
+
return value.map((item) => substitutePlaceholderRefs(item, deposited))
|
|
341
|
+
}
|
|
342
|
+
if (typeof value === 'object' && value !== null) {
|
|
343
|
+
return Object.fromEntries(
|
|
344
|
+
Object.entries(value).map(([key, item]) => [key, substitutePlaceholderRefs(item, deposited)]),
|
|
345
|
+
)
|
|
346
|
+
}
|
|
347
|
+
return value
|
|
348
|
+
}
|