Skip to content

Commit 2036c24

Browse files
authored
Merge pull request #51 from galaxyproject/agent/cast-second-adopter
Complete the first-cast guidance
2 parents a2ca3d8 + 0690fcb commit 2036c24

5 files changed

Lines changed: 124 additions & 41 deletions

File tree

content/pattern/astro-stack-glossary.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,20 +71,21 @@ summarized paper). Three consequences worth stating outright:
7171
- Only directory-shaped kinds have companions.
7272
- A sibling that is itself a note is never a companion — a `cli-command` beside a `cli-tool` is a
7373
note, and nothing can tell the difference from the filename.
74-
- A companion describes **layout** only. A file a note actually *depends on* is a
75-
[[glossary|Reference]] instead.
74+
- A companion describes fixed **layout and cast disposition**, not progressive loading. A file a
75+
Mold depends on is still a [[glossary|Reference]]; resolving that referenced note is what makes
76+
its eligible companions relevant to the cast.
7677

7778
Each declaration carries a **requirement level** (`required` / `recommended` / `optional`) and a
7879
**disposition** — whether casting may carry the file into a skill artifact (`foundry-only` never
7980
leaves; `cast-input` is read by the caster but does not appear in the output; `bundled` is copied
80-
in). The disposition is enforced, not descriptive: a cast's forbidden-file list is derived from
81-
it rather than restated beside it.
82-
83-
> A second collision worth naming, like the one above. An instance may also carry a per-*note*
84-
> `companions:` field, and it answers a different question — not *what may sit beside this note*
85-
> (layout, the kind's to declare) but *what does this note carry into a cast* (membership, which
86-
> stays declared per note precisely so that no file ships because of where it was saved). Both
87-
> senses are legitimate; a page using either should say which.
81+
in). The disposition is enforced, not descriptive: when a cast resolves a directory-shaped note,
82+
its fixed `bundled` companions travel automatically and the other two stay out. Presence elsewhere
83+
in the directory is never enough to ship a file.
84+
85+
> A kind with `additionalCompanions: allow` has an open extension to that fixed layout. A per-note
86+
> `companions:` field may enumerate those additional members, but it supplements the kind; it
87+
> cannot reclassify a fixed `foundry-only` or `cast-input` file as bundled. A closed kind accepts no
88+
> per-note additions.
8889
8990
**Collection** — a *location*: a base directory plus the pattern selecting which files under it are
9091
notes, and the kind those notes are. Collections and kinds are deliberately not one-to-one — one

content/pattern/kind-catalog.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,10 @@ Three things that declaration makes visible for the first time:
8181
acquisition files sit at the *book* level, one directory above the chapter that is the note, so
8282
declaring the chapter open would have claimed unboundedness where the truth is those files
8383
belong to a container that is not a note at all.
84-
- **The declaration is load-bearing, not documentation.** One instance's casting pipeline kept a
85-
hand-written list of files a skill artifact may never carry; it named two of the eight its kinds
86-
declare. Deriving that list from the dispositions instead is what turned the metadata this page
87-
reports into something a check answers to — and the size of the gap is the argument for it.
84+
- **The declaration is load-bearing, not documentation.** Validation reads it to check the note
85+
directory, catalogs read it to report the layout, and casting reads the same declaration to copy
86+
fixed `bundled` companions while keeping `foundry-only` and `cast-input` files out. No target or
87+
note restates that fixed membership.
8888

8989
Each substrate kind below carries a companion table with one row per file and one column per
9090
instance, reading *requirement · disposition*. A file both instances declare at the same

content/pattern/setting-up-a-foundry.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,15 @@ The payoff is one surface serving both readers a Foundry has. A human reads the
7272

7373
**Produce.** Choose one representative decision-and-handoff unit and author a [[the-model|Mold]] for it. Declare every dependency by kind, along with its load policy and placement mode. Keep facts, schemas, examples, prompts, and rationale as references rather than duplicating them into the procedure.
7474

75-
**Done when.** The Mold describes one coherent action — neither an entire journey nor a dust of fragments — and every declared reference resolves and validates. Someone should be able to explain why each dependency is present and why it loads when it does. Let the boundary be corrected by the first real use before multiplying it into a taxonomy.
75+
**Done when.** The Mold describes one coherent action — neither an entire journey nor a dust of fragments — and every declared reference resolves and validates. Someone should be able to explain why each dependency is present and why it loads when it does. The reference contract should contain only kinds the current Mold corpus uses and only placement modes an implemented target can perform. It need not contain cast strategy yet: a reader-only instance should reject configuration no installed caster reads. Let the boundary be corrected by the first real use before multiplying it into a taxonomy.
7676

7777
## 5. Choose one target and set up casting
7878

