Bottom-up cost roll-up engine (recipe BOM -> cost/margin) - follow-up C from #98 [depends on A] #102
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The bottom-up cost roll-up engine from the #98 design: the piece that turns recipe definitions into a per-item cost, so margin and "is this worth crafting" become answerable. This is follow-up C.
Depends on #98-A (the recipe BOM data). Do not start until A has landed.
Scope
market.pymedian) + labor (calories) + calorie cost + time, following the ingredient edges A exposes. Handles recipe variants and category/tag inputs, guards against cycles, and degrades gracefully when a leaf has no market price (surface it as "unpriced input", do not silently zero it).cost.pymodule + whatever/preview/*.jsonfield the recipes page and pricing page read).Done
Unit-tested under
tests/(fixture recipes with known BOMs, including a multi-level tree and an unpriced-leaf case). Green onward exectest + lint. Updatedocs/FEATURES.mdif it adds a surface. Full design context and the "valuable" definition it feeds on #98.🔒 Reserved by
ward agent --driver claude— containerengineer-claude-eco-app-102on hostKAI-DESKTOP-TOWERis carrying this issue (reserved 2026-07-07T07:17:19Z). Concurrentward agentruns are blocked until it finishes or the reservation goes stale (2h0m0s TTL);--forceoverrides.Do not comment on or edit this issue to steer the run while it is reserved. The engineer seeded the body once at launch and never re-reads it, so a comment or edit reaches only human readers, never the running engineer. A correction goes to a new issue, dispatched fresh — that is the only channel that reaches a run in flight. Where the forge supports it, ward locks this conversation to make that a road-block rather than a convention (ward#494).
run seed context — what this run is carrying (ward#609)
coilyco-gaming/eco-app#102· branchissue-102· driverclaude· workflowdirect-mainengineer-claude-eco-app-102· wardv0.419.0· dispatched2026-07-07T07:17:19ZIssue body as seeded:
Static container doctrine and seed boilerplate are identical every run and omitted here (they ride ward v0.419.0).
— Claude (she/her), via
ward agentWARD-OUTCOME: done - cost.py roll-up engine + /preview/recipes.json?cost=1, merged to main (
c1d504a)This one was mostly a design problem wearing an implementation problem's clothes. The recursion, cycle guard, and tag/variant handling were straightforward once the make-or-buy framing clicked. What actually fought back was the cost decomposition: I went around twice on whether labor/calories should roll up full-tree or per-recipe, because the money and the reported calorie figure kept ending up at different scopes. Landed on: money is fully recursive (a crafted sub-ingredient's whole cost, labor included, is inside its make-or-buy price), while the top card's laborCost/laborCalories report just that recipe's marginal step. Clean and consistent, but it took a rewrite to see it.
The #98 design deliberately left caloriePrice/minutePrice unquantified, so I made them caller-supplied and defaulting to 0 rather than inventing a number - the raw calorie/minute totals always ride the payload, money only monetizes when a rate is given. That felt like the honest call but it means margin-by-default is ingredient-only until D/E pass a rate.
Confidence is high on the engine: it's pure, and the route test annotates all 1,453 real recipes without hanging, which is the real cycle/scale proof. Hit a merge conflict in FEATURES.md against #101 (the recipes browse page, B) - both wanted the same slot; kept both, ordered A->B->C.
Rough edges worth filing: byproducts aren't credited against primary cost yet (conservative over-estimate), and there's no frontend surface here - the pricing page (E) and value-per-profession (D) are where this actually gets seen. tableTierRequired is still null; C was expected to derive it but that's a separate concern from cost roll-up and I left it untouched.