How Molds become cast artifacts. Anchored to the file layout in architecture (molds/<name>/ -> casts/<target>/<name>/). Working premise: deterministic assembly first, LLM second, reproducible enough to diff. In this Foundry the deterministic half reaches all the way — there is no LLM phase, every reference is copied or built mechanically, and a re-cast of an unchanged Mold is byte-identical. That is what makes --check a gate rather than a diff review.
What casting is
Casting takes a Mold (a typed reference manifest plus a procedural body), its artifact IO contracts, and its declared references — pattern pages, CLI manual pages, IO schemas, prompt fragments, examples, and operational research notes — and produces a target-specific cast artifact. mold-spec owns the source-layout and manifest contract; this document describes how casting consumes that contract. The cast is isolated — no links back to the Foundry, no runtime dependency on it.
For the Claude target, SKILL.md is always rendered from Mold source. The renderer combines the Mold summary, input_artifacts[], output_artifacts[], inherited producer/schema metadata, resolved references[], and the procedural body of index.md. Generated skill bodies are not hand-maintained; if a cast looks under-instructed, improve the Mold body or referenced notes and re-cast.
Casting operates as per-kind dispatch over the manifest, not a single resolve-and-inline pass. Different reference kinds get different transformations:
| Reference kind | Source location | Casting transformation | Lands at | Status |
|---|---|---|---|---|
pattern | content/patterns/*.md | Verbatim copy; may carry per-note companions | references/patterns/<slug>.md | v1 |
cli-command | content/cli/<tool>/<cmd>.md framing note plus registered upstream CLI metadata | Deterministic JSON sidecar sourced from registry metadata + framing markdown | references/cli/<slug>.json (flat — <slug> is the source basename) | v1 |
schema | [[wiki-link]] to a type: schema note in content/schemas/. The note declares package + package_export; cast imports the named runtime export at build time and serializes it. Foundry-authored: schemas in packages/<name>-schema/src/<name>.schema.json (e.g. summary-nextflow, galaxy-tool-discovery). Vendored: schemas synced from upstream packages into packages/<name>-schema/src/ (e.g. tests-format from @galaxy-tool-util/schema). | Verbatim copy of the imported export, JSON-serialized | references/schemas/<note-slug>.schema.json | v1 |
research | content/research/<slug>/index.md plus any companion files in that directory | Verbatim copy | references/notes/<slug>.md for the note; each companion keeps its own filename | v1 |
prompt | content/prompts/<area>/<slug>/index.md wrapper note plus its upstream.prompt companion | Raw prompt sidecar copied verbatim | references/prompts/<slug>.md | v1 |
example | content/molds/<slug>/examples/, shared content/examples/ | Verbatim copy | references/examples/ | Contracted; caster rejects until a real Mold needs it |
eval | content/molds/<slug>/eval.md | Never packaged | — (Foundry-only) | n/a |
mold (smell) | another Mold | Discouraged; factor shared content into other reference kinds | — | n/a |
Every path above is deterministic. Which one a kind takes is not knowledge the caster holds: each kind’s cast: block in reference_contract.yml declares its resolve strategy (note, package-export, payload-companion), its default_mode, an optional slug_field, and whether its notes may carry companions. A kind with no cast: block is not castable, which is how example is refused — stated where the kinds live rather than in a second list inside the caster.
The inherited mode vocabulary is verbatim and sidecar, and this Foundry renders both — the copies above and the cli-command JSON. So it narrows nothing: every mode an author may spell here is one the caster can perform.
example is declared in the contract but no Mold uses it yet, so the caster fails fast rather than guessing dst conventions. prompt is active for wrapper notes; the raw text is the upstream.prompt file beside index.md, named by convention rather than declared in frontmatter.
Typed reference manifest
Molds declare operational dependencies through the object-shaped references manifest. mold-spec is canonical for field requirements and authoring rules; the reference contract is canonical for vocabulary labels and descriptions — reference_contract.yml for kind, @galaxy-foundry/reference-contract for the four inherited vocabularies. Casting reads the manifest, resolves each reference by kind, and writes the target-specific reference layout described below.
Mold IO contracts live on input_artifacts[] / output_artifacts[]. Producer-owned output_artifacts[].schema wiki-links point at schema notes that casting packages; consumers inherit those contracts by binding to the same artifact id.
Agent-facing vs. human-facing vendored artifacts
When an upstream project ships both a structured source (YAML, JSON Schema, IDL) and a derived human-rendered form (LaTeX-heavy Markdown, generated HTML), cast from the structured source, not the rendered form. The structured source is denser per token, schema-regular, and preserves identifiers (labels, test pin names) that the renderer typically discards.
Canonical examples: galaxy-collection-semantics and galaxy-xsd. Upstream (galaxyproject/galaxy) keeps the formal collection type-rule spec in lib/galaxy/model/dataset_collections/types/collection_semantics.yml, runs semantics.py to generate doc/source/dev/collection_semantics.md (MyST admonitions + LaTeX math), and keeps the Galaxy tool wrapper XML contract in lib/galaxy/tool_util/xsd/galaxy.xsd. The Foundry vendors these artifacts at the same SHA:
content/research/galaxy-collection-semantics/galaxy-collection-semantics.yml— canonical for casting and for any agent reasoning about collection mapping/reduction. Carriestests:blocks pinning concrete Galaxy test names that the rendered MD drops.content/research/galaxy-collection-semantics/galaxy-collection-semantics.upstream.myst— vendored solely so the site can render the upstream view for human readers. Not consumed by casting.content/research/galaxy-xsd/galaxy.xsd— canonical for casting and agent reasoning about Galaxy tool wrapper XML. Framed by galaxy-xsd and synced through the same vendored-upstream manifest as the collection-semantics artifacts.
Casting policy: a cast that needs collection-semantics knowledge resolves the .yml and inlines from there; a cast that needs Galaxy wrapper syntax resolves galaxy.xsd; the rendered MyST is a site-rendering concern only. Pattern generalizes — when both forms exist, agents read structure, humans read prose.
The casting process is itself expected to evolve. Today: deterministic SKILL.md assembly, deterministic file copies and sidecars, no LLM phase at all. Tomorrow: maybe additional target renderers, or a condensation phase if some kind ever earns one — the vocabulary for that is still in the shared contract, declined rather than deleted, so re-admitting it is a one-line narrowing change plus the machinery. The Foundry does not lock in every implementation detail; it locks in a contract (input shape, output shape, provenance).
When casting runs
Three triggers, in increasing automation:
- Manual.
npm run cast -- <mold-name> --target=<target>. That is the whole cast — there is no follow-up phase, andSKILL.mdis never hand-maintained. - CI on Mold change. When a PR touches
molds/<name>/, CI re-casts that Mold against all configured targets and surfaces the diff in review. - Watch-on-change for development convenience.
Drift surfaces via foundry-build cast <mold> --check (per-Mold) and cast-skill-verify.ts <mold> (verifier rejects hash drift, missing dst, schema violations, and missing or stale SKILL.md). make check-casts and make check-verify run each over every Mold — the first as foundry-build cast-all --check, which sweeps in one process and says nothing when nothing moved. The sweep is @galaxy-foundry/cast; the list of Molds it sweeps is this Foundry’s, because every Mold here is expected to be cast.
Input contract
To cast a Mold, the casting process consumes:
- The Mold directory —
index.md(frontmatter manifest + procedural body) plus, if the schema permits, casting hints. The cast renders the procedural body ofindex.mdintoSKILL.md. Which sibling files travel is not decided here: themoldkind declares a disposition per companion (packages/note-schema/src/types/mold/schema.ts), and the cast verifier refuses a bundle carrying one that is notbundled.eval.mdand the other Foundry-only companions never leave the Foundry;casting.mdandcast-skill-verification.mdare read while casting but not shipped. Author-facing meta-content (changelog entries, casting open-questions) belongs in those sibling files, not in the body ofindex.md— anything in the body is runtime instruction. - Artifact IO contracts —
input_artifacts[]andoutput_artifacts[]define what a skill consumes and produces. Producer-owned schemas declared onoutput_artifacts[].schemaare surfaced to consumers by shared artifactid; cast provenance records the producer list and inherited schema hints for harnesses. - All typed references declared in the manifest, resolved by kind:
references— object-shaped typed references withkind,ref,used_at,load, andmode; this is the preferred manifest for new operational references.patterns— legacy wiki links intocontent/patterns/.cli_commands— legacy wiki links intocontent/cli/<tool>/<cmd>.md.output_artifacts[].schema(and inherited consumer-side schemas viainput_artifacts[].id) — wiki-links intocontent/schemas/<name>.md; resolved at cast time via the schema note’spackage+package_exportto a runtime import frompackages/<name>-schema/.prompts— legacy wiki links intocontent/prompts/(when the Mold needs them).examples— legacy paths intocontent/molds/<slug>/examples/or sharedcontent/examples/.- IWC exemplar URLs cited in pattern bodies are resolved by the pattern transformation, not by the casting top-level (URLs stay URLs in pattern bodies; pinning to a SHA is at the pattern author’s discretion).
- Other Molds (
related_molds) — flagged as a smell; shared operational content should move to a pattern page, CLI manual page, schema, prompt, example, or research note.
- The cast bundle spec — the deterministic Agent Skills assembly and reference layout declared in
casts/claude/_target.yml. The historical target name remains for provenance compatibility; Claude Code and Codex package the resulting tree through separate thin manifests.
Resolution policy is per-kind, not a single rule:
pattern— verbatim copy, and one of the two kinds whose notes may declare companions.cli-command— always cast to JSON sidecar from registered upstream metadata plus the Foundry framing note; no token-budget condensation needed because the sidecar is loaded only when the agent needs that command.schema,example,prompt— always verbatim copy unless the typed reference declares a future supported transformation.research— operational background; copied verbatim, loaded according toused_at/load, and the other kind that may carry companions.eval— never packaged.
Output contract
Per cast: casts/claude/skills/<mold-name>/. The directory uses the portable Agent Skills core shared by Claude Code and Codex:
casts/claude/skills/<mold-name>/
├── SKILL.md # deterministic render of Mold body + artifacts + refs
├── references/ # supporting content, organized by kind
│ ├── schemas/ # verbatim *.schema.json
│ ├── cli/ # deterministic JSON sidecars (flat, <slug>.json)
│ ├── patterns/ # verbatim pattern excerpts
│ ├── notes/ # research notes, verbatim
│ ├── prompts/ # raw prompt sidecars copied from prompt wrapper notes
│ └── examples/ # populated when example refs exist
└── _provenance.json # required, not part of the skill (schema v4 — see below)
Per-kind dst conventions are declared in casts/claude/_target.yml (kinds.<kind>.dst_dir + dst_extension + allowed modes). For verbatim modes the dst basename matches the source 1:1; for sidecars it’s <source-slug><dst_extension>.
Per-kind subdirectories under references/ mirror the casting dispatch and let the generated skill’s runtime locate any artifact deterministically.
SKILL.md contains deterministic sections for when to use the skill, upstream artifact inputs, produced artifacts, upfront references, on-demand references and triggers, validation hints, the Mold procedure, and runtime notes. Raw Foundry wiki-links are stripped or resolved to packaged reference paths so the skill is self-contained. Its frontmatter stays in the shared name/description core; runtime-specific invocation syntax belongs in manifests and usage documentation.
The plugin root carries both .claude-plugin/plugin.json and .codex-plugin/plugin.json, each pointing to the same skills/ directory. Repo marketplace metadata is likewise thin: Claude reads .claude-plugin/marketplace.json, while Codex reads .agents/plugins/marketplace.json. Neither duplicates skill bodies, references, schemas, provenance, or Pipeline assemblies.
Claude is the only target. A target becomes real by acquiring a casts/<target>/_target.yml —
that file’s existence is what the caster and the site each read, so there is no list of targets
anywhere to keep in step with the directories.
_provenance.json is required for every cast. The contract of record is the cast-provenance schema note (rendered field-by-field from scripts/lib/schemas/cast-provenance.schema.json, schema version 4); the JSON below is an illustrative sketch, not the authority. Shape:
{
"provenance_schema_version": 4,
"cast_target": "claude",
"mold": {
"name": "summarize-nextflow",
"path": "content/molds/summarize-nextflow/index.md",
"revision": 7,
"content_hash": "<sha256 of index.md>",
"commit": "<git SHA at cast time>"
},
"cast_at": "2026-05-02T22:44:00.546Z",
"cast_history": [
{ "rev": 1, "date": "2026-05-01", "note": "initial deterministic cast" }
],
"refs": [
{
"kind": "research",
"mode": "verbatim",
"ref": "[[component-nextflow-testing]]",
"src": "content/research/component-nextflow-testing/index.md",
"dst": "references/notes/component-nextflow-testing.md",
"used_at": "runtime",
"load": "on-demand",
"evidence": "hypothesis",
"src_hash": "<sha256>",
"dst_hash": "<sha256>",
"source": "deterministic"
},
{
"kind": "cli-command",
"mode": "sidecar",
"ref": "[[planemo-test]]",
"src": "content/cli/planemo/test.md",
"dst": "references/cli/test.json",
"used_at": "runtime",
"load": "on-demand",
"trigger": "before running a tool test",
"src_hash": "<sha256>",
"dst_hash": "<sha256 of the built sidecar>",
"source": "deterministic"
}
],
"artifacts": {
"produces": [
{ "id": "summary-nextflow", "kind": "json", "default_filename": "summary-nextflow.json", "schema": "[[summary-nextflow]]", "description": "..." }
],
"consumes": [
{ "id": "nextflow-galaxy-interface", "description": "...", "producers": ["nextflow-summary-to-galaxy-interface"] }
]
}
}
refs[] is sorted by (kind, src) for stable diffs. Each entry’s source records how the dst was produced; it is deterministic and nothing else, kept as a positive claim rather than dropped so a reader never has to infer determinism from a missing field. A verbatim entry proves itself with src_hash == dst_hash. artifacts records the runtime handoff contract after producer inheritance.
Provenance is the foundation for drift detection, reproducibility audits, and “why does this cast contain X” forensics. See cast-provenance for the per-field contract and stable anchors.
Schema artifacts in casts
The test-format schema is the canonical case. @galaxy-tool-util/schema ships tests.schema.json (generated from galaxy.tool_util_models.Tests Pydantic models — see galaxyproject/galaxy#22566 and jmchilton/galaxy-tool-util-ts#75 for the source-of-truth chain). It carries every assertion’s parameters, types, defaults, required fields, the that discriminator constant, and the original Python docstring as description. An agent equipped with that JSON Schema can author syntactically valid <workflow>-tests.yml and look up what each assertion does — no prose vocabulary catalog required.
Casting policy for upstream-package schemas:
- Source of truth lives upstream. The Foundry pins a version (in its toolchain
package.jsonfor npm, etc.) but does not edit the schema. - Casting copies the schema verbatim into
references/schemas/. The generated skill’s runtime loads it for AJV / equivalent validation; no Foundry round-trip needed. - Bundle helper functions when applicable. For test-format specifically,
@galaxy-tool-util/schemaalso exportsvalidateTestsFileandcheckTestsAgainstWorkflow(label/type cross-check between a.gaand a tests file). When a cast’s runtime is Node-capable, depending on the package directly is cleaner than vendoring just the JSON; the dependency is also recorded in_provenance.jsonso reviewers can see the version pin. - Schema-page rendering in the Foundry uses the same vendored copy. The Foundry syncs the vendored test schema to
packages/foundry/src/schemas/tests-format/tests.schema.jsonand renders it viasite/src/lib/schema-registry.tsas a navigable schema note, so research notes and Mold bodies can deep-link individual$defs(e.g.[[tests-format#has_text]]). The vendored JSON is the single source for both casting output and site rendering.
Other schemas that fall under this policy as they land:
gxformat2— workflow source format. Schema-Salad-derived; vendored similarly.- Mold IO summary schemas (
summarize-nextflow,summarize-cwl, and future structured summaries) — Foundry-authored underpackages/<name>-schema/src/, paired with a<name>.mdschema note incontent/schemas/; cast and site-rendered through the same machinery so consumers see one consistent surface. Narrative starts (summarize-paper,interview-to-freeform-summary) currently emit Markdownfreeform-summaryrather than a rigid schema.
The reference-kind schema does not distinguish between Foundry-authored and upstream-vendored at cast time — both are verbatim copies. The distinction matters only for sync/update flow: upstream schemas update via package bumps, Foundry-authored schemas update via direct edits.
Process steps (per cast)
cast_mold(mold_name, target):
mold <- read molds/<mold_name>/index.md
validate mold against frontmatter schema (incl. typed-reference manifest)
refs <- resolve_manifest(mold) # by kind: references plus legacy fields
validate every ref exists and conforms to its kind's contract
target <- load_target_adapter(target)
# Per-kind dispatch:
for ref in refs:
case ref.kind:
pattern -> verbatim copy (plus any declared companions)
write to references/patterns/<source-basename>
cli-command -> deterministic JSON sidecar from registry metadata + framing body
write to references/cli/<source-slug>.json
schema -> copy verbatim to references/schemas/<source-basename>
research -> copy verbatim (plus any declared companions)
write to references/notes/<source-basename>
prompt -> copy sibling `upstream.prompt` verbatim to references/prompts/<slug>.md
example -> reject until first example ref establishes target convention
eval -> skip (never packaged)
artifacts <- read_artifact_contracts(mold.meta, producer_index)
skill_md <- target.assemble_skill(mold.summary, mold.body, artifacts, refs)
write SKILL.md to casts/<target>/<mold_name>/
write _provenance.json (schema v4: mold object, refs[] sorted by kind+src,
per-ref src_hash/dst_hash, source=deterministic,
per-ref license lineage for redistributed bytes)
foundry-build cast handles verbatim copies, sidecars, SKILL.md rendering, orphan pruning, and provenance — the whole cast. Nothing hand-edits a bundle; skill-body changes flow from Mold source changes, and a hand edit is reported as drift by --check and overwritten by the next cast. The deterministic verifier (scripts/cast-skill-verify.ts) enforces the contract on the result.
Drift detection
A cast is stale when any of:
- The Mold’s
index.mdcontent hash differs from_provenance.mold.content_hash. - Any resolved ref’s source hash differs from the recorded
refs[*].src_hash, or its dst hash drifts fromrefs[*].dst_hash. - The deterministic
SKILL.mdrender differs from the committedSKILL.md. - The target adapter has changed.
foundry status enumerates stale casts; foundry cast --all re-casts every stale entry. Re-casting an unchanged Mold with unchanged refs produces the same SKILL.md, sidecars, copied refs, and provenance except for cast timestamps, commit, and history — which is exactly what make check-casts asserts over all 47 Molds.
Versioning
No semver on Molds, no semver on casts. Identity is content hash + commit SHA. Re-casting is the migration path. If a generated skill needs to be “frozen” (e.g., a published skill on a marketplace), pin it by commit SHA in the consumer.
This keeps the Foundry’s iteration loop fast: change a Mold, re-cast, review the diff. Don’t bump versions, don’t manage compatibility tables, don’t write changelogs for every cast.
Reproducibility
Casting is deterministic end to end. Every cast records exactly what went into it (Mold hash, ref hashes, license lineage, artifact contracts). A reviewer can:
- Check whether a cast is up-to-date (drift detection).
- Reproduce deterministic cast outputs from the recorded Mold and refs.
- Compare two casts’ provenance to explain content differences.
Assembly is byte-stable aside from timestamps, commit, and provenance history. There is no non-deterministic path left to carve out of that guarantee, which is why the drift gate can be a pass/fail check in CI rather than a diff a human reads.
What casting does not do
- Does not write to the Foundry. Casting is read-only against
content/molds/,content/patterns/,content/cli/,content/prompts/,content/examples/, andcontent/schemas/. All writes go tocasts/. - Does not invoke gxwf or Planemo. Those are the generated skill’s responsibility at runtime, not casting time. (Validation tooling does invoke schemas, but that’s distinct.)
- Does not update Molds. If casting reveals a generated skill is weak or wrong, migrate the needed instruction into the Mold body or referenced notes by hand, then re-cast.
- Does not touch eval plans.
eval.mdis Foundry-only; never read by casting.
Minimum Exercise
To exercise the architecture without overbuilding:
- One cast target: Claude. A second one starts by adding
casts/<target>/_target.yml. - One casting model: pick one, pin in
casts/claude/_target.yml. - Cast 3-4 Molds end-to-end:
summarize-paperorinterview-to-freeform-summary(exercises freeform Markdown handoff),implement-galaxy-tool-step(exercisespattern+example),advance-galaxy-draft-step(exercises orchestrator-shaped Mold withcli-commandreferences and leaf sequencing),validate-galaxy-workflow(exercises terminal validation posture). Diversity exercises the per-kind dispatch, not just the prompt. - Manual
foundry castonly. - Commit casts to the repo so we can review the actual outputs.
If those casts look reasonable and the provenance flow holds, scale to more Molds and more targets.