Other data types
Messages and enums that more than one Daemon service uses.
Messages and enums used by more than one service in builder, kept here
rather than repeated on each service's page.
PortForward
A host→pod port forward (host_port on the node → pod_port inside the pod).
message PortForward {
optional uint32 host_port = 1;
optional uint32 pod_port = 2;
optional bool udp = 3;
}| Field | |
|---|---|
host_port | |
pod_port | |
udp | UDP instead of TCP |
TestCaseView
message TestCaseView {
optional string name = 1;
optional TestCaseStatus status = 2;
optional string message = 3;
optional uint64 duration_ms = 4;
optional map<string, string> labels = 5;
repeated TestAttachment attachments = 6;
}| Field | |
|---|---|
name | |
status | |
message | failure detail; empty unless failed |
duration_ms | |
labels | What kind of case this is. bldr.test-type=visual-snapshot marks one whose real output is the images in attachments. |
attachments | Files the case produced (screenshots, logs). Empty for almost every case. |
TestAttachment
A file a test produced, kept by CID. What it is lives in the labels rather than in the type, so the schema stays still as the kinds of attachment grow: bldr.content-type = an IANA media type, e.g. image/png bldr.snapshot = before | after | diff
message TestAttachment {
optional string cid = 1;
optional map<string, string> labels = 2;
}TaskEvent
A snapshot of one node in the invocation progress tree. Consumers key by
id, link children via parent, and render state. A node moves through
CACHE_LOOKUP → {CACHE_HIT | RUNNING} → {COMPLETED | FAILED}.
message TaskEvent {
optional uint64 id = 1;
optional string label = 3;
optional TaskState state = 4;
optional google.protobuf.Timestamp emitted_at = 6;
optional map<string, string> labels = 12;
repeated uint64 waiting_for = 13;
oneof _parent {
uint64 parent = 2;
}
oneof _output {
string output = 5;
}
oneof _running_ms {
uint64 running_ms = 7;
}
oneof _waiting_ms {
uint64 waiting_ms = 8;
}
oneof _log_stream_id {
string log_stream_id = 9;
}
oneof _log_cid {
string log_cid = 10;
}
oneof _pod_id {
string pod_id = 11;
}
oneof _input {
string input = 14;
}
oneof _function {
string function = 15;
}
oneof _rootfs {
string rootfs = 16;
}
oneof _queued_at {
google.protobuf.Timestamp queued_at = 17;
}
oneof _started_at {
google.protobuf.Timestamp started_at = 18;
}
oneof _ended_at {
google.protobuf.Timestamp ended_at = 19;
}
oneof _peer_id {
string peer_id = 20;
}
oneof _step {
TaskStep step = 21;
}
oneof _deadline {
google.protobuf.Timestamp deadline = 22;
}
}| Field | |
|---|---|
id | |
parent | Absent → a root node; otherwise the id of the parent node. |
label | human-readable description |
state | |
output | The invocation's result CID, on terminal states of an invocation node. |
emitted_at | Wall-clock time when this event was emitted on the server. |
running_ms | On a terminal event: server-tracked time (ms) the node spent actively running, and (if any) blocked waiting on a resource. Absent otherwise. |
waiting_ms | |
log_stream_id | The log stream carrying this node's output, published as soon as output starts (before the sealed CID exists). Read via the Logs service. |
log_cid | The sealed log Blob CID, attached once the node's output stream closes. |
pod_id | The id of the pod this node ran, if it ran one. Lets the UI link the node to the Pods page. The pod may already be reaped by the time it's viewed. |
labels | Free-form key/value metadata. language names a syntax for rendering the label (e.g. "sh"), so consumers need not pattern-match the text. |
waiting_for | When queued: the tasks this one is waiting on. |
input | The invocation's input CID, so a viewer can open what went in as readily as what came out. Always the actual input block of the invocation (e.g. a pod.dag op's spec), never a substitute — see rootfs for the tree a pod ran on. |
function | The invoked function's name (e.g. "pod.dag/v0.0.0"), on invocation nodes. label starts out as this but functions replace it with a description, so the name is carried separately where a viewer can always reach it. |
rootfs | The resolved rootfs FsNode CID a pod step ran on, where applicable. Kept apart from input: the rootfs is derived context, not the block the step consumed. |
queued_at | The node's own span, stamped from the server's phase accumulator on every event rather than only on the terminal one — the replay a late subscriber receives is compacted to the latest event per node, so a span assembled from the event sequence would be lost the moment a node moved on. |
started_at | |
ended_at | |
peer_id | The peer that executed this invocation, base58, when it did not run here. |
step | How this node fits a deployment's plan — the block it is, or the action it runs — when it is a step of one. Absent on every other node: a build's sync tree, a function's own subtasks (a push's layers, an apply's resources) are not steps. Set once, when the plan is published, and kept through the node's later events by the server's replay. |
deadline | When this node must have finished, when it runs against a timeout (a composite block's timeoutSecs, k8s.job.wait's). A viewer draws the node's progress against it. |
TaskStep
A deployment step's place in its plan. A deployment is a step function:
before anything runs, the composite publishes every block and action it
will run, each as a queued node carrying one of these, and the nodes
then move through running → completed | failed | skipped.
message TaskStep {
optional TaskStepKind kind = 1;
optional string form = 2;
optional string phase = 3;
optional string name = 4;
repeated string needs = 5;
optional uint32 index = 6;
optional uint32 count = 7;
}| Field | |
|---|---|
kind | |
form | A block's form: "sequence" | "parallel" | "try" | "dag". Empty on an action. |
phase | The phase of a try block this step is: "try" | "catch" | "finally". Empty for a step that is not directly under a try block. |
name | A DAG node's name, and the names of the nodes it needs. Empty otherwise. |
needs | |
index | The step's 1-based position among its siblings, and how many there are. |
count |
TaskState
message TaskState {
oneof kind {
Unit cache_lookup = 1;
Unit cache_hit = 2;
TaskRunning running = 3;
Unit completed = 4;
TaskFailed failed = 5;
TaskWaiting waiting = 6;
Unit queued = 7;
Unit cancelled = 8;
TaskWaitingForResources waiting_for_resources = 9;
TaskRetrying retrying = 10;
TaskSkipped skipped = 11;
}
}| Field | |
|---|---|
cache_lookup | consulting the cache |
cache_hit | resolved from cache (terminal) |
running | executing |
completed | finished ok (terminal) |
failed | failed (terminal) |
waiting | blocked on a resource (download slot, rate limit) |
queued | declared, not started — the build knows it is coming |
cancelled | abandoned because something else failed (terminal) |
waiting_for_resources | held at the admission gate |
retrying | an attempt failed and another will follow (NOT terminal) |
skipped | Planned, and deliberately not run (terminal): a sequence step after a failure, a catch whose try succeeded. Distinct from cancelled (abandoned because something broke) and from failed (it never ran). |
TaskSkipped
A planned step that did not run, and why — "step 2 failed", "try succeeded".
message TaskSkipped {
optional string reason = 1;
}TaskRetrying
An attempt failed and the task will be tried again — deliberately NOT a
failed state: a red node reads as "this build is broken", and a retryable
attempt does not mean that. Non-terminal; followed by another attempt (and
eventually by completed or a failed carrying the final attempt counts).
message TaskRetrying {
optional string error = 1;
optional uint32 attempt = 2;
optional uint32 limit = 3;
oneof _retry_in_ms {
uint64 retry_in_ms = 4;
}
}| Field | |
|---|---|
error | The failing attempt's error, kept so the attempt stays diagnosable. |
attempt | Which attempt just failed (1-based) and how many will be made at most. |
limit | |
retry_in_ms | Backoff remaining before the next attempt starts, when the retrier knows it — so the tree reads "retrying in 2.0s" instead of looking stalled. |
TaskWaiting
message TaskWaiting {
optional string reason = 1;
optional TaskProgress progress = 2;
}| Field | |
|---|---|
reason | What the node is blocked on, e.g. "download slot" or "rate limit — retry in 5s". |
progress | Optional countdown / progress while blocked. |
TaskWaitingForResources
Held at the node's admission gate before execution starts: the host lacks
the resources to start another function execution right now. Distinct from
waiting, which a running function reports about its own external waits —
here the function body has not begun. Non-terminal; followed by running
once admitted.
message TaskWaitingForResources {
optional string reason = 1;
optional string resource = 2;
optional uint64 needed = 3;
optional uint64 available = 4;
}| Field | |
|---|---|
reason | Human-readable, e.g. "waiting for memory (need 2.0GiB, free 0.4GiB)". |
resource | Which resource admission is short of: "cpu" | "memory" | "slots", or "queue" when this execution is short of nothing itself and is waiting behind earlier executions (only the head of the queue is admitted; reason says what the head is held on). |
needed | What admission needs: millicores (cpu), bytes of headroom (memory), the concurrency cap that is fully in use (slots), or the number of executions ahead of this one (queue). |
available | What is free right now: millicores (cpu), bytes of headroom (memory), or free slots (0). Always 0 for queue. |
Unit
message Unit {
// no fields
}TaskRunning
message TaskRunning {
optional string source = 1;
optional TaskProgress progress = 2;
}| Field | |
|---|---|
source | "local", or a base58 PeerId for a remote execution. |
progress | optional quantitative progress |
TaskProgress
message TaskProgress {
optional uint64 current = 1;
optional string unit = 3;
oneof _total {
uint64 total = 2;
}
oneof _detail {
string detail = 4;
}
}| Field | |
|---|---|
current | |
total | |
unit | "bytes" | "items" | "seconds" |
detail | The progress in the reporter's own words, when the fraction alone does not say enough: "3 of 5 layers, 41.2 of 68.3 MiB", "142 s of 3600 s". |
TaskFailed
message TaskFailed {
optional string error = 1;
oneof _attempts_made {
uint32 attempts_made = 2;
}
oneof _attempt_limit {
uint32 attempt_limit = 3;
}
}| Field | |
|---|---|
error | |
attempts_made | How many attempts were made before giving up, and the limit that was hit. Present only for a task that was retried — a bare "failed" hides that the daemon tried five times, which is the first thing a reader needs to know. |
attempt_limit |
CodeDiagnostic
One thing a build's tooling said about one place in the source: a type error, a lint, a deprecation.
The point of a message rather than a log line is that the location is
structured. A compiler prints a path that means something inside its own pod —
/src/bldr-ui/src/App.tsx — and a reader wants the file in the workspace they
can open. Splitting member from path-in-member is what makes that translation
the producer's job, done once where the mapping is known, instead of every
consumer guessing at a prefix.
Every positional field is optional in the sense that 0 means "not reported". A tool that knows only the file must still be able to say so, and a diagnostic with no line is worth strictly more than no diagnostic.
message CodeDiagnostic {
optional string member = 1;
optional string path = 2;
optional uint32 line = 3;
optional uint32 column = 4;
optional uint32 end_line = 5;
optional uint32 end_column = 6;
optional DiagnosticLevel level = 7;
optional string title = 8;
optional string description = 9;
optional string snippet = 10;
optional uint32 snippet_start_line = 11;
optional string code = 12;
optional string tool = 13;
optional string target = 14;
repeated RelatedDiagnostic related = 15;
repeated DiagnosticFix fixes = 16;
optional map<string, string> labels = 17;
optional string root = 18;
optional uint64 offset = 19;
optional uint64 end_offset = 20;
}| Field | |
|---|---|
member | Workspace member the file belongs to, e.g. bldr/ui. Empty when the producer could not attribute it to one — a generated file, or a path outside every member. Such a diagnostic is still shown, keyed on path. |
path | Path within the member, relative and without a leading slash, e.g. src/App.tsx. When member is empty this is whatever path the tool gave, verbatim, since anything else would be an invention. |
line | 1-based. 0 means the tool did not report a position. |
column | |
end_line | 1-based, inclusive end of the span. 0 for a point diagnostic — a consumer then highlights from (line, column) to the end of that line. |
end_column | |
level | |
title | One line, no trailing newline — what a list shows. e.g. Type 'true' is not assignable to type 'CargoOptions'. |
description | The full text, including whatever notes and hints the tool attached. Empty when it adds nothing to title; a consumer then shows title alone rather than an empty panel. |
snippet | Source lines around the diagnostic, verbatim and newline-separated, so a consumer can render context without fetching the file — which it may not be able to do at all, since the file lives in a member CID it would have to resolve. Empty when the producer chose not to include one. |
snippet_start_line | 1-based line number of snippet's first line, so the excerpt can be numbered correctly. 0 when there is no snippet. |
code | The tool's own code, e.g. TS2322 or clippy::needless_borrow. Empty when the tool has no such concept. Clients group and filter on this; they must not parse it. |
tool | What produced it, e.g. tsc, clippy, rustc. Names a tool, not a version. |
target | The build target it came out of, when the producer knows — bldr/ui/check. Empty otherwise. |
related | Other places involved — a compiler's "expected because of this". |
fixes | Fixes the tool offered. |
labels | Anything tool-specific with no field here. The escape hatch that keeps this message from growing a column per tool. |
root | The tree path is relative to; empty means the member's own source. See DiagnosticSpan.root, which this mirrors for the primary location. |
offset | 0-based byte offsets, for tools that report them instead of line/column. |
end_offset |
BuildDiagnostics
Diagnostics a build produced. Emitted as they are found, so a long typecheck reports its first error immediately rather than at the end; a client appends rather than replaces.
message BuildDiagnostics {
optional uint64 generation = 1;
repeated CodeDiagnostic diagnostics = 2;
}DiagnosticSpan
A place a diagnostic points at.
Split out of CodeDiagnostic so that a related place — a compiler's "expected because of this" — is described exactly the same way as the primary one. Two shapes for one idea is two shapes to keep in step.
message DiagnosticSpan {
optional string member = 1;
optional string path = 2;
optional uint32 line = 3;
optional uint32 column = 4;
optional uint32 end_line = 5;
optional uint32 end_column = 6;
optional uint64 offset = 7;
optional uint64 end_offset = 8;
optional string root = 9;
}| Field | |
|---|---|
member | Workspace member the file belongs to, e.g. bldr/ui. Empty when the producer could not attribute it to one. |
path | Path within the member, relative and without a leading slash. When member is empty this is whatever path the tool gave, verbatim. |
line | 1-based; 0 means the tool did not report a position. |
column | |
end_line | 1-based, inclusive end of the span. 0 for a point diagnostic. |
end_column | |
offset | 0-based byte offsets, for the tools that work in them rather than in line/column. Both 0 when not reported — a byte 0 span is not a thing any tool reports about code. |
end_offset | |
root | The tree path is relative to, as a CID. Empty means the member's own source — the file a developer can open, which is the common case. |
RelatedDiagnostic
A second place involved in a diagnostic, with what it has to do with it.
Not a diagnostic of its own: no severity, no code, because it is not a separate finding. Dropping these is what makes a re-rendered compiler error so much less useful than the original.
message RelatedDiagnostic {
optional string message = 1;
optional DiagnosticSpan location = 2;
}DiagnosticFix
A change the tool believes would resolve the finding.
Described, not applied: a build runs on a content-addressed copy, so a fix
applied there would produce a tree nobody sees. What is worth carrying is
that a fix exists and how far the tool trusts it, because that is what
decides whether a human runs the tool's --write mode.
message DiagnosticFix {
optional string message = 1;
optional string applicability = 2;
}| Field | |
|---|---|
message | What the fix would do, in the tool's words. |
applicability | How safe the tool says it is — safe, unsafe, maybe-incorrect. The tool's own vocabulary, not normalised: the words mean different things per tool and flattening them would lose the warning. |
TrackingInfo
A member's effective upstream tracking. An empty kind means "no
tracking" (absent, or kind: none). Otherwise kind names the
content-tracking-provider/<kind> function and settings carries its
free-form parameters.
message TrackingInfo {
optional string kind = 1;
optional map<string, string> settings = 2;
}TestCaseStatus
enum TestCaseStatus {
TEST_CASE_STATUS_UNSPECIFIED = 0;
TEST_CASE_STATUS_PASSED = 1;
TEST_CASE_STATUS_FAILED = 2;
TEST_CASE_STATUS_SKIPPED = 3;
}TaskStepKind
enum TaskStepKind {
TASK_STEP_KIND_UNSPECIFIED = 0;
TASK_STEP_KIND_BLOCK = 1;
TASK_STEP_KIND_ACTION = 2;
}| Value | |
|---|---|
TASK_STEP_KIND_UNSPECIFIED | |
TASK_STEP_KIND_BLOCK | Groups other steps: a sequence, a parallel, a try or a dag block. |
TASK_STEP_KIND_ACTION | One child function call. |
DiagnosticLevel
enum DiagnosticLevel {
DIAGNOSTIC_LEVEL_UNSPECIFIED = 0;
DIAGNOSTIC_LEVEL_ERROR = 1;
DIAGNOSTIC_LEVEL_WARNING = 2;
DIAGNOSTIC_LEVEL_INFO = 3;
}Diagnostics
── Diagnostics ───────────────────────────────────────────────────────────── Editor tooling for bldr's own inputs (bldr-workspace.yml, build scripts), served by the daemon rather than by an IDE extension. The daemon is the only process that already knows what a workspace *means* — its members, the content each one resolves to, the build graph they produce — so an extension that re-derived any of that would be a second implementation, permanently a little behind this one. The editor therefore speaks ordinary LSP to a thin passthrough (bldr internal lsp), which does nothing but framing, and every answer comes from the node.
BldrService
BldrService in Cloud.