Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/dwarves

crates/dwarves-embed/proto/explorer.proto

// explorer.proto — the forge's 🧭 EXPLORER (2026-10-16).
//
// The Dwarves project (`<warehouse>/projects/<name>.dwarves.toml`) as a tree —
// project → Mímir → Workspaces → Build Things → Pipelines — and, for the node a
// person selects, what the forge knows about it: a workspace's repos and their
// state and its recent builds; a Build Thing's variants and the artifacts Builder 2
// landed in Mímir; a pipeline's stages and its recent runs.
//
// Every answer is AT ONCE. A read is folded on the forge's jera queue (the kept
// answer, or `queued` / `running` and the job); every action (build a workspace,
// build a Build Thing, run a pipeline) is a jera job too: the call answers with the
// job id, and `Job` answers how that job is doing. The UI asks again, each a short
// call. It never dials nornir.
//
// The SAME file is compiled by the forge (`crates/dwarves`, server + client) and by
// the UI's thin client (`crates/dwarves-embed`, client): a test keeps the copies
// byte-identical.
syntax = "proto3";
package dwarf.v1;

service Explorer {
  // The project tree + the detail of `select` (a node id of that tree).
  rpc Ask (ExplorerAsk) returns (ExplorerAnswer);
  // Queue the super build of a workspace (`nornir workspace build <ws>`, the road a
  // Runa `BuildWorkspace` step runs). `only = "affected"` builds what moved and what
  // depends on it (`--affected`); any other scope is refused by name.
  rpc BuildWorkspace (ExplorerBuildWorkspace) returns (ExplorerAnswer);
  // Queue a build of one of the project's Build Things (Builder 2).
  rpc BuildThing (ExplorerBuildThing) returns (ExplorerAnswer);
  // Queue a run of one of the project's Runa pipelines.
  rpc RunPipeline (ExplorerRunPipeline) returns (ExplorerAnswer);
  // How a queued action is doing.
  rpc Job (ExplorerJob) returns (ExplorerAnswer);
}

message ExplorerAsk {
  // The registered project; empty = the forge's first.
  string project = 1;
  // The selected node id (`workspace:nordisk`, `build_thing:nornir`,
  // `pipeline:dwarves-forge`, …); empty = the project itself.
  string select = 2;
  // Fold it again even when a fresh answer is kept.
  bool fresh = 3;
}

message ExplorerBuildWorkspace {
  string project = 1;
  string workspace = 2;
  // `all` (or empty) · `affected` (what moved and what depends on it).
  string only = 3;
}

message ExplorerBuildThing {
  string project = 1;
  // The Build Thing's name in the project.
  string name = 2;
  // One variant; empty = the Build Thing's default.
  string variant = 3;
  // The operator's cargo feature choice for its cargo variant(s): `--features`
  // (one entry per feature), `--no-default-features`, `--all-features`.
  repeated string features = 4;
  bool no_default_features = 5;
  bool all_features = 6;
}

message ExplorerRunPipeline {
  string project = 1;
  // The pipeline's name in the project.
  string name = 2;
}

message ExplorerJob {
  string job_id = 1;
}

message ExplorerAnswer {
  // Ask: `done` (json is the answer) · `queued` / `running` (job_id; json may carry
  // the last kept answer) · `failed` · `refused` (note says why).
  // An action: `queued` (job_id) · `refused` (note says why).
  // Job: `queued` · `running` · `done` · `failed` · `unknown`.
  string state = 1;
  string job_id = 2;
  string note = 3;
  string json = 4;
  // How long the job has waited / run, in ms.
  uint64 waited_ms = 5;
  // How old the answer in json is, in ms.
  uint64 age_ms = 6;
}