superspecs 0.1.0 → 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/.skills/cross-linker/SKILL.md +119 -0
- package/.skills/design-import/SKILL.md +289 -0
- package/.skills/execute-subagent/SKILL.md +31 -11
- package/.skills/execute-tdd/SKILL.md +5 -3
- package/.skills/plan-discuss/SKILL.md +14 -5
- package/.skills/plan-grill/SKILL.md +209 -0
- package/.skills/plan-spec/SKILL.md +34 -6
- package/.skills/tag-taxonomy/SKILL.md +141 -0
- package/.skills/techstack/SKILL.md +7 -5
- package/.skills/verify-wiki/SKILL.md +174 -35
- package/.skills/wiki-capture/SKILL.md +136 -0
- package/.skills/wiki-lint/SKILL.md +245 -0
- package/.skills/wiki-query/SKILL.md +157 -0
- package/.skills/wiki-rebuild/SKILL.md +163 -0
- package/.skills/wiki-status/SKILL.md +156 -0
- package/AGENTS.md +42 -13
- package/HOWITWORKS.md +151 -49
- package/README.md +375 -62
- package/package.json +1 -1
- package/setup.sh +481 -37
package/setup.sh
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# SuperSpecs Setup — symlinks skills into
|
|
2
|
+
# SuperSpecs Setup — symlinks skills into supported AI agent directories
|
|
3
3
|
|
|
4
4
|
set -e
|
|
5
5
|
|
|
@@ -11,9 +11,11 @@ SKILLS_DIR="$SCRIPT_DIR/.skills"
|
|
|
11
11
|
# Falls back to SCRIPT_DIR for direct `bash setup.sh` usage inside the repo.
|
|
12
12
|
PROJECT_DIR="${SUPERSPECS_PROJECT_DIR:-$SCRIPT_DIR}"
|
|
13
13
|
|
|
14
|
-
# SUPERSPECS_SKIP_SYMLINKS=1 skips
|
|
14
|
+
# SUPERSPECS_SKIP_SYMLINKS=1 skips agent symlinking (used by `superspecs init`)
|
|
15
15
|
SKIP_SYMLINKS="${SUPERSPECS_SKIP_SYMLINKS:-0}"
|
|
16
16
|
|
|
17
|
+
# ─── Banner ───────────────────────────────────────────────────────────────────
|
|
18
|
+
|
|
17
19
|
echo ""
|
|
18
20
|
echo "╔══════════════════════════════════════════════════════════╗"
|
|
19
21
|
echo "║ SuperSpecs Setup ║"
|
|
@@ -21,48 +23,250 @@ echo "║ Plan · Execute · Verify · Ship ║"
|
|
|
21
23
|
echo "╚══════════════════════════════════════════════════════════╝"
|
|
22
24
|
echo ""
|
|
23
25
|
|
|
24
|
-
# ───
|
|
26
|
+
# ─── Agent definitions ────────────────────────────────────────────────────────
|
|
27
|
+
# Indices 0-3: project-level | Indices 4-11: global
|
|
28
|
+
|
|
29
|
+
LABELS=(
|
|
30
|
+
"Claude Code (project)"
|
|
31
|
+
"Cursor (project)"
|
|
32
|
+
"Windsurf (project)"
|
|
33
|
+
"OpenCode / Aider / generic (project)"
|
|
34
|
+
"Claude Code (global)"
|
|
35
|
+
"Codex (global)"
|
|
36
|
+
"Gemini CLI (global)"
|
|
37
|
+
"GitHub Copilot CLI (global)"
|
|
38
|
+
"OpenCode (global)"
|
|
39
|
+
"Cursor (global)"
|
|
40
|
+
"Kiro (global)"
|
|
41
|
+
"Pi (global)"
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
DIRS=(
|
|
45
|
+
"$PROJECT_DIR/.claude/skills"
|
|
46
|
+
"$PROJECT_DIR/.cursor/skills"
|
|
47
|
+
"$PROJECT_DIR/.windsurf/skills"
|
|
48
|
+
"$PROJECT_DIR/.agents/skills"
|
|
49
|
+
"$HOME/.claude/skills"
|
|
50
|
+
"$HOME/.codex/skills"
|
|
51
|
+
"$HOME/.gemini/skills"
|
|
52
|
+
"$HOME/.copilot/skills"
|
|
53
|
+
"$HOME/.agents/skills"
|
|
54
|
+
"$HOME/.cursor/skills"
|
|
55
|
+
"$HOME/.kiro/skills"
|
|
56
|
+
"$HOME/.pi/agent/skills"
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# Selection state (1=selected, 0=deselected) — all selected by default
|
|
60
|
+
SEL=( 1 1 1 1 1 1 1 1 1 1 1 1 )
|
|
25
61
|
|
|
62
|
+
# ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
63
|
+
|
|
64
|
+
# Skills: create <name>/SKILL.md directory structure (required by Claude + OpenCode discovery)
|
|
26
65
|
symlink_skills() {
|
|
27
66
|
local target_dir="$1"
|
|
28
67
|
local label="$2"
|
|
29
68
|
mkdir -p "$target_dir"
|
|
30
69
|
for skill_dir in "$SKILLS_DIR"/*/; do
|
|
70
|
+
local skill_name
|
|
31
71
|
skill_name=$(basename "$skill_dir")
|
|
32
|
-
skill_file="$skill_dir/SKILL.md"
|
|
72
|
+
local skill_file="$skill_dir/SKILL.md"
|
|
33
73
|
if [ -f "$skill_file" ]; then
|
|
34
|
-
|
|
74
|
+
rm -f "$target_dir/$skill_name.md" 2>/dev/null || true # remove old flat-file if present
|
|
75
|
+
mkdir -p "$target_dir/$skill_name"
|
|
76
|
+
ln -sf "$skill_file" "$target_dir/$skill_name/SKILL.md" 2>/dev/null || true
|
|
35
77
|
fi
|
|
36
78
|
done
|
|
37
79
|
echo " ✓ $label"
|
|
38
80
|
}
|
|
39
81
|
|
|
82
|
+
# Commands: generate a clean command .md file for each skill
|
|
83
|
+
# File name determines command name — NOT frontmatter.
|
|
84
|
+
# Claude Code: <cmd_dir>/superspecs/<slash_cmd>.md → /superspecs:<slash_cmd>
|
|
85
|
+
# OpenCode: <cmd_dir>/superspecs-<slash_cmd>.md → /superspecs-<slash_cmd>
|
|
86
|
+
# NOTE: Only `description` frontmatter is written — agent-specific fields
|
|
87
|
+
# (slash_command, name, phase) from SKILL.md are intentionally omitted.
|
|
88
|
+
install_commands() {
|
|
89
|
+
local cmd_dir="$1" # base commands directory
|
|
90
|
+
local prefix="$2" # "" (use superspecs/ subdir) or "superspecs-" (flat prefix)
|
|
91
|
+
local label="$3"
|
|
92
|
+
local target_dir
|
|
93
|
+
|
|
94
|
+
if [ -z "$prefix" ]; then
|
|
95
|
+
target_dir="$cmd_dir/superspecs"
|
|
96
|
+
else
|
|
97
|
+
target_dir="$cmd_dir"
|
|
98
|
+
fi
|
|
99
|
+
mkdir -p "$target_dir"
|
|
100
|
+
|
|
101
|
+
for skill_dir in "$SKILLS_DIR"/*/; do
|
|
102
|
+
local skill_file="$skill_dir/SKILL.md"
|
|
103
|
+
[ -f "$skill_file" ] || continue
|
|
104
|
+
|
|
105
|
+
# Read slash_command from frontmatter (determines the command file name)
|
|
106
|
+
local slash_cmd
|
|
107
|
+
slash_cmd=$(grep '^slash_command:' "$skill_file" 2>/dev/null | head -1 \
|
|
108
|
+
| sed 's/^slash_command: *//' | tr -d '"' | tr -d "'")
|
|
109
|
+
[ -z "$slash_cmd" ] && continue
|
|
110
|
+
case "$slash_cmd" in *"<"*) continue ;; esac # skip template placeholders
|
|
111
|
+
|
|
112
|
+
# Read description from frontmatter (the only frontmatter field agents need)
|
|
113
|
+
local description
|
|
114
|
+
description=$(grep '^description:' "$skill_file" 2>/dev/null | head -1 \
|
|
115
|
+
| sed 's/^description: *//')
|
|
116
|
+
|
|
117
|
+
# Extract body = everything after the closing frontmatter `---`
|
|
118
|
+
local body
|
|
119
|
+
body=$(awk 'BEGIN{c=0} /^---/{c++; next} c>=2{print}' "$skill_file")
|
|
120
|
+
|
|
121
|
+
# Remove old file or symlink, then write a real generated command file
|
|
122
|
+
local cmd_file="$target_dir/${prefix}${slash_cmd}.md"
|
|
123
|
+
rm -f "$cmd_file" 2>/dev/null || true
|
|
124
|
+
{
|
|
125
|
+
printf -- '---\ndescription: %s\n---\n\n' "$description"
|
|
126
|
+
printf '%s\n' "$body"
|
|
127
|
+
} > "$cmd_file"
|
|
128
|
+
done
|
|
129
|
+
echo " ✓ $label"
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
# ─── Selection helpers ────────────────────────────────────────────────────────
|
|
133
|
+
|
|
134
|
+
_apply_selection() {
|
|
135
|
+
# Reads newline-separated selected labels from $1, updates SEL array
|
|
136
|
+
local result="$1"
|
|
137
|
+
SEL=( 0 0 0 0 0 0 0 0 0 0 0 0 )
|
|
138
|
+
while IFS= read -r line; do
|
|
139
|
+
[ -z "$line" ] && continue
|
|
140
|
+
for ((i=0; i<12; i++)); do
|
|
141
|
+
[ "${LABELS[$i]}" = "$line" ] && SEL[$i]=1
|
|
142
|
+
done
|
|
143
|
+
done <<< "$result"
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
_select_with_fzf() {
|
|
147
|
+
local result
|
|
148
|
+
result=$(printf '%s\n' "${LABELS[@]}" | \
|
|
149
|
+
fzf --multi \
|
|
150
|
+
--bind 'start:select-all' \
|
|
151
|
+
--bind 'ctrl-a:select-all' \
|
|
152
|
+
--bind 'ctrl-d:deselect-all' \
|
|
153
|
+
--height='~100%' \
|
|
154
|
+
--layout=reverse \
|
|
155
|
+
--border=rounded \
|
|
156
|
+
--prompt=' Install › ' \
|
|
157
|
+
--header=$'TAB/SPACE toggle · CTRL-A select all · CTRL-D deselect all · ENTER confirm\n\n Project: Claude Code · Cursor · Windsurf · OpenCode\n Global: Claude Code · Codex · Gemini · Copilot · OpenCode · Cursor · Kiro · Pi'
|
|
158
|
+
) || return 1
|
|
159
|
+
_apply_selection "$result"
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
_select_with_gum() {
|
|
163
|
+
local selected_str result
|
|
164
|
+
# Build comma-separated pre-selection string from all labels
|
|
165
|
+
selected_str=$(printf '%s,' "${LABELS[@]}")
|
|
166
|
+
selected_str="${selected_str%,}" # remove trailing comma
|
|
167
|
+
|
|
168
|
+
result=$(gum choose --no-limit \
|
|
169
|
+
--height=16 \
|
|
170
|
+
--header="Select agents to install (SPACE toggle, ENTER confirm):" \
|
|
171
|
+
--selected="$selected_str" \
|
|
172
|
+
"${LABELS[@]}") || return 1
|
|
173
|
+
_apply_selection "$result"
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
_select_fallback() {
|
|
177
|
+
# Simple numbered list — press ENTER to install all, or enter numbers to skip
|
|
178
|
+
echo " Agents available:"
|
|
179
|
+
echo ""
|
|
180
|
+
echo " ── Project ──────────────────────────────────"
|
|
181
|
+
for ((i=0; i<4; i++)); do
|
|
182
|
+
printf " %2d) %s\n" $((i+1)) "${LABELS[$i]}"
|
|
183
|
+
done
|
|
184
|
+
echo ""
|
|
185
|
+
echo " ── Global ───────────────────────────────────"
|
|
186
|
+
for ((i=4; i<12; i++)); do
|
|
187
|
+
printf " %2d) %s\n" $((i+1)) "${LABELS[$i]}"
|
|
188
|
+
done
|
|
189
|
+
echo ""
|
|
190
|
+
printf " Enter numbers to SKIP (e.g. 5 6 7), or press ENTER to install all: "
|
|
191
|
+
local skip_input
|
|
192
|
+
read -r skip_input
|
|
193
|
+
if [ -n "$skip_input" ]; then
|
|
194
|
+
for n in $skip_input; do
|
|
195
|
+
local idx=$((n-1))
|
|
196
|
+
[ "$idx" -ge 0 ] && [ "$idx" -lt 12 ] && SEL[$idx]=0
|
|
197
|
+
done
|
|
198
|
+
fi
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
# ─── Tool detection + multiselect ─────────────────────────────────────────────
|
|
202
|
+
|
|
203
|
+
run_multiselect() {
|
|
204
|
+
[ -t 0 ] && [ -t 1 ] || return 0 # Skip when non-interactive (CI, piped)
|
|
205
|
+
|
|
206
|
+
if command -v fzf >/dev/null 2>&1; then
|
|
207
|
+
_select_with_fzf && return 0
|
|
208
|
+
fi
|
|
209
|
+
|
|
210
|
+
if command -v gum >/dev/null 2>&1; then
|
|
211
|
+
_select_with_gum && return 0
|
|
212
|
+
fi
|
|
213
|
+
|
|
214
|
+
# Neither fzf nor gum found — offer to install gum via brew
|
|
215
|
+
if command -v brew >/dev/null 2>&1; then
|
|
216
|
+
echo " For a better selection UI, install gum (Charm):"
|
|
217
|
+
echo " brew install gum"
|
|
218
|
+
echo ""
|
|
219
|
+
printf " Install gum now? [y/N] "
|
|
220
|
+
local answer
|
|
221
|
+
read -r answer
|
|
222
|
+
echo ""
|
|
223
|
+
if [[ "$answer" =~ ^[Yy]$ ]]; then
|
|
224
|
+
brew install gum
|
|
225
|
+
_select_with_gum && return 0
|
|
226
|
+
fi
|
|
227
|
+
fi
|
|
228
|
+
|
|
229
|
+
# Final fallback: numbered list
|
|
230
|
+
_select_fallback
|
|
231
|
+
}
|
|
232
|
+
|
|
40
233
|
# ─── Project-level + Global symlinks ────────────────────────────────────────
|
|
41
234
|
|
|
42
235
|
if [ "$SKIP_SYMLINKS" != "1" ]; then
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
236
|
+
run_multiselect
|
|
237
|
+
|
|
238
|
+
proj_done=0
|
|
239
|
+
glob_done=0
|
|
240
|
+
|
|
241
|
+
for ((i=0; i<4; i++)); do
|
|
242
|
+
if [ "${SEL[$i]}" -eq 1 ]; then
|
|
243
|
+
[ "$proj_done" -eq 0 ] && echo "→ Project-level agent skills..." && proj_done=1
|
|
244
|
+
symlink_skills "${DIRS[$i]}" "${LABELS[$i]}"
|
|
245
|
+
fi
|
|
246
|
+
done
|
|
247
|
+
[ "$proj_done" -eq 1 ] && echo ""
|
|
48
248
|
|
|
249
|
+
for ((i=4; i<12; i++)); do
|
|
250
|
+
if [ "${SEL[$i]}" -eq 1 ]; then
|
|
251
|
+
[ "$glob_done" -eq 0 ] && echo "→ Global agent skills..." && glob_done=1
|
|
252
|
+
symlink_skills "${DIRS[$i]}" "${LABELS[$i]}"
|
|
253
|
+
fi
|
|
254
|
+
done
|
|
255
|
+
[ "$glob_done" -eq 1 ] && echo ""
|
|
256
|
+
|
|
257
|
+
# ── Commands ── always install for Claude Code + OpenCode (project + global)
|
|
258
|
+
echo "→ Installing slash commands..."
|
|
259
|
+
# Claude Code (subdir style → /superspecs:<cmd>)
|
|
260
|
+
install_commands "$PROJECT_DIR/.claude/commands" "" "Claude Code commands (project)"
|
|
261
|
+
install_commands "$HOME/.claude/commands" "" "Claude Code commands (global)"
|
|
262
|
+
# OpenCode (flat prefix → /superspecs-<cmd>)
|
|
263
|
+
install_commands "$PROJECT_DIR/.opencode/commands" "superspecs-" "OpenCode commands (project)"
|
|
264
|
+
install_commands "$HOME/.config/opencode/commands" "superspecs-" "OpenCode commands (global)"
|
|
49
265
|
echo ""
|
|
50
|
-
echo "→ Global agent skills..."
|
|
51
|
-
symlink_skills "$HOME/.claude/skills" "Claude Code (global)"
|
|
52
|
-
symlink_skills "$HOME/.codex/skills" "Codex (global)"
|
|
53
|
-
symlink_skills "$HOME/.gemini/skills" "Gemini CLI (global)"
|
|
54
|
-
symlink_skills "$HOME/.copilot/skills" "GitHub Copilot CLI (global)"
|
|
55
|
-
symlink_skills "$HOME/.agents/skills" "OpenCode (global)"
|
|
56
|
-
|
|
57
|
-
[ -d "$HOME/.windsurf" ] && symlink_skills "$HOME/.windsurf/skills" "Windsurf (global)"
|
|
58
|
-
[ -d "$HOME/.cursor" ] && symlink_skills "$HOME/.cursor/skills" "Cursor (global)"
|
|
59
|
-
[ -d "$HOME/.kiro" ] && symlink_skills "$HOME/.kiro/skills" "Kiro (global)"
|
|
60
|
-
[ -d "$HOME/.pi" ] && symlink_skills "$HOME/.pi/agent/skills" "Pi (global)"
|
|
61
266
|
fi
|
|
62
267
|
|
|
63
268
|
# ─── Initialize SuperSpecs directories ───────────────────────────────────────
|
|
64
269
|
|
|
65
|
-
echo ""
|
|
66
270
|
echo "→ Initializing project structure..."
|
|
67
271
|
|
|
68
272
|
mkdir -p "$PROJECT_DIR/superspec/specs"
|
|
@@ -70,26 +274,257 @@ mkdir -p "$PROJECT_DIR/superspec/phases"
|
|
|
70
274
|
mkdir -p "$PROJECT_DIR/superspec/archive"
|
|
71
275
|
mkdir -p "$PROJECT_DIR/superspec/wiki"
|
|
72
276
|
|
|
73
|
-
|
|
74
|
-
|
|
277
|
+
# ── Obsidian vault config ──────────────────────────────────────────────────
|
|
278
|
+
# Creates superspec/wiki/.obsidian/ so the wiki can be opened as an Obsidian
|
|
279
|
+
# vault directly. Workspace and plugin-data files are gitignored.
|
|
280
|
+
|
|
281
|
+
OBSIDIAN_DIR="$PROJECT_DIR/superspec/wiki/.obsidian"
|
|
282
|
+
mkdir -p "$OBSIDIAN_DIR"
|
|
283
|
+
|
|
284
|
+
if [ ! -f "$OBSIDIAN_DIR/app.json" ]; then
|
|
285
|
+
cat > "$OBSIDIAN_DIR/app.json" << 'APPEOF'
|
|
286
|
+
{
|
|
287
|
+
"attachmentFolderPath": "_attachments",
|
|
288
|
+
"newFileLocation": "folder",
|
|
289
|
+
"newFileFolderPath": "",
|
|
290
|
+
"useMarkdownLinks": false,
|
|
291
|
+
"showUnsupportedFiles": false,
|
|
292
|
+
"promptDelete": true,
|
|
293
|
+
"trashOption": "local"
|
|
294
|
+
}
|
|
295
|
+
APPEOF
|
|
296
|
+
fi
|
|
297
|
+
|
|
298
|
+
if [ ! -f "$OBSIDIAN_DIR/core-plugins.json" ]; then
|
|
299
|
+
cat > "$OBSIDIAN_DIR/core-plugins.json" << 'CPEOF'
|
|
300
|
+
[
|
|
301
|
+
"file-explorer",
|
|
302
|
+
"global-search",
|
|
303
|
+
"switcher",
|
|
304
|
+
"graph",
|
|
305
|
+
"backlinks",
|
|
306
|
+
"outgoing-link",
|
|
307
|
+
"tag-pane",
|
|
308
|
+
"page-preview",
|
|
309
|
+
"outline",
|
|
310
|
+
"starred",
|
|
311
|
+
"command-palette",
|
|
312
|
+
"file-recovery",
|
|
313
|
+
"templates",
|
|
314
|
+
"word-count"
|
|
315
|
+
]
|
|
316
|
+
CPEOF
|
|
317
|
+
fi
|
|
318
|
+
|
|
319
|
+
# Gitignore for vault-local / user-specific Obsidian files
|
|
320
|
+
if [ ! -f "$OBSIDIAN_DIR/.gitignore" ]; then
|
|
321
|
+
cat > "$OBSIDIAN_DIR/.gitignore" << 'OGIEOF'
|
|
322
|
+
# User-specific Obsidian state — do not commit
|
|
323
|
+
workspace.json
|
|
324
|
+
workspace-mobile.json
|
|
325
|
+
cache
|
|
326
|
+
.trash/
|
|
327
|
+
plugins/*/data.json
|
|
328
|
+
OGIEOF
|
|
329
|
+
fi
|
|
330
|
+
|
|
331
|
+
# ── Wiki 3-layer structure (Karpathy LLM Wiki pattern) ────────────────────
|
|
332
|
+
# raw/ — immutable source material (agent reads, never modifies)
|
|
333
|
+
# wiki/ — compiled knowledge base (agent writes on ingest/query/lint-fix)
|
|
334
|
+
# .skills/verify-wiki/SKILL.md — schema / operating rules
|
|
335
|
+
|
|
336
|
+
mkdir -p "$PROJECT_DIR/superspec/wiki/raw"
|
|
337
|
+
|
|
338
|
+
# raw/.gitkeep so the folder is tracked in git
|
|
339
|
+
if [ ! -f "$PROJECT_DIR/superspec/wiki/raw/.gitkeep" ]; then
|
|
340
|
+
touch "$PROJECT_DIR/superspec/wiki/raw/.gitkeep"
|
|
341
|
+
fi
|
|
342
|
+
|
|
343
|
+
# raw/README.md — instructions for humans dropping in source material
|
|
344
|
+
if [ ! -f "$PROJECT_DIR/superspec/wiki/raw/README.md" ]; then
|
|
345
|
+
cat > "$PROJECT_DIR/superspec/wiki/raw/README.md" << 'RAWEOF'
|
|
346
|
+
# raw/ — Source Material
|
|
347
|
+
|
|
348
|
+
Drop articles, PDFs, bookmarks, meeting notes, and external docs here.
|
|
349
|
+
|
|
350
|
+
**Rules:**
|
|
351
|
+
- Agent reads this folder but never edits or deletes files here.
|
|
352
|
+
- You commit these files; the agent compiles them into `../` (the wiki).
|
|
353
|
+
- To compile a raw document: `/superspecs:wiki-ingest <filename>`
|
|
354
|
+
- To compile a completed spec: `/superspecs:wiki <slug>`
|
|
355
|
+
|
|
356
|
+
Supported: `.md`, `.txt`, `.pdf` (text-extractable)
|
|
357
|
+
RAWEOF
|
|
358
|
+
fi
|
|
359
|
+
|
|
360
|
+
# ── Wiki home page ─────────────────────────────────────────────────────────
|
|
361
|
+
|
|
362
|
+
TODAY=$(date +%Y-%m-%d 2>/dev/null || echo "")
|
|
363
|
+
|
|
364
|
+
if [ ! -f "$PROJECT_DIR/superspec/wiki/Home.md" ]; then
|
|
365
|
+
cat > "$PROJECT_DIR/superspec/wiki/Home.md" << HOMEEOF
|
|
366
|
+
---
|
|
367
|
+
title: Wiki Home
|
|
368
|
+
tags: [index, home]
|
|
369
|
+
updated: $TODAY
|
|
370
|
+
---
|
|
371
|
+
|
|
75
372
|
# Project Wiki
|
|
76
373
|
|
|
77
|
-
|
|
374
|
+
Compiled knowledge base — architecture decisions, patterns, trade-offs, gotchas.
|
|
375
|
+
|
|
376
|
+
> **Obsidian vault** — open \`superspec/wiki/\` in [Obsidian](https://obsidian.md) for graph view, backlinks, tag search, and hover previews.
|
|
78
377
|
|
|
79
378
|
## Domains
|
|
80
379
|
|
|
81
|
-
|
|
380
|
+
| Domain | Description | Last updated |
|
|
381
|
+
|--------|-------------|-------------|
|
|
382
|
+
|
|
383
|
+
_(domains added automatically by \`/superspecs:wiki\` as features ship)_
|
|
82
384
|
|
|
83
385
|
## Recent Updates
|
|
84
386
|
|
|
85
|
-
(
|
|
86
|
-
|
|
387
|
+
_(last 10 entries — full history in [[log]])_
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
## Wiki Operations
|
|
392
|
+
|
|
393
|
+
| Command | What it does |
|
|
394
|
+
|---------|-------------|
|
|
395
|
+
| \`/superspecs:wiki <slug>\` | Compile a shipped spec into wiki pages |
|
|
396
|
+
| \`/superspecs:wiki-query\` | Query the compiled wiki |
|
|
397
|
+
| \`/superspecs:wiki-lint\` | Health check: orphans, broken links, contradictions |
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
_Maintained by [SuperSpecs](https://github.com/fokkerone/superspecs)_
|
|
402
|
+
HOMEEOF
|
|
403
|
+
fi
|
|
404
|
+
|
|
405
|
+
# ── Wiki log (append-only activity log) ───────────────────────────────────
|
|
406
|
+
|
|
407
|
+
if [ ! -f "$PROJECT_DIR/superspec/wiki/log.md" ]; then
|
|
408
|
+
cat > "$PROJECT_DIR/superspec/wiki/log.md" << LOGEOF
|
|
409
|
+
---
|
|
410
|
+
title: Wiki Log
|
|
411
|
+
tags: [log, activity]
|
|
412
|
+
---
|
|
413
|
+
|
|
414
|
+
# Wiki Log
|
|
415
|
+
|
|
416
|
+
Append-only activity log. Every ingest, query, and lint run appends an entry here.
|
|
417
|
+
|
|
418
|
+
> grep-friendly: \`grep "## \[" log.md\` lists all events
|
|
419
|
+
|
|
420
|
+
---
|
|
421
|
+
|
|
422
|
+
## [$TODAY] init | Wiki initialized
|
|
423
|
+
|
|
424
|
+
- Structure: \`raw/\` (sources) + \`wiki/\` (compiled) + \`.skills/verify-wiki/SKILL.md\` (schema)
|
|
425
|
+
- Vault ready to open in Obsidian
|
|
426
|
+
|
|
427
|
+
LOGEOF
|
|
87
428
|
fi
|
|
88
429
|
|
|
89
430
|
if [ ! -f "$PROJECT_DIR/superspec/wiki/_manifest.json" ]; then
|
|
90
431
|
echo '{"sources":[]}' > "$PROJECT_DIR/superspec/wiki/_manifest.json"
|
|
91
432
|
fi
|
|
92
433
|
|
|
434
|
+
# ── Wiki meta directory (taxonomy, insights) ───────────────────────────────
|
|
435
|
+
|
|
436
|
+
mkdir -p "$PROJECT_DIR/superspec/wiki/_meta"
|
|
437
|
+
mkdir -p "$PROJECT_DIR/superspec/wiki/_archives"
|
|
438
|
+
|
|
439
|
+
if [ ! -f "$PROJECT_DIR/superspec/wiki/_meta/taxonomy.md" ]; then
|
|
440
|
+
cat > "$PROJECT_DIR/superspec/wiki/_meta/taxonomy.md" << 'TAXEOF'
|
|
441
|
+
---
|
|
442
|
+
title: Wiki Taxonomy
|
|
443
|
+
updated: ""
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
# Wiki Taxonomy
|
|
447
|
+
|
|
448
|
+
Canonical vocabulary for this vault: domain folders and tags.
|
|
449
|
+
- Run `/superspecs:tag-taxonomy` to audit and normalize tags.
|
|
450
|
+
- Run `/superspecs:wiki-lint` to detect domain drift.
|
|
451
|
+
|
|
452
|
+
---
|
|
453
|
+
|
|
454
|
+
## Domains
|
|
455
|
+
|
|
456
|
+
Domains are concern-centric, not feature-centric. A page's domain describes *what the
|
|
457
|
+
knowledge is about*, not which feature introduced it. Feature traceability lives in
|
|
458
|
+
`spec:` frontmatter, not in the folder name.
|
|
459
|
+
|
|
460
|
+
### Core Domains
|
|
461
|
+
|
|
462
|
+
| Domain | Folder | What goes here |
|
|
463
|
+
|--------|--------|----------------|
|
|
464
|
+
| `patterns` | `patterns/` | Cross-cutting implementation patterns: error handling, caching, retry, testing |
|
|
465
|
+
| `decisions` | `decisions/` | Architecture Decision Records — why X was chosen over Y |
|
|
466
|
+
| `auth` | `auth/` | Authentication, authorization, sessions, tokens |
|
|
467
|
+
| `api` | `api/` | API contracts, endpoint design, versioning, request/response shapes |
|
|
468
|
+
| `data` | `data/` | Data models, schemas, storage strategy, migrations |
|
|
469
|
+
| `ui` | `ui/` | Frontend components, routing, state management, styling patterns |
|
|
470
|
+
| `infra` | `infra/` | Deployment, CI/CD, environment config, hosting |
|
|
471
|
+
| `techstack` | `techstack/` | Stack profile and library choices (managed by /techstack) |
|
|
472
|
+
|
|
473
|
+
### Routing Rules
|
|
474
|
+
|
|
475
|
+
When ingesting a feature, assign each knowledge unit to a domain using this decision tree:
|
|
476
|
+
|
|
477
|
+
1. **Reusable cross-cutting pattern** (error handling, caching, retry, logging)? → `patterns/`
|
|
478
|
+
2. **Architecture decision** — why X was chosen over Y? → `decisions/`
|
|
479
|
+
3. **Auth, sessions, tokens, permissions**? → `auth/`
|
|
480
|
+
4. **API contract, endpoint, or request/response shape**? → `api/`
|
|
481
|
+
5. **Data model, schema, or storage decision**? → `data/`
|
|
482
|
+
6. **Infrastructure or deployment**? → `infra/`
|
|
483
|
+
7. **Frontend / UI concern**? → `ui/`
|
|
484
|
+
8. **Feature-specific knowledge that fits none of the above**?
|
|
485
|
+
→ Create a domain named after the feature slug (e.g. `payment-flow/`)
|
|
486
|
+
→ Add it to this file under "Project Domains" before creating the folder
|
|
487
|
+
|
|
488
|
+
**One domain per page.** If a page spans multiple concerns, split it into separate pages.
|
|
489
|
+
**Prefer existing domains.** Only create a new domain if nothing above fits.
|
|
490
|
+
|
|
491
|
+
### Project Domains
|
|
492
|
+
|
|
493
|
+
_(feature-specific domains added here as the project grows)_
|
|
494
|
+
|
|
495
|
+
---
|
|
496
|
+
|
|
497
|
+
## Domain Tags
|
|
498
|
+
|
|
499
|
+
Tags mirror domain names. Every page gets a tag matching its domain.
|
|
500
|
+
|
|
501
|
+
- `auth` — authentication and authorization
|
|
502
|
+
- `api` — API design and contracts
|
|
503
|
+
- `data` — data models and storage
|
|
504
|
+
- `ui` — frontend and interface
|
|
505
|
+
- `infra` — infrastructure and deployment
|
|
506
|
+
- `patterns` — reusable implementation patterns
|
|
507
|
+
- `decisions` — architecture decision records
|
|
508
|
+
|
|
509
|
+
## Topic Tags
|
|
510
|
+
|
|
511
|
+
_(add project-specific topic tags here)_
|
|
512
|
+
|
|
513
|
+
## Meta Tags
|
|
514
|
+
|
|
515
|
+
- `index` — index and home pages (reserved)
|
|
516
|
+
- `log` — activity log (reserved)
|
|
517
|
+
- `insights` — generated insights pages (reserved)
|
|
518
|
+
- `lint` — lint report pages (reserved)
|
|
519
|
+
- `query-derived` — pages created from /wiki-query results
|
|
520
|
+
- `capture` — pages created from /wiki-capture
|
|
521
|
+
|
|
522
|
+
## Aliases
|
|
523
|
+
|
|
524
|
+
_(non-canonical → canonical mappings, managed by /tag-taxonomy)_
|
|
525
|
+
TAXEOF
|
|
526
|
+
fi
|
|
527
|
+
|
|
93
528
|
# ─── Done ─────────────────────────────────────────────────────────────────────
|
|
94
529
|
|
|
95
530
|
echo ""
|
|
@@ -99,13 +534,22 @@ echo "╚═══════════════════════
|
|
|
99
534
|
echo ""
|
|
100
535
|
echo " Open your agent and say: \"Tell me about your superspecs\""
|
|
101
536
|
echo ""
|
|
102
|
-
echo "
|
|
103
|
-
echo "
|
|
104
|
-
echo "
|
|
105
|
-
echo "
|
|
106
|
-
echo "
|
|
107
|
-
echo "
|
|
108
|
-
echo " /
|
|
109
|
-
echo " /
|
|
110
|
-
echo " /
|
|
537
|
+
echo " Claude Code / Cursor: /superspecs:<cmd>"
|
|
538
|
+
echo " OpenCode: /superspecs-<cmd>"
|
|
539
|
+
echo ""
|
|
540
|
+
echo " Wiki as Obsidian vault → open superspec/wiki/ in Obsidian"
|
|
541
|
+
echo ""
|
|
542
|
+
echo " First feature workflow:"
|
|
543
|
+
echo " /superspecs:techstack (or /superspecs-techstack)"
|
|
544
|
+
echo " /superspecs:discuss (or /superspecs-discuss)"
|
|
545
|
+
echo " /superspecs:spec (or /superspecs-spec)"
|
|
546
|
+
echo " /superspecs:grill (or /superspecs-grill)"
|
|
547
|
+
echo " /superspecs:pick-spec (or /superspecs-pick-spec)"
|
|
548
|
+
echo " /superspecs:branch (or /superspecs-branch)"
|
|
549
|
+
echo " /superspecs:subagent (or /superspecs-subagent)"
|
|
550
|
+
echo " /superspecs:tdd (or /superspecs-tdd)"
|
|
551
|
+
echo " /superspecs:code-review (or /superspecs-code-review)"
|
|
552
|
+
echo " /superspecs:check-tests (or /superspecs-check-tests)"
|
|
553
|
+
echo " /superspecs:wiki (or /superspecs-wiki)"
|
|
554
|
+
echo " /superspecs:ship (or /superspecs-ship)"
|
|
111
555
|
echo ""
|