Agent Skill · cast

discover-shed-tool

Search the Tool Shed for an existing wrapper, drill from hit to a pinnable changeset, classify candidates, and recommend or fall through.

← All cast skills · Source mold →

Install with Claude Code

/plugin marketplace add galaxyproject/foundry
/plugin install foundry-skills@galaxy-workflow-foundry

Then invoke as:

/foundry-skills:discover-shed-tool

Install with Codex

codex plugin marketplace add galaxyproject/foundry
codex plugin add foundry-skills@galaxy-workflow-foundry

Then select with /skills or invoke explicitly as:

$discover-shed-tool

Skill Bundle

/ packaged cast
attached files
5
upfront
1
on demand
4
cast rev
5
validated
0

Produces: 1 artifact.

Artifact Contract

/ skill handoff

Produces

galaxy-tool-pin

(owner, repo, tool_id, version, changeset_revision) pin for a Tool Shed wrapper plus discovery classification.

jsongalaxy-tool-pin.json[[galaxy-tool-discovery]]
Raw artifact contract
{
  "id": "galaxy-tool-pin",
  "kind": "json",
  "default_filename": "galaxy-tool-pin.json",
  "schema": "[[galaxy-tool-discovery]]",
  "description": "(owner, repo, tool_id, version, changeset_revision) pin for a Tool Shed wrapper plus discovery classification."
}

Attached Files

/ runtime references

Load upfront

schema

galaxy-tool-discovery

packaged

Validate the hit, weak, or miss recommendation emitted by Tool Shed discovery.

