feat!: docs/ sorted into tutorials, how-to, reference, explanation plus unshipped docs/dev/; explanation pages and developer guide moved, human docs English (#187)
The seven explanation pages move to docs/explanation/ without a stub, DEVELOPMENT.md becomes docs/dev/development.md (translated to English), dist export leaves docs/dev/ out, docs verify rejects a file outside the five areas, and AGENTS.md states that the stack's human documentation is English. Required migration 9.0.0-docs-diataxis rewrites the old path in an instance's own kb/CONVENTIONS.md. Files changed: - .wikitool-kb.json - AGENTS.md - CHANGES.md - CLAUDE.md - DEVELOPMENT.md - INSTALL.md - README.md - VERSION - docs/dev/development.md - docs/explanation/README.md - docs/explanation/knowledge-and-commitment.md - docs/explanation/language-boundaries.md - docs/explanation/model-and-effort-selection.md - docs/explanation/ownership-and-templates.md - docs/explanation/pipeline-rationale.md - docs/explanation/version-model.md - docs/explanation/why-gates-are-code.md - docs/how-to/README.md - docs/knowledge-and-commitment.md - docs/language-boundaries.md - docs/model-and-effort-selection.md - docs/ownership-and-templates.md - docs/pipeline-rationale.md - docs/reference/README.md - docs/tutorials/README.md - docs/version-model.md - docs/why-gates-are-code.md - instructions/CONTRACT.md - instructions/dev/dev-setup.md - instructions/dev/doc-pull-through.md - instructions/dev/stack-close/SKILL.md - instructions/dev/stack-mode.md - instructions/gtd-weekly-review/SKILL.md - instructions/ingest-queue.md - instructions/migrations/6.0.0-type-guidance-split.md - instructions/migrations/9.0.0-docs-diataxis.md - instructions/upgrade-instance.md - kb/CONVENTIONS.md - kb/CONVENTIONS.md.template - tools/CONTRACT.md - tools/chemenu/commands/dist_cmd.py - tools/chemenu/commands/docs_verify.py - tools/chemenu/commands/new_page.py - tools/chemenu/commands/task_cmd.py - tools/chemenu/tasks/protocol.py - tools/chemenu/tests/test_dist_cmd.py - tools/chemenu/tests/test_docs_verify.py - tools/chemenu/tests/test_git_publish.py - tools/chemenu/tests/test_toc.py - types/type-guidance.md Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SnAJ7Z3CpVD3PRbN73QtU2
This commit is contained in:
1 parent
0e15972ee7
commit
d66a3f65f4
43 files changed
+756
-324
No files matched your search
@@ -0,0 +1,196 @@
|
||||
# Developing this stack
|
||||
|
||||
This document is for people working on `tools/wikitool`, the type schema or the
|
||||
instruction/skill layer itself - not for the operators of an instance. For the other side
|
||||
(installing, upgrading and running an instance) see [INSTALL.md](../../INSTALL.md).
|
||||
|
||||
**This file is not shipped.** It lives under `docs/dev/`, the human counterpart of
|
||||
`instructions/dev/`, and `tools/wikitool dist export` excludes both directories wholesale: a
|
||||
distributed instance has no release workflow, no CI and no issue board, so it needs no guide to
|
||||
them. The reason is a comment at `dist_cmd.DOCS_DEV_ONLY`, so that a later session does not
|
||||
"repair" the apparent gap. And because it is not shipped, this file may link into
|
||||
`instructions/dev/` - unlike a shipped document such as `README.md`, which
|
||||
`instructions verify` checks on exactly that point.
|
||||
|
||||
<!-- wikitool:toc -->
|
||||
## Contents
|
||||
|
||||
- [Development environment](#development-environment)
|
||||
- [`dist export` as a build and test tool](#dist-export-as-a-build-and-test-tool)
|
||||
- [A release feed in a non-public repository](#a-release-feed-in-a-non-public-repository)
|
||||
- [The release workflow](#the-release-workflow)
|
||||
- [The CI half](#the-ci-half)
|
||||
- [Stack development as a session type of its own](#stack-development-as-a-session-type-of-its-own)
|
||||
<!-- /wikitool:toc -->
|
||||
|
||||
## Development environment
|
||||
|
||||
Work on the stack happens in a clone of this repository. Such a clone is **not an instance** and
|
||||
never becomes one. Instances come only from releases - see [INSTALL.md](../../INSTALL.md).
|
||||
|
||||
```bash
|
||||
git clone https://gitea.nehmer.net/torben/chemenu.git
|
||||
cd chemenu
|
||||
```
|
||||
|
||||
Then have the agent run `instructions/bootstrap.md`: the preflight, then
|
||||
`tools/wikitool instructions sync`. The agent's side of it - what differs here from an instance,
|
||||
and how `dist export` runs as a test tool - is
|
||||
[instructions/dev/dev-setup.md](../../instructions/dev/dev-setup.md).
|
||||
|
||||
What a clone has and an instance does not:
|
||||
|
||||
- **The demo corpus.** Some 170 pages documenting the stack itself: gates, lint, versioning,
|
||||
search, the wiki pattern. It is a testbed and a walkable example, not a productive knowledge
|
||||
base. What may be changed in it is governed by
|
||||
[instructions/dev/corpus-policy.md](../../instructions/dev/corpus-policy.md).
|
||||
- **A demo persona** in `USER.md`/`SOUL.md`. `doctor` reports both as filled in. They describe
|
||||
the demo setup, not you.
|
||||
- **Telemetry on.** Without `.wikitool-release.json` the clone is the measuring station the stack
|
||||
evaluates itself with ([EVALS.md](../../EVALS.md) § "Whether it runs at all").
|
||||
- **`instructions/dev/`, `docs/dev/`, `commonplace/` and `.gitea/`.** `dist export` ships none
|
||||
of them.
|
||||
|
||||
`ENVIRONMENT.md` is missing after every clone, because the file is gitignored: it describes a
|
||||
checkout, not the repository. Creating it (template `ENVIRONMENT.md.template`, step 5 in
|
||||
`instructions/bootstrap.md`) spares every stack session the questions about harness, `gitea-mcp`
|
||||
and remote.
|
||||
|
||||
### `dist export` as a build and test tool
|
||||
|
||||
`tools/wikitool dist export <empty directory>` writes exactly the tree a release ships: the
|
||||
machinery without wiki content, without git history, without `instructions/dev/` or `docs/dev/`.
|
||||
That is how you check before a release what would ship (`--dry-run` only lists it). And it is
|
||||
how you replay the installation path without waiting for a release: build a tarball from it the
|
||||
way `.gitea/workflows/release.yml` does, then start the preflight script in an empty directory
|
||||
with `--archive <tarball>`. The CI step "The distribution works as a fresh instance" in
|
||||
`.gitea/workflows/ci.yml` does exactly that.
|
||||
|
||||
For a real instance such an export is not a way in. It lacks the release origin in its stamp,
|
||||
and `dist upgrade --latest` later compares against a state that never existed as a release.
|
||||
|
||||
### A release feed in a non-public repository
|
||||
|
||||
Whoever runs the stack from a repository of their own that is not public, and upgrades instances
|
||||
from there, points `WIKITOOL_UPDATE_URL` at its feed. There is one quirk: Gitea answers an
|
||||
anonymous caller with the same `404` for an invisible repository as for one that does not exist
|
||||
at all. A missing release and missing access then look identical - and "no update found" would
|
||||
simply be wrong. A Gitea token with read access in `WIKITOOL_UPDATE_TOKEN` fixes that. It is sent
|
||||
only to downloads on the same host as the feed.
|
||||
|
||||
## The release workflow
|
||||
|
||||
Between two releases the stack carries **one** running version candidate instead of a new
|
||||
number per bump. The full model - where the state lives, how escalation works, why a number is
|
||||
only consumed by a release - is in
|
||||
[instructions/dev/version-parts.md](../../instructions/dev/version-parts.md) and
|
||||
[docs/explanation/version-model.md](../explanation/version-model.md). Here only the sequence, in
|
||||
the order a session actually goes through it:
|
||||
|
||||
1. **A bump opens or escalates the candidate, graded with `--impact`.**
|
||||
|
||||
```bash
|
||||
tools/wikitool version bump --minor --title "What changed" --impact medium
|
||||
```
|
||||
|
||||
Writes `VERSION` as `X.Y.Z-beta.N` and opens (or updates) the matching `CHANGES.md` entry.
|
||||
Several bumps for the same change are normal - each one updates the same entry instead of
|
||||
opening a new one. `--impact high|medium|low` (default `medium`) groups the entry;
|
||||
`tools/wikitool version regrade` corrects a grade later, when the candidate's overall shape
|
||||
changes the read on an earlier bump.
|
||||
|
||||
2. **The entry gets its prose - only where it is needed.** `bump` writes the skeleton (heading,
|
||||
date, author, the machine-managed, grouped list of bump titles, and the breaking and migration
|
||||
lines where they apply). A smaller change needs nothing beyond its bump title; a larger one
|
||||
gets a paragraph for its topic, and a short summary is added before the release. The form, and
|
||||
the size budget `docs verify` and `version release` check, are in
|
||||
[instructions/dev/version-parts.md](../../instructions/dev/version-parts.md) § The candidate
|
||||
model.
|
||||
|
||||
3. **Run the checks before anything is published:**
|
||||
|
||||
```bash
|
||||
cd tools && .venv/bin/python -m pytest -q
|
||||
tools/wikitool docs verify
|
||||
tools/wikitool instructions verify
|
||||
```
|
||||
|
||||
4. **`version release` fixes the candidate** once it is meant to ship:
|
||||
|
||||
```bash
|
||||
tools/wikitool version release --title "Summarising title"
|
||||
```
|
||||
|
||||
Strips the `-beta.N` suffix from `VERSION` and closes the changelog entry. `--title` is
|
||||
optional - without it the last bump's title stays; with it, a candidate that collected several
|
||||
bump titles gets a summarising heading. Refused when the candidate collected two or more bumps
|
||||
and the summary from step 2 is still missing - a candidate with exactly one bump is exempt -
|
||||
and likewise when the entry is over its size budget. Commits and pushes nothing (invariant 5
|
||||
in [AGENTS.md](../../AGENTS.md)).
|
||||
|
||||
5. **Publish moves `VERSION` on `main`.**
|
||||
|
||||
```bash
|
||||
tools/wikitool publish --message "..."
|
||||
```
|
||||
|
||||
The Mass-Update Gate and the Publish-Remote Gate apply as on every other publish - see
|
||||
[instructions/gates.md](../../instructions/gates.md).
|
||||
|
||||
6. **CI does the rest.** `.gitea/workflows/release.yml` reacts to every push that moves
|
||||
`VERSION`: a `VERSION` with a suffix (a candidate) makes the job skip cleanly before it even
|
||||
queries the releases API - betas are never published. A suffix-free `VERSION` builds the
|
||||
distribution (`dist export`), creates the tag and the release, and uploads the tarball and its
|
||||
checksum, along with the two preflight scripts and the instructions `setup-instance.md` and
|
||||
`preflight.md` that the installation sentence in `INSTALL.md` points at. **CI sets the tag,
|
||||
never a session** - that keeps invariant 5 intact.
|
||||
|
||||
The release note is the `CHANGES.md` entry; Gitea on MySQL stores at most 65535 bytes, and
|
||||
the job refuses from 60000 on, before it creates a tag. That is only the last net: `docs
|
||||
verify` already holds the topmost entry to at most 32000 bytes while it is a candidate (step
|
||||
2). If the job fails after `VERSION` is already on `main`, neither a push (the version does
|
||||
not rise again) nor a re-run (it takes the workflow file of the failed commit) helps: fix the
|
||||
cause, publish, and start `release.yml` on `main` via `workflow_dispatch`. The check for an
|
||||
existing release prevents a second one.
|
||||
|
||||
The three check commands are in step 3 above; what each of them checks is in
|
||||
[tools/CONTRACT.md](../../tools/CONTRACT.md), where `docs verify` holds it against the actual
|
||||
CLI. It is deliberately **not** repeated here: a second description of the same commands is
|
||||
exactly the copy that drifts (AGENTS.md invariant 8), and this document lies outside the files
|
||||
the command-record check of `docs verify` covers - so a drift here would go unnoticed. What
|
||||
`pytest` expects of the developer at this point is in
|
||||
[instructions/dev/testing-conventions.md](../../instructions/dev/testing-conventions.md).
|
||||
|
||||
## The CI half
|
||||
|
||||
`.gitea/workflows/ci.yml` runs on every push/PR against `main` (content paths excepted) and
|
||||
runs the test suite, `docs verify`, `instructions verify` and a complete `setup-instance.md`
|
||||
replay: a locally built release tarball, the preflight script with `--archive` in an empty
|
||||
directory, then the instruction's steps - the same path a new user actually takes, just without
|
||||
the download. `.gitea/workflows/nightly.yml` is the drift check against time rather than against
|
||||
a commit. `.gitea/workflows/release.yml` is step 6 above.
|
||||
|
||||
Three more workflows carry the live tests of the tracker adapters (Super Productivity, CalDAV):
|
||||
`ci.yml` runs the CalDAV half in a step of its own against Radicale as a process,
|
||||
`tracker-live.yml` runs nightly and covers both providers, and `sp-live-image.yml` builds the
|
||||
`chemenu-sp-live` image daily (when there is a new version) and monthly (always) with the current
|
||||
Super Productivity version. The image follows the desktop clients' update channel, not a fixed
|
||||
version. Once, after the very first push, the package has to be linked to the `torben/chemenu`
|
||||
repository by hand. What the suite writes, how to run it against a tracker of your own, and what
|
||||
a red run means is in
|
||||
[instructions/dev/tracker-testing.md](../../instructions/dev/tracker-testing.md).
|
||||
|
||||
## Stack development as a session type of its own
|
||||
|
||||
Three skills (`instructions/dev/`, present only in this origin repository) carry a session that
|
||||
works on the stack itself rather than on wiki content through three phases: `stack-dev` works
|
||||
the issue out until its body is "ready", `stack-build` builds, publishes and waits for a green CI
|
||||
run, `stack-close` checks the body's final state and stale `docs/` and contract prose, and closes
|
||||
the issue. The handover goes through the state in the tracker, not through a session's context:
|
||||
every phase change works in the same session or after `/clear`. `stack-dev` triggers
|
||||
automatically; `stack-build` and `stack-close` are started only by the operator, by slash command
|
||||
(`/stack-build #N`, `/stack-close`) - exactly where the choice falls whether to continue in the
|
||||
same session or a new one, and on which model. None of the three offers a model switch in the
|
||||
middle of a session. Rules and the phase table are in
|
||||
[instructions/dev/stack-mode.md](../../instructions/dev/stack-mode.md), the issue tracker itself
|
||||
in [instructions/dev/issue-tracking.md](../../instructions/dev/issue-tracking.md).
|
||||
Reference in new issue
Block a user