@eric0117/agentforge 0.1.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/LICENSE +21 -0
- package/README.md +275 -0
- package/dist/add-agent.js +145 -0
- package/dist/add-skill.js +185 -0
- package/dist/agent-prompt.js +211 -0
- package/dist/agentforge-config.js +106 -0
- package/dist/agents/claude.js +46 -0
- package/dist/agents/codex.js +67 -0
- package/dist/agents/cursor.js +54 -0
- package/dist/agents/index.js +15 -0
- package/dist/agents/io.js +252 -0
- package/dist/agents/types.js +1 -0
- package/dist/cli.js +374 -0
- package/dist/confirm.js +20 -0
- package/dist/doctor.js +223 -0
- package/dist/enter.js +85 -0
- package/dist/init.js +272 -0
- package/dist/lang-prompt.js +88 -0
- package/dist/list-skills.js +120 -0
- package/dist/logo.js +181 -0
- package/dist/path-prompt.js +148 -0
- package/dist/remove-agent.js +63 -0
- package/dist/remove-skill.js +88 -0
- package/dist/rename.js +222 -0
- package/dist/skill-prompt.js +199 -0
- package/dist/skills-data.js +727 -0
- package/dist/sync-skills.js +59 -0
- package/dist/templates/CLAUDE.md.tpl +141 -0
- package/dist/templates/context-handoff.SKILL.md.tpl +222 -0
- package/dist/templates/cross-repo-impact.SKILL.md.tpl +241 -0
- package/dist/templates/feature-retro.SKILL.md.tpl +312 -0
- package/dist/templates/feature-start.SKILL.md.tpl +631 -0
- package/dist/templates/history.SKILL.md.tpl +165 -0
- package/dist/templates/incident-context.SKILL.md.tpl +260 -0
- package/dist/templates/pr-create.SKILL.md.tpl +403 -0
- package/dist/templates/pr-review-analyze.SKILL.md.tpl +303 -0
- package/dist/templates/pre-deploy-check.SKILL.md.tpl +350 -0
- package/dist/templates/project-router.SKILL.md.tpl +55 -0
- package/dist/templates/release-coordinate.SKILL.md.tpl +209 -0
- package/package.json +54 -0
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agentforge-feature-retro
|
|
3
|
+
description: Wraps up a finished feature in a multi-repo workspace. Writes a retrospective and supporting artifacts (Claude Code session logs, plan files, branch/PR refs) into artifacts/<YYYYMMDD>/<slug>/, removes the now-stale git worktrees from anvil/<slug>/, and deletes the empty anvil/<slug>/ directory so anvil/ only ever contains in-progress work. Triggers when the user signals a feature is done — e.g. "we're done", "feature is complete", "let's wrap this up", "write a retro", "archive this work".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# feature-retro
|
|
7
|
+
|
|
8
|
+
Closes the loop on a finished feature. Conceptually three things happen, in order:
|
|
9
|
+
|
|
10
|
+
1. Capture everything worth keeping (retro, sessions, plans, git refs) into
|
|
11
|
+
`artifacts/<YYYYMMDD>/<slug>/`.
|
|
12
|
+
2. Remove the git worktrees the feature used.
|
|
13
|
+
3. Delete the now-empty `anvil/<slug>/` directory.
|
|
14
|
+
|
|
15
|
+
After this, `anvil/` only contains in-progress work, and `artifacts/` holds the
|
|
16
|
+
permanent record of every finished feature, grouped by completion date.
|
|
17
|
+
|
|
18
|
+
## When to apply
|
|
19
|
+
|
|
20
|
+
Apply this skill when the user signals a feature is **done** or wants to wrap up:
|
|
21
|
+
- "We're done with this feature."
|
|
22
|
+
- "Let's wrap this up / close this out."
|
|
23
|
+
- "Write a retro / recap."
|
|
24
|
+
- "Archive this work."
|
|
25
|
+
|
|
26
|
+
Only run this inside a feature worktree (the user's cwd should be under
|
|
27
|
+
`anvil/<slug>/`). If the user is at the workspace root, ask which feature to retro on
|
|
28
|
+
(show `ls anvil/`).
|
|
29
|
+
|
|
30
|
+
## Concurrency lock
|
|
31
|
+
|
|
32
|
+
Before any destructive action, take the workspace lock:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
LOCK="anvil/<slug>/.agentforge.lock"
|
|
36
|
+
if [ -f "$LOCK" ]; then
|
|
37
|
+
cat "$LOCK"
|
|
38
|
+
# → another session is working on this feature. Stop and tell the user.
|
|
39
|
+
fi
|
|
40
|
+
printf 'pid=%s\nstarted=%s\nskill=agentforge-feature-retro\n' \
|
|
41
|
+
"$$" "$(date -u +%FT%TZ)" > "$LOCK"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Release on success and every failure path.
|
|
45
|
+
|
|
46
|
+
## How to do it
|
|
47
|
+
|
|
48
|
+
### 1. Establish the feature context
|
|
49
|
+
|
|
50
|
+
- Confirm cwd is under `anvil/<slug>/` — capture the `<slug>`.
|
|
51
|
+
- Read `anvil/<slug>/CLAUDE.md` (created by `feature-start`) to get the original
|
|
52
|
+
feature description and list of repos in scope.
|
|
53
|
+
- **Validate the listed repos against reality.** For each repo claimed in
|
|
54
|
+
`Repos in scope:`, verify the worktree exists at `anvil/<slug>/<repo>/`. If any
|
|
55
|
+
are missing (user moved or deleted them manually), report the mismatch and let
|
|
56
|
+
the user decide whether to archive only what's present, or fix the discrepancy
|
|
57
|
+
first.
|
|
58
|
+
- Compute today's date in UTC as `YYYYMMDD`:
|
|
59
|
+
```bash
|
|
60
|
+
TODAY=$(date -u +%Y%m%d)
|
|
61
|
+
ARCHIVE_DIR="artifacts/${TODAY}/<slug>"
|
|
62
|
+
```
|
|
63
|
+
If `artifacts/<TODAY>/<slug>/` already exists, ask the user whether to overwrite
|
|
64
|
+
(a previous retro attempt for the same feature on the same day).
|
|
65
|
+
|
|
66
|
+
### 2. Create the archive directory
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
mkdir -p artifacts/<YYYYMMDD>/<slug>/sessions
|
|
70
|
+
mkdir -p artifacts/<YYYYMMDD>/<slug>/plans
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 3. Capture Claude Code session logs
|
|
74
|
+
|
|
75
|
+
Claude Code stores transcripts at:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
~/.claude/projects/<encoded-cwd>/<session-id>.jsonl
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`<encoded-cwd>` is the absolute path of the directory where `claude` was launched,
|
|
82
|
+
with `/` replaced by `-` and prefixed with `-`. Example:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
launched in: /Users/alice/work/anvil/260418-feat-retry-logic
|
|
86
|
+
encoded: -Users-alice-work-anvil-260418-feat-retry-logic
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Steps:
|
|
90
|
+
1. Compute the encoded path for `anvil/<slug>/` (absolute path, slashes → hyphens).
|
|
91
|
+
2. List `~/.claude/projects/<encoded>/*.jsonl`.
|
|
92
|
+
3. Copy each matching `.jsonl` into `artifacts/<YYYYMMDD>/<slug>/sessions/`.
|
|
93
|
+
4. If the directory does not exist, tell the user — they may have started Claude
|
|
94
|
+
from a different cwd. Offer to take a path argument from them.
|
|
95
|
+
|
|
96
|
+
### 4. Capture plan files
|
|
97
|
+
|
|
98
|
+
Plan files live at `~/.claude/plans/*.md`. Plans aren't scoped to a feature, so:
|
|
99
|
+
1. List all plan files (most recently modified first).
|
|
100
|
+
2. Show candidates (with mtime + first heading) and ask which belong to this feature.
|
|
101
|
+
Default selection: most recently modified.
|
|
102
|
+
3. Copy chosen plans into `artifacts/<YYYYMMDD>/<slug>/plans/`.
|
|
103
|
+
|
|
104
|
+
### 5. Capture git refs (branch / HEAD / PR per repo)
|
|
105
|
+
|
|
106
|
+
Source code is **not** copied into the archive — each repo's git history already
|
|
107
|
+
contains the feature branch + any merged PR. We only preserve the pointers needed
|
|
108
|
+
to navigate back to the exact commits.
|
|
109
|
+
|
|
110
|
+
For each worktree under `anvil/<slug>/<repo>/`, capture (BEFORE the worktree is
|
|
111
|
+
removed in step 7):
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
HEAD=$(git -C anvil/<slug>/<repo> rev-parse HEAD)
|
|
115
|
+
MAIN=$( # base branch detection — see feature-start
|
|
116
|
+
git -C repos/<repo> symbolic-ref --quiet refs/remotes/origin/HEAD \
|
|
117
|
+
| sed 's@^refs/remotes/origin/@@'
|
|
118
|
+
)
|
|
119
|
+
if git -C repos/<repo> merge-base --is-ancestor <slug> "$MAIN" 2>/dev/null; then
|
|
120
|
+
MERGED_INTO="$MAIN"
|
|
121
|
+
else
|
|
122
|
+
MERGED_INTO=null
|
|
123
|
+
fi
|
|
124
|
+
PR_URL=$(gh -R <owner>/<repo> pr view <slug> --json url --jq .url 2>/dev/null || echo "")
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
After processing every repo, write `artifacts/<YYYYMMDD>/<slug>/refs.json`:
|
|
128
|
+
|
|
129
|
+
```jsonc
|
|
130
|
+
[
|
|
131
|
+
{
|
|
132
|
+
"repo": "backend-api",
|
|
133
|
+
"branch": "260418-feat-retry-logic",
|
|
134
|
+
"head": "abc1234...",
|
|
135
|
+
"merged_into": "main",
|
|
136
|
+
"pr": "https://github.com/acme/backend-api/pull/412"
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"repo": "admin-web",
|
|
140
|
+
"branch": "260418-feat-retry-logic",
|
|
141
|
+
"head": "def4567...",
|
|
142
|
+
"merged_into": null,
|
|
143
|
+
"pr": "https://github.com/acme/admin-web/pull/88"
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### 6. Write the retrospective
|
|
149
|
+
|
|
150
|
+
**Language**: the section headings below (`What we set out to do`, `Requirements`,
|
|
151
|
+
etc.) stay in English so the structure is consistent across features. The prose
|
|
152
|
+
inside each section is written in the workspace's output language — see the
|
|
153
|
+
"Output language" instruction at the bottom of this file. Code, commands, file
|
|
154
|
+
paths, and English proper nouns stay as-is.
|
|
155
|
+
|
|
156
|
+
Write `artifacts/<YYYYMMDD>/<slug>/RETRO.md`:
|
|
157
|
+
|
|
158
|
+
```markdown
|
|
159
|
+
# Retrospective: <feature description>
|
|
160
|
+
|
|
161
|
+
- Slug: `<slug>`
|
|
162
|
+
- Started: <YYYY-MM-DD> # from CLAUDE.md or YYMMDD slug prefix
|
|
163
|
+
- Closed: <YYYY-MM-DD> # today
|
|
164
|
+
- Repos in scope: <repo list>
|
|
165
|
+
|
|
166
|
+
## What we set out to do
|
|
167
|
+
<1–3 sentences. The original ask, in the user's words if possible.>
|
|
168
|
+
|
|
169
|
+
## Requirements
|
|
170
|
+
<Bullets — explicit asks + things that emerged mid-stream.>
|
|
171
|
+
|
|
172
|
+
## Key decisions and trade-offs
|
|
173
|
+
<For each significant decision: what was chosen, alternatives considered, why this
|
|
174
|
+
one won. Pull from plan files and from places in the transcript where the user
|
|
175
|
+
pushed back or redirected.>
|
|
176
|
+
|
|
177
|
+
## What was built
|
|
178
|
+
<Concrete outcomes per repo. Include `git log --oneline <slug>` and
|
|
179
|
+
`git diff --stat <base>..<slug>` outputs.>
|
|
180
|
+
|
|
181
|
+
## Open items / follow-ups
|
|
182
|
+
<Deferred items, TODOs left in code, scope cuts. Be honest about partial work.>
|
|
183
|
+
|
|
184
|
+
## Lessons / things to remember
|
|
185
|
+
<Non-obvious insights that future-you would want to know.>
|
|
186
|
+
|
|
187
|
+
## Archived artifacts
|
|
188
|
+
- sessions/ (<N> Claude session transcripts)
|
|
189
|
+
- plans/ (<N> plan files)
|
|
190
|
+
- refs.json (per-repo branch / HEAD / PR pointers)
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Also **move `anvil/<slug>/CLAUDE.md` into `artifacts/<YYYYMMDD>/<slug>/CLAUDE.md`**
|
|
194
|
+
so the feature metadata travels with the archive.
|
|
195
|
+
|
|
196
|
+
### 7. Tear down worktrees
|
|
197
|
+
|
|
198
|
+
For each `anvil/<slug>/<repo>/` worktree, **first capture the actual branch**
|
|
199
|
+
from the worktree's HEAD — `feature-start` lets each repo follow its own
|
|
200
|
+
branch-naming convention, so the branch name may differ from the slug:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
branch=$(git -C anvil/<slug>/<repo> rev-parse --abbrev-ref HEAD)
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Capture this before `worktree remove`; once the worktree is gone, looking it up
|
|
207
|
+
from `repos/<repo>` alone is awkward.
|
|
208
|
+
|
|
209
|
+
Then run safety checks **before** removal:
|
|
210
|
+
|
|
211
|
+
1. **Uncommitted changes** — `git -C anvil/<slug>/<repo> status --porcelain`. If
|
|
212
|
+
non-empty, stop and tell the user what's dirty. Default: skip removal, offer
|
|
213
|
+
to commit / stash / discard first.
|
|
214
|
+
2. **Unpushed commits** — `git -C anvil/<slug>/<repo> log @{u}.. --oneline 2>/dev/null`.
|
|
215
|
+
If non-empty and the branch has an upstream, warn — removing the worktree
|
|
216
|
+
keeps the local branch but its commits aren't on the remote. Ask before
|
|
217
|
+
continuing.
|
|
218
|
+
3. **Unmerged branch** — `git -C repos/<repo> merge-base --is-ancestor "$branch" <main>`.
|
|
219
|
+
If not merged, this is fine for archiving (the branch survives `worktree
|
|
220
|
+
remove`) but tell the user, and confirm before deleting the branch in the
|
|
221
|
+
optional cleanup step.
|
|
222
|
+
|
|
223
|
+
For each worktree that passes (or that the user confirms despite warnings):
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
git -C repos/<repo> worktree remove ../../anvil/<slug>/<repo>
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Optionally also delete the local branch (only with explicit user confirmation;
|
|
230
|
+
never force-delete unmerged branches without asking):
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
git -C repos/<repo> branch -d "$branch" # safe — refuses if unmerged
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### 8. Delete the empty anvil/<slug>/ directory
|
|
237
|
+
|
|
238
|
+
After every worktree is removed and `CLAUDE.md` has been moved to the archive,
|
|
239
|
+
`anvil/<slug>/` should be empty (or contain only the lock file). Remove it:
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
rm -f anvil/<slug>/.agentforge.lock # release the lock
|
|
243
|
+
rmdir anvil/<slug> # fails if anything else is in there
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**If `rmdir` fails because something else is still inside** — stop and report it.
|
|
247
|
+
Do not `rm -rf` the directory; that would risk losing user files we didn't
|
|
248
|
+
account for. Tell the user what's in there and let them decide.
|
|
249
|
+
|
|
250
|
+
### 9. Hand off
|
|
251
|
+
|
|
252
|
+
Tell the user what was archived and what (if anything) was kept:
|
|
253
|
+
|
|
254
|
+
```
|
|
255
|
+
✓ Feature `<slug>` closed.
|
|
256
|
+
artifacts/<YYYYMMDD>/<slug>/RETRO.md
|
|
257
|
+
artifacts/<YYYYMMDD>/<slug>/sessions/ (<N> sessions)
|
|
258
|
+
artifacts/<YYYYMMDD>/<slug>/plans/ (<N> plans)
|
|
259
|
+
artifacts/<YYYYMMDD>/<slug>/refs.json (<N> repo refs)
|
|
260
|
+
artifacts/<YYYYMMDD>/<slug>/CLAUDE.md (feature metadata)
|
|
261
|
+
|
|
262
|
+
Worktrees removed:
|
|
263
|
+
✓ backend-api (branch deleted)
|
|
264
|
+
✓ admin-web (branch kept on user request)
|
|
265
|
+
|
|
266
|
+
anvil/<slug>/ removed.
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
If any worktree was skipped (uncommitted / unpushed), say so and explain how to
|
|
270
|
+
resume after the user resolves it.
|
|
271
|
+
|
|
272
|
+
## Activity log
|
|
273
|
+
|
|
274
|
+
After each successful step (archive directory created, worktree removed, branch
|
|
275
|
+
deleted), append a JSONL line to `<workspace>/agentforge/log.jsonl`:
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
mkdir -p <workspace>/agentforge
|
|
279
|
+
printf '%s\n' "$(jq -nc \
|
|
280
|
+
--arg ts "$(date -u +%FT%TZ)" \
|
|
281
|
+
--arg skill agentforge-feature-retro \
|
|
282
|
+
--arg slug '<slug>' \
|
|
283
|
+
--arg action '<archived|worktree-removed|branch-deleted|anvil-pruned>' \
|
|
284
|
+
--arg repo '<repo>' \
|
|
285
|
+
--arg archive 'artifacts/<YYYYMMDD>/<slug>' \
|
|
286
|
+
'{ts:$ts, skill:$skill, slug:$slug, action:$action, repo:$repo, archive:$archive}')" \
|
|
287
|
+
>> <workspace>/agentforge/log.jsonl
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
When writing RETRO.md, include a **Timeline** section built from this log file
|
|
291
|
+
filtered by the current slug — it gives a chronological audit trail of the feature.
|
|
292
|
+
|
|
293
|
+
## Rules
|
|
294
|
+
|
|
295
|
+
- **Never `rm -rf anvil/<slug>/`** — use `rmdir` only, so unexpected user files are
|
|
296
|
+
never silently destroyed.
|
|
297
|
+
- **Capture refs BEFORE removing worktrees** — once the worktree is gone, you
|
|
298
|
+
can't query its HEAD anymore.
|
|
299
|
+
- **Move `CLAUDE.md` to the archive, don't copy** — there should be exactly one
|
|
300
|
+
copy of the feature metadata; it now lives in `artifacts/<YYYYMMDD>/<slug>/`.
|
|
301
|
+
- **artifacts/<YYYYMMDD>/<slug>/ is the permanent record.** Once created, it should
|
|
302
|
+
never be modified by other skills (only by manual user edits or a deliberate
|
|
303
|
+
re-run of feature-retro).
|
|
304
|
+
- **Ask before overwriting an existing archive entry** — a same-day re-run is
|
|
305
|
+
sometimes intentional but often a mistake.
|
|
306
|
+
- **If anything fails partway through**, leave the archive partially written and
|
|
307
|
+
the worktrees intact. Do not roll back the archive (it's recoverable info).
|
|
308
|
+
Tell the user what succeeded and what didn't.
|
|
309
|
+
|
|
310
|
+
## Output language
|
|
311
|
+
|
|
312
|
+
{{OUTPUT_LANGUAGE_INSTRUCTION}}
|