agentscamp 0.1.0 → 0.2.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.
@@ -0,0 +1,126 @@
1
+ ---
2
+ description: "Drive git bisect to find the exact commit that introduced a regression."
3
+ argument-hint: "<bug description; optional good and bad refs>"
4
+ allowed-tools: "Bash, Read"
5
+ ---
6
+
7
+ Find the commit that introduced the regression described in `$ARGUMENTS` using `git bisect`. The binary search is only as trustworthy as the test you feed it, so the first job is a rock-solid reproduction — not running `git bisect start`.
8
+
9
+ ## Scope
10
+
11
+ Parse `$ARGUMENTS` into three parts:
12
+
13
+ - **Bug description** — the observable regression (a failing test, a wrong output, a crash). Required.
14
+ - **Bad ref** — a commit where the bug is present. Defaults to `HEAD`.
15
+ - **Good ref** — a commit where the bug is absent (e.g. the last release tag `v2.3.0`, or `HEAD~200`). If not given, you will hunt for one in Step 3.
16
+
17
+ If `$ARGUMENTS` is empty, ask one question and stop: *"What is the regression, and do you know a commit/tag where it still worked?"* Do not invent a bug or guess refs — a wrong good/bad boundary makes bisect confidently point at the wrong commit.
18
+
19
+ > [!WARNING]
20
+ > Bisect checks out historical commits, which discards uncommitted work and may break the build. Before starting, run `git status` and confirm the tree is clean. If it is not, tell the user to commit or stash first — do not stash on their behalf.
21
+
22
+ ## Step 1 — Build a fast, deterministic reproduction
23
+
24
+ This is the make-or-break step. Distill the bug into a single command that exits **0 when the code is good** and **non-zero when it is bad**.
25
+
26
+ - Prefer the narrowest, fastest signal: one unit test (`npm test -- path/to.test.ts -t "name"`, `pytest -k name -q`), a focused script, or a one-line `grep` over program output. Bisect runs this command ~log2(N) times, so a 2-minute build over 500 commits is ~18 minutes — trim it.
27
+ - Run the command on the **bad ref first** and confirm it fails. Then mentally verify it would pass on good code. If you cannot make it fail on the known-bad ref, you do not yet have a reproduction — stop and refine.
28
+
29
+ > [!WARNING]
30
+ > A flaky reproduction poisons the entire bisect. If the test passes and fails non-deterministically (timing, network, random seeds, shared state, leftover DB rows), bisect will mislabel commits and blame the wrong one. Pin seeds, isolate state, and run the repro 3-5 times on the bad ref — it must fail **every** time before you continue.
31
+
32
+ ## Step 2 — Confirm the bad ref
33
+
34
+ By default `HEAD` is bad. Verify it:
35
+
36
+ ```bash
37
+ git status # tree must be clean
38
+ git rev-parse HEAD # record the bad ref so you can return to it
39
+ <your repro command> # must exit non-zero (bug reproduces)
40
+ ```
41
+
42
+ ## Step 3 — Establish a good ref
43
+
44
+ You need a commit where the repro **passes**. If `$ARGUMENTS` named one, check it out and verify; otherwise walk backward to find one.
45
+
46
+ ```bash
47
+ git checkout v2.3.0 # or a suspected-good tag / older commit
48
+ <your repro command> # must exit 0 here
49
+ git checkout - # return to the bad ref
50
+ ```
51
+
52
+ If the candidate still fails, go further back (`HEAD~100`, then `HEAD~400`) until the repro passes. Pick the *most recent* known-good commit you can — a tighter `[good, bad]` window means fewer steps.
53
+
54
+ ## Step 4 — Start the bisect
55
+
56
+ ```bash
57
+ git bisect start
58
+ git bisect bad HEAD # or your explicit bad ref
59
+ git bisect good v2.3.0 # the good ref you confirmed in Step 3
60
+ ```
61
+
62
+ Git now checks out a commit roughly halfway between them and reports how many steps remain.
63
+
64
+ ## Step 5 — Drive the search (prefer automation)
65
+
66
+ **Preferred — automate it.** Hand bisect the repro command and let it run unattended:
67
+
68
+ ```bash
69
+ git bisect run <your repro command>
70
+ ```
71
+
72
+ The exit-code contract `git bisect run` relies on:
73
+
74
+ | Exit code | Meaning to bisect |
75
+ | --- | --- |
76
+ | `0` | this commit is **good** |
77
+ | `1`–`124`, `126`, `127` | this commit is **bad** |
78
+ | `125` | **skip** — cannot be tested (won't build, deps changed) |
79
+
80
+ > [!NOTE]
81
+ > Use exit `125` for commits you cannot evaluate — e.g. a build failure unrelated to the bug. Wrap the repro in a script that builds first and `exit 125` on build failure, then runs the test: that keeps unbuildable commits from being misjudged as bad. Bisect will route around skipped commits and may report a small range instead of a single culprit.
82
+
83
+ **Manual fallback.** If the repro needs human judgment, evaluate each checked-out commit yourself and mark it:
84
+
85
+ ```bash
86
+ git bisect good # repro passed at this commit
87
+ git bisect bad # repro failed at this commit
88
+ git bisect skip # cannot test this one
89
+ ```
90
+
91
+ Repeat until git prints `<sha> is the first bad commit`.
92
+
93
+ ## Step 6 — Inspect the culprit and explain the cause
94
+
95
+ Once the first bad commit is identified, read it before declaring victory:
96
+
97
+ ```bash
98
+ git show <sha> # full diff + message
99
+ git show <sha> --stat # files touched, for a quick map
100
+ ```
101
+
102
+ Read the actual diff (use the Read tool to open the changed files at that revision if needed) and connect a specific line or hunk to the observed regression. Do not just report the SHA — explain *why* that change causes the bug.
103
+
104
+ ## Step 7 — Always reset
105
+
106
+ Bisect leaves the repo on a detached historical commit. Restore the original state:
107
+
108
+ ```bash
109
+ git bisect reset # returns to the branch/ref you started from
110
+ git status # confirm the tree is back to normal
111
+ ```
112
+
113
+ > [!WARNING]
114
+ > Never leave a bisect session open. If you stop early or hit an error, run `git bisect reset` before doing anything else, or the user will be stranded on a detached HEAD with a half-finished search log.
115
+
116
+ ## Report
117
+
118
+ Deliver, as your message:
119
+
120
+ 1. **First bad commit** — SHA, short message, author, and date.
121
+ 2. **Root cause** — the specific change in that commit that introduced the regression, tied to the bug in `$ARGUMENTS`.
122
+ 3. **Confidence** — note any `skip`ped commits or a returned range that widens the result.
123
+ 4. **Reproduction used** — the exact command, so the finding is repeatable.
124
+ 5. **Suggested fix or next step** — e.g. revert the commit, patch the offending hunk, or open an issue.
125
+
126
+ Confirm you ran `git bisect reset` and the working tree is clean before finishing.
@@ -0,0 +1,131 @@
1
+ ---
2
+ description: "Safely rename a symbol project-wide, distinguishing the real symbol from coincidental substring matches."
3
+ argument-hint: "<oldName> <newName>"
4
+ allowed-tools: "Read, Grep, Glob, Edit, Bash"
5
+ ---
6
+
7
+ Rename a code symbol — a function, class, method, variable, type, interface, enum, or constant — everywhere it appears, so the project compiles and behaves exactly as before under the new name. This is a precision refactor: the danger is not finding too few matches, it is changing too many.
8
+
9
+ ## Scope
10
+
11
+ Parse `$ARGUMENTS` as exactly two tokens: the **old name** then the **new name**.
12
+
13
+ - `getUserById fetchUserById` → rename `getUserById` to `fetchUserById`.
14
+ - If only one token is given, or the two are identical, ask for the missing piece. Do not invent the target name.
15
+ - If `$ARGUMENTS` is empty, ask: *"Which symbol should I rename, and to what?"* and stop.
16
+
17
+ If the old name is **ambiguous** — it resolves to more than one distinct symbol (e.g. a local `id` in three unrelated functions, or a `Status` type and a `Status` enum) — list the candidates with their file and line and ask which one. Renaming the wrong binding is worse than renaming nothing.
18
+
19
+ > [!WARNING]
20
+ > This is behavior-preserving. Rename only — do not change the symbol's type, signature, value, or call order, and do not "improve" code you pass through. A rename that needs a test assertion changed is a rename that broke something.
21
+
22
+ ## Step 1 — Find and read the definition
23
+
24
+ Locate where the symbol is **defined**, not just used. The definition tells you its kind (function/class/type/const), its scope (module-level, class member, block-local), and whether it is exported.
25
+
26
+ ```bash
27
+ # Anchor on word boundaries so `getUser` does not match `getUserById`
28
+ rg -nw "getUserById" --type-add 'src:*.{ts,tsx,js,jsx,py,go,rs,java}' -tsrc
29
+
30
+ # Narrow to likely definition sites
31
+ rg -nw "(function|const|let|class|interface|type|enum|def|fn|public|private)\s+getUserById"
32
+ ```
33
+
34
+ Read the definition and its immediate surroundings. Establish three facts before editing anything:
35
+
36
+ 1. **Kind** — function, class, type, variable, etc. (affects where else the name can legally appear).
37
+ 2. **Scope** — is this name unique in the project, or shadowed/reused in other scopes?
38
+ 3. **Export surface** — is it exported? Re-exported through a barrel/index file? Part of the public API?
39
+
40
+ ## Step 2 — Separate the real symbol from coincidental matches
41
+
42
+ This is the core of the command and where naive renames fail. A raw text match for the old name will hit three categories — you must keep only the first.
43
+
44
+ - **The symbol itself** — keep. Same binding, in scope.
45
+ - **A different symbol with the same name** — skip. A local `count` in another function, a `Status` from another module. Same characters, unrelated binding.
46
+ - **A substring of an unrelated identifier** — skip. `user` inside `username`, `userId`, `getUser`, `superuser`.
47
+
48
+ > [!WARNING]
49
+ > Never run an unanchored find-and-replace. `s/user/account/g` rewrites `username`, `currentUser`, and `userId` and is almost impossible to fully undo. Always match whole words (`rg -w`, `\b…\b`) and, when the name is common, confirm each hit resolves to the binding you read in Step 1 — by scope, import source, or the object/class it hangs off.
50
+
51
+ For methods and fields accessed via `.`, scope the match to the receiver's type. Renaming a `save` method on `OrderRepo` must not touch `save` on every other object in the codebase. Read the call to confirm the receiver before editing.
52
+
53
+ ## Step 3 — Build the reference list
54
+
55
+ Sweep for every legitimate occurrence and group it by category so nothing is missed:
56
+
57
+ ```bash
58
+ # All whole-word occurrences, with file:line for review
59
+ rg -nw "getUserById"
60
+
61
+ # Imports / exports / barrel re-exports that name it
62
+ rg -nw "getUserById" -g '*.{ts,js}' -g '!**/*.test.*' | rg "import|export|require|from"
63
+
64
+ # Tests, fixtures, and snapshots referencing it
65
+ rg -nw "getUserById" -g '*{test,spec}*' -g '*__snapshots__*'
66
+
67
+ # Docs, comments, and string literals (rename only if the string is the identifier, e.g. a DI token or route name)
68
+ rg -nw "getUserById" -g '*.{md,mdx}'
69
+ ```
70
+
71
+ Decide string-literal cases deliberately: a DI token, event name, GraphQL field, or serialized key that must stay wire-compatible should usually **not** change even if it spells the old name — changing it is a behavior change, not a rename. Comments and docstrings that describe the symbol **should** change.
72
+
73
+ ## Step 4 — Prefer language tooling, then verify by hand
74
+
75
+ If the project has language-server rename available, use it — it understands scope and won't touch substrings:
76
+
77
+ ```bash
78
+ # TypeScript / JS via ts-morph or the language server's rename
79
+ # Rust: cargo fix is not a rename; use rust-analyzer rename in-editor
80
+ # Go: gopls rename -w 'path/file.go:#offset' 'newName'
81
+ # Python: rope / pyright rename
82
+ gopls rename -w "./internal/user/service.go:#1423" "fetchUserById"
83
+ ```
84
+
85
+ > [!NOTE]
86
+ > Language tooling is the safe default, but it is not the final word. After any automated rename, run the Step 2 grep sweep again for the **old** name — stray hits in comments, generated files, string templates, or tooling-excluded paths are exactly what the language server skips.
87
+
88
+ If no rename tool fits, apply edits with `Edit` one occurrence at a time from your Step 3 list, never with `replace_all` on a bare word that could appear in other scopes.
89
+
90
+ ## Step 5 — Apply the edits
91
+
92
+ Edit each occurrence from the reference list. Keep edits surgical: change only the identifier token, leave surrounding whitespace, types, and arguments untouched. Update declaration, every call/reference, imports, exports/barrels, tests, and descriptive comments together so the tree never sits half-renamed.
93
+
94
+ ## Step 6 — Rename the file if it encodes the name
95
+
96
+ If the symbol's name is baked into a filename — `UserService.ts` for `class UserService`, `use_auth.py` for `use_auth` — rename the file and fix the import paths:
97
+
98
+ ```bash
99
+ git mv src/services/UserService.ts src/services/AccountService.ts
100
+ # then update every importer
101
+ rg -nw "services/UserService"
102
+ ```
103
+
104
+ Leave the filename alone if it doesn't track the symbol (e.g. a `utils.ts` that merely contains the function) — renaming it is scope creep.
105
+
106
+ ## Step 7 — Prove nothing broke
107
+
108
+ The compiler is your strongest oracle that the rename is complete and correct. Run the project's checks and confirm a clean tree:
109
+
110
+ ```bash
111
+ # Use whatever the project actually uses
112
+ npm run typecheck && npm run build && npm test
113
+ # or: tsc --noEmit / cargo check && cargo test / go build ./... && go test ./... / pytest
114
+ ```
115
+
116
+ - A "cannot find name `getUserById`" error means a reference was missed — find and fix it.
117
+ - A duplicate-identifier or shadowing error means the new name collides with an existing symbol in that scope — stop and report; the new name is unsafe.
118
+ - Final sweep: `rg -nw "getUserById"` should return **zero** code hits (intentional wire-compatible string literals aside).
119
+
120
+ > [!NOTE]
121
+ > If a test assertion had to change to pass, the rename altered behavior — most often a serialized key or public-API string you should have left alone. Revert that edit and reclassify it as a string literal to preserve.
122
+
123
+ ## Report
124
+
125
+ Summarize concisely:
126
+
127
+ - **Renamed** — `oldName` → `newName`, its kind and where it is defined.
128
+ - **Touched** — count and grouping of edits: definition, references, imports/exports, tests, comments, and any renamed file.
129
+ - **Skipped** — coincidental substring matches and same-name symbols in other scopes you deliberately left alone, plus any wire-compatible string literals preserved.
130
+ - **Verification** — typecheck, build, and tests pass; final grep for the old name is clean.
131
+ - **Caveats** — anything ambiguous you resolved by asking, or any public-API/string surface left unchanged on purpose.
@@ -0,0 +1,127 @@
1
+ ---
2
+ description: "Walk through resolving the in-progress merge, rebase, or cherry-pick conflict in the current repo by understanding both sides, then verify before continuing."
3
+ allowed-tools: "Read, Edit, Bash, Grep"
4
+ ---
5
+
6
+ Resolve the merge, rebase, or cherry-pick conflict that is currently paused in this repo. Work through the steps in order. This command rewrites working-tree files and advances an in-progress git operation, so correctness beats speed — stop and report rather than guess if a conflict is genuinely undecidable.
7
+
8
+ ## Scope
9
+
10
+ This command takes **no arguments**; it operates on the conflict already in progress. If `$ARGUMENTS` is non-empty, treat it only as a hint about which file or hunk to prioritize — never as an instruction to start a new merge or rebase. Otherwise ignore it and resolve every conflict git has paused on.
11
+
12
+ If there is no conflict in progress (Step 1 finds a clean tree and no `MERGE_HEAD`/`rebase-merge`/`CHERRY_PICK_HEAD` state), there is nothing to do — report that and stop. Do not invent a merge to perform.
13
+
14
+ > [!WARNING]
15
+ > Never resolve by reflex with `git checkout --ours <file>` or `--theirs <file>`. That keeps one side verbatim and throws the other away wholesale, which is rarely the correct merge and silently drops changes. Decide per hunk based on intent, not per file based on convenience.
16
+
17
+ ## Step 1 — Detect the conflict state
18
+
19
+ Find out which operation is paused — the "continue" command differs for each.
20
+
21
+ ```bash
22
+ git status
23
+ git rev-parse -q --verify MERGE_HEAD # set during a merge
24
+ git rev-parse -q --verify CHERRY_PICK_HEAD # set during a cherry-pick
25
+ ls -d "$(git rev-parse --git-dir)"/rebase-merge "$(git rev-parse --git-dir)"/rebase-apply 2>/dev/null # present during a rebase
26
+ ```
27
+
28
+ - `MERGE_HEAD` exists -> you are mid-**merge**; you will finish with `git merge --continue`.
29
+ - A `rebase-merge`/`rebase-apply` dir exists -> you are mid-**rebase**; finish with `git rebase --continue`.
30
+ - `CHERRY_PICK_HEAD` exists -> you are mid-**cherry-pick**; finish with `git cherry-pick --continue`.
31
+
32
+ State which operation you detected before touching any file. Record the current `git rev-parse HEAD` so you can describe what you started from.
33
+
34
+ > [!NOTE]
35
+ > "Ours" and "theirs" flip meaning between merge and rebase. In a **merge**, ours = your current branch (`HEAD`), theirs = the branch being merged in. In a **rebase**, ours = the branch you are replaying onto (the upstream), theirs = the commit being replayed (your work). Confirm the direction before reasoning about either side, or you will resolve backwards.
36
+
37
+ ## Step 2 — List the conflicted files
38
+
39
+ Enumerate every conflict, not just the obvious text ones.
40
+
41
+ ```bash
42
+ git diff --name-only --diff-filter=U # content conflicts (UU)
43
+ git status --short | grep -E '^(DD|AU|UD|UA|DU|AA|UU)' # add/add, delete/modify, etc.
44
+ ```
45
+
46
+ Handle the non-content cases deliberately: a **modify/delete** conflict (`UD`/`DU`) is a decision to keep the file (`git add <file>`) or remove it (`git rm <file>`), not a marker edit. An **add/add** (`AA`) needs the two versions reconciled into one file. Process files in a stable order and track which remain.
47
+
48
+ ## Step 3 — Understand both sides of each conflict
49
+
50
+ For each conflicted file, learn *why* each side changed those lines before editing anything.
51
+
52
+ ```bash
53
+ git diff <file> # both sides of the conflict together
54
+ git log --oneline -5 HEAD -- <file> # recent history on our side
55
+ git log --oneline -5 MERGE_HEAD -- <file> # ...and theirs (use the right ref per Step 1)
56
+ ```
57
+
58
+ In the file, the markers delimit the two sides:
59
+
60
+ - Lines between `<<<<<<<` and `=======` are **our** version.
61
+ - Lines between `=======` and `>>>>>>>` are **their** version.
62
+
63
+ Read the surrounding function and any callers (`Grep` for the changed symbols) to grasp each side's intent. The right resolution is usually neither side verbatim: when the two changes are independent (e.g. each adds a different import or a different field), keep **both**; when they genuinely contradict (two different values for the same constant), keep the correct one and understand what breaks for the other.
64
+
65
+ > [!WARNING]
66
+ > If a hunk is load-bearing and you cannot determine which side is correct without product context, do not guess. Skip to the abort path at the end and hand it back to the user with the specific question.
67
+
68
+ ## Step 4 — Edit each file to a correct merged result
69
+
70
+ Use `Edit` to replace each conflict region with the reconciled code. Remove **all three** marker lines (`<<<<<<<`, `=======`, `>>>>>>>`) and any commit-ref/branch-name suffixes git appended to them. The file must read as if one author wrote it intentionally — no leftover duplication, no dead half of a hunk.
71
+
72
+ After editing, prove no markers survive anywhere — a single stray marker is invalid source that breaks the build:
73
+
74
+ ```bash
75
+ git grep -nE '^(<{7}|={7}|>{7})( |$)' -- $(git diff --name-only --diff-filter=U)
76
+ ```
77
+
78
+ This must return nothing before you continue. (Use `git grep -n '<<<<<<< '` across the whole tree if you want a belt-and-suspenders check.)
79
+
80
+ ## Step 5 — Verify before staging
81
+
82
+ A file that merges textually can still be wrong logically. Build and test on the resolved tree **before** marking conflicts done.
83
+
84
+ ```bash
85
+ # Adapt to the repo's real scripts
86
+ npm run build
87
+ npm test
88
+ ```
89
+
90
+ If the build or typecheck fails, you reintroduced or mis-merged something — fix it now and re-run until green. Do not stage on a red build.
91
+
92
+ ## Step 6 — Stage and continue
93
+
94
+ Once verification passes, mark each conflict resolved and finish the paused operation with the matching command from Step 1.
95
+
96
+ ```bash
97
+ git add <each resolved file> # or `git rm <file>` for a modify/delete you chose to drop
98
+
99
+ git merge --continue # if mid-merge
100
+ git rebase --continue # if mid-rebase (repeat Steps 2-6 if the next commit also conflicts)
101
+ git cherry-pick --continue # if mid-cherry-pick
102
+ ```
103
+
104
+ > [!NOTE]
105
+ > A rebase replays commits one at a time, so a later commit can raise a fresh conflict the moment you continue. Loop back to Step 2 for each new pause until `git status` reports the rebase is complete.
106
+
107
+ ## Step 7 — Escape hatch
108
+
109
+ If the conflict is undecidable, or anything looks wrong mid-resolution, restore the pre-conflict state cleanly rather than committing a guess:
110
+
111
+ ```bash
112
+ git merge --abort # mid-merge
113
+ git rebase --abort # mid-rebase
114
+ git cherry-pick --abort # mid-cherry-pick
115
+ ```
116
+
117
+ Each abort returns the tree to where Step 1 started. Use it and explain what blocked you instead of shipping a merge you do not trust.
118
+
119
+ ## Report
120
+
121
+ Summarize the outcome as your message:
122
+
123
+ - Which operation was in progress and the ref you resolved against.
124
+ - Every file you touched and the resolution choice for each, with the one-line reason (kept both / chose ours / chose theirs / dropped the file — and why).
125
+ - Confirmation that no conflict markers remain.
126
+ - The build and test status (must be green).
127
+ - Whether you continued the operation, and if not, the exact question blocking it.
@@ -0,0 +1,76 @@
1
+ ---
2
+ description: "Scaffold a Retrieval-Augmented Generation pipeline — ingestion (load, chunk, embed, upsert) and retrieval (search, rerank, grounded prompt with citations) — fitted to the project's stack."
3
+ argument-hint: "<data source and use case>"
4
+ allowed-tools: "Read, Write, Glob, Grep"
5
+ ---
6
+
7
+ ## Scope
8
+
9
+ Treat `$ARGUMENTS` as the data source(s) and the use case — e.g. "our markdown docs, for an in-app Q&A assistant" or "support tickets in Postgres, for answer suggestions". Restate it in one sentence to confirm before scaffolding.
10
+
11
+ If `$ARGUMENTS` is empty, ask one focused question: *"What are you retrieving over, and what's the use case?"* Do not scaffold a generic pipeline against an imagined corpus.
12
+
13
+ > [!WARNING]
14
+ > Chunking quality dominates retrieval quality. A great embedding model and a great vector store cannot rescue chunks that split a sentence in half or merge three unrelated sections. Spend your attention on Step 3, not on picking a fancier model.
15
+
16
+ ## Step 1 — Detect the stack and existing AI dependencies
17
+
18
+ Before writing anything, ground the scaffold in what's already here:
19
+
20
+ 1. Identify the language/runtime — `Glob` for `package.json`, `pyproject.toml`, `requirements.txt`, `go.mod`, etc.
21
+ 2. `Grep` for AI/RAG deps already in use: `openai`, `@anthropic-ai/sdk`, `anthropic`, `langchain`, `llamaindex`, `@ai-sdk`, and any vector store client (`pinecone`, `weaviate`, `chromadb`, `qdrant`, `pgvector`, `@supabase`).
22
+ 3. `Grep` for an existing embeddings/vector call so you extend the project's conventions instead of introducing a parallel one.
23
+
24
+ Match the scaffold to what you find. If the project already has a vector store or an LLM client, build on it rather than adding a competing dependency.
25
+
26
+ ## Step 2 — Decide and state the key choices
27
+
28
+ Write these decisions at the top of the generated code as a comment block, so they're reviewable and tunable. Pick concrete defaults — don't punt to "configurable":
29
+
30
+ - **Chunking** — split on natural boundaries (headings, paragraphs, code blocks), not a blind character count. Default: ~400-800 tokens per chunk, 10-15% overlap. Attach metadata to every chunk: `source`, `title`, `heading`, and a line/char range for citation.
31
+ - **Embedding model** — use the project's existing provider if one is present; otherwise pick a current general-purpose embedding model and pin the dimension. State it explicitly so ingestion and retrieval can never drift apart.
32
+ - **Vector store** — reuse what's installed; if nothing exists, default to whatever the deployment already runs (e.g. `pgvector` if there's a Postgres, otherwise a local store). Store the chunk text alongside the vector and metadata.
33
+ - **Retrieval** — default top-k of 8-12 candidates, then an optional rerank pass down to the 3-5 chunks actually placed in the prompt.
34
+ - **Generation** — when a generation model is needed (answer synthesis, rerank-by-LLM), default to Anthropic's latest, most capable model: `claude-opus-4-8`.
35
+
36
+ > [!NOTE]
37
+ > Pin the embedding model and dimension in one shared constant imported by both halves. If ingestion embeds with one model and retrieval queries with another, every search silently returns noise — and there's no error to catch it.
38
+
39
+ ## Step 3 — Scaffold ingestion (idempotent, re-runnable)
40
+
41
+ Generate the ingestion path as: **load → clean → chunk → embed → upsert**.
42
+
43
+ - **Load** the source(s) from `$ARGUMENTS`.
44
+ - **Clean** — strip boilerplate, normalize whitespace, drop empty fragments.
45
+ - **Chunk** per the Step 2 strategy, carrying source metadata into each chunk.
46
+ - **Embed** each chunk in batches with retry/backoff.
47
+ - **Upsert** by a stable content-derived ID (e.g. a hash of `source` + chunk index + chunk text) so re-running the pipeline replaces changed chunks and skips unchanged ones instead of duplicating them.
48
+
49
+ Make it safe to run repeatedly against a partially-populated store — that's the whole point of a content-derived key.
50
+
51
+ ## Step 4 — Scaffold retrieval (grounded, with citations)
52
+
53
+ Generate the query path as: **embed query → vector search → optional rerank → assemble grounded prompt**.
54
+
55
+ - Embed the incoming query with the **same** pinned model from Step 2.
56
+ - Vector-search for top-k candidates.
57
+ - Optionally rerank (cross-encoder or LLM-as-reranker) down to the few chunks that go in the prompt.
58
+ - Assemble a prompt that includes the selected chunks **and their source attributions**, instructing the model to answer only from the provided context, cite each claim by source, and say it doesn't know when the context doesn't cover the question.
59
+ - Return the answer **with the source list**, so the caller can render citations.
60
+
61
+ > [!WARNING]
62
+ > Never return an ungrounded answer. If retrieval finds nothing relevant, the pipeline must surface "I don't have information on that" — not let the model answer from parametric memory. An unsourced answer in a RAG system is a bug, not a fallback.
63
+
64
+ ## Step 5 — Leave a slot for evaluation
65
+
66
+ Stub an evaluation entry point next to retrieval — a small harness that takes question/expected-source pairs and reports retrieval hit-rate and answer faithfulness. Leave it empty but wired in, with a comment on what to measure. Don't fabricate eval data; let the user supply it.
67
+
68
+ ## Report
69
+
70
+ List every file you created and what each one does (ingestion, retrieval, shared config, eval stub). Then give the exact next steps to make it live:
71
+
72
+ 1. Which credentials/env vars to set (embedding + generation API keys, vector-store connection).
73
+ 2. The command to run ingestion against the real `$ARGUMENTS` source.
74
+ 3. The single first query to verify retrieval returns grounded, cited results.
75
+
76
+ End with the one decision most worth revisiting after a first run — almost always the chunking strategy.
@@ -0,0 +1,102 @@
1
+ ---
2
+ description: "Trace how a value, field, or variable flows through the codebase from source to sink."
3
+ argument-hint: "<variable, field, or value to trace>"
4
+ allowed-tools: "Read, Grep, Glob"
5
+ ---
6
+
7
+ Trace how `$ARGUMENTS` moves through this codebase — from where it enters, through every transform, to where it lands. Build a directed flow map (source → transforms → sinks) with `file:line` citations, and flag anything notable on the path. Do not change any files; the map and the observations are the whole deliverable.
8
+
9
+ ## Scope
10
+
11
+ `$ARGUMENTS` is the value to trace — a request/response field (`order.shippingAddress`), a config key (`STRIPE_WEBHOOK_SECRET`), a DB column (`users.email_verified_at`), a query param, an event property, or a plain variable. Trace the **data**, not just the name: the same value is often spelled differently at each layer (`snake_case` column → `camelCase` model attr → `kebab-case` JSON key), so you are following an identity across renames, not grepping one literal.
12
+
13
+ If `$ARGUMENTS` is empty, do not guess. Ask one focused question: *"Which value should I trace — name a field, config key, column, or variable?"*
14
+
15
+ > [!WARNING]
16
+ > Read-only mode. Use only Read, Grep, and Glob. Do not edit files, run code, or hit a database to "follow" the value. The flow map is reconstructed from source, not from a live trace.
17
+
18
+ ## Step 1 — Pin down the value and its aliases
19
+
20
+ Find every name this value can wear before you start tracing, or you will lose it at the first layer boundary.
21
+
22
+ ```bash
23
+ # Seed search on the literal name and its common case variants
24
+ rg -n "shippingAddress|shipping_address|shipping-address" src
25
+ ```
26
+
27
+ - Note the **declared type/shape** at each spelling (string, cents-int, ISO-8601 string, enum, nullable).
28
+ - Watch for **destructuring and renames** — `const { email: userEmail } = body`, `address AS shipping` in SQL, `@SerializedName`, `@JsonProperty`, ORM column maps, GraphQL field resolvers, protobuf/`zod`/`pydantic` schemas. Each is a rename you must carry forward.
29
+
30
+ > [!NOTE]
31
+ > Aliases hide at every boundary: HTTP body → DTO, DTO → domain model, model → ORM entity, entity → table column, and back out through serializers. Build the alias set first; trace second.
32
+
33
+ ## Step 2 — Find the source(s)
34
+
35
+ Locate where the value first enters this system. Typical origins:
36
+
37
+ - **Inbound request** — route/controller param, request body field, header, query string.
38
+ - **Config / environment** — `process.env.X`, a config file, a secrets loader.
39
+ - **Storage read** — a column selected from a query, a cache `get`, a file read.
40
+ - **External call / event** — a webhook payload, a queue message, a third-party API response.
41
+
42
+ Record each source as `file:line` with the type it has *at the moment of entry*. If there are multiple independent sources, the value has multiple origins — trace each.
43
+
44
+ ## Step 3 — Walk every transform and validation
45
+
46
+ From each source, follow the value forward. At each hop, classify what happens to it:
47
+
48
+ | Hop kind | What to capture |
49
+ | --- | --- |
50
+ | **Validation / parse** | the rule (schema, regex, range, enum) and what passes through unchecked |
51
+ | **Transform** | the function and the type/unit change (cents↔dollars, ms↔s, trim/normalize, encrypt/hash) |
52
+ | **Rename / remap** | old name → new name across the boundary |
53
+ | **Branch / default** | conditionals that drop, substitute, or fork the value |
54
+ | **Aggregation** | merged into another object, array, or computed field |
55
+
56
+ Follow it through function calls and across files — when it is passed as an argument, jump into the callee and keep going. Stop a branch only when the value is consumed (read into a decision and not propagated) or reaches a sink.
57
+
58
+ > [!NOTE]
59
+ > A transform that changes **units or type without a matching change at the consumer** is the highest-value bug this command finds — e.g. cents stored but dollars displayed, or a UTC timestamp compared against a local one. Record the unit/type at *every* hop so mismatches between layers are visible.
60
+
61
+ ## Step 4 — Identify the sinks
62
+
63
+ A sink is where the value leaves your control. Find all of them:
64
+
65
+ - **Persistence** — DB write/upsert, cache `set`, file write.
66
+ - **Outbound** — API response body, third-party request, queue publish, email/SMS.
67
+ - **Logs / telemetry** — `console.log`, logger calls, metrics tags, error reporters.
68
+
69
+ For each sink, record the name and type the value has *as it leaves*, so the entry shape and exit shape can be compared end to end.
70
+
71
+ ## Step 5 — Assemble the flow map and the observations
72
+
73
+ Compose the hops into a single directed map, then list what you noticed along the way.
74
+
75
+ ```markdown
76
+ ## Flow: `$ARGUMENTS`
77
+
78
+ **Source** → `routes/orders.ts:31` — `body.shipping_address` (string, unvalidated)
79
+ → **validate** `schemas/order.ts:18` — zod `.string().min(1)` (rejects empty only)
80
+ → **rename** `services/order.ts:74` — `shipping_address` → `shippingAddress`
81
+ → **transform** `services/geo.ts:22` — normalized + uppercased country code
82
+ → **persist** `repo/orders.ts:55` — `INSERT orders.shipping_addr`
83
+ → **outbound** `clients/shipping.ts:40` — POSTed to carrier API as `destination`
84
+ → **log** `services/order.ts:80` — full address written to info log
85
+
86
+ ## Observations
87
+ - [validation gap] `routes/orders.ts:31` — accepts any non-empty string; no postal-code/country check before it reaches the carrier API.
88
+ - [type mismatch] `repo/orders.ts:55` vs `clients/shipping.ts:40` — column is `varchar(120)`; carrier rejects > 100 chars, no truncation between.
89
+ - [sensitive log] `services/order.ts:80` — PII (full address) logged at info level in plaintext.
90
+ ```
91
+
92
+ Use `→` to show direction; indent or fork the arrows when the value branches. Every node carries a `file:line` and the value's name+type at that point.
93
+
94
+ ## Report
95
+
96
+ Deliver the flow map and the observations as your message — that is the whole deliverable. Make sure:
97
+
98
+ 1. Each node has a real `file:line` citation; never invent a path you did not open.
99
+ 2. Every rename across a layer boundary is shown explicitly.
100
+ 3. Observations are tagged (`[validation gap]`, `[type mismatch]`, `[sensitive log]`, `[unit mismatch]`, `[dead path]`) and each cites the exact line.
101
+
102
+ End with the single most important finding — the one hop a reviewer should look at first — or, if the path is clean, say so plainly and name the source and primary sink.