Task: Run a report from its page and read its rows

Table of Contents

This page documents a task in the Prove the report grid run end to end — the remaining work story. It captures the goal, current status, acceptance, and any notes or results.

1. Goal

A reader can start a run where the report is defined, watch it reach the grid, and open what it produced without leaving the reporting area.

2. Status

Field Value
State DONE
Parent story Prove the report grid run end to end — the remaining work
Now Nothing.
Waiting on Nothing.
Next Nothing.
Last touched 2026-10-27

3. Acceptance

  • The report definition page states a Run action that triggers a run and shows the new run in the runs list.
  • The runs list states the run's state as it moves through the pipeline, and the run page names the compute batch and its jobs.
  • The results screen draws from ores_reporting_report_result_rows_tbl, and nothing in the request path parses npv.csv.
  • A manual test scenario walks the whole path: run, grid, jobs, results.

4. Plan

(Implementation strategy. Written when work starts; key decisions are distilled into the parent story's * Decisions at close, but the plan itself stays — it is the historical record of what we did.)

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
Rows the table holds for run e31abdee-0dbe-404c-977d-80539b44fe17 24, which is 8 trades for each of npv, npv_base and notional compass sql -- -c "select measure, count(*) from ores_reporting_report_result_rows_tbl where report_instance_id = 'e31abdee-0dbe-404c-977d-80539b44fe17' group by measure" 3ffd149319
NPV of that run 40,960,906.05 HKD at 2026-05-05; its notional is 38,322,972.60 compass sql -- -c "select measure, sum(figure)::numeric(24,2) from ores_reporting_report_result_rows_tbl where report_instance_id = 'e31abdee-…' group by measure" 3ffd149319

6. Notes

  • compass sql describes the row set of every run that post-processed on this environment, so four runs each carry the same 24 rows. Only one of them was triggered from the report page.
  • The entity's codegen drift is not clean. check_component_drift.py --component reporting reports twelve untracked files it would materialise: the eventing header, the generator header and source, the CRUD handler and registrar, the history field mapper, the service, and the service-side event registrar for report_result_row. The generated CRUD service cannot serve this entity, so those layers were left out of the branch; the generator still emits them. The codegen drift job did not catch it because codegen-drift.yml does not watch projects/ores.reporting/modeling/. This is follow-up work: either the model states the layers it does not generate, or the job watches the model.

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
Run a report and read its rows BACKLOG The six-step path: run, follow, read.
Run a report through the grid and read every result BACKLOG Twelve steps from the page to the rows in the store, marked swift_curie.

8. PRs

PR Title
#3929 [web] Run a report from its page and read its rows

9. Review

# Comment summary File Decision Notes
1 The row limit and offset are ignored, so the read is unbounded, and total is the returned count rather than the true one run_result_rows_handler.cpp, grid-report-results.ts Fixed The BFF sends limit: 20000 and the service reads every row of the run. The number is about three per trade, so a large run is an unbounded reply on one NATS subject. Fixed in #3986: The generated service applies offset and limit and answers total from get_total_row_count.
2 The handler drops the filter members it accepts run_result_rows_handler.cpp Fixed It reads only filter->report_instance_id; measure and measure_one_of are ignored, and report_instance_id_one_of with them. Fixed in #3986: The generated service applies every filter member, measure and the *_one_of lists included.
3 Neither the handler nor the BFF checks a read permission run_result_rows_handler.cpp Fixed make_request_context authenticates the caller and nothing checks a permission. The generated CRUD handler is the reference. Fixed in #3986: The generated handler checks reporting::report_result_rows:read, and the permission is seeded and granted to Member.
4 Dead constants and a dead route remain in the BFF grid-report-results.ts Fixed The TAR_* constants are still defined and nothing uses them. Fixed in #3986: The TAR_* constants are removed.
5 Shared repository helpers were renamed in a generated file report_result_row_repository.cpp Resolved The file carries the generated marker, and the prefixed names are what the generator emits for this entity. The drift check runs clean on the files that are committed; what it does report is the twelve missing layers, recorded under Notes.
6 Minor points: include order, the counterparty refusal, the silent trigger failure, job_instance_id: 0, and the missing BFF test several Partially Recorded as written; none blocks the feature. Fixed in #3986: the include order.

10. Result

Merged as #3929. A person starts a run from the report definition's own page, the page lists the new run, the run page names its state and the batch and jobs it reached, and the results screen draws from ores_reporting_report_result_rows_tbl. The request path no longer parses an archive: the BFF asks reporting.v1.report_result_rows.list for the run and the service reads the rows by run.

The review found no blocking defect. Two of its points are settled: the value the post-processor writes is the figure the screen draws, and point 5 is generation, not hand-editing. The other four stand, and the run should be read with them in mind: the read returns every row of the run with no bound, four filter members are ignored, no permission is checked, and the BFF keeps dead tar constants. They are recorded in * Review for follow-up work.

One defect was found after the merge and is recorded under Notes: the entity's generation is not fully committed, so check_component_drift.py --component reporting fails on twelve untracked files. The drift job did not see it because it does not watch projects/ores.reporting/modeling/.

Emacs 29.3 (Org mode 9.6.15)