7979
**Goal.** Prove that the structured source can become a frozen, usable artifact without becoming a second source of truth.
8080

81-
**Produce.** Select one target format and implement its deterministic casting rules: how each reference kind resolves, what is inlined or bundled, and how target-specific files are laid out. Emit provenance beside the artifact, including the Mold and target identities, resolved references, hashes, placement, and cast-time checks.
81+
**Produce.** Select one target format and implement its deterministic casting rules: how each reference kind resolves, what is inlined or bundled, and how target-specific files are laid out. Pass the same Kind layout used by validation into casting. Fixed companion membership belongs there: a `bundled` companion travels with a resolved note, while `foundry-only` and `cast-input` companions do not. Do not repeat that decision in note frontmatter, reference-kind configuration, or target exclusions. Emit provenance beside the artifact, including the Mold and target identities, resolved references, hashes, placement, and cast-time checks.
8282

83-
**Done when.** The same source, Mold, and target reproduce the same bytes; links back into the KB have been resolved away; the artifact is self-contained for its intended runtime; and a reviewer can trace packaged material back to its source. When the artifact is wrong, the repair happens in the Mold, its references, or the target rules — never by hand-editing the cast.
83+
**Done when.** The same source, Mold, and target reproduce the same bytes; a check run is inert; links back into the KB have been resolved away; the artifact is self-contained for its intended runtime; and a reviewer can trace every packaged note and companion back to its source. Missing required companions fail, absent recommended companions do not become phantom references, and no companion outside the Kind's eligible layout can be smuggled in by note metadata. When the artifact is wrong, the repair happens in the Mold, its references, its Kind, or the target rules — never by hand-editing the cast.
8484

8585
## 6. Build the external check
8686

content/pattern/standing-up-a-foundry.instructions.txt

Lines changed: 105 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -225,11 +225,13 @@ have either a dependency dictating your domain or a copy that drifts:
225225
that data for collection-backed sites; a lower-level direct consumer uses
226226
`fileSlug` and `slugify` so the path and authored-target halves cannot drift.
227227
cast Ships `castMold`, cast-contract parsing, the generic skill-document shape,
228-
deterministic placement/reconciliation and provenance. You keep the kind
229-
declarations, target policy, slug map and hooks: domain skill sections,
230-
non-verbatim renderers, extra bundle files, aliases and external checks.
231-
Errors and drift return as values; your caller decides how they affect the
232-
process. Do not disguise instance vocabulary as substrate.
228+
Kind-layout companion expansion, deterministic placement/reconciliation and
229+
provenance. You keep the kind declarations, target policy, corpus index and
230+
hooks: domain skill sections, non-verbatim renderers, extra bundle files and
231+
external checks. Pass the Kind table as `kindLayouts`; do not translate it
232+
into another companion policy. Errors and drift return as values; your
233+
caller decides how they affect the process. Do not disguise instance
234+
vocabulary as substrate.
233235
audit-citations Ships one replayable scholarly-citation audit and its strict wire formats.
234236
You keep source selection, trusted hosts, artifact kinds and the acceptance
235237
gate. It is experimental; its citation-specific candidates and verdicts are
@@ -621,24 +623,25 @@ wants to know what a Mold is opens types/mold/ rather than scrolling a 400-line
621623
`disposition` is ONE axis — whether the file reaches a skill artifact. `foundry-only` never
622624
leaves (eval, scenarios). `cast-input` means the caster READS it and it does not appear in the
623625
output (rendering metadata or a placement manifest). `bundled` is copied in (a vendored schema).
624-
Derive target exclusions from these declarations rather than restating names in target config.
625-
Across kinds, a name declared `bundled` anywhere remains bundle-eligible, and a file legally
626-
claimed by a reference is exempt from companion-only exclusion.
626+
The caster reads the referenced note's Kind layout and carries fixed `bundled` companions
627+
automatically. Derive target exclusions from the same declarations rather than restating names
628+
in target config. A file's presence in the directory does not make it eligible; the declaration
629+
does.
627630
- COMPANIONS DESCRIBE LAYOUT, NOT DEPENDENCIES. If a companion declaration starts growing
628631
`used_at` / `load` / `mode`, it has turned into a second reference contract, and the answer is a
629632
`references:` entry instead. Worth watching precisely because both sides can be described as
630633
"a file this note needs" — the difference is that a companion says where a file SITS and a
631634
reference says what a note DRAWS ON.
632-
- WHAT MAY SIT BESIDE A NOTE AND WHAT A NOTE CARRIES INTO A CAST ARE TWO QUESTIONS, and only the
633-
first is the kind's. It is tempting to collapse them once the kind knows the layout — the
634-
directory listing is right there, so why should a note declare anything? Because the answer to
635-
the second question decides what reaches a SKILL BUNDLE, and deriving it from the listing means a
636-
file ships because of where somebody saved it. What a note carries is DECLARED, never inferred.
637-
The two lists coexist without duplicating because they
638-
answer different questions: the kind's list is names in one directory and is about layout; the
639-
note's is paths (its own subdirectories included) and is about membership. Reject `..` in the
640-
second one — a character class permissive enough for filenames admits it as a whole segment, and
641-
a note that can name `../` can bundle a file it does not own.
635+
- FIXED COMPANION MEMBERSHIP BELONGS TO THE KIND. A referenced directory note carries exactly the
636+
fixed companions whose disposition is `bundled`; `foundry-only` and `cast-input` cannot be
637+
reclassified by note metadata. This is not inference from the directory listing: the Kind names
638+
each eligible file, and validation separately checks whether the directory satisfies that
639+
declaration. Missing required companions remain refs so the cast reports the missing source;
640+
absent recommended or optional companions are skipped.
641+
An open Kind (`additionalCompanions: 'allow'`) may let a note enumerate additional bundle members
642+
in a per-note `companions:` field. Those are additions only. Reject absolute paths and `..`, and
643+
recurse declared directories into one provenance entry per file. A closed Kind accepts no
644+
per-note additions. Do not add a second `companions` permission to `reference_contract.yml`.
642645
- A LAYOUT DECLARATION SAYS A FILE IS THERE, NEVER THAT IT SAYS ANYTHING. Whether `eval.md` exists
643646
beside a Mold is the declaration's business, and `recommended` is what produces the warning.
644647
Whether it contains a single property check is a rule about CONTENTS, which no layout vocabulary
@@ -879,7 +882,10 @@ formats, the loaders and the inherited vocabularies are installed (see "The shar
879882
`kinds`) — the boundary is enforced in both directions, because it is the kind of split that
880883
otherwise decays quietly. Compose the two halves in src/lib/reference-contract.ts. Your kinds
881884
keep their own `href` into your spec docs; the inherited four link to the Foundry Pattern, which
882-
is where they are specified.
885+
is where they are specified. Once the instance adopts @galaxy-foundry/cast, a kind may also carry
886+
the delegated `cast:` block Part 7 defines. Load it through `loadCastReferenceContract`; a
887+
reader-only composition deliberately refuses that field because no installed capability acts on
888+
it.
883889
- meta_tags.yml — the controlled tag vocabulary, grouped into FACETS: `version: 1` plus
884890
`facets: <facet>: { label, description, values: { <tag>: <gloss> } }` (`values` may be omitted
885891
while a facet is still empty). Parse it with @galaxy-foundry/tag-registry — loadTagRegistry()
@@ -1047,7 +1053,82 @@ Decompose the domain into repeatable decision-and-handoff units — one Mold per
10471053
- Get the boundary right: not one monolith, not a dust of fragments.
10481054

