Task: ores.shell: feed verbs for every asset class
Table of Contents
This page documents a task in the Feed lifecycle harmonization: asset-class-agnostic feed control-plane story. It captures the goal, current status, acceptance, and any notes or results.
Goal
ores.shell has feed verbs for every asset class: folder start/stop (one request, server-side cascade) and per-config start/stop/list keyed by config_id — including the IR curve commands that are missing today. No shell command enumerates asset classes; new asset classes are covered automatically via the factory.
Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Feed lifecycle harmonization: asset-class-agnostic feed control-plane |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-08-11 |
Acceptance
- synthetic start folder <token> and synthetic stop folder <token> cascade every feed kind under the folder.
- synthetic start feed <config_id> / stop feed <config_id> / list feeds work for every asset class (IR curve start/stop/list were previously unreachable from the shell).
- Feed lookup by name/token resolves to a config_id without the shell knowing the kind.
- Command help and completion are kind-agnostic.
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.)
The folder cascade (task 9E2344CF) already covers both asset classes server-side; the shell's folder verbs need no change. The per-config verbs need a kind-agnostic token resolution and a list verb.
resolve_feed(synthetic_commands.cpp) becomes kind-agnostic: it probes the FX config family first, then the IR curve family — mirroring the server's own kind resolution infeed_config_handler, which probes the per-kind repositories byconfig_idwith FX first. It returns aresolved_feed{config_id, source_name, optional ore_key}; the shell never knows the kind. UUID tokens match config ids across both families ("Feed not found" after both probes); name tokens match FX ore_key/source_name then IR source_name, withreport_ambiguousper family and "No feed matching" after both.start feedandstop feedsend the resolvedconfig_idinstart_feed_request/stop_feed_requestas before — the requests were already kind-agnostic. Only the token resolution changed.- New
synthetic list feedsverb:process_list_feeds=/=list_feedssendlist_feeds_request{}and print each running feed'ssource_nameplus the running count. The response carries no message field, so failure prints a generic message. validate-vintagestays FX-shaped:get_vintage_validityentries are keyed by fx config id, so only FX feeds can match one; IR curves report no entry. The ore key renders only when present.- Help and completion were already kind-agnostic: the start/stop
usage string is "folder <folder-token> | feed <feed-token>" and
cli::Menu completion completes command names only. The
list feedshelp text says "of every asset class".
Notes
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 |
|---|---|---|
PRs
| PR | Title |
|---|---|
| #1973 | [shell] Feed verbs for every asset class |
Review
| # | Comment summary | File | Decision | Notes |
|---|---|---|---|---|
| 1 | resolve_feed skips the success check on the FX/IR list responses; a backend failure reads as "No feed matching" | synthetic_commands.cpp | Applied | success guard added after each probe, mirroring list_folders/list_configs. Raised by both review passes. |
| 2 | The exact-match and ambiguity blocks are duplicated across the FX and IR probes | synthetic_commands.cpp | Applied | factored into exact_feed_match and feed_by_id; try_uuid hoisted above both probes. Raised by both review passes. |
| 3 | try_uuid(token) parsed twice, once per probe | synthetic_commands.cpp | Applied | hoisted in the same refactor as row 2. |
| 4 | Cross-family ambiguity unchecked for exact-name tokens; the FX match wins silently | synthetic_commands.cpp | Declined | FX-first mirrors the server's kind resolution (documented in resolve_feed); the server resolves the same config_id to the FX feed, so the win is consistent. A guard would add an IR round-trip to every FX match for a collision the naming conventions make unreachable. |
Result
The shell's feed verbs now cover every asset class. Folder start/stop
already cascaded both kinds server-side (task 9E2344CF) and needed no
change. Per-config verbs gained a kind-agnostic token resolution:
resolve_feed probes the FX config family first, then the IR curve
family — the server's own kind resolution in feed_config_handler
probes the repositories in the same order — and returns a
resolved_feed{config_id, source_name, optional ore_key}; the shell
never knows the kind. start feed and stop feed send the resolved
config_id; validate-vintage keeps its FX shape (entries are keyed
by fx config id, IR curves report no entry, the ore key renders only
when present). The new synthetic list feeds verb sends
list_feeds_request{} and prints every running feed's source_name
plus the running count — the IR curve start/stop/list verbs that were
previously unreachable from the shell. Help text and completion were
already kind-agnostic and remain so; the list feeds entry says "of
every asset class".
Verification: full build green; no SQL change, so no DB recreate;
compass build rat green (all suites pass, including the synthetic
service feed_config_* cases).