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.
83 lines
3.5 KiB
Markdown
83 lines
3.5 KiB
Markdown
# 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](../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](../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](./library.md) | Public API design, the type-level contract, and its limitations |
|
|
| [workflow.md](./workflow.md) | Branching and merging, script prefixes, feedback tiers, commit messages |
|
|
| [tooling.md](./tooling.md) | Toolchain choices and configuration, editor setup |
|
|
| [testing.md](./testing.md) | Test strategy and type-driven development |
|
|
| [docs.md](./docs.md) | Validating the Markdown code fences in the prose docs |
|
|
| [ci.md](./ci.md) | CI pipeline, runner image, coverage serving |
|
|
| [publishing.md](./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:
|
|
|
|
```md
|
|
## 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](../CONTRIBUTING.md) in the same commit and cross-link.
|
|
Never change a rule there without updating its rationale here.
|