Skip to content

feat(openehr-specs): add scaffold skill for the standard specification-repo file set - #6

Merged
sebastian-iancu merged 1 commit into
mainfrom
feat/scaffold-skill
Oct 7, 2026
Merged

sebastian-iancu merged 1 commit into
mainfrom
feat/scaffold-skill

Conversation

@sebastian-iancu

Copy link
Copy Markdown
Member

Summary

Adds /openehr-specs:scaffold, a user-only skill that initialises a specification repository, or brings an existing one up to a standard file set. It adds nothing to the always-on context (disable-model-invocation: true).

A stdlib-only script, scripts/scaffold.py, does the file work. The skill plans first (nothing is written), asks the user to confirm any guessed variables, shows each file's action, and applies only what was approved.

What it installs

File Kept up to date by
AGENTS.md Managed regions between invisible markers: the openehr-specs@openehr plugin table, the Docker build invocation, and the commit and branch conventions built around the Jira key (Changes for <KEY> - <what changed>). Text outside the markers is the repo's own and is never touched.
.claude/settings.json Merged: registers the openehr marketplace and enables openehr-specs. Existing values win, and items the user removed are not added back.
.gitignore, .asciidoctorconfig Missing lines appended.
manifest.json, LICENSE, README.md Written once, never changed. LICENSE is CC BY-SA 3.0, or Apache 2.0 for ITS-*; an existing README.adoc counts as a README.
.claude/CLAUDE.md Replaced only while unedited since it was scaffolded.

Versioning and upgrades

assets/template-set.json is the schema: a revision number, the variables, and a strategy per file. Each scaffolded repo records its revision, variables and file hashes in .claude/scaffold.json. A later run compares the recorded revision with the latest, calculates the migration path (migrations/NNNN.json), and uses the hashes to tell an untouched file from a hand-edited one. A hand-edited file or region is reported as a conflict and is never overwritten without --overwrite. There are three modes: init, upgrade (some files exist, either never scaffolded or at an older revision) and current.

CI keeps this honest: scripts/validate.py runs the template-set check, which fails when a template, variable or file entry changes without a new revision and migration file.

Other changes

  • scripts/validate.py checks the template set (once per plugin) and reports an unimportable script as an error, not a traceback.
  • CI also runs the unit tests (scripts/test_scaffold.py, 109 tests).
  • .gitignore ignores __pycache__/; READMEs, AGENTS.md, docs/testing.md, docs/skill-authoring.md, CONTRIBUTING.md and the PR template are updated.

For reviewers

  • Where the content comes from. The standard file set and the commit style are derived from a survey of the 18 specifications-* clones, recorded in references/maintaining.md. In BASE, RM and AM the leading Changes for SPECXX-NN - … form dominates (154 commits against 24 with the key last), so it is primary. Across all nine key-heavy repos the trailing <text> (SPECXX-NN) form is more common (333 against 221), so the template says it is understood. The licence texts are byte-identical copies of BASE's and ITS-REST's LICENSE.
  • Inferred, not surveyed. "Do not stage regenerated docs/*.html" comes from BASE's practice and its AGENTS.md, not from every repo.
  • README. The seed target is README.md, as requested, but 15 of the 18 clones use README.adoc. exists-alternative stops a duplicate where one exists. Say if new repos should get .adoc.
  • settings.json grants. The template mirrors BASE, RM and ITS-REST: three third-party plugins, pre-approved git add, git commit and git diff, WebFetch on specifications.openehr.org, and three read-only Atlassian MCP calls. The skill tells the user this before applying.
  • Descriptor location. .claude/scaffold.json and not manifest.json, which is human-owned and read by the publisher; a merge would reformat it and put hashes into every diff. I did not check every consumer of manifest.json.
  • Version. A new skill is a minor change under docs/versioning.md; no bump here, per CONTRIBUTING.md.
  • Reviewed. plugin-dev:skill-reviewer, plugin-dev:plugin-validator and feature-dev:code-reviewer each read it. The findings that held up are fixed: CRLF and file-mode preservation, unpaired region markers, removed items staying removed, symlinks, atomic writes, clean JSON errors, and several documentation errors.
  • Python. scaffold.py targets Python 3.8+. scripts/validate.py:26 already uses dict | None, which fails on 3.8 and 3.9; CI runs 3.12, so I left it.

Limits

  • AsciiDoc specification repos only. specifications-ITS-REST is OpenAPI built with make, so its AGENTS.md needs its own variant; until then pin agents, claude-md and asciidoctorconfig there.
  • One BMM schema per repo; with several (AM, LANG) the highest version is used and a warning lists the others.
  • Written for Claude Code: the script path comes from ${CLAUDE_SKILL_DIR} (SKILL.md says what to do where it is not expanded).

Checklist

  • python3 scripts/validate.py passes (also claude plugin validate plugins/openehr-specs --strict, scaffold.py check, and python3 -m unittest discover -s scripts -p 'test_*.py', 109 tests)
  • Skill triggering tested locally in Claude Code (see docs/testing.md) — partly: a nested headless claude -p --plugin-dir … ran the skill twice (an empty directory, and a copy of BASE's root files), and followed the steps with no permission prompts. Those runs predate the final renames (adopt to upgrade, descriptor to .claude/scaffold.json), which are covered by the tests and a CLI run, not a live session
  • Cursor install tested locally when plugin or manifest content changed (see docs/install.md) — not done
  • Both marketplaces updated when plugin metadata changed (n/a: no manifest or version change)
  • CHANGELOG.md updated under Unreleased; no version bump
  • Content grounded in published openEHR specifications — no invented identifiers (conventions from the survey above and BASE's AGENTS.md; settings keys from the Claude Code docs; the licence texts are verbatim)

🤖 Generated with Claude Code

…n-repo file set

/openehr-specs:scaffold initialises a specification repository, or brings an
existing one up to the standard file set. It is a user-only skill, so it adds
nothing to the always-on context.

A stdlib-only script (scripts/scaffold.py) does the file work; the skill plans
first, asks the user to confirm guessed variables, and applies only what was
approved. Files and how each is kept up to date:

- AGENTS.md: managed regions (plugin table, Docker build, Jira-key commit and
  branch conventions) between markers; the rest is the repo's own.
- .claude/settings.json: merged; registers the openehr marketplace and enables
  openehr-specs. Items the user removed are not added back.
- .gitignore, .asciidoctorconfig: missing lines appended.
- manifest.json, LICENSE (CC BY-SA 3.0, or Apache 2.0 for ITS-*), README.md:
  written once, never changed.
- .claude/CLAUDE.md: replaced only while unedited since it was scaffolded.

The file set is versioned (assets/template-set.json: revision, variables, a
strategy per file). Each scaffolded repo records its revision, variables and
file hashes in .claude/scaffold.json, so a later run calculates the migration
path to the latest revision and tells an edited file from an untouched one.
Modes are init, upgrade (never scaffolded, or an older revision) and current.

scripts/validate.py also checks the template set (templates render, revisions
have migration files, the digest matches), and CI runs the 109 unit tests in
scripts/test_scaffold.py.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@sebastian-iancu
sebastian-iancu merged commit 2fb5547 into main Oct 7, 2026
1 check passed
@sebastian-iancu
sebastian-iancu deleted the feat/scaffold-skill branch October 7, 2026 20:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant