@nurix/etna 0.1.3 → 0.2.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 +34 -27
- package/bin/etna.js +82 -56
- package/data/harness-index.json +0 -7
- package/data/harnesses/code/agents/change-review.md +80 -0
- package/data/harnesses/code/agents/contract-monitor.md +65 -0
- package/data/harnesses/code/agents/dep-health.md +148 -0
- package/data/harnesses/code/agents/git-history.md +201 -0
- package/data/harnesses/code/agents/maintenance.md +112 -0
- package/data/harnesses/code/agents/review.md +109 -0
- package/data/harnesses/code/agents/spec-mode.md +56 -0
- package/data/harnesses/code/rules/general.md +96 -0
- package/data/harnesses/code/rules/nomenclature.md +34 -0
- package/data/harnesses/code/scripts/build-ownership-index.sh +138 -0
- package/data/harnesses/code/scripts/check-doc-drift.sh +125 -0
- package/data/harnesses/code/skills/documentation/SKILL.md +238 -0
- package/data/harnesses/code/skills/documentation/references/examples.md +193 -0
- package/data/harnesses/code/skills/documentation/references/style-guide.md +288 -0
- package/data/harnesses/code/skills/documentation/references/templates.md +901 -0
- package/data/harnesses/code/skills/introspect/SKILL.md +135 -0
- package/data/harnesses/code/skills/workflow-mapper/SKILL.md +430 -0
- package/data/harnesses/code/skills/workflow-mapper/references/patterns.md +214 -0
- package/data/harnesses/kb-agi/agents/kb-agi-init.md +276 -0
- package/data/harnesses/kb-agi/agents/kb-catch-stale.md +22 -0
- package/data/harnesses/kb-agi/agents/kb-find-gaps.md +27 -0
- package/data/harnesses/kb-agi/agents/kb-fix-links.md +22 -0
- package/data/harnesses/kb-agi/agents/kb-refresh-frontdoor.md +22 -0
- package/data/harnesses/kb-agi/agents/kb-refresh-summaries.md +22 -0
- package/data/harnesses/kb-agi/agents/kb-sync-metadata.md +25 -0
- package/data/harnesses/kb-agi/rules/kb.md +13 -0
- package/package.json +1 -1
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# scripts/build-ownership-index.sh - Generate docs/OWNERSHIP_INDEX.md from feature doc frontmatter
|
|
3
|
+
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
7
|
+
OUTPUT="$REPO_ROOT/docs/OWNERSHIP_INDEX.md"
|
|
8
|
+
FEATURES_DIR="$REPO_ROOT/docs/features"
|
|
9
|
+
TMP_OWNS=$(mktemp)
|
|
10
|
+
TMP_DEPS=$(mktemp)
|
|
11
|
+
TMP_DIRS=$(mktemp)
|
|
12
|
+
trap 'rm -f "$TMP_OWNS" "$TMP_DEPS" "$TMP_DIRS"' EXIT
|
|
13
|
+
|
|
14
|
+
# Extract YAML frontmatter list field values from a markdown file
|
|
15
|
+
extract_field() {
|
|
16
|
+
local file="$1" field="$2"
|
|
17
|
+
awk -v field="$field" '
|
|
18
|
+
/^---$/ { fm++; next }
|
|
19
|
+
fm == 1 && $0 ~ "^"field":" {
|
|
20
|
+
in_field = 1
|
|
21
|
+
sub("^"field":[ ]*", "")
|
|
22
|
+
if ($0 != "" && $0 !~ /^\[/) { print $0; in_field = 0 }
|
|
23
|
+
next
|
|
24
|
+
}
|
|
25
|
+
fm == 1 && in_field && /^ +- / {
|
|
26
|
+
sub("^ +- ", "")
|
|
27
|
+
gsub(/^[ \t]+|[ \t]+$/, "")
|
|
28
|
+
print
|
|
29
|
+
next
|
|
30
|
+
}
|
|
31
|
+
fm == 1 && in_field && /^[a-z]/ { in_field = 0 }
|
|
32
|
+
fm == 1 && in_field && /^---$/ { in_field = 0 }
|
|
33
|
+
fm >= 2 { exit }
|
|
34
|
+
' "$file"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
# Collect ownership and dependency data from all feature docs
|
|
38
|
+
find "$FEATURES_DIR" -name "*.md" ! -name "README.md" -print0 | sort -z | while IFS= read -r -d '' file; do
|
|
39
|
+
rel_path="${file#$REPO_ROOT/}"
|
|
40
|
+
|
|
41
|
+
extract_field "$file" "owns" | while IFS= read -r pattern; do
|
|
42
|
+
[ -z "$pattern" ] && continue
|
|
43
|
+
printf '%s\t%s\n' "$pattern" "$rel_path" >> "$TMP_OWNS"
|
|
44
|
+
done
|
|
45
|
+
|
|
46
|
+
deps=$(extract_field "$file" "depends_on" | tr '\n' ', ' | sed 's/,$//' | sed 's/, $//')
|
|
47
|
+
if [ -n "$deps" ]; then
|
|
48
|
+
printf '%s\t%s\n' "$rel_path" "$deps" >> "$TMP_DEPS"
|
|
49
|
+
fi
|
|
50
|
+
done
|
|
51
|
+
|
|
52
|
+
# Collect owned directory prefixes for unowned path detection
|
|
53
|
+
sed 's|/\*\*$||; s|/\*$||; s|/[^/]*$||' "$TMP_OWNS" | awk -F'\t' '{ print $1 }' | sort -u > "$TMP_DIRS"
|
|
54
|
+
|
|
55
|
+
# Find unowned src/ directories
|
|
56
|
+
unowned=""
|
|
57
|
+
if [ -d "$REPO_ROOT/src" ]; then
|
|
58
|
+
for dir in "$REPO_ROOT"/src/*/; do
|
|
59
|
+
[ -d "$dir" ] || continue
|
|
60
|
+
rel_dir="${dir#$REPO_ROOT/}"
|
|
61
|
+
rel_dir="${rel_dir%/}"
|
|
62
|
+
is_owned=0
|
|
63
|
+
while IFS= read -r owned; do
|
|
64
|
+
case "$rel_dir" in
|
|
65
|
+
"$owned"*) is_owned=1; break ;;
|
|
66
|
+
esac
|
|
67
|
+
case "$owned" in
|
|
68
|
+
"$rel_dir"*) is_owned=1; break ;;
|
|
69
|
+
esac
|
|
70
|
+
done < "$TMP_DIRS"
|
|
71
|
+
if [ "$is_owned" -eq 0 ]; then
|
|
72
|
+
unowned="${unowned}- \`${rel_dir}\`
|
|
73
|
+
"
|
|
74
|
+
fi
|
|
75
|
+
done
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
# Generate output
|
|
79
|
+
cat > "$OUTPUT" << 'HEADER'
|
|
80
|
+
# Ownership Index
|
|
81
|
+
|
|
82
|
+
> **Generated file** — do not edit manually.
|
|
83
|
+
> Regenerate with: `bash scripts/build-ownership-index.sh`
|
|
84
|
+
|
|
85
|
+
Machine-readable lookup table generated from feature doc frontmatter.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## By Code Path
|
|
90
|
+
|
|
91
|
+
| Code Path | Owning Doc |
|
|
92
|
+
|---|---|
|
|
93
|
+
HEADER
|
|
94
|
+
|
|
95
|
+
sort "$TMP_OWNS" | while IFS=$'\t' read -r pattern doc; do
|
|
96
|
+
echo "| \`$pattern\` | \`$doc\` |" >> "$OUTPUT"
|
|
97
|
+
done
|
|
98
|
+
|
|
99
|
+
cat >> "$OUTPUT" << 'SECTION'
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Unowned Paths
|
|
104
|
+
|
|
105
|
+
Top-level `src/` directories with no owning feature doc:
|
|
106
|
+
|
|
107
|
+
SECTION
|
|
108
|
+
|
|
109
|
+
if [ -z "$unowned" ]; then
|
|
110
|
+
echo "_All top-level src/ directories have owners._" >> "$OUTPUT"
|
|
111
|
+
else
|
|
112
|
+
printf '%s' "$unowned" >> "$OUTPUT"
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
cat >> "$OUTPUT" << 'SECTION'
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Dependency Graph
|
|
120
|
+
|
|
121
|
+
Feature docs and their declared `depends_on` relationships:
|
|
122
|
+
|
|
123
|
+
| Feature Doc | Depends On |
|
|
124
|
+
|---|---|
|
|
125
|
+
SECTION
|
|
126
|
+
|
|
127
|
+
if [ -s "$TMP_DEPS" ]; then
|
|
128
|
+
sort "$TMP_DEPS" | while IFS=$'\t' read -r doc deps; do
|
|
129
|
+
echo "| \`$doc\` | $deps |" >> "$OUTPUT"
|
|
130
|
+
done
|
|
131
|
+
fi
|
|
132
|
+
|
|
133
|
+
echo "" >> "$OUTPUT"
|
|
134
|
+
echo "---" >> "$OUTPUT"
|
|
135
|
+
echo "" >> "$OUTPUT"
|
|
136
|
+
echo "_Generated: $(date -u '+%Y-%m-%d %H:%M UTC')_" >> "$OUTPUT"
|
|
137
|
+
|
|
138
|
+
echo "Generated $OUTPUT"
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# scripts/check-doc-drift.sh - Detect potentially stale docs based on recent code changes
|
|
3
|
+
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
DAYS="${1:-14}"
|
|
7
|
+
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
8
|
+
FEATURES_DIR="$REPO_ROOT/docs/features"
|
|
9
|
+
TMP_OWNS=$(mktemp)
|
|
10
|
+
TMP_STALE=$(mktemp)
|
|
11
|
+
TMP_UNOWNED=$(mktemp)
|
|
12
|
+
trap 'rm -f "$TMP_OWNS" "$TMP_STALE" "$TMP_UNOWNED"' EXIT
|
|
13
|
+
|
|
14
|
+
echo "Checking for doc drift over the last $DAYS days..."
|
|
15
|
+
echo ""
|
|
16
|
+
|
|
17
|
+
# Extract owns patterns from a markdown file
|
|
18
|
+
extract_owns() {
|
|
19
|
+
local file="$1"
|
|
20
|
+
awk '
|
|
21
|
+
/^---$/ { fm++; next }
|
|
22
|
+
fm == 1 && /^owns:/ { in_owns = 1; next }
|
|
23
|
+
fm == 1 && in_owns && /^ +- / {
|
|
24
|
+
sub("^ +- ", "")
|
|
25
|
+
gsub(/^[ \t]+|[ \t]+$/, "")
|
|
26
|
+
print
|
|
27
|
+
next
|
|
28
|
+
}
|
|
29
|
+
fm == 1 && in_owns && /^[a-z]/ { exit }
|
|
30
|
+
fm >= 2 { exit }
|
|
31
|
+
' "$file"
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
# Get recently changed files
|
|
35
|
+
changed_files=$(cd "$REPO_ROOT" && git log --since="$DAYS days ago" --name-only --pretty=format:"" | sort -u | grep -v '^$' || true)
|
|
36
|
+
|
|
37
|
+
if [ -z "$changed_files" ]; then
|
|
38
|
+
echo "No files changed in the last $DAYS days."
|
|
39
|
+
exit 0
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
changed_count=$(echo "$changed_files" | wc -l | tr -d ' ')
|
|
43
|
+
echo "Found $changed_count changed files in the last $DAYS days."
|
|
44
|
+
echo ""
|
|
45
|
+
|
|
46
|
+
# Build ownership map: pattern\tdoc
|
|
47
|
+
find "$FEATURES_DIR" -name "*.md" ! -name "README.md" -print0 | sort -z | while IFS= read -r -d '' file; do
|
|
48
|
+
rel_path="${file#$REPO_ROOT/}"
|
|
49
|
+
extract_owns "$file" | while IFS= read -r pattern; do
|
|
50
|
+
[ -z "$pattern" ] && continue
|
|
51
|
+
printf '%s\t%s\n' "$pattern" "$rel_path" >> "$TMP_OWNS"
|
|
52
|
+
done
|
|
53
|
+
done
|
|
54
|
+
|
|
55
|
+
# Check each changed file against ownership
|
|
56
|
+
echo "$changed_files" | while IFS= read -r changed_file; do
|
|
57
|
+
[ -z "$changed_file" ] && continue
|
|
58
|
+
# Skip non-source files
|
|
59
|
+
case "$changed_file" in
|
|
60
|
+
docs/*|.claude/*|.github/*|node_modules/*|package*.json|*.lock*|*.config*) continue ;;
|
|
61
|
+
esac
|
|
62
|
+
|
|
63
|
+
found_owner=0
|
|
64
|
+
while IFS=$'\t' read -r pattern doc; do
|
|
65
|
+
prefix="${pattern%%\*\**}"
|
|
66
|
+
prefix="${prefix%%\**}"
|
|
67
|
+
case "$changed_file" in
|
|
68
|
+
${prefix}*)
|
|
69
|
+
found_owner=1
|
|
70
|
+
# Check if the doc was also modified recently
|
|
71
|
+
if ! echo "$changed_files" | grep -q "^${doc}$"; then
|
|
72
|
+
printf '%s\t%s\n' "$doc" "$changed_file" >> "$TMP_STALE"
|
|
73
|
+
fi
|
|
74
|
+
break
|
|
75
|
+
;;
|
|
76
|
+
esac
|
|
77
|
+
done < "$TMP_OWNS"
|
|
78
|
+
|
|
79
|
+
if [ "$found_owner" -eq 0 ]; then
|
|
80
|
+
case "$changed_file" in
|
|
81
|
+
src/*|app/*|packages/*) echo "$changed_file" >> "$TMP_UNOWNED" ;;
|
|
82
|
+
esac
|
|
83
|
+
fi
|
|
84
|
+
done
|
|
85
|
+
|
|
86
|
+
# Report stale docs
|
|
87
|
+
if [ -s "$TMP_STALE" ]; then
|
|
88
|
+
echo "## Potentially Stale Docs"
|
|
89
|
+
echo ""
|
|
90
|
+
echo "These docs own code that changed recently, but the docs themselves were not updated:"
|
|
91
|
+
echo ""
|
|
92
|
+
current_doc=""
|
|
93
|
+
sort "$TMP_STALE" | while IFS=$'\t' read -r doc file; do
|
|
94
|
+
if [ "$doc" != "$current_doc" ]; then
|
|
95
|
+
[ -n "$current_doc" ] && echo ""
|
|
96
|
+
echo "**$doc**"
|
|
97
|
+
current_doc="$doc"
|
|
98
|
+
fi
|
|
99
|
+
echo " - $file"
|
|
100
|
+
done
|
|
101
|
+
echo ""
|
|
102
|
+
else
|
|
103
|
+
echo "## No Stale Docs Detected"
|
|
104
|
+
echo ""
|
|
105
|
+
echo "All docs whose owned code changed were also updated."
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
echo ""
|
|
109
|
+
|
|
110
|
+
# Report unowned files
|
|
111
|
+
if [ -s "$TMP_UNOWNED" ]; then
|
|
112
|
+
unowned_count=$(wc -l < "$TMP_UNOWNED" | tr -d ' ')
|
|
113
|
+
echo "## Unowned Changed Files ($unowned_count)"
|
|
114
|
+
echo ""
|
|
115
|
+
echo "These changed source files have no owning feature doc:"
|
|
116
|
+
echo ""
|
|
117
|
+
sort -u "$TMP_UNOWNED" | head -30 | while IFS= read -r file; do
|
|
118
|
+
echo "- $file"
|
|
119
|
+
done
|
|
120
|
+
if [ "$unowned_count" -gt 30 ]; then
|
|
121
|
+
echo "- ... and $((unowned_count - 30)) more"
|
|
122
|
+
fi
|
|
123
|
+
else
|
|
124
|
+
echo "## No Unowned Changed Files"
|
|
125
|
+
fi
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: documentation
|
|
3
|
+
description: Create and maintain technical documentation. Use when the user asks to (1) baseline, audit, or reorganize docs — enforces an opinionated 6-folder structure (architecture, features, operations, history, memory, tests) with ownership frontmatter and scaffold files, (2) document a feature or module, (3) create or update a changelog entry, (4) document data flows or Redux state, (5) add to protected files, (6) create or update guardrails (cascading failure boundaries), (7) record an architecture decision (ADR), (8) create or update the project root README, (9) create or update a plan, or (10) co-author any technical doc. Triggers on "document this", "create docs", "update changelog", "baseline docs", "audit docs", "add to protected files", "guardrails", "ADR", "architecture decision", "root README", "plan".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Technical Documentation Skill
|
|
7
|
+
|
|
8
|
+
Document contracts and architecture, not implementation details. Show function signatures and API shapes — never paste full implementations (they rot fast). Use ASCII diagrams over prose for flows. Only document state at persistence boundaries (Redux persistence, DB schemas, API shapes), not component-level or transient state. Mark deprecated fields with `// UNUSED:` comments. Breaking changes belong in changelogs only, not module docs.
|
|
9
|
+
|
|
10
|
+
**No redirect docs.** When moving a doc to a new location, delete the old file entirely. Update all references (routing, ownership index, memory files, frontmatter `depends_on`, cross-doc links) to point to the new path. Never leave a stub file that says "Moved to X" — redirect docs rot, clutter the repo, and create false search hits.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Decision Tree
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
User request
|
|
18
|
+
│
|
|
19
|
+
├─ "Baseline/audit docs" ──────────▶ Baseline Audit (below)
|
|
20
|
+
│
|
|
21
|
+
├─ "Document feature/module" ──────▶ Module Template
|
|
22
|
+
│
|
|
23
|
+
├─ "Create/update changelog" ──────▶ Changelog Template
|
|
24
|
+
│
|
|
25
|
+
├─ "Document data flow" ───────────▶ Module Template (Architecture section)
|
|
26
|
+
│
|
|
27
|
+
├─ "Document Redux/state" ─────────▶ Module Template (State section)
|
|
28
|
+
│
|
|
29
|
+
├─ "Add to protected files" ───────▶ Protected Files Template
|
|
30
|
+
│
|
|
31
|
+
├─ "Create/update guardrails" ─────▶ Guardrails Template
|
|
32
|
+
│
|
|
33
|
+
├─ "Record architecture decision" ─▶ ADR Template
|
|
34
|
+
│
|
|
35
|
+
├─ "Create/update root README" ────▶ Project Root README Template
|
|
36
|
+
│
|
|
37
|
+
├─ "Create/update plan" ───────────▶ Plan Template
|
|
38
|
+
│
|
|
39
|
+
├─ "Update existing doc" ──────────▶ Preserve existing structure
|
|
40
|
+
│
|
|
41
|
+
└─ No template matches ────────────▶ Co-Authoring Workflow (below)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Baseline Audit
|
|
47
|
+
|
|
48
|
+
When asked to "baseline", "audit", or "review" docs, enforce the canonical 6-folder documentation structure. This is an opinionated reorganization — the target structure is non-negotiable.
|
|
49
|
+
|
|
50
|
+
### Target Structure
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
docs/
|
|
54
|
+
├── README.md # Documentation root — quick links table, section index
|
|
55
|
+
├── structure.md # Authority map, folder rules, health log
|
|
56
|
+
├── CODEBASE_MAP.md # Auto-generated directory map (optional)
|
|
57
|
+
├── faq.md # Common issues (optional)
|
|
58
|
+
├── architecture/ # System-wide decisions, patterns, technical references
|
|
59
|
+
│ ├── adr/ # Architecture Decision Records (numbered, immutable)
|
|
60
|
+
│ └── core/ # Core module internals (auth, state, routing)
|
|
61
|
+
├── features/ # Living feature specs with ownership frontmatter
|
|
62
|
+
│ └── {feature}/ # Subfolder for deep features (e.g., editor/)
|
|
63
|
+
├── operations/ # Setup, development, deployment, CI/CD
|
|
64
|
+
│ └── guardrails.md # Cascading failure boundaries (cross-module contracts)
|
|
65
|
+
├── history/ # Frozen/append-only records
|
|
66
|
+
│ ├── CHANGELOG.md # Master changelog index
|
|
67
|
+
│ ├── changelog/ # Individual changelog entries
|
|
68
|
+
│ ├── plans/ # Historical implementation plans (Status field required)
|
|
69
|
+
│ └── backlog.md # Tracked work items by priority (P0-P3)
|
|
70
|
+
├── memory/ # Agent memory files
|
|
71
|
+
└── tests/ # Test plans and automation docs (optional)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Workflow
|
|
75
|
+
|
|
76
|
+
**Step 1: Inventory existing docs**
|
|
77
|
+
|
|
78
|
+
Glob all markdown files in the repo. Categorize each file:
|
|
79
|
+
|
|
80
|
+
| Category | Matches | Target |
|
|
81
|
+
|----------|---------|--------|
|
|
82
|
+
| Architecture | System design, patterns, config, API specs, tech decisions | `docs/architecture/` |
|
|
83
|
+
| Features | How a feature works, user-facing behavior, data models | `docs/features/` |
|
|
84
|
+
| Operations | Setup, dev workflow, deployment, CI/CD, runbooks | `docs/operations/` |
|
|
85
|
+
| Plans | Implementation plans, proposals, RFCs | `docs/history/plans/` |
|
|
86
|
+
| Changelogs | Change records, release notes | `docs/history/changelog/` |
|
|
87
|
+
| Backlogs/Tasks | Work items, TODOs, tech debt | Merge into `docs/history/backlog.md` |
|
|
88
|
+
| Stale/Deprecated | Self-marked deprecated, fully superseded, empty docs | Delete |
|
|
89
|
+
| Root docs | `README.md`, `CLAUDE.md`, `AGENTS.md` | Stay in root |
|
|
90
|
+
|
|
91
|
+
**Step 2: Detect duplicates and overlaps**
|
|
92
|
+
|
|
93
|
+
For each topic, identify all files covering it. Keep the most complete version as canonical. Extract unique content from others before deleting.
|
|
94
|
+
|
|
95
|
+
**Step 3: Present reorganization plan**
|
|
96
|
+
|
|
97
|
+
Present a table to the user:
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
| File | Action | From | To | Reason |
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Actions: `Move`, `Merge into {target}`, `Delete`, `Keep`, `Create`
|
|
104
|
+
|
|
105
|
+
Ask: "Approve this plan? I'll execute all moves, merges, and deletions."
|
|
106
|
+
|
|
107
|
+
**Step 4: Execute reorganization**
|
|
108
|
+
|
|
109
|
+
After approval:
|
|
110
|
+
|
|
111
|
+
1. Create the full folder structure:
|
|
112
|
+
- `docs/architecture/`
|
|
113
|
+
- `docs/features/`
|
|
114
|
+
- `docs/operations/`
|
|
115
|
+
- `docs/history/plans/`
|
|
116
|
+
- `docs/history/changelog/`
|
|
117
|
+
- `docs/memory/`
|
|
118
|
+
- `docs/tests/` (if test docs exist)
|
|
119
|
+
2. Move files per the plan
|
|
120
|
+
3. Merge content where specified (extract unique content, append to target)
|
|
121
|
+
4. Delete stale/superseded files
|
|
122
|
+
5. Add `Status: Complete | In Progress | Draft | Abandoned` to all plan files
|
|
123
|
+
6. Add YAML frontmatter to feature docs (see Frontmatter Derivation below)
|
|
124
|
+
7. Merge scattered backlog/task files into `docs/history/backlog.md`
|
|
125
|
+
8. Scaffold standard files if missing:
|
|
126
|
+
- `docs/README.md` — from template (see `references/templates.md`)
|
|
127
|
+
- `docs/structure.md` — from template (see `references/templates.md`)
|
|
128
|
+
- `docs/operations/guardrails.md` — cascading failure boundaries (see `references/templates.md` for what to include/exclude)
|
|
129
|
+
- `docs/history/CHANGELOG.md` — master changelog index (header + table linking to entries)
|
|
130
|
+
- `docs/history/backlog.md` — work items by priority (P0-P3 sections, empty if nothing to merge)
|
|
131
|
+
- `docs/memory/index.md` — agent memory index (empty scaffold with section headers)
|
|
132
|
+
- `docs/memory/main.md` — main agent project memory (empty header + date marker)
|
|
133
|
+
- `docs/OWNERSHIP_INDEX.md` — generated table of feature doc ownership. Build it now from the frontmatter you derived in Step 6 (same shape the maintenance agent regenerates each run — see `references/templates.md`)
|
|
134
|
+
- `README.md` (repo root) — from §11 in `references/templates.md`, filled with concrete details from the repo (real package manager from the lockfile, real scripts, real layout). **Never overwrite an existing root README** — if one is present, leave it untouched.
|
|
135
|
+
9. Fix all internal links broken by moves
|
|
136
|
+
10. Record baseline in `docs/memory/index.md` with today's date (see template)
|
|
137
|
+
|
|
138
|
+
**Step 5: Verify**
|
|
139
|
+
|
|
140
|
+
1. Confirm all standard files exist: `docs/README.md`, `docs/structure.md`, `docs/operations/guardrails.md`, `docs/history/CHANGELOG.md`, `docs/history/backlog.md`, `docs/memory/index.md`, `docs/memory/main.md`, `docs/OWNERSHIP_INDEX.md`, `README.md` (repo root — must exist; either pre-existing untouched or freshly scaffolded)
|
|
141
|
+
2. Confirm no dead links in `docs/README.md`
|
|
142
|
+
3. Confirm every plan file has a `Status:` field
|
|
143
|
+
4. Confirm feature docs have ownership frontmatter
|
|
144
|
+
5. Confirm `docs/OWNERSHIP_INDEX.md` rows match the frontmatter on disk (no orphans, no missing entries)
|
|
145
|
+
6. Confirm no docs remain outside the 6-folder structure (except `README.md`, `structure.md`, `CODEBASE_MAP.md`, `faq.md`)
|
|
146
|
+
7. Confirm duplicates are eliminated — each topic has one canonical source
|
|
147
|
+
|
|
148
|
+
### Rules
|
|
149
|
+
|
|
150
|
+
- The 6-folder structure is mandatory. No `docs/guides/`, `docs/core/`, `docs/editor/`, `docs/pt/`, or any other top-level folder
|
|
151
|
+
- Guides about how-to-run → `operations/`. Guides about a feature → `features/`
|
|
152
|
+
- Core module docs → `docs/architecture/core/`. Editor module docs → `docs/features/editor/`
|
|
153
|
+
- Only `CLAUDE.md`, `AGENTS.md`, and `README.md` are allowed in the repository root (not inside `docs/`)
|
|
154
|
+
- Root-level `README.md` is for humans. `docs/README.md` is the agent/doc entry point
|
|
155
|
+
- One canonical source per topic — link, don't copy
|
|
156
|
+
- **No redirect docs** — when moving a file, delete the original and fix all references. Never leave a "Moved to X" stub.
|
|
157
|
+
- For 10+ files, use parallel sub-agents (5-8 files each)
|
|
158
|
+
|
|
159
|
+
### Naming & Lifecycle
|
|
160
|
+
|
|
161
|
+
- Features: `kebab-case.md` — living reference, status `Active`
|
|
162
|
+
- Plans: `YYYY-MM-DD-kebab-case.md` — frozen after `Complete` or `Abandoned`
|
|
163
|
+
- Changelogs: `YYYY-MM-DD-kebab-case.md` — append-only
|
|
164
|
+
- Memory: `{agent-name}.md` — agent-maintained
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Frontmatter Derivation
|
|
169
|
+
|
|
170
|
+
When creating or updating a feature doc in `docs/features/`, generate `owns`, `touches`, `depends_on` frontmatter from the source code the doc describes.
|
|
171
|
+
|
|
172
|
+
### When to run
|
|
173
|
+
|
|
174
|
+
- **Baseline audit Step 6** — for every feature doc missing frontmatter
|
|
175
|
+
- **New feature doc** — when creating a doc via the Module Documentation template
|
|
176
|
+
- **Doc update** — when updating an existing feature doc and the frontmatter is missing or the documented scope changed
|
|
177
|
+
|
|
178
|
+
### How to derive values
|
|
179
|
+
|
|
180
|
+
**1. Identify `owns` patterns**
|
|
181
|
+
|
|
182
|
+
Read the feature doc's content. Extract every source file path referenced in the doc (file listings, function locations, component paths). Group them into the narrowest glob patterns that cover all referenced files without overlapping other features.
|
|
183
|
+
|
|
184
|
+
| Doc references | `owns` pattern |
|
|
185
|
+
|---|---|
|
|
186
|
+
| Multiple files under one directory | `src/feature/**` |
|
|
187
|
+
| Specific files in a shared directory | List each file explicitly |
|
|
188
|
+
| A single entry-point file | The exact file path |
|
|
189
|
+
|
|
190
|
+
Verify patterns match real files — glob each pattern against the codebase. Remove any that match nothing.
|
|
191
|
+
|
|
192
|
+
**2. Identify `touches` patterns**
|
|
193
|
+
|
|
194
|
+
From the same source files the doc describes, find imports and calls to code outside the `owns` scope. These are files the feature uses but doesn't own.
|
|
195
|
+
|
|
196
|
+
Common `touches` candidates:
|
|
197
|
+
- Shared Redux slices the feature reads/writes
|
|
198
|
+
- Utility functions from other modules
|
|
199
|
+
- Shared hooks the feature calls
|
|
200
|
+
- API route files the feature's frontend calls
|
|
201
|
+
|
|
202
|
+
Keep `touches` to direct dependencies only — not transitive ones.
|
|
203
|
+
|
|
204
|
+
**3. Identify `depends_on` docs**
|
|
205
|
+
|
|
206
|
+
Check for explicit cross-references to other docs in `docs/features/` or `docs/architecture/`. Also check if the feature's `touches` paths are `owns`-ed by another feature doc — that doc is a dependency.
|
|
207
|
+
|
|
208
|
+
### Rules
|
|
209
|
+
|
|
210
|
+
- Every feature doc must have all three fields, even if empty (`depends_on: []`)
|
|
211
|
+
- Use glob patterns for directories, explicit paths for individual files
|
|
212
|
+
- Don't list paths that don't exist in the codebase
|
|
213
|
+
- When a doc covers a deep feature with sub-specs (e.g., `editor/`), each sub-spec gets its own frontmatter — don't duplicate ownership across siblings
|
|
214
|
+
- For baseline audits with 10+ files needing frontmatter, use parallel sub-agents to read and analyze the source files
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Co-Authoring Workflow
|
|
219
|
+
|
|
220
|
+
For docs that don't match templates:
|
|
221
|
+
|
|
222
|
+
**Stage 1: Context Gathering**
|
|
223
|
+
- Ask: Audience? Purpose? Existing format?
|
|
224
|
+
- Have user dump all context, then ask 5-10 clarifying questions
|
|
225
|
+
|
|
226
|
+
**Stage 2: Structure & Draft**
|
|
227
|
+
- Propose section structure, draft section by section
|
|
228
|
+
- User indicates changes (don't edit directly — learn their style)
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Resources
|
|
233
|
+
|
|
234
|
+
| File | Use For |
|
|
235
|
+
|------|---------|
|
|
236
|
+
| `references/templates.md` | docs/README.md, structure.md, frontmatter, scaffolds (CHANGELOG, backlog, memory, OWNERSHIP_INDEX), guardrails, feature, changelog, plan, protected files, ADR, project root README templates |
|
|
237
|
+
| `references/style-guide.md` | Writing rules, formatting conventions |
|
|
238
|
+
| `references/examples.md` | Good vs bad documentation examples |
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# Documentation Examples
|
|
2
|
+
|
|
3
|
+
Good vs bad examples showing the key differences.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Example 1: Function Documentation
|
|
8
|
+
|
|
9
|
+
### ❌ Bad: Full Implementation
|
|
10
|
+
|
|
11
|
+
```markdown
|
|
12
|
+
### mergeData
|
|
13
|
+
|
|
14
|
+
function mergeData(server, local, changes) {
|
|
15
|
+
const result = {};
|
|
16
|
+
const serverMap = new Map(server.map((i) => [i.id, i]));
|
|
17
|
+
// ... 30 more lines
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Problems:** Will become obsolete, focuses on HOW not WHAT.
|
|
23
|
+
|
|
24
|
+
### ✅ Good: Contract Only
|
|
25
|
+
|
|
26
|
+
```markdown
|
|
27
|
+
### `mergeData(serverData, localData, changes)`
|
|
28
|
+
|
|
29
|
+
**Goal:** Merge server data with local changes
|
|
30
|
+
**Input:**
|
|
31
|
+
|
|
32
|
+
- `serverData` (array) - Fresh from API
|
|
33
|
+
- `localData` (array) - Current state
|
|
34
|
+
- `changes` (object) - `{ added, updated, removed }`
|
|
35
|
+
**Output:** `{ merged: array, conflicts: array }`
|
|
36
|
+
|
|
37
|
+
**Merge Rules:**
|
|
38
|
+
|
|
39
|
+
- Server wins for conflicts
|
|
40
|
+
- Local additions preserved
|
|
41
|
+
- Local removals marked as intent
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Example 2: State Documentation
|
|
47
|
+
|
|
48
|
+
### ❌ Bad: State Everywhere
|
|
49
|
+
|
|
50
|
+
```markdown
|
|
51
|
+
## Component State
|
|
52
|
+
|
|
53
|
+
const [items, setItems] = useState([]);
|
|
54
|
+
|
|
55
|
+
## Hook State
|
|
56
|
+
|
|
57
|
+
{ data: items, isLoading: loading, error: null }
|
|
58
|
+
|
|
59
|
+
## Redux State
|
|
60
|
+
|
|
61
|
+
{ items: [], loading: false, error: null }
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Problems:** Documents transient state, repeats shapes.
|
|
65
|
+
|
|
66
|
+
### ✅ Good: Persistence Points Only
|
|
67
|
+
|
|
68
|
+
```markdown
|
|
69
|
+
## State
|
|
70
|
+
|
|
71
|
+
**Frontend (at persistence):**
|
|
72
|
+
{
|
|
73
|
+
"data": [],
|
|
74
|
+
"changes": { "added": [], "updated": [], "removed": [] }
|
|
75
|
+
// "cache": {} // UNUSED: Deprecated
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
**Storage:** localStorage `app_state`
|
|
79
|
+
|
|
80
|
+
**Backend:**
|
|
81
|
+
model Item {
|
|
82
|
+
id String @id
|
|
83
|
+
data Json
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Example 3: Changelog
|
|
90
|
+
|
|
91
|
+
### ❌ Bad: Vague
|
|
92
|
+
|
|
93
|
+
```markdown
|
|
94
|
+
# 2025-01-05 - Updates
|
|
95
|
+
|
|
96
|
+
## Changes
|
|
97
|
+
|
|
98
|
+
- Updated editor
|
|
99
|
+
- Fixed bugs
|
|
100
|
+
- Improved performance
|
|
101
|
+
|
|
102
|
+
## Files
|
|
103
|
+
|
|
104
|
+
- Various files in src/
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### ✅ Good: Function-Level Detail
|
|
108
|
+
|
|
109
|
+
```markdown
|
|
110
|
+
# 2025-01-05 - Version-Based Merge
|
|
111
|
+
|
|
112
|
+
## Summary
|
|
113
|
+
|
|
114
|
+
Replaced change-tracking merge with version-based conflict resolution.
|
|
115
|
+
|
|
116
|
+
## Changes
|
|
117
|
+
|
|
118
|
+
### Added
|
|
119
|
+
|
|
120
|
+
- `mergeAndDerive(server, local, versionsMatch, type)` in `src/utils/merge.js`
|
|
121
|
+
- Purpose: Single-pass merge with change detection
|
|
122
|
+
- Returns: `{ merged, changes }`
|
|
123
|
+
|
|
124
|
+
### Modified
|
|
125
|
+
|
|
126
|
+
- `useDataSync()` in `src/hooks/useDataSync.js`
|
|
127
|
+
- Changed: Now compares versions before merge
|
|
128
|
+
|
|
129
|
+
### Removed
|
|
130
|
+
|
|
131
|
+
- `deriveChanges()` from `src/utils/derive.js`
|
|
132
|
+
- Replaced by: Logic in `mergeAndDerive()`
|
|
133
|
+
|
|
134
|
+
## Breaking Changes
|
|
135
|
+
|
|
136
|
+
⚠️ **Merge behavior changed**
|
|
137
|
+
|
|
138
|
+
- Old: Local changes always preserved
|
|
139
|
+
- New: Local preserved only if versions match
|
|
140
|
+
|
|
141
|
+
## Files Changed
|
|
142
|
+
|
|
143
|
+
- `src/hooks/useDataSync.js`
|
|
144
|
+
- `src/utils/merge.js`
|
|
145
|
+
- `src/utils/derive.js` (deleted)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Example 4: Data Flow
|
|
151
|
+
|
|
152
|
+
### ❌ Bad: Prose Description
|
|
153
|
+
|
|
154
|
+
```markdown
|
|
155
|
+
When the page loads, the useAppInit hook calls the syncData function.
|
|
156
|
+
This function first fetches data from the server using the API. Then
|
|
157
|
+
it gets the local data from Redux. After that, it compares versions...
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### ✅ Good: Diagram + Key Points
|
|
161
|
+
|
|
162
|
+
```markdown
|
|
163
|
+
## Data Flow
|
|
164
|
+
|
|
165
|
+
┌─────────────────────────────────────────┐
|
|
166
|
+
│ DATA SYNC │
|
|
167
|
+
├─────────────────────────────────────────┤
|
|
168
|
+
│ │
|
|
169
|
+
│ ┌──────┐ ┌──────┐ ┌──────┐ │
|
|
170
|
+
│ │Server│────▶│Merge │────▶│Redux │ │
|
|
171
|
+
│ │ API │ │ │ │Store │ │
|
|
172
|
+
│ └──────┘ └──────┘ └──────┘ │
|
|
173
|
+
│ │ │
|
|
174
|
+
│ ▼ │
|
|
175
|
+
│ Version Check │
|
|
176
|
+
│ │
|
|
177
|
+
└─────────────────────────────────────────┘
|
|
178
|
+
|
|
179
|
+
**Trigger:** `useAppInit()` on page load
|
|
180
|
+
**Version Rule:** Match → local wins, Mismatch → server wins
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Quick Comparison
|
|
186
|
+
|
|
187
|
+
| Aspect | Bad | Good |
|
|
188
|
+
| ---------- | -------------------- | --------------------------- |
|
|
189
|
+
| Code | Full implementations | Signatures + contracts |
|
|
190
|
+
| State | Every occurrence | Persistence points only |
|
|
191
|
+
| Flows | Prose paragraphs | ASCII diagrams |
|
|
192
|
+
| Changelogs | "Updated X" | Function names + migrations |
|
|
193
|
+
| Length | 100+ lines | 20-40 lines |
|