Task: Bring ores.shell to the clean standard

Table of Contents

This page documents a task in the Clean ores.shell to the component clean standard story. It captures the goal, current status, acceptance, and any notes or results.

1. Goal

ores.shell passes the Component Clean Standard for a component of kind All.

2. Status

Field Value
State DONE
Parent story Clean ores.shell to the component clean standard
Now Nothing.
Waiting on Nothing.
Next Nothing.
Last touched 2026-09-23

3. Acceptance

  • Every checklist item that applies to a component of kind All passes, with its evidence recorded on the task.
  • Every item that does not apply is recorded as not applicable, with the reason.
  • Every generator defect found is fixed at its source, with a regression test.
  • ores.shell is listed in COMPONENTS_UNDER_TEST, and check_component_drift.py --all passes.

4. Plan

Work the Component Clean Standard in its section order, one entity at a time, and record each item's result in the table below.

  1. Baseline and inventory (B01 to B05). Record the baseline before any edit.
  2. Models (M01 to M10).
  3. Protocol (P01 to P06).
  4. Generation (G01 to G06).
  5. Wiring and data (W01 to W04).
  6. Shell (S01, S02).
  7. Structure and hygiene (H01 to H03).
  8. Verification (V01 to V06), ending with the registry entry.
Item Result Evidence
B01 Baseline recorded before any edit. Regeneration at every address reproduces the checked-in tree: no pre-existing difference, so any later difference is this work's. The model drift check is clean, with one known exception in ores.reporting that is not this component's. check_component_drift.py --component shell --dry-run reports "No drift: generated output matches the checked-in tree" at all six addresses. check_model_drift.py --summary reports "No model drift".
B02 One model in the shell's own modeling/ directory, component_overview.org, metatype ores.codegen.component. No entity, junction, operation, message, field group or module model. The Entity and Protocol sections therefore do not apply to a model of this component: every generated shell unit is output of another component's model, rendered into the shell's tree. grep '^#+type:' projects/ores.shell/modeling/*.org yields one line, ores.codegen.component.
B03 642 C++ files: 501 generated (334 non-test, 167 test) and 141 hand-written (120 non-test, 21 test). The hand-written remainder is the shell's own application surface and the component adapters the generation does not yet own, which is what S01 and G02 are about. File census over projects/ores.shell by the generated marker.
B04 Not applicable: a Protocol item, and the shell owns no subject. It is a client of every other component's protocol. Recorded rather than skipped, and the part of it that does apply is clean: the shell holds no raw subject literal outside generated code, so every subject it sends is a generated constant. grep for subject-shaped literals over the non-generated sources returns none.
B05 Recorded before any edit: the open captures and in-flight branches that touch this component are listed under Notes, with what each one means for this work. The Notes section of this task.
B06 No public symbol's only consumer is a test, so no dead public API. Every header of the shared surface has production consumers inside the component; none has a consumer outside it, which is what an application-internal component looks like. The shared surface is reachable only from the shell, and the build enforces that. Per-header census of projects/ores.shell/api/include against the production and test trees.
M01 Not applicable: an Entity item, and ores.shell has no entity model. B02.
M02 Not applicable: an Entity item. There is nothing to bind to a profile. B02.
M03 Not applicable: an Entity item. B02.
M04 Not applicable: an Entity item. B02.
M05 Not applicable: an Entity item. B02.
M06 Not applicable: a Protocol item, and no wire type belongs to this component. The units in its tree are other components' generated output. B02.
M07 Not applicable: an Entity item. B02.
M08 Not applicable: an Entity item. B02.
M09 Pass. No legacy fragment in the model: no Qt or Wt presentation drawer or property, no retired message type, no retired feature, no dead history property. grep over projects/ores.shell/modeling for the retired keywords returns one file, the component model, with no match.
M10 Pass. The component model is current, declares its parts, and its root CMakeLists.txt generates from it. validate_docs.sh; the ores.cmake address of the drift check.
P01 Not applicable: a Protocol item. B02.
P02 Not applicable, with the client-side half checked and clean under B04. B04.
P03 Not applicable: this component declares no subject. B02.
P04 Not applicable: it owns no operation model. B02.
P05 Pass, and it is the item this component feels first. Every consumer of a protocol change follows it in the same work, which for the shell means the generated unit and its recipe arrive in the same regeneration. The last change to the shell-command template took every one of the 167 generated units with it in one commit. The template change and the regeneration in PR #2272.
P06 Not applicable: the shell is an event consumer, not a cache. B02.
G01 Pass. Regeneration is byte-identical to the checked-in tree at all six addresses, and a second run changes nothing. check_component_drift.py --component shell --dry-run then --all, the second with shell listed.
G02 Pass with the reason recorded. No hand-written file here is superseded by generation today: no menu name is registered by both a hand-written and a generated unit, so the wholesale deletion the item asks for has no target. The fourteen hand-written trading instrument units are the shell surface of ores.trading entities whose models do not enable the shell facet, so generation does not supersede them yet; they are that component's S01, and the finding is recorded for it rather than absorbed here. The menu-ownership census: 30 hand-written-only names, 0 shared.
G03 Pass. Every generated file carries the marker and no hand-written file does. Marker census over projects/ores.shell: 0 generated without it, 0 hand-written with it.
G04 Not applicable: an Entity item, about the generated code reading like the component's best hand-written code. The code generated into this tree belongs to the entities' own components. B02.
G05 Pass, after one finding. The diagram parser dropped any declaration whose parameter list held a parenthesis, because the parameter pattern excluded them: a std::function or function-pointer parameter states a signature of its own there. ores.shell's shell_root_menu lost add_extension that way and the box read as the whole API. Fixed in the pattern, with four cases added to the codegen suite, and the diagram regenerated so the member now arrives from the header rather than from the manual pass. A facet of free functions arrives as nothing by design, which the standard records as the reason the manual pass exists, and the diagram states both facets as notes. build/scripts/generate_component_puml.py; test_plantuml_component_parse_nested_paren_param.py; the rendered image.
G06 Pass for this component. Its two CMake source lists were stale under the marker template and are regenerated; both now match the tree. Thirty-two further lists are stale tree-wide and belong to their own components. The item is a manual check: no workflow and no compass command runs the check, which is recorded as a gate gap. regenerate_cmake_component_files.py --component ores.shell.synthetic; --all --check for the tree-wide count.
G07 Pass, with the generator's own dry run read first as the item requires. The known parser defect does not reach this component: it fires on a one-line enum class in a header and the shell has none. The diagram was refreshed by hand and its rendered image read. grep for one-line enum class; the diagram diff and the image.
G08 Pass. The component keeps one namespace documentation header for its outermost namespace, and it carries the @brief doxygen renders. Its claim was stale and is corrected in place. Facet-header coverage is uneven across the tree and the item says filling those gaps is separate work. projects/ores.shell/api/include/ores.shell/ores.shell.hpp.
H01 Pass, with two parser gaps recorded rather than papered over. The diagram is authored in two passes. The automated pass is generate_component_puml.py, which reads a composite part by part and left twelve of the fourteen part diagrams stale: ores.shell.api had no shell_root_menu and still drew a class for history_diff_renderer, which is a facet of free functions with no class at all. Regenerated, and every manual section below the sentinel verified byte for byte before and after. The manual pass then filled what the parser cannot reach: shell_root_menu inherits cli::Menu from the third-party cli library, so the edge is drawn by hand; the parameter of add_extension is a std::function and the parser used to drop the whole declaration, which is fixed in G05 so the member arrives from the header; and both free-function facets, the three-function seam and render_history_diff, get notes because a class-only reading misses them. The rendered image was read, not merely regenerated. projects/ores.shell/*/modeling/*.puml and *.png; the sentinel-preservation check; the image.
H02 Pass. No Qt or Wt fragment survives, no TODO, FIXME, XXX or HACK, and no commented-out block. No hand-written duplicate of a generated artefact remains in the sense this item means: the duplicates the component held were the shadowed menus, and the last change removed them. Scans over projects/ores.shell for the Qt and Wt keywords, the marker words, and runs of three or more code-shaped comment lines.
H03 Pass. Comments sit above the code they explain, no comment narrates an edit, and no explanatory comment shares a line with code. The closing-brace annotation the project uses, such as } // anonymous namespace, is the one end-of-line form and is not an explanation. Scan for explanatory end-of-line comments and for commented-out code: none.
H04 Pass. No hand-rolled per-platform shim. No ORES_NO_UNIQUE_ADDRESS, no compiler-conditional block, and no bespoke unreachable. grep for the shim spellings.
H05 Pass, after six findings. Every component and every part of a composite carries an overview, and all fifteen carried the six sections the Guide requires. Six parts had no Diagram section at all (assets, dq, iam, refdata, storage, variability) and four had no rendered image (assets, compute, iam, refdata), so the section was added to the six and every part's diagram rendered. Each Diagram section now points at a committed image sitting beside its .puml source. Every diagram is refreshed in this pass because the code changed in the api and application parts. Two parts, reporting and variability, hold hand-authored .puml with no generator sentinel; the generator refuses to overwrite them, which is the right answer, and their images are rendered. Placeholder prose and empty bullets: none. The fifteen component_overview.org files and their .puml=/.png= pairs; validate_docs.sh reporting all 40 components pass.
S01 Not applicable: an Entity item, and this component has no entity. What it does hold is the shell surface of other components' entities, and G02 records where that work belongs. B02; G02.
S02 Not applicable: an Entity item. The recipe inventory is a gate nonetheless, and it passes. regenerate_shell_recipe_inventory.py --check, exit 0.
V01 Pass. The whole tree builds, with this component's tests and every consumer. A full cmake --build of the linux-clang-debug-make preset, exit 0.
V02 Pass. The codegen suite passes, and all fourteen of this component's test suites pass with the fleet up: 6,280 assertions over 2,796 cases. One case was red before this pass, and the finding was in the case rather than the code. The codegen suite at 906 case(s); the fourteen test_ores.shell.*.tests targets.
V03 Not applicable: an Entity item. B02.
V04 Not applicable: an Entity item. The generated commands replayed live are the entities' components' V04; this component's verbs were exercised live during the work. The live runs recorded in the commits.
V05 Pass for every gate this component can run. Component drift, the catalogue sweep, model drift, protocol twin coverage, handler permissions, populate references, the recipe inventory, test case reachability and registry exceptions are green. The CMake source list gate is green for this component and red tree-wide for thirty-two lists outside it. Each check script, run with shell listed.
V06 Pass. shell is listed in COMPONENTS_UNDER_TEST, and check_component_drift.py --all passes with it listed and leaves the tree clean. It is the first component of kind All to join. component_registry.py; the writing --all run.
V07 Pass after four findings, all in the seam suite this work added. Four cases asserted only that a call did not throw, so a claim_name that accepted every name would have passed them; they now assert a value. The one remaining match is a second assertion in a case that asserts a parsed vector equals a literal. The scan, and the suite at 83 assertions over 31 cases.
V08 Recorded, which is what the item asks. 52 source files have no test that matches them by name: the REPL host, the application entry point and the argument parser; the api helpers whose tests are named with an app_ prefix; and the hand-written command units, which are the coverage work item. The generated units are all covered. The per-file census under src against tests.

5. Notes

6. 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
     

7. PRs

PR Title
#2277 [codegen] Parse a parameter whose type carries parentheses
#2275 [shell] Bring ores.shell to the component clean standard

8. Review

Comment summary File Decision Notes
       

9. Notes

9.1. What the component is, and what that makes not applicable

ores.shell holds no entity, junction or operation model of its own. Its single model is component_overview.org, metatype ores.codegen.component, and every generated unit under projects/ores.shell/<component>/ is output of that other component's model, rendered into this tree.

Three consequences run through the whole checklist.

  • The Entity section (M01 to M10) is about this component's own models, and there are none. Each item is recorded not applicable with that reason rather than left blank.
  • The Protocol section (P01 to P06) is about the subjects this component owns. The shell serves none: it is a client of every other component's protocol. The items that speak of subjects this component declares are not applicable; the ones about consumers following a protocol change in the same work (P05) very much are, because the shell is the consumer that breaks first.
  • G01 has two halves. The shell's own models are already byte-identical, which the baseline proves. The generated units it hosts belong to their own components' G01, and a change to a shell-command template changes them all, which is why the codegen sweep exists.

9.2. Where the component sits under other components' work

The shell is the render target of twelve components' shell-command facets, so a model change anywhere reaches this tree. Twenty generated units right now carry their components' pending model drift rather than this component's: sixteen in refdata and four in synthetic, missing a party_id positional and stale usage text. Their own clean-up stories bring them current; regenerating them here would absorb another component's change.

9.3. The shadowing exception this branch supersedes

The registry carries an accepted exception on item S01 that reads "Four hand-written shell units survive and are registered after the generated aggregator, so some overlapping verbs are shadowed and the rest duplicate generated behaviour." That was true when it was written. Story 42C0752B, merged as PR #2272, removed the possibility: a second unit no longer registers a second menu, it extends the one that exists, and a duplicate name fails at startup. The exception's reason is now stale and belongs to whichever component it is filed on, which is not this one; this note is so the two are not read as agreeing.

9.4. Open captures and branches to avoid colliding with

  • doc/agile/product_backlog/inbox/two_components_register_the_same_shell_command_nam.org (207B3EA7) is closed by PR #2272 and can be retired.
  • commands-lost-their-only-recipe.org names four hand-written commands with no recipe, all in this component's surface.
  • compass-shell-load-exit-status-ignores-a-script-abort.org is about the scripted session path.
  • codegen-shell-recipe-sentinel-for-optional-columns.org is about the recipe template.

9.5. The largest hand-written block belongs to another component

Fourteen hand-written command units in application/src/app/commands/trading/ register the shell surface of ores.trading entities. Eleven of those entities have a model that does not enable the shell facet, and four have no model at all (commodity_instrument, composite_instrument, credit_instrument, scripted_instrument). Their verb set is a subset of what generation produces, and with a non-canonical spelling: get is a paged list where the convention gives get <key> for one row and list for the page.

So generation supersedes none of them today, and S01, the item that asks for them to be deleted, is an Entity item that applies to ores.trading rather than to the component that hosts their output. Enabling the facet on eleven trading models and writing four more is trading's work; ores.trading is in flight with one hundred and fifty-one files of regeneration, so it is not this branch's to start.

9.6. Two gate gaps the pass found

regenerate_cmake_component_files.py --check was red for thirty-two lists outside this component and green for the two inside it. No workflow and no compass command runs it, so the tree-wide staleness the standard already records is invisible to every gate.

generate_component_puml.py reads a composite part by part and leaves the composite's own diagram alone, which is why projects/ores.shell/modeling/ is hand-authored. Two parser gaps are recorded instead of worked around in the diagram text alone: a parameter whose type is a std::function with a comma in its argument list ends the member, and a facet of free functions arrives as nothing and used to arrive as a class that does not exist. Both are stated in the manual section of the diagram they affect, and the second is what H01's manual pass is for.

10. Result

Every item of the Component Clean Standard that applies to a component of kind All is worked and recorded in the table under Plan, with the evidence that proves it. Every item that does not apply is recorded not applicable with its reason, and the reason is the same for most of them: ores.shell has no entity, junction or operation model and owns no subject. Its one model is the component model, and every shell unit in its tree is output of some other component's model.

The component joins COMPONENTS_UNDER_TEST, the first of kind All to do so, and check_component_drift.py --all passes with it listed and leaves the tree clean. Every codegen gate this component can run is green. The whole tree builds, the codegen suite passes at 906 cases, and all fourteen of the component's test suites pass with the fleet up at 6,280 assertions over 2,796 cases.

What the pass changed, rather than confirmed:

  • Two CMake source lists were stale under the marker template, carrying no generated marker and a Qt reason in the test list's header.
  • Twelve of the fourteen part diagrams were stale; ores.shell.api had no shell_root_menu and drew a class for a facet of free functions that has no class. All twelve regenerated with their manual sections verified byte for byte, and the manual pass completed where the header parser cannot reach.
  • Six part overviews had no Diagram section and four parts had no rendered image at all. Both fixed; validate_docs.sh passes for all 40 components.
  • The diagram parser dropped every declaration whose parameter list held a parenthesis. Fixed in the pattern with four regression cases, and the member it had hidden now arrives from the header.
  • The namespace documentation header's brief described a shell of currency and account commands and named namespaces that do not exist.
  • One suite was red on a case that asserted a timestamp form the platform does not write. The finding was in the case, not the writer: five other suites in the tree assert the form the writer produces. The remaining finding is that to_iso8601_utc writes the relaxed separator its name disclaims, which is ores.platform's to settle.
  • Four cases in the seam suite asserted only that a call did not throw. They now assert values.

What this pass does not close, recorded rather than glossed:

  • The largest hand-written block, fourteen trading instrument units, belongs to ores.trading. Eleven of their entities have a model that does not enable the shell facet and four have no model, so generation supersedes none of them today and the item that asks for their deletion is trading's S01.
  • regenerate_cmake_component_files.py --check is red tree-wide for thirty-two lists outside this component, and no workflow and no compass command runs it.
  • The header parser arrives as nothing for a facet of free functions, which is by design rather than a defect: there is no class to draw, and the manual pass states the facet as a note. The other parser gap this pass found, a parameter whose type carries parentheses, is fixed with a regression test.
  • V08 is recorded rather than closed, which is what the item asks: 52 source files have no name-matched test and the list is the coverage work item.

Emacs 29.3 (Org mode 9.6.15)