@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.
Files changed (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +275 -0
  3. package/dist/add-agent.js +145 -0
  4. package/dist/add-skill.js +185 -0
  5. package/dist/agent-prompt.js +211 -0
  6. package/dist/agentforge-config.js +106 -0
  7. package/dist/agents/claude.js +46 -0
  8. package/dist/agents/codex.js +67 -0
  9. package/dist/agents/cursor.js +54 -0
  10. package/dist/agents/index.js +15 -0
  11. package/dist/agents/io.js +252 -0
  12. package/dist/agents/types.js +1 -0
  13. package/dist/cli.js +374 -0
  14. package/dist/confirm.js +20 -0
  15. package/dist/doctor.js +223 -0
  16. package/dist/enter.js +85 -0
  17. package/dist/init.js +272 -0
  18. package/dist/lang-prompt.js +88 -0
  19. package/dist/list-skills.js +120 -0
  20. package/dist/logo.js +181 -0
  21. package/dist/path-prompt.js +148 -0
  22. package/dist/remove-agent.js +63 -0
  23. package/dist/remove-skill.js +88 -0
  24. package/dist/rename.js +222 -0
  25. package/dist/skill-prompt.js +199 -0
  26. package/dist/skills-data.js +727 -0
  27. package/dist/sync-skills.js +59 -0
  28. package/dist/templates/CLAUDE.md.tpl +141 -0
  29. package/dist/templates/context-handoff.SKILL.md.tpl +222 -0
  30. package/dist/templates/cross-repo-impact.SKILL.md.tpl +241 -0
  31. package/dist/templates/feature-retro.SKILL.md.tpl +312 -0
  32. package/dist/templates/feature-start.SKILL.md.tpl +631 -0
  33. package/dist/templates/history.SKILL.md.tpl +165 -0
  34. package/dist/templates/incident-context.SKILL.md.tpl +260 -0
  35. package/dist/templates/pr-create.SKILL.md.tpl +403 -0
  36. package/dist/templates/pr-review-analyze.SKILL.md.tpl +303 -0
  37. package/dist/templates/pre-deploy-check.SKILL.md.tpl +350 -0
  38. package/dist/templates/project-router.SKILL.md.tpl +55 -0
  39. package/dist/templates/release-coordinate.SKILL.md.tpl +209 -0
  40. 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}}