start-vibing 4.4.3 → 4.4.4
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/package.json +1 -1
- package/template/.claude/agents/research-query.md +128 -0
- package/template/.claude/agents/research-scout.md +124 -0
- package/template/.claude/agents/research-synthesize.md +139 -0
- package/template/.claude/agents/research-verify.md +84 -0
- package/template/.claude/commands/research.md +18 -0
- package/template/.claude/hooks/research-session-start.sh +4 -0
- package/template/.claude/settings.json +4 -0
- package/template/.claude/skills/research/SKILL.md +285 -0
- package/template/.claude/skills/research/references/domain-playbooks.md +604 -0
- package/template/.claude/skills/research/references/ontology-patterns.md +376 -0
- package/template/.claude/skills/research/references/research-methodology.md +794 -0
- package/template/.claude/skills/research/references/source-directory.md +280 -0
- package/template/.claude/skills/research/scripts/__pycache__/extract-claims.cpython-313.pyc +0 -0
- package/template/.claude/skills/research/scripts/check-cache.sh +129 -0
- package/template/.claude/skills/research/scripts/dedup-research.sh +80 -0
- package/template/.claude/skills/research/scripts/extract-claims.py +83 -0
- package/template/.claude/skills/research/scripts/update-index.sh +106 -0
- package/template/.claude/skills/research/scripts/verify-citations.sh +107 -0
- package/template/.claude/skills/research/templates/adr.md.tpl +66 -0
- package/template/.claude/skills/research/templates/index.md.tpl +25 -0
- package/template/.claude/skills/research/templates/moc.md.tpl +39 -0
- package/template/.claude/skills/research/templates/research-state.schema.json +64 -0
- package/template/.claude/skills/research/templates/research.md.tpl +117 -0
- package/template/.claude/agents/research-web.md +0 -164
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# update-index.sh — regenerate /docs/research/index.md and per-folder
|
|
3
|
+
# indexes from frontmatter of all docs. Idempotent.
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
ROOT="${CLAUDE_PROJECT_DIR:-$(pwd)}"
|
|
7
|
+
DIR="${ROOT}/docs/research"
|
|
8
|
+
INDEX="${DIR}/index.md"
|
|
9
|
+
DEC_DIR="${DIR}/decisions"
|
|
10
|
+
DEC_INDEX="${DEC_DIR}/index.md"
|
|
11
|
+
MOC_DIR="${DIR}/moc"
|
|
12
|
+
MOC_INDEX="${MOC_DIR}/index.md"
|
|
13
|
+
|
|
14
|
+
mkdir -p "$DIR" "$DEC_DIR" "$MOC_DIR"
|
|
15
|
+
|
|
16
|
+
fm_get() {
|
|
17
|
+
# fm_get <file> <key>
|
|
18
|
+
awk -v k="$2" '
|
|
19
|
+
/^---$/ { fm = !fm; next }
|
|
20
|
+
fm {
|
|
21
|
+
if (match($0, "^" k ":")) {
|
|
22
|
+
sub("^" k ":[[:space:]]*", ""); print; exit
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
' "$1"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
list_topics() {
|
|
29
|
+
find "$DIR" -maxdepth 1 -type f -name "*.md" ! -name "index.md" 2>/dev/null | sort
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
list_decisions() {
|
|
33
|
+
find "$DEC_DIR" -maxdepth 1 -type f -name "*.md" ! -name "index.md" 2>/dev/null | sort
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
list_mocs() {
|
|
37
|
+
find "$MOC_DIR" -maxdepth 1 -type f -name "*.md" ! -name "index.md" 2>/dev/null | sort
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# ---- root index ----
|
|
41
|
+
{
|
|
42
|
+
echo "# Research Index"
|
|
43
|
+
echo
|
|
44
|
+
echo "_Auto-generated by \`.claude/skills/research/scripts/update-index.sh\`. Do not edit by hand._"
|
|
45
|
+
echo
|
|
46
|
+
echo "## Topics"
|
|
47
|
+
echo
|
|
48
|
+
echo "| Topic | Date | Bucket | Status | Confidence | Sources |"
|
|
49
|
+
echo "|-------|------|--------|--------|------------|---------|"
|
|
50
|
+
for f in $(list_topics); do
|
|
51
|
+
SLUG=$(basename "$f" .md)
|
|
52
|
+
DATE=$(fm_get "$f" date); [ -z "$DATE" ] && DATE="—"
|
|
53
|
+
BUCKET=$(fm_get "$f" content_type_bucket); [ -z "$BUCKET" ] && BUCKET="—"
|
|
54
|
+
STATUS=$(fm_get "$f" freshness); [ -z "$STATUS" ] && STATUS="—"
|
|
55
|
+
CONF=$(fm_get "$f" confidence_summary); [ -z "$CONF" ] && CONF="—"
|
|
56
|
+
SRC=$(fm_get "$f" sources_count); [ -z "$SRC" ] && SRC="—"
|
|
57
|
+
echo "| [${SLUG}](./${SLUG}.md) | ${DATE} | ${BUCKET} | ${STATUS} | ${CONF} | ${SRC} |"
|
|
58
|
+
done
|
|
59
|
+
echo
|
|
60
|
+
echo "## Decisions (ADRs)"
|
|
61
|
+
echo
|
|
62
|
+
echo "| ADR | Date | Status |"
|
|
63
|
+
echo "|-----|------|--------|"
|
|
64
|
+
for f in $(list_decisions); do
|
|
65
|
+
SLUG=$(basename "$f" .md)
|
|
66
|
+
DATE=$(fm_get "$f" date); [ -z "$DATE" ] && DATE="—"
|
|
67
|
+
STAT=$(fm_get "$f" status); [ -z "$STAT" ] && STAT="—"
|
|
68
|
+
echo "| [${SLUG}](./decisions/${SLUG}.md) | ${DATE} | ${STAT} |"
|
|
69
|
+
done
|
|
70
|
+
echo
|
|
71
|
+
echo "## Maps of Content"
|
|
72
|
+
echo
|
|
73
|
+
for f in $(list_mocs); do
|
|
74
|
+
SLUG=$(basename "$f" .md)
|
|
75
|
+
echo "- [${SLUG}](./moc/${SLUG}.md)"
|
|
76
|
+
done
|
|
77
|
+
} > "$INDEX"
|
|
78
|
+
|
|
79
|
+
# ---- decisions index ----
|
|
80
|
+
{
|
|
81
|
+
echo "# Architecture Decision Records"
|
|
82
|
+
echo
|
|
83
|
+
echo "_Auto-generated. Format: Nygard 2011._"
|
|
84
|
+
echo
|
|
85
|
+
for f in $(list_decisions); do
|
|
86
|
+
SLUG=$(basename "$f" .md)
|
|
87
|
+
DATE=$(fm_get "$f" date); [ -z "$DATE" ] && DATE="—"
|
|
88
|
+
STAT=$(fm_get "$f" status); [ -z "$STAT" ] && STAT="—"
|
|
89
|
+
TITLE=$(fm_get "$f" title); [ -z "$TITLE" ] && TITLE="$SLUG"
|
|
90
|
+
echo "- **[${SLUG}](./${SLUG}.md)** — ${TITLE} _(${DATE} · ${STAT})_"
|
|
91
|
+
done
|
|
92
|
+
} > "$DEC_INDEX"
|
|
93
|
+
|
|
94
|
+
# ---- moc index ----
|
|
95
|
+
{
|
|
96
|
+
echo "# Maps of Content"
|
|
97
|
+
echo
|
|
98
|
+
for f in $(list_mocs); do
|
|
99
|
+
SLUG=$(basename "$f" .md)
|
|
100
|
+
echo "- [${SLUG}](./${SLUG}.md)"
|
|
101
|
+
done
|
|
102
|
+
} > "$MOC_INDEX"
|
|
103
|
+
|
|
104
|
+
echo "updated: $INDEX"
|
|
105
|
+
echo "updated: $DEC_INDEX"
|
|
106
|
+
echo "updated: $MOC_INDEX"
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# verify-citations.sh — anti-hallucination gate.
|
|
3
|
+
# Reads a rendered research doc + the session sources.jsonl/claims.jsonl,
|
|
4
|
+
# verifies every citation: HTTP 200, quote greppable in cached snapshot,
|
|
5
|
+
# DOI resolvable in Crossref. Emits JSON array to stdout. Exits non-zero
|
|
6
|
+
# on any FAIL verdict.
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# verify-citations.sh <doc.md> <session_dir>
|
|
10
|
+
#
|
|
11
|
+
# Dependencies: bash, jq, curl, grep. All present on dev/CI defaults.
|
|
12
|
+
set -euo pipefail
|
|
13
|
+
|
|
14
|
+
DOC="${1:?usage: verify-citations.sh <doc.md> <session_dir>}"
|
|
15
|
+
SESSION_DIR="${2:?usage: verify-citations.sh <doc.md> <session_dir>}"
|
|
16
|
+
|
|
17
|
+
[ -f "$DOC" ] || { echo "doc not found: $DOC" >&2; exit 2; }
|
|
18
|
+
[ -d "$SESSION_DIR" ] || { echo "session dir not found: $SESSION_DIR" >&2; exit 2; }
|
|
19
|
+
|
|
20
|
+
SOURCES="${SESSION_DIR}/sources.jsonl"
|
|
21
|
+
CLAIMS="${SESSION_DIR}/claims.jsonl"
|
|
22
|
+
[ -f "$SOURCES" ] || { echo "missing sources.jsonl" >&2; exit 2; }
|
|
23
|
+
[ -f "$CLAIMS" ] || { echo "missing claims.jsonl" >&2; exit 2; }
|
|
24
|
+
|
|
25
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
26
|
+
echo "jq is required" >&2; exit 2
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
FAIL_COUNT=0
|
|
30
|
+
RESULTS=()
|
|
31
|
+
|
|
32
|
+
# Iterate every claim
|
|
33
|
+
while IFS= read -r CLAIM_JSON; do
|
|
34
|
+
[ -z "$CLAIM_JSON" ] && continue
|
|
35
|
+
CID=$(echo "$CLAIM_JSON" | jq -r '.id')
|
|
36
|
+
SID=$(echo "$CLAIM_JSON" | jq -r '.source_id')
|
|
37
|
+
QUOTE=$(echo "$CLAIM_JSON" | jq -r '.quote')
|
|
38
|
+
|
|
39
|
+
SRC=$(grep -F "\"id\":\"$SID\"" "$SOURCES" || true)
|
|
40
|
+
if [ -z "$SRC" ]; then
|
|
41
|
+
RESULTS+=("$(jq -nc --arg cid "$CID" --arg sid "$SID" \
|
|
42
|
+
'{citation_id:$cid, source_id:$sid, url_status:"missing-source", quote_match:false, doi_status:null, verdict:"fail"}')")
|
|
43
|
+
FAIL_COUNT=$((FAIL_COUNT+1)); continue
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
URL=$(echo "$SRC" | jq -r '.url // empty')
|
|
47
|
+
DOI=$(echo "$SRC" | jq -r '.doi // empty')
|
|
48
|
+
SNAP=$(echo "$SRC" | jq -r '.snapshot_path // empty')
|
|
49
|
+
|
|
50
|
+
# 1. URL reachability (HEAD, then GET if HEAD denied)
|
|
51
|
+
URL_STATUS="unknown"
|
|
52
|
+
if [ -n "$URL" ]; then
|
|
53
|
+
CODE=$(curl -fsSL -o /dev/null -w "%{http_code}" --max-time 12 -I "$URL" 2>/dev/null || echo "000")
|
|
54
|
+
if [ "$CODE" = "405" ] || [ "$CODE" = "403" ] || [ "$CODE" = "000" ]; then
|
|
55
|
+
CODE=$(curl -fsSL -o /dev/null -w "%{http_code}" --max-time 12 "$URL" 2>/dev/null || echo "000")
|
|
56
|
+
fi
|
|
57
|
+
URL_STATUS="$CODE"
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
# 2. DOI Crossref check
|
|
61
|
+
DOI_STATUS="n/a"
|
|
62
|
+
if [ -n "$DOI" ]; then
|
|
63
|
+
DOI_CODE=$(curl -fsSL -o /dev/null -w "%{http_code}" --max-time 12 \
|
|
64
|
+
"https://api.crossref.org/works/${DOI}" 2>/dev/null || echo "000")
|
|
65
|
+
DOI_STATUS="$DOI_CODE"
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
# 3. Quote-grep against snapshot
|
|
69
|
+
QUOTE_MATCH="false"
|
|
70
|
+
if [ -n "$SNAP" ] && [ -f "${CLAUDE_PROJECT_DIR:-.}/$SNAP" ]; then
|
|
71
|
+
if grep -qF -- "$QUOTE" "${CLAUDE_PROJECT_DIR:-.}/$SNAP"; then
|
|
72
|
+
QUOTE_MATCH="true"
|
|
73
|
+
else
|
|
74
|
+
# try whitespace-collapsed match
|
|
75
|
+
NEEDLE=$(echo "$QUOTE" | tr -s '[:space:]' ' ')
|
|
76
|
+
HAYSTACK=$(tr -s '[:space:]' ' ' < "${CLAUDE_PROJECT_DIR:-.}/$SNAP")
|
|
77
|
+
if echo "$HAYSTACK" | grep -qF -- "$NEEDLE"; then QUOTE_MATCH="true"; fi
|
|
78
|
+
fi
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
# 4. Verdict
|
|
82
|
+
VERDICT="pass"
|
|
83
|
+
if [ "$QUOTE_MATCH" = "false" ]; then VERDICT="fail"; fi
|
|
84
|
+
if [ -n "$DOI" ] && [ "$DOI_STATUS" != "200" ]; then VERDICT="fail"; fi
|
|
85
|
+
if [ -z "$DOI" ] && [ "$URL_STATUS" != "200" ] && [ "$URL_STATUS" != "301" ] && [ "$URL_STATUS" != "302" ]; then
|
|
86
|
+
if [ "$VERDICT" = "pass" ] && [ "$QUOTE_MATCH" = "true" ]; then VERDICT="stale"; else VERDICT="fail"; fi
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
[ "$VERDICT" = "fail" ] && FAIL_COUNT=$((FAIL_COUNT+1))
|
|
90
|
+
|
|
91
|
+
RESULTS+=("$(jq -nc \
|
|
92
|
+
--arg cid "$CID" --arg sid "$SID" \
|
|
93
|
+
--arg url "$URL_STATUS" --argjson qm "$QUOTE_MATCH" \
|
|
94
|
+
--arg doi "$DOI_STATUS" --arg verdict "$VERDICT" \
|
|
95
|
+
'{citation_id:$cid, source_id:$sid, url_status:$url, quote_match:$qm, doi_status:$doi, verdict:$verdict}')")
|
|
96
|
+
done < "$CLAIMS"
|
|
97
|
+
|
|
98
|
+
# Emit array
|
|
99
|
+
printf '['
|
|
100
|
+
FIRST=1
|
|
101
|
+
for R in "${RESULTS[@]}"; do
|
|
102
|
+
if [ $FIRST -eq 1 ]; then FIRST=0; else printf ','; fi
|
|
103
|
+
printf '%s' "$R"
|
|
104
|
+
done
|
|
105
|
+
printf ']\n'
|
|
106
|
+
|
|
107
|
+
[ "$FAIL_COUNT" -eq 0 ]
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "{{TITLE}}"
|
|
3
|
+
adr_number: {{NNNN}}
|
|
4
|
+
date: "{{DATE_YYYY_MM_DD}}"
|
|
5
|
+
status: "{{STATUS}}" # proposed | accepted | superseded-by-NNNN | deprecated | rejected
|
|
6
|
+
deciders: [{{DECIDERS}}]
|
|
7
|
+
related_research: "{{RESEARCH_DOC_PATH}}"
|
|
8
|
+
session_id: "{{SESSION_ID}}"
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# ADR-{{NNNN}}: {{TITLE}}
|
|
12
|
+
|
|
13
|
+
_Format: Michael Nygard (2011), "Documenting Architecture Decisions"._
|
|
14
|
+
|
|
15
|
+
## Status
|
|
16
|
+
|
|
17
|
+
{{STATUS}}
|
|
18
|
+
|
|
19
|
+
## Context
|
|
20
|
+
|
|
21
|
+
{{CONTEXT}}
|
|
22
|
+
|
|
23
|
+
## Decision
|
|
24
|
+
|
|
25
|
+
{{DECISION}}
|
|
26
|
+
|
|
27
|
+
## Consequences
|
|
28
|
+
|
|
29
|
+
### Positive
|
|
30
|
+
|
|
31
|
+
{{#each POSITIVE}}
|
|
32
|
+
- {{TEXT}}
|
|
33
|
+
{{/each}}
|
|
34
|
+
|
|
35
|
+
### Negative
|
|
36
|
+
|
|
37
|
+
{{#each NEGATIVE}}
|
|
38
|
+
- {{TEXT}}
|
|
39
|
+
{{/each}}
|
|
40
|
+
|
|
41
|
+
### Neutral
|
|
42
|
+
|
|
43
|
+
{{#each NEUTRAL}}
|
|
44
|
+
- {{TEXT}}
|
|
45
|
+
{{/each}}
|
|
46
|
+
|
|
47
|
+
## Alternatives Considered
|
|
48
|
+
|
|
49
|
+
{{#each ALTERNATIVE}}
|
|
50
|
+
### {{NAME}}
|
|
51
|
+
|
|
52
|
+
- **Why considered:** {{WHY}}
|
|
53
|
+
- **Why rejected:** {{WHY_NOT}}
|
|
54
|
+
{{/each}}
|
|
55
|
+
|
|
56
|
+
## Reversibility
|
|
57
|
+
|
|
58
|
+
- **Class:** {{REVERSIBILITY_CLASS}} <!-- one-way-door | two-way-door (Bezos) -->
|
|
59
|
+
- **Cost to reverse:** {{REVERSE_COST}}
|
|
60
|
+
- **Trigger to reconsider:** {{REVERSE_TRIGGER}}
|
|
61
|
+
|
|
62
|
+
## References
|
|
63
|
+
|
|
64
|
+
- Research doc: [{{RESEARCH_DOC_PATH}}](../{{RESEARCH_DOC_PATH}})
|
|
65
|
+
- Session evidence: `docs/research/.cache/sessions/{{SESSION_ID}}/`
|
|
66
|
+
- Nygard 2011 — https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Research Index
|
|
2
|
+
|
|
3
|
+
_Auto-generated by `.claude/skills/research/scripts/update-index.sh`. Do not edit by hand._
|
|
4
|
+
|
|
5
|
+
## Topics
|
|
6
|
+
|
|
7
|
+
| Topic | Date | Bucket | Status | Confidence | Sources |
|
|
8
|
+
|-------|------|--------|--------|------------|---------|
|
|
9
|
+
{{#each TOPIC}}
|
|
10
|
+
| [{{SLUG}}](./{{SLUG}}.md) | {{DATE}} | {{BUCKET}} | {{FRESHNESS}} | {{CONFIDENCE}} | {{SOURCES_COUNT}} |
|
|
11
|
+
{{/each}}
|
|
12
|
+
|
|
13
|
+
## Decisions (ADRs)
|
|
14
|
+
|
|
15
|
+
| ADR | Date | Status |
|
|
16
|
+
|-----|------|--------|
|
|
17
|
+
{{#each ADR}}
|
|
18
|
+
| [{{NNNN}}-{{SLUG}}](./decisions/{{NNNN}}-{{SLUG}}.md) | {{DATE}} | {{STATUS}} |
|
|
19
|
+
{{/each}}
|
|
20
|
+
|
|
21
|
+
## Maps of Content
|
|
22
|
+
|
|
23
|
+
{{#each MOC}}
|
|
24
|
+
- [{{TITLE}}](./moc/{{SLUG}}.md)
|
|
25
|
+
{{/each}}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "{{THEME_TITLE}}"
|
|
3
|
+
type: moc
|
|
4
|
+
date: "{{DATE_YYYY_MM_DD}}"
|
|
5
|
+
theme: "{{THEME_SLUG}}"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# MOC — {{THEME_TITLE}}
|
|
9
|
+
|
|
10
|
+
_Map of Content (Nick Milo, "Linking Your Thinking"). A curated entry
|
|
11
|
+
point that links related research docs around a theme._
|
|
12
|
+
|
|
13
|
+
## Overview
|
|
14
|
+
|
|
15
|
+
{{OVERVIEW}}
|
|
16
|
+
|
|
17
|
+
## Topics in this map
|
|
18
|
+
|
|
19
|
+
{{#each TOPIC}}
|
|
20
|
+
- [{{TITLE}}](../{{SLUG}}.md) — {{ONE_LINER}}
|
|
21
|
+
{{/each}}
|
|
22
|
+
|
|
23
|
+
## ADRs in this map
|
|
24
|
+
|
|
25
|
+
{{#each ADR}}
|
|
26
|
+
- [ADR-{{NNNN}}: {{TITLE}}](../decisions/{{NNNN}}-{{SLUG}}.md)
|
|
27
|
+
{{/each}}
|
|
28
|
+
|
|
29
|
+
## Recurring concepts
|
|
30
|
+
|
|
31
|
+
{{#each CONCEPT}}
|
|
32
|
+
- **{{CONCEPT_NAME}}** — appears in: {{IN_DOCS}}
|
|
33
|
+
{{/each}}
|
|
34
|
+
|
|
35
|
+
## Open questions across topics
|
|
36
|
+
|
|
37
|
+
{{#each OPEN_Q}}
|
|
38
|
+
- {{TEXT}}
|
|
39
|
+
{{/each}}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://hakutaku.dev/schema/research-state-0.1.0.json",
|
|
4
|
+
"title": "research-state JSONL entry",
|
|
5
|
+
"description": "One JSON line per research run appended to docs/research/.research-state.jsonl",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["topic_slug", "ts", "verdict"],
|
|
8
|
+
"additionalProperties": true,
|
|
9
|
+
"properties": {
|
|
10
|
+
"topic_slug": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"pattern": "^[a-z0-9][a-z0-9-]{1,59}$",
|
|
13
|
+
"description": "Kebab-case slug; matches /docs/research/<slug>.md filename."
|
|
14
|
+
},
|
|
15
|
+
"ts": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"format": "date-time",
|
|
18
|
+
"description": "UTC ISO-8601 timestamp of run completion."
|
|
19
|
+
},
|
|
20
|
+
"session_id": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "Session directory name under docs/research/.cache/sessions/"
|
|
23
|
+
},
|
|
24
|
+
"verdict": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"enum": ["pass", "pass-with-warnings", "fail", "abort", "reuse"]
|
|
27
|
+
},
|
|
28
|
+
"content_type_bucket": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"enum": ["fast", "medium", "slow", "permanent", "unknown"]
|
|
31
|
+
},
|
|
32
|
+
"freshness_status": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"enum": ["fresh", "aging", "stale", "outdated", "missing"]
|
|
35
|
+
},
|
|
36
|
+
"playbook": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"enum": [
|
|
39
|
+
"ux-design",
|
|
40
|
+
"library-evaluation",
|
|
41
|
+
"api-integration",
|
|
42
|
+
"architectural-decision",
|
|
43
|
+
"market-competitive",
|
|
44
|
+
"academic-literature",
|
|
45
|
+
"news-current-events",
|
|
46
|
+
"security",
|
|
47
|
+
"pricing-cost",
|
|
48
|
+
"other"
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
"domain": { "type": "string" },
|
|
52
|
+
"lang": { "type": "string", "default": "en" },
|
|
53
|
+
"queries_used": { "type": "integer", "minimum": 0 },
|
|
54
|
+
"sources_cited": { "type": "integer", "minimum": 0 },
|
|
55
|
+
"findings_count": { "type": "integer", "minimum": 0 },
|
|
56
|
+
"disagreements_count": { "type": "integer", "minimum": 0 },
|
|
57
|
+
"verify_pass": { "type": "integer", "minimum": 0 },
|
|
58
|
+
"verify_stale": { "type": "integer", "minimum": 0 },
|
|
59
|
+
"verify_fail": { "type": "integer", "minimum": 0 },
|
|
60
|
+
"duration_seconds": { "type": "number" },
|
|
61
|
+
"doc_path": { "type": "string" },
|
|
62
|
+
"adr_path": { "type": ["string", "null"] }
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "{{TITLE}}"
|
|
3
|
+
slug: "{{SLUG}}"
|
|
4
|
+
date: "{{DATE_YYYY_MM_DD}}"
|
|
5
|
+
lang: "{{LANG}}"
|
|
6
|
+
content_type_bucket: "{{BUCKET}}" # fast | medium | slow | permanent
|
|
7
|
+
freshness: "{{FRESHNESS}}" # fresh | aging | stale | outdated
|
|
8
|
+
freshness_window_days: {{WINDOW_DAYS}}
|
|
9
|
+
playbook: "{{PLAYBOOK}}"
|
|
10
|
+
domain: "{{DOMAIN}}"
|
|
11
|
+
sources_count: {{SOURCES_COUNT}}
|
|
12
|
+
findings_count: {{FINDINGS_COUNT}}
|
|
13
|
+
disagreements_count: {{DISAGREEMENTS_COUNT}}
|
|
14
|
+
open_questions_count: {{OPEN_Q_COUNT}}
|
|
15
|
+
confidence_summary: "{{CONFIDENCE_SUMMARY}}" # e.g. "5 high · 3 medium · 1 low"
|
|
16
|
+
concepts:
|
|
17
|
+
{{CONCEPTS_YAML_LIST}}
|
|
18
|
+
session_id: "{{SESSION_ID}}"
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
# Research: {{TITLE}}
|
|
22
|
+
|
|
23
|
+
> Bucket: **{{BUCKET}}** · Status: **{{FRESHNESS}}** · Confidence: {{CONFIDENCE_SUMMARY}}
|
|
24
|
+
> Session: `docs/research/.cache/sessions/{{SESSION_ID}}/`
|
|
25
|
+
|
|
26
|
+
## Executive summary
|
|
27
|
+
|
|
28
|
+
{{EXEC_SUMMARY}}
|
|
29
|
+
|
|
30
|
+
## Question
|
|
31
|
+
|
|
32
|
+
{{ORIGINAL_QUESTION}}
|
|
33
|
+
|
|
34
|
+
## Ontology Map
|
|
35
|
+
|
|
36
|
+
Concepts and their relationships using the SKOS-adapted vocabulary
|
|
37
|
+
(see `.claude/skills/research/references/ontology-patterns.md`).
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
{{ONTOLOGY_RELATIONS}}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Findings
|
|
44
|
+
|
|
45
|
+
{{#each FINDING}}
|
|
46
|
+
### Finding {{ID}} — {{TITLE}}
|
|
47
|
+
|
|
48
|
+
{{ASSERTION}}
|
|
49
|
+
|
|
50
|
+
**Confidence:** {{CONFIDENCE}}{{#if FRESHNESS_WARNING}} · _Freshness warning: {{FRESHNESS_WARNING}}_{{/if}}{{#if TRIANGULATION_WARNING}} · _Triangulation: {{TRIANGULATION_WARNING}}_{{/if}}
|
|
51
|
+
|
|
52
|
+
Evidence:
|
|
53
|
+
|
|
54
|
+
{{#each EVIDENCE}}
|
|
55
|
+
> "{{QUOTE}}" [{{SOURCE_ID}}]
|
|
56
|
+
> URL: {{URL}}
|
|
57
|
+
> Accessed: {{ACCESSED_AT}}
|
|
58
|
+
> Verify: {{VERIFY_METHOD}}
|
|
59
|
+
{{/each}}
|
|
60
|
+
|
|
61
|
+
{{/each}}
|
|
62
|
+
|
|
63
|
+
## Disagreements
|
|
64
|
+
|
|
65
|
+
{{#each DISAGREEMENT}}
|
|
66
|
+
### {{TOPIC}}
|
|
67
|
+
|
|
68
|
+
- **Position A** ([{{SRC_A}}]): {{POSITION_A}}
|
|
69
|
+
- **Position B** ([{{SRC_B}}]): {{POSITION_B}}
|
|
70
|
+
- **Resolution requires:** {{RESOLUTION_HINT}}
|
|
71
|
+
{{/each}}
|
|
72
|
+
|
|
73
|
+
## Recommendations
|
|
74
|
+
|
|
75
|
+
### DO
|
|
76
|
+
|
|
77
|
+
{{#each RECOMMENDATION_DO}}
|
|
78
|
+
- {{TEXT}} — _{{REASON}}_
|
|
79
|
+
{{/each}}
|
|
80
|
+
|
|
81
|
+
### AVOID
|
|
82
|
+
|
|
83
|
+
{{#each RECOMMENDATION_AVOID}}
|
|
84
|
+
- {{TEXT}} — _{{REASON}}_
|
|
85
|
+
{{/each}}
|
|
86
|
+
|
|
87
|
+
## Implementation Path
|
|
88
|
+
|
|
89
|
+
{{#each STEP}}
|
|
90
|
+
{{N}}. {{TEXT}}
|
|
91
|
+
{{/each}}
|
|
92
|
+
|
|
93
|
+
## Open Questions
|
|
94
|
+
|
|
95
|
+
{{#each OPEN_Q}}
|
|
96
|
+
- {{TEXT}}
|
|
97
|
+
{{/each}}
|
|
98
|
+
|
|
99
|
+
## Dead Ends
|
|
100
|
+
|
|
101
|
+
_Searched but not found / not applicable_
|
|
102
|
+
|
|
103
|
+
{{#each DEAD_END}}
|
|
104
|
+
- {{TEXT}}
|
|
105
|
+
{{/each}}
|
|
106
|
+
|
|
107
|
+
## Sources
|
|
108
|
+
|
|
109
|
+
| ID | Title | Publisher | Authority (1-5) | Independence | Accessed | URL |
|
|
110
|
+
|----|-------|-----------|-----------------|--------------|----------|-----|
|
|
111
|
+
{{#each SOURCE}}
|
|
112
|
+
| {{ID}} | {{TITLE}} | {{PUBLISHER}} | {{AUTHORITY_LEVEL}} | {{INDEPENDENCE}} | {{ACCESSED_AT}} | {{URL}} |
|
|
113
|
+
{{/each}}
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
_Generated by the `research` skill. Pipeline: scout → query → synthesize → verify. Verify status: {{VERIFY_STATUS}}._
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: research-web
|
|
3
|
-
description: "AUTOMATICALLY invoke BEFORE implementing any new feature or technology. Triggers: new feature, new technology, 'search', 'find info'. Web research specialist. PROACTIVELY searches for current solutions."
|
|
4
|
-
model: sonnet
|
|
5
|
-
color: cyan
|
|
6
|
-
tools: WebSearch, WebFetch, Read, Write, Glob, Grep
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Research Web Agent
|
|
10
|
-
|
|
11
|
-
Targeted web research for development decisions. Output goes to `/docs/research/`.
|
|
12
|
-
|
|
13
|
-
## Research Flow
|
|
14
|
-
|
|
15
|
-
```
|
|
16
|
-
1. Understand Question → Define problem + constraints
|
|
17
|
-
2. Check /docs/research/ → Reuse if fresh (<3 months)
|
|
18
|
-
3. Ontology Map → Identify concepts, relationships, constraints
|
|
19
|
-
4. Query (3-5 searches) → [topic] [aspect] [2025-2026] [context]
|
|
20
|
-
5. Triangulate → Same claim in 3+ independent sources
|
|
21
|
-
6. Structure → Ontology-based output (concepts → relationships → decisions)
|
|
22
|
-
7. Save → Write to /docs/research/[topic].md
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## Query Strategy
|
|
26
|
-
|
|
27
|
-
```
|
|
28
|
-
[technology] + [specific aspect] + [2025 OR 2026] + [project context]
|
|
29
|
-
|
|
30
|
-
Examples:
|
|
31
|
-
- "Playwright authentication 2026 best practices Next.js"
|
|
32
|
-
- "MongoDB aggregation pipeline patterns 2025-2026"
|
|
33
|
-
- "React Server Components data fetching 2026"
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
### Source Priority
|
|
37
|
-
|
|
38
|
-
1. Official documentation
|
|
39
|
-
2. GitHub issues/discussions
|
|
40
|
-
3. Stack Overflow (recent answers, 2025-2026)
|
|
41
|
-
4. Technical blogs (verified authors)
|
|
42
|
-
5. Conference talks/presentations
|
|
43
|
-
|
|
44
|
-
## UI/UX Research Flow (for UI tasks)
|
|
45
|
-
|
|
46
|
-
When research involves UI/UX features, follow this structured flow:
|
|
47
|
-
|
|
48
|
-
```
|
|
49
|
-
1. Competitor Analysis
|
|
50
|
-
- Identify 3-5 competitors solving same user problem
|
|
51
|
-
- Run heuristic evaluation (Nielsen's 10 heuristics)
|
|
52
|
-
- Score issues 0-4 by severity
|
|
53
|
-
|
|
54
|
-
2. Design System Check
|
|
55
|
-
- Check existing patterns (shadcn/ui, Radix, etc.)
|
|
56
|
-
- Map component to known pattern (Button, Dialog, Combobox)
|
|
57
|
-
- Cross-reference WCAG 2.1 for the component category
|
|
58
|
-
|
|
59
|
-
3. User Flow Mapping
|
|
60
|
-
- Define entry/exit points for the journey
|
|
61
|
-
- Map happy path + 2 error/edge-case paths
|
|
62
|
-
- Identify decision points needing UI affordances
|
|
63
|
-
|
|
64
|
-
4. Accessibility Audit
|
|
65
|
-
- Automated scan first (axe, Lighthouse)
|
|
66
|
-
- Manual keyboard navigation check
|
|
67
|
-
- Screen reader test plan (NVDA + VoiceOver)
|
|
68
|
-
- Color contrast AA minimum, AAA for body text
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
## Ontology-Based Structuring
|
|
72
|
-
|
|
73
|
-
Structure findings using relationships, not flat lists:
|
|
74
|
-
|
|
75
|
-
```
|
|
76
|
-
Concept → relationships → constraints → recommended-pattern → implementation-path
|
|
77
|
-
|
|
78
|
-
Example:
|
|
79
|
-
Button is-a InteractiveElement
|
|
80
|
-
Button has-a Label, Icon, LoadingState
|
|
81
|
-
Button depends-on AccessibilityRole (role="button")
|
|
82
|
-
Button constrained-by TouchTarget (min 44x44px mobile)
|
|
83
|
-
Button resolved-by shadcn/ui Button + CVA variants
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### Relationship Types
|
|
87
|
-
|
|
88
|
-
| Relationship | Meaning | Example |
|
|
89
|
-
|-------------|---------|---------|
|
|
90
|
-
| `is-a` | Inheritance/subtype | Dialog is-a Overlay |
|
|
91
|
-
| `has-a` | Composition | Form has-a ValidationSchema |
|
|
92
|
-
| `depends-on` | Dependency | AuthFlow depends-on SessionStore |
|
|
93
|
-
| `constrained-by` | Limitation | MobileNav constrained-by ViewportWidth |
|
|
94
|
-
| `resolved-by` | Implementation | DataFetch resolved-by TanStackQuery |
|
|
95
|
-
| `precedes` | Ordering | Research precedes Implementation |
|
|
96
|
-
|
|
97
|
-
## Output Format
|
|
98
|
-
|
|
99
|
-
Save to `/docs/research/[topic-kebab-case].md`:
|
|
100
|
-
|
|
101
|
-
```markdown
|
|
102
|
-
# Research: [Topic]
|
|
103
|
-
|
|
104
|
-
**Date:** YYYY-MM-DD
|
|
105
|
-
**Freshness:** fresh | aging | stale
|
|
106
|
-
**Stack:** [relevant tech]
|
|
107
|
-
|
|
108
|
-
## Problem
|
|
109
|
-
|
|
110
|
-
[1-2 sentences: what we're solving]
|
|
111
|
-
|
|
112
|
-
## Ontology Map
|
|
113
|
-
|
|
114
|
-
[Key concepts and their relationships using is-a, has-a, depends-on, constrained-by, resolved-by]
|
|
115
|
-
|
|
116
|
-
## Findings
|
|
117
|
-
|
|
118
|
-
### [Finding 1 Title]
|
|
119
|
-
**Source:** [URL] ([date])
|
|
120
|
-
**Relevance:** high | medium
|
|
121
|
-
|
|
122
|
-
[Concise summary + code example if applicable]
|
|
123
|
-
|
|
124
|
-
### [Finding 2 Title]
|
|
125
|
-
...
|
|
126
|
-
|
|
127
|
-
## Recommendations
|
|
128
|
-
|
|
129
|
-
### DO
|
|
130
|
-
1. [Best practice] — why
|
|
131
|
-
|
|
132
|
-
### AVOID
|
|
133
|
-
1. [Anti-pattern] — why
|
|
134
|
-
|
|
135
|
-
## Implementation Path
|
|
136
|
-
|
|
137
|
-
1. [Step 1]
|
|
138
|
-
2. [Step 2]
|
|
139
|
-
|
|
140
|
-
## Sources
|
|
141
|
-
|
|
142
|
-
| Title | URL | Date |
|
|
143
|
-
|-------|-----|------|
|
|
144
|
-
| ... | ... | ... |
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
## Freshness Rules
|
|
148
|
-
|
|
149
|
-
| Age | Status | Action |
|
|
150
|
-
|-----|--------|--------|
|
|
151
|
-
| < 3 months | Fresh | Use directly |
|
|
152
|
-
| 3-6 months | Aging | Verify still valid |
|
|
153
|
-
| 6-12 months | Stale | Update recommended |
|
|
154
|
-
| > 12 months | Outdated | Full re-research |
|
|
155
|
-
|
|
156
|
-
## Critical Rules
|
|
157
|
-
|
|
158
|
-
1. **CHECK /docs/research/ FIRST** — avoid duplicate research
|
|
159
|
-
2. **CITE SOURCES** — every finding needs a URL
|
|
160
|
-
3. **2025-2026 CONTENT** — prefer recent, flag anything older than 12 months
|
|
161
|
-
4. **TRIANGULATE** — same claim in 3+ sources before treating as truth
|
|
162
|
-
5. **ONTOLOGY STRUCTURE** — map concepts and relationships, not just flat summaries
|
|
163
|
-
6. **ACTIONABLE OUTPUT** — every finding must have an implementation path
|
|
164
|
-
7. **CONCISE** — bullet points over paragraphs, tables over prose
|