@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,165 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agentforge-history
|
|
3
|
+
description: Queries past features in the workspace — searches every artifacts/<YYYYMMDD>/<slug>/ for retrospectives, decisions, PR/commit pointers, and Claude session transcripts, plus in-progress features under anvil/. Triggers when the user asks about earlier work, like "how did we handle X last time?", "which feature added Y?", "find that PR about Z", "show me past features touching a specific repo", "what did we decide about A previously?". Read-only.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# agentforge-history
|
|
7
|
+
|
|
8
|
+
When the user has a question about something done before — a past decision, a
|
|
9
|
+
shipped PR, a feature that touched a particular repo — this skill scans the
|
|
10
|
+
workspace's accumulated history and answers with grounded references (file paths,
|
|
11
|
+
commit hashes, PR URLs) instead of guesses.
|
|
12
|
+
|
|
13
|
+
**Read-only.** Reports only; never modifies anything.
|
|
14
|
+
|
|
15
|
+
## When to apply
|
|
16
|
+
|
|
17
|
+
Trigger phrases:
|
|
18
|
+
- "How did we handle `<X>` last time?"
|
|
19
|
+
- "Which feature added `<Y>`?"
|
|
20
|
+
- "Find that PR about `<Z>`."
|
|
21
|
+
- "Show me past features that touched `<repo>`."
|
|
22
|
+
- "What did we decide about `<topic>`?"
|
|
23
|
+
- "Pull up retros from the last three months."
|
|
24
|
+
- "Anything similar to this we've done before?"
|
|
25
|
+
|
|
26
|
+
If the question is clearly about live code or current work, route to `project-router`
|
|
27
|
+
or `feature-start` instead. Use this skill specifically for **looking back**.
|
|
28
|
+
|
|
29
|
+
## Data sources
|
|
30
|
+
|
|
31
|
+
Finished features live under `artifacts/<YYYYMMDD>/<slug>/` (the close date is the
|
|
32
|
+
first directory). All of these files may be present per feature:
|
|
33
|
+
|
|
34
|
+
| Source | What it gives you |
|
|
35
|
+
|---|---|
|
|
36
|
+
| `artifacts/<YYYYMMDD>/<slug>/CLAUDE.md` | Original feature description, repos in scope, start date |
|
|
37
|
+
| `artifacts/<YYYYMMDD>/<slug>/RETRO.md` | What was asked, decisions, what was built, lessons |
|
|
38
|
+
| `artifacts/<YYYYMMDD>/<slug>/refs.json` | Per-repo `{branch, head, merged_into, pr}` pointers |
|
|
39
|
+
| `artifacts/<YYYYMMDD>/<slug>/plans/*.md` | Plan files captured during the work |
|
|
40
|
+
| `artifacts/<YYYYMMDD>/<slug>/sessions/*.jsonl` | Full Claude Code transcripts (large; query last) |
|
|
41
|
+
| `agentforge/log.jsonl` | Append-only activity log (start / archive / PR events) |
|
|
42
|
+
|
|
43
|
+
In-progress features (not yet archived) live under `anvil/<slug>/` with their
|
|
44
|
+
`CLAUDE.md` describing scope; the rest of the artifacts only exist after
|
|
45
|
+
`feature-retro` runs. Don't confuse the two: `anvil/` = active, `artifacts/` = done.
|
|
46
|
+
|
|
47
|
+
A feature folder may not have all of the above files — older features may
|
|
48
|
+
pre-date some fields. Handle missing files gracefully.
|
|
49
|
+
|
|
50
|
+
## How to do it
|
|
51
|
+
|
|
52
|
+
### Step 1 — Enumerate features
|
|
53
|
+
|
|
54
|
+
Walk both archive and in-progress:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
ls -1 artifacts/ 2>/dev/null # YYYYMMDD directories of close dates
|
|
58
|
+
ls -1 anvil/ 2>/dev/null # in-progress features (no archive yet)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
For archive, recurse one more level: `artifacts/<YYYYMMDD>/<slug>/`.
|
|
62
|
+
|
|
63
|
+
For each feature directory, capture:
|
|
64
|
+
- the slug (last directory component)
|
|
65
|
+
- the **close date** for archived features (the `YYYYMMDD` parent directory)
|
|
66
|
+
- the **start date** parsed from the slug's `YYMMDD-` prefix
|
|
67
|
+
- the original description (first heading in `CLAUDE.md`)
|
|
68
|
+
- the in-scope repos (from `CLAUDE.md` or `refs.json`)
|
|
69
|
+
- whether the feature is closed (lives in `artifacts/`) or in-progress (lives in
|
|
70
|
+
`anvil/`)
|
|
71
|
+
|
|
72
|
+
Sorting:
|
|
73
|
+
- Archive features: by close date (parent directory), newest first.
|
|
74
|
+
- In-progress features: by slug `YYMMDD-` prefix, newest first.
|
|
75
|
+
|
|
76
|
+
Skip directories that aren't features (no `CLAUDE.md`).
|
|
77
|
+
|
|
78
|
+
### Step 2 — Narrow by the user's question
|
|
79
|
+
|
|
80
|
+
Extract intent + keywords from the question. Then filter:
|
|
81
|
+
|
|
82
|
+
- **By keyword** — grep `CLAUDE.md`, `RETRO.md`, plan files for the terms. Skip
|
|
83
|
+
`sessions/` directories on this pass (they're large; query them only after
|
|
84
|
+
the answer needs more depth).
|
|
85
|
+
- **By repo** — match against the `Repos in scope:` list / `refs.json` repos.
|
|
86
|
+
- **By date window** — when the user says "last 3 months", "this quarter",
|
|
87
|
+
"since the deploy migration", filter on the `YYYYMMDD` archive parent dir
|
|
88
|
+
(close date) or the `YYMMDD` slug prefix (start date), depending on which
|
|
89
|
+
the user meant.
|
|
90
|
+
- **By PR / commit** — if the user mentions a PR number or partial commit hash,
|
|
91
|
+
grep every `refs.json` for it.
|
|
92
|
+
|
|
93
|
+
Rank candidates by signal strength (keyword hit count, recency, repo match).
|
|
94
|
+
|
|
95
|
+
### Step 3 — Compose the answer
|
|
96
|
+
|
|
97
|
+
Lead with the **most relevant feature**. For each match, include just enough to
|
|
98
|
+
let the user open the right file next:
|
|
99
|
+
|
|
100
|
+
```markdown
|
|
101
|
+
## 260418-feat-retry-logic (closed 2026-05-09, ~3 weeks ago)
|
|
102
|
+
*Retry logic refactor across services* · scope: backend-api, admin-web
|
|
103
|
+
|
|
104
|
+
**Decisions** (from RETRO.md):
|
|
105
|
+
- Retry policy enforced at the API layer, not the client (so all callers behave consistently).
|
|
106
|
+
- Kept the old endpoint, added v2 alongside for a deprecation window.
|
|
107
|
+
|
|
108
|
+
**Built** (from refs.json):
|
|
109
|
+
- backend-api: branch `260418-feat-retry-logic`, head `abc1234`, merged into `main` — PR acme/backend-api#412
|
|
110
|
+
- admin-web: branch `260418-feat-retry-logic`, head `def5678`, merged into `main` — PR acme/admin-web#88
|
|
111
|
+
|
|
112
|
+
**More**: open `artifacts/20260509/260418-feat-retry-logic/RETRO.md` for the full
|
|
113
|
+
retro; session transcripts are under `sessions/`.
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
If multiple features match strongly, list the top 3–5 in this format. Don't dump
|
|
117
|
+
every feature — narrow to ones that actually answer the question.
|
|
118
|
+
|
|
119
|
+
If there's one clear match and the user asked something specific (e.g. "what was
|
|
120
|
+
the rationale?"), **answer the specific question** by quoting the relevant lines
|
|
121
|
+
from RETRO.md, then point to the file for the rest. Don't paraphrase invisibly —
|
|
122
|
+
quote the source so the user can verify.
|
|
123
|
+
|
|
124
|
+
### Step 4 — Drill into sessions (only if needed)
|
|
125
|
+
|
|
126
|
+
`artifacts/<YYYYMMDD>/<slug>/sessions/*.jsonl` files are large (each line is a
|
|
127
|
+
message). Only open
|
|
128
|
+
them when:
|
|
129
|
+
- The RETRO doesn't have the answer the user is looking for.
|
|
130
|
+
- The user explicitly asks for the original conversation ("what exactly did I ask
|
|
131
|
+
back then?").
|
|
132
|
+
|
|
133
|
+
When you do, grep the jsonl for the keyword first; only read the surrounding
|
|
134
|
+
messages for context.
|
|
135
|
+
|
|
136
|
+
## Cross-feature questions
|
|
137
|
+
|
|
138
|
+
For "anything similar we've done?" or "show me patterns":
|
|
139
|
+
|
|
140
|
+
1. Pull the user's current intent or current diff (if they're in a worktree).
|
|
141
|
+
2. Search across **all** RETROs for similar problem statements / decisions.
|
|
142
|
+
3. Group the matches and surface the recurring themes (e.g. "we've tackled cache
|
|
143
|
+
invalidation 3 times — each retro chose a slightly different invalidation
|
|
144
|
+
scope; here's the contrast").
|
|
145
|
+
|
|
146
|
+
Be explicit when you're synthesizing across multiple features vs. quoting one.
|
|
147
|
+
|
|
148
|
+
## Rules
|
|
149
|
+
|
|
150
|
+
- **Always cite the source file.** Every claim should be traceable to a path the
|
|
151
|
+
user can open: `artifacts/<YYYYMMDD>/<slug>/RETRO.md:L42` or `refs.json` etc.
|
|
152
|
+
- **Don't fabricate decisions or PR numbers.** If the source data doesn't contain
|
|
153
|
+
it, say so.
|
|
154
|
+
- **Respect privacy.** Old session transcripts may contain incidentally pasted
|
|
155
|
+
alerts with customer identifiers. Apply the same redaction conventions as the
|
|
156
|
+
`agentforge-incident-context` skill if you find any (Bearer tokens, JWTs,
|
|
157
|
+
emails, etc.) before echoing them.
|
|
158
|
+
- **Sessions are heavy.** Never open all of them in bulk. Always go RETRO/plans
|
|
159
|
+
first, then drop into sessions only for specific lookups.
|
|
160
|
+
- **Read-only.** This skill never edits a RETRO, plan, refs.json, or log entry.
|
|
161
|
+
If the user wants to correct an old record, they edit the file themselves.
|
|
162
|
+
|
|
163
|
+
## Output language
|
|
164
|
+
|
|
165
|
+
{{OUTPUT_LANGUAGE_INSTRUCTION}}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agentforge-incident-context
|
|
3
|
+
description: First-responder context for a production incident in a multi-repo workspace. Given a clue from an alert — error message, stack trace line, HTTP path, metric name, exception class, or timestamp — searches every repo in the workspace for matching code, identifies recent merged PRs that touched it, names the last committers, traces the call path, and returns a single briefing optimized for "I just got paged, what changed?". Triggers on "incident context", "got an alert about X", "production error", "what changed recently around X", "page-out for …". Read-only.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# incident-context
|
|
7
|
+
|
|
8
|
+
Optimized for the moment an alert fires. Instead of grepping six repos one by one,
|
|
9
|
+
this skill takes the alert's clue, walks the whole workspace, and returns a single
|
|
10
|
+
briefing: where the keyword lives, what changed there recently, who touched it last,
|
|
11
|
+
and what to look at next.
|
|
12
|
+
|
|
13
|
+
**Read-only.** Reports only; never modifies code.
|
|
14
|
+
|
|
15
|
+
## When to apply
|
|
16
|
+
|
|
17
|
+
Trigger phrases:
|
|
18
|
+
- "Incident context for `<keyword>`."
|
|
19
|
+
- "Got an alert about `<X>` — what could be causing it?"
|
|
20
|
+
- "Production error: `<stack trace line>`."
|
|
21
|
+
- "What changed recently around `<symbol or path>`?"
|
|
22
|
+
- "Page-out — please pull context."
|
|
23
|
+
|
|
24
|
+
If the user's clue is overly generic (`null`, `error`, `failed`), ask for a more
|
|
25
|
+
specific signal (the surrounding class name, a unique substring of the error message,
|
|
26
|
+
the HTTP path) before searching — false positives at 4am help nobody.
|
|
27
|
+
|
|
28
|
+
## Redact secrets from the clue (do this FIRST, before any analysis)
|
|
29
|
+
|
|
30
|
+
Alert payloads pasted by an on-call engineer commonly contain tokens, customer
|
|
31
|
+
identifiers, or credentials. Before you echo, log, or quote any part of the clue
|
|
32
|
+
back to the user — and before any of it lands in your output — scrub it.
|
|
33
|
+
|
|
34
|
+
**Pattern checks to apply** (regex-level, conservative):
|
|
35
|
+
|
|
36
|
+
| Pattern | Example | Action |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| `Bearer\s+[A-Za-z0-9._\-]{20,}` | `Bearer eyJhbGc...` | replace with `Bearer <REDACTED>` |
|
|
39
|
+
| `Basic\s+[A-Za-z0-9+/=]{16,}` | `Basic YWRtaW46...` | `Basic <REDACTED>` |
|
|
40
|
+
| AWS access key `AKIA[0-9A-Z]{16}` | `AKIAIOSFODNN7EXAMPLE` | `<AWS_KEY>` |
|
|
41
|
+
| AWS secret `[A-Za-z0-9/+=]{40}` next to a key context | `aws_secret=...` | `<AWS_SECRET>` |
|
|
42
|
+
| GitHub PAT `gh[pousr]_[A-Za-z0-9]{36,}` | `ghp_xxxxx` | `<GH_TOKEN>` |
|
|
43
|
+
| Slack token `xox[abprs]-[A-Za-z0-9-]+` | `xoxb-...` | `<SLACK_TOKEN>` |
|
|
44
|
+
| JWT `eyJ[A-Za-z0-9_\-]+\.eyJ[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+` | full JWTs | `<JWT>` |
|
|
45
|
+
| Long hex secret `\b[a-f0-9]{32,64}\b` near `key=`/`secret=`/`token=` | hashes/keys | `<SECRET>` |
|
|
46
|
+
| Email `[a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]{2,}` | customer email | `<email>` (only inside log/error text, not from the user's own message) |
|
|
47
|
+
| Phone `\+?\d[\d \-]{7,}` near `phone=` / `tel=` | customer phone | `<phone>` |
|
|
48
|
+
| Credit card-like `\b(?:\d[ \-]?){13,19}\b` | numeric runs | `<CC>` |
|
|
49
|
+
|
|
50
|
+
If any pattern matched, **tell the user once**:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
⚠ Redacted from the clue: 2 tokens, 1 JWT, 1 customer ID
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Continue analysis with the redacted version. Never include the original values in any
|
|
57
|
+
output, file, or subsequent tool call.
|
|
58
|
+
|
|
59
|
+
## What the user provides
|
|
60
|
+
|
|
61
|
+
Accept one or more of (the clue can come from any stack — backend, frontend, mobile,
|
|
62
|
+
worker, CLI):
|
|
63
|
+
- **Error message / exception text**, e.g.
|
|
64
|
+
- JS/TS: `TypeError: Cannot read properties of undefined (reading 'foo')`
|
|
65
|
+
- Java/Kotlin: `NullPointerException at Foo.process`
|
|
66
|
+
- Python: `KeyError: 'foo'` / `AttributeError: 'NoneType' object has no attribute 'bar'`
|
|
67
|
+
- Go: `runtime error: invalid memory address or nil pointer dereference`
|
|
68
|
+
- Swift: `Fatal error: Unexpectedly found nil while unwrapping an Optional value`
|
|
69
|
+
- **Stack trace line**, e.g.
|
|
70
|
+
- JS: `at fetchData (src/api/things.ts:42:13)`
|
|
71
|
+
- Kotlin: `at com.example.app.JobRunner.process(JobRunner.kt:88)`
|
|
72
|
+
- Python: `File "src/foo.py", line 142, in process`
|
|
73
|
+
- Go: `src/foo/handler.go:88 +0x4c`
|
|
74
|
+
- **HTTP request path** (e.g. `POST /v1/things/<id>`, `GET /api/users/:id`)
|
|
75
|
+
- **Symbol name** — function, class, method, component, hook
|
|
76
|
+
- **Metric or log key** (e.g. `things.process.failure.count`, `feature.search-ranking.enabled`)
|
|
77
|
+
- **Time window** (e.g. "starting 30 min ago", "since yesterday's deploy") — scopes
|
|
78
|
+
the "recent PRs" search.
|
|
79
|
+
|
|
80
|
+
If a time window is missing, default to **last 7 days** for PR scanning, but tell the
|
|
81
|
+
user so they can narrow it.
|
|
82
|
+
|
|
83
|
+
## Locate the workspace
|
|
84
|
+
|
|
85
|
+
Walk up from cwd to find a directory containing `repos/`. The search set is every
|
|
86
|
+
`repos/<name>/`. If no agentforge workspace is detected, fall back to cwd as the
|
|
87
|
+
single repo and say so.
|
|
88
|
+
|
|
89
|
+
## Normalize the clue
|
|
90
|
+
|
|
91
|
+
Extract searchable tokens from whatever the user pasted:
|
|
92
|
+
|
|
93
|
+
- **Stack trace** → pull the fully-qualified type + method + file:line. The file:line
|
|
94
|
+
is the highest-signal anchor; search for the file basename first.
|
|
95
|
+
- **Error message** → extract the unique substring (skip framework boilerplate like
|
|
96
|
+
"Exception in thread"). A class name + a noun phrase is usually enough.
|
|
97
|
+
- **HTTP path** → keep both the literal path and the path with `:id` style
|
|
98
|
+
placeholders. Search both forms.
|
|
99
|
+
- **Metric / log key** → search the literal key as a string.
|
|
100
|
+
|
|
101
|
+
If multiple anchors are available, search for all of them and intersect results.
|
|
102
|
+
|
|
103
|
+
## Search every repo
|
|
104
|
+
|
|
105
|
+
For each `repos/<name>/`:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# code search for the most specific anchor first
|
|
109
|
+
git -C repos/<name> grep -nE "<anchor-regex>" -- ':!*.lock' ':!node_modules' ':!dist' ':!build'
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Track:
|
|
113
|
+
- File paths and line numbers that match.
|
|
114
|
+
- The function / method enclosing each match (read a few lines of context).
|
|
115
|
+
- Whether the hit is in production code or in a test file (`*test*`, `__tests__`,
|
|
116
|
+
`*_test.go`, `*Test.kt`, etc.) — test hits are usually noise during an incident.
|
|
117
|
+
|
|
118
|
+
If a repo has zero hits, mention it briefly ("`mobile-app`: no matches"). Don't hide
|
|
119
|
+
it — the responder needs to know what was searched.
|
|
120
|
+
|
|
121
|
+
## Pull recent PRs per repo
|
|
122
|
+
|
|
123
|
+
For each repo that has matches, find PRs merged in the time window that touched any
|
|
124
|
+
of the matching files:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# PRs merged in window (default: 7d)
|
|
128
|
+
gh -R <owner>/<repo> pr list --state merged --search "merged:>=$(date -u -v-7d '+%Y-%m-%d')" --json number,title,url,mergedAt,author,files --limit 50
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Filter the result to PRs whose `files[]` list intersects the matching file paths.
|
|
132
|
+
|
|
133
|
+
If `gh` isn't available or the repo has no remote, fall back to git:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
git -C repos/<name> log --merges --since="7 days ago" --pretty='%h %ci %s' -- <matched-files...>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
For each PR / commit, capture:
|
|
140
|
+
- PR number + title + URL (or commit hash + subject)
|
|
141
|
+
- Merged-at timestamp
|
|
142
|
+
- Author handle
|
|
143
|
+
- Which of the matching files it changed (just the count)
|
|
144
|
+
|
|
145
|
+
**Rank by suspicion**:
|
|
146
|
+
1. Merged inside the user's time window (if given) — strongest signal.
|
|
147
|
+
2. Merged most recently.
|
|
148
|
+
3. Touched the highest-signal file (the one matching the stack trace line).
|
|
149
|
+
|
|
150
|
+
## Identify the last committers
|
|
151
|
+
|
|
152
|
+
For each matching file, `git -C <repo> log -1 --format='%an <%ae> %ai' -- <file>` to get
|
|
153
|
+
the most recent author. Optionally also list the top 2–3 historical committers
|
|
154
|
+
(`git -C <repo> shortlog -sne -- <file> | head -3`) — they're the people who
|
|
155
|
+
understand the code best.
|
|
156
|
+
|
|
157
|
+
## Trace the call path (light)
|
|
158
|
+
|
|
159
|
+
For the strongest single match (the most specific anchor — usually the stack trace
|
|
160
|
+
line), do a one-hop call site search using the language-appropriate idiom:
|
|
161
|
+
|
|
162
|
+
| Language | Caller pattern |
|
|
163
|
+
|---|---|
|
|
164
|
+
| TS / JS | `\.X\(` , `\bX\(` |
|
|
165
|
+
| Kotlin / Java | `\.X\(` |
|
|
166
|
+
| Python | `\bX\(` |
|
|
167
|
+
| Go | `\.X\(` |
|
|
168
|
+
| Rust | `::X\(` , `\.X\(` |
|
|
169
|
+
|
|
170
|
+
Show up to 10 call sites grouped by repo. This is enough to know "is this called from
|
|
171
|
+
a sync HTTP handler, a Kafka listener, or a cron?" — which often determines blast
|
|
172
|
+
radius.
|
|
173
|
+
|
|
174
|
+
## Output format
|
|
175
|
+
|
|
176
|
+
Lead with the **most actionable** sections (suspects, recent PRs) and push general
|
|
177
|
+
context lower. Make it scannable in 30 seconds.
|
|
178
|
+
|
|
179
|
+
```markdown
|
|
180
|
+
# 🚨 Incident context: <keyword>
|
|
181
|
+
|
|
182
|
+
> Searched: 4 repos (backend-api, mobile-app, admin-web, worker-service)
|
|
183
|
+
> Time window: last 7 days (override by specifying a window)
|
|
184
|
+
> Anchors: `Foo.process` · `things.process.failure.count`
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## 🎯 Primary suspects
|
|
189
|
+
|
|
190
|
+
### `backend-api` · `Foo.kt:142` — `process()`
|
|
191
|
+
- 📞 Reached via:
|
|
192
|
+
- `FooController.handleRequest` (sync HTTP `POST /v1/things/:id`)
|
|
193
|
+
- `SomeConsumer.onMessage` (Kafka, `things.event.requested`) ⚡ async — no request transaction
|
|
194
|
+
- 🕒 Last touched: 2 hours ago by `alice <s@example.com>`
|
|
195
|
+
- 📜 Recent PRs touching this file:
|
|
196
|
+
- **#412** "Refactor error handling" — merged 2h ago by @alice
|
|
197
|
+
[link]
|
|
198
|
+
- **#398** "Add `reason` column" — merged 3d ago by @bob [link]
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## 📜 Recent merged PRs (in window, ranked)
|
|
203
|
+
|
|
204
|
+
| Repo | PR | When | Author | Matched files | Title |
|
|
205
|
+
|---|---|---|---|---|---|
|
|
206
|
+
| backend-api | #412 | 2h ago | @alice | 3 | Refactor error handling |
|
|
207
|
+
| backend-api | #398 | 3d ago | @bob | 1 | Add `reason` column |
|
|
208
|
+
| worker-service | #71 | 1d ago | @carol | 1 | Bump webhook version |
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## 🔍 Other matches (older / lower signal)
|
|
213
|
+
|
|
214
|
+
- `admin-web` · `src/api/things.ts:18` — display layer; last touched 6 weeks ago.
|
|
215
|
+
- `mobile-app`: no matches.
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## 👥 Who knows this code
|
|
220
|
+
|
|
221
|
+
- `Foo.kt` — alice (last touch), colleague (most commits), legacy-dev
|
|
222
|
+
(original author)
|
|
223
|
+
- `SomeConsumer.kt` — colleague
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## 📋 Next steps
|
|
228
|
+
|
|
229
|
+
1. Read **PR #412** diff — it's the most recent change to the suspect file.
|
|
230
|
+
2. Check logs for the time window — search by `request_id` and the exception class.
|
|
231
|
+
3. Confirm whether the failures are on the sync path or the Kafka consumer (call
|
|
232
|
+
path shows both).
|
|
233
|
+
4. If async, confirm transaction / MDC propagation in `SomeConsumer.onMessage`.
|
|
234
|
+
5. If you need a wider search, re-run with a longer time window or a broader anchor.
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Always include "Next steps" — a context dump without a path forward isn't useful at
|
|
238
|
+
4am. Limit it to 3–5 concrete actions.
|
|
239
|
+
|
|
240
|
+
## Rules
|
|
241
|
+
|
|
242
|
+
- **Workspace-bounded**: only search `repos/*` (and explicitly included worktrees).
|
|
243
|
+
Don't escape to unrelated directories.
|
|
244
|
+
- **Don't claim a root cause.** Report what was found and what is most suspicious;
|
|
245
|
+
let the user decide.
|
|
246
|
+
- **Distinguish sync vs async entry points.** When a Kafka listener / scheduled job /
|
|
247
|
+
webhook handler is in the call path, flag it — incidents often hide there.
|
|
248
|
+
- **Distinguish production vs test hits.** Test hits go to the "other matches"
|
|
249
|
+
section, not the suspects list.
|
|
250
|
+
- **Acknowledge silence.** A repo with no hits is information — list it.
|
|
251
|
+
- **No data exfiltration.** If a user pastes a stack trace containing customer
|
|
252
|
+
identifiers (emails, account IDs), do not echo those identifiers in your response —
|
|
253
|
+
use placeholders like `<id>`. Redact tokens / passwords if they appear.
|
|
254
|
+
- **No edits, ever.** Reporting only.
|
|
255
|
+
- **Time-boxed.** The user is under pressure. Aim to deliver the first useful version
|
|
256
|
+
of the briefing fast; offer to drill deeper afterwards.
|
|
257
|
+
|
|
258
|
+
## Output language
|
|
259
|
+
|
|
260
|
+
{{OUTPUT_LANGUAGE_INSTRUCTION}}
|