Skip to content

Contributing ​

Where does new content go? ​

  • docs/ is for internal engineering records, such as the design and product notes in docs/DESIGN.md and docs/PRODUCT.md. It stays flat, unstructured markdown, read through GitHub's own file viewer. Working plans and specs (docs/plans/, docs/specs/, docs/superpowers/), like audits in docs/audit/, are gitignored: never commit them.
  • docs-site/ (this site) is the published documentation for users and contributors. If you're writing something a user or a first-time contributor should read, it belongs here, not in docs/.

Linting before you commit ​

npm install runs the prepare script, which points git at .githooks/ (git config core.hooksPath .githooks). After that, every commit runs .githooks/pre-commit: it lints any staged .js/.mjs files with eslint and blocks the commit if linting fails. git commit --no-verify skips it. To run the same linter by hand, use npm run lint.

Changesets and releases ​

A changeset is required for a PR that touches packages/core, packages/cli, packages/mcp, packages/server, packages/analyze, packages/sparkforensics, or the root site app (src/, index.html, vite.config.ts, or the root package.json). Run npx changeset add, answer its prompts, and commit the generated .changeset/*.md file. CI's changeset job (scripts/check-changeset.sh) fails the PR otherwise, with instructions to fix it. docs-site/ and docs/ are exempt: doc-only changes don't need one.

Needing a changeset doesn't mean getting published, though. Only packages/cli, packages/mcp, packages/server, and the two alias packages publish to npm. The aliases, packages/analyze (sparkforensics-analyze) and packages/sparkforensics (sparkforensics), hold no code of their own: each depends on sparkforensics-cli and runs its sparkforensics-analyze bin, so npx sparkforensics-analyze works outside a checkout and nobody else can publish under either name. .changeset/config.json's fixed group keeps their versions equal to sparkforensics-cli's, so every CLI release republishes them. The root site (sparkforensics-web) is "private": true and never published; its changeset only bumps its package.json version and writes a CHANGELOG.md entry, via .changeset/config.json's privatePackages.version setting. @sparkforensics/core is the other private package but stays out of this entirely (.changeset/config.json's ignore list): it's vendored into each publishable code package (packages/{cli,mcp,server}) by filesystem copy at pack time (scripts/vendor-core.mjs), not read as a real dependency, so versioning it would have no consumer.

A release itself is two merges, not one: merging your feature PR into main runs .github/workflows/release.yml, which opens (or updates) a "Version Packages" PR collecting all pending changesets. Nothing publishes at this step. Merging that PR lands the version bumps and changelog entries it carries, and the release run that follows runs the full build and test suite, then npm publish for each publishable package whose new version isn't on npm yet.

Publishing a new package name (maintainers) ​

The release workflow publishes through npm Trusted Publishing, which can't create a package name that doesn't exist on npmjs.com yet. A new publishable package needs one manual publish from a maintainer's npm account first, then a Trusted Publisher entry. All five current packages (sparkforensics-cli, sparkforensics-mcp, sparkforensics-server, sparkforensics-analyze and sparkforensics) have their Trusted Publisher entries; this only applies to a package added later. Until it's done, that package's publish step fails and the release run exits non-zero; packages that don't depend on it still publish.

First add the package to PACKAGES in scripts/publish-packages.mjs and to the path regex in scripts/check-changeset.sh (the comments in both list every place to keep in sync); an alias of the CLI also goes in .changeset/config.json's fixed group. Then:

  1. From a clean checkout of main, logged in with npm login, publish the new package at the version in its package.json:

    bash
    (cd packages/<new-package> && npm publish --access public)
  2. On npmjs.com, open the package's Settings, add a Trusted Publisher for GitHub Actions with organization shuffle-works, repository sparkforensics, workflow filename release.yml and no environment, and save.

  3. Optional: in the same settings page, set publishing access to require two-factor authentication and disallow tokens, so only the workflow can publish from then on.

scripts/publish-packages.mjs skips a version that's already on the registry, so the next release run won't try to republish the bootstrap version.

For the full setup and test workflow, see Development setup and Testing & verification.