Generated from
fhir-harness/skills/fhir-ig-base/fhir-ig-create.md— do not edit here.
fhir-ig-create
Skill id:
fhir-ig-create· Package:fhir-ig-base· Instance:fhir-harnessBean3tza
Owner, 2026-10-06: “when asked to create a new FHIR IG …, that can either be done in a new repo or within the folio of an existing harnessed repo. the agent should determine users intent and act accordingly.”
This is the IG-shaped half of
getting-started,
which triages “create a folio” in general. Read that skill’s §1 for how facts
are gathered and §3 for how a question is put. This skill does not restate
them. It adds the one fork getting-started has no branch for: an IG that
starts inside a repository and may leave it later.
When a harness above this one specialises it
An IG built on a harness that needs this one (for example one that adds its
own pre- and post-processing, theme and layout rules) may carry its own
creation skill that specialises this one. If the request names such a
harness’s kind of guide, ask skill_list for that skill and run it instead.
It will route back here for every step it does not change. This skill names
no such harness, on purpose: the bare FHIR layer knows nothing above it.
1. Read three facts — read-only, before anything is written
| fact | how | values |
|---|---|---|
inHarness | a <name>.json instance declaration at the working directory’s root (describeRepository membership harness) | yes / no |
hasIg | an IG source already present: a sushi-config.yaml or an ig.ini at the root | yes / no |
statedWhere | what the user said about where it goes | new-repo, in-repo, existing-ig, unstated |
statedWhere is unstated until the user has said it. “Make me an IG” states
nothing about where. “Start an IG in its own repo” states new-repo. Do not
infer it from the repository you happen to be in.
2. Decide
statedWhere | inHarness | hasIg | route |
|---|---|---|---|
| stated | any | any | what they said |
unstated | no | yes | existing-ig: hand to repo-conversion, scan first |
unstated | no | no | new-repo: the only route that answers itself |
unstated | yes | any | ask, with default in-repo |
The question, when the table says ask
Put it as numbered options, four at most, recommended first, with the default
stated. Load
interaction-modality
first; for some users a typed answer is not available at all.
Where should the new IG live?
- Inside this repository, as a staged sub-KG (recommended). Cheapest to start and to change your mind about. It can move to its own repository later, and nothing outside this repository changes until you say so.
- In a new repository of its own. Creating it is visible outside this repository, so I will ask once more before I create anything.
- Over an IG repository you already have. I scan it first and show you what I find before importing anything.
- Tell me more.
Default if you do not answer: 1. Nothing outside this repository is touched.
Why in-repo is the default: every step of it is reversible with
git revert, and the week of separations it was extracted from (bean
3tza) staged every guide in place first and created repositories only
after the rehearsal was green. A repository is the first irreversible act,
so it is not the first act.
Then ask the name, as a short slug, offering the one derived from what they said as option 1.
3. Route
in-repo — a staged sub-KG
The lifecycle is sub-kg-lifecycle
and its process sub-kg-lifecycle.bpmn; this is what its stage 1 means for an
IG.
- Scaffold the declaration and the seam:
bun run cat init-folio --staged <name> --title "<title>" --repository <owner>/<name> --needs fhir-harness. It writes<name>/<name>.json(repositoryis the planned home, andlivesAtis this repository) and an empty<name>/platform.ts, and nothing at the repository’s root. Never--instancehere: that scaffolds a whole repository. - Declare the graphs as their files arrive. An IG’s graphs are typically
ig-ast,fhir-artifact-indexanddocswithigSite: true. Route every platform import throughplatform.ts: an empty seam on day one costs nothing, and retrofitting one later cost 25 reroutes in one instance. - Get the IG source, one of:
- authored here:
sushi-config.yamlandinput/under the instance, authored withl3-fhir-authoring; - an IG already published elsewhere: ingest its artefact index and
navigation, which record the source repository and commit they read:
bun run cat ingest:ig -- --source <published output> --kind gh-pages --id <name> --base <published url> --out <name>andbun run cat ingest:ig-menu -- --source <ig repo checkout> --out <name>/fhir-artifact-index.
- authored here:
- Build its site from a local checkout:
bun run fhir-harness/scripts/stage-ig-sites.ts --work <dir> --baseurl <baseurl> --only <name> --source <ig repo checkout>(ig-build-pipeline,ig-render-jekyll). - Seed the plan: one bean for the IG, under the epic the work belongs to,
after the existence check in
todo-manager.
From there the IG grows in place, and leaves only through
sub-kg-lifecycle’s two owner confirmations.
new-repo — its own repository
- Confirm before creating. Creating a repository is outward-facing and
is not undone by a revert, so the question in
sub-kg-lifecycle§”7 and 12” is asked first, with default “not yet”. The owner may create it themselves; a session without the permission hands over withagent-handoff. - Mount, don’t declare. The repository gets an
index.config.jsonnaming the layer it builds on (this one, or an overlay above it such as the WHO SMART Base IG) as a remote instance with consent, and theindex.lock.jsonremote-mount.tswrites. No<repo>.jsonand no submodule: an IG repository needs no harness of its own (owner, 2026-10-14). - Then steps 3 to 5 of
in-repo, at the root. - Ask the two build questions before the first push: whether the
repository’s automatic gh-pages builds stay automatic, and whether to
install the just-the-docs site (default yes). The rule and the question
text are
ig-build-pipeline§”Who starts a build”; a repository forked from an upstream IG is the usual case. - Copy the site templates, unchanged.
templates/ig-repo-site/holdsig-ast-refresh.ymlandsite-publish.yml; copy both into.github/workflows/, as they are. An IG repository’s site is built from the AST cache (§”The AST cache lifecycle” ofig-build-pipeline), andig-ast-refresh.ymlis its one writer. Without it the repository has no site, andstage-local.tsrefuses with no cache branch for this IG. The first refresh is dispatched once on the default branch by the owner, or by an agent the owner names for that run. Until it has run, the repository’s preview is not built anywhere: say so and ask. Do not stage it on another repository’s site instead (feature-staging, Which site).
existing-ig
repo-conversion scans first and imports second, never the other way round.
After the import, mount its layer through index.config.json as in
new-repo step 2 (no declaration of its own), then ask the two build questions in ig-build-pipeline
§”Who starts a build”. Then new-repo step 5: copy the site templates if they are
missing. An existing IG repository almost always carries build
workflows that publish on every push.
Anti-patterns
- Creating a repository because the request said “new”. “A new IG” is not “a new repository”. Ask.
- Running
init-folio --instanceinside a harnessed repository for an in-repo IG. It writesAGENTS.md,.mcp.json, a beans store and a session hook into a subdirectory.--stagedis the in-repo mode. - Hard-coding a publisher’s identity here. Template, chrome and publication target belong to a harness above this one.
- Skipping the seam because the IG has no code yet. The first test that imports a platform helper is the first climb.
- Typing a workflow the templates already hold. A repository scaffolded
by hand on 2026-10-15 had no
ig-ast-refresh.yml, so it had no site, and its preview went to another repository’s site. Copytemplates/ig-repo-site/.