10491055

1050-
PART 7 — BUILD THE EXTERNAL CHECK
1056+
PART 7 — CAST ONE MOLD TO ONE TARGET
1057+
1058+
Adopt @galaxy-foundry/cast only after one real Mold and all of its references validate. The reader,
1059+
Kind catalog and reference view are a complete earlier vertical; do not install a caster merely to
1060+
make its configuration look anticipated.
1061+
1062+
- LOAD BOTH HALVES OF THE REFERENCE CONTRACT at the one composition point that already supplies
1063+
the site schema. `loadCastReferenceContract` delegates the `cast:` block to the cast parser while
1064+
returning the same reader-facing contract the site renders. A reference kind's block declares
1065+
strategy, never companion membership or target placement:
1066+
1067+
kinds:
1068+
environment:
1069+
label: Environment
1070+
description: A runnable fixture and its declared bundled companions.
1071+
ref_shape: wiki-link
1072+
cast:
1073+
resolve: note
1074+
default_mode: verbatim
1075+
1076+
`resolve` answers where the primary payload comes from (`note`, `package-export`, or
1077+
`payload-companion`). `note_types` widens a reference kind that intentionally addresses several
1078+
note types; do not rename the corpus to make the two vocabularies coincide. Omit `cast:` to make a
1079+
reference kind reader-visible but uncastable. Before cast is installed, load the contract with
1080+
`buildReferenceContract` instead; its refusal of an unknown `cast:` field prevents dead
1081+
configuration from looking implemented.
1082+
1083+
- BUILD ONE CORPUS INDEX and project every cast input from it: the slug map, parsed frontmatter by
1084+
path, and note targets. The map must apply the same aliases and collision precedence as prose and
1085+
frontmatter links, and it must be driven by the collection table so companions never become note
1086+
targets. Do not add a cast-only walk or slug policy. If the shared reader cannot expose a needed
1087+
projection, improve that seam upstream rather than make two indexes agree by convention.
1088+
1089+
- PASS THE KIND TABLE AS `kindLayouts`. Casting consumes only `shape`, `companions`, and
1090+
`additionalCompanions`, but it must consume the same declarations the validator and generated
1091+
manifest use. A missing layout is a cast error. Do not translate the table into target excludes,
1092+
note defaults, or a second list of companion filenames.
1093+
1094+
- DECLARE ONE TARGET in its own directory. The target owns bundle placement, document vocabulary,
1095+
per-reference-kind destinations, extensions and supported modes; the reference kind owns source
1096+
resolution. A minimal target is explicit about the runtime-facing document:
1097+
1098+
bundle_path: 'skills/{mold}'
1099+
document:
1100+
path: SKILL.md
1101+
noun: skill
1102+
kinds:
1103+
environment:
1104+
dst_dir: references/environments/
1105+
dst_extension: .md
1106+
modes: [verbatim]
1107+
1108+
Quote `{mold}` in YAML. Keep `_provenance.json` out of target vocabulary: it is the caster's
1109+
runtime-neutral account, not a format-specific document. A target may constrain a kind's modes
1110+
but cannot make an unsupported mode or uncastable kind valid.
1111+
1112+
- KEEP HOOKS DOMAIN-SHAPED. Supply the cast document's lede and sections, any implemented
1113+
non-verbatim renderers, extra bundle files and bundle checks. Register `payloadCompanion` or
1114+
`packageLoader` only when a reference kind selects those strategies. An absent implementation is
1115+
an error; never fall back to packaging a plausible but different source.
1116+
1117+
- CALL `castMold` with the loaded Mold, composed reference/cast contracts, reference kinds, corpus
1118+
index, Kind layouts, target and hooks. Treat `errors`, `drift` and `wrote` as values: aggregate
1119+
findings in the caller, set the process exit there, and publish only when the complete staged
1120+
bundle clears every check. A refused cast must leave the working tree untouched.
1121+
1122+
- HOLD THE FIRST BUNDLE AS AN EXECUTABLE CONTRACT. A write run produces the document, eligible
1123+
references, eligible companions and provenance. A subsequent `--check` reports no drift and
1124+
writes nothing. Exercise at least: an unresolved ref; a wrong note type; a missing Kind layout;
1125+
a missing required companion; an absent recommended companion; a `foundry-only` companion; a
1126+
bundled file and directory; a duplicate destination; stale owned output; and a license refusal.
1127+
Assert provenance hashes the actual source and destination bytes. Run the inert check in CI and
1128+
commit the bundle only when committed casts are part of the instance's distribution contract.
1129+
1130+
1131+
PART 8 — BUILD THE EXTERNAL CHECK
10511132

