Project Docs
This skill governs the three root-level Markdown files that describe a project to external
readers: README.md, SECURITY.md, CONTRIBUTING.md. They are the first thing visitors see,
setting expectations for usage, security contact, and how to contribute, so they must be accurate,
scannable, and consistent across all Agora services.
They carry the global picture — the architecture, the layer split, the principles behind the
shape of the system — which code comments defer to instead of re-explaining the system from inside
one source file (see document-code). Keep that wide-angle view current, so the comments in the code
can stay local and specific.
README.md is a reference entrypoint: how to install, configure, and call the project, plus that
global picture. Closer to an extension of the code comments than to a guide, it follows the section
order below rather than a narrative. CONTRIBUTING.md and SECURITY.md are guides: they walk a
reader through a process, as do the pages they link (onboarding, a board-lifecycle walkthrough).
The skill has two modes, detected in Phase 2: scaffold generates a missing file from the templates here, update edits the relevant section of an existing one in place.
Separate concerns:
CODE_OF_CONDUCT.md— not managed by this skill. Copy the Contributor Covenant verbatim from https://www.contributor-covenant.org/version/2/1/code_of_conduct.md when setting up a new project and do not edit further.document-code— governs doc comments inside source files (Go, SQL, TS, etc.), not these project-level Markdown files. Its Prose economy section does reach here: it owns sentence-level prose craft on every surface we write, README sections included. Load it alongside this skill and treat it as the base layer the Editorial Principles below build on.
Fleet standard (current)
This section is authoritative and supersedes any older guidance below where they conflict.
It applies to EVERY repo in the a-novel and a-novel-kit orgs — backend services, the Go
library (golib), the JS/TS packages (nodelib), the reusable Actions repo (workflows),
and the stack CLI. Reference implementations: the
service-json-keys README (service) and the
golib README (library).
Header — identical shape across all repos
# <Title>
<one concise line describing what this is> ← ALWAYS present, directly under the title
[](https://twitter.com/agorastoryverse)
[](https://discord.gg/rp4Qr8cA)
<hr />
<tech badges — vary by repo type, see table>
<codecov sunburst image — ONLY if the repo reports coverage>
The one-line description under the title is mandatory (older service READMEs omitted it and
put badges where the description should be — add the line). Social badges, then a literal
<hr />, then the tech-badge block. The codecov badge + sunburst image appear ONLY for repos
whose CI uploads coverage.
| Repo type | Tech badges (in order) | Codecov? |
|---|---|---|
Go service (service-*) |
go-mod version · file count · code size · CI status | yes |
Go library (golib) |
go-mod version · file count · code size · CI status | no |
JS package (nodelib) |
file count · code size · CI status | yes |
Actions (workflows) |
file count · code size · CI status | no |
CLI (stack) |
go-mod version (?filename=cli/go.mod) · file count · code size · CI status |
no |
"Codecov if applicable" = the repo's CI calls the generic-actions/codecov action. Verify
before adding the badge: grep -rl generic-actions/codecov <repo>/.github/workflows. Today
services + nodelib report coverage; golib, workflows, stack do not.
Section order — ONE order, every repo
Every README uses the same five slots in the same order. Only the content of each slot changes with repo type; the order never does. Frequently-referenced material comes first, rarely-needed material last, so readers scroll as little as possible.
| # | Slot | Always contains |
|---|---|---|
| 1 | Header | Title, one-line description, badges (+ codecov sunburst if the repo reports coverage). |
| 2 | Role | What it is / does: the noun it owns, who it serves, the surface. 1–3 short paragraphs of prose — never an inline capability list (that lives in slot 4). |
| 3 | Use it | The primary how-to-use, leading with the expected path (see hard rules). |
| 4 | Reference | Detailed material — comes after the slot-3 example, never before it. |
| 5 | Contributing | The onboarding-guide link + ./CONTRIBUTING.md, nothing else — contribution rules live in CONTRIBUTING.md. Always last. |
Use these exact slot headings per repo type:
| Repo type | Slot 2 (role) | Slot 3 (use it) | Slot 4 (reference) |
|---|---|---|---|
| Backend service | ## What it does |
## Deploying (+ ### Configuration) |
## Using the client packages, then ## Running locally |
| Go / JS library | ## What this is |
## Installation (go get / pnpm add) |
## Sub-packages (Go) / ## Packages (JS) |
| Actions repo | ## What this is |
## Using an action |
## Action catalog |
| CLI (stack) | ## What this is |
## Install |
operational sections (## The UI, ## Non-interactive commands, …) |
Hard rules — no exceptions:
- Role (slot 2) ALWAYS precedes use / install / deploy (slot 3). The header's one-line
description does NOT replace it — slot 2 is its own
##section. Ago get/pnpm addone-liner sitting before the first##heading is a violation; put it inside slot 3. - Slot 3 leads with the EXPECTED / production path. For a service that is the production
split-image composition (one canonical compose block + an image-role table) plus the OpenTofu
forward-note below. The standalone single-command dev compose is relegated to
## Running locally, the LAST section before Contributing.### Configurationlives inside## Deploying: required env vars visible, optional groups (REST tuning, OTel) under<details>.OpenTofu modules are the planned canonical deployment path. Until they land, deploy the images with any container orchestrator — the composition below is the reference for which images to run, how they wire together, and the environment they expect.
- Contributing (slot 5) is always the last section.
- Describe in prose; enumerate in tables. The role section (slot 2) is prose — never inline a capability list (sub-packages, packages, endpoints, env vars) in a sentence, and never pause an explanation to catalog its members. Each list lives once, in its slot-4 reference table or wherever it already exists; point there instead of repeating it (principles 6 and 19). Rule of thumb: four-plus comma-separated items belong in a table, not a sentence. Lead with the plain-English purpose and let the table, intellisense, or the API reference carry the inventory. Cut every word that adds no information, and drop boilerplate ("if you have questions or run into issues", "check existing issues"). Cutting filler is not cutting explanation: an unfamiliar concept or a non-obvious rationale earns the words to make it clear, in plain language.
- Contribution rules live in
CONTRIBUTING.md, not the README. The README Contributing section is only the two links. The "what belongs here / bar for additions" policy, review norms, and any other contributor guidance go in CONTRIBUTING.md, phrased naturally. - Rationale over surface. Explain why a thing exists, what kind of logic belongs in it, and how a dev should approach it — the doc is a guide, not a second copy of the API. Note large-scale facts that are hard to spot at a glance (a service's env vars, that OTel ships local and GCP exporters, the deployment images), but never an inventory of functions, methods, or client calls (principle 6). A package or sub-package description says what it is FOR, not which symbols it exports.
- Concrete versions live only in copy-paste code blocks. A real tag (
@v1.0.3, image:v2.3.1) belongs only where the reader copies the block verbatim — auses:, compose, or install snippet. In prose, placeholder examples, and inline references, use a generic@<tag>or link the latest release. A hard-coded version in prose is redundant with the repo and goes stale.
The one documented exception: service-template MAY prepend a ## Using this template
section before slot 2 — its primary reader is forking it. No other repo reorders the five slots.
Contributing section + links (fix the fleet-wide 404s)
Every repo ends with a short ## Contributing section that points at TWO things:
- The developer onboarding guide for platform setup (toolchain, the
a-novelCLI, daily usage):https://github.com/a-novel-kit/.github/blob/master/README.md. This is the single canonical onboarding doc for BOTH orgs. - The repo's own
./CONTRIBUTING.mdfor repo-specific concepts.
Each org's .github repo does carry a CONTRIBUTING.md — the concepts doc holding what is true
of every repo of a kind (see contributing-doc-dedup in practice: the layer model, service anatomy,
the libraries/tooling taxonomy). Link it when a repo doc needs a concept rather than restating it.
Platform setup is the onboarding guide above, which is a different document. The legacy
a-novel-kit/.github/.../contributing/readme.md path 404s — never link it.
CONTRIBUTING.md itself: intro (link the onboarding guide + "read the README first") →
repo-specific concepts → ## Questions? (issues link). Never restate platform setup or the
service role there.
Editorial Principles
These come before the templates. The templates implement them; when a generated file looks
right but violates a principle, the principle wins. They build on document-code's Prose
economy section, which owns the sentence-level craft for every prose surface — load it too.
All of them apply to every file except the narrative ones, which shape the guides only: principle
12 (tell a story), and principle 10's natural headings, give way in a README.md to the fixed section
order above — though principle 10's show-over-tell holds anywhere.
1. Audience-first — name the reader before writing the section
Every section in README.md and CONTRIBUTING.md answers a question a specific reader is holding.
Three readers exist:
| Reader | What they want | File |
|---|---|---|
| Operator | "How do I run this service?" | README.md |
| Client integrator | "How do I call this service from another service?" | README.md |
| Contributor | "How do I work on this codebase locally?" | CONTRIBUTING.md |
A section that answers none of those questions does not belong. A question answered twice for the
same reader — across the two files or twice in one — is cut to one home and linked (principle 19): if
the JS client install snippet is in README.md, CONTRIBUTING.md says "see the README".
Write at the reader's knowledge, not yours; the curse of knowledge is the default failure. A term you
use daily reads as jargon to a first-time contributor — a Closes line, an issue number, a Pull
Request description. When a passage only parses because you already know the tool, define what you
assumed, on first use.
2. Lead with the role, not the runbook
The first text after the badges in README.md is what the service does and why it exists — one
to three short paragraphs. Not the stack it is built on, not how to deploy it, not a table of
contents. A reader who cannot tell what the service does from the first paragraph will not find out
by scrolling further.
A good role section answers:
- What does this service own? (the noun: "signing keys", "narrative state", "user identities")
- Who does it serve? (the verb: "lets other services sign tokens", "stores the in-progress story", "authenticates users")
- What is the surface? (REST? gRPC? both? public? internal?)
If the answer is "I don't know" for any of those, find out before drafting — the role section is the doc.
3. Open with what the document is about, not with a mechanism
The first sentence of a guide (a README role paragraph, a CONTRIBUTING page, any standalone doc) says what the document is about, in plain purpose terms: "This document is about how a feature is planned, built, and shipped." Never open on an implementation fact — "Every piece of work is a GitHub issue" drops the reader into the mechanism with no frame. State the purpose first and the mechanism arrives as its answer.
Guide, don't assert: "This document is about…" orients the reader, while "We plan before we build" commands them, and prescriptive first-person openers read as manifesto. Test the first two sentences alone — a stranger should know what the doc covers and why, and should not yet have met an implementation term without a reason for it.
4. Verify every factual claim against the source
A README that says "AES-GCM" when the code uses NaCl secretbox is worse than one that says nothing about encryption. Before describing any of:
- Cryptographic primitives (algorithm names, modes, key sizes)
- Configuration field names and shapes (YAML keys, env var names)
- API surface (RPC names, REST paths, status codes)
- Lifecycle states (active / expired / deleted)
- What a named thing is in the platform (a GitHub Milestone is a grouping feature, not an issue type; a label is not a status)
- File paths referenced in prose
…open the source and confirm. The doc commit must reflect the code at the same SHA; when the code changes one of these things, the doc update belongs in the same change, not a follow-up.
A process still taking shape is not a fact yet: state what the system does today, not the policy you expect it to grow into ("an Epic ships one per release" is fiction until releases work that way). An option the platform merely offers is not taxonomy either — an enabled type carrying zero issues is configured, not real, so check usage, not just config. Name the condition on a conditional rule ("only for Epics under one Initiative or Milestone"), or it reads as universal. Mark a workaround a current limitation forces as temporary ("for now, a Milestone is tied to one repository"): unmarked, it hardens into apparent design and no one revisits it when the limitation lifts.
5. Show the canonical, link or table the variants
When a service has several deployment shapes (REST × gRPC × standalone × split = four combinations),
do not paste four near-identical compose blocks in sequence: the reader who wants the simplest path
scans past three they will not use, and any future update becomes a four-place edit. Show one
canonical block inline — the production / expected shape, per the Fleet standard above (lead with
production, relegate the dev one-liner to "Running locally") — then list the other shapes in a table or
collapse them under a <details> block. Any time two blocks differ by one line, the second belongs in
a diff, table, or collapsible block, not in line.
The same holds for any set of parallel items, a catalog of types or a matrix of options: in a reference or in-depth section, a table reads faster than a run of paragraphs, while the narrative up front stays prose. Go harder on presentation the deeper into the document you are.
6. Reference, don't enumerate
Comprehensive lists of fields, methods, or env vars are reference material. They go in a dedicated section (or in generated reference docs like the OpenAPI viewer or godoc), after the canonical example, never interleaved with prose: readers who need the reference jump to it, readers who don't are not made to scroll past it.
For client packages, the README example shows the minimum viable call — install, construct, one
real operation. That is enough to unblock someone; the full surface is what intellisense,
pkg.go.dev, or the published API reference is for.
7. Edit in place; preserve unknown content
In update mode, treat existing custom sections (architecture diagrams, team notes, org-specific footers, release call-outs that are not in the template) as data, not noise: read the whole file, then edit only the section the user is changing. A "rewrite" instruction from the user is the only override, and even then, surface anything that looks like deliberate custom content before discarding it.
8. Lead with rationale; dose examples to disambiguate
A doc earns its keep by explaining what a thing is, why it exists, and how to approach it. That rationale leads and carries the weight; an example never stands in for it, because one left to do the explaining goes stale and breaks the rhythm. Never import an example from the conversation that produced the doc — it aided the author, not the reader, and lands as arbitrary and dated later.
Once the rationale is on the page, a short example pins down what prose leaves fuzzy: an inline pairing ("named for its goal, not its version"), a compact do / don't table, or a code block. Dose them — short, few, and only where the explanation needs it, judging per point. Across a do / don't series, thread one running example through every row so the reader tracks a single thing and the rows can cross-reference, and pair every don't with why it is wrong, or it is a second example rather than a lesson.
An example must instantiate the rule it illustrates, not a cousin of it: explaining an Epic's atomic landing (its Tasks merging as a unit) with a cross-repo dependency — really the stages rule, one piece released before another can use it — teaches a false model and braids two rules under one heading. An example that holds only under another rule belongs under that rule, and the muddle usually signals the section should split in two.
Concrete specifics that run long (exact commands, names, links) are reference material, not
explanation: keep the prose general and push them where reference belongs — a table, a code block, or
the relevant service's own CONTRIBUTING.md. An analogy is its own kind of example: reach for it when
the concept is genuinely hard, and state the concept directly otherwise.
9. Plain language, plain sentences
Write so a tired reader gets it on the first pass. document-code's Prose economy section states
this rule in full and covers these files: prefer the common, short word and reach for a technical one
only when it earns its place; state each point as a plain subject-verb-object sentence rather than a
rhetorical label ("Why this matters:", "Note:"); keep the plain word order, since a fronted object, an
inversion, or a cleft makes the reader unpack a sentence before reading it. Load and apply that section
here, including its anti-tautology check for headings, prose, and examples.
What project docs add: two short sentences beat one long one spliced together. Avoid the em-dash that cuts a sentence in half, and the enumeration that only restates what you just wrote. Get the conjunction comma right — put one before and, but, or so only when a full clause with its own subject follows ("the board runs itself, and you barely notice it"), never before a compound predicate sharing the subject ("easier to write and far easier to review"); "so" meaning "therefore" takes the comma, a restrictive "because" does not. When a draft feels dense, revise for plainness before shipping: the plain version is the finished one, not a step toward it.
10. Show the flow, don't announce it
Let the reader absorb the model by reading, not by being told its shape. A section named "The big picture" or "The design" announces your structure instead of teaching the subject; drop the label, and name in the heading what the reader is doing or learning there ("When the board needs you").
A heading must match the scope of what it covers. When a rule recurs at every level of a hierarchy, state it once as the general rule and title its home for the whole hierarchy: "Planning an issue" fits, "Planning a task" strands the rule under the smallest case it governs. A heading level is likewise a claim of sameness, so let the levels mirror the kinds — peers are the same sort of thing, the board's objects grouped apart from the practices for working with them.
Subheadings help a section the reader scans, not one they read through: a reference block answering many separate questions reads better broken under headings a reader can jump between, while an argument or a story only fragments under them. Match the anchor's weight to the need — a heading is heaviest, for a section the reader jumps around; bold lead-ins or a distinctive topic sentence per paragraph carry a lighter scan; a pure read-through needs nothing. Over-anchoring a rarely-visited explanation costs more than it gives.
Prefer showing to telling: a worked path teaches the model better than a list of definitions (an idea becomes a Task, the Task becomes a Pull Request, the Pull Request merges and ships). When a sequence of states is the point, a small text diagram beats a paragraph — visual and sparse, a few words per node, marking what matters, like who acts or where a gate falls. It also beats a screenshot whenever the subject changes or sits behind a login (a board, a pipeline, a console): it diffs in review, renders in the reader's own theme, tracks the concepts rather than the pixels, and keeps private data out of a public repo, where a snapshot of a live UI rots the moment the UI moves. Keep one diagram per idea, deleting an earlier one a richer diagram subsumes. A diagram is a claim, so its shorthand must stay true: a label that sweeps a human gate into "the board does it" is a bug, not a simplification.
11. Keep it self-contained, no links to ephemeral work items
Never point a doc at a specific issue, epic, or PR, by number or by link. They close, archive, and get renumbered, so "see #46" rots and leads nowhere. If a rationale is worth keeping, write it into the doc itself. Commit messages and PR descriptions may reference issues; docs may not.
12. Tell a story, not a spec
A guide is a narrative with an arc, not a catalog of facts. The arc that carries a reader: what this document is, then what they will do, then how it works, then what to pay attention to, then the edge cases, then the machinery underneath. Each part earns the next, so the reader is led through, never dropped into a list.
Pacing does the leading. Set up what is coming, then move through it with real transitions ("It starts with the intention," "Then comes the code," "Now it is a maintainer's turn"). Let a motif thread through and pay off later: the point where the work "waits for a human" becomes the very thing to pay attention to. Vary the sentence length, and land the important beat on a short one.
A story is the order of ideas, not extra words — keep each beat as tight as principle 9 demands ("Task being the smallest unit" beats "the smallest, the one that turns straight into code"). The chain holds inside a paragraph too: each sentence follows from the one before. A paragraph that packs several ideas and leaves the links implicit reads as dense, not concise; make each link explicit, or split it.
The trap is the appliance manual: "There is a wash cycle and a rinse cycle. Press start. If it beeps,
open the door." Flat, listed, no momentum. This principle governs the shape of a guide, and the others
refine the prose inside it; it does not apply to a README.md, a reference entrypoint (see the scope
note above).
13. Name a concept once, concretely, and keep the name
document-code's Prose economy owns this rule and its extensions; apply it as written. One thing
is specific to a guide: a motif (principle 12) may echo a term, never replace it.
14. Start simple: the global picture first, then the details
Give the reader the whole shape in its simplest form before any detail: someone new grasps how the thing works from the opening, then meets the specifics, then the edge cases, each layer resting on the one before. Do not open a section with an exception or a corner case; open with the common path, and let the rare and the deep follow. This orders the document as a whole and every section inside it, and it binds a concept to the rules about it: introduce a type before any rule that leans on it. A crisp rule ("an Epic lands whole") invites use as an early capstone, but before the reader has met the concept it rests on nothing, so it belongs no earlier than the section defining the term.
The same instinct decides what a document carries at all. A process or lifecycle doc holds the generic shape; the language, the stack, and the specific tooling belong in the repository's or language's own doc, linked to rather than stamped in. Detail only some readers need — a step an agent handles on its own, an advanced path — gets its own section with a line up front saying who it is for, so the main narrative stays simple and universal and whoever needs more follows the link.
A concept with behavior of its own — its own lifecycle, flow, or failure modes — earns a section too, never an aside on a neighbor: "A Bug is like a Task, for a defect," tucked into a table cell, under-serves a thing that carries its own hotfix path. The aside signals the concept has outgrown its host.
15. A link rides on the prose, never the other way around
Anchor a link to a phrase that already earns its place in the sentence; never write a clause, a sentence, or a stacked list just to hold one. "Taking time to refine it makes the whole planning process smooth" reads as prose; "refine it, and planning walks through it" reads as a footnote bolted on. When a phrase needs several URLs at once, such as the same view in two orgs, a short parenthetical on it carries them ("the Roadmap view (a-novel, a-novel-kit)"). If a link has nowhere natural to sit, rework the prose or drop the link.
16. Lead with the do; keep the don't a footnote
document-code sets the default: write the choice, not the rejected alternative, and keep a
counter-example only where the wrong path is the one a reader would otherwise take. When one earns its
place, this principle sets the order and the weight. Lead with the instruction, plain and given the
most room ("make the spec sharp; it is the foundation"), then set the failure it guards against apart
after it and smaller — it is a transient warning, there only to make the instruction land: "a vague one
builds the wrong thing." Do not lead with the failure, weld a caveat onto it, or bury the do at the
tail. "Build from a vague one and you build the wrong thing, however clean the code, so make it sharp"
does all three, hiding the instruction behind the warning meant to drive it home.
17. Make every reference land on something the reader already holds
document-code's Prose economy owns this: a pronoun sits beside its one possible antecedent, and
earlier content is named by a plain description rather than an abstract handle the reader must decode.
18. State what is, not what is not
This is document-code's "write the choice, not the rejected alternative", applied to absent features:
describe what the system has and does, and leave out what it lacks, because "there is no tier between
Task and Epic" or "we do not use a Feature type" summons a thing into the reader's mind for the sole
purpose of denying it. The tell, specific to docs: the absence you feel the urge to explain is usually
one only you can see, because you just removed it or argued it away. Cut it; the plain list of what
exists says all the reader needs.
19. State each thing once; duplicate only to go deeper
Give each fact, rule, or mechanism a single home, and refer to it from anywhere else that needs it. The same explanation in two places is not reinforcement but two copies to keep in sync, and a reader who meets it twice at the same depth wonders what changed between them. A repeat earns its place only when the second pass goes materially deeper: the overview names a mechanism, the deep section takes it apart. When two passages say nearly the same thing at the same altitude, keep the one in its natural home — the mechanism with the machinery, the practice with the workflow — and cut the other. When a passage carries a fresh point wrapped around restated material, keep the point and link the rest: a philosophy recap states the philosophy and points at the mechanism it rests on.
Phase 1: Collect Required Inputs
Before scaffolding a new file, ask the user for the inputs below, in a single message rather than one question at a time. In update mode, ask only for the inputs relevant to the section being edited.
1.1 Always required
| Input | Example | Default for Agora |
|---|---|---|
| Project display name | JSON Keys service |
(ask) |
| Repo path (org/repo) | a-novel/service-json-keys |
a-novel/<service-slug> |
| Main branch | master |
master |
1.2 Required for README.md
| Input | Example | Default / Fallback |
|---|---|---|
| Main CI workflow | main.yaml |
main.yaml |
| Codecov graph token | almKepuGQE (public token, safe to commit) |
Omit the ?token=… query parameter entirely and leave a TODO(project-docs) comment next to the badge. |
| Twitter handle | agorastoryverse |
agorastoryverse |
| Discord invite ID | numeric ID 1315240114691248138 + invite code rp4Qr8cA |
same as existing services |
The codecov graph token is public — it controls badge/graph rendering only, not repo access, so committing it is safe (see Badge Catalog).
1.3 Required for SECURITY.md
| Input | Example | Default |
|---|---|---|
| Org / project display label | A-Novel (used in running prose) |
A-Novel |
| Security contact email | geoffroy.vincent@agorastoryverse.com |
geoffroy.vincent@agorastoryverse.com |
1.4 Required for CONTRIBUTING.md
| Input | Example | Default |
|---|---|---|
| Project slug | service-json-keys |
(ask — used in page title) |
| Developer onboarding URL | a-novel-kit/.github/blob/master/README.md |
a-novel-kit/.github/blob/master/README.md (single canonical onboarding doc for both orgs; there is NO org CONTRIBUTING.md) |
1.5 Capability flags (shape template output)
Ask the user which of these apply. Each flag turns a section of README/CONTRIBUTING on or off:
| Flag | What it enables |
|---|---|
has-grpc |
gRPC compose examples + grpcurl interaction snippets |
has-rest |
REST compose examples + curl interaction snippets |
has-standalone |
Standalone (all-in-one) image in addition to split images |
has-go-client |
pkg/go usage example in README, Go client section in CONTRIBUTING |
has-js-client |
pkg/js usage example in README, JS client section in CONTRIBUTING |
has-openapi-docs |
Link to GitHub Pages docs in README + redocly/scalar mention |
has-cron-jobs |
Scheduled-job section (like rotate-keys) in CONTRIBUTING |
When an input is unknown or the user declines to provide it, insert an HTML TODO comment (see Handling Missing Values) rather than guessing or leaving the field blank.
Phase 2: Detect Scaffold vs. Update
ls README.md SECURITY.md CONTRIBUTING.md 2>/dev/null
- File missing → scaffold mode: generate from template in Phase 4
- File present → update mode: read it first, edit the relevant section only (Phase 5)
Never overwrite an existing file with the full template — see Principle 7.
Phase 3: Handling Missing Values
When an input is required but not available, write an HTML TODO comment at the exact location where the value belongs. Format:
<!-- TODO(project-docs): <what is missing> — <where to get it> -->
HTML comments do not render in GitHub's Markdown preview, so the file still looks clean to visitors, while grep finds them instantly:
grep -rn "TODO(project-docs)" .
Examples:
[](https://codecov.io/gh/a-novel/service-json-keys) <!-- TODO(project-docs): add ?token=<graph-token> from codecov.io/gh/a-novel/service-json-keys/settings > Badge if a tokenized badge is required -->
Report security bugs by emailing the lead maintainer at <!-- TODO(project-docs): security contact email -->.
Do not invent values. A fake email or a YOUR_TOKEN_HERE placeholder that a reader might
mistake for real content is worse than a visible TODO.
Phase 4: Scaffold Templates
All three templates below use {{variable}} placeholders. Substitute every placeholder with the
inputs from Phase 1 before writing the file; an unresolved {{…}} in the output is a bug.
4.1 README.md template
# {{project-display-name}}
[](https://twitter.com/{{twitter-handle}})
[](https://discord.gg/{{discord-invite-code}})
<hr />




[](https://codecov.io/gh/{{repo-path}}) <!-- TODO(project-docs): if this repo requires a tokenized Codecov badge, append `?token=<codecov-graph-token>` to the badge URL above using the value from codecov.io/gh/{{repo-path}}/settings > Badge -->
 <!-- TODO(project-docs): if this repo requires a tokenized Codecov sunburst, append `?token=<codecov-graph-token>` to the image URL above -->
## What it does
<!-- Mandatory role section per Editorial Principle 2. One to three short paragraphs: what this
service owns (the entity, the noun), who it serves and how (the verb), and the surface
(REST? gRPC? both? public? internal?). Then, if relevant, a one-line note on related
concepts (e.g. "Authentication and identity live in service-authentication; this service
only manages signing keys"). -->
## Deploying
The service runs as published OCI images plus Postgres; both surfaces are stateless and scale to
multiple replicas.
> **OpenTofu modules are the planned canonical deployment path.** Until they land, deploy the
> images with any container orchestrator — the composition below is the reference for which
> images to run, how they wire together, and the environment they expect.
| Image | Role |
| ----- | ---- |
<!-- One row per PUBLISHED image. Verify the exact names against
.github/workflows/release.yaml (image_name:) — they are often `<repo>/jobs/<name>`
(e.g. jobs/migrations, jobs/rotatekeys), NOT a bare `<repo>/<name>`. -->
Pin every image to the same release tag — see the [latest release](https://github.com/{{repo-path}}/releases/latest).
<!-- ONE canonical PRODUCTION compose block: database -> migrations (to completion) -> the
split server(s). This is the lead per Fleet-standard hard rule 2 — never the dev one. -->
### Configuration
<!-- Required env vars in a visible table; optional groups (REST tuning, OTel) under <details>.
The Images column lists EVERY image that reads each var — verify against internal/config,
and note when the rest surface maps ${REST_PORT} rather than ${GRPC_PORT}. -->
| Name | Description | Images |
| ---- | ----------- | ------ |
## Using the client packages
<!-- One minimum-viable example per client (Go, JS). Link the API reference / pkg.go.dev;
do not enumerate the full surface (Principle 6). -->
## Running locally
<!-- LAST section before Contributing. The standalone single-command dev compose (bundles
migrations), with the dev-only caveat. Relegated on purpose — least-retrieved. Point
contributors at the a-novel CLI + CONTRIBUTING. -->
## Cont
…(truncated)