feat(recipes): parse Eco's AutoGen C# into the vendored recipe graph #245
No reviewers
Labels
No labels
burndown-2026-06
headless
autonomy
async-consult
autonomy
epic
autonomy
headless
autonomy
live-collab
c#
priority
P0
priority
P1
priority
P2
priority
P3
priority
P4
role/ai
role/creator
role/design
role/director
role/engineer
role/exec
role/human
role/ops
role/qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
coilyco-gaming/eco-app!245
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/autogen-recipe-index"
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?
What
Parses Eco's own generated C# into the vendored recipe graph, replacing the Eco Gnome export as the primary source. Implements the decision on #242.
Eco's dedicated server ships
Mods/__core__/AutoGen— one plain C# file per recipe, item, skill, and tag, emitted fromRecipeTemplate.tt. It is downloadable withsteamcmd +login anonymous +app_update 739590: an anonymous-login depot, so no Steam account and no game licence, confirmed by SLG on the official Steam discussions. That makes it the only vanilla source carrying every DTO field at once — including a crafting station and a real craft time for every recipe, which the Gnome export does not have.What's here
src/eco_mcp_app/autogen.py— the parser. Regex over the generated shapes, no .NET anywhere in the pipeline.scripts/autogen_refresh.py+ward exec autogen-refresh— the maintenance verb that regenerates the vendored index. Downloads the server, or takes--rootfor a tree already on disk.data/eco_autogen_data.json— the vendored index, plus.SOURCE.txtrecording provenance and the SLG copyright.recipes.load_recipe_index()prefers it, falling back to the Gnome seed.tests/mcp/test_autogen.py— 12 tests over miniature fixtures.Verification
Parsed from Steam build 24618181 (Eco 0.13.0), 2,284 source files:
1,487 recipes / 44 skills / 112 tags / 1,323 products / 68 stations, zero warnings.
Every recipe has a station, a non-zero labor cost, and a non-zero craft time. Every tag ingredient resolves to a known tag. Independent cross-check:
Eco.ReferenceAssembliesat the same version declares 1,088 directRecipeFamilysubclasses and the tree has 1,122; the Gnome seed has 1,453 recipes and 43 skills against our 1,487 and 44.ward exec lintclean (ruff + format + mypy, 110 files).ward exec smokepasses. 630 tests pass — see the caveat below.Three things worth reviewing
Tag-product variants inherit family cost. A
class X : Reciperegistered viaAddTagProductdeclares only its own ingredients; Eco applies the owning family's labor and craft time at craft time. Left unresolved, 365 of 1,487 recipes would report a free, instant craft — a plausible-looking answer that is wrong, the class of defect #240 catalogued. The parser pushes the family's values down, and warns rather than silently zeroing when a family is missing.Two parse bugs that only surfaced under test. Eco emits three
CreateCraftTimeValueshapes and the 0.13 named form neststypeof(...)inside the call, so a regex stopping at the first)reads nothing — hence the paren-balanced argument scan. Separately, generated attributes combine on one line ([RequiresSkill(...), Tag("..."), Tier(3)]), so anchoring a pattern on[drops every attribute after the first; that one was caught by a failing assertion, not by reading the source.Vendored, not fetched at build time. Per the #105 finding. It does mean ~1.6 MB of SLG-derived game data in the repo.
eco_gnome_data.jsonset the precedent and/preview/recipes.jsonalready serves this class of data publicly, so the exposure category is unchanged — but it is SLG's proprietary content with no licence grant, unlike the MIT Gnome file, so flagging it explicitly rather than burying it..SOURCE.txtstates this.Caveat
tests/discord/test_worker.py::test_worker_uses_only_non_privileged_intentsfails, and it fails on cleanmaintoo — verified in a detached worktree atorigin/main. It passes in isolation and fails in a full-suite run, so it is a test-ordering/isolation issue, pre-existing and unrelated. Happy to file it separately.Not in this PR
The MCP tools themselves (
get_recipes,price_recipe,get_skillsviaDualRouteRegistry, step 4 of the #242 plan). This lands the data layer, which already upgrades the existing/preview/recipes.jsonplane. The tools are a focused follow-up on top.Also unchanged:
data/eco_gnome_data.jsonstays as the fallback. Removing it is a separate call once the AutoGen graph has run for a while.Refs #242
Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com
Pushed two changes since the first review pass.
The graph now ships gzipped
data/eco_autogen_data.json.gz, 1.6 MB → 125 KB. It was putting 73k lines into everygit diffand hitting everyrgfor an item or recipe name. The reviewable diff on this PR drops from 73,937 insertions to 1,163 as a result.The loader gunzips in place.
mtime=0keeps the gzip header from adding nondeterminism on top of the payload's ownfetchedAtISO.data/eco_autogen_data.SOURCE.txtcarries the two one-liners for reading it back (gzcat … | jq, orgzip.openfrom Python).Two things fell out while making the change:
warningsthat it fell back. Silently serving the older graph would be worse than failing.631 tests pass,
ward exec lintandward exec smokeclean.Correction on the licensing note
The PR body says the exposure category is unchanged because
eco_gnome_data.jsonset the precedent. That was too comfortable, and I checked properly. The Eco EULA says:and
A parsed index of the recipe definitions is a derivative work of a component of the Software, redistributed. There is also no LICENSE file in the server root, despite every AutoGen header saying "See LICENSE file in the project root."
Against that: SLG ships the server free on an anonymous depot, supports modding with free API and tooling, and their own
Mods/UserCode/README.mdtells you to "just copy the original file" when overriding a recipe. The ecosystem — Eco Gnome's DataExporter, the official wiki — publishes derived recipe data openly and unchallenged. That is tolerance in practice, not a grant. And Eco Gnome licensing their file MIT gives neither them nor us rights over SLG's underlying data, so the precedent is thinner than the PR body implies.Nothing here resolves that, and the gzip does not either — it is an ergonomics change, not a rights one, and it is trivially reversible with the parser and provenance file sitting next to it. Recorded so the decision to merge is a visible one. The cleanest fix remains generating the index at build or first boot from a server copy the operator already has, which keeps the parser (entirely our code) in the repo and the derived data out; that stays available as a follow-up if the licensing question ever gets sharp.