agent-docs-kit 2.1.0__py3-none-any.whl

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.
Files changed (40) hide show
  1. agent_docs_kit-2.1.0.dist-info/METADATA +299 -0
  2. agent_docs_kit-2.1.0.dist-info/RECORD +40 -0
  3. agent_docs_kit-2.1.0.dist-info/WHEEL +4 -0
  4. agent_docs_kit-2.1.0.dist-info/entry_points.txt +3 -0
  5. agent_docs_kit-2.1.0.dist-info/licenses/LICENSE +21 -0
  6. living_docs_cli/__init__.py +686 -0
  7. living_docs_cli/__main__.py +3 -0
  8. living_docs_cli/assets/fumadocs-starter/app/docs/[[...slug]]/page.tsx +44 -0
  9. living_docs_cli/assets/fumadocs-starter/app/docs/layout.tsx +12 -0
  10. living_docs_cli/assets/fumadocs-starter/app/global.css +450 -0
  11. living_docs_cli/assets/fumadocs-starter/app/layout.tsx +15 -0
  12. living_docs_cli/assets/fumadocs-starter/app/page.tsx +5 -0
  13. living_docs_cli/assets/fumadocs-starter/components/living-docs/index.tsx +185 -0
  14. living_docs_cli/assets/fumadocs-starter/components/mdx.tsx +27 -0
  15. living_docs_cli/assets/fumadocs-starter/content/docs/architecture.mdx +55 -0
  16. living_docs_cli/assets/fumadocs-starter/content/docs/components.mdx +132 -0
  17. living_docs_cli/assets/fumadocs-starter/content/docs/glossary.mdx +16 -0
  18. living_docs_cli/assets/fumadocs-starter/content/docs/index.mdx +72 -0
  19. living_docs_cli/assets/fumadocs-starter/content/docs/meta.json +4 -0
  20. living_docs_cli/assets/fumadocs-starter/lib/layout.shared.ts +7 -0
  21. living_docs_cli/assets/fumadocs-starter/lib/source.ts +7 -0
  22. living_docs_cli/assets/fumadocs-starter/next-env.d.ts +4 -0
  23. living_docs_cli/assets/fumadocs-starter/next.config.mjs +10 -0
  24. living_docs_cli/assets/fumadocs-starter/package.json +27 -0
  25. living_docs_cli/assets/fumadocs-starter/source.config.ts +34 -0
  26. living_docs_cli/assets/fumadocs-starter/tsconfig.json +23 -0
  27. living_docs_cli/assets/project/.living-docs/scripts/check.mjs +72 -0
  28. living_docs_cli/assets/project/.living-docs/scripts/create-doc.mjs +88 -0
  29. living_docs_cli/assets/project/.living-docs/scripts/glossary.mjs +107 -0
  30. living_docs_cli/assets/project/.living-docs/templates/architecture.mdx +51 -0
  31. living_docs_cli/assets/project/.living-docs/templates/change.mdx +40 -0
  32. living_docs_cli/assets/project/.living-docs/templates/glossary.mdx +15 -0
  33. living_docs_cli/assets/project/.living-docs/templates/plan.mdx +54 -0
  34. living_docs_cli/assets/styles/atlas.css +450 -0
  35. living_docs_cli/assets/workflow-skills/living-docs-architecture/SKILL.md +55 -0
  36. living_docs_cli/assets/workflow-skills/living-docs-change/SKILL.md +62 -0
  37. living_docs_cli/assets/workflow-skills/living-docs-check/SKILL.md +32 -0
  38. living_docs_cli/assets/workflow-skills/living-docs-glossary/SKILL.md +30 -0
  39. living_docs_cli/assets/workflow-skills/living-docs-plan/SKILL.md +55 -0
  40. living_docs_cli/assets/workflow-skills/living-docs-write/SKILL.md +46 -0
