Files
tmu 30d97a9209 ✨ Compile doc code fences into tests
Every `ts`-tagged fence in README.md / CONTRIBUTING.md now becomes an
executed `node:test` case in a gitignored generated file, so a
documented example cannot drift from the API. The generator hoists and
merges the leading imports, rewrites the library specifier to the
`#test-tiny-pattern-ts` alias, and rejects a fence with no describing
paragraph or one that re-imports a prelude module.

CI regenerates via `pretest:ci`; `create:doc-tests` runs the generator,
formats, then typechecks the output against a scoped tsconfig that
relaxes `noUnusedLocals`. c8's default excludes already omit the
generated `*.test.ts`, so `test:ci` is unchanged.
2026-09-24 11:53:29 +00:00

3.5 KiB

Development documentation

Why this project works the way it does: the decisions, what was rejected, and the shortcomings and known issues we carry. Written for maintainers and contributors.

The actionable rules — setup, running, testing, submitting — live in CONTRIBUTING.md. Each fact is written once: the rule there, the reason here; neither restates the other, and where a fact is useful in both they link. Read the relevant file before changing an area, and when a rule changes update its rationale here in the same commit.

User-facing documentation is README.md. docs/ is deliberately unused: that name is reserved for the future user documentation site, and deploying it is out of scope. These files are not part of that site.

Layout

One file per category:

File Covers
library.md Public API design, the type-level contract, and its limitations
workflow.md Branching and merging, script prefixes, feedback tiers, commit messages
tooling.md Toolchain choices and configuration, editor setup
testing.md Test strategy and type-driven development
docs.md Validating the Markdown code fences in the prose docs
ci.md CI pipeline, runner image, coverage serving
publishing.md Release and npm publishing

We start with one file per category so each area stays small enough to hold in mind; a category that outgrows it becomes a folder with an index, and the links in CONTRIBUTING.md and README.md point at the category, not a single decision.

Decision blocks

Record every non-obvious choice as a block in the relevant category file:

## Runner image

#### Decision (2026-09)

Bake Node into the CI job image at the setup-node tool-cache layout instead
of downloading per job.

#### Why

- ...

#### Rejected

- Gitea Pages / per-job download
- force-pull

#### Known issue

- a Dockerfile-only change re-pushed under an unchanged tag is invisible to the runner
    - recover with `docker rmi <image>`
  • The date is the month the decision was made, not when the file was edited — the anchor for "current" versus "was current once".
  • Rejected stops the project re-litigating the same alternatives; an empty one usually means they were never written down.
  • Known issue is where shortcomings live. A caveat not tied to one decision goes under a ## Known issues section at the end of the file.
  • Replace a superseded decision in place rather than archiving it; git history is the archive.
  • Terse is the point: humans skim and agents imitate the style already in the file, so verbosity compounds edit over edit. Grammar loses to density here on purpose.

Adding to these docs

  1. Pick the category: library, workflow, tooling, testing, ci, publishing.
  2. Add or update a decision block; keep existing text unless the decision changed.
  3. If an actionable rule changes, update CONTRIBUTING.md in the same commit and cross-link. Never change a rule there without updating its rationale here.