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_summary carries tasks_failed (int, default 0) and max_task_duration_ms (std::int64_t, default 0), each documented for what the summary states rather than for what the sample stores.
  • get_grid_stats fills both fields on every node summary from the node's most recent sample, so the reply never drops them.
  • The shell's compute grid-stats node 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_failed and max_task_duration_ms to node_stats_summary in the telemetry model and regenerate the compute-cpp component.
  • Fill both in get_grid_stats from each node's newest sample.
  • Print both in the shell's compute grid-stats node 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 build exit 0 under linux-clang-debug-make.
  • ./compass.sh test run 94/94 passed, 0 failed (1089.62 s).
  • check_component_drift.py --all reports no drift.
  • pytest projects/ores.codegen/tests -q is 1288 passed with the two pre-existing test_check_subject_conformance failures about ores.iam.storage_capability_messages.org, unchanged by this task.
  • validate_docs.sh passes; check_prototype_inventory.py lists 46 prototypes.
  • The mapping was read on the live fleet. A row was inserted for the system tenant with tasks_failed 7 and max_task_duration_ms 9876, and compute grid-stats returned 11111111-2222-4333-8444-555555555555 3 7 3 111 9876 4096 2048 5 under 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.

Emacs 29.3 (Org mode 9.6.15)