agentpack-cli 0.2.0__tar.gz → 0.2.2__tar.gz
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.
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/PKG-INFO +84 -22
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/README.md +83 -21
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/pyproject.toml +1 -1
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/__init__.py +1 -1
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/analysis/dependency_graph.py +27 -15
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/analysis/ranking.py +90 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/application/pack_service.py +16 -2
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/commands/benchmark.py +342 -4
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/commands/doctor.py +1 -1
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/commands/hook_cmd.py +7 -2
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/commands/install.py +2 -2
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/commands/pack.py +11 -2
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/core/context_pack.py +11 -1
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/data/agentpack.md +6 -7
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/installers/claude.py +2 -1
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/installers/cursor.py +2 -2
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/installers/windsurf.py +1 -1
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/mcp_server.py +71 -16
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/.gitignore +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/LICENSE +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/adapters/__init__.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/adapters/antigravity.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/adapters/base.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/adapters/claude.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/adapters/codex.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/adapters/cursor.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/adapters/detect.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/adapters/generic.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/adapters/windsurf.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/analysis/__init__.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/analysis/go_imports.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/analysis/java_imports.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/analysis/js_ts_imports.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/analysis/monorepo.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/analysis/python_imports.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/analysis/repo_map.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/analysis/rust_imports.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/analysis/symbols.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/analysis/task_classifier.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/analysis/tests.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/application/__init__.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/cli.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/commands/__init__.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/commands/_shared.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/commands/claude_cmd.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/commands/diff.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/commands/explain.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/commands/init.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/commands/mcp_cmd.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/commands/monitor.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/commands/quickstart.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/commands/repair.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/commands/scan.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/commands/stats.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/commands/status.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/commands/summarize.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/commands/tune.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/commands/watch.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/core/__init__.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/core/bootstrap.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/core/cache.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/core/config.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/core/diff.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/core/git.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/core/git_hooks.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/core/global_install.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/core/ignore.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/core/merkle.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/core/models.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/core/redactor.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/core/scanner.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/core/snapshot.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/core/token_estimator.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/core/vscode_tasks.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/installers/__init__.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/installers/antigravity.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/installers/codex.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/integrations/__init__.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/integrations/agents.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/integrations/git_hooks.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/integrations/global_install.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/integrations/vscode_tasks.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/renderers/__init__.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/renderers/compact.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/renderers/markdown.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/renderers/receipts.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/session/__init__.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/session/state.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/summaries/__init__.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/summaries/base.py +0 -0
- {agentpack_cli-0.2.0 → agentpack_cli-0.2.2}/src/agentpack/summaries/offline.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentpack-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Task-aware context packing for AI coding agents — Claude, Cursor, Windsurf, Codex, and Antigravity
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -44,7 +44,7 @@ Description-Content-Type: text/markdown
|
|
|
44
44
|
[](https://opensource.org/licenses/MIT)
|
|
45
45
|
[](https://github.com/vishal2612200/agentpack/actions/workflows/ci.yml)
|
|
46
46
|
|
|
47
|
-
> **Status: alpha (v0.2.
|
|
47
|
+
> **Status: alpha (v0.2.1).** Works, tested, used in real sessions. Python and JavaScript/TypeScript are the best-supported languages. Not yet validated across a wide range of repos. API may change before 1.0.
|
|
48
48
|
>
|
|
49
49
|
> **Platform note:** macOS and Linux are fully supported. Windows support is not yet implemented (git hooks use POSIX shell; the Claude Code session hooks use `python3`/`rm -f`). Contributions welcome.
|
|
50
50
|
|
|
@@ -100,7 +100,8 @@ The npm package is a Node launcher around the Python implementation. It installs
|
|
|
100
100
|
```bash
|
|
101
101
|
cd your-project
|
|
102
102
|
agentpack init --agent codex # or claude, cursor, windsurf, antigravity
|
|
103
|
-
|
|
103
|
+
printf '%s\n' "fix auth token expiry" > .agentpack/task.md
|
|
104
|
+
agentpack pack
|
|
104
105
|
```
|
|
105
106
|
|
|
106
107
|
This creates `.agentpack/` state, installs the requested agent integration, generates a ranked context pack, and writes the adapter output for that agent. For active local work, keep context fresh with:
|
|
@@ -150,10 +151,19 @@ Use real repo evals instead of trusting compression numbers:
|
|
|
150
151
|
```bash
|
|
151
152
|
agentpack benchmark --init
|
|
152
153
|
# add historical tasks and files actually changed
|
|
153
|
-
agentpack benchmark --compare --misses
|
|
154
|
+
agentpack benchmark --compare --misses --public-table
|
|
155
|
+
agentpack benchmark --public-repos --prove-targets --misses --public-table
|
|
154
156
|
agentpack benchmark --results-template
|
|
155
157
|
```
|
|
156
158
|
|
|
159
|
+
For public proof, use several real repositories or anonymized historical task
|
|
160
|
+
sets and publish the generated table from `benchmarks/results/*-public.md`.
|
|
161
|
+
This repo includes a curated public smoke suite in
|
|
162
|
+
`benchmarks/public-repos.toml`; it evaluates real commits from Pallets Click,
|
|
163
|
+
ItsDangerous, and MarkupSafe by checking out each commit's parent and scoring
|
|
164
|
+
against files actually changed by the commit. Synthetic fixtures are useful
|
|
165
|
+
regression tests, but should not be presented as market proof.
|
|
166
|
+
|
|
157
167
|
## Debugging Selection
|
|
158
168
|
|
|
159
169
|
When AgentPack misses a file, the next command should explain the miss:
|
|
@@ -169,6 +179,41 @@ agentpack explain --task "fix billing webhook" --budget-plan
|
|
|
169
179
|
|
|
170
180
|
This is the core reliability loop: pack, measure recall, inspect misses, then tune task wording, `.agentignore`, or scoring weights.
|
|
171
181
|
|
|
182
|
+
## MCP-First Workflow
|
|
183
|
+
|
|
184
|
+
For MCP-capable agents, the preferred workflow is pull-based:
|
|
185
|
+
|
|
186
|
+
1. Call `start_task(task)` when a new task begins. AgentPack writes `.agentpack/task.md`, packs context, and returns ranked markdown.
|
|
187
|
+
2. Call `get_context()` when you need the latest cached pack; it tells you if the pack is stale.
|
|
188
|
+
3. Call `get_delta_context()` after edits or hook hints to see what changed without loading the full pack.
|
|
189
|
+
4. Call `explain_file(path)` or `get_related_files(path)` when a file looks relevant or suspicious.
|
|
190
|
+
|
|
191
|
+
The CLI remains the setup/debug/release path. MCP is the best interactive path because the agent can ask for only the context it needs instead of relying on one static startup blob.
|
|
192
|
+
|
|
193
|
+
## Before / After Agent Behavior
|
|
194
|
+
|
|
195
|
+
Without AgentPack:
|
|
196
|
+
|
|
197
|
+
```text
|
|
198
|
+
User: fix auth token expiry
|
|
199
|
+
Agent: rg "auth"; opens router; opens middleware; opens tests; opens config;
|
|
200
|
+
asks for more files; eventually finds token/session code.
|
|
201
|
+
Cost: repeated repo exploration and many unrelated file reads.
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
With AgentPack:
|
|
205
|
+
|
|
206
|
+
```text
|
|
207
|
+
User: fix auth token expiry
|
|
208
|
+
Agent: calls start_task("fix auth token expiry")
|
|
209
|
+
AgentPack: returns ranked files with reasons:
|
|
210
|
+
1. src/auth/token.py — filename/content match, changed dependency
|
|
211
|
+
2. src/auth/session.py — related implementation
|
|
212
|
+
3. tests/test_auth.py — paired test
|
|
213
|
+
Agent: verifies those files, edits, runs tests, checks misses if needed.
|
|
214
|
+
Cost: starts from a measured map, then still verifies source normally.
|
|
215
|
+
```
|
|
216
|
+
|
|
172
217
|
## When it helps
|
|
173
218
|
|
|
174
219
|
| Workflow | Value |
|
|
@@ -437,7 +482,8 @@ Most users only need four commands:
|
|
|
437
482
|
|
|
438
483
|
```bash
|
|
439
484
|
agentpack init --agent codex
|
|
440
|
-
|
|
485
|
+
printf '%s\n' "describe the change" > .agentpack/task.md
|
|
486
|
+
agentpack pack
|
|
441
487
|
agentpack watch
|
|
442
488
|
agentpack doctor --agent all
|
|
443
489
|
```
|
|
@@ -640,18 +686,21 @@ Summaries are built with parallel AST/regex analysis — no network, no tokens s
|
|
|
640
686
|
|
|
641
687
|
### `agentpack pack`
|
|
642
688
|
|
|
643
|
-
Generate a context pack.
|
|
689
|
+
Generate a context pack. Task text lives in `.agentpack/task.md`; inline task strings are no longer supported on `pack`. `--task auto` remains for old hooks and scripts, and is the default when the flag is omitted.
|
|
644
690
|
|
|
645
691
|
```bash
|
|
646
|
-
|
|
647
|
-
agentpack pack
|
|
648
|
-
agentpack pack --
|
|
692
|
+
printf '%s\n' "fix auth session bug" > .agentpack/task.md
|
|
693
|
+
agentpack pack # auto-detects your IDE
|
|
694
|
+
agentpack pack --agent claude # explicit agent
|
|
695
|
+
agentpack pack --workspace apps/web
|
|
649
696
|
|
|
650
697
|
# Only include changes since a git ref
|
|
651
|
-
|
|
698
|
+
printf '%s\n' "review these changes" > .agentpack/task.md
|
|
699
|
+
agentpack pack --since main
|
|
652
700
|
|
|
653
701
|
# Watch mode — re-packs on every file change
|
|
654
|
-
|
|
702
|
+
printf '%s\n' "refactor auth" > .agentpack/task.md
|
|
703
|
+
agentpack pack --session
|
|
655
704
|
```
|
|
656
705
|
|
|
657
706
|
Options:
|
|
@@ -659,7 +708,7 @@ Options:
|
|
|
659
708
|
| Flag | Default | Description |
|
|
660
709
|
|------|---------|-------------|
|
|
661
710
|
| `--agent` | `auto` | Target agent (`auto` \| `claude` \| `cursor` \| `windsurf` \| `codex` \| `antigravity` \| `generic`). `auto` detects the active IDE from env and project files. |
|
|
662
|
-
| `--task` | `auto` |
|
|
711
|
+
| `--task` | `auto` | Backward-compatible task source. Only `auto` is supported; write task text to `.agentpack/task.md`. |
|
|
663
712
|
| `--mode` | `balanced` | Budget mode: `minimal`, `balanced`, `deep` |
|
|
664
713
|
| `--budget` | 0 (uses config default 25000) | Token budget |
|
|
665
714
|
| `--workspace` | — | Restrict packing to a monorepo workspace and write `.agentpack/workspaces/<workspace>/context.md` |
|
|
@@ -761,7 +810,8 @@ Register in Claude Code settings (`~/.claude/settings.json`):
|
|
|
761
810
|
|
|
762
811
|
| Tool | Description |
|
|
763
812
|
|---|---|
|
|
764
|
-
| `
|
|
813
|
+
| `start_task(task, mode, budget, max_tokens)` | Recommended MCP-first entry point. Writes `.agentpack/task.md`, generates a ranked pack, and returns packed markdown. |
|
|
814
|
+
| `pack_context(task, mode, budget, max_tokens)` | Generate a ranked context pack. If `task` is provided, writes it to `.agentpack/task.md`; if omitted, reads `task.md` or infers from git. |
|
|
765
815
|
| `get_context()` | Return the latest pre-built pack instantly (no repack). Prepends a freshness/staleness header so you know if it's stale. |
|
|
766
816
|
| `refresh()` | Refresh using the current `task.md` or git-inferred task. |
|
|
767
817
|
| `explain_file(path, task)` | Show score, inclusion mode, reasons, symbols, imports, and importers for one file. |
|
|
@@ -774,7 +824,7 @@ Register in Claude Code settings (`~/.claude/settings.json`):
|
|
|
774
824
|
> **Stale context** — repo changed since last pack (generated: ...). Run pack_context() to refresh.
|
|
775
825
|
```
|
|
776
826
|
|
|
777
|
-
**Smart truncation:** `pack_context()`
|
|
827
|
+
**Smart truncation:** `start_task()` and `pack_context()` keep headers intact and trim file content blocks to fit the token budget, appending a note about how many files were omitted.
|
|
778
828
|
|
|
779
829
|
Zero API calls — all analysis is offline. Summary cache keyed by file hash: cold run parallelises AST parsing across CPU cores; warm cache hits are instant.
|
|
780
830
|
|
|
@@ -826,8 +876,10 @@ agentpack benchmark --init # scaffold .agentpack
|
|
|
826
876
|
agentpack benchmark --results-template # scaffold publishable results note
|
|
827
877
|
agentpack benchmark # run all cases in benchmark.toml
|
|
828
878
|
agentpack benchmark --sample-fixtures # source checkout demo evals
|
|
879
|
+
agentpack benchmark --public-repos # real public commit evals
|
|
829
880
|
agentpack benchmark --misses # explain expected-file misses
|
|
830
881
|
agentpack benchmark --prove-targets # fail if recall/token precision targets miss
|
|
882
|
+
agentpack benchmark --public-table # write benchmarks/results/*-public.md
|
|
831
883
|
```
|
|
832
884
|
|
|
833
885
|
Output per case:
|
|
@@ -884,6 +936,15 @@ Use `--misses` when recall is low. It prints each expected file that was not sel
|
|
|
884
936
|
|
|
885
937
|
Use `--prove-targets` in CI or release prep when benchmark cases have `expected_files`. By default it requires average recall >=60% and token precision >=50%; tune with `--min-recall` and `--min-token-precision`.
|
|
886
938
|
|
|
939
|
+
Use `--public-repos` from an AgentPack source checkout to run the committed
|
|
940
|
+
real-repo smoke suite:
|
|
941
|
+
|
|
942
|
+
```bash
|
|
943
|
+
agentpack benchmark --public-repos --prove-targets --misses --public-table
|
|
944
|
+
```
|
|
945
|
+
|
|
946
|
+
Use `--public-table` after adding real historical tasks to write a publishable Markdown table with per-repo/task recall, token precision, rank@K, pack size, and miss count. This is the recommended artifact for README claims, release notes, and external benchmarks.
|
|
947
|
+
|
|
887
948
|
Add `task_type` to group results by workflow area. Benchmark summaries report average precision, recall, F1, and token noise by type, so a repo can show "backend-api is good, frontend-web is noisy" instead of hiding that under one aggregate.
|
|
888
949
|
|
|
889
950
|
---
|
|
@@ -1313,7 +1374,7 @@ src/agentpack/
|
|
|
1313
1374
|
compact.py # compact protocol format for session context files
|
|
1314
1375
|
receipts.py # context receipt formatter
|
|
1315
1376
|
|
|
1316
|
-
mcp_server.py # MCP tools: pack_context, get_context, explain, related, stats, delta
|
|
1377
|
+
mcp_server.py # MCP tools: start_task, pack_context, get_context, explain, related, stats, delta
|
|
1317
1378
|
|
|
1318
1379
|
session/
|
|
1319
1380
|
state.py # SessionState dataclass + load/save/create/stop helpers
|
|
@@ -1351,6 +1412,7 @@ src/agentpack/
|
|
|
1351
1412
|
- **Repo maps are first-class context**: `analysis/repo_map.py` builds a compact semantic map before file context, and its token cost is reserved before file selection.
|
|
1352
1413
|
- **Metrics feed history learning**: selection accuracy records hit/noise paths, token precision, mode counts, and mode tokens. Later packs gently penalize repeated noisy paths unless they are currently changed.
|
|
1353
1414
|
- **Git history feeds recall**: files that historically changed in the same commits as live changed files receive a small boost, helping related tests, schemas, services, and configs surface without forcing full-content inclusion.
|
|
1415
|
+
- **Second-pass expansion is guarded**: after first scoring, strong seeds can lift two-hop import, reverse-import, config, and related-test neighbours only when they share task or domain signal.
|
|
1354
1416
|
- **Co-change is guarded by precision history**: one-off co-change neighbors are ignored, and paths repeatedly measured as noise do not get revived by history boosts.
|
|
1355
1417
|
- **Precision guardrails adapt to bad history**: when summary token precision stays near zero, later packs raise the summary score floor, cap summaries more aggressively, and suppress summaries entirely for no-live-change packs. Weak filename-only matches are also damped unless other signals confirm them.
|
|
1356
1418
|
- **`AdapterRegistry` maps agent → adapter**: adding a new agent output format requires one entry in `AdapterRegistry.get()`, not changes to `PackService`.
|
|
@@ -1359,7 +1421,7 @@ src/agentpack/
|
|
|
1359
1421
|
- **`integrations/` vs `core/`**: git hooks, shell rc patching, and VS Code tasks are infrastructure concerns — they live in `integrations/`, not `core/`. `core/` is pure domain logic.
|
|
1360
1422
|
- **Adapters render; installers configure**: `adapters/` knows how to write a context file for an agent. `installers/` knows how to configure the agent's tool (CLAUDE.md, .cursorrules, settings.json). They are separate concerns and separate classes.
|
|
1361
1423
|
- **Agent integration contract is shared**: `integrations/agents.py` defines install, audit, and repair behavior for Claude, Cursor, Windsurf, Codex, Antigravity, and Generic. `install`, `repair`, `doctor --agent all`, and release verification use the same contract.
|
|
1362
|
-
- **MCP
|
|
1424
|
+
- **MCP is the interactive path**: `start_task()` writes task state and returns a fresh pack, while `get_context()`, `get_delta_context()`, `explain_file()`, and `get_related_files()` let agents pull follow-up context on demand.
|
|
1363
1425
|
|
|
1364
1426
|
---
|
|
1365
1427
|
|
|
@@ -1378,7 +1440,7 @@ src/agentpack/
|
|
|
1378
1440
|
|
|
1379
1441
|
- **Windows**: not supported. Git hooks use POSIX shell (`#!/bin/sh`, `>/dev/null 2>&1 &`). The Claude Code session hooks use `python3` and `rm -f`. Contributions welcome.
|
|
1380
1442
|
- **Monorepos**: workspace-aware ranking supports npm/pnpm, Cargo, and `go.work` layouts. `--workspace` creates filtered per-workspace outputs. Package dependency hints currently come from npm/pnpm `package.json`; Cargo/Go workspace membership is detected, but package-manager dependency edges for Cargo/Go are not yet modeled.
|
|
1381
|
-
- **Public benchmark proof**:
|
|
1443
|
+
- **Public benchmark proof**: `benchmarks/public-repos.toml` is a curated smoke suite over real public commits, and `benchmarks/results/2026-05-15-public.md` records the current proof run. Treat it as a floor, not a leaderboard; expand cases before broad external claims.
|
|
1382
1444
|
- **Symbol extraction**: Python (AST, full) and JavaScript/TypeScript (regex, arrow functions + classes) are well-supported. Go, Rust, Java, Kotlin have import graph traversal but no symbol extraction — they fall back to file-level summaries.
|
|
1383
1445
|
- **Selection recall**: ranking is heuristic. It can miss files when task language differs from code language, when repos have unusual architecture, or when important files are only connected at runtime.
|
|
1384
1446
|
- **Secret redaction**: covers AWS keys, GitHub tokens, OpenAI/Anthropic keys, JWTs, and private key blocks. Not a substitute for a dedicated secrets scanner on sensitive repos.
|
|
@@ -1389,12 +1451,12 @@ src/agentpack/
|
|
|
1389
1451
|
|
|
1390
1452
|
## Roadmap
|
|
1391
1453
|
|
|
1392
|
-
Next release target: **0.
|
|
1454
|
+
Next release target: **0.3.0 = public proof + npm publish hardening**.
|
|
1393
1455
|
|
|
1394
|
-
- Expand public
|
|
1395
|
-
-
|
|
1396
|
-
-
|
|
1397
|
-
- Make
|
|
1456
|
+
- Expand the public real-repo suite beyond the current curated Pallets smoke set.
|
|
1457
|
+
- Keep recall gains measured with `--prove-targets`; target 60%+ recall, 50%+ token precision, and task packs under 25k tokens.
|
|
1458
|
+
- Extend second-pass expansion with framework route/service/schema pairs once benchmark misses prove the pattern.
|
|
1459
|
+
- Make npm publishing reliable by adding `NPM_TOKEN` and rerunning the npm release workflow.
|
|
1398
1460
|
- Keep integration contracts stable across Claude, Cursor, Windsurf, Codex, Antigravity, and Generic before any 1.0 work.
|
|
1399
1461
|
|
|
1400
1462
|
---
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
6
|
[](https://github.com/vishal2612200/agentpack/actions/workflows/ci.yml)
|
|
7
7
|
|
|
8
|
-
> **Status: alpha (v0.2.
|
|
8
|
+
> **Status: alpha (v0.2.1).** Works, tested, used in real sessions. Python and JavaScript/TypeScript are the best-supported languages. Not yet validated across a wide range of repos. API may change before 1.0.
|
|
9
9
|
>
|
|
10
10
|
> **Platform note:** macOS and Linux are fully supported. Windows support is not yet implemented (git hooks use POSIX shell; the Claude Code session hooks use `python3`/`rm -f`). Contributions welcome.
|
|
11
11
|
|
|
@@ -61,7 +61,8 @@ The npm package is a Node launcher around the Python implementation. It installs
|
|
|
61
61
|
```bash
|
|
62
62
|
cd your-project
|
|
63
63
|
agentpack init --agent codex # or claude, cursor, windsurf, antigravity
|
|
64
|
-
|
|
64
|
+
printf '%s\n' "fix auth token expiry" > .agentpack/task.md
|
|
65
|
+
agentpack pack
|
|
65
66
|
```
|
|
66
67
|
|
|
67
68
|
This creates `.agentpack/` state, installs the requested agent integration, generates a ranked context pack, and writes the adapter output for that agent. For active local work, keep context fresh with:
|
|
@@ -111,10 +112,19 @@ Use real repo evals instead of trusting compression numbers:
|
|
|
111
112
|
```bash
|
|
112
113
|
agentpack benchmark --init
|
|
113
114
|
# add historical tasks and files actually changed
|
|
114
|
-
agentpack benchmark --compare --misses
|
|
115
|
+
agentpack benchmark --compare --misses --public-table
|
|
116
|
+
agentpack benchmark --public-repos --prove-targets --misses --public-table
|
|
115
117
|
agentpack benchmark --results-template
|
|
116
118
|
```
|
|
117
119
|
|
|
120
|
+
For public proof, use several real repositories or anonymized historical task
|
|
121
|
+
sets and publish the generated table from `benchmarks/results/*-public.md`.
|
|
122
|
+
This repo includes a curated public smoke suite in
|
|
123
|
+
`benchmarks/public-repos.toml`; it evaluates real commits from Pallets Click,
|
|
124
|
+
ItsDangerous, and MarkupSafe by checking out each commit's parent and scoring
|
|
125
|
+
against files actually changed by the commit. Synthetic fixtures are useful
|
|
126
|
+
regression tests, but should not be presented as market proof.
|
|
127
|
+
|
|
118
128
|
## Debugging Selection
|
|
119
129
|
|
|
120
130
|
When AgentPack misses a file, the next command should explain the miss:
|
|
@@ -130,6 +140,41 @@ agentpack explain --task "fix billing webhook" --budget-plan
|
|
|
130
140
|
|
|
131
141
|
This is the core reliability loop: pack, measure recall, inspect misses, then tune task wording, `.agentignore`, or scoring weights.
|
|
132
142
|
|
|
143
|
+
## MCP-First Workflow
|
|
144
|
+
|
|
145
|
+
For MCP-capable agents, the preferred workflow is pull-based:
|
|
146
|
+
|
|
147
|
+
1. Call `start_task(task)` when a new task begins. AgentPack writes `.agentpack/task.md`, packs context, and returns ranked markdown.
|
|
148
|
+
2. Call `get_context()` when you need the latest cached pack; it tells you if the pack is stale.
|
|
149
|
+
3. Call `get_delta_context()` after edits or hook hints to see what changed without loading the full pack.
|
|
150
|
+
4. Call `explain_file(path)` or `get_related_files(path)` when a file looks relevant or suspicious.
|
|
151
|
+
|
|
152
|
+
The CLI remains the setup/debug/release path. MCP is the best interactive path because the agent can ask for only the context it needs instead of relying on one static startup blob.
|
|
153
|
+
|
|
154
|
+
## Before / After Agent Behavior
|
|
155
|
+
|
|
156
|
+
Without AgentPack:
|
|
157
|
+
|
|
158
|
+
```text
|
|
159
|
+
User: fix auth token expiry
|
|
160
|
+
Agent: rg "auth"; opens router; opens middleware; opens tests; opens config;
|
|
161
|
+
asks for more files; eventually finds token/session code.
|
|
162
|
+
Cost: repeated repo exploration and many unrelated file reads.
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
With AgentPack:
|
|
166
|
+
|
|
167
|
+
```text
|
|
168
|
+
User: fix auth token expiry
|
|
169
|
+
Agent: calls start_task("fix auth token expiry")
|
|
170
|
+
AgentPack: returns ranked files with reasons:
|
|
171
|
+
1. src/auth/token.py — filename/content match, changed dependency
|
|
172
|
+
2. src/auth/session.py — related implementation
|
|
173
|
+
3. tests/test_auth.py — paired test
|
|
174
|
+
Agent: verifies those files, edits, runs tests, checks misses if needed.
|
|
175
|
+
Cost: starts from a measured map, then still verifies source normally.
|
|
176
|
+
```
|
|
177
|
+
|
|
133
178
|
## When it helps
|
|
134
179
|
|
|
135
180
|
| Workflow | Value |
|
|
@@ -398,7 +443,8 @@ Most users only need four commands:
|
|
|
398
443
|
|
|
399
444
|
```bash
|
|
400
445
|
agentpack init --agent codex
|
|
401
|
-
|
|
446
|
+
printf '%s\n' "describe the change" > .agentpack/task.md
|
|
447
|
+
agentpack pack
|
|
402
448
|
agentpack watch
|
|
403
449
|
agentpack doctor --agent all
|
|
404
450
|
```
|
|
@@ -601,18 +647,21 @@ Summaries are built with parallel AST/regex analysis — no network, no tokens s
|
|
|
601
647
|
|
|
602
648
|
### `agentpack pack`
|
|
603
649
|
|
|
604
|
-
Generate a context pack.
|
|
650
|
+
Generate a context pack. Task text lives in `.agentpack/task.md`; inline task strings are no longer supported on `pack`. `--task auto` remains for old hooks and scripts, and is the default when the flag is omitted.
|
|
605
651
|
|
|
606
652
|
```bash
|
|
607
|
-
|
|
608
|
-
agentpack pack
|
|
609
|
-
agentpack pack --
|
|
653
|
+
printf '%s\n' "fix auth session bug" > .agentpack/task.md
|
|
654
|
+
agentpack pack # auto-detects your IDE
|
|
655
|
+
agentpack pack --agent claude # explicit agent
|
|
656
|
+
agentpack pack --workspace apps/web
|
|
610
657
|
|
|
611
658
|
# Only include changes since a git ref
|
|
612
|
-
|
|
659
|
+
printf '%s\n' "review these changes" > .agentpack/task.md
|
|
660
|
+
agentpack pack --since main
|
|
613
661
|
|
|
614
662
|
# Watch mode — re-packs on every file change
|
|
615
|
-
|
|
663
|
+
printf '%s\n' "refactor auth" > .agentpack/task.md
|
|
664
|
+
agentpack pack --session
|
|
616
665
|
```
|
|
617
666
|
|
|
618
667
|
Options:
|
|
@@ -620,7 +669,7 @@ Options:
|
|
|
620
669
|
| Flag | Default | Description |
|
|
621
670
|
|------|---------|-------------|
|
|
622
671
|
| `--agent` | `auto` | Target agent (`auto` \| `claude` \| `cursor` \| `windsurf` \| `codex` \| `antigravity` \| `generic`). `auto` detects the active IDE from env and project files. |
|
|
623
|
-
| `--task` | `auto` |
|
|
672
|
+
| `--task` | `auto` | Backward-compatible task source. Only `auto` is supported; write task text to `.agentpack/task.md`. |
|
|
624
673
|
| `--mode` | `balanced` | Budget mode: `minimal`, `balanced`, `deep` |
|
|
625
674
|
| `--budget` | 0 (uses config default 25000) | Token budget |
|
|
626
675
|
| `--workspace` | — | Restrict packing to a monorepo workspace and write `.agentpack/workspaces/<workspace>/context.md` |
|
|
@@ -722,7 +771,8 @@ Register in Claude Code settings (`~/.claude/settings.json`):
|
|
|
722
771
|
|
|
723
772
|
| Tool | Description |
|
|
724
773
|
|---|---|
|
|
725
|
-
| `
|
|
774
|
+
| `start_task(task, mode, budget, max_tokens)` | Recommended MCP-first entry point. Writes `.agentpack/task.md`, generates a ranked pack, and returns packed markdown. |
|
|
775
|
+
| `pack_context(task, mode, budget, max_tokens)` | Generate a ranked context pack. If `task` is provided, writes it to `.agentpack/task.md`; if omitted, reads `task.md` or infers from git. |
|
|
726
776
|
| `get_context()` | Return the latest pre-built pack instantly (no repack). Prepends a freshness/staleness header so you know if it's stale. |
|
|
727
777
|
| `refresh()` | Refresh using the current `task.md` or git-inferred task. |
|
|
728
778
|
| `explain_file(path, task)` | Show score, inclusion mode, reasons, symbols, imports, and importers for one file. |
|
|
@@ -735,7 +785,7 @@ Register in Claude Code settings (`~/.claude/settings.json`):
|
|
|
735
785
|
> **Stale context** — repo changed since last pack (generated: ...). Run pack_context() to refresh.
|
|
736
786
|
```
|
|
737
787
|
|
|
738
|
-
**Smart truncation:** `pack_context()`
|
|
788
|
+
**Smart truncation:** `start_task()` and `pack_context()` keep headers intact and trim file content blocks to fit the token budget, appending a note about how many files were omitted.
|
|
739
789
|
|
|
740
790
|
Zero API calls — all analysis is offline. Summary cache keyed by file hash: cold run parallelises AST parsing across CPU cores; warm cache hits are instant.
|
|
741
791
|
|
|
@@ -787,8 +837,10 @@ agentpack benchmark --init # scaffold .agentpack
|
|
|
787
837
|
agentpack benchmark --results-template # scaffold publishable results note
|
|
788
838
|
agentpack benchmark # run all cases in benchmark.toml
|
|
789
839
|
agentpack benchmark --sample-fixtures # source checkout demo evals
|
|
840
|
+
agentpack benchmark --public-repos # real public commit evals
|
|
790
841
|
agentpack benchmark --misses # explain expected-file misses
|
|
791
842
|
agentpack benchmark --prove-targets # fail if recall/token precision targets miss
|
|
843
|
+
agentpack benchmark --public-table # write benchmarks/results/*-public.md
|
|
792
844
|
```
|
|
793
845
|
|
|
794
846
|
Output per case:
|
|
@@ -845,6 +897,15 @@ Use `--misses` when recall is low. It prints each expected file that was not sel
|
|
|
845
897
|
|
|
846
898
|
Use `--prove-targets` in CI or release prep when benchmark cases have `expected_files`. By default it requires average recall >=60% and token precision >=50%; tune with `--min-recall` and `--min-token-precision`.
|
|
847
899
|
|
|
900
|
+
Use `--public-repos` from an AgentPack source checkout to run the committed
|
|
901
|
+
real-repo smoke suite:
|
|
902
|
+
|
|
903
|
+
```bash
|
|
904
|
+
agentpack benchmark --public-repos --prove-targets --misses --public-table
|
|
905
|
+
```
|
|
906
|
+
|
|
907
|
+
Use `--public-table` after adding real historical tasks to write a publishable Markdown table with per-repo/task recall, token precision, rank@K, pack size, and miss count. This is the recommended artifact for README claims, release notes, and external benchmarks.
|
|
908
|
+
|
|
848
909
|
Add `task_type` to group results by workflow area. Benchmark summaries report average precision, recall, F1, and token noise by type, so a repo can show "backend-api is good, frontend-web is noisy" instead of hiding that under one aggregate.
|
|
849
910
|
|
|
850
911
|
---
|
|
@@ -1274,7 +1335,7 @@ src/agentpack/
|
|
|
1274
1335
|
compact.py # compact protocol format for session context files
|
|
1275
1336
|
receipts.py # context receipt formatter
|
|
1276
1337
|
|
|
1277
|
-
mcp_server.py # MCP tools: pack_context, get_context, explain, related, stats, delta
|
|
1338
|
+
mcp_server.py # MCP tools: start_task, pack_context, get_context, explain, related, stats, delta
|
|
1278
1339
|
|
|
1279
1340
|
session/
|
|
1280
1341
|
state.py # SessionState dataclass + load/save/create/stop helpers
|
|
@@ -1312,6 +1373,7 @@ src/agentpack/
|
|
|
1312
1373
|
- **Repo maps are first-class context**: `analysis/repo_map.py` builds a compact semantic map before file context, and its token cost is reserved before file selection.
|
|
1313
1374
|
- **Metrics feed history learning**: selection accuracy records hit/noise paths, token precision, mode counts, and mode tokens. Later packs gently penalize repeated noisy paths unless they are currently changed.
|
|
1314
1375
|
- **Git history feeds recall**: files that historically changed in the same commits as live changed files receive a small boost, helping related tests, schemas, services, and configs surface without forcing full-content inclusion.
|
|
1376
|
+
- **Second-pass expansion is guarded**: after first scoring, strong seeds can lift two-hop import, reverse-import, config, and related-test neighbours only when they share task or domain signal.
|
|
1315
1377
|
- **Co-change is guarded by precision history**: one-off co-change neighbors are ignored, and paths repeatedly measured as noise do not get revived by history boosts.
|
|
1316
1378
|
- **Precision guardrails adapt to bad history**: when summary token precision stays near zero, later packs raise the summary score floor, cap summaries more aggressively, and suppress summaries entirely for no-live-change packs. Weak filename-only matches are also damped unless other signals confirm them.
|
|
1317
1379
|
- **`AdapterRegistry` maps agent → adapter**: adding a new agent output format requires one entry in `AdapterRegistry.get()`, not changes to `PackService`.
|
|
@@ -1320,7 +1382,7 @@ src/agentpack/
|
|
|
1320
1382
|
- **`integrations/` vs `core/`**: git hooks, shell rc patching, and VS Code tasks are infrastructure concerns — they live in `integrations/`, not `core/`. `core/` is pure domain logic.
|
|
1321
1383
|
- **Adapters render; installers configure**: `adapters/` knows how to write a context file for an agent. `installers/` knows how to configure the agent's tool (CLAUDE.md, .cursorrules, settings.json). They are separate concerns and separate classes.
|
|
1322
1384
|
- **Agent integration contract is shared**: `integrations/agents.py` defines install, audit, and repair behavior for Claude, Cursor, Windsurf, Codex, Antigravity, and Generic. `install`, `repair`, `doctor --agent all`, and release verification use the same contract.
|
|
1323
|
-
- **MCP
|
|
1385
|
+
- **MCP is the interactive path**: `start_task()` writes task state and returns a fresh pack, while `get_context()`, `get_delta_context()`, `explain_file()`, and `get_related_files()` let agents pull follow-up context on demand.
|
|
1324
1386
|
|
|
1325
1387
|
---
|
|
1326
1388
|
|
|
@@ -1339,7 +1401,7 @@ src/agentpack/
|
|
|
1339
1401
|
|
|
1340
1402
|
- **Windows**: not supported. Git hooks use POSIX shell (`#!/bin/sh`, `>/dev/null 2>&1 &`). The Claude Code session hooks use `python3` and `rm -f`. Contributions welcome.
|
|
1341
1403
|
- **Monorepos**: workspace-aware ranking supports npm/pnpm, Cargo, and `go.work` layouts. `--workspace` creates filtered per-workspace outputs. Package dependency hints currently come from npm/pnpm `package.json`; Cargo/Go workspace membership is detected, but package-manager dependency edges for Cargo/Go are not yet modeled.
|
|
1342
|
-
- **Public benchmark proof**:
|
|
1404
|
+
- **Public benchmark proof**: `benchmarks/public-repos.toml` is a curated smoke suite over real public commits, and `benchmarks/results/2026-05-15-public.md` records the current proof run. Treat it as a floor, not a leaderboard; expand cases before broad external claims.
|
|
1343
1405
|
- **Symbol extraction**: Python (AST, full) and JavaScript/TypeScript (regex, arrow functions + classes) are well-supported. Go, Rust, Java, Kotlin have import graph traversal but no symbol extraction — they fall back to file-level summaries.
|
|
1344
1406
|
- **Selection recall**: ranking is heuristic. It can miss files when task language differs from code language, when repos have unusual architecture, or when important files are only connected at runtime.
|
|
1345
1407
|
- **Secret redaction**: covers AWS keys, GitHub tokens, OpenAI/Anthropic keys, JWTs, and private key blocks. Not a substitute for a dedicated secrets scanner on sensitive repos.
|
|
@@ -1350,12 +1412,12 @@ src/agentpack/
|
|
|
1350
1412
|
|
|
1351
1413
|
## Roadmap
|
|
1352
1414
|
|
|
1353
|
-
Next release target: **0.
|
|
1415
|
+
Next release target: **0.3.0 = public proof + npm publish hardening**.
|
|
1354
1416
|
|
|
1355
|
-
- Expand public
|
|
1356
|
-
-
|
|
1357
|
-
-
|
|
1358
|
-
- Make
|
|
1417
|
+
- Expand the public real-repo suite beyond the current curated Pallets smoke set.
|
|
1418
|
+
- Keep recall gains measured with `--prove-targets`; target 60%+ recall, 50%+ token precision, and task packs under 25k tokens.
|
|
1419
|
+
- Extend second-pass expansion with framework route/service/schema pairs once benchmark misses prove the pattern.
|
|
1420
|
+
- Make npm publishing reliable by adding `NPM_TOKEN` and rerunning the npm release workflow.
|
|
1359
1421
|
- Keep integration contracts stable across Claude, Cursor, Windsurf, Codex, Antigravity, and Generic before any 1.0 work.
|
|
1360
1422
|
|
|
1361
1423
|
---
|
|
@@ -37,8 +37,9 @@ def build(
|
|
|
37
37
|
if summaries and fi.path in summaries:
|
|
38
38
|
cached_imports = summaries[fi.path].get("imports", [])
|
|
39
39
|
if cached_imports:
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
resolved_cached = _resolve_imports(fi.path, fi.language, cached_imports, root, path_set)
|
|
41
|
+
graph.nodes[fi.path].imports = resolved_cached
|
|
42
|
+
for dep in resolved_cached:
|
|
42
43
|
if dep in graph:
|
|
43
44
|
graph.nodes[dep].imported_by.append(fi.path)
|
|
44
45
|
continue
|
|
@@ -58,19 +59,7 @@ def build(
|
|
|
58
59
|
elif lang in ("java", "kotlin"):
|
|
59
60
|
raw_imports = java_imports(fi.abs_path, cached)
|
|
60
61
|
|
|
61
|
-
resolved
|
|
62
|
-
for imp in raw_imports:
|
|
63
|
-
if imp.startswith("."):
|
|
64
|
-
if lang == "python":
|
|
65
|
-
r = py_resolve(fi.path, imp, root)
|
|
66
|
-
elif lang in ("javascript", "typescript"):
|
|
67
|
-
r = js_resolve(fi.path, imp, root)
|
|
68
|
-
else:
|
|
69
|
-
r = None
|
|
70
|
-
if r and r in path_set:
|
|
71
|
-
resolved.append(r)
|
|
72
|
-
else:
|
|
73
|
-
resolved.append(imp)
|
|
62
|
+
resolved = _resolve_imports(fi.path, lang, raw_imports, root, path_set)
|
|
74
63
|
|
|
75
64
|
graph.nodes[fi.path].imports = resolved
|
|
76
65
|
for dep in resolved:
|
|
@@ -78,3 +67,26 @@ def build(
|
|
|
78
67
|
graph.nodes[dep].imported_by.append(fi.path)
|
|
79
68
|
|
|
80
69
|
return graph
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _resolve_imports(
|
|
73
|
+
importer: str,
|
|
74
|
+
language: str | None,
|
|
75
|
+
imports: list[str],
|
|
76
|
+
root: Path,
|
|
77
|
+
path_set: set[str],
|
|
78
|
+
) -> list[str]:
|
|
79
|
+
resolved: list[str] = []
|
|
80
|
+
for imp in imports:
|
|
81
|
+
if imp.startswith("."):
|
|
82
|
+
if language == "python":
|
|
83
|
+
r = py_resolve(importer, imp, root)
|
|
84
|
+
elif language in ("javascript", "typescript"):
|
|
85
|
+
r = js_resolve(importer, imp, root)
|
|
86
|
+
else:
|
|
87
|
+
r = None
|
|
88
|
+
if r and r in path_set:
|
|
89
|
+
resolved.append(r)
|
|
90
|
+
else:
|
|
91
|
+
resolved.append(imp)
|
|
92
|
+
return resolved
|
|
@@ -695,6 +695,96 @@ def boost_recall_neighbors(
|
|
|
695
695
|
return result
|
|
696
696
|
|
|
697
697
|
|
|
698
|
+
def boost_second_pass_expansion(
|
|
699
|
+
scored: list[tuple[FileInfo, float, list[str]]],
|
|
700
|
+
dep_graph: DependencyGraph,
|
|
701
|
+
keywords: set[str] | dict[str, float],
|
|
702
|
+
weights: ScoringWeights | None = None,
|
|
703
|
+
*,
|
|
704
|
+
seed_limit: int = 10,
|
|
705
|
+
max_boosts: int = 32,
|
|
706
|
+
) -> list[tuple[FileInfo, float, list[str]]]:
|
|
707
|
+
"""Boost guarded two-hop neighbours around strong first-pass seeds.
|
|
708
|
+
|
|
709
|
+
This is deliberately conservative: it only boosts files that are close to a
|
|
710
|
+
strong seed and share task/domain signal, are paired tests, or are config
|
|
711
|
+
files. That raises recall for adjacent implementation files without turning
|
|
712
|
+
broad task wording into repo-wide expansion.
|
|
713
|
+
"""
|
|
714
|
+
if not scored:
|
|
715
|
+
return scored
|
|
716
|
+
w = weights or _DEFAULT_WEIGHTS
|
|
717
|
+
path_map = {fi.path: (fi, score, reasons) for fi, score, reasons in scored}
|
|
718
|
+
keyword_tokens = set(_keyword_token_weights(keywords)) - _PATH_NOISE_TOKENS
|
|
719
|
+
|
|
720
|
+
seed_paths = [
|
|
721
|
+
fi.path
|
|
722
|
+
for fi, score, reasons in sorted(scored, key=lambda row: row[1], reverse=True)
|
|
723
|
+
if score >= 100
|
|
724
|
+
or any(
|
|
725
|
+
reason.startswith((
|
|
726
|
+
"modified",
|
|
727
|
+
"staged",
|
|
728
|
+
"workspace match",
|
|
729
|
+
"cross-layer related",
|
|
730
|
+
"recall neighbor",
|
|
731
|
+
"historically co-changed",
|
|
732
|
+
))
|
|
733
|
+
for reason in reasons
|
|
734
|
+
)
|
|
735
|
+
][:seed_limit]
|
|
736
|
+
if not seed_paths:
|
|
737
|
+
return scored
|
|
738
|
+
|
|
739
|
+
boosts: dict[str, tuple[float, str, str]] = {}
|
|
740
|
+
|
|
741
|
+
def neighbours(path: str) -> set[str]:
|
|
742
|
+
node = dep_graph.get(path)
|
|
743
|
+
return {p for p in (*node.imports, *node.imported_by, *node.tests) if p in path_map and p != path}
|
|
744
|
+
|
|
745
|
+
for seed in seed_paths:
|
|
746
|
+
seed_domains = _domain_tokens(seed) | keyword_tokens
|
|
747
|
+
first_hop = neighbours(seed)
|
|
748
|
+
second_hop = {candidate for hop in first_hop for candidate in neighbours(hop)}
|
|
749
|
+
for candidate in sorted(second_hop - {seed} - first_hop):
|
|
750
|
+
fi, _score, _reasons = path_map[candidate]
|
|
751
|
+
if fi.ignored or fi.binary:
|
|
752
|
+
continue
|
|
753
|
+
candidate_domains = _domain_tokens(candidate)
|
|
754
|
+
is_test_pair = _is_test_file(candidate) and (
|
|
755
|
+
any(_test_matches_source(candidate, hop) for hop in first_hop | {seed})
|
|
756
|
+
or any(_test_matches_source(candidate, hop) for hop in seed_domains)
|
|
757
|
+
)
|
|
758
|
+
has_domain_signal = bool(candidate_domains & seed_domains)
|
|
759
|
+
has_config_signal = _is_config_file(candidate) and bool(seed_domains)
|
|
760
|
+
if not (is_test_pair or has_domain_signal or has_config_signal):
|
|
761
|
+
continue
|
|
762
|
+
amount = w.recall_neighbor * 0.5
|
|
763
|
+
label = "second-pass related test" if is_test_pair else "second-pass recall neighbor"
|
|
764
|
+
if has_domain_signal:
|
|
765
|
+
amount += 4
|
|
766
|
+
current = boosts.get(candidate)
|
|
767
|
+
if current is None or amount > current[0]:
|
|
768
|
+
boosts[candidate] = (amount, seed, label)
|
|
769
|
+
|
|
770
|
+
if not boosts:
|
|
771
|
+
return scored
|
|
772
|
+
keep = {
|
|
773
|
+
path: value
|
|
774
|
+
for path, value in sorted(boosts.items(), key=lambda item: item[1][0], reverse=True)[:max_boosts]
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
result: list[tuple[FileInfo, float, list[str]]] = []
|
|
778
|
+
for fi, score, reasons in scored:
|
|
779
|
+
boost = keep.get(fi.path)
|
|
780
|
+
if boost:
|
|
781
|
+
amount, seed, label = boost
|
|
782
|
+
score += amount
|
|
783
|
+
reasons = reasons + [f"{label} of {seed}"]
|
|
784
|
+
result.append((fi, score, reasons))
|
|
785
|
+
return result
|
|
786
|
+
|
|
787
|
+
|
|
698
788
|
def boost_monorepo_workspaces(
|
|
699
789
|
scored: list[tuple[FileInfo, float, list[str]]],
|
|
700
790
|
*,
|