upfront runtime verbatim cast-validated deterministic 7.5 KB
bundle
references/schemas/galaxy-tool-discovery.schema.json
source
package://@galaxy-foundry/foundry#galaxyToolDiscoverySchema
Preview json
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://galaxyproject.org/foundry/schemas/galaxy-tool-discovery.schema.json",
  "$comment": "Canonical source: packages/foundry/src/schemas/galaxy-tool-discovery/galaxy-tool-discovery.schema.json in galaxyproject/foundry. Mold frontmatter cites this schema via [[galaxy-tool-discovery]] wiki-links; the cast pipeline imports the `galaxyToolDiscoverySchema` runtime export and serializes it into cast bundles.",
  "title": "Galaxy Tool Discovery Recommendation",
  "description": "Structured recommendation emitted by the discover-shed-tool Mold after searching the Galaxy Tool Shed and resolving any selected candidate to a pinnable Tool Shed version and changeset revision.",
  "$ref": "#/$defs/DiscoveryRecommendation",
  "$defs": {
    "DiscoveryRecommendation": {
      "title": "DiscoveryRecommendation",
      "description": "Top-level output from discover-shed-tool. A hit or weak result carries a selected candidate; a miss carries null candidate plus fallthrough rationale.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "status",
        "candidate",
        "alternates",
        "rationale",
        "warnings"
      ],
      "properties": {
        "status": {
          "type": "string",
          "enum": [
            "hit",
            "weak",
            "miss"
          ],
          "description": "Recommendation class. hit means proceed with the selected Tool Shed pin; weak means candidate exists but needs confirmation or may fall through; miss means no usable wrapper was found."
        },
        "candidate": {
          "anyOf": [
            {
              "$ref": "#/$defs/ToolCandidate"
            },
            {
              "type": "null"
            }
          ],
          "description": "Selected candidate for hit/weak results. Null for miss."
        },
        "alternates": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/ToolCandidate"
          },
          "description": "Runner-up candidates worth surfacing to the user or harness. Empty when no plausible alternates were found."
        },
        "rationale": {
          "type": "string",
          "minLength": 1,
          "description": "Short explanation of why this status and candidate were selected, including ambiguity or fallthrough reasoning.
...

Load on demand

cli-command

tool-revisions

packaged

Resolve a Tool Shed tool version to an installable changeset revision.

Trigger: After selecting a candidate version that needs a reproducible changeset pin.

on-demand runtime sidecar corpus-observed deterministic 4.3 KB
bundle
references/cli/tool-revisions.json
source
content/cli/gxwf/tool-revisions.md
Preview json
{
  "type": "cli-command",
  "tool": "gxwf",
  "command": "tool-revisions",
  "summary": "Resolve a Tool Shed tool to changeset revisions for reproducible workflow pinning. Final step in discover-and-pin.",
  "source_path": "content/cli/gxwf/tool-revisions.md",
  "source_revision": 2,
  "package": "@galaxy-tool-util/cli",
  "description": "List changeset revisions that publish a Tool Shed tool (ordered oldest→newest). Use for reproducible (name, owner, changeset_revision) workflow pins. Caveat: version strings are not monotonic — the same version can appear in multiple changesets.",
  "synopsis": "gxwf tool-revisions [options] <tool-id>",
  "args": [
    {
      "raw": "tool-id",
      "name": "tool-id",
      "required": true,
      "variadic": false,
      "description": "TRS id (owner~repo~tool_id) or pretty form (owner/repo/tool_id)"
    }
  ],
  "options": [
    {
      "flags": "--tool-version <v>",
      "name": "toolVersion",
      "description": "Restrict to revisions that publish this exact tool version",
      "takesArgument": true,
      "argumentPlaceholder": "<v>",
      "optionalArgument": false,
      "negatable": false
    },
    {
      "flags": "--latest",
      "name": "latest",
      "description": "Print only the newest matching revision",
      "takesArgument": false,
      "optionalArgument": false,
      "negatable": false
    },
    {
      "flags": "--json",
      "name": "json",
      "description": "Emit machine-readable JSON envelope",
      "takesArgument": false,
      "optionalArgument": false,
      "negatable": false
    }
  ],
  "body": "# `gxwf tool-revisions`\n\nResolve a Tool Shed tool to the changeset revisions that publish it, ordered oldest→newest by `get_ordered_installable_revisions`. Needed when emitting a workflow that pins `(name, owner, changeset_revision)` for reproducible reinstall — TRS version strings alone are insufficient because the Tool Shed dedupes versions across changesets.\n\n`<tool-id>` accepts both TRS form (`owner~repo~tool_id`) and pretty form (`owner/repo/tool_id`).\n\n## Output\n\nDefault: lines of `<changesetRevision>\\t<toolVersion>`.\n\n`--json`:\n\n```json\n{\n  \"trsToolId\": \"devteam~fastqc~fastqc\",\n  \"version\": \"0.74+galaxy0\",\n  \"revisions\": [\n    { \"changesetRevision\": \"5ec9f6bceaee\", \"toolVersion\": \"0.74+galaxy0\" }\n  ]\n}\n```\n\n`--json` without `--tool-version` r
...
cli-command

tool-search

packaged

Search the Tool Shed for candidate wrappers matching a step's tool need.

Trigger: When resolving a workflow step to an installable Galaxy tool wrapper.

on-demand runtime sidecar corpus-observed deterministic 5.8 KB
bundle
references/cli/tool-search.json
source
content/cli/gxwf/tool-search.md
Preview json
{
  "type": "cli-command",
  "tool": "gxwf",
  "command": "tool-search",
  "summary": "Free-text Tool Shed search returning candidate tools as JSON; first step in the discover-and-pin sequence.",
  "source_path": "content/cli/gxwf/tool-search.md",
  "source_revision": 2,
  "package": "@galaxy-tool-util/cli",
  "description": "Search the Galaxy Tool Shed for tools matching a query",
  "synopsis": "gxwf tool-search [options] <query>",
  "args": [
    {
      "raw": "query",
      "name": "query",
      "required": true,
      "variadic": false,
      "description": "Search text (e.g. 'fastqc')"
    }
  ],
  "options": [
    {
      "flags": "--page-size <n>",
      "name": "pageSize",
      "description": "Server-side page size",
      "takesArgument": true,
      "argumentPlaceholder": "<n>",
      "optionalArgument": false,
      "negatable": false,
      "defaultValue": "20"
    },
    {
      "flags": "--max-results <n>",
      "name": "maxResults",
      "description": "Hard cap on hits returned",
      "takesArgument": true,
      "argumentPlaceholder": "<n>",
      "optionalArgument": false,
      "negatable": false,
      "defaultValue": "50"
    },
    {
      "flags": "--page <n>",
      "name": "page",
      "description": "Starting page (1-indexed)",
      "takesArgument": true,
      "argumentPlaceholder": "<n>",
      "optionalArgument": false,
      "negatable": false,
      "defaultValue": "1"
    },
    {
      "flags": "--owner <user>",
      "name": "owner",
      "description": "Filter hits to a single repo owner (client-side)",
      "takesArgument": true,
      "argumentPlaceholder": "<user>",
      "optionalArgument": false,
      "negatable": false
    },
    {
      "flags": "--match-name",
      "name": "matchName",
      "description": "Drop hits where the query is not a token in the tool name",
      "takesArgument": false,
      "optionalArgument": false,
      "negatable": false
    },
    {
      "flags": "--json",
      "name": "json",
      "description": "Emit machine-readable JSON envelope",
      "takesArgument": false,
      "optionalArgument": false,
      "negatable": false
    },
    {
      "flags": "--enrich",
      "name": "enrich",
      "description": "Resolve each hit's ParsedTool and attach it as `parsedTool` (one fetch per hit; off by default)",
      "takesArgument": false,
      "optionalArgument": false,
     
...
cli-command

tool-versions

packaged

List available Tool Shed versions for a selected candidate.

Trigger: After a Tool Shed search candidate is selected and before pinning a version.

on-demand runtime sidecar corpus-observed deterministic 3.6 KB
bundle
references/cli/tool-versions.json
source
content/cli/gxwf/tool-versions.md
Preview json
{
  "type": "cli-command",
  "tool": "gxwf",
  "command": "tool-versions",
  "summary": "List TRS-published versions of a Tool Shed tool, oldest→newest. Second step in the discover-and-pin sequence.",
  "source_path": "content/cli/gxwf/tool-versions.md",
  "source_revision": 2,
  "package": "@galaxy-tool-util/cli",
  "description": "List TRS-published versions of a Tool Shed tool (newest last)",
  "synopsis": "gxwf tool-versions [options] <tool-id>",
  "args": [
    {
      "raw": "tool-id",
      "name": "tool-id",
      "required": true,
      "variadic": false,
      "description": "TRS id (owner~repo~tool_id) or pretty form (owner/repo/tool_id)"
    }
  ],
  "options": [
    {
      "flags": "--json",
      "name": "json",
      "description": "Emit machine-readable JSON envelope",
      "takesArgument": false,
      "optionalArgument": false,
      "negatable": false
    },
    {
      "flags": "--latest",
      "name": "latest",
      "description": "Print only the latest version",
      "takesArgument": false,
      "optionalArgument": false,
      "negatable": false
    }
  ],
  "body": "# `gxwf tool-versions`\n\nList the TRS-published versions of a Tool Shed tool, ordered oldest→newest (newest last). Used after [[tool-search]] has surfaced a candidate `trsToolId` and the caller needs to pick a version to cache.\n\n`<tool-id>` accepts both forms:\n- TRS form: `owner~repo~tool_id` (e.g. `devteam~fastqc~fastqc`).\n- Pretty form: `owner/repo/tool_id` (e.g. `devteam/fastqc/fastqc`).\n\nThe `~` form is the Tool Shed's TRS encoding (slashes break FastAPI path-param decoding); the CLI accepts both and normalizes.\n\n## Output\n\nDefault: one version string per line, oldest first.\n\n`--json`:\n\n```json\n{\n  \"trsToolId\": \"devteam~fastqc~fastqc\",\n  \"versions\": [\"0.72+galaxy1\", \"0.73+galaxy0\", \"0.74+galaxy0\"]\n}\n```\n\n`--latest --json`:\n\n```json\n{\n  \"trsToolId\": \"devteam~fastqc~fastqc\",\n  \"versions\": [\"0.74+galaxy0\"]\n}\n```\n\n## Examples\n\n```bash\ngxwf tool-versions devteam/fastqc/fastqc\ngxwf tool-versions devteam~fastqc~fastqc --latest\ngxwf tool-versions devteam/fastqc/fastqc --json\n```\n\n## Gotchas\n\n- **TRS dedupes by version string.** If multiple changesets publish the same `version` (which is legal — the XML version field is not monotonic and not enforced unique), only the last-seen one appears. The other changesets 
...
research

component-tool-shed-search

packaged

Explain Tool Shed search/indexing limitations that affect hit scoring and fallthrough decisions.

Trigger: When results are missing, weak, duplicated across owners, stale, or ambiguous.

on-demand runtime verbatim corpus-observed deterministic 27.1 KB
bundle
references/notes/component-tool-shed-search.md
source
content/research/component-tool-shed-search/index.md
Preview md
---
type: research
tags:
  - target/galaxy
component: "Tool Shed Search and Indexing"
status: draft
created: 2026-04-30
revised: 2026-05-03
revision: 2
summary: "Tool Shed's Whoosh repo/tool search and partial GA4GH TRS v2, indexed from hg-walked metadata with no auto-refresh on upload"
related_notes:
  - "[[galaxy-tool-summary-input-source]]"
  - "[[tool-search]]"
  - "[[tool-versions]]"
  - "[[tool-revisions]]"
  - "[[discover-shed-tool]]"
---

# Galaxy Tool Shed — Search, Indexing, and TRS APIs: Current State

## 1. Architecture primer

The Galaxy Tool Shed is a standalone web application that hosts and serves Galaxy tool wrappers (XML tool definitions plus helper files) to Galaxy servers for installation. Its server code lives under `lib/tool_shed/` in the Galaxy monorepo, sharing model/security/tool-parsing libraries with Galaxy itself but running as its own FastAPI application (`lib/tool_shed/webapp/fast_app.py`, with route modules under `lib/tool_shed/webapp/api2/`). The legacy web framework is almost gone — only `lib/tool_shed/webapp/controllers/hg.py` survives, because the Tool Shed also serves each repository's Mercurial working copy over HTTP for `hg clone`.

A **repository** is the unit of distribution in the Tool Shed: it is a named, owned Mercurial repository (the Tool Shed still runs on `hg`, not `git` — see `mercurial` imports in `lib/tool_shed/util/shed_index.py:4` and `lib/tool_shed/managers/repositories.py:471` onward). A repository has a `name`, an owner (`User.username`), a `type` (e.g. `unrestricted`, `repository_suite_definition`, `tool_dependency_definition` — see `lib/tool_shed/repository_types/`), optional `description`/`long_description`/`homepage_url`/`remote_repository_url`, and a set of categories associated via `RepositoryCategoryAssociati
...

SKILL.md


# discover-shed-tool

Follow the procedure below and use the artifact/reference sections as the runtime contract.

## When To Use

- Search the Tool Shed for an existing wrapper, drill from hit to a pinnable changeset, classify candidates, and recommend or fall through.

## Inputs

- No upstream artifact inputs declared. See the procedure for user-supplied runtime inputs.

## Outputs

- Write artifact `galaxy-tool-pin` as `galaxy-tool-pin.json`. Format: `json`. Schema: galaxy-tool-discovery. (owner, repo, tool_id, version, changeset_revision) pin for a Tool Shed wrapper plus discovery classification.

## Required Tools

- **`gxwf`** (gxwf). `npm install -g '@galaxy-tool-util/cli@^1.8.1'`.
  Ephemeral run: `npx --yes --package @galaxy-tool-util/cli@1.8.1 gxwf`.
  Check: `gxwf --help | grep -q draft-validate`.
  Docs: https://github.com/jmchilton/galaxy-tool-util-ts/tree/main/packages/cli

## Load Upfront

- `references/schemas/galaxy-tool-discovery.schema.json`: Schema file copied verbatim into the bundle. Validate the hit, weak, or miss recommendation emitted by Tool Shed discovery.

## Load On Demand

- `references/cli/tool-revisions.json`: CLI command reference packaged as a sidecar. Resolve a Tool Shed tool version to an installable changeset revision. Use when: after selecting a candidate version that needs a reproducible changeset pin.
- `references/cli/tool-search.json`: CLI command reference packaged as a sidecar. Search the Tool Shed for candidate wrappers matching a step's tool need. Use when: resolving a workflow step to an installable Galaxy tool wrapper.
- `references/cli/tool-versions.json`: CLI command reference packaged as a sidecar. List available Tool Shed versions for a selected candidate. Use when: after a Tool Shed search candidate is selected and before pinning a version.
- `references/notes/component-tool-shed-search.md`: Research note copied verbatim into the bundle. Explain Tool Shed search/indexing limitations that affect hit scoring and fallthrough decisions. Use when: results are missing, weak, duplicated across owners, stale, or ambiguous.

## Validation

- Validate `galaxy-tool-pin.json` before returning it: run `foundry validate-galaxy-tool-discovery galaxy-tool-pin.json` from `@galaxy-foundry/foundry`. If the command is not on PATH, run `npx --package @galaxy-foundry/foundry foundry validate-galaxy-tool-discovery galaxy-tool-pin.json`. This checks artifact `galaxy-tool-pin` against the galaxy-tool-discovery schema.

## Procedure

Discover whether the Galaxy Tool Shed already publishes a wrapper for the tool a workflow step needs, and resolve the discovery to a `(owner, repo, tool_id, version, changeset_revision)` quintuple that downstream steps can pin and cache.

This skill is the **Tool Shed leg** of the `discover-or-author` branch in Galaxy-targeting per-step pipelines. On a hit, the skill recommends a pin and exits successfully. On a miss (or a low-quality hit), it falls through to author-galaxy-tool-wrapper. The branch itself is harness logic; this skill owns only the discovery half.

### Inputs

The skill expects, per step:

- A free-text **need** describing what the step should do (typically a one-line description of the tool, plus any constraints — file format in/out, container language, license preferences).
- Optional **owner hint** (e.g. `devteam`, `iuc`) when the caller has a strong prior.
- Optional **exact-name hint** when the caller knows the canonical XML id.

### Outputs

A structured recommendation object, JSON-shaped:

```json
{
  "status": "hit",
  "candidate": {
    "tool_shed_url": "https://toolshed.g2.bx.psu.edu",
    "owner": "devteam",
    "repo": "fastqc",
    "tool_id": "fastqc",
    "trs_tool_id": "devteam~fastqc~fastqc",
    "version": "0.74+galaxy0",
    "changeset_revision": "5ec9f6bceaee",
    "score": 12.3,
    "matched_terms": ["fastqc"],
    "match_fields": ["name", "description"],
    "rationale": "single dominant hit on tool name"
  },
  "alternates": [],
  "rationale": "single dominant hit on tool name; latest version pinned to newest changeset",
  "warnings": []
}
```

`status` semantics:
- `hit` — recommend pinning. Caller should cache and proceed.
- `weak` — candidate exists but the skill is not confident (e.g. only help-text matched, multiple owners with similar tools, deprecated repo, stale-index suspicion). Caller should confirm or fall through.
- `miss` — no usable hit. Caller falls through to author-galaxy-tool-wrapper.

### Procedure

The skill follows the gxwf-shaped discover-and-pin chain. **It does not call the Tool Shed HTTP API directly** — the TS CLI wraps the call sequence and gotchas covered in component-tool-shed-search.

#### 1. Search

Issue tool-search with the need's keywords. Start narrow:

```
gxwf tool-search "<keywords>" --json --max-results 10
```

If an owner hint is present, add `--owner <owner>`. If an exact-name hint is present, add `--match-name`. Lowercase the query (the tool index does not lowercase, see component-tool-shed-search §6).

**Normalize a tool-id-shaped need before searching.** A caller (e.g. a template `_plan_context` that guessed a candidate) may hand this skill an XML-id token rather than a human name — `iuc/integron_finder`, `integron_finder`. The lexical index does **not** reliably match the underscored token: `tool-search integron_finder` returns no hits while `integron finder` and `integron` both score. So derive query variants instead of feeding the token verbatim: strip any `owner/` prefix, split on `_` / `-` into space-separated words, and also try the bare significant word. A `miss` is only honest after the name variants have been tried — a no-hit on the raw underscored token alone is a search artifact, not evidence the tool is absent.

#### 2. Triage hits

For each hit, score on:
- **Name match.** Exact match on `toolId` or `name` is a strong signal; help-only matches are weak.
- **Owner reputation.** `iuc` and `devteam` repos are typically maintained; an unfamiliar owner with a single-tool repo is a weaker prior. (No machine-readable approval flag exists — the Tool Shed's `approved` field is dead code.)
- **Recency.** Recent `last_updated` strengthens a hit; very old wrappers can still be valid but warrant the `weak` classification.
- **Duplicates across repos.** Two owners can publish wrappers with the same XML id. Either pick the maintained one or downgrade to `weak` and surface the choice.

Drop hits from deprecated repos when detectable. Note: deprecated repos can still appear in shed search results until the next index rebuild — see component-tool-shed-search §6.

#### 3. Resolve to a pinnable version

For the top candidate, list versions:

```
gxwf tool-versions <trsToolId> --json
```

Pick the newest installable version unless the need specifies otherwise (rare: a workflow may pin to a specific historical version for reproducibility). Be aware that **TRS dedupes by version string** — multiple changesets may publish the same version, and only one is visible at this layer.

#### 4. Resolve to a changeset

Drill from `(trsToolId, version)` to a concrete changeset:

```
gxwf tool-revisions <trsToolId> --tool-version <v> --latest --json
```

Prefer `--latest` so the newest changeset publishing that version wins (tool versions are not monotonic; two changesets can legally publish the same version with different content). The output's `changesetRevision` is what lands in the workflow's `tool_shed_repository.changeset_revision` for reproducible reinstall.

#### 5. Classify and emit

Combine the scored hit and the resolved pin into the recommendation object above:
- One dominant hit + clean version+changeset resolution → `hit`.
- Multiple plausible hits, ambiguous owner, deprecated suspicion, or only-help-text match → `weak` with the leading candidate plus alternates.
- No usable hit → `miss`.

Validate the recommendation with `validate-galaxy-tool-discovery` before returning it. Do not rely on prose-only shape checks; downstream phases branch on this contract.

### Caveats baked into the procedure

The procedure assumes — and the skill must surface in its rationale when relevant — the following Tool Shed realities (full detail in component-tool-shed-search §6):

- **Indexes are stale by design.** A freshly published tool may not appear; a deprecated tool may still appear. Treat absence as soft evidence, not proof.
- **Wildcard `*term*` wrapping** disables stemming; spelling matters. Try alternate phrasings before declaring `miss`. In particular an underscored or owner-prefixed **tool-id token** (`integron_finder`, `iuc/integron_finder`) can score zero where the **human name** (`integron finder`) hits — never declare `miss` on a single id-token query (see §1 normalization).
- **No EDAM in shed search** — semantic queries that work in Galaxy's installed-toolbox search will not work here. Stick to lexical name/keyword queries.
- **Same XML id across repos.** Hits collapse only on `(repoName, owner)`; expect duplicates that need triage.
- **Repo-level discovery is a different surface.** For "find me the *package* that contains a tool about X" with server-side `owner:` / `category:` keywords, `gxwf repo-search` is the right command — out of scope for this skill but a known sibling.

### Non-goals

- **Authoring.** This skill never produces a tool wrapper. On `miss`, the harness's `discover-or-author` branch fall-through invokes author-galaxy-tool-wrapper.
- **Caching.** This skill emits a pin recommendation. The caller (or the next phase) runs `galaxy-tool-cache add toolshed.g2.bx.psu.edu/repos/<owner>/<repo>/<tool_id> --tool-version <v>` to populate the cache.
- **Galaxy-instance discovery.** Hitting a running Galaxy server's installed-tool index (EDAM-aware, panel-aware) is a different mechanism — the future `discover-tool-via-galaxy-api` skill. The contrast is sketched in component-tool-shed-search §4.
- **Test-data resolution.** Out of scope; handled by the `test-data-resolution` branch elsewhere in the pipeline.

## Feedback Mode

- Feedback mode is off unless the caller explicitly enables `--feedback` or supplies a feedback-ledger path.
- When enabled, read `_feedback.md` before doing the work and use its registered `foundry-feedback.ledger.yml` protocol.
- Preserve harness-owned run and phase state. Append only concrete observations about a canonical Foundry source asset or a related project that this run showed to be at fault; do not put ordinary workflow requirements in this ledger.
- Before reporting completion, make one explicit pass over the work you just did. Do not ask yourself whether anything was unclear — recall what happened: where you guessed at something the instructions should have settled, needed information this bundle does not carry, hit an instruction that contradicted another or contradicted the artifacts in front of you, used a packaged reference that did not cover your case, or did something the procedure never describes.
- Append an entry for each such event that clears the protocol's bar. If none do, append nothing and report `no feedback` explicitly. Silence and a clean pass are not the same thing, and nothing downstream can tell them apart unless you say which one it was.
- Pass the same ledger path to any subagent used for this work, and merge updates serially so one writer cannot overwrite another.

## Runtime Notes

- Do not read Foundry source files at runtime; use only files packaged in this skill bundle and user-supplied artifacts.
- Preserve declared artifact filenames unless the user or harness supplies explicit paths.
- Carry unresolved assumptions into the output artifact instead of silently inventing missing source evidence.