@johanesimm/fundamentum 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,185 @@
1
+ # Fundamentum — Documentation-First Project Initialization Skills
2
+
3
+ > A Claude Code skill suite that builds a complete, fully-decided
4
+ > documentation set for a software project — **before any code is
5
+ > written** for a greenfield build, or **retro-fitted onto an existing
6
+ > codebase** — then plans the implementation.
7
+
8
+ ------------------------------------------------------------------------
9
+
10
+ ## Quick start
11
+
12
+ ```bash
13
+ npx @johanesimm/fundamentum
14
+ ```
15
+
16
+ That's it — the installer asks whether to install **globally** (every
17
+ project) or into the **current project**, copies the skills into the
18
+ right `.claude/skills/` folder, and you're done. Restart Claude Code,
19
+ then say *"Initialize this project documentation-first"* to kick off
20
+ `blueprint`. Full walkthrough in [Installation](#installation) below.
21
+
22
+ ------------------------------------------------------------------------
23
+
24
+ ## What it does
25
+
26
+ You start with an idea. The skills interview you — they never invent
27
+ product facts — and produce, in order:
28
+
29
+ ```
30
+ docs/
31
+ ├── foundation/ 00–08 vision, principles, glossary, domain model,
32
+ │ org model, IA, user journeys, AI strategy,
33
+ │ MVP roadmap
34
+ ├── architecture/ 09.x solution architecture, ADRs, module/data/
35
+ │ permission/state boundaries, stack decision
36
+ ├── prd/ 10–16 Master PRD (cross-cutting requirements,
37
+ │ permission & notification matrices, metric
38
+ │ formulas, event catalog) + one fully-decided
39
+ │ Feature PRD per module — zero open questions
40
+ ├── engineering/ 20–25 ERD, database schema (validated against a
41
+ │ real database), REST API with guard-code
42
+ │ registry, frontend & backend specs,
43
+ │ deployment + dev-environment guide
44
+ └── planning/ priority-ordered dev phases with checkbox
45
+ deliverables and verifiable exit criteria
46
+ ```
47
+
48
+ …plus the four state files (README, PROJECT_STATE, ROADMAP, CHANGELOG) and, at the end, an
49
+ agent-context file (`CLAUDE.md`, `AGENTS.md`, `GEMINI.md`, … — whichever your coding tool reads)
50
+ so any future session can implement the project without re-deriving anything.
51
+
52
+ ## The method (what makes it different)
53
+
54
+ 1. **Grill first** — every phase starts by interviewing the user;
55
+ gaps found in earlier docs become questions, never assumptions.
56
+ 2. **Fully-decided rule** — Feature PRDs and engineering specs ship
57
+ with no "Open Questions"/"TBD"; the Master PRD's deferred registry
58
+ is the single sanctioned backlog for future questions.
59
+ 3. **Validate, don't just write** — any schema runs against a throwaway
60
+ database instance; requirement references are machine-checked across
61
+ every document.
62
+ 4. **Bookkeeping discipline** — PROJECT_STATE/CHANGELOG/ROADMAP are
63
+ updated after every major document, so any session can resume.
64
+ 5. **Stack-agnostic** — the method fits any project type (web app,
65
+ service, CLI, library, mobile, data pipeline). The suite's
66
+ containerized-web-app conventions (Docker, Node/Express + Postgres,
67
+ React) are offered as a **recommended default profile** each skill
68
+ lets you confirm, adapt, or replace — never a hard requirement.
69
+ Stack-specific docs (frontend spec, DDL, deployment) are produced
70
+ only when they apply.
71
+
72
+ ## Skill inventory
73
+
74
+ Three skills — two orchestrators (new vs existing project) plus the
75
+ standalone agent-context (primer) generator:
76
+
77
+ | Skill | Role | Invoke when |
78
+ |---|---|---|
79
+ | `blueprint` | **Greenfield orchestrator** — scaffolds `docs/` and drives all five phases (foundation → architecture → prd → engineering → planning), deciding everything by interview | Starting a brand-new project documentation-first, or asking for any single phase |
80
+ | `excavate` | **Brownfield orchestrator** — surveys the real code + DB, then drives a reduced pipeline (foundation → prd → data/API → planning) that documents what's already built and plans the gap | Documenting / reverse-engineering an existing codebase |
81
+ | `primer` | Standalone: generate the house-style agent-context file for any project — asks which agentic tool the user uses and writes the right file (`CLAUDE.md` / `AGENTS.md` / `GEMINI.md` / …) | Anytime; also each pipeline's final step |
82
+
83
+ The phases are **not** separate skills — each orchestrator bundles them
84
+ as instruction files under its own `phases/`, read one at a time:
85
+
86
+ ```
87
+ blueprint/ (greenfield) excavate/ (existing codebase)
88
+ ├── SKILL.md scaffold + drive ├── SKILL.md survey code, then drive
89
+ └── phases/ └── phases/
90
+ ├── foundation.md 00–08 ├── foundation.md 00–08 (derived + intent)
91
+ ├── architecture.md 09.x ├── prd.md 10–16 (as-built PRDs)
92
+ ├── prd.md 10–16 ├── engineering.md 20–22 (introspected
93
+ ├── engineering.md 20–25 │ ERD/schema/API)
94
+ └── planning.md dev phases └── planning.md remaining-work plan
95
+ ```
96
+
97
+ The existing-project pipeline deliberately **skips architecture (09.x)
98
+ and the backend/frontend build-specs + deploy guide (23–25)** — for a
99
+ codebase that already exists, the code is the authority for those. Its
100
+ method flips too: **code is the source of truth**, and the user is
101
+ interviewed only for product intent the code can't reveal (vision,
102
+ non-goals, rationale, canonical names).
103
+
104
+ In both, the pipeline order is enforced by each phase file's stated
105
+ prerequisites and "Done when" gate, not by hidden state — so you can
106
+ jump straight to one phase, provided its inputs already exist.
107
+
108
+ ## Installation
109
+
110
+ ### The `npx` installer (recommended)
111
+
112
+ **Prerequisites:** [Node.js](https://nodejs.org) 18+ (gives you `npx`)
113
+ and [Claude Code](https://claude.com/claude-code).
114
+
115
+ **Step 1 — run the installer.** No global install needed; `npx` fetches
116
+ and runs it on the fly:
117
+
118
+ ```bash
119
+ npx @johanesimm/fundamentum
120
+ ```
121
+
122
+ **Step 2 — choose where the skills go.** You'll be asked:
123
+
124
+ ```
125
+ Fundamentum — installing: blueprint, excavate, primer
126
+
127
+ Where should these skills go?
128
+ 1) Global ~/.claude/skills (available in every project)
129
+ 2) Project ./.claude/skills (this repo only)
130
+ Choose [1/2]:
131
+ ```
132
+
133
+ - **Global** → the skills work in *every* project on your machine.
134
+ - **Project** → installed only into the repo you're currently in
135
+ (`./.claude/skills/`); commit them to share with your team.
136
+
137
+ **Step 3 — done.** It copies the folders and confirms:
138
+
139
+ ```
140
+ ✓ blueprint → ~/.claude/skills/blueprint
141
+ ✓ excavate → ~/.claude/skills/excavate
142
+ ✓ primer → ~/.claude/skills/primer
143
+
144
+ Done. Installed 3 skill(s) into the global directory.
145
+ Restart Claude Code (or start a new session) to pick them up.
146
+ ```
147
+
148
+ **Step 4 — use them.** Restart Claude Code, then just ask:
149
+
150
+ | Say this | Runs |
151
+ |---|---|
152
+ | "Initialize this new project documentation-first" | `blueprint` |
153
+ | "Document this existing codebase" | `excavate` |
154
+ | "Generate the agent-context file for this project" | `primer` |
155
+
156
+ ### More installer options
157
+
158
+ ```bash
159
+ npx @johanesimm/fundamentum add primer # install just one skill (space-separate for several)
160
+ npx @johanesimm/fundamentum --global # skip the prompt: install for every project
161
+ npx @johanesimm/fundamentum --project # skip the prompt: install into ./.claude/skills
162
+ npx @johanesimm/fundamentum --force # overwrite existing skills without asking
163
+ npx @johanesimm/fundamentum list # show which skills are bundled
164
+ npx @johanesimm/fundamentum --help # full usage
165
+ ```
166
+
167
+ ### Run without npm (from source)
168
+
169
+ ```bash
170
+ npx github:<owner>/fundamentum # straight from GitHub, no publish needed
171
+ node bin/cli.mjs --project # from a local checkout of this repo
172
+ ```
173
+
174
+ ### Manual copy (no Node at all)
175
+
176
+ Copy the skill folders (`blueprint/`, `excavate/`, `primer/`) into
177
+ `~/.claude/skills/` (global) or `<repo>/.claude/skills/` (project).
178
+
179
+ ### Fork & publish your own
180
+
181
+ It's a plain npm package. Set a unique `name` in `package.json` (a
182
+ scoped `@you/fundamentum` is always free), then `npm publish` (scoped
183
+ packages need `--access public`, already set here via `publishConfig`).
184
+ Whatever you name it becomes the `npx <name>` command; `files` in
185
+ `package.json` ships only the CLI + skill folders + README.
package/bin/cli.mjs ADDED
@@ -0,0 +1,167 @@
1
+ #!/usr/bin/env node
2
+ // Fundamentum skill installer — copies the bundled skills into a Claude Code
3
+ // skills directory (global ~/.claude/skills or project ./.claude/skills).
4
+ // Zero dependencies: uses only the Node standard library.
5
+
6
+ import { readdir, cp, mkdir } from 'node:fs/promises';
7
+ import { existsSync } from 'node:fs';
8
+ import { fileURLToPath } from 'node:url';
9
+ import { dirname, join, resolve } from 'node:path';
10
+ import { homedir } from 'node:os';
11
+ import { createInterface } from 'node:readline/promises';
12
+ import process from 'node:process';
13
+
14
+ const HERE = dirname(fileURLToPath(import.meta.url));
15
+ const ROOT = resolve(HERE, '..'); // package root — where the skill folders live
16
+
17
+ const HELP = `fundamentum — install documentation-first Claude Code skills
18
+
19
+ Usage:
20
+ npx fundamentum [add] [skills...] [options]
21
+ npx fundamentum list
22
+
23
+ Arguments:
24
+ skills... Names of skills to install (default: all bundled skills)
25
+
26
+ Options:
27
+ -g, --global Install into ~/.claude/skills (every project)
28
+ -p, --project Install into ./.claude/skills (this repo only)
29
+ -f, --force Overwrite an existing skill without asking
30
+ -h, --help Show this help
31
+
32
+ With no --global/--project flag, you'll be asked which one.
33
+
34
+ Examples:
35
+ npx fundamentum # install all skills, ask scope
36
+ npx fundamentum add primer -g # install just 'primer' globally
37
+ npx fundamentum --project # install all into this repo
38
+ `;
39
+
40
+ /** Discover bundled skills = top-level dirs that contain a SKILL.md. */
41
+ async function discoverSkills() {
42
+ const entries = await readdir(ROOT, { withFileTypes: true });
43
+ const skills = [];
44
+ for (const e of entries) {
45
+ if (!e.isDirectory()) continue;
46
+ if (e.name.startsWith('.') || e.name === 'bin' || e.name === 'node_modules') continue;
47
+ if (existsSync(join(ROOT, e.name, 'SKILL.md'))) skills.push(e.name);
48
+ }
49
+ return skills.sort();
50
+ }
51
+
52
+ function parseArgs(argv) {
53
+ const args = [...argv];
54
+ // optional leading verb
55
+ if (['add', 'install', 'i'].includes(args[0])) args.shift();
56
+ const flags = new Set();
57
+ const names = [];
58
+ for (const a of args) {
59
+ if (a === '-h' || a === '--help') flags.add('help');
60
+ else if (a === '-g' || a === '--global') flags.add('global');
61
+ else if (a === '-p' || a === '--project') flags.add('project');
62
+ else if (a === '-f' || a === '--force') flags.add('force');
63
+ else if (a.startsWith('-')) throw new Error(`Unknown option: ${a}`);
64
+ else names.push(a);
65
+ }
66
+ return { flags, names, verb: argv[0] };
67
+ }
68
+
69
+ async function main() {
70
+ const { flags, names, verb } = parseArgs(process.argv.slice(2));
71
+
72
+ if (flags.has('help')) {
73
+ process.stdout.write(HELP);
74
+ return;
75
+ }
76
+
77
+ const available = await discoverSkills();
78
+ if (available.length === 0) throw new Error(`No skills found in ${ROOT}`);
79
+
80
+ if (verb === 'list') {
81
+ process.stdout.write(`Bundled skills:\n${available.map((s) => ` - ${s}`).join('\n')}\n`);
82
+ return;
83
+ }
84
+
85
+ // Which skills?
86
+ let selected = available;
87
+ if (names.length) {
88
+ const unknown = names.filter((n) => !available.includes(n));
89
+ if (unknown.length) {
90
+ throw new Error(
91
+ `Unknown skill(s): ${unknown.join(', ')}\nAvailable: ${available.join(', ')}`,
92
+ );
93
+ }
94
+ selected = names;
95
+ }
96
+
97
+ // Interactive prompts share one readline instance.
98
+ const interactive = process.stdin.isTTY && process.stdout.isTTY;
99
+ const rl = interactive ? createInterface({ input: process.stdin, output: process.stdout }) : null;
100
+
101
+ try {
102
+ // Scope: global vs project.
103
+ let scope;
104
+ if (flags.has('global')) scope = 'global';
105
+ else if (flags.has('project')) scope = 'project';
106
+ else if (rl) {
107
+ process.stdout.write(
108
+ `\nFundamentum — installing: ${selected.join(', ')}\n\n` +
109
+ `Where should these skills go?\n` +
110
+ ` 1) Global ${join(homedir(), '.claude', 'skills')} (available in every project)\n` +
111
+ ` 2) Project ${join(process.cwd(), '.claude', 'skills')} (this repo only)\n`,
112
+ );
113
+ const ans = (await rl.question('Choose [1/2]: ')).trim();
114
+ scope = ans === '2' || ans.toLowerCase().startsWith('p') ? 'project' : ans === '1' || ans.toLowerCase().startsWith('g') ? 'global' : null;
115
+ if (!scope) throw new Error('No scope chosen. Aborting.');
116
+ } else {
117
+ throw new Error('Non-interactive shell: pass --global or --project.');
118
+ }
119
+
120
+ const targetBase =
121
+ scope === 'global'
122
+ ? join(homedir(), '.claude', 'skills')
123
+ : join(process.cwd(), '.claude', 'skills');
124
+
125
+ await mkdir(targetBase, { recursive: true });
126
+
127
+ const force = flags.has('force');
128
+ const installed = [];
129
+ for (const name of selected) {
130
+ const src = join(ROOT, name);
131
+ const dest = join(targetBase, name);
132
+
133
+ if (existsSync(dest) && !force) {
134
+ if (rl) {
135
+ const ans = (await rl.question(` ${dest} exists. Overwrite? [y/N]: `)).trim().toLowerCase();
136
+ if (ans !== 'y' && ans !== 'yes') {
137
+ process.stdout.write(` skipped ${name}\n`);
138
+ continue;
139
+ }
140
+ } else {
141
+ process.stdout.write(` skipped ${name} (exists; use --force)\n`);
142
+ continue;
143
+ }
144
+ }
145
+
146
+ await cp(src, dest, { recursive: true, force: true });
147
+ installed.push(name);
148
+ process.stdout.write(` ✓ ${name} → ${dest}\n`);
149
+ }
150
+
151
+ if (installed.length) {
152
+ process.stdout.write(
153
+ `\nDone. Installed ${installed.length} skill(s) into the ${scope} directory.\n` +
154
+ `Restart Claude Code (or start a new session) to pick them up.\n`,
155
+ );
156
+ } else {
157
+ process.stdout.write(`\nNothing installed.\n`);
158
+ }
159
+ } finally {
160
+ rl?.close();
161
+ }
162
+ }
163
+
164
+ main().catch((err) => {
165
+ process.stderr.write(`Error: ${err.message}\n`);
166
+ process.exit(1);
167
+ });
@@ -0,0 +1,96 @@
1
+ ---
2
+ name: blueprint
3
+ description: Bootstrap AND drive the documented-initialization pipeline for a NEW / greenfield project — creates the docs/ scaffold (README, PROJECT_STATE, ROADMAP, CHANGELOG) and runs all five documentation phases in order (foundation → architecture → prd → engineering → planning), each defined in its own bundled phase file under phases/. Use when the user wants to start a project "documentation-first", asks to "initialize project docs", or asks for any single phase (vision/glossary/domain, architecture/ADRs, Master/Feature PRDs, engineering specs/schema/API, or the dev plan). Self-contained entry point for the whole docs pipeline.
4
+ ---
5
+
6
+ # Documented Project Initialization (orchestrator)
7
+
8
+ You are bootstrapping a project that will be **fully documented before
9
+ any code is written**, using this pipeline:
10
+
11
+ ```
12
+ foundation (00-08) → architecture (09.x) → PRDs (10-16)
13
+ → engineering (20-25) → planning (dev phases)
14
+ ```
15
+
16
+ Each phase is a bundled instruction file in `phases/`; this skill sets
17
+ up the scaffold, then you **read the relevant `phases/*.md` file and
18
+ follow it** for that phase. **Never write code during this pipeline.**
19
+ Never skip a phase: each consumes the previous one. If the user asks
20
+ for just one phase, jump straight to that phase file — but first
21
+ confirm its prerequisite docs exist (each file states what it needs).
22
+
23
+ ## Step 1 — Interview (always first)
24
+
25
+ Ask (AskUserQuestion, batched): project name and one-sentence purpose;
26
+ what it explicitly is NOT; target users; whether any docs already
27
+ exist; and how far they want to go now (full pipeline vs one phase).
28
+ Do not proceed on assumptions.
29
+
30
+ ## Step 2 — Scaffold `./docs/`
31
+
32
+ Create these four state files (small, from the answers):
33
+
34
+ - `docs/README.md` — documentation index listing the five phases
35
+ with status markers (✅ / 🚧 Next / ⏳ Planned)
36
+ - `docs/PROJECT_STATE.md` — sections: Project, Current Phase,
37
+ Current Milestone, Completed, Next Tasks, Locked Decisions
38
+ (empty), Conversation Resume Prompt
39
+ - `docs/ROADMAP.md` — phase table + upcoming deliverables +
40
+ "Repository Rule: always update PROJECT_STATE.md and CHANGELOG.md
41
+ after completing a major document"
42
+ - `docs/CHANGELOG.md` — `## v0.1` with the scaffold entry + policy
43
+ line ("Record all significant product, architecture, and
44
+ documentation decisions here")
45
+
46
+ Create empty dirs: `docs/foundation`, `docs/architecture`, `docs/prd`,
47
+ `docs/engineering`, `docs/planning`.
48
+
49
+ ## Step 3 — Drive the phases
50
+
51
+ Work through these in order, one at a time, finishing each before the
52
+ next. For each, **read the phase file and follow it to completion**:
53
+
54
+ | Order | Phase file | Produces |
55
+ |---|---|---|
56
+ | 1 | `phases/foundation.md` | foundation/00–08 |
57
+ | 2 | `phases/architecture.md` | architecture/09 + 09.5 ADRs + 09.A–J |
58
+ | 3 | `phases/prd.md` | prd/10-Master-PRD + Feature PRDs 11+ |
59
+ | 4 | `phases/engineering.md` | engineering/20–25 |
60
+ | 5 | `phases/planning.md` | planning/ overview + phase files |
61
+
62
+ Each phase file ends with a "Done when" gate and a pointer to the next
63
+ file — do not advance until the gate passes.
64
+
65
+ ## House conventions (every phase skill enforces these; you enforce
66
+ them too when reviewing output)
67
+
68
+ 1. **Grill first**: every phase starts with an interview; nothing is
69
+ invented. Recommended defaults are offered, the user decides.
70
+ 2. **Doc format**: header blockquote (`Document ID`, `Status: Draft
71
+ vX.Y`, `Depends On`), a Documentation Roadmap status table,
72
+ `---` separators between sections.
73
+ 3. **Numbering**: 00–08 foundation, 09.x architecture, 10 Master PRD,
74
+ 11+ Feature PRDs, 20+ engineering. IDs never reused.
75
+ 4. **Single source of truth**: reference authoritative docs, never
76
+ duplicate them; the glossary owns terminology; changes to a locked
77
+ decision require a superseding decision recorded in CHANGELOG.
78
+ 5. **Fully-decided rule** (PRDs onward): no "Open Questions" /
79
+ "Pending" / "TBD" sections in Feature PRDs or engineering specs —
80
+ every question is resolved with the user before the document is
81
+ finished. The Master PRD's deferred-registry chapter is the ONLY
82
+ place unresolved future questions may live.
83
+ 6. **Bookkeeping after every major document**: update
84
+ PROJECT_STATE.md (current milestone), CHANGELOG.md (what + why),
85
+ README.md and ROADMAP.md status markers.
86
+ 7. **Validate before declaring done**: grep for unresolved language,
87
+ check ID uniqueness and dangling references, check banned-term
88
+ consistency. Executable artifacts (SQL) get run, not just written.
89
+
90
+ ## Exit
91
+
92
+ When all five phases are complete, generate the project's agent-context
93
+ (primer) file with the `primer` skill — it asks which agentic coding
94
+ tool the user uses and writes the correctly-named file (`CLAUDE.md`,
95
+ `AGENTS.md`, `GEMINI.md`, …) or skips if they use none, reusing
96
+ everything above as interview input. Then hand over to implementation.
@@ -0,0 +1,78 @@
1
+ # Phase 2 — Solution Architecture (docs/architecture/09.x)
2
+
3
+ > Extension of `blueprint`. Read and follow this file when the
4
+ > orchestrator reaches the architecture phase. Requires the foundation
5
+ > docs (00–08) to exist; interviews the user on every technology and
6
+ > boundary choice.
7
+
8
+ Translate the foundation (00–08) into locked technical decisions.
9
+ **Read the foundation docs first** — architecture serves the domain
10
+ model and journeys, not the other way around. Every choice is either
11
+ proposed-with-rationale and confirmed by the user, or given by the
12
+ user directly. The recommendations below are a common default for a
13
+ **web application**; first establish what KIND of system this is (web
14
+ app, service/API, CLI, library, mobile, data pipeline, …) and only
15
+ offer the recommendations that fit — never assume a web stack.
16
+
17
+ ## Interview (before writing)
18
+
19
+ Round 1 — shape: overall structure (for a web/service product recommend
20
+ a modular monolith; but a CLI, library, or pipeline has its own shape —
21
+ match the project type); interface style (REST with a versioned prefix
22
+ is a good web default; others use gRPC, GraphQL, a CLI surface, a public
23
+ library API, message consumers — pick what fits); event needs; async/
24
+ background work if any. Round 2 — stack, offered per tier only when it
25
+ applies and always replaceable: *frontend* (default React + Vite +
26
+ Tailwind + shadcn/ui + TanStack Query + Zustand + RHF + Zod — only if it
27
+ has a UI); *backend/core* (default Node/Express + PostgreSQL + JWT/
28
+ refresh + Argon2id + RBAC — or whatever language/runtime/datastore the
29
+ project actually uses: Python, Go, Rust, Java, …); anything the user's
30
+ org mandates. Round 3 — boundaries: which modules own which data; AI
31
+ isolation requirements; permission/trust philosophy.
32
+
33
+ ## Documents to produce
34
+
35
+ | Doc | Content |
36
+ |---|---|
37
+ | **09-Solution-Architecture** | The umbrella: context, chosen shape, module list, data-flow overview, security boundaries, integration points, and a closing "Transition" section authorizing the Master PRD |
38
+ | **09.5-Architecture-Decision-Records** | ADR-001…N — one per significant choice: context, decision, consequences, alternatives rejected. Governance rule: future changes must reference/supersede an ADR |
39
+ | **09.A-Frontend-Architecture** | Stack, feature-based structure, rendering/build decisions |
40
+ | **09.B-Backend-Architecture** | Stack, process model (api + worker), auth mechanics |
41
+ | **09.C-Module-Boundaries** | The definitive module list — this becomes the Feature-PRD structure AND the code layout; choose carefully |
42
+ | **09.D-Service-Boundaries** | What runs where (processes, jobs) |
43
+ | **09.E-Event-Architecture** | Core business events + consumers (Timeline/Analytics/AI/Notifications pattern) |
44
+ | **09.F-Data-Ownership** | Entity → owning module table; no entity has two owners |
45
+ | **09.G-API-Boundaries** | API prefix, versioning, external surface |
46
+ | **09.H-Permission-Boundaries** | Role → capability summary (coarse; the PRD refines to resource level) |
47
+ | **09.I-State-Management** | Frontend state rules (e.g. "server state in query cache only, never in the client store" — make one locked rule like this) |
48
+ | **09.J-Technology-Stack-Decision** | Final stack table, one line of rationale each |
49
+
50
+ Produce only the docs that fit the project type — several are
51
+ web-specific. A headless service or CLI omits **09.A** (frontend) and
52
+ **09.I** (frontend state); a single-process tool may fold **09.D** into
53
+ 09.B; a project with no eventing skips **09.E**; a library exposing a
54
+ public API documents its surface in **09.G** rather than an HTTP prefix.
55
+ Keep the umbrella (09), ADRs (09.5), module boundaries (09.C), data
56
+ ownership (09.F), and the stack decision (09.J) in every case; note any
57
+ intentionally-omitted doc in 09 so the omission is explicit.
58
+
59
+ Short docs are fine — several of these are half a page. Precision
60
+ beats length.
61
+
62
+ ## Rules
63
+
64
+ - Every decision traces to a foundation need (cite the doc); if the
65
+ user requests something the foundation doesn't justify, ask.
66
+ - Locked decisions go into PROJECT_STATE.md's "Locked Decisions"
67
+ list.
68
+ - House format (metadata header, status table, separators);
69
+ bookkeeping after each doc (PROJECT_STATE, CHANGELOG, ROADMAP,
70
+ README).
71
+
72
+ ## Done when
73
+
74
+ 09 + 09.5 + 09.C + 09.F + 09.J exist plus every other boundary doc that
75
+ applies to this project type (any omitted one is noted in 09); module
76
+ list (09.C) and data ownership (09.F) are mutually consistent; ADRs
77
+ cover every stack row in 09.J; PROJECT_STATE points at the Master PRD
78
+ (`phases/prd.md`).
@@ -0,0 +1,146 @@
1
+ # Phase 4 — Engineering Specifications (docs/engineering/20–25)
2
+
3
+ > Extension of `blueprint`. Read and follow this file when the
4
+ > orchestrator reaches the engineering phase. Derives mechanically from
5
+ > the PRDs; asks the user only for genuine engineering choices;
6
+ > validates executable artifacts.
7
+
8
+ Requires fully-decided PRDs. These documents **derive** from the PRDs
9
+ — if you hit an undecided product question, STOP and send it back
10
+ through the PRD process (Master PRD amendment) before continuing.
11
+ Interview the user only for genuine engineering-level choices (e.g.
12
+ email transport mechanism, deployment target) — present options with a
13
+ recommendation.
14
+
15
+ **Adapt the doc set to the project type (this catalogue is the
16
+ web-app-with-relational-DB default).** Produce only the specs that
17
+ apply, and translate each to the project's real stack:
18
+
19
+ - **20-ERD / 21-Database-Schema** — only if the project has a managed
20
+ datastore. Relational → ERD + DDL as below; a document/KV store →
21
+ document the collections, keys, and invariants in the store's own
22
+ terms; no persistent store (CLI, stateless service, library) → skip
23
+ both.
24
+ - **22-REST-API** — retitle to the actual interface: **22-API** for
25
+ gRPC/GraphQL, **22-CLI-Interface** for a command-line tool,
26
+ **22-Public-API** for a library's exported surface. Keep the intent
27
+ (every operation, its inputs, its errors, its requirement refs).
28
+ - **23-Frontend-Specification** — only if it has a UI; otherwise skip.
29
+ - **24-Backend-Specification** — retitle to **24-Core-Specification**
30
+ for a non-HTTP service, CLI, or library; keep the module/layering,
31
+ guard-placement, and verification content, drop web-only pieces
32
+ (request pipeline, outbox) that don't apply.
33
+ - **25-Deployment-Guide** — match the real delivery model: container
34
+ topology (below), a serverless deploy, a published package
35
+ (registry + versioning + release process), or an app-store build.
36
+
37
+ Renumber nothing — keep 20–25 for the slots that exist, and note any
38
+ skipped doc in 20 (or the umbrella) so the omission is explicit. The
39
+ per-doc detail below is the default profile; carry its *intent* into
40
+ whatever stack the project chose.
41
+
42
+ Every requirement ID cited in these specs must exist in the PRDs —
43
+ run the cross-check grep after each document:
44
+
45
+ ```
46
+ comm -13 <(cat docs/prd/*.md | grep -oE '<ID-REGEX>' | sort -u) \
47
+ <(grep -oE '<ID-REGEX>' <spec>.md | sort -u)
48
+ ```
49
+
50
+ ## 20-ERD
51
+
52
+ Relational model: engineering conventions table (PK strategy, naming,
53
+ timestamps, enum policy, deletion policy = lifecycle statuses not
54
+ soft-deletes, immutability strategy, week/time identification); entity
55
+ overview by owning module (mirror 09.F exactly); mermaid `erDiagram`;
56
+ entity notes for **non-obvious choices only**, each justified by a
57
+ requirement ID; a "referential-integrity rules enforced in schema"
58
+ table (PRD rule → mechanism) and an explicit list of what is
59
+ service-layer instead (state machines, cross-module guards,
60
+ permissions).
61
+
62
+ ## 21-Database-Schema
63
+
64
+ Complete DDL implementing 20, ordered to run top-to-bottom: enum
65
+ types (from the controlled vocabularies — cite requirement IDs in
66
+ comments), tables per module with CHECK constraints for every PRD
67
+ invariant, partial indexes for hot paths, immutability triggers
68
+ (append-only tables + column-level guards for content-immutable
69
+ rows), worker-infrastructure tables (outbox, job ledger, email queue)
70
+ if 24 needs them.
71
+
72
+ **MANDATORY when there is a schema: validate it against a real
73
+ instance** of the chosen engine (a throwaway Docker container or
74
+ equivalent): for SQL, extract the DDL, run with `ON_ERROR_STOP`, count
75
+ tables, smoke-test 2–3 key guards (an immutability trigger, a CHECK
76
+ constraint), tear down; for a non-SQL store, apply the schema/validators
77
+ to a throwaway instance and assert a couple of the invariants. A schema
78
+ doc that hasn't been executed against a real engine is not done.
79
+ Re-validate after every later amendment.
80
+
81
+ ## 22-REST-API
82
+
83
+ Conventions first: base path/versioning (09.G), auth, response/error
84
+ envelope, HTTP-status table (including 409 = business-guard
85
+ violation), pagination. Then per-module endpoint tables (method, path,
86
+ roles, behavior with requirement refs). Rules: **state transitions are
87
+ POST actions, never PATCH status**; a **guard-code registry** section
88
+ mapping every 409 `code` → PRD rule → endpoints; cross-cutting
89
+ behavior section (transactional event emission, AI isolation, async
90
+ 202 pattern, performance budgets).
91
+
92
+ ## 23-Frontend-Specification
93
+
94
+ Stack (from 09.A); feature-folder structure mirroring 09.C with a
95
+ no-cross-feature-internals rule; **route × role matrix** (every route,
96
+ R/RW/— per role, role landing redirects); state-management rules
97
+ (restate the 09.I locked rule operationally: query keys, invalidation,
98
+ optimistic-update policy — never optimistic on guarded actions); API
99
+ layer + **guard-code → UI mapping** (409s become actionable dialogs);
100
+ screens per feature with requirement anchors; cross-cutting UI rules
101
+ (action-first, three-click, read-only rendering, accessibility of
102
+ status colors, AI labeling, performance budgets); verification plan
103
+ (route-permission tests, guard-dialog tests, glossary lint in CI).
104
+
105
+ ## 24-Backend-Specification
106
+
107
+ Process model (api + worker from one codebase); module layout with
108
+ lint-enforced layering (controllers → services → repositories;
109
+ cross-module via exported interfaces only); request pipeline
110
+ (authenticate → status gate → authorize from a single policy table
111
+ transcribing the master permission matrix); **transactional outbox**
112
+ (business write + activity + outbox in one transaction; at-least-once
113
+ idempotent consumers); guard placement table (which service owns which
114
+ guard, row-locked inside the mutation transaction); notification
115
+ matrix engine; **scheduled-jobs table** (job, schedule in org
116
+ timezone, behavior, all idempotent via the job ledger); external
117
+ integration flows in full (e.g. email: connection, send pipeline,
118
+ retry/backoff, failure handling — never leave an integration as a
119
+ one-liner); AI pipeline + isolation (restricted DB role) if
120
+ applicable; security parameters; verification plan.
121
+
122
+ ## 25-Deployment-Guide
123
+
124
+ Topology (recommend Docker Compose single host for a modular-monolith
125
+ MVP; images orchestrator-agnostic); image table (multi-stage, non-root,
126
+ SHA-versioned, never `latest`); environment-variable table (secrets
127
+ only — runtime org config belongs in the database); migrations
128
+ (one-shot container, forward-only, boot-time version check);
129
+ least-privilege DB roles; backup/PITR/restore-drill policy sized to
130
+ what the PRDs declare precious; TLS/proxy/runtime policies;
131
+ health/monitoring/alerts table; deploy + rollback procedure; first-
132
+ install bootstrap (including the seed-admin exception); **Development
133
+ Guide section**: docker-compose.dev with hot reload (watcher backend,
134
+ HMR frontend, bind mounts), dev provider substitutions through the
135
+ same interfaces (mail catcher, AI stub), committed dev env file, seed
136
+ command, manual job triggering, and dev/prod parity rules (no guard
137
+ bypasses).
138
+
139
+ ## Bookkeeping & done
140
+
141
+ After each doc: cross-check grep, PROJECT_STATE, CHANGELOG (record
142
+ engineering decisions like transport choices individually), ROADMAP/
143
+ README markers. Done when every applicable spec in the 20–25 range
144
+ exists (skipped ones noted), any schema has passed live validation
145
+ against a real engine, all reference greps are clean, and PROJECT_STATE
146
+ points at planning (`phases/planning.md`).