# Contributing to `simplicio-prompt`

Thanks for taking the time to dig in. This document is the load-bearing
guide for everything that touches code, prompts, releases, or process.
Read it once end-to-end if you're contributing anything beyond a typo —
it's short on purpose.

The high-level story:

- The repo is canonically dual-published as both an **npm package**
  (the CLI + the prompt content + multi-IDE installer) and a **PyPI
  package** (the real-subagent runtime + provider clients). Both live
  here so they stay in lockstep.
- An **optional Rust extension** (`rust/`) accelerates a small set of
  Python hot paths and is opt-in via `maturin develop`. It is **not**
  bundled in the PyPI wheel today.
- Strategic direction is tracked by the **roadmap epic
  ([#28](https://github.com/wesleysimplicio/simplicio-prompt/issues/28))**:
  Phase 0 hygiene (shipped 1.10.1) → Phase 1 diverse-prompt fan-out
  (v1.11) → Phase 2 behavior consensus (v1.12) → Phase 3 adversarial
  pairs (v2.0). Empirical validation lives in
  `simplicio-dev-cli`'s bench harness, not here.

## Local setup

```bash
git clone https://github.com/wesleysimplicio/simplicio-prompt
cd simplicio-prompt
npm install              # no runtime deps — only dev tooling if any is added later
```

The Python kernel is dependency-free; nothing to install for the
runtime. Build tooling (`build`, `twine`, `maturin`) is only needed if
you cut a release locally or build the Rust extension.

Optional Rust extension (for the parity-tested accel layer):

```bash
pip install maturin
cd rust && maturin develop --release
# back in repo root:
python -c "from kernel.utils import accel; print(accel.backend_name())"  # -> 'native'
```

Without the Rust build, `accel.backend_name() == 'python'` and the
parity tests in `tests/test_accel.py` auto-skip the cross-backend
assertions.

## Running tests

```bash
npm test                 # runs both suites, the canonical command
npm run test:node        # 4 suites: cli + hooks + cache + targets
npm run test:py          # unittest discover under tests/
```

CI runs the same `npm test` across **Python 3.10 / 3.11 / 3.12** on every
push to `main` and every PR — see `.github/workflows/tests.yml`. If
`npm test` is green locally, CI should be green.

Adding a new test file? Wire it into `package.json::scripts.test:node`
so it runs in CI. Python tests are picked up automatically by the
`unittest discover` glob (`test_*.py`).

## Branch + commit conventions

Branch names: `<type>/<short-slug>`. Examples:

- `feat/phase-1-diversifier`
- `fix/cli-error-handling`
- `refactor/integrate-kernel-utils`
- `chore/release-1.11.0`
- `docs/contributing`
- `ci/wheels-matrix`

Commit messages follow a loose
[Conventional Commits](https://www.conventionalcommits.org/) shape:

```
type(scope): short imperative subject

Optional body explaining the why. Reference issues by number; close
issues with `Closes #<n>` so the issue auto-closes on merge.
```

Types in use: `feat`, `fix`, `refactor`, `test`, `docs`, `chore`, `ci`,
`perf`. Subjects in present-tense, lowercase, no trailing period. Keep
the body focused on the **why** — the diff already says **what**.

## Roadmap-aligned work

Issue-tagged work matters more than spontaneous improvements. Before
opening a non-trivial PR, check the
[roadmap epic (#28)](https://github.com/wesleysimplicio/simplicio-prompt/issues/28)
and the issue lifecycle:

1. Open or claim an issue. State your approach in a comment.
2. Branch from `main`, never from a release branch.
3. Open a **draft PR** with `Closes #<n>` in the body so the linkage is
   automatic.
4. Keep PRs small. The recent merge cadence (single-purpose PRs that
   tackle exactly one issue) is the target.

## Editing the prompt templates

The two templates in `prompts/` are the **product** for npm consumers.
Changes there have the highest blast radius:

- `prompts/agent-runtime-execution-prompt.md` — the ONE-SHOT default
  shipped to every multi-IDE target.
- `prompts/agent-runtime-batch.md` — the BATCH opt-in for fan-out work.

Before changing either:

- Read the
  [bench report in simplicio-dev-cli](https://github.com/wesleysimplicio/simplicio-dev-cli)
  so the change is informed by evidence, not vibes.
- Run the existing E2E CLI tests (`tests/cli.test.mjs`) — they assert
  on specific markers in the rendered template (`[CLI-6LAYER]`,
  `single deliverable artifact`, `Hilbert-indexed tuple graph`). If
  your edit changes those, update the assertions in the same PR.
- The same content is also embedded by `plugins/claude-code/hooks/runtime-directive.md`
  (and `-batch.md`). The hook is the always-on injection point, so
  keep the two surfaces consistent.
- Phase 0 anti-pattern: **don't grow the ONE-SHOT body**. Every token
  added near the tail is a quartile of mid-tier models lost.

## Release flow

There's a single canonical sequence. CI does the publish step; humans
do the bump.

1. **Update `CHANGELOG.md`.** Bump the `[Unreleased]` section into a
   new `[X.Y.Z]` entry with the date and a one-line "what + why".
2. **Bump version in three files** (these must always agree):
   - `package.json`
   - `pyproject.toml`
   - `kernel/__init__.py` (`__version__`)
   The `release.yml` workflow has a `version cross-check` step that
   fails the build if any of the three disagrees — that's the
   mechanical safety net that prevents the historical drift documented
   in #33.
3. **Open a `chore/release-X.Y.Z` PR**, merge.
4. **Tag the merge:**
   ```bash
   git checkout main && git pull
   git tag vX.Y.Z
   git push origin vX.Y.Z
   ```
   The `release.yml` workflow does the rest: build, twine check,
   PyPI publish, npm publish, fresh-venv smoke install. If a secret is
   missing or the version cross-check fails, **no publish happens** —
   the failure is loud, not silent.

Secrets the workflow needs (one-time setup on the repo):

- `PYPI_API_TOKEN` — project-scoped automation token.
- `NPM_TOKEN` — `Automation` type (publish-only).

If npm falls behind after PyPI has already published a version, use the
manual **npm release** workflow instead of re-running `release.yml`. It
checks out the requested ref, verifies `package.json` matches the
expected version, runs `npm whoami`, performs `npm pack --dry-run`,
publishes to npm, then verifies the registry version, the `latest`
dist-tag, `npx simplicio-prompt@<version> --version`, and the raw prompt
smoke check.

If you have to publish manually for some reason (CI broken, etc.):

```bash
python -m build
python -m twine check dist/*
python -m twine upload dist/*
npm publish --access public
```

…but the existence of working CI means manual publish should be a
once-in-a-blue-moon event. The drift in #34 happened because manual was
the only path.

## Reporting bugs / proposing features

- **Bug:** open an issue with the bug report template. Minimal repro is
  required; including Python / Node / OS / model versions is gold.
- **Feature:** open an issue with the feature request template. Use case
  first; don't open a PR for a non-trivial feature without an issue
  conversation — it's often cheaper to discuss the shape before code lands.
- **Pull requests** use `.github/PULL_REQUEST_TEMPLATE.md`; the form
  asks for the `Closes #` linkage and roadmap-phase tag described above.

The issue and PR templates show up automatically on GitHub's New Issue /
New PR pages.

For prompt-related findings: the most credible bug reports include the
exact bench harness invocation and the model output that contradicts
expectations.

## Security disclosures

**Do not** open a public GitHub issue for a security vulnerability. See
[`SECURITY.md`](SECURITY.md) for the private reporting channels and the
disclosure timeline.

## What we don't do

- We don't add runtime dependencies to the Python kernel. The
  zero-deps property is load-bearing for the "drop in anywhere"
  pitch. Optional accelerators (`orjson`, Rust extension) are fine —
  they must always have a transparent fallback.
- We don't ship single-call wrappers around LLM providers. That's
  `simplicio-cli`'s territory; this repo is the **fan-out runtime**.
- We don't extend the ONE-SHOT template with new instructions to fix
  a single failing case. Template hygiene is a hard rule — if the
  prompt needs to grow, the work belongs in BATCH.

## Code of conduct

Be technical, be specific, be honest about evidence. The bench reports
in `simplicio-dev-cli` are the source of truth — they sometimes
contradict the README. When that happens, the README is wrong; fix it.

The full code is in [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md), including
the private reporting channel for behavior that violates it.
