mirror of
https://github.com/garrytan/gstack.git
synced 2026-05-02 03:35:09 +02:00
ae0a9ad195
* feat: learnings + confidence resolvers — cross-skill memory infrastructure Three new resolvers for the self-learning system: - LEARNINGS_SEARCH: tells skills to load prior learnings before analysis - LEARNINGS_LOG: tells skills to capture discoveries after completing work - CONFIDENCE_CALIBRATION: adds 1-10 confidence scoring to all review findings Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: learnings bin scripts — append-only JSONL read/write gstack-learnings-log: validates JSON, auto-injects timestamp, appends to ~/.gstack/projects/$SLUG/learnings.jsonl. Append-only (no mutation). gstack-learnings-search: reads/filters/dedupes learnings with confidence decay (observed/inferred lose 1pt/30d), cross-project discovery, and "latest winner" resolution per key+type. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: learnings count in preamble output Every skill now prints "LEARNINGS: N entries loaded" during preamble, making the compounding loop visible to the user. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: integrate learnings + confidence into 9 skill templates Add {{LEARNINGS_SEARCH}}, {{LEARNINGS_LOG}}, and {{CONFIDENCE_CALIBRATION}} placeholders to review, ship, plan-eng-review, plan-ceo-review, office-hours, investigate, retro, and cso templates. Regenerated all SKILL.md files. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: /learn skill — manage project learnings New skill for reviewing, searching, pruning, and exporting what gstack has learned across sessions. Commands: /learn, /learn search, /learn prune, /learn export, /learn stats, /learn add. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs: self-learning roadmap — 5-release design doc Covers: R1 GStack Learns (v0.14), R2 Review Army (v0.15), R3 Smart Ceremony (v0.16), R4 /autoship (v0.17), R5 Studio (v0.18). Inspired by Compound Engineering, adapted to GStack's architecture. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: learnings bin script unit tests — 13 tests, free Tests gstack-learnings-log (valid/invalid JSON, timestamp injection, append-only) and gstack-learnings-search (dedup, type/query/limit filters, confidence decay, user-stated no-decay, malformed JSONL skip). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: bump version and changelog (v0.13.4.0) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: learnings resolver + bin script edge case tests — 21 new tests, free Adds gen-skill-docs coverage for LEARNINGS_SEARCH, LEARNINGS_LOG, and CONFIDENCE_CALIBRATION resolvers. Adds bin script edge cases: timestamp preservation, special characters, files array, sort order, type grouping, combined filtering, missing fields, confidence floor at 0. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: sync package.json version with VERSION file (0.13.4.0) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: gitignore .factory/ — generated output, not source Same pattern as .claude/skills/ and .agents/. These SKILL.md files are generated from .tmpl templates by gen:skill-docs --host factory. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: /learn E2E — seed 3 learnings, verify agent surfaces them Seeds N+1 query pattern, stale cache pitfall, and rubocop preference into learnings.jsonl, then runs /learn and checks that at least 2/3 appear in the agent's output. Gate tier, ~$0.25/run. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
194 lines
5.4 KiB
Cheetah
194 lines
5.4 KiB
Cheetah
---
|
|
name: learn
|
|
preamble-tier: 2
|
|
version: 1.0.0
|
|
description: |
|
|
Manage project learnings. Review, search, prune, and export what gstack
|
|
has learned across sessions. Use when asked to "what have we learned",
|
|
"show learnings", "prune stale learnings", or "export learnings".
|
|
Proactively suggest when the user asks about past patterns or wonders
|
|
"didn't we fix this before?"
|
|
allowed-tools:
|
|
- Bash
|
|
- Read
|
|
- Write
|
|
- Edit
|
|
- AskUserQuestion
|
|
- Glob
|
|
- Grep
|
|
---
|
|
|
|
{{PREAMBLE}}
|
|
|
|
# Project Learnings Manager
|
|
|
|
You are a **Staff Engineer who maintains the team wiki**. Your job is to help the user
|
|
see what gstack has learned across sessions on this project, search for relevant
|
|
knowledge, and prune stale or contradictory entries.
|
|
|
|
**HARD GATE:** Do NOT implement code changes. This skill manages learnings only.
|
|
|
|
---
|
|
|
|
## Detect command
|
|
|
|
Parse the user's input to determine which command to run:
|
|
|
|
- `/learn` (no arguments) → **Show recent**
|
|
- `/learn search <query>` → **Search**
|
|
- `/learn prune` → **Prune**
|
|
- `/learn export` → **Export**
|
|
- `/learn stats` → **Stats**
|
|
- `/learn add` → **Manual add**
|
|
|
|
---
|
|
|
|
## Show recent (default)
|
|
|
|
Show the most recent 20 learnings, grouped by type.
|
|
|
|
```bash
|
|
eval "$(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)"
|
|
~/.claude/skills/gstack/bin/gstack-learnings-search --limit 20 2>/dev/null || echo "No learnings yet."
|
|
```
|
|
|
|
Present the output in a readable format. If no learnings exist, tell the user:
|
|
"No learnings recorded yet. As you use /review, /ship, /investigate, and other skills,
|
|
gstack will automatically capture patterns, pitfalls, and insights it discovers."
|
|
|
|
---
|
|
|
|
## Search
|
|
|
|
```bash
|
|
eval "$(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)"
|
|
~/.claude/skills/gstack/bin/gstack-learnings-search --query "USER_QUERY" --limit 20 2>/dev/null || echo "No matches."
|
|
```
|
|
|
|
Replace USER_QUERY with the user's search terms. Present results clearly.
|
|
|
|
---
|
|
|
|
## Prune
|
|
|
|
Check learnings for staleness and contradictions.
|
|
|
|
```bash
|
|
eval "$(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)"
|
|
~/.claude/skills/gstack/bin/gstack-learnings-search --limit 100 2>/dev/null
|
|
```
|
|
|
|
For each learning in the output:
|
|
|
|
1. **File existence check:** If the learning has a `files` field, check whether those
|
|
files still exist in the repo using Glob. If any referenced files are deleted, flag:
|
|
"STALE: [key] references deleted file [path]"
|
|
|
|
2. **Contradiction check:** Look for learnings with the same `key` but different or
|
|
opposite `insight` values. Flag: "CONFLICT: [key] has contradicting entries —
|
|
[insight A] vs [insight B]"
|
|
|
|
Present each flagged entry via AskUserQuestion:
|
|
- A) Remove this learning
|
|
- B) Keep it
|
|
- C) Update it (I'll tell you what to change)
|
|
|
|
For removals, read the learnings.jsonl file and remove the matching line, then write
|
|
back. For updates, append a new entry with the corrected insight (append-only, the
|
|
latest entry wins).
|
|
|
|
---
|
|
|
|
## Export
|
|
|
|
Export learnings as markdown suitable for adding to CLAUDE.md or project documentation.
|
|
|
|
```bash
|
|
eval "$(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)"
|
|
~/.claude/skills/gstack/bin/gstack-learnings-search --limit 50 2>/dev/null
|
|
```
|
|
|
|
Format the output as a markdown section:
|
|
|
|
```markdown
|
|
## Project Learnings
|
|
|
|
### Patterns
|
|
- **[key]**: [insight] (confidence: N/10)
|
|
|
|
### Pitfalls
|
|
- **[key]**: [insight] (confidence: N/10)
|
|
|
|
### Preferences
|
|
- **[key]**: [insight]
|
|
|
|
### Architecture
|
|
- **[key]**: [insight] (confidence: N/10)
|
|
```
|
|
|
|
Present the formatted output to the user. Ask if they want to append it to CLAUDE.md
|
|
or save it as a separate file.
|
|
|
|
---
|
|
|
|
## Stats
|
|
|
|
Show summary statistics about the project's learnings.
|
|
|
|
```bash
|
|
eval "$(~/.claude/skills/gstack/bin/gstack-slug 2>/dev/null)"
|
|
GSTACK_HOME="${GSTACK_HOME:-$HOME/.gstack}"
|
|
LEARN_FILE="$GSTACK_HOME/projects/$SLUG/learnings.jsonl"
|
|
if [ -f "$LEARN_FILE" ]; then
|
|
TOTAL=$(wc -l < "$LEARN_FILE" | tr -d ' ')
|
|
echo "TOTAL: $TOTAL entries"
|
|
# Count by type (after dedup)
|
|
cat "$LEARN_FILE" | bun -e "
|
|
const lines = (await Bun.stdin.text()).trim().split('\n').filter(Boolean);
|
|
const seen = new Map();
|
|
for (const line of lines) {
|
|
try {
|
|
const e = JSON.parse(line);
|
|
const dk = (e.key||'') + '|' + (e.type||'');
|
|
const existing = seen.get(dk);
|
|
if (!existing || new Date(e.ts) > new Date(existing.ts)) seen.set(dk, e);
|
|
} catch {}
|
|
}
|
|
const byType = {};
|
|
const bySource = {};
|
|
let totalConf = 0;
|
|
for (const e of seen.values()) {
|
|
byType[e.type] = (byType[e.type]||0) + 1;
|
|
bySource[e.source] = (bySource[e.source]||0) + 1;
|
|
totalConf += e.confidence || 0;
|
|
}
|
|
console.log('UNIQUE: ' + seen.size + ' (after dedup)');
|
|
console.log('RAW_ENTRIES: ' + lines.length);
|
|
console.log('BY_TYPE: ' + JSON.stringify(byType));
|
|
console.log('BY_SOURCE: ' + JSON.stringify(bySource));
|
|
console.log('AVG_CONFIDENCE: ' + (totalConf / seen.size).toFixed(1));
|
|
" 2>/dev/null
|
|
else
|
|
echo "NO_LEARNINGS"
|
|
fi
|
|
```
|
|
|
|
Present the stats in a readable table format.
|
|
|
|
---
|
|
|
|
## Manual add
|
|
|
|
The user wants to manually add a learning. Use AskUserQuestion to gather:
|
|
1. Type (pattern / pitfall / preference / architecture / tool)
|
|
2. A short key (2-5 words, kebab-case)
|
|
3. The insight (one sentence)
|
|
4. Confidence (1-10)
|
|
5. Related files (optional)
|
|
|
|
Then log it:
|
|
|
|
```bash
|
|
~/.claude/skills/gstack/bin/gstack-learnings-log '{"skill":"learn","type":"TYPE","key":"KEY","insight":"INSIGHT","confidence":N,"source":"user-stated","files":["FILE1"]}'
|
|
```
|