# Contributing

The most useful contribution is traceable evidence that the contract is unclear, unimplementable, or wrong. Concrete counterexamples beat endorsements.

**An alternative or prior result that makes part of this unnecessary is a successful outcome, not a loss.**

## What helps most

- **Ambiguity reports** — name a file and anchor, then give two reasonable conflicting readings.
- **Fixture corrections** — show how an implementation could satisfy a case while violating its intent, or why a case is nondeterministic.
- **Implementation reports** — what actually happened when you implemented a profile directly or projected an existing backend, including where the abstraction lost useful behavior.
- **Contract reductions** — show that a smaller Core still completes the class's ten jobs.
- **Semantic counterexamples** — two operations that look alike but differ in target space, state, effect, lifecycle, or agent workflow.
- **Degradation cases** — optional behavior that could vanish or be substituted with no observable result.
- **Prior art** — link a primary source and say which part of this it should constrain, replace, or remove.
- **New capability classes** — proposed as a contract with a stated job and a plug-in test, not as a directory label.

## Report an ambiguity

Open an issue titled `ambiguity: <file>#<anchor>` with the two interpretations, the observable difference between them, and a proposed fixture or wording change if you have one. Ambiguity in contract text is a specification defect; resolve it with an executable case where possible.

## Change rules

1. `profile.json` is authoritative. Markdown that disagrees with it has the bug.
2. A behavioral promise requires a fixture. Change the descriptor and its fixtures together.
3. Core is all-or-nothing. Partial support is not a baseline claim.
4. Every non-baseline member declares what its absence costs.
5. Direct and projected implementations are held to the same cases.
6. Preserve stable anchors in the numbered spec chapters — profiles, decisions, and the site cite them by name.

Terminology is in [`GLOSSARY.md`](GLOSSARY.md). Related work already considered is in [`PRIOR-ART.md`](PRIOR-ART.md).

## Working on the repository

Node.js 20 (see [`.node-version`](.node-version)), npm with the committed lockfile, and PowerShell 7 for artifact validation.

```powershell
npm ci
npm test                      # build the site, then check site, simulation, and research
pwsh ./scripts/validate.ps1   # check profiles, fixtures, links, and anchors
```

| Command | Purpose |
|---|---|
| `npm run serve` | Eleventy dev server |
| `npm run build` | Clean and build `src/` into `dist/` |
| `npm run check` | Check the simulation and an existing `dist/` |
| `npm run research:check` | Validate research ledgers and derivations |
| `npm run research:derive` | Rebuild structural and identity-candidate artifacts |

Neither validation path is a conformance runner. `npm test` checks the generated site, verifies that the native and projected simulations receive equal profile requests and reach equal comparable outcomes while emitting different backend traces, and re-derives every published research measurement. `validate.ps1` checks the artifacts themselves.

**What `validate.ps1` will and will not check.** A check belongs there only if it would catch a bug in a profile nobody has written yet. It does not pin the wording of an existing profile — decisions belong in [`decisions/`](decisions/), not in regexes that fail the moment someone improves a sentence.

### Website

Eleventy reads `src/` and writes `dist/`. `dist/` is generated; never edit or commit it.

- `src/index.njk` — the entry page; `src/dialects.njk` and `src/research.njk` — the evidence pages
- `src/_includes/base.njk` — document shell; `src/_data/site.js` — metadata and asset revision
- `src/assets/demo-engine.js` — the deterministic simulation; `src/assets/demo.js` — its browser controller
- `.eleventy.js` — copies public artifacts alongside the pages, enumerating research paths explicitly so rights-limited material can never be copied wholesale

Two things to know before editing:

- **Add every new CSS or JS asset to `src/_data/site.js`**, so the revision hash changes with the asset. Local builds hash the files; Cloudflare builds use `CF_PAGES_COMMIT_SHA`.
- **Reusing a styled class means adopting its child structure.** `scripts/check-site.js` asserts the shape each grid-based component expects, because a mismatch renders wrongly while every other check stays green.

Essential copy and the worked calls must remain readable without JavaScript.

### Delivery

Cloudflare Pages builds from the Git repository: production branch `main`, build command `npx @11ty/eleventy`, output `dist`, custom domain `classprofiles.org`. GitHub Actions validates but does not deploy, and there is no Wrangler path. After a push, confirm the deployed HTML's `build-revision` and the asset query strings both carry that commit SHA. A failed build leaves the previous deployment live.

Contributions are accepted under the repository's [Apache-2.0 license](LICENSE).
