Task: Keep the failure fields on the node summary
Table of Contents
This page documents a task in the Implement the operations journeys in ores.web story. It captures the goal, current status, acceptance, and any notes or results.
1. Goal
The node sample carries the count of failed tasks and the longest task the
node ran: tasks_failed and max_task_duration_ms. The reply's per-node
summary, node_stats_summary, carries neither, so both fields are stored and
dropped on the way out — and a node failing every task reads as a node doing
nothing
(The node summary drops the failure fields).
This task carries both fields into node_stats_summary, so the node row
states the failures beside the completions.
2. Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Implement the operations journeys in ores.web |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-10-07 |
3. Acceptance
node_stats_summarycarriestasks_failed(int, default 0) andmax_task_duration_ms(std::int64_t, default 0), each documented for what the summary states rather than for what the sample stores.get_grid_statsfills both fields on every node summary from the node's most recent sample, so the reply never drops them.- The shell's
compute grid-statsnode table prints both fields beside the completions, and the table's header row names both columns. - The capture The node summary drops the failure fields moves out of the inbox with this task's evidence.
4. Plan
- Add
tasks_failedandmax_task_duration_mstonode_stats_summaryin the telemetry model and regenerate thecompute-cppcomponent. - Fill both in
get_grid_statsfrom each node's newest sample. - Print both in the shell's
compute grid-statsnode table and name them in its header row. - No handler unit test: the class is header-only with an injected NATS client and inline repositories, so the mapping has no seam. Verify it on the live fleet instead, and write plainly in the Result what stays unproven.
5. Measurements
Every number this task claims about a tree, with the command that produced it
and the commit it was measured at. A number without both is not a measurement,
because a clean-up record describes a tree and trunk moves under a branch: a
consumer count, a gate's component count and a suite's size all change with no
code changing, and the reader of a bare number cannot tell which tree it came
from. Where the raw output matters, put it in an evidence/ file beside the
task and name that file in the Command column.
| What | Value | Command | Commit |
|---|---|---|---|
| Build (linux-clang-debug-make) | exit 0, every target built | ./compass.sh build |
379132dbce |
| Test suite | 94/94 passed, 0 failed, 1089.62 s | ./compass.sh test run |
379132dbce |
| Component drift | No drift | check_component_drift.py --all |
379132dbce |
| Codegen suite | 1288 passed, 2 pre-existing failures | pytest projects/ores.codegen/tests -q |
379132dbce |
| Docs validation | 42/42 components pass | validate_docs.sh |
379132dbce |
| Prototype inventory | 46 prototypes, all listed | check_prototype_inventory.py |
379132dbce |
6. Notes
7. Test Scenarios
Manual QA scenarios (scaffolded via compass add test_scenario)
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 |
|---|---|---|
8. PRs
| PR | Title |
|---|---|
| #2774 | [compute,shell] Keep the failure fields on the node summary |
9. Review
| # | Comment summary | File | Decision | Notes |
|---|---|---|---|---|
| 1 | The new doc comments restate the sample's fields | ores.compute.telemetry.org |
Accepted | Re-phrased to the summary's voice and regenerated. |
| 2 | The capture carried no Resolution section | discarded/the_node_summary_drops_the_failure_fields.org |
Accepted | Added a Resolution naming the task and its evidence. |
| 3 | The journey's missing-failures item is now stale | journey_watch_the_compute_grid.org |
Declined | Journey documents are the extraction pass's, per the story's Out of scope; the grid-read task left item 1 in the same state. |
| 4 | The STARTED commit lands after the implementation | — | Declined | Bookkeeping order only; the code commit is the change and the history stands. |
| 5 | The header row is raw snake_case and unaligned | compute_commands.cpp |
Declined | The preliminary table is space-separated with no alignment to break. |
10. Result
All four acceptance bullets hold. node_stats_summary declares both fields with
their defaults; get_grid_stats sets s.tasks_failed and
s.max_task_duration_ms from each node's newest sample; the shell's node table
prints both beside the completions and its new header row names them; and the
capture moved to the discarded bucket with this task's evidence.
Verified:
./compass.sh buildexit 0 underlinux-clang-debug-make../compass.sh test run94/94 passed, 0 failed (1089.62 s).check_component_drift.py --allreports no drift.pytest projects/ores.codegen/tests -qis 1288 passed with the two pre-existingtest_check_subject_conformancefailures aboutores.iam.storage_capability_messages.org, unchanged by this task.validate_docs.shpasses;check_prototype_inventory.pylists 46 prototypes.- The mapping was read on the live fleet. A row was inserted for the system
tenant with
tasks_failed7 andmax_task_duration_ms9876, andcompute grid-statsreturned11111111-2222-4333-8444-555555555555 3 7 3 111 9876 4096 2048 5under the header row; the row was then deleted.
A local review round re-phrased the two summary doc comments, which had restated
the sample's fields, and added a Resolution section to the capture; both were
regenerated. The change's other class checks also pass: site page publishes
998 files with 0 failures, tangle leaves projects/ores.shell/scripts/library
clean, and the cmake-sources, paste-block, handler-permission,
test-case-reachability, populate-reference, pattern-uses and catalogue-sweep
checks are clean. The four declined review findings sit in the Review table.
What is not tested: the handler has no automated test. It is header-only, holds
an injected NATS client and a database context, constructs its repositories
inline, and replies over NATS, so no test can call the mapping without a live
broker and database. A model test would only assert that the generated struct
declares the fields, which would still pass if get_grid_stats dropped both
assignments, so none was added. The live read above is the proof; a future edit
that removes the two assignments would fail no automated test.
Environment note: the mandated compass db recreate -y -k left the database
unprovisioned. The standard Acme provisioning created the initial super_admin
but its system_provision step never answered
iam.v1.ops.provision_tenant_step and timed out after 20 minutes, so the Acme
tenant is not fully provisioned. The iam service journal shows no error. The
change touches compute telemetry only, so this is not its cause; it was reported
rather than chased.