Task: Add compute read verbs to the shell: list apps, app versions, platforms, hosts and batches
Table of Contents
This page documents a task in the Manage the compute grid from the shell story. It captures the goal, current status, acceptance, and any notes or results.
1. Goal
The shell's compute menu gains five read-only verbs: list-apps,
list-app-versions, list-platforms, list-hosts and
list-batches. Each verb renders the domain rows as a table with the
fields a script needs — ids, names, versions, status — so the grid
can be inspected from the shell with no UI.
2. Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Manage the compute grid from the shell |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-08-10 |
3. Acceptance
compute list-appslists the app catalogue (id, name, description).compute list-app-versionslists app versions (app id, wrapper and engine version, min RAM).compute list-platformslists platform triplets (id, code, display name, OS, CPU arch).compute list-hostslists grid nodes (id, external id, display name, hardware, last RPC time, credit).compute list-batcheslists batches (id, external ref, status).- Every verb works against a live serving environment; empty domains
render a header-only table, not an error (
list-platformsprints no rows until a platform exists).
4. Plan
All five verbs reuse existing NATS subjects and the codegen table
renderers in ores.compute.api (*_table_io.hpp); no backend or
codegen changes. Implementation lives in the existing
compute_commands.{hpp,cpp} next to publish-package, following its
shape: require a login, send the list request authenticated, log the
row count, print the table. compute_platform has no table renderer
(it is hand-written, not model-owned), so list-platforms renders
raw rows until the drift story generates the renderer (see Notes).
5. Notes
- Live proof (2026-08-10): scripted session against brave_hopper with
all 23 services up.
compute list-appsreturned the ORE and hello apps;list-app-versionstwo versions;list-platformssix triplets (hand-rolled table at the time, replaced by raw rows later — see the provisional-output note below);list-hostssix registered nodes;list-batchesthe remote-compute-node-join-proof batch (closed). - The compute grid is controlled by the system super admin, not by a
tenant; the
.envauto-login defaults (tenant_admin@acme_corporation) fail against this environment ("Auto-login failed", empty message), so the recipes and the live proof log in assuper_admin@localhost. All five library scripts run as authored against the current environment: connect, login, verb, logout — each renders its table with live data (2 apps, 2 app versions, 6 platforms, 6 hosts, 1 batch). - Recipes live in
doc/recipes/shell/compute/(one per verb), tangled intoprojects/ores.shell/scripts/library/compute/, indexed under the newComputesection ofdoc/recipes/shell/shell.org. - Provisional output (2026-08-10):
compute_platformis the one hand-written island in an otherwise codegen-owned component — every other compute entity is generated from a model org (ores.compute.modeling: domain type,*_table_io, protocol, repository, SQL), but platform predates the model migration and has no org and no table renderer. Rather than block the verbs on that drift,list-platformsprints raw rows (one platform per line, space-separated fields, no table formatting) until the Entity classification and drift baseline: ores.compute story generates the renderer. The story's reconciliation task then swaps the loop forout << resp->platforms, matching the other four verbs.
6. Test Scenarios
Manual QA scenarios (scaffolded via compass add test_scenario, run
through the QA Validation Runner panel) that verify this task. Link
new ones here as they're created; the scenario doc itself links back
via its "Verifies task" field.
| Scenario | State | Notes |
|---|---|---|
7. PRs
| PR | Title |
|---|---|
| #1992 | [ores.shell] Add compute grid management verbs to the shell |
8. Review
| # | Comment summary | File | Decision | Notes |
|---|---|---|---|---|
| 1 | canonical_result_id left uninitialized in dispatched workunits (5410154095) | compute_commands.cpp | Fixed | Set wu.canonical_result_id = uuid{}; mapper stores nil as NULL (dddb3ca710) |
| 2 | Batch marked dispatched before the workunit loop; partial failure strands it (5410154095, 5410154821, 5410160036) | compute_commands.cpp | Fixed | Status save moved after the loop; a partial failure leaves the batch open, re-dispatchable (dddb3ca710) |
| 3 | limit = 1000 with no pagination on list requests (5410154095) | compute_commands.cpp | Declined | Matches the existing convention in crm/provision/accounts commands; reviewer 2 checked and called it "Not a concern" |
| 4 | Hand-built input key bypasses the compute_storage helper (5410154095, 5410160036) | compute_commands.cpp | Partial | Comment documents the batch-scoped convention and the download-input reverse; an input_key helper for batch bundles is a follow-up |
| 5 | Smoke online-host snapshot taken after the drain loop exits (5410154095) | compute_commands.cpp | Fixed | Host set captured at the drain transition, not re-fetched (67406e0ea2) |
| 6 | PR traceability table points at the artifact-download task (5410154821) | PR body | Fixed | gh pr edit; body now cites the read-verbs task (7FB32716-261C-45D9-A5C9-6A43FF2AD6F5) |
| 7 | list-platforms header comment says "as a table" (5410159838) | compute_commands.hpp | Fixed | Comment now states provisional raw rows until the drift story lands table_io (01ad6a94e3) |
| 8 | is_online 90s window disagrees with the server's 5-minute grid-stats window (5410160036) | compute_commands.cpp | Fixed | online_window{300} aligned with ores_compute_grid_stats_fn_create.sql (67406e0ea2) |
| 9 | O(n×m) match in results_of_batch (5410160036) | compute_commands.cpp | Fixed | std::unordered_set<uuid> lookup, O(n+m) (01ad6a94e3) |
| 10 | dispatch-batch retry after a partial failure duplicates already-dispatched jobs (5411538471) | compute_commands.cpp | Declined | Inherent to the leave-open-and-redispatch design: a re-run mints job_count new workunits; accepted risk, documented in the reply |
| 11 | limit = 1000 without pagination on batch-scoped lookups (5411538471) | compute_commands.cpp | Declined | Same as row 3; tracked as follow-up (paginate_compute_list_requests.org) |
| 12 | delete-host docstring says 90s heartbeat window (5411538471) | compute_commands.hpp | Fixed | Doc now states 300s, matching online_window{300} (0dc9f4a13b) |
| 13 | Stale 90s heartbeat text in the header doc and the delete-host recipe (5411583598) | compute_commands.hpp, delete-host recipe | Fixed | Both now state 300 seconds (5 minutes), matching online_window{300} (0dc9f4a13b) |
| 14 | split_storage_uri hardcodes "api/v1/storage" (5412188603) | compute_commands.cpp | Fixed | Prefix derived from storage_paths::prefix, in sync with make_object_path (58761e0ffa) |
| 15 | Stale 90s heartbeat in the monitoring task doc Acceptance/Plan (5412188603) | task_grid-monitoring-verbs.org | Fixed | Aligned with the Result section's 5 minutes (0dc9f4a13b) |
| 16 | Smoke recipe variable INPUT_DIR stale for the tarball input (5418263168) | recipes, .ores scripts | Fixed | Renamed to INPUT_TARBALL in the smoke and dispatch recipes, retangled (bb0b13bcd7) |
9. Result
- Five read-only verbs shipped in
compute_commands.{hpp,cpp}:list-apps,list-app-versions,list-platforms,list-hosts,list-batches. All reuse existing NATS subjects and codegen table renderers; no backend or codegen changes. - All acceptance criteria met, verified live against brave_hopper: 2 apps, 2 app versions, 6 platforms, 6 hosts, 1 batch. Empty domains render a header-only table, not an error.
list-platformsprints provisional raw rows; the reconciliation task swaps the loop for the generatedtable_ioonce the drift story ships the platform renderer.- Five recipes added under
doc/recipes/shell/compute/, tangled intoprojects/ores.shell/scripts/library/compute/and indexed in theComputesection ofdoc/recipes/shell/shell.org.