@nurix/etna 0.19.66 → 0.19.67
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/bin/etna.js +10 -1
- package/data/harness-index.json +1 -5
- package/data/harnesses/code/CLAUDE.md +2 -0
- package/data/harnesses/code/agents/maintenance.md +3 -1
- package/data/harnesses/code/harness.json +7 -2
- package/data/harnesses/code/hooks/compliance.mjs +1 -0
- package/data/harnesses/code/hooks/lib/frozen.mjs +3 -0
- package/data/harnesses/code/hooks/lib/ownership.mjs +3 -1
- package/data/harnesses/code/skills/documentation/scripts/doc-lint.mjs +1 -1
- package/data/harnesses/delivery/agents/maintenance.md +3 -1
- package/data/harnesses/delivery/harness.json +2 -2
- package/data/harnesses/delivery/skills/documentation/scripts/doc-lint.mjs +1 -1
- package/data/harnesses/etna/agents/maintenance.md +3 -1
- package/data/harnesses/etna/harness.json +2 -2
- package/data/harnesses/etna/skills/documentation/scripts/doc-lint.mjs +1 -1
- package/lib/install/materialize.mjs +51 -57
- package/package.json +2 -2
- package/data/harnesses/apollo/.mcp.json +0 -8
- package/data/harnesses/apollo/.prettierignore +0 -29
- package/data/harnesses/apollo/.prettierrc.json +0 -3
- package/data/harnesses/apollo/.vscode/settings.json +0 -19
- package/data/harnesses/apollo/CLAUDE.md +0 -162
- package/data/harnesses/apollo/agents/bookkeeper.md +0 -28
- package/data/harnesses/apollo/agents/brainstorm.md +0 -144
- package/data/harnesses/apollo/agents/change-review.md +0 -251
- package/data/harnesses/apollo/agents/lld-mode.md +0 -58
- package/data/harnesses/apollo/agents/maintenance.md +0 -234
- package/data/harnesses/apollo/agents/performance-review.md +0 -223
- package/data/harnesses/apollo/agents/retro.md +0 -46
- package/data/harnesses/apollo/codex/agents/bookkeeper.toml +0 -26
- package/data/harnesses/apollo/codex/agents/brainstorm.toml +0 -142
- package/data/harnesses/apollo/codex/agents/change-review.toml +0 -249
- package/data/harnesses/apollo/codex/agents/lld-mode.toml +0 -52
- package/data/harnesses/apollo/codex/agents/maintenance.toml +0 -228
- package/data/harnesses/apollo/codex/agents/performance-review.toml +0 -222
- package/data/harnesses/apollo/codex/agents/retro.toml +0 -45
- package/data/harnesses/apollo/harness.json +0 -19
- package/data/harnesses/apollo/hooks/approved-packages.md +0 -44
- package/data/harnesses/apollo/hooks/awareness.mjs +0 -405
- package/data/harnesses/apollo/hooks/check-bookkeeping-clean.mjs +0 -19
- package/data/harnesses/apollo/hooks/check-changelog-presence.mjs +0 -57
- package/data/harnesses/apollo/hooks/check-completion-integrity.mjs +0 -71
- package/data/harnesses/apollo/hooks/check-ownership.mjs +0 -22
- package/data/harnesses/apollo/hooks/compliance.mjs +0 -457
- package/data/harnesses/apollo/hooks/hooks.json +0 -23
- package/data/harnesses/apollo/hooks/lib/frozen.mjs +0 -58
- package/data/harnesses/apollo/hooks/lib/ownership.mjs +0 -242
- package/data/harnesses/apollo/hooks/lib/state.mjs +0 -170
- package/data/harnesses/apollo/rules/changelog.md +0 -27
- package/data/harnesses/apollo/rules/database.md +0 -34
- package/data/harnesses/apollo/rules/frontend.md +0 -30
- package/data/harnesses/apollo/rules/general.md +0 -40
- package/data/harnesses/apollo/rules/nomenclature.md +0 -30
- package/data/harnesses/apollo/rules/pnpm.md +0 -57
- package/data/harnesses/apollo/rules/testing.md +0 -64
- package/data/harnesses/apollo/skills/boundary/SKILL.md +0 -75
- package/data/harnesses/apollo/skills/boundary/references/index.md +0 -16
- package/data/harnesses/apollo/skills/boundary/references/mechanisms.md +0 -99
- package/data/harnesses/apollo/skills/boundary/references/packs/async-messaging.md +0 -81
- package/data/harnesses/apollo/skills/boundary/references/packs/auth.md +0 -93
- package/data/harnesses/apollo/skills/boundary/references/packs/build-config-runtime.md +0 -93
- package/data/harnesses/apollo/skills/boundary/references/packs/cloudflare.md +0 -93
- package/data/harnesses/apollo/skills/boundary/references/packs/frontend.md +0 -93
- package/data/harnesses/apollo/skills/boundary/references/packs/generic-tail.md +0 -55
- package/data/harnesses/apollo/skills/boundary/references/packs/persistence.md +0 -93
- package/data/harnesses/apollo/skills/boundary/references/packs/wire-api.md +0 -87
- package/data/harnesses/apollo/skills/brainstorm/README.md +0 -56
- package/data/harnesses/apollo/skills/brainstorm/SKILL.md +0 -173
- package/data/harnesses/apollo/skills/brainstorm/references/doctrine.md +0 -98
- package/data/harnesses/apollo/skills/brainstorm/references/harvest.md +0 -86
- package/data/harnesses/apollo/skills/brainstorm/references/session-schema.md +0 -186
- package/data/harnesses/apollo/skills/brainstorm/scripts/detector.mjs +0 -460
- package/data/harnesses/apollo/skills/design/SKILL.md +0 -121
- package/data/harnesses/apollo/skills/design/components/charts.md +0 -76
- package/data/harnesses/apollo/skills/design/components/collections.md +0 -132
- package/data/harnesses/apollo/skills/design/components/feedback.md +0 -47
- package/data/harnesses/apollo/skills/design/components/hooks.md +0 -35
- package/data/harnesses/apollo/skills/design/components/index.md +0 -143
- package/data/harnesses/apollo/skills/design/components/inputs.md +0 -327
- package/data/harnesses/apollo/skills/design/components/layout.md +0 -52
- package/data/harnesses/apollo/skills/design/components/media.md +0 -66
- package/data/harnesses/apollo/skills/design/components/motion.md +0 -82
- package/data/harnesses/apollo/skills/design/components/navigation.md +0 -29
- package/data/harnesses/apollo/skills/design/components/overlays.md +0 -72
- package/data/harnesses/apollo/skills/design/components/setup.md +0 -40
- package/data/harnesses/apollo/skills/design/components/typography.md +0 -46
- package/data/harnesses/apollo/skills/design/components/utils.md +0 -37
- package/data/harnesses/apollo/skills/design/data/blueprints/browse.md +0 -38
- package/data/harnesses/apollo/skills/design/data/blueprints/creation-flow.md +0 -38
- package/data/harnesses/apollo/skills/design/data/blueprints/dashboard.md +0 -38
- package/data/harnesses/apollo/skills/design/data/blueprints/grid.md +0 -38
- package/data/harnesses/apollo/skills/design/data/blueprints/queue.md +0 -38
- package/data/harnesses/apollo/skills/design/data/blueprints/record-detail.md +0 -38
- package/data/harnesses/apollo/skills/design/data/blueprints/settings.md +0 -38
- package/data/harnesses/apollo/skills/design/data/charts/census.csv +0 -58
- package/data/harnesses/apollo/skills/design/data/checklists/browse.md +0 -21
- package/data/harnesses/apollo/skills/design/data/checklists/creation-flow.md +0 -20
- package/data/harnesses/apollo/skills/design/data/checklists/dashboard.md +0 -21
- package/data/harnesses/apollo/skills/design/data/checklists/grid.md +0 -21
- package/data/harnesses/apollo/skills/design/data/checklists/queue.md +0 -21
- package/data/harnesses/apollo/skills/design/data/checklists/record-detail.md +0 -21
- package/data/harnesses/apollo/skills/design/data/checklists/settings.md +0 -21
- package/data/harnesses/apollo/skills/design/data/chrome/board-column.md +0 -68
- package/data/harnesses/apollo/skills/design/data/chrome/data-table.md +0 -63
- package/data/harnesses/apollo/skills/design/data/chrome/side-panel.md +0 -60
- package/data/harnesses/apollo/skills/design/data/chrome/sidebar.md +0 -78
- package/data/harnesses/apollo/skills/design/data/chrome/stat-cards.md +0 -62
- package/data/harnesses/apollo/skills/design/data/chrome/topbar.md +0 -65
- package/data/harnesses/apollo/skills/design/data/elevation/ant-design-directional-shadow.md +0 -19
- package/data/harnesses/apollo/skills/design/data/elevation/apple-liquid-glass-material.md +0 -18
- package/data/harnesses/apollo/skills/design/data/elevation/atlassian-surface-shadow-pairing.md +0 -20
- package/data/harnesses/apollo/skills/design/data/elevation/fluent-2-key-ambient-ramp.md +0 -20
- package/data/harnesses/apollo/skills/design/data/elevation/github-primer-sparing-shadow.md +0 -19
- package/data/harnesses/apollo/skills/design/data/elevation/ibm-carbon-layer-and-border.md +0 -19
- package/data/harnesses/apollo/skills/design/data/elevation/linear-dark-surface-ladder.md +0 -17
- package/data/harnesses/apollo/skills/design/data/elevation/material-2-key-ambient-dp-ramp.md +0 -19
- package/data/harnesses/apollo/skills/design/data/elevation/material-3-tonal-elevation.md +0 -21
- package/data/harnesses/apollo/skills/design/data/elevation/neobrutalist-hard-offset.md +0 -19
- package/data/harnesses/apollo/skills/design/data/elevation/neumorphic-soft-dual-shadow.md +0 -18
- package/data/harnesses/apollo/skills/design/data/elevation/notion-warm-minimal-hairline.md +0 -17
- package/data/harnesses/apollo/skills/design/data/elevation/polaris-elevation-inset-bevel.md +0 -21
- package/data/harnesses/apollo/skills/design/data/elevation/radix-themes-alpha-ring-scale.md +0 -19
- package/data/harnesses/apollo/skills/design/data/elevation/shadcn-neutral-derived-radius.md +0 -19
- package/data/harnesses/apollo/skills/design/data/elevation/stripe-brand-tinted-dual-shadow.md +0 -18
- package/data/harnesses/apollo/skills/design/data/elevation/tailwind-default-utility-scale.md +0 -19
- package/data/harnesses/apollo/skills/design/data/elevation/vercel-geist-shadow-as-border.md +0 -20
- package/data/harnesses/apollo/skills/design/data/iconography.md +0 -199
- package/data/harnesses/apollo/skills/design/data/motion/accordion-expand.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/destructive-hold-confirm.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/drag-dismiss-momentum.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/empty-state-arrive.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/hover-lift.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/modal-center-arrive.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/number-ticker-roll.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/onboarding-bounce.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/panel-slide.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/press-feedback.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/progress-linear-loop.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/route-crossfade.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/rubber-band-overscroll.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/skeleton-shimmer.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/stagger-arrive.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/toast-enter-stack.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/tooltip-chain-instant.md +0 -18
- package/data/harnesses/apollo/skills/design/data/motion/trigger-anchored-reveal.md +0 -18
- package/data/harnesses/apollo/skills/design/data/tells.csv +0 -34
- package/data/harnesses/apollo/skills/design/data/voices/bright-collaborator.md +0 -29
- package/data/harnesses/apollo/skills/design/data/voices/direct-operator.md +0 -29
- package/data/harnesses/apollo/skills/design/data/voices/earnest-helper.md +0 -29
- package/data/harnesses/apollo/skills/design/data/voices/editorial-composed.md +0 -29
- package/data/harnesses/apollo/skills/design/data/voices/quiet-concierge.md +0 -29
- package/data/harnesses/apollo/skills/design/data/voices/warm-guide.md +0 -29
- package/data/harnesses/apollo/skills/design/references/compose.md +0 -23
- package/data/harnesses/apollo/skills/design/references/content.md +0 -28
- package/data/harnesses/apollo/skills/design/references/emission.md +0 -21
- package/data/harnesses/apollo/skills/design/references/existing-apps.md +0 -27
- package/data/harnesses/apollo/skills/design/references/foundations.md +0 -57
- package/data/harnesses/apollo/skills/design/references/intake.md +0 -40
- package/data/harnesses/apollo/skills/design/references/object-pass.md +0 -24
- package/data/harnesses/apollo/skills/design/references/ship-gate.md +0 -29
- package/data/harnesses/apollo/skills/design/references/ux-patterns/Readme.md +0 -195
- package/data/harnesses/apollo/skills/design/references/ux-patterns/ai-layer.md +0 -49
- package/data/harnesses/apollo/skills/design/references/ux-patterns/attributes-lifecycle.md +0 -43
- package/data/harnesses/apollo/skills/design/references/ux-patterns/container-choice.md +0 -44
- package/data/harnesses/apollo/skills/design/references/ux-patterns/creation-paths.md +0 -46
- package/data/harnesses/apollo/skills/design/references/ux-patterns/dashboards.md +0 -42
- package/data/harnesses/apollo/skills/design/references/ux-patterns/modes.md +0 -42
- package/data/harnesses/apollo/skills/design/references/ux-patterns/object-model.md +0 -46
- package/data/harnesses/apollo/skills/design/references/ux-patterns/page-archetype.md +0 -48
- package/data/harnesses/apollo/skills/design/references/ux-patterns/promotion-demotion.md +0 -37
- package/data/harnesses/apollo/skills/design/references/ux-patterns/settings.md +0 -42
- package/data/harnesses/apollo/skills/design/references/ux-patterns/standard-pages.md +0 -46
- package/data/harnesses/apollo/skills/design/references/ux-patterns/state-matrix.md +0 -41
- package/data/harnesses/apollo/skills/design/references/ux-patterns/table-mechanics.md +0 -48
- package/data/harnesses/apollo/skills/design/references/ux-patterns/verbs.md +0 -45
- package/data/harnesses/apollo/skills/design/references/ux-patterns/viewer-context.md +0 -40
- package/data/harnesses/apollo/skills/design/scripts/README-validator.md +0 -27
- package/data/harnesses/apollo/skills/design/scripts/select-chart.mjs +0 -622
- package/data/harnesses/apollo/skills/design/scripts/validate-design-md.mjs +0 -1198
- package/data/harnesses/apollo/skills/documentation/SKILL.md +0 -135
- package/data/harnesses/apollo/skills/documentation/references/examples.md +0 -279
- package/data/harnesses/apollo/skills/documentation/references/frontmatter.md +0 -44
- package/data/harnesses/apollo/skills/documentation/references/instruction-style.md +0 -50
- package/data/harnesses/apollo/skills/documentation/references/style-guide.md +0 -384
- package/data/harnesses/apollo/skills/documentation/references/untemplated.md +0 -38
- package/data/harnesses/apollo/skills/documentation/scripts/doc-lint.mjs +0 -140
- package/data/harnesses/apollo/skills/documentation/templates/Readme.md +0 -35
- package/data/harnesses/apollo/skills/documentation/templates/api-reference.md +0 -20
- package/data/harnesses/apollo/skills/documentation/templates/architecture-decision.md +0 -121
- package/data/harnesses/apollo/skills/documentation/templates/backlog.md +0 -33
- package/data/harnesses/apollo/skills/documentation/templates/behavioral-checklist.md +0 -81
- package/data/harnesses/apollo/skills/documentation/templates/bookkeeping.md +0 -18
- package/data/harnesses/apollo/skills/documentation/templates/changelog-entry.md +0 -57
- package/data/harnesses/apollo/skills/documentation/templates/changelog-index.md +0 -41
- package/data/harnesses/apollo/skills/documentation/templates/docs-readme.md +0 -72
- package/data/harnesses/apollo/skills/documentation/templates/domain-model.md +0 -30
- package/data/harnesses/apollo/skills/documentation/templates/environment-registry.md +0 -15
- package/data/harnesses/apollo/skills/documentation/templates/feature.md +0 -150
- package/data/harnesses/apollo/skills/documentation/templates/glossary.md +0 -11
- package/data/harnesses/apollo/skills/documentation/templates/implementation-map.md +0 -42
- package/data/harnesses/apollo/skills/documentation/templates/journal.md +0 -13
- package/data/harnesses/apollo/skills/documentation/templates/memory-main.md +0 -25
- package/data/harnesses/apollo/skills/documentation/templates/migration-runbook.md +0 -34
- package/data/harnesses/apollo/skills/documentation/templates/non-goals.md +0 -11
- package/data/harnesses/apollo/skills/documentation/templates/operations-procedure.md +0 -36
- package/data/harnesses/apollo/skills/documentation/templates/plan.md +0 -88
- package/data/harnesses/apollo/skills/documentation/templates/protected-files.md +0 -37
- package/data/harnesses/apollo/skills/documentation/templates/root-readme.md +0 -104
- package/data/harnesses/apollo/skills/documentation/templates/security-overview.md +0 -27
- package/data/harnesses/apollo/skills/documentation/templates/structure.md +0 -65
- package/data/harnesses/apollo/skills/documentation/templates/system-overview.md +0 -32
- package/data/harnesses/apollo/skills/documentation/templates/testing-strategy.md +0 -29
- package/data/harnesses/apollo/skills/schema-design/SKILL.md +0 -141
- package/data/harnesses/apollo/skills/test/SKILL.md +0 -104
- package/data/harnesses/apollo/skills/testing/SKILL.md +0 -166
- package/data/harnesses/apollo/skills/workflow-mapper/SKILL.md +0 -451
- package/data/harnesses/apollo/skills/workflow-mapper/references/patterns.md +0 -214
- /package/data/harnesses/{apollo → code}/docs/README.md +0 -0
- /package/data/harnesses/{apollo → code}/docs/history/CHANGELOG.md +0 -0
- /package/data/harnesses/{apollo → code}/docs/history/backlog.md +0 -0
- /package/data/harnesses/{apollo → code}/docs/memory/main.md +0 -0
- /package/data/harnesses/{apollo → code}/docs/structure.md +0 -0
- /package/data/harnesses/{apollo → code}/rules/cloudflare.md +0 -0
|
@@ -1,384 +0,0 @@
|
|
|
1
|
-
# Documentation Style Guide
|
|
2
|
-
|
|
3
|
-
Writing rules for clear, maintainable documentation.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Function Documentation
|
|
8
|
-
|
|
9
|
-
### Signature Format
|
|
10
|
-
|
|
11
|
-
```markdown
|
|
12
|
-
### `functionName(param1, param2, options)`
|
|
13
|
-
|
|
14
|
-
**Goal:** One-line purpose
|
|
15
|
-
|
|
16
|
-
**Input:**
|
|
17
|
-
|
|
18
|
-
- `param1` (type) - Description
|
|
19
|
-
- `param2` (type, optional) - Description
|
|
20
|
-
|
|
21
|
-
**Output:** `{ field1, field2 }`
|
|
22
|
-
|
|
23
|
-
**Side Effects:** State updates, API calls, etc.
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
### Parameter Rules
|
|
27
|
-
|
|
28
|
-
- Name + type + one-line purpose
|
|
29
|
-
- Mark optional params with `(type, optional)`
|
|
30
|
-
- Nest object properties:
|
|
31
|
-
```markdown
|
|
32
|
-
- `options` (object) - Configuration
|
|
33
|
-
- `options.retry` (boolean) - Enable retries
|
|
34
|
-
- `options.timeout` (number) - Timeout in ms
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
### Return Values
|
|
38
|
-
|
|
39
|
-
Always specify:
|
|
40
|
-
|
|
41
|
-
- Type: `Array<Object>`, `boolean`, `{ merged, changes }`
|
|
42
|
-
- Shape for objects/arrays
|
|
43
|
-
- Meaning: "True if sync successful"
|
|
44
|
-
|
|
45
|
-
---
|
|
46
|
-
|
|
47
|
-
## State Documentation
|
|
48
|
-
|
|
49
|
-
### When to Document State
|
|
50
|
-
|
|
51
|
-
✅ Do:
|
|
52
|
-
|
|
53
|
-
- Redux persistence (localStorage, IndexedDB)
|
|
54
|
-
- Database schemas
|
|
55
|
-
- API request/response shapes
|
|
56
|
-
|
|
57
|
-
❌ Don't:
|
|
58
|
-
|
|
59
|
-
- Component-level state
|
|
60
|
-
- Derived/computed state
|
|
61
|
-
- Temporary UI state
|
|
62
|
-
|
|
63
|
-
### Format
|
|
64
|
-
|
|
65
|
-
````markdown
|
|
66
|
-
**Frontend (at persistence):**
|
|
67
|
-
|
|
68
|
-
```json
|
|
69
|
-
{
|
|
70
|
-
"activeField": "value"
|
|
71
|
-
// "deprecated": null // UNUSED: dead key; kept so old persisted state rehydrates
|
|
72
|
-
}
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
**Storage:** localStorage key `state_key`
|
|
76
|
-
|
|
77
|
-
**Backend:**
|
|
78
|
-
|
|
79
|
-
```ts
|
|
80
|
-
export const table = pgTable('table', {
|
|
81
|
-
id: text('id').primaryKey(),
|
|
82
|
-
data: jsonb('data'),
|
|
83
|
-
// old: text('old'), // UNUSED: dead column; nothing reads it
|
|
84
|
-
});
|
|
85
|
-
```
|
|
86
|
-
````
|
|
87
|
-
|
|
88
|
-
### Mark Unused Keys
|
|
89
|
-
|
|
90
|
-
Always comment deprecated/unused fields. The annotation states why the field is dead _now_ — never where it went, what replaced it, or when it will be removed (no "Remove in v3", no "Migrated to newField"; that is history narration, § The Two Natures below):
|
|
91
|
-
|
|
92
|
-
```json
|
|
93
|
-
{
|
|
94
|
-
"active": [],
|
|
95
|
-
// "legacy": {} // UNUSED: dead key; kept for rehydrate compatibility
|
|
96
|
-
}
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
---
|
|
100
|
-
|
|
101
|
-
## ASCII Diagrams
|
|
102
|
-
|
|
103
|
-
### When to Use
|
|
104
|
-
|
|
105
|
-
- Data flows
|
|
106
|
-
- System architecture
|
|
107
|
-
- Component interactions
|
|
108
|
-
- Process flows
|
|
109
|
-
|
|
110
|
-
**Docs only.** Diagrams belong in documents read on demand (feature docs, ADs, operations). Instruction files — `CLAUDE.md`, rules, agent definitions, `SKILL.md` prose — never carry them: they load on every turn or every invocation, and a table or a sentence carries the same information at a fraction of the tokens.
|
|
111
|
-
|
|
112
|
-
### Pattern
|
|
113
|
-
|
|
114
|
-
```
|
|
115
|
-
┌─────────────────────────────────────────┐
|
|
116
|
-
│ TITLE │
|
|
117
|
-
├─────────────────────────────────────────┤
|
|
118
|
-
│ │
|
|
119
|
-
│ ┌──────┐ ┌──────┐ ┌──────┐ │
|
|
120
|
-
│ │ A │────▶│ B │────▶│ C │ │
|
|
121
|
-
│ └──────┘ └──────┘ └──────┘ │
|
|
122
|
-
│ │ │ │
|
|
123
|
-
│ ▼ ▼ │
|
|
124
|
-
│ Detail Detail │
|
|
125
|
-
│ │
|
|
126
|
-
└─────────────────────────────────────────┘
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
### Characters
|
|
130
|
-
|
|
131
|
-
- Boxes: `┌─┐│└┘├┤┬┴┼`
|
|
132
|
-
- Arrows: `───▶` `◀───` `│▼` `│▲`
|
|
133
|
-
- Width: ~70 chars max
|
|
134
|
-
|
|
135
|
-
### UI Wireframes
|
|
136
|
-
|
|
137
|
-
For screen layouts (not data flows), use these conventions:
|
|
138
|
-
|
|
139
|
-
```
|
|
140
|
-
**Route:** `path/:id`
|
|
141
|
-
**Tab:** Tab Name
|
|
142
|
-
|
|
143
|
-
┌────────────────────────────────────┐
|
|
144
|
-
│ Title [i]3 [Button]│
|
|
145
|
-
│ [i]Label [Tag1][Tag2][+Add] │
|
|
146
|
-
└────────────────────────────────────┘
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
- `[text]` = clickable button/badge
|
|
150
|
-
- `[i]` = icon (followed by label or count)
|
|
151
|
-
- `v` / `^` = expand/collapse indicator
|
|
152
|
-
- Show each UI state (collapsed/expanded) as separate diagrams
|
|
153
|
-
- Include Route/Tab context above wireframe
|
|
154
|
-
|
|
155
|
-
---
|
|
156
|
-
|
|
157
|
-
## Mermaid Diagrams
|
|
158
|
-
|
|
159
|
-
**Structure at rest is ASCII; behaviour over time is mermaid.** A file tree, an on-disk layout, a load-class split, a wireframe — draw with box characters, because the diagram *is* the thing's shape. A sequence of turns, a state machine, a branching flow — write mermaid, because a renderer tracks the arrows better than a reader tracks them across box art, and the source stays diffable when a step is inserted.
|
|
160
|
-
|
|
161
|
-
**Docs only**, on the same reasoning as ASCII: a diagram never enters an instruction file.
|
|
162
|
-
|
|
163
|
-
### When to Use
|
|
164
|
-
|
|
165
|
-
| Diagram | Use for |
|
|
166
|
-
| --- | --- |
|
|
167
|
-
| `sequenceDiagram` | Who calls whom in what order — a session turn, a hand-off between components |
|
|
168
|
-
| `stateDiagram-v2` | Modes with transitions — a workflow, a record's lifecycle |
|
|
169
|
-
| `flowchart` | A process with branches, gates, or fan-out |
|
|
170
|
-
| `timeline` | A dated lineage, in records only — never in a truth document |
|
|
171
|
-
|
|
172
|
-
### Rules
|
|
173
|
-
|
|
174
|
-
- **At most 7 participants and 15 interactions** per diagram. Past that, split it — an unreadable diagram is worse than the prose it replaced.
|
|
175
|
-
- **Labels under 8 words**, no trailing punctuation.
|
|
176
|
-
- **Declare a direction** on every flowchart (`flowchart TD` / `LR`) so the render is stable.
|
|
177
|
-
- **The diagram never carries a fact the prose omits.** It restates structure for a reader who scans; a reader who greps must still find everything in the text.
|
|
178
|
-
- **No styling directives** — no `style`, no `classDef`, no theme overrides. Rendering is the reader's; the source stays portable across GitHub, Obsidian, and a plain editor.
|
|
179
|
-
|
|
180
|
-
```
|
|
181
|
-
flowchart LR
|
|
182
|
-
A[Plan approved] --> B{boundary}
|
|
183
|
-
B -->|BLOCK| C[Re-plan]
|
|
184
|
-
B -->|PASS| D[testing plan-gate]
|
|
185
|
-
D --> E[Implement]
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
---
|
|
189
|
-
|
|
190
|
-
## Code Examples
|
|
191
|
-
|
|
192
|
-
### Rules
|
|
193
|
-
|
|
194
|
-
- Under 15 lines
|
|
195
|
-
- Show contracts, not implementations
|
|
196
|
-
- Use pseudocode for algorithms
|
|
197
|
-
|
|
198
|
-
✅ Good:
|
|
199
|
-
|
|
200
|
-
```javascript
|
|
201
|
-
// Critical: Balanced brace matching
|
|
202
|
-
function extract(json) {
|
|
203
|
-
// Track brace depth
|
|
204
|
-
// Ignore braces inside strings
|
|
205
|
-
// Return complete objects only
|
|
206
|
-
}
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
❌ Bad: Full 50-line implementation
|
|
210
|
-
|
|
211
|
-
(Worked example: [`examples.md`](examples.md) Example 1.)
|
|
212
|
-
|
|
213
|
-
---
|
|
214
|
-
|
|
215
|
-
## Writing Style
|
|
216
|
-
|
|
217
|
-
### Voice
|
|
218
|
-
|
|
219
|
-
Use imperative/active:
|
|
220
|
-
|
|
221
|
-
- ✅ "Fetches data from server"
|
|
222
|
-
- ✅ "Returns array of objects"
|
|
223
|
-
- ❌ "This function is used to fetch"
|
|
224
|
-
- ❌ "An array is returned"
|
|
225
|
-
|
|
226
|
-
### When Prose Adds Value
|
|
227
|
-
|
|
228
|
-
Prose is valuable for context that contracts can't capture:
|
|
229
|
-
|
|
230
|
-
| Use Prose For | Example |
|
|
231
|
-
| --- | --- |
|
|
232
|
-
| Section intros | "When the editor mounts, `useAppInit` is called with the `appId` from URL." |
|
|
233
|
-
| Non-obvious behavior | "The hook always fetches fresh data. There is no caching or version checking." |
|
|
234
|
-
| Design rationale | "Why parallel fetches? Each entity type is independent, reducing load time." |
|
|
235
|
-
| Edge cases | "If created then deleted before save, it's removed from `added[]` without adding to `removed[]`." |
|
|
236
|
-
| Limitations, stated as facts | "`useAppInit` is standalone — nothing in the mount path calls it." |
|
|
237
|
-
| Usage context | "Used to show 'Unsaved' badge, warn before navigation, enable save buttons." |
|
|
238
|
-
|
|
239
|
-
### When to Avoid Prose
|
|
240
|
-
|
|
241
|
-
- Describing WHAT code does (use signatures instead)
|
|
242
|
-
- Step-by-step flows (use diagrams instead)
|
|
243
|
-
- Structured comparisons (use tables instead)
|
|
244
|
-
|
|
245
|
-
### Conciseness
|
|
246
|
-
|
|
247
|
-
One line when possible:
|
|
248
|
-
|
|
249
|
-
- ✅ "Merge server data with local changes using version-based conflict resolution"
|
|
250
|
-
- ❌ "This function takes the data from the server and also takes the local data..."
|
|
251
|
-
|
|
252
|
-
### Tables
|
|
253
|
-
|
|
254
|
-
Use for structured info:
|
|
255
|
-
|
|
256
|
-
```markdown
|
|
257
|
-
| Parameter | Type | Description |
|
|
258
|
-
| --------- | ------ | -------------- |
|
|
259
|
-
| `data` | object | Fresh from API |
|
|
260
|
-
| `local` | object | Current state |
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
---
|
|
264
|
-
|
|
265
|
-
## Self-Contained Documents & References
|
|
266
|
-
|
|
267
|
-
Two verbosity regimes, split by who pays for the words. **Instruction files** (`CLAUDE.md`, rules, agents, skill prose) load into an agent's context on every turn or invocation — they stay lean, per [`instruction-style.md`](instruction-style.md). **Documents** are read on demand, by humans and agents alike — they are written **verbose and self-contained**, and the cost of a reader hopping files exceeds the cost of extra words on the page.
|
|
268
|
-
|
|
269
|
-
- **The body reads whole without opening another file.** Restate the one or two sentences of context a borrowed concept needs, right where it's used — a reader forced mid-paragraph into a second document loses the thread of the first.
|
|
270
|
-
- **Restate for readability, cite for authority — never fork the fact.** A changing detail (a version, a count, a path list) keeps one canonical home; the restatement carries what the page needs to be understood and points at the authority for the rest. Link-don't-copy governs where a fact is *owned*, not how readable the page that uses it must be.
|
|
271
|
-
- **Inline links are the minimum that action requires.** Link mid-prose only where the reader must go there to act on this page. Every other sister document — everything the topic touches — belongs in one **Related** (or **References**) section at the document's end.
|
|
272
|
-
- **The Related tail is the document's entire link surface.** Deep relative paths (`../../../../…`) are fragile — a folder move breaks every one — so they are confined to that one block, where a path change touches one place; body mentions use the plain name (`the boundary skill`, `structure.md`) instead of a link.
|
|
273
|
-
|
|
274
|
-
---
|
|
275
|
-
|
|
276
|
-
## The Two Natures — Tense & History
|
|
277
|
-
|
|
278
|
-
Every document is a **truth document** (states current absolutes, updated in place) or a **record** (dated account of activity, frozen or append-only) — see `SKILL.md` § The Two Natures. The tense rules follow directly:
|
|
279
|
-
|
|
280
|
-
**Truth documents describe the present, not the past.** Everything outside `docs/history/` states what the system _is_ and how it works _today_. It must not narrate how it got there. The journey — the dates, the migrations — lives **only** in records (`docs/history/`: changelog, plans, migrations). Three sanctioned exceptions: `docs/memory/` is the agent's own dated ledger; an AD's **Decision Changelog** tail carries that decision's dated revision history; and `docs/structure.md`'s **Health Log** tail carries the maintenance agent's tooling-stamped audit rows. In both tail bridges the body stays current-truth-only — head is truth, tail is provenance.
|
|
281
|
-
|
|
282
|
-
**Records are never edited to match the present.** A frozen plan stays wrong-in-hindsight; a changelog entry describes what shipped as it shipped. A scope change gets a new dated record that links back.
|
|
283
|
-
|
|
284
|
-
Strip this language from truth documents:
|
|
285
|
-
|
|
286
|
-
| ❌ Historical narration (belongs in a record) | ✅ Present-tense fact (belongs in the truth doc) |
|
|
287
|
-
| --- | --- |
|
|
288
|
-
| "Folded in from the `NuStack-X` repo (2026-06-12)." | "Vendor-connector catalogue; one subpath per vendor." |
|
|
289
|
-
| "Built 2026-06-14; shipped + verified 2026-06-13." | "`agentSessionWorkflow` runs an outer turn loop over `runAgentLoop`." |
|
|
290
|
-
| "The legacy worker was deleted in the 2026-06-14 fold." | "One worker interprets `WorkflowDefinition`." |
|
|
291
|
-
| "ex-`@nurix/mcp-runtime`, M9 Phase C; was X, now Y." | "MCP client runtime, wired into `agentTriggerWorkflow`." |
|
|
292
|
-
| "Build Sequence phases 0–4 are complete." | Nothing — progress lives in the plan/backlog record; the doc describes what exists |
|
|
293
|
-
| "There is no standalone `skills/components/` — treat any reference to it as stale." | Nothing — delete or repoint the stale references; state only the present design |
|
|
294
|
-
| "Read first: `docs/history/plans/2026-…-fold.md`" (routing) | "Read first: `docs/architecture/<current-truth-doc>.md`" |
|
|
295
|
-
|
|
296
|
-
Rules:
|
|
297
|
-
|
|
298
|
-
- **No dates and no progress narration in truth documents.** Nothing about _when_ something shipped, was verified, folded, or was removed — and no completion markers either: no "phases 0–4 are complete", no per-item `✅ shipped` / `⏳ pending`. Progress tracking is a **record's** job (the plan, the backlog); a truth document describes what exists, as if it had always been so.
|
|
299
|
-
- **No stale-reference tripwires.** Never write "X is gone — treat references to X as stale"; that is a redirect doc compressed into one sentence. Delete or repoint every stale reference instead (same rule as the **No redirect docs** rule in `SKILL.md` § The Two Natures) and state only the present fact.
|
|
300
|
-
- **No version or phase framing.** A bare `v1`/`v2` as a label, "Phase 1/2", "the old X", "supersedes the earlier" — there is one design; describe it without its predecessors. (A version naming an external present-tense fact stays: a schema literal like `design-tokens/v2`, a dependency pin like `@0.14.0`.)
|
|
301
|
-
- **Temporal hedges are progress markers in prose.** "currently", "not yet", "still", "for now" smuggle a ⏳ into a truth document — state the fact without the hedge ("the hook is standalone; nothing in the mount path calls it") and let the backlog record carry the intention.
|
|
302
|
-
- **A published artifact's own version surface is external fact.** Release notes and upgrade guides for a shipped package may use version framing (`v1 → v2`) — that is the artifact's public contract, not the doc narrating its own past. They live beside the artifact or under `docs/operations/`, never in `docs/features/` or `docs/architecture/`.
|
|
303
|
-
- **Cite the AD for the _why_, never the _when_.** `Provenance: AD-002` is good (it points to the decision rationale). "Decided in AD-002 and shipped 2026-06-13" is not.
|
|
304
|
-
- **Routing/index docs point only to truth documents as a topic's authority.** A row whose "read first" target for a topic is a historical plan or changelog is a redirect-for-history — repoint it to the current truth doc, or drop the row. (An index _of the records themselves_ — a History section listing `plans/`, `changelog/` — is sanctioned: that indexes records, it doesn't route a topic.)
|
|
305
|
-
- **When a doc changes because the system changed, the change-story goes in `docs/history/` (a changelog entry), and the truth document simply becomes correct in present tense.** Never leave the diff narrated in place.
|
|
306
|
-
- **A decision that moves is an edit, not a new document.** Rewrite the AD's affected sections to the new truth and append the revision to its Decision Changelog — never mint a parallel doc and never leave the old choice narrated in the body.
|
|
307
|
-
|
|
308
|
-
Worked example of the strip-and-relocate move: [`examples.md`](examples.md) Example 6.
|
|
309
|
-
|
|
310
|
-
---
|
|
311
|
-
|
|
312
|
-
## Mechanics
|
|
313
|
-
|
|
314
|
-
- Inline-code every identifier, filename, command, and config key.
|
|
315
|
-
- Bullet rules take the form "**bold assertion** — explanation."
|
|
316
|
-
|
|
317
|
-
---
|
|
318
|
-
|
|
319
|
-
## Structure
|
|
320
|
-
|
|
321
|
-
### Headers
|
|
322
|
-
|
|
323
|
-
```markdown
|
|
324
|
-
# Document Title (H1 - once)
|
|
325
|
-
|
|
326
|
-
## Major Section (H2)
|
|
327
|
-
|
|
328
|
-
### Subsection (H3)
|
|
329
|
-
|
|
330
|
-
#### Detail (H4 - sparingly)
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
**Headings are retrieval keys.** Search and agents retrieve sections out of context, and a bare `## State` reads identically across every feature doc. In long docs, qualify generic headings with the feature name — `## State — invoice-pdf`, `### Merge rules — data sync` — so a section stands alone when retrieved. Short docs whose H1 disambiguates can keep bare headings.
|
|
334
|
-
|
|
335
|
-
### Standard Layout
|
|
336
|
-
|
|
337
|
-
```markdown
|
|
338
|
-
# [Title]
|
|
339
|
-
|
|
340
|
-
**Goal:** One-line purpose
|
|
341
|
-
|
|
342
|
-
## Architecture
|
|
343
|
-
|
|
344
|
-
[Diagram + explanation]
|
|
345
|
-
|
|
346
|
-
## Key Functions
|
|
347
|
-
|
|
348
|
-
[Signatures and contracts]
|
|
349
|
-
|
|
350
|
-
## State
|
|
351
|
-
|
|
352
|
-
[Persistence shapes]
|
|
353
|
-
|
|
354
|
-
## Files
|
|
355
|
-
|
|
356
|
-
[Source file list]
|
|
357
|
-
```
|
|
358
|
-
|
|
359
|
-
### File References
|
|
360
|
-
|
|
361
|
-
Always end with:
|
|
362
|
-
|
|
363
|
-
```markdown
|
|
364
|
-
## Files
|
|
365
|
-
|
|
366
|
-
- `src/path/main.js` - Core logic
|
|
367
|
-
- `src/path/hooks.js` - React hooks
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
---
|
|
371
|
-
|
|
372
|
-
## Summary
|
|
373
|
-
|
|
374
|
-
| Aspect | Rule |
|
|
375
|
-
| ---------- | ------------------------------- |
|
|
376
|
-
| Functions | Always include signatures |
|
|
377
|
-
| Parameters | Type + purpose |
|
|
378
|
-
| Returns | Type + shape |
|
|
379
|
-
| State | Persistence points only |
|
|
380
|
-
| Diagrams | ASCII for structure at rest, mermaid for behaviour over time — docs only, never instruction files |
|
|
381
|
-
| Code | Under 15 lines, contracts only |
|
|
382
|
-
| Voice | Imperative/active |
|
|
383
|
-
| Mechanics | Inline-code identifiers; bold-assertion bullets |
|
|
384
|
-
| Length | Concise, one line when possible |
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# Writing an Untemplated Document
|
|
2
|
-
|
|
3
|
-
Load when: no template in [`templates/`](../templates/Readme.md) matches the document being written — a design note, a comparison, an investigation writeup, an index, a reference sheet, anything the Routing table sends to "no template matches".
|
|
4
|
-
|
|
5
|
-
A template is a pre-made set of shape decisions. With no template, make the same decisions explicitly, in this order.
|
|
6
|
-
|
|
7
|
-
## 1. Decide the nature — truth or record
|
|
8
|
-
|
|
9
|
-
Every document is exactly one (`SKILL.md` § The Two Natures). Ask: *when reality changes, is this file rewritten, or is it frozen?*
|
|
10
|
-
|
|
11
|
-
- Rewritten in place → **truth document**. Topic-named (`kebab-case.md`), lives outside `docs/history/`, present tense throughout — the iron rule in `SKILL.md` § Present tense, always.
|
|
12
|
-
- Frozen or append-only → **record**. Date-named (`YYYY-MM-DD-slug.md`), lives in `docs/history/` — inside an existing subfolder where it fits (an investigation or research writeup → `history/research/{topic}/`); a genuinely new category of record needs a `docs/structure.md` folder-rule row in the same change, never an invented folder.
|
|
13
|
-
|
|
14
|
-
When a draft wants to be both — the current state *and* the story of getting there — split it: the state becomes a truth document, the story becomes a record that links to it. Never mix the natures in one body.
|
|
15
|
-
|
|
16
|
-
## 2. Place and name it
|
|
17
|
-
|
|
18
|
-
- `docs/structure.md` is the placement authority — match the document's topic to its folder map before inventing a location.
|
|
19
|
-
- **One canonical home per topic.** If a document on the topic already exists, extend it; a second document on the same topic is drift waiting to happen. Link, don't copy.
|
|
20
|
-
- A new topic *folder* gets a `Readme.md` landing page that introduces and indexes it.
|
|
21
|
-
|
|
22
|
-
## 3. Shape it
|
|
23
|
-
|
|
24
|
-
- **Open with the goal.** The first line under the H1 states what the document is for and who reads it — a reader (or agent) landing here cold decides in one sentence whether to keep reading.
|
|
25
|
-
- **Headings are retrieval keys.** Sections get pulled out of context by search and agents; qualify generic headings with the topic (`## Merge rules — data sync`, not `## Rules`) so each stands alone.
|
|
26
|
-
- **Tables for enumerable facts, prose for judgment.** One row per item; anything needing a *because* lives in prose around the table, never inside a cell.
|
|
27
|
-
- **Every section earns its place.** No empty stubs — omit what has nothing real to say; write an explicit "None" only where the absence itself is information.
|
|
28
|
-
- **Cite sources and link neighbours.** If the document mentions a concept another document owns, link it; if it draws on code, name the files.
|
|
29
|
-
|
|
30
|
-
## 4. Write it in the house style
|
|
31
|
-
|
|
32
|
-
`references/style-guide.md` carries the rules: present tense with no history narration, progress markers, or stale-reference tripwires (§ The Two Natures); imperative/active voice; code examples under 15 lines showing contracts, not implementations; ASCII diagrams in docs only; inline-code every identifier, filename, command, and config key.
|
|
33
|
-
|
|
34
|
-
## 5. With a human in the loop — the co-authoring workflow
|
|
35
|
-
|
|
36
|
-
**Stage 1 — context gathering.** Ask: audience? purpose? existing format to match? Have the user dump all the context they hold, then ask 5–10 clarifying questions before proposing anything.
|
|
37
|
-
|
|
38
|
-
**Stage 2 — structure & draft.** Propose the section structure from §1–3 above, then draft section by section. The user indicates changes — learn their style from their edits; don't silently rewrite them.
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
// skills/documentation/scripts/doc-lint.mjs - mechanical checks over markdown docs (tense narration, dates, stubs, redirects)
|
|
2
|
-
// Usage: node doc-lint.mjs <file.md ...> | node doc-lint.mjs --changed (git-changed + untracked .md)
|
|
3
|
-
// Exit 1 when any block-severity finding survives. Escape hatch: <!-- doc-lint-disable: id[, id] --> (file-wide, or on the offending line).
|
|
4
|
-
|
|
5
|
-
import { readFileSync, existsSync, statSync, readdirSync } from 'node:fs';
|
|
6
|
-
import { execSync } from 'node:child_process';
|
|
7
|
-
|
|
8
|
-
const RULES = [
|
|
9
|
-
{ id: 'stale-tripwire', severity: 'block', scope: 'truth', pattern: /treat (any )?[\w`./-]+ ?(references? )?as stale|superseded (by|the)|\bused to (be|target|live|hold)\b/i, message: 'stale-reference tripwire / supersession talk — fix the references, state the present fact' },
|
|
10
|
-
{ id: 'history-narration', severity: 'block', scope: 'truth', pattern: /\bno longer\b|\bwas (renamed|removed|extracted|folded|migrated|replaced)\b|\bmoved (to|from|into) [\w`./-]+ \(?20\d{2}/i, message: 'history narration — the journey belongs in a dated record' },
|
|
11
|
-
{ id: 'progress-marker', severity: 'block', scope: 'truth', pattern: /\bphases?\s+\d[^.\n]{0,40}\b(complete|done)\b|\b(build|implementation) (is )?(\d+%|partially) (complete|done)\b/i, message: 'progress marker — progress lives in the plan/backlog record' },
|
|
12
|
-
{ id: 'temporal-hedge', severity: 'warn', scope: 'truth', pattern: /\bnot yet\b|\bfor now\b|\bcurrently\b|\bstill (unsupported|missing|pending|unimplemented|in progress)\b/i, message: 'temporal hedge — state the fact without "currently / not yet / for now"' },
|
|
13
|
-
// "previously-fetched" is a hyphenated adjective naming a thing, not a predecessor design — don't fire on it.
|
|
14
|
-
{ id: 'predecessor-frame', severity: 'warn', scope: 'truth', pattern: /\bpreviously\b(?!-)|\bthe old \w+\b|\blegacy \w+ (was|is)\b/i, message: 'predecessor framing — describe the one current design' },
|
|
15
|
-
// docs/tests/ behavioral checklists use `- [ ]` as test-step notation (step → **Assert**) and docs/operations/
|
|
16
|
-
// procedures use it for operator verification steps — neither is progress tracking. Every other truth doc still bans checkboxes.
|
|
17
|
-
{ id: 'status-glyph', severity: 'warn', scope: 'truth', exempt: /(^|\/)docs\/(tests|operations)\//, pattern: /(^|\s)(✅|⏳|- \[[ x]\])/u, message: 'status glyph / checklist in a truth doc — tracking belongs in a record' },
|
|
18
|
-
// Truth docs are supposed to cite records, and record filenames are dated — so a date inside a link
|
|
19
|
-
// target or a code span is a path, not narration. Strip those before matching.
|
|
20
|
-
{ id: 'date-in-truth-doc', severity: 'warn', scope: 'truth', strip: /\[[^\]]*\]\([^)]*\)|`[^`]*`/g, pattern: /\b20\d{2}-\d{2}-\d{2}\b/, message: 'date in a truth doc — only the AD Decision Changelog and structure.md Health Log tails carry dates' },
|
|
21
|
-
];
|
|
22
|
-
|
|
23
|
-
// Sections inside a truth doc where dated history is sanctioned (the two bridges).
|
|
24
|
-
const BRIDGE_HEADINGS = /^#{1,4}\s+(decision changelog|health log)\b/i;
|
|
25
|
-
// Instruction files and generated trees are a different genre — out of this linter's scope.
|
|
26
|
-
const SKIP = /(^|\/)(\.claude|node_modules|skills|rules|agents|harness|packages\/[^/]+\/data)\/|(^|\/)(CLAUDE|AGENTS)\.md$/;
|
|
27
|
-
const RECORD = /(^|\/)docs\/(history|research|memory)\//;
|
|
28
|
-
|
|
29
|
-
// Classify a path: skipped genre, record, or truth.
|
|
30
|
-
function scopeOf(path) {
|
|
31
|
-
if (SKIP.test(path)) return 'skip';
|
|
32
|
-
return RECORD.test(path) ? 'record' : 'truth';
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Yield prose lines only: frontmatter, fenced code blocks, and bridge sections drop out.
|
|
36
|
-
function proseLines(text) {
|
|
37
|
-
const lines = text.split('\n');
|
|
38
|
-
const out = [];
|
|
39
|
-
let inFence = false;
|
|
40
|
-
let inFrontmatter = lines[0] === '---';
|
|
41
|
-
let inBridge = false;
|
|
42
|
-
let bridgeLevel = 0;
|
|
43
|
-
for (let i = inFrontmatter ? 1 : 0; i < lines.length; i++) {
|
|
44
|
-
const line = lines[i];
|
|
45
|
-
if (inFrontmatter) { if (line === '---') inFrontmatter = false; continue; }
|
|
46
|
-
if (/^\s*(```|~~~|````)/.test(line)) { inFence = !inFence; continue; }
|
|
47
|
-
if (inFence) continue;
|
|
48
|
-
const heading = line.match(/^(#{1,4})\s/);
|
|
49
|
-
if (heading) {
|
|
50
|
-
if (inBridge && heading[1].length <= bridgeLevel) inBridge = false;
|
|
51
|
-
if (BRIDGE_HEADINGS.test(line)) { inBridge = true; bridgeLevel = heading[1].length; }
|
|
52
|
-
}
|
|
53
|
-
if (!inBridge) out.push({ n: i + 1, line });
|
|
54
|
-
}
|
|
55
|
-
return out;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Collect file-wide disabled rule ids from <!-- doc-lint-disable: a, b --> comments.
|
|
59
|
-
function fileDisables(text) {
|
|
60
|
-
const ids = new Set();
|
|
61
|
-
for (const m of text.matchAll(/<!--\s*doc-lint-disable:\s*([\w-,\s]+?)\s*-->/g))
|
|
62
|
-
m[1].split(',').forEach((id) => ids.add(id.trim()));
|
|
63
|
-
return ids;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function lintFile(path, findings) {
|
|
67
|
-
const scope = scopeOf(path);
|
|
68
|
-
if (scope === 'skip' || !existsSync(path)) return;
|
|
69
|
-
const text = readFileSync(path, 'utf8');
|
|
70
|
-
const disabled = fileDisables(text);
|
|
71
|
-
const lines = proseLines(text);
|
|
72
|
-
|
|
73
|
-
const nonEmpty = text.split('\n').filter((l) => l.trim()).length;
|
|
74
|
-
if (scope === 'truth' && nonEmpty <= 10 && /\b(moved to|relocated to|see [\w`./-]+ instead)\b/i.test(text) && !disabled.has('redirect-doc'))
|
|
75
|
-
findings.push({ path, n: 1, severity: 'block', id: 'redirect-doc', message: 'redirect stub — delete the file and repoint every inbound link' });
|
|
76
|
-
|
|
77
|
-
for (const rule of RULES) {
|
|
78
|
-
if (rule.scope !== scope || disabled.has(rule.id)) continue;
|
|
79
|
-
if (rule.exempt && rule.exempt.test(path)) continue;
|
|
80
|
-
for (const { n, line } of lines) {
|
|
81
|
-
const subject = rule.strip ? line.replace(rule.strip, '') : line;
|
|
82
|
-
if (!rule.pattern.test(subject)) continue;
|
|
83
|
-
if (line.includes(`doc-lint-disable: ${rule.id}`) || new RegExp(`doc-lint-disable:[^>]*\\b${rule.id}\\b`).test(line)) continue;
|
|
84
|
-
findings.push({ path, n, severity: rule.severity, id: rule.id, message: rule.message, excerpt: line.trim().slice(0, 90) });
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// A folder index (Readme.md/README.md) is a browse page, not a feature doc — it owns no code.
|
|
89
|
-
const isFolderIndex = /(^|\/)(readme)\.md$/i.test(path);
|
|
90
|
-
if (scope === 'truth' && !isFolderIndex && /(^|\/)docs\/features\/[^/]+\.md$/.test(path)) {
|
|
91
|
-
const fm = text.startsWith('---') ? text.slice(0, text.indexOf('\n---', 3)) : '';
|
|
92
|
-
for (const key of ['owns:', 'keywords:', 'status:', 'type:'])
|
|
93
|
-
if (!fm.includes(key)) findings.push({ path, n: 1, severity: 'block', id: 'feature-frontmatter', message: `feature doc missing \`${key}\` frontmatter` });
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// A changed plan whose committed version is already frozen must not be edited.
|
|
98
|
-
function checkFrozenEdits(paths, findings) {
|
|
99
|
-
for (const path of paths) {
|
|
100
|
-
if (!/(^|\/)docs\/history\/(plans|changelog|migrations)\//.test(path)) continue;
|
|
101
|
-
try {
|
|
102
|
-
const head = execSync(`git show HEAD:"${path}"`, { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] });
|
|
103
|
-
if (/(^|\/)plans\//.test(path) && !/Status:\s*(Complete|Abandoned)/i.test(head)) continue;
|
|
104
|
-
findings.push({ path, n: 1, severity: 'block', id: 'frozen-record-edit', message: 'frozen record modified — records are never edited; write a new dated record that links back' });
|
|
105
|
-
} catch { /* new file — creating a record is fine */ }
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const args = process.argv.slice(2);
|
|
110
|
-
let files = args.filter((a) => a !== '--changed');
|
|
111
|
-
const changedMode = args.includes('--changed');
|
|
112
|
-
if (changedMode) {
|
|
113
|
-
const out = execSync('git diff --name-only HEAD -- "*.md"; git ls-files --others --exclude-standard -- "*.md"', { encoding: 'utf8', shell: '/bin/bash' });
|
|
114
|
-
files = [...new Set([...files, ...out.split('\n').filter(Boolean)])];
|
|
115
|
-
}
|
|
116
|
-
// Expand any directory argument into the .md files beneath it, so `doc-lint.mjs docs/` works.
|
|
117
|
-
function expandDirs(paths) {
|
|
118
|
-
const out = [];
|
|
119
|
-
for (const p of paths) {
|
|
120
|
-
if (!existsSync(p)) { out.push(p); continue; }
|
|
121
|
-
if (!statSync(p).isDirectory()) { out.push(p); continue; }
|
|
122
|
-
for (const e of readdirSync(p, { withFileTypes: true })) {
|
|
123
|
-
if (e.name === 'node_modules' || e.name.startsWith('.')) continue;
|
|
124
|
-
out.push(...expandDirs([`${p.replace(/\/$/, '')}/${e.name}`]));
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
return out;
|
|
128
|
-
}
|
|
129
|
-
files = expandDirs(files).filter((f) => f.endsWith('.md'));
|
|
130
|
-
if (!files.length) { console.error('usage: node doc-lint.mjs <file.md | dir ...> | --changed'); process.exit(2); }
|
|
131
|
-
|
|
132
|
-
const findings = [];
|
|
133
|
-
files.forEach((f) => lintFile(f, findings));
|
|
134
|
-
if (changedMode) checkFrozenEdits(files.filter((f) => existsSync(f)), findings);
|
|
135
|
-
|
|
136
|
-
for (const f of findings.sort((a, b) => (a.severity === b.severity ? 0 : a.severity === 'block' ? -1 : 1)))
|
|
137
|
-
console.log(`${f.path}:${f.n} [${f.severity}] ${f.id} — ${f.message}${f.excerpt ? `: "${f.excerpt}"` : ''}`);
|
|
138
|
-
const blocks = findings.filter((f) => f.severity === 'block').length;
|
|
139
|
-
console.log(`\n${findings.length} finding(s), ${blocks} blocking, ${files.length} file(s) checked.`);
|
|
140
|
-
process.exit(blocks ? 1 : 0);
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# Documentation Templates
|
|
2
|
-
|
|
3
|
-
One file per template. Every template is either a **truth document** (states current absolutes, updated in place) or a **record** (dated account of activity, frozen or append-only) — the split is defined in `SKILL.md` § The Two Natures, and each template names its nature in its opening line.
|
|
4
|
-
|
|
5
|
-
| Template | File | Nature |
|
|
6
|
-
| --- | --- | --- |
|
|
7
|
-
| Feature (LLD) | [feature.md](feature.md) | Truth |
|
|
8
|
-
| Architecture Decision (AD) | [architecture-decision.md](architecture-decision.md) | Truth (Decision Changelog tail sanctioned) |
|
|
9
|
-
| System overview | [system-overview.md](system-overview.md) | Truth |
|
|
10
|
-
| Domain model | [domain-model.md](domain-model.md) | Truth |
|
|
11
|
-
| Glossary | [glossary.md](glossary.md) | Truth |
|
|
12
|
-
| Non-goals | [non-goals.md](non-goals.md) | Truth |
|
|
13
|
-
| API reference | [api-reference.md](api-reference.md) | Truth |
|
|
14
|
-
| Environment registry | [environment-registry.md](environment-registry.md) | Truth |
|
|
15
|
-
| Security overview | [security-overview.md](security-overview.md) | Truth |
|
|
16
|
-
| Testing strategy | [testing-strategy.md](testing-strategy.md) | Truth |
|
|
17
|
-
| Behavioral checklist | [behavioral-checklist.md](behavioral-checklist.md) | Truth |
|
|
18
|
-
| Operations procedure | [operations-procedure.md](operations-procedure.md) | Truth |
|
|
19
|
-
| Implementation map | [implementation-map.md](implementation-map.md) | Truth |
|
|
20
|
-
| Bookkeeping ledger | [bookkeeping.md](bookkeeping.md) | Truth (work queue) |
|
|
21
|
-
| Protected files | [protected-files.md](protected-files.md) | Truth |
|
|
22
|
-
| Project root README | [root-readme.md](root-readme.md) | Truth |
|
|
23
|
-
| docs/README.md (doc index) | [docs-readme.md](docs-readme.md) | Truth |
|
|
24
|
-
| docs/structure.md (authority map) | [structure.md](structure.md) | Truth (Health Log tail sanctioned) |
|
|
25
|
-
| Plan | [plan.md](plan.md) | Record |
|
|
26
|
-
| Changelog entry | [changelog-entry.md](changelog-entry.md) | Record |
|
|
27
|
-
| Migration runbook | [migration-runbook.md](migration-runbook.md) | Record |
|
|
28
|
-
| Journal | [journal.md](journal.md) | Record (append-only) |
|
|
29
|
-
| CHANGELOG master index | [changelog-index.md](changelog-index.md) | Record index (append-only) |
|
|
30
|
-
| Backlog | [backlog.md](backlog.md) | Record (append-only) |
|
|
31
|
-
| Memory (main agent) | [memory-main.md](memory-main.md) | Record (append-only ledger) |
|
|
32
|
-
|
|
33
|
-
**Baseline scaffolds** — files that must exist after every baseline; the `maintenance` agent (baseline mode) creates any that are missing: [docs-readme.md](docs-readme.md), [structure.md](structure.md), [changelog-index.md](changelog-index.md), [backlog.md](backlog.md), [memory-main.md](memory-main.md), and [root-readme.md](root-readme.md) (never overwriting an existing root README).
|
|
34
|
-
|
|
35
|
-
**Ownership.** A feature doc is the canonical reference for the code paths in its **`owns:` frontmatter** — the only ownership key. To find what a doc owns, read its `owns:` globs; to find the doc for a path, match the path against the injected ownership index (the union of every feature's `owns:` globs), narrower glob wins. See [`../references/frontmatter.md`](../references/frontmatter.md) for turning code into `owns:` globs.
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
# API Reference (docs/architecture/api.md)
|
|
2
|
-
|
|
3
|
-
Truth document. Use for: the consolidated catalog of the system's HTTP surface — every live route in one place. This is the **index**: request/response shapes stay in the owning feature docs; this doc answers "what exists and where is it documented." If the repo generates an OpenAPI spec, this doc points at it and carries only what the spec can't (auth model, conventions, ownership links).
|
|
4
|
-
|
|
5
|
-
Required: **Conventions**, the **route tables**. One row per live route; a route that isn't here doesn't exist.
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
# API Reference
|
|
9
|
-
|
|
10
|
-
## Conventions
|
|
11
|
-
|
|
12
|
-
- Base path: `/api/v{N}` · Auth: {scheme} · Envelope: `{ "status": 1, "message": "...", "data": {...} }`
|
|
13
|
-
- Errors: `{ "status": 0, "message": "...", "data": null }` · Codes: 200/201/400/401/403/404/500
|
|
14
|
-
|
|
15
|
-
## {Resource group}
|
|
16
|
-
|
|
17
|
-
| Method | Path | Purpose | Auth | Owning doc |
|
|
18
|
-
| ------ | ---- | ------- | ---- | ---------- |
|
|
19
|
-
| GET | `/api/foo` | {one line} | {role} | [feature](../features/{feature}.md) |
|
|
20
|
-
```
|