@@ -0,0 +1,27 @@
1
+ import defaultMdxComponents from 'fumadocs-ui/mdx';
2
+ import type { MDXComponents } from 'mdx/types';
3
+ import {
4
+ ArchMap,
5
+ ChangeMeta,
6
+ DocsHero,
7
+ FlowSteps,
8
+ SkillGrid,
9
+ StateFlow,
10
+ TermGrid,
11
+ } from './living-docs';
12
+
13
+ export function getMDXComponents(components?: MDXComponents) {
14
+ return {
15
+ ...defaultMdxComponents,
16
+ ArchMap,
17
+ ChangeMeta,
18
+ DocsHero,
19
+ FlowSteps,
20
+ SkillGrid,
21
+ StateFlow,
22
+ TermGrid,
23
+ ...components,
24
+ } satisfies MDXComponents;
25
+ }
26
+
27
+ export const useMDXComponents = getMDXComponents;
@@ -0,0 +1,55 @@
1
+ ---
2
+ title: "System Architecture"
3
+ description: "Current cross-domain architecture."
4
+ domain: "system"
5
+ type: "architecture"
6
+ status: "active"
7
+ date: "__TODAY__"
8
+ terms:
9
+ - name: "Domain"
10
+ description: "A documentation area that maps to a subsystem, product surface, or ownership boundary."
11
+ - name: "Change Record"
12
+ description: "An immutable page that records a shipped change, its motivation, and verification."
13
+ ---
14
+
15
+ # System Architecture
16
+
17
+ Use this page for cross-domain architecture. Keep it current; put history in change records.
18
+
19
+ <ArchMap
20
+ tiers={[
21
+ {
22
+ title: 'Documentation source',
23
+ boxes: [
24
+ { title: 'MDX pages', body: 'Human and agent editable source files.', tone: 'blue' },
25
+ { title: 'Frontmatter', body: 'Structured metadata for domains, types, dates, and terms.' },
26
+ ],
27
+ },
28
+ {
29
+ title: 'Presentation',
30
+ boxes: [
31
+ { title: 'Fumadocs', body: 'Renders navigation, search-ready pages, and MDX components.', tone: 'green' },
32
+ ],
33
+ },
34
+ {
35
+ title: 'Agent workflow',
36
+ boxes: [
37
+ { title: 'living-docs skills', body: 'Create architecture, change, plan, glossary, and check workflows.', tone: 'violet' },
38
+ ],
39
+ },
40
+ ]}
41
+ />
42
+
43
+ ## Maintenance Rules
44
+
45
+ - Update architecture pages after meaningful system changes.
46
+ - Create change records for shipped behavior, contracts, or architecture changes.
47
+ - Run the glossary generator when terms change.
48
+ - Run the check gate before committing docs changes.
49
+
50
+ <TermGrid
51
+ items={[
52
+ { name: 'Domain', description: 'A documentation area that maps to a subsystem, product surface, or ownership boundary.' },
53
+ { name: 'Change Record', description: 'An immutable page that records a shipped change, its motivation, and verification.' },
54
+ ]}
55
+ />
@@ -0,0 +1,132 @@
1
+ ---
2
+ title: "Components"
3
+ description: "Reusable MDX components for architecture, flow, state, change, and glossary docs."
4
+ type: "guide"
5
+ ---
6
+
7
+ # Components
8
+
9
+ Use these MDX components directly in living-docs pages. Prefer components for
10
+ common documentation shapes, and use mermaid only when the diagram needs custom
11
+ graph syntax such as sequence diagrams, complex branches, or ER diagrams.
12
+
13
+ ## Architecture Map
14
+
15
+ Use `<ArchMap />` for layered system structure.
16
+
17
+ ```mdx
18
+ <ArchMap
19
+ tiers={[
20
+ {
21
+ title: 'Entry points',
22
+ boxes: [
23
+ { title: 'Web app', body: 'User-facing route or shell.', tone: 'blue' },
24
+ { title: 'API', body: 'Server boundary and contract.', tone: 'green' },
25
+ ],
26
+ },
27
+ {
28
+ title: 'Core services',
29
+ boxes: [
30
+ { title: 'Domain service', body: 'Business rules and orchestration.' },
31
+ ],
32
+ },
33
+ ]}
34
+ />
35
+ ```
36
+
37
+ <ArchMap
38
+ tiers={[
39
+ {
40
+ title: 'Entry points',
41
+ boxes: [
42
+ { title: 'Web app', body: 'User-facing route or shell.', tone: 'blue' },
43
+ { title: 'API', body: 'Server boundary and contract.', tone: 'green' },
44
+ ],
45
+ },
46
+ {
47
+ title: 'Core services',
48
+ boxes: [
49
+ { title: 'Domain service', body: 'Business rules and orchestration.' },
50
+ ],
51
+ },
52
+ ]}
53
+ />
54
+
55
+ ## Flow Steps
56
+
57
+ Use `<FlowSteps />` for request paths, execution flows, or operational runbooks.
58
+
59
+ ```mdx
60
+ <FlowSteps
61
+ title="Request flow"
62
+ steps={[
63
+ { title: 'Receive input', body: 'Validate payload and identify the domain.', tone: 'blue' },
64
+ { title: 'Run service', body: 'Execute the domain action and persist state.', tone: 'green' },
65
+ { title: 'Return result', body: 'Send user-visible status and telemetry.', tone: 'amber' },
66
+ ]}
67
+ />
68
+ ```
69
+
70
+ <FlowSteps
71
+ title="Request flow"
72
+ steps={[
73
+ { title: 'Receive input', body: 'Validate payload and identify the domain.', tone: 'blue' },
74
+ { title: 'Run service', body: 'Execute the domain action and persist state.', tone: 'green' },
75
+ { title: 'Return result', body: 'Send user-visible status and telemetry.', tone: 'amber' },
76
+ ]}
77
+ />
78
+
79
+ ## State Flow
80
+
81
+ Use `<StateFlow />` for lifecycle states and simple state machines.
82
+
83
+ ```mdx
84
+ <StateFlow
85
+ title="Document lifecycle"
86
+ states={[
87
+ { name: 'draft', description: 'Plan or work in progress.', tone: 'amber' },
88
+ { name: 'active', description: 'Current runtime truth.', tone: 'green' },
89
+ { name: 'archived', description: 'Kept for history.' },
90
+ ]}
91
+ />
92
+ ```
93
+
94
+ <StateFlow
95
+ title="Document lifecycle"
96
+ states={[
97
+ { name: 'draft', description: 'Plan or work in progress.', tone: 'amber' },
98
+ { name: 'active', description: 'Current runtime truth.', tone: 'green' },
99
+ { name: 'archived', description: 'Kept for history.' },
100
+ ]}
101
+ />
102
+
103
+ ## Change Metadata
104
+
105
+ Use `<ChangeMeta />` at the top of change records.
106
+
107
+ ```mdx
108
+ <ChangeMeta date="2026-06-17" source="commit or PR" tests="npm run build" />
109
+ ```
110
+
111
+ <ChangeMeta date="2026-06-17" source="commit or PR" tests="npm run build" />
112
+
113
+ ## Terms
114
+
115
+ Use `<TermGrid />` for page-local vocabulary. The generated glossary is still
116
+ built from frontmatter `terms`, so keep the frontmatter updated too.
117
+
118
+ ```mdx
119
+ <TermGrid
120
+ items={[
121
+ { name: 'Domain', description: 'A subsystem or business area.' },
122
+ { name: 'Change record', description: 'Immutable record of shipped behavior.' },
123
+ ]}
124
+ />
125
+ ```
126
+
127
+ <TermGrid
128
+ items={[
129
+ { name: 'Domain', description: 'A subsystem or business area.' },
130
+ { name: 'Change record', description: 'Immutable record of shipped behavior.' },
131
+ ]}
132
+ />
@@ -0,0 +1,16 @@
1
+ ---
2
+ title: "Glossary"
3
+ description: "Generated term index for living-docs"
4
+ type: "glossary"
5
+ ---
6
+
7
+ # Glossary
8
+
9
+ Generated from MDX frontmatter `terms`.
10
+
11
+ <TermGrid
12
+ items={[
13
+ { name: "Change Record", description: "An immutable page that records a shipped change, its motivation, and verification.", meta: "system · architecture.mdx" },
14
+ { name: "Domain", description: "A documentation area that maps to a subsystem, product surface, or ownership boundary.", meta: "system · architecture.mdx" },
15
+ ]}
16
+ />
@@ -0,0 +1,72 @@
1
+ ---
2
+ title: "Overview"
3
+ description: "A living documentation system powered by Fumadocs and MDX."
4
+ type: "guide"
5
+ ---
6
+
7
+ <DocsHero
8
+ title="__PROJECT_NAME__ Documentation"
9
+ description="A skills-first documentation workspace for architecture, shipped changes, future plans, and shared vocabulary."
10
+ primaryLabel="Open architecture"
11
+ primaryHref="/docs/architecture"
12
+ secondaryLabel="View glossary"
13
+ secondaryHref="/docs/glossary"
14
+ />
15
+
16
+ This documentation system is managed by living-docs. Use MDX as the source of truth and Fumadocs as the presentation layer.
17
+
18
+ Reusable documentation components are available in [Components](/docs/components).
19
+
20
+ ## Structure
21
+
22
+ - Architecture pages describe current system shape.
23
+ - Change pages record what changed and why.
24
+ - Plan pages capture future design directions.
25
+ - The glossary is generated from frontmatter `terms`.
26
+
27
+ ## Skills
28
+
29
+ Use these project-local skills from your agent:
30
+
31
+ <SkillGrid
32
+ items={[
33
+ {
34
+ name: 'living-docs-write',
35
+ body: 'Route general documentation requests to the right architecture, change, plan, glossary, or validation workflow.',
36
+ tone: 'violet',
37
+ },
38
+ {
39
+ name: 'living-docs-architecture',
40
+ body: 'Capture the current system shape, contracts, runtime paths, and diagrams.',
41
+ tone: 'blue',
42
+ },
43
+ {
44
+ name: 'living-docs-change',
45
+ body: 'Record shipped behavior changes with source files, validation, and follow-up notes.',
46
+ tone: 'green',
47
+ },
48
+ {
49
+ name: 'living-docs-plan',
50
+ body: 'Draft future design directions before they become committed change records.',
51
+ tone: 'amber',
52
+ },
53
+ {
54
+ name: 'living-docs-glossary',
55
+ body: 'Regenerate shared vocabulary from frontmatter terms across the docs.',
56
+ tone: 'violet',
57
+ },
58
+ {
59
+ name: 'living-docs-check',
60
+ body: 'Validate MDX health, required diagrams, generated glossary, and managed docs metadata.',
61
+ tone: 'red',
62
+ },
63
+ ]}
64
+ />
65
+
66
+ The skills use these project-local scripts:
67
+
68
+ ```bash
69
+ node .living-docs/scripts/create-doc.mjs change api auth-flow "Auth Flow Update"
70
+ node .living-docs/scripts/glossary.mjs
71
+ node .living-docs/scripts/check.mjs
72
+ ```
@@ -0,0 +1,4 @@
1
+ {
2
+ "title": "__PROJECT_NAME__",
3
+ "pages": ["index", "architecture", "components", "glossary", "..."]
4
+ }
@@ -0,0 +1,7 @@
1
+ import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
2
+
3
+ export const baseOptions: BaseLayoutProps = {
4
+ nav: {
5
+ title: '__PROJECT_NAME__ Docs',
6
+ },
7
+ };
@@ -0,0 +1,7 @@
1
+ import { docs } from '@/.source/server';
2
+ import { loader } from 'fumadocs-core/source';
3
+
4
+ export const source = loader({
5
+ baseUrl: '/docs',
6
+ source: docs.toFumadocsSource(),
7
+ });
@@ -0,0 +1,4 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
3
+
4
+ // This file is generated for the living-docs starter and should not be edited.
@@ -0,0 +1,10 @@
1
+ import { createMDX } from 'fumadocs-mdx/next';
2
+
3
+ const withMDX = createMDX();
4
+
5
+ /** @type {import('next').NextConfig} */
6
+ const config = {
7
+ reactStrictMode: true,
8
+ };
9
+
10
+ export default withMDX(config);
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "__PROJECT_NAME__-docs",
3
+ "private": true,
4
+ "scripts": {
5
+ "dev": "next dev",
6
+ "build": "next build",
7
+ "start": "next start",
8
+ "typecheck": "fumadocs-mdx && tsc --noEmit",
9
+ "docs:check": "node ../.living-docs/scripts/check.mjs",
10
+ "docs:glossary": "node ../.living-docs/scripts/glossary.mjs"
11
+ },
12
+ "dependencies": {
13
+ "fumadocs-core": "^16.10.3",
14
+ "fumadocs-mdx": "^15.0.12",
15
+ "fumadocs-ui": "^16.10.3",
16
+ "next": "^16.2.9",
17
+ "react": "^19.2.7",
18
+ "react-dom": "^19.2.7",
19
+ "zod": "^4.4.3"
20
+ },
21
+ "devDependencies": {
22
+ "@types/node": "^25.9.3",
23
+ "@types/react": "^19.2.17",
24
+ "@types/react-dom": "^19.2.3",
25
+ "typescript": "^6.0.3"
26
+ }
27
+ }
@@ -0,0 +1,34 @@
1
+ import { defineConfig, defineDocs } from 'fumadocs-mdx/config';
2
+ import { pageSchema, metaSchema } from 'fumadocs-core/source/schema';
3
+ import { z } from 'zod';
4
+
5
+ export const docs = defineDocs({
6
+ dir: 'content/docs',
7
+ docs: {
8
+ schema: pageSchema.extend({
9
+ domain: z.string().optional(),
10
+ type: z.enum(['guide', 'architecture', 'change', 'plan', 'glossary']).default('guide'),
11
+ status: z.enum(['draft', 'active', 'shipped', 'deprecated']).optional(),
12
+ date: z.string().optional(),
13
+ source: z.string().optional(),
14
+ tests: z.string().optional(),
15
+ terms: z
16
+ .array(
17
+ z.object({
18
+ name: z.string(),
19
+ description: z.string(),
20
+ }),
21
+ )
22
+ .default([]),
23
+ }),
24
+ },
25
+ meta: {
26
+ schema: metaSchema,
27
+ },
28
+ });
29
+
30
+ export default defineConfig({
31
+ mdxOptions: {
32
+ providerImportSource: '@/components/mdx',
33
+ },
34
+ });
@@ -0,0 +1,23 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["dom", "dom.iterable", "es2022"],
5
+ "allowJs": false,
6
+ "skipLibCheck": true,
7
+ "strict": true,
8
+ "noEmit": true,
9
+ "esModuleInterop": true,
10
+ "module": "esnext",
11
+ "moduleResolution": "bundler",
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "jsx": "react-jsx",
15
+ "incremental": true,
16
+ "plugins": [{ "name": "next" }],
17
+ "paths": {
18
+ "@/*": ["./*"]
19
+ }
20
+ },
21
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".source/**/*.ts", ".next/types/**/*.ts", ".next/dev/types/**/*.ts"],
22
+ "exclude": ["node_modules"]
23
+ }
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env node
2
+ import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
3
+ import { join, relative } from 'node:path';
4
+
5
+ const root = process.cwd();
6
+ const configPath = join(root, '.living-docs', 'config.json');
7
+ const errors = [];
8
+
9
+ function walk(dir) {
10
+ const results = [];
11
+ for (const name of readdirSync(dir)) {
12
+ const path = join(dir, name);
13
+ const stat = statSync(path);
14
+ if (stat.isDirectory()) results.push(...walk(path));
15
+ if (stat.isFile() && path.endsWith('.mdx')) results.push(path);
16
+ }
17
+ return results;
18
+ }
19
+
20
+ function frontmatter(text) {
21
+ if (!text.startsWith('---\n')) return '';
22
+ const end = text.indexOf('\n---', 4);
23
+ return end === -1 ? '' : text.slice(4, end);
24
+ }
25
+
26
+ function scalar(fm, key) {
27
+ const match = fm.match(new RegExp(`^${key}:\\s*["']?([^"'\\n]+)["']?\\s*$`, 'm'));
28
+ return match?.[1]?.trim() || '';
29
+ }
30
+
31
+ function hasDiagram(text) {
32
+ return ['<ArchMap', '<FlowSteps', '<StateFlow', '```mermaid'].some((marker) => text.includes(marker));
33
+ }
34
+
35
+ if (!existsSync(configPath)) {
36
+ errors.push('missing .living-docs/config.json');
37
+ } else {
38
+ const config = JSON.parse(readFileSync(configPath, 'utf8'));
39
+ const contentDir = join(root, config.contentDir || 'docs/content/docs');
40
+ if (!existsSync(contentDir)) {
41
+ errors.push(`missing content directory: ${relative(root, contentDir)}`);
42
+ } else {
43
+ const files = walk(contentDir);
44
+ if (files.length === 0) errors.push('no MDX files found');
45
+ for (const file of files) {
46
+ const rel = relative(root, file);
47
+ const text = readFileSync(file, 'utf8');
48
+ const fm = frontmatter(text);
49
+ const type = scalar(fm, 'type');
50
+ if (!scalar(fm, 'title')) errors.push(`${rel}: missing title`);
51
+ if (rel.includes('/changes/') && type !== 'change') errors.push(`${rel}: changes pages must set type: change`);
52
+ if (rel.includes('/plans/') && type !== 'plan') errors.push(`${rel}: plan pages must set type: plan`);
53
+ if ((type === 'architecture' || type === 'change') && !hasDiagram(text)) {
54
+ errors.push(`${rel}: architecture/change docs need <ArchMap />, <FlowSteps />, <StateFlow />, or mermaid`);
55
+ }
56
+ if ((type === 'architecture' || type === 'change' || type === 'plan') && !fm.includes('terms:') && !text.includes('<TermGrid')) {
57
+ errors.push(`${rel}: managed docs should define terms or render <TermGrid />`);
58
+ }
59
+ }
60
+ if (!existsSync(join(contentDir, 'glossary.mdx'))) {
61
+ errors.push('missing glossary.mdx; run node .living-docs/scripts/glossary.mjs');
62
+ }
63
+ }
64
+ }
65
+
66
+ if (errors.length) {
67
+ console.error(`living-docs check failed (${errors.length} issue(s))`);
68
+ for (const error of errors) console.error(` - ${error}`);
69
+ process.exit(1);
70
+ }
71
+
72
+ console.log('living-docs check passed');
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env node
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
3
+ import { dirname, join } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+
6
+ const root = process.cwd();
7
+ const configPath = join(root, '.living-docs', 'config.json');
8
+
9
+ function fail(message) {
10
+ console.error(`Error: ${message}`);
11
+ process.exit(1);
12
+ }
13
+
14
+ if (!existsSync(configPath)) {
15
+ fail('missing .living-docs/config.json; run living-docs init first');
16
+ }
17
+
18
+ const config = JSON.parse(readFileSync(configPath, 'utf8'));
19
+ const contentDir = join(root, config.contentDir || 'docs/content/docs');
20
+ const templatesDir = join(root, '.living-docs', 'templates');
21
+
22
+ function slugify(input) {
23
+ return input
24
+ .toLowerCase()
25
+ .trim()
26
+ .replace(/[^a-z0-9]+/g, '-')
27
+ .replace(/^-+|-+$/g, '') || 'doc';
28
+ }
29
+
30
+ function titleize(input) {
31
+ return input
32
+ .replace(/[-_]+/g, ' ')
33
+ .replace(/\s+/g, ' ')
34
+ .trim()
35
+ .replace(/\b\w/g, (c) => c.toUpperCase());
36
+ }
37
+
38
+ function render(template, values) {
39
+ let out = template;
40
+ for (const [key, value] of Object.entries(values)) {
41
+ out = out.replaceAll(`__${key}__`, value);
42
+ }
43
+ return out;
44
+ }
45
+
46
+ function writeNew(path, content) {
47
+ if (existsSync(path)) {
48
+ fail(`refusing to overwrite existing file: ${path}`);
49
+ }
50
+ mkdirSync(dirname(path), { recursive: true });
51
+ writeFileSync(path, content);
52
+ }
53
+
54
+ const [kind, domainArg, topicArg, ...titleParts] = process.argv.slice(2);
55
+ if (!kind || !['architecture', 'change', 'plan'].includes(kind)) {
56
+ fail('usage: create-doc.mjs <architecture|change|plan> <domain> [topic-slug] [title]');
57
+ }
58
+ if (!domainArg) {
59
+ fail('domain is required');
60
+ }
61
+
62
+ const domain = slugify(domainArg);
63
+ const today = new Date().toISOString().slice(0, 10);
64
+ const topic = topicArg ? slugify(topicArg) : domain;
65
+ const title = titleParts.length ? titleParts.join(' ') : titleize(topic);
66
+ const source = process.env.LIVING_DOCS_SOURCE || 'TODO';
67
+ const tests = process.env.LIVING_DOCS_TESTS || 'TODO';
68
+
69
+ let templateName = `${kind}.mdx`;
70
+ let outPath;
71
+ if (kind === 'architecture') {
72
+ outPath = join(contentDir, domain, 'architecture.mdx');
73
+ } else if (kind === 'change') {
74
+ outPath = join(contentDir, domain, 'changes', `${today}-${topic}.mdx`);
75
+ } else {
76
+ outPath = join(contentDir, domain, 'plans', `${topic}.mdx`);
77
+ }
78
+
79
+ const template = readFileSync(join(templatesDir, templateName), 'utf8');
80
+ writeNew(outPath, render(template, {
81
+ TITLE: title,
82
+ DOMAIN: domain,
83
+ DATE: today,
84
+ SOURCE: source,
85
+ TESTS: tests,
86
+ }));
87
+
88
+ console.log(outPath);