Contributing to Skill Forge
July 19, 2026 · View on GitHub
SKF turns code and docs into verified agent skills. Every instruction traces back to a real line of source. See README.md for the pitch; this file covers how to land changes without setting the test suite on fire.
SKF is a BMAD module. For BMAD philosophy, framework conventions, and module-authoring patterns in general, start at docs.bmad-method.org. This doc stays scoped to what's SKF-specific.
What You Can Contribute
- Workflows (
src/skf-*/) — new skill-compilation or lifecycle flows. Example: askf-diff-skillthat compares two versions of the same skill and emits a migration note. - Knowledge fragments (
src/knowledge/) — cross-workflow principles Ferris loads just-in-time. Example: a newsecurity-review.mdthat captures rules reused by CS, QS, and AS. - Forger assets (
src/forger/,src/shared/) — shared agent memory, preferences, or helpers (e.g. tier detection, health-check templates). - Validators (
tools/validate-*.js) — deterministic checks that run innpm run quality. Example: a new validator that flags{installed_path}leaks in step files. - Docs (
docs/,website/) — tutorial / reference / explanation content surfaced at armelhbobdad.github.io/bmad-module-skill-forge. - Ecosystem integrations — new tool bridges (ast-grep, cocoindex, QMD, tessl, Snyk, graphify-style indexers) wired through the tier-aware discovery path.
- Bug reports — always useful, especially if they come in via the workflow health-check loop (see below).
If you're not sure where a change belongs, open an issue and ask before writing code.
Local Setup
Platforms: Linux, Windows, and macOS. Linux and Windows are exercised in CI on every PR (ubuntu-latest + windows-latest matrix); macOS works in practice (POSIX-equivalent to Linux) but isn't CI-gated. On Windows, SKF transparently falls back to NTFS junctions when symlink privilege isn't held — no Developer Mode or admin rights required. Git Bash (bundled with Git for Windows), PowerShell, and WSL2 all work.
Prerequisites:
- Node.js >= 22 — the supported floor (
engines.node); development and CI run Node 24 (see.nvmrc) - Python >= 3.10
- uv — runs the Python test suite
git,gh— used by several workflows and by the health-check loop
git clone https://github.com/armelhbobdad/bmad-module-skill-forge.git
cd bmad-module-skill-forge
npm install # also wires husky pre-commit hooks via "prepare"
npm run quality # run the full local pre-flight
The npm run quality script is your contract with CI. It runs:
format:check(Prettier),lint(ESLint),lint:md(markdownlint)test:schemas,test:install,test:cli,test:workflow,test:python,test:knowledgevalidate:schemas,validate:skills,validate:refsdocs:validate-drift— SKF docs vs. the canonical oh-my-skills output
If npm run quality passes locally, CI should too. The same steps run in .github/workflows/quality.yaml on every pull request.
Workflow for Changes
-
Branch from
main. Name it like the commit scope:fix/skf-test-skill-...,feat/health-check-...,docs/.... -
Match the commit-message convention from the git log. SKF uses conventional-commit prefixes with a scoped subsystem:
feat(skf-create-skill): ...fix(health-check): ...docs(readme): ...ci(health-check): ...refactor(skf-create-skill): ...chore: ...(no scope needed)
git log --oneline -20is the authoritative style guide. Match what you see. -
Reference issues with
Fixes #NNNin the PR body (and optionally in the commit trailer). Use same-repo GitHub issue numbers only — do not reference internal IDs under_bmad-output/todo/or elsewhere; those are author notes, not public contracts. -
Pre-commit hooks run automatically via husky + lint-staged:
eslint --fix,prettier --write, andmarkdownlint-cli2on.mdfiles. They run on staged files only. -
PR description: explain why. What was broken, what does this change, and how did you verify it? Keep it honest and short. The template in .github/ is a starting point; ignore the sections that don't apply.
-
If you used Claude (or any AI assistant) to help write a non-trivial chunk of the change, add a
Co-Authored-By:trailer to the commit — SKF's recent history uses the format:Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>Not mandatory, but we prefer accurate attribution over silent ghostwriting.
The Quality Gate
npm run quality must pass before you push. If it fails:
- Fix the root cause. Do not
git commit --no-verify. Do not disable a rule to make the linter shut up. If a hook is wrong, fix the hook in a separate PR. - If a Python test fails on your machine but not in CI, check your
uvversion and re-runnpm run test:pythonfrom a clean shell. - If
docs:validate-driftfails, you either touched a pinned version/commit SHA that no longer resolves in oh-my-skills, or you added a library reference the whitelist doesn't cover. Fix the reference; don't relax the validator unless the fix is clearly out of scope.
CI re-runs everything on the PR. A green local run and a red CI run means either (a) you have uncommitted files, or (b) your Node/uv versions drift from .nvmrc / test:python. Check both before filing a CI bug.
Releasing
Maintainers only — if you're not cutting a release, skip this section.
- Canonical path:
.github/workflows/release.yaml, triggered via GitHub Actions → Run workflow → chooseversion_bump(alpha/beta/rc/patch/minor/major). That is the only supported route — OIDC-backed publish, required-reviewer gate on thereleaseenvironment, auto-provenance on the npm tarball.
See docs/_internal/RELEASING.md for the full procedure — branch-protection rules, the release environment with its required-reviewer gate, npm Trusted Publisher registration, and the seven-scenario rollback playbook.
Adding a New Workflow Skill
The src/skf-*/ directories each follow the same shape:
src/skf-<name>/
SKILL.md # frontmatter (name, description, "Use when ..."), stages table
references/ # one file per step, loaded one-at-a-time by Ferris
references/ # step-scoped rules, protocols, decision tables
assets/ # step-scoped templates, schemas, output formats
- Start from an existing skill with similar shape —
skf-quick-skillis the simplest,skf-create-skillis the reference for the full pipeline. - Or scaffold with BMAD tooling — the
bmad-workflow-builderskill builds / edits / converts workflows interactively;@Ferris CS(skf-create-skill) is the content-extraction pattern SKF uses for its own skills in the wild. - Frontmatter matters.
validate:skillsenforces SKILL-01 through STEP-07 (seetools/validate-skills.js): SKILL.md must havename+descriptionwith a "Use when" / "Use if" trigger; step files must not havename/description; step count must be 2–10; step filenames must matchstep-NN-<slug>.md. - Manifest. Agent-facing skills (e.g.
skf-forger) require abmad-skill-manifest.yaml. Copy the one fromsrc/skf-forger/and adapt. - Knowledge JiT. If your workflow shares a principle with others, factor it into
src/knowledge/and load it from the step rather than inlining the rule. - Quality review. Before shipping, run a tessl skill review pass on the SKILL.md content — SKF uses tessl for actionability scoring and AI-judge evaluation (see the references under
src/skf-create-skill/assets/). - Register the workflow in
src/module-help.csv(ordering / preceded-by / followed-by fields) and in thedocs/workflows.mdreference table.
Adding Knowledge Fragments
Knowledge lives in src/knowledge/ and is loaded just-in-time by workflow steps — never preloaded.
- Keep each file single-concern: zero-hallucination, confidence-tiers, provenance-tracking, version-paths, etc.
- Add the new file to the Knowledge Map table in
src/knowledge/overview.mdwith its purpose and the workflow codes (CS, QS, US, ...) that consume it. - Reference it from the step that needs it with a
Load:directive (see anyreferences/step-*.mdfor the pattern). - If the principle cuts across ≥2 workflows, it belongs in
knowledge/. If it's step-scoped, it belongs in the workflow'sreferences/instead.
Forger-sidecar (src/forger/) is Ferris's own memory: preferences.yaml and forge-tier.yaml. Changes here should be rare and tied to a real behavioural change in a workflow.
Reporting Bugs
-
Normal bugs: open a GitHub issue with a reproducer — input (URL / package / brief), SKF version (
npm ls bmad-module-skill-forge), capability tier Ferris reported at setup, the error or wrong output, and what you expected. The bug-report template in.github/ISSUE_TEMPLATE/prompts you for the rest. -
Workflow friction: every SKF workflow ends with a health-check reflection step that can file a GitHub issue on your behalf. Reports are auto-deduped by fingerprint — the
.github/workflows/health-check-dedup.yamlAction extracts thefp-XXXXXXXlabel on a new issue, finds any earlier open issue with the same fingerprint, comments "duplicate of #N", upvotes the canonical issue to preserve the signal count, and closes the duplicate. Re-reporting is safe. If you skipped the terminal step in-session, ask Ferris:@Ferris please run the workflow health check for this session. -
Closing out a health-check finding. The reporter's machine keeps a global seen-cache at
$HOME/.skf/health-check-seen.jsonthat stops the same fingerprint being re-reported. Once a finding is fixed, that entry must stop suppressing, or a later regression of the same defect is silently swallowed — the one report the loop most needs to surface. Two mechanisms, in the order they actually fire:- Close the issue as completed, and nothing else is required. The health check reads the issue's own
stateandstateReason, and treatsCLOSED/COMPLETED(or aMERGEDPR link) as a regression trigger on the next sighting. Issue state is shared, so this works for every reporter, on every machine, with no action on their part. Closing as not planned deliberately does not count: that is how the dedup Action closes duplicates and how a wontfix is closed, neither of which is a fix. - Only when there is no issue to close — a finding that was only ever queued locally — hand-edit your own cache entry to
"action": "resolved", keepingissue_urland settingdateto the fix date. This is machine-local, so it clears the suppression for you and nobody else. Prefer deleting nothing:resolvedkeeps the record that the defect was once seen, which is what lets the next sighting be reported as a regression rather than as a first sighting.
- Close the issue as completed, and nothing else is required. The health check reads the issue's own
-
Provenance failures are always bugs. If an AST citation in a SKF-compiled skill doesn't resolve to the claimed line at the claimed commit, that's the whole deal breaking — please file it.
What We Don't Accept
- Features that fork core BMAD conventions. SKF is a module; it follows the framework. If your idea needs BMAD to behave differently, take it upstream to bmad-code-org/BMAD-METHOD first.
- Tests that mock the database / the real extraction pipeline. SKF's validation is meaningful because it runs against real extraction output and real oh-my-skills skills. Mocks that hide that contract don't buy us anything.
- Changes that bypass
npm run quality— skipping hooks, excluding files from linters, loosening a validator to make a PR green. Fix the underlying issue instead. - Documentation that duplicates external canonical sources. Link out to docs.bmad-method.org, agentskills.io, tool docs, etc., rather than restating them. SKF docs are for what's unique to SKF.
- Emoji in source files and docs. Project standard. (Badges and contributor avatars in the README are the exceptions.)
- Drive-by reformats. Please don't reflow whole files or rename things you didn't touch.
Code of Conduct and License
By participating, you agree to the Code of Conduct. Be decent; assume good faith; disagree with the argument, not the person.
Contributions are licensed under the project's MIT License.
Acknowledgement
SKF is maintained in spare hours. Good issues, small focused PRs, and willingness to iterate on review are the most useful things you can send. If SKF saved you an afternoon, a ⭐ or a coffee keeps the forge lit.