10521133
Decide what "correct" means in your domain and what can decide it. This is the sharpest, most
10531134
domain-specific part; the substrate deliberately leaves it open, so paths below are structural,
@@ -1065,7 +1146,7 @@ not a fixed tool.
10651146
is low is the work-list.
10661147

10671148

1068-
PART 8 — COMPOSE, IF THE WORK IS SEQUENTIAL
1149+
PART 9 — COMPOSE, IF THE WORK IS SEQUENTIAL
10691150

10701151
Where a domain's task is an inherently multi-step journey, compose Molds into an ordered
10711152
end-to-end protocol and orchestrate them; a domain whose actions stand alone needs no such layer.
@@ -1092,8 +1173,9 @@ Parts 2–4 are the substrate, and they now arrive in three grades rather than o
10921173
YOURS The halves the packages deliberately decline. Which kinds exist and what each
10931174
requires; your facet vocabulary; your reference `kinds`; your link aliases, routes
10941175
and unresolved-link policy; your license COHERENCE rules; your base envelope, ported
1095-
honestly; your site's identity
1096-
and its palette; and the domain furniture rendered inside the shared note frame.
1176+
honestly; your site's identity and its palette; the domain furniture rendered
1177+
inside the shared note frame; and, once casting exists, reference strategies,
1178+
targets, hooks, corpus projections and the release threshold for cast findings.
10971179

10981180
Mechanical wiring is a package candidate when it exposes a stable, reusable contract. Duplication
10991181
is a prompt to investigate that contract, not sufficient evidence by itself. Reconcile genuine

content/pattern/standing-up-a-foundry.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ page is canonical for what those packages can truthfully own.
105105
</table>
106106
</div>
107107

108-
The domain's external check remains instance-owned. Part 7 asks what can produce an independent
108+
The domain's external check remains instance-owned. Part 8 asks what can produce an independent
109109
verdict without pretending Astro or a shared package can answer that domain question.
110110

111111
## Keep the handoffs explicit

0 commit comments

Comments
 (0)