feat(forge): ForgeRecipe + ForgeArtifact Rust types (Phase 1a of #1164)#1170
Merged
Conversation
Implements Phase 1a of the design at docs/architecture/FORGE-RECIPE-AS-ENTITY.md (continuum#1165). Pure value types only. What ships: - ForgeRecipe entity (authored input): identity, prose, methodology, source, pipeline (stages opaque JSON for v1), calibration corpus, top-level quant tiers, evaluation benchmarks, hardware, lineage. - ForgeArtifact entity (foundry output): snapshot of recipe fields and execution outputs (forged_at_ms, duration, params_b, hardware_verified, alloy_hash, results/receipt/integrity opaque JSON for v1). Recipe lineage frozen so later recipe edits cannot retroactively rewrite what the artifact claims. - Supporting types: AlloySource, PriorBaseline, CorpusRef (canonical sha256 hex matching admission), QuantTier, BenchmarkDef, AlloyHardware, HardwareProfile. - ts-rs bindings to shared/generated/forge/ (9 files plus barrel). Tests: 26 passing covering serde roundtrip, minimal recipe with defaults, opaque blob preservation, partial artifact, recipe lineage immutability, ts-rs binding generation. Barrel-sync ratchet from PR #1137 still green. Phase 1b: rename existing TS-side ForgeAlloy to ForgeArtifact (15 files, separate slice). Phase 2: typed RecipeStage enum and typed results/receipt/integrity. Phase 3: entity registry plus forge/run IPC. Card: continuum#1169. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
joelteply
added a commit
that referenced
this pull request
May 14, 2026
…ct (#1164 Phase 1b) (#1171) Per the consensus on continuum#1165 (design doc), the existing single-entity 'ForgeAlloy' name splits across two roles: - 'ForgeRecipe' (the authored input — what stages, prose, methodology, hardware target). All 14 stage-element widget JSDoc references update here: 'Maps 1:1 to ForgeAlloy XStage schema' becomes 'Maps 1:1 to ForgeRecipe XStage schema', and 'Each ForgeAlloy stage type' becomes 'Each ForgeRecipe stage type'. The stage widgets are recipe-authoring UI; stages live on the recipe side. - 'ForgeArtifact' (the foundry output — what got measured, hardware verified, alloy hash, publication receipt). FactoryStatsWidget's 'X / Y models have an alloy' panel relabels to 'ForgeArtifact' because the panel counts published artifacts, not authored recipes. Pure rename — no behavior change. The Python forge_alloy/types.py is untouched (Phase 2 ports those types to Rust as the source of truth); TS code only references the entity names in JSDoc + UI labels, never imports them as types. Validation: - grep ForgeAlloy in src returns 0 results - npm run build:ts passes clean - Hooks ran without --no-verify Card: continuum#1170 (PR #1170 was Phase 1a; Phase 1b card is created per the airc queue lane named 1170-pr-phase1b — the CI auto-close will land on whatever issue # this PR opens against). Co-authored-by: Test <test@test.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
joelteply
added a commit
that referenced
this pull request
May 14, 2026
#1164 Phase 3) (#1180) Phase 3 of continuum#1164 (design at FORGE-RECIPE-AS-ENTITY.md). TS-side entity classes that wrap the Rust ts-rs types from #1170 (Phase 1a) + register both with the data daemon's EntityRegistry so callers can CRUD forge recipes + artifacts via the standard data/* commands. What ships: - src/system/data/entities/ForgeRecipeEntity.ts — class extending BaseEntity, mirrors the ForgeRecipe Rust shape with field decorators (TextField, JsonField, NumberField). validate() checks required fields. Collection: 'forge_recipes'. - src/system/data/entities/ForgeArtifactEntity.ts — class extending BaseEntity, mirrors ForgeArtifact. ForeignKeyField on recipeId + unique-indexed alloyHash for content-addressable lookup. validate() checks lineage + execution-time fields. Collection: 'forge_artifacts'. - EntityRegistry.ts — imports both entity classes, instantiates each during initializeEntityRegistry() so the decorators register metadata, then registerEntity() with the collection name. Same pattern as the existing entity bulk. - shared/generated/entity_schemas.json regenerates with the two new collections (sha goes from 8cf44380640f to d5c1cff2a1ed6a6c, entity count 55 -> 57). Field naming subtlety: Rust 'version: string' (semver) collides with BaseEntity 'version: number' (ORM row version). Renamed to 'recipeVersion: string' on the entity to avoid the conflict + leave both cross-layer fields workable. Doc-comment notes the drift; Phase 2+ may rename the Rust field for cross-layer alignment. Validation: npm run build:ts clean. Hooks ran without --no-verify. Phase 4 (next slice): forge/run IPC handler that takes a recipeId, runs the foundry pipeline, persists the artifact via data/* commands. Card: continuum#1180. Co-authored-by: Test <test@test.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements Phase 1a of the design at
docs/architecture/FORGE-RECIPE-AS-ENTITY.md(continuum#1165). Pure Rust value types for the recipe-as-entity layer — no rename of existing TS-sideForgeAlloyyet (Phase 1b), no entity registry hookup yet (Phase 3), no foundry executor yet (Phase 2).Card
continuum#1169.
What ships
ForgeRecipeentity (authored input): identity, prose, methodology, source, pipeline (stages opaque JSON for v1), calibration corpus, top-level quant tiers, evaluation benchmarks, hardware, lineage.ForgeArtifactentity (foundry output): snapshot of recipe fields plus execution outputs (forged_at_ms, duration, params_b, hardware_verified, alloy_hash, results/receipt/integrity opaque JSON for v1). Recipe lineage frozen so later recipe edits cannot retroactively rewrite what the artifact claims.AlloySource,PriorBaseline,CorpusRef(canonical sha256:hex matching admission's content_hash format),QuantTier,BenchmarkDef,AlloyHardware,HardwareProfile.shared/generated/forge/(9 files + barrel).Validation
26 unit tests covering serde roundtrip, minimal recipe with serde defaults, opaque blob preservation, partial artifact (None results), recipe lineage immutability, ts-rs binding generation. Barrel-sync ratchet from #1137 still green (the 9 new .ts files are correctly referenced from
shared/generated/forge/index.ts).npm run build:tsclean.cargo clippyclean (160 warnings, baseline 163 — 3 below). Hooks ran without--no-verify.Phase plan (per design doc)
ForgeAlloy→ForgeArtifactacross the 15 referencing files (separate slice)RecipeStageenum (currentlyVec<serde_json::Value>) + typedAlloyResults/AlloyReceipt/IntegrityAttestation(currentlyserde_json::Valueblobs)forge/runIPC handlerTest plan
🤖 Generated with Claude Code