Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-30 00:34:18 +06:00
co-authored by Claude Opus 5
commit 02268f9121
33 changed files with 2730 additions and 0 deletions
+111
View File
@@ -0,0 +1,111 @@
# atelier — agent constitution
`atelier` is a flat-file personal publishing engine in Go, built solo, one feature at a time.
You implement; the human owns scope and taste. This file overrides your defaults.
A **personal publishing substrate**: a directory of Markdown becomes an owned, networked home for
fiction, webcomics, art, and essays, in English and Bengali. Values: data sovereignty, minimalism
as aesthetic, comprehensibility by one person.
---
## 1. Read order (do not skip, do not exceed)
1. This file.
2. `docs/state.md` — what exists **right now**, plus the earn-it counters.
3. `docs/README.md` — always. The map: how you find which doc owns your topic. Not "exceeding".
4. Every doc owning a topic your change asserts a rule about (ownership table in `docs/README.md`).
5. Only the source files you will edit, plus their direct callers.
No reading the repo "for context", no speculative greps. Where `docs/state.md` and the code
disagree, the code wins — say so, fix the doc in Document.
**The ceiling has a floor.** "Read less" governs breadth, never the doc that owns what you are
writing. Before stating a rule, contract, threshold, or gate, read its owning doc; if it already
says it, amend there instead of restating elsewhere.
`ideas/` and `reference/` are out of context by default, indexes included. Open one only when the
human names it. Never sweep, never list, never cite unasked. Storage, not background.
## 2. The primitives — everything reduces to one
**Bundle · Stage · Query · View · Interaction · Effect** (+ bundle-as-program).
Definitions and STATUS: `docs/architecture.md`.
Name the primitive before writing code. If it reduces to none it is a **trunk** (wants a permanent
service or a core-model change): stop, say so in a paragraph, propose the leaf, wait.
## 3. Hard rules
1. **No abstraction before its second concrete use** — pipeline, resolver, interface, generic, config
knob, registry. The counters table in `docs/state.md` holds every threshold and is the only place
they are written down: read them, increment them, never anticipate them.
2. **No new dependency** without an ADR and human approval. Allowlist:
`scripts/allowed-deps.txt`. Stdlib first, always.
3. **Surgical diffs.** Only the lines the feature needs. No renames, no reformatting beyond
`gofmt`, no "while I was in there". Spotted something bad? Latent list in `docs/state.md`.
4. **The untrusted boundary is absolute.** Anything not from the site root (comments, webmentions,
form input) never reaches shortcode or template evaluation. Crossing it needs a plan callout.
5. **Permalinks are permanent.** A published URL never changes meaning; renames add aliases and
permanent redirects. The path shape is decided (ADR-0008) and written in `docs/content-model.md`
read it before emitting a URL, and never invent a second shape.
6. **No speculative anything**: no unused parameters, no `interface{}` for flexibility, no "we
might want to" comments, no one-field options structs, no plugin registry before its counter is due, no
cache until requests feel slow, no concurrency until profiled, no
`utils`/`helpers`/`common`/`manager`/`base` packages, ever.
7. **Delete before you add.** If removing code buys the feature, do that.
8. **Nothing ships without the doc that describes it, and nothing ships still describing what you
replaced.** Code carries its `state.md` update; harness changes (this file, `scripts/`,
`.claude/`) carry their `HARNESS.md` update; both are gated. Changed a rule, value, name or path?
Grep the repo for the old form and every doc that names the concept, and fix them in this change —
`verify.sh` catches dangling paths and ADR numbers, never a superseded sentence. And never assert a
mechanism that does not exist yet: if a doc says a gate rejects something, run it and watch it reject,
or do not write the sentence. `./scripts/verify.sh --list` names every gate there actually is. The harness
evolves: when a rule here proves wrong, fix the rule *and* its description rather than working
around it.
9. **Surface conflicts; never resolve them silently.** If a request contradicts a decision already
recorded — an ADR, an architecture invariant, the permalink shape, the untrusted boundary, a
budget, a frozen contract — say so before writing code: quote the line, name the file, and give
the two paths (comply, or change the decision on purpose). A request that merely exceeds a
convention is not a conflict; a request that reverses a deliberate choice always is. Kinds and
procedure: the Clarify step in `SKILL.md`. Silently doing what was asked is the failure mode this
rule exists to prevent — the human cannot audit a conflict they were never shown.
## 4. The loop (every request, no exceptions)
`Clarify → Plan → Implement → Verify → Document → Report`.
Procedure: `.claude/skills/atelier-feature-loop/SKILL.md`. The two gates people skip:
**Clarify.** Only questions whose answer changes the code or the bytes on disk. Max three,
batched, up front, each with a **bold** default so silence answers. Never about naming, formatting,
or anything `docs/conventions.md` decides. None to ask? State assumptions in one line and move on.
**Verify.** `./scripts/verify.sh` green, plus one piece of feature-specific evidence you actually
ran (golden file, `curl`, test name, benchmark). Never report success from reading your own diff.
"Should work" is not a result.
## 5. Definition of done
- [ ] Plan's success criteria demonstrated with real output.
- [ ] `./scripts/verify.sh` green.
- [ ] Diff contains nothing outside the planned files.
- [ ] `docs/state.md` updated (inventory, counters, latent items, verified-at line).
- [ ] ADR in `docs/decisions.md` if a load-bearing choice was made.
- [ ] Report states LOC delta, what is now earned, what you deliberately did not do.
## 6. Stop conditions — halt and ask
- The change exceeds planned LOC by ~50%, or touches an unplanned file.
- You need a new dependency, a new package, or a change to a frozen contract.
- You are about to write a mock, a `switch` on a type, or a second copy of parsing logic.
- The feature only works if the untrusted boundary bends.
- Two reasonable designs exist and the choice is expensive to reverse — present both, briefly.
Stopping early costs one message. Guessing costs a refactor.
## 7. Style floor
Go stdlib idiom, `net/http` + `html/template`, no framework. `%w` wrapping at package boundaries
only. `log/slog`. Table-driven tests, golden files in `testdata/`. Explicit wiring in one file, no
`init()`. Size thresholds live in `scripts/budgets.env` only. Full rules: `docs/conventions.md`
read them, do not ask.