Skip to content

Latest commit

 

History

History
102 lines (78 loc) · 4.85 KB

CONTRIBUTING.md

File metadata and controls

102 lines (78 loc) · 4.85 KB

Contributing

Bug fixes, tests, documentation, and focused enhancements are welcome. Spec questions are welcome too: if SPEC.md and the code disagree, that is a bug in one of them, and saying which is half the work.

Do not report an exploitable vulnerability in a public issue or pull request. Follow SECURITY.md to send a private report.

The rules that are load-bearing live in AGENTS.md

AGENTS.md is the one copy of the things a change here can quietly break — the golden vectors and why a failing one means the wire format moved, exact canonical encoding, fail-closed on the money path, and the MCP server holding nothing. It is written for whoever edits the code, human or model. Read it before your first pull request; it is not restated here, because a second copy would drift from it.

Development setup

pnpm only — a stray package-lock.json must not be committed. The version is pinned by packageManager in package.json, so corepack picks it up on its own.

pnpm install --frozen-lockfile

Turn on the repository's hooks once, in your clone:

git config core.hooksPath .githooks

That is one hook, commit-msg, and it refuses a message carrying a coding-agent session link. Those URLs resolve for nobody but the account that made them, and a public history cannot take one back — this repository's history was squashed once to remove them, and the hook exists so that does not happen twice. Git will not run a hook out of a fresh clone on its own, which is why the same check also runs on every pull request (scripts/no-agent-trailers.sh, one definition, two callers).

CI runs exactly these three against the code, in this order (plus the commit-message scan above):

pnpm install --frozen-lockfile
pnpm -r --include-workspace-root build
pnpm -r --include-workspace-root test

--include-workspace-root is not optional: the library is the root package (mcp/ is the only child), so a plain pnpm -r skips it and mcp/ then builds against a stale dist/. The same reason means you must build before running examples/live-deal.mjs — it imports dist/.

Making a change

  • One problem per pull request. Bug fixes and small documentation improvements can go straight to a pull request; discuss a change to the wire format, the state machine, or the rail interface in an issue first, because those are the things other people's already-posted frames depend on.
  • Add tests for behavior that changes. A bug fix should include a regression test that fails without the fix. Prefer assertions on observable behavior over private implementation details.
  • Keep SPEC.md and the code in agreement, and say in the pull request which one you treated as correct.
  • Every user-visible change gets a CHANGELOG.md entry under [Unreleased], following Keep a Changelog. Leave version bumps and dated release sections to a maintainer.
  • Avoid unrelated refactors, formatting sweeps, or version bumps in the same pull request.
  • New surface on the money path: say what a hostile counterparty gets from it, or say "nothing".

Pull requests

Explain what changes for a caller and why, link related issues, and confirm the three CI commands pass locally. Keep the branch current with main; address review with additional commits or a clean rebase. All required checks must pass before merge.

Releasing (maintainers)

Publishing runs from .github/workflows/release.yml on a v* tag, and holds no registry token: pnpm exchanges the workflow's OIDC id-token for a short-lived one and attaches provenance, so there is no long-lived secret in this repository to leak. A fork cannot push a tag, so there is no route from an untrusted pull request to the registry.

One release:

  1. Fold [Unreleased] in CHANGELOG.md into a dated section and set the version in both package.json and mcp/package.json — the workflow refuses to publish if the tag and the two manifests disagree.
  2. Tag it vX.Y.Z and push the tag.
  3. Approve the npm environment when it asks.

pnpm -r --include-workspace-root publish runs in dependency order, so @flop-labs/tclk lands before the MCP server that depends on it, and already-published versions are skipped — a re-run after a partial failure finishes the release rather than failing on what already went out.

To rehearse without publishing, run the workflow manually: workflow_dispatch takes the same path and ends in --dry-run.

Bootstrapping. npm can only attach a trusted publisher to a package that already exists, so the very first version of each package goes out by hand (pnpm publish, authenticated locally). After that, configure each package's trusted publisher on npmjs.com — this repository, workflow release.yml, environment npm — and every later release comes from the tag.