agentpack-cli 0.3.25__tar.gz → 0.3.26__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.3.25 → agentpack_cli-0.3.26}/PKG-INFO +1 -1
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/pyproject.toml +1 -1
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/__init__.py +1 -1
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/application/pack_service.py +7 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/benchmark.py +20 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/doctor.py +37 -4
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/next_cmd.py +4 -3
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/pack.py +3 -2
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/start_cmd.py +2 -3
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/status.py +2 -1
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/task_cmd.py +3 -2
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/workflow_cmd.py +5 -3
- agentpack_cli-0.3.26/src/agentpack/core/command_surface.py +127 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/context_pack.py +12 -1
- agentpack_cli-0.3.26/src/agentpack/core/e2e_benchmark.py +75 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/data/agentpack.md +7 -7
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/data/codex_plugin/.codex-plugin/plugin.json +1 -1
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/data/codex_plugin/skills/agentpack-refresh.md +3 -3
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/installers/antigravity.py +19 -9
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/installers/claude.py +23 -9
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/installers/codex.py +19 -9
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/installers/cursor.py +23 -25
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/installers/windsurf.py +20 -10
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/integrations/agents.py +11 -9
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/integrations/vscode_tasks.py +5 -2
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/mcp_server.py +56 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/renderers/markdown.py +14 -3
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/router/models.py +5 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/router/prompt_builder.py +19 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/router/service.py +239 -1
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/.gitignore +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/LICENSE +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/README.md +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/adapters/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/adapters/antigravity.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/adapters/base.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/adapters/claude.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/adapters/codex.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/adapters/cursor.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/adapters/detect.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/adapters/generic.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/adapters/windsurf.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/analysis/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/analysis/dependency_graph.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/analysis/go_imports.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/analysis/java_imports.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/analysis/js_ts_imports.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/analysis/monorepo.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/analysis/naming_signals.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/analysis/python_ast.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/analysis/python_imports.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/analysis/ranking.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/analysis/repo_map.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/analysis/role_inference.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/analysis/rust_imports.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/analysis/symbols.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/analysis/task_classifier.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/analysis/tests.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/application/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/cli.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/_shared.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/ci_cmd.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/claude_cmd.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/compress_output.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/dashboard.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/dev_check.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/diagnose_selection.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/diff.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/eval_cmd.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/explain.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/guard.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/hook_cmd.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/ignore_cmd.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/init.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/install.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/learn.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/mcp_cmd.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/memory.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/migrate.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/monitor.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/perf.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/quickstart.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/release_check.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/release_cmd.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/repair.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/retrieve.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/route.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/scan.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/skills.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/state_cmd.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/stats.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/summarize.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/threads.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/tune.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/upgrade.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/verify_wheel.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/watch.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/commands/wrap.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/bootstrap.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/cache.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/changed_paths.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/config.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/diff.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/evals.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/execution_state.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/git.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/git_hooks.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/global_install.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/ignore.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/loop_protocol.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/merkle.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/models.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/modes.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/pack_registry.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/redactor.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/scanner.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/snapshot.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/task_freshness.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/thread_context.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/token_estimator.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/core/vscode_tasks.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/dashboard/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/dashboard/collectors.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/dashboard/models.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/dashboard/renderers.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/data/codex_plugin/skills/agentpack-pack.md +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/data/codex_plugin/skills/agentpack-review.md +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/data/codex_plugin/skills/agentpack-route.md +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/data/codex_plugin/skills/agentpack.md +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/installers/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/integrations/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/integrations/git_hooks.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/integrations/global_install.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/integrations/platform.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/learning/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/learning/collector.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/learning/extractor.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/learning/feedback.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/learning/lesson_ranker.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/learning/models.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/learning/provider.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/learning/quality.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/learning/renderers.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/learning/skill_map.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/output_compression/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/output_compression/core.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/renderers/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/renderers/compact.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/renderers/receipts.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/router/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/router/discovery.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/router/parser.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/router/scoring.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/router/skills_index.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/session/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/session/events.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/session/state.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/summaries/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/src/agentpack/summaries/base.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.26}/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.3.
|
|
3
|
+
Version: 0.3.26
|
|
4
4
|
Summary: Local context engine for AI coding agents that ranks relevant repo files and builds compact task-focused context packs for Claude Code, Codex, Cursor, Windsurf, MCP, and CI workflows.
|
|
5
5
|
Project-URL: Homepage, https://github.com/vishal2612200/agentpack
|
|
6
6
|
Project-URL: Documentation, https://vishal2612200.github.io/agentpack/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "agentpack-cli"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.26"
|
|
4
4
|
description = "Local context engine for AI coding agents that ranks relevant repo files and builds compact task-focused context packs for Claude Code, Codex, Cursor, Windsurf, MCP, and CI workflows."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
@@ -9,6 +9,7 @@ from datetime import datetime, timezone
|
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
from typing import Any
|
|
11
11
|
|
|
12
|
+
from agentpack import __version__
|
|
12
13
|
from agentpack.core.config import load_config
|
|
13
14
|
from agentpack.core.changed_paths import clear_changed_paths, read_changed_paths
|
|
14
15
|
from agentpack.core.ignore import DEFAULT_AGENTIGNORE, load_spec
|
|
@@ -16,6 +17,7 @@ from agentpack.core.scanner import scan, scan_incremental
|
|
|
16
17
|
from agentpack.core.snapshot import build_snapshot, save_snapshot, load_snapshot
|
|
17
18
|
from agentpack.core.diff import diff_snapshots
|
|
18
19
|
from agentpack.core import git
|
|
20
|
+
from agentpack.core.command_surface import refresh_commands
|
|
19
21
|
from agentpack.core.context_pack import enrich_call_site_scores, select_files, save_pack_metadata, load_pack_metadata
|
|
20
22
|
from agentpack.core.execution_state import build_execution_state, compact_execution_state
|
|
21
23
|
from agentpack.core.models import (
|
|
@@ -1575,7 +1577,12 @@ def _build_freshness_metadata(
|
|
|
1575
1577
|
) -> dict[str, Any]:
|
|
1576
1578
|
dirty = git.dirty_files(root) if git.is_git_repo(root) else set()
|
|
1577
1579
|
metadata: dict[str, Any] = {
|
|
1580
|
+
"agentpack_version": __version__,
|
|
1578
1581
|
"generated_at": datetime.now(timezone.utc).isoformat(),
|
|
1582
|
+
"cwd": str(Path.cwd()),
|
|
1583
|
+
"git_root": str(root),
|
|
1584
|
+
"worktree_path": str(root),
|
|
1585
|
+
"source_command": refresh_commands(request.agent).primary,
|
|
1579
1586
|
"task_source": request.task_source,
|
|
1580
1587
|
"changed_files_source": plan.changed_files_source,
|
|
1581
1588
|
"snapshot_root_hash": snapshot_root_hash,
|
|
@@ -166,6 +166,7 @@ class E2EResult:
|
|
|
166
166
|
expected_files_touched: list[str]
|
|
167
167
|
missing_expected_edits: list[str]
|
|
168
168
|
unexpected_files_touched: list[str]
|
|
169
|
+
agentpack_noise: list[str]
|
|
169
170
|
agent_log_path: str
|
|
170
171
|
test_log_path: str
|
|
171
172
|
workdir: str
|
|
@@ -3226,6 +3227,7 @@ def _e2e_strategy_metrics(records: list[dict[str, Any]], strategy: str) -> dict[
|
|
|
3226
3227
|
return {
|
|
3227
3228
|
"runs": float(len(subset)),
|
|
3228
3229
|
"success_rate": sum(1 for row in subset if row.get("passed")) / len(subset),
|
|
3230
|
+
"noise_rate": sum(1 for row in subset if row.get("agentpack_noise")) / len(subset),
|
|
3229
3231
|
"expected_touch_rate": expected_touch_rate,
|
|
3230
3232
|
"avg_input_tokens": avg("input_tokens"),
|
|
3231
3233
|
"avg_output_tokens": avg("agent_output_tokens"),
|
|
@@ -3285,6 +3287,7 @@ def _print_e2e_ab_table(
|
|
|
3285
3287
|
table.add_row("runs", f"{base['runs']:.0f}", f"{treat['runs']:.0f}", "-")
|
|
3286
3288
|
table.add_row("task success", f"{base['success_rate']:.0%}", f"{treat['success_rate']:.0%}", f"{deltas['success_rate_pp']:+.1f} pp")
|
|
3287
3289
|
table.add_row("expected file touched", f"{base['expected_touch_rate']:.0%}", f"{treat['expected_touch_rate']:.0%}", "-")
|
|
3290
|
+
table.add_row("AgentPack noise cases", f"{base['noise_rate']:.0%}", f"{treat['noise_rate']:.0%}", "-")
|
|
3288
3291
|
table.add_row("tool calls", f"{base['avg_tool_calls']:.1f}", f"{treat['avg_tool_calls']:.1f}", f"{deltas['tool_calls_saved']:+.1f}")
|
|
3289
3292
|
table.add_row("tokens", f"{base['avg_total_tokens']:,.0f}", f"{treat['avg_total_tokens']:,.0f}", f"{deltas['tokens_saved']:+,.0f}")
|
|
3290
3293
|
table.add_row("cost", f"${base['avg_total_cost_usd']:.4f}", f"${treat['avg_total_cost_usd']:.4f}", _fmt_signed_usd(deltas["token_cost_saved_usd"]))
|
|
@@ -3317,6 +3320,7 @@ def _e2e_ab_markdown(
|
|
|
3317
3320
|
f"| runs | {base['runs']:.0f} | {treat['runs']:.0f} | - |",
|
|
3318
3321
|
f"| task success | {base['success_rate']:.0%} | {treat['success_rate']:.0%} | {deltas['success_rate_pp']:+.1f} pp |",
|
|
3319
3322
|
f"| expected file touched | {base['expected_touch_rate']:.0%} | {treat['expected_touch_rate']:.0%} | - |",
|
|
3323
|
+
f"| AgentPack noise cases | {base['noise_rate']:.0%} | {treat['noise_rate']:.0%} | - |",
|
|
3320
3324
|
f"| tool calls | {base['avg_tool_calls']:.1f} | {treat['avg_tool_calls']:.1f} | {deltas['tool_calls_saved']:+.1f} |",
|
|
3321
3325
|
f"| tokens | {base['avg_total_tokens']:,.0f} | {treat['avg_total_tokens']:,.0f} | {deltas['tokens_saved']:+,.0f} |",
|
|
3322
3326
|
f"| token cost | ${base['avg_total_cost_usd']:.4f} | ${treat['avg_total_cost_usd']:.4f} | {_fmt_signed_usd(deltas['token_cost_saved_usd'])} |",
|
|
@@ -3410,6 +3414,7 @@ def _run_e2e_case(
|
|
|
3410
3414
|
expected_touched = _expected_files_touched(public_changed, case.expected_edit_paths)
|
|
3411
3415
|
missing_expected = sorted(set(case.expected_edit_paths) - set(expected_touched))
|
|
3412
3416
|
unexpected_touched = _unexpected_files_touched(public_changed, case.expected_edit_paths)
|
|
3417
|
+
agentpack_noise = _agentpack_noise(strategy, unexpected_touched, missing_expected, public_changed)
|
|
3413
3418
|
time_to_first_expected_file = _time_to_first_expected_file(repo, expected_touched, agent_start_epoch)
|
|
3414
3419
|
tool_calls = _estimate_agent_tool_calls(agent)
|
|
3415
3420
|
duration = time.perf_counter() - start
|
|
@@ -3442,6 +3447,7 @@ def _run_e2e_case(
|
|
|
3442
3447
|
expected_files_touched=expected_touched,
|
|
3443
3448
|
missing_expected_edits=missing_expected,
|
|
3444
3449
|
unexpected_files_touched=unexpected_touched,
|
|
3450
|
+
agentpack_noise=agentpack_noise,
|
|
3445
3451
|
agent_log_path=str(agent_log_path),
|
|
3446
3452
|
test_log_path=str(test_log_path),
|
|
3447
3453
|
workdir=str(work_root),
|
|
@@ -3495,6 +3501,20 @@ def _unexpected_files_touched(changed: list[str], expected_edit_paths: list[str]
|
|
|
3495
3501
|
return sorted(path for path in changed if path not in expected)
|
|
3496
3502
|
|
|
3497
3503
|
|
|
3504
|
+
def _agentpack_noise(strategy: str, unexpected: list[str], missing_expected: list[str], changed: list[str]) -> list[str]:
|
|
3505
|
+
if "agentpack" not in strategy:
|
|
3506
|
+
return []
|
|
3507
|
+
noise: list[str] = []
|
|
3508
|
+
if unexpected:
|
|
3509
|
+
noise.append(f"unexpected edits: {', '.join(unexpected[:5])}")
|
|
3510
|
+
if missing_expected:
|
|
3511
|
+
noise.append(f"missed expected files: {', '.join(missing_expected[:5])}")
|
|
3512
|
+
generated = [path for path in changed if _is_generated_e2e_path(path)]
|
|
3513
|
+
if generated:
|
|
3514
|
+
noise.append(f"generated AgentPack files changed: {', '.join(generated[:5])}")
|
|
3515
|
+
return noise
|
|
3516
|
+
|
|
3517
|
+
|
|
3498
3518
|
def _process_output_tokens(result: subprocess.CompletedProcess[str]) -> int:
|
|
3499
3519
|
return estimate_tokens("\n".join(part for part in (result.stdout, result.stderr) if part))
|
|
3500
3520
|
|
|
@@ -17,6 +17,7 @@ from agentpack.integrations.global_install import (
|
|
|
17
17
|
_detect_rc_file,
|
|
18
18
|
)
|
|
19
19
|
from agentpack.commands._shared import console, _root
|
|
20
|
+
from agentpack.core.command_surface import available_cli_commands, installed_cli_status, refresh_commands
|
|
20
21
|
from agentpack.core.context_pack import load_pack_metadata
|
|
21
22
|
from agentpack.core.ignore import agentignore_sync_status, format_import_summary
|
|
22
23
|
from agentpack.core.task_freshness import task_freshness
|
|
@@ -45,7 +46,12 @@ def register(app: typer.Typer) -> None:
|
|
|
45
46
|
|
|
46
47
|
# --- CLI binary ---
|
|
47
48
|
console.print("[bold]CLI[/]")
|
|
48
|
-
|
|
49
|
+
cli_status = installed_cli_status()
|
|
50
|
+
binary = cli_status.get("binary") or shutil.which("agentpack")
|
|
51
|
+
console.print(f" [green]✓[/] importable AgentPack version: {cli_status.get('agentpack_version')}")
|
|
52
|
+
importable = cli_status.get("importable_commands") or []
|
|
53
|
+
if importable:
|
|
54
|
+
console.print(f" [green]✓[/] importable commands: {', '.join(str(cmd) for cmd in importable)}")
|
|
49
55
|
if binary:
|
|
50
56
|
try:
|
|
51
57
|
result = subprocess.run(["agentpack", "--version"], capture_output=True, text=True)
|
|
@@ -56,6 +62,15 @@ def register(app: typer.Typer) -> None:
|
|
|
56
62
|
else:
|
|
57
63
|
console.print(" [red]✗[/] agentpack not on PATH — run: pipx install agentpack-cli")
|
|
58
64
|
ok = False
|
|
65
|
+
help_commands = cli_status.get("help_commands") or []
|
|
66
|
+
if help_commands:
|
|
67
|
+
console.print(f" [green]✓[/] installed CLI commands: {', '.join(str(cmd) for cmd in help_commands)}")
|
|
68
|
+
if binary and "guard" not in set(str(cmd) for cmd in help_commands) and "guard" in set(available_cli_commands()):
|
|
69
|
+
console.print(
|
|
70
|
+
" [yellow]![/] installed CLI command surface may be stale; "
|
|
71
|
+
f"exact repair: {cli_status.get('repair_command')}"
|
|
72
|
+
)
|
|
73
|
+
ok = False
|
|
59
74
|
|
|
60
75
|
try:
|
|
61
76
|
root = _root()
|
|
@@ -147,8 +162,19 @@ def register(app: typer.Typer) -> None:
|
|
|
147
162
|
"MCP get_context auto-refreshes this, or run: agentpack pack --task auto"
|
|
148
163
|
)
|
|
149
164
|
ok = False
|
|
165
|
+
meta = load_pack_metadata(root) or {}
|
|
166
|
+
freshness = meta.get("freshness") or {}
|
|
167
|
+
if freshness:
|
|
168
|
+
console.print(
|
|
169
|
+
" [green]✓[/] context provenance: "
|
|
170
|
+
f"task_source={freshness.get('task_source', 'unknown')}, "
|
|
171
|
+
f"git_root={freshness.get('git_root', root)}, "
|
|
172
|
+
f"worktree={freshness.get('worktree_path', root)}, "
|
|
173
|
+
f"branch={freshness.get('git_branch', 'unknown')}, "
|
|
174
|
+
f"generated={freshness.get('generated_at', 'unknown')}"
|
|
175
|
+
)
|
|
150
176
|
else:
|
|
151
|
-
console.print(" [yellow]![/] No context pack yet — write .agentpack/task.md, then run:
|
|
177
|
+
console.print(f" [yellow]![/] No context pack yet — write .agentpack/task.md, then run: {refresh_commands(agent).context_missing}")
|
|
152
178
|
|
|
153
179
|
# --- Agent-specific config ---
|
|
154
180
|
console.print("\n[bold]Agent config[/]")
|
|
@@ -249,6 +275,14 @@ def register(app: typer.Typer) -> None:
|
|
|
249
275
|
pass
|
|
250
276
|
if not _local_has_mcp and not _global_has_mcp:
|
|
251
277
|
console.print(" [yellow]![/] MCP server not registered — mcp__agentpack__* tools unavailable")
|
|
278
|
+
console.print(" [yellow]![/] exact repair: agentpack install --agent claude")
|
|
279
|
+
ok = False
|
|
280
|
+
else:
|
|
281
|
+
console.print(
|
|
282
|
+
" [green]✓[/] expected MCP tools: "
|
|
283
|
+
"readiness, route_task, pack_context, get_context, refresh, get_stats"
|
|
284
|
+
)
|
|
285
|
+
console.print(" [green]✓[/] live exposure proof: call MCP tool `readiness` from the agent host")
|
|
252
286
|
|
|
253
287
|
# --- Agent integration matrix ---
|
|
254
288
|
console.print("\n[bold]Agent integration audit[/]")
|
|
@@ -268,8 +302,7 @@ def register(app: typer.Typer) -> None:
|
|
|
268
302
|
ok = False
|
|
269
303
|
if not selected_ok:
|
|
270
304
|
console.print(
|
|
271
|
-
f" [yellow]![/]
|
|
272
|
-
f"agentpack guard --agent {selected} --repair-stale --refresh-context"
|
|
305
|
+
f" [yellow]![/] exact repair: {refresh_commands(selected).repair}"
|
|
273
306
|
)
|
|
274
307
|
|
|
275
308
|
# --- Concurrent threads ---
|
|
@@ -7,6 +7,7 @@ import typer
|
|
|
7
7
|
from agentpack.commands._shared import console, _root, run_refresh
|
|
8
8
|
from agentpack.commands.diagnose_selection import build_selection_diagnosis, _markdown_report
|
|
9
9
|
from agentpack.commands.guard import _context_is_fresh
|
|
10
|
+
from agentpack.core.command_surface import refresh_commands
|
|
10
11
|
from agentpack.core.config import load_config
|
|
11
12
|
from agentpack.core.context_pack import load_pack_metadata
|
|
12
13
|
from agentpack.core.loop_protocol import load_loop_state
|
|
@@ -34,7 +35,7 @@ def register(app: typer.Typer) -> None:
|
|
|
34
35
|
stats = run_refresh(root, "auto", "balanced", 0)
|
|
35
36
|
if stats:
|
|
36
37
|
recommendations = [{"kind": "fixed", "command": "agentpack next", "reason": "refreshed stale context"}]
|
|
37
|
-
fixes.append({"kind": "stale_context", "command": "
|
|
38
|
+
fixes.append({"kind": "stale_context", "command": refresh_commands("auto").repair, "returncode": 0})
|
|
38
39
|
payload = {"recommendations": recommendations, "fixes": fixes, "ok": not recommendations}
|
|
39
40
|
if json_output:
|
|
40
41
|
typer.echo(json.dumps(payload, indent=2, sort_keys=True))
|
|
@@ -58,7 +59,7 @@ def _recommendations(root) -> list[dict[str, str]]:
|
|
|
58
59
|
items.append({"kind": "missing_task", "command": 'agentpack start "describe the task"', "reason": "no concrete task is set"})
|
|
59
60
|
fresh, reason = _context_is_fresh(root)
|
|
60
61
|
if not fresh:
|
|
61
|
-
items.append({"kind": "stale_context", "command": "
|
|
62
|
+
items.append({"kind": "stale_context", "command": refresh_commands("auto").repair, "reason": reason})
|
|
62
63
|
if _has_thread_conflicts(root):
|
|
63
64
|
items.append({"kind": "thread_conflict", "command": "agentpack threads --conflicts", "reason": "active threads overlap on this branch/worktree"})
|
|
64
65
|
if _pack_looks_noisy(root):
|
|
@@ -138,7 +139,7 @@ def _fix_all_safe(root, recommendations: list[dict[str, str]]) -> tuple[list[dic
|
|
|
138
139
|
stats = run_refresh(root, "auto", "balanced", 0)
|
|
139
140
|
fixes.append({
|
|
140
141
|
"kind": "stale_context",
|
|
141
|
-
"command": "
|
|
142
|
+
"command": refresh_commands("auto").repair,
|
|
142
143
|
"returncode": 0 if stats else 1,
|
|
143
144
|
})
|
|
144
145
|
recommendations = _recommendations(root)
|
|
@@ -17,6 +17,7 @@ from agentpack.analysis.ranking import suggest_task_rewrite
|
|
|
17
17
|
from agentpack.application.pack_service import PackRequest, PackService, PackResult
|
|
18
18
|
from agentpack.commands._shared import console, _root, _file_hash, _now_iso
|
|
19
19
|
from agentpack.core.changed_paths import record_changed_paths
|
|
20
|
+
from agentpack.core.command_surface import refresh_commands
|
|
20
21
|
from agentpack.core.modes import MODE_HELP, invalid_mode_message, is_requested_mode
|
|
21
22
|
from agentpack.integrations.agents import check_agent_integration, install_agent_integration
|
|
22
23
|
from agentpack.session.state import TASK_FILE, load_session, save_session, log_activity
|
|
@@ -314,7 +315,7 @@ def _agent_integration_warnings(result: PackResult) -> list[str]:
|
|
|
314
315
|
if not failing:
|
|
315
316
|
return []
|
|
316
317
|
return [
|
|
317
|
-
f"Agent integration needs repair ({agent}); run `
|
|
318
|
+
f"Agent integration needs repair ({agent}); run `{refresh_commands(agent).repair}`."
|
|
318
319
|
]
|
|
319
320
|
|
|
320
321
|
|
|
@@ -337,7 +338,7 @@ def _auto_repair_stale_agent_rules(agent: str) -> None:
|
|
|
337
338
|
except Exception as exc:
|
|
338
339
|
console.print(
|
|
339
340
|
f"[yellow]Stale AgentPack integration detected for {agent}; "
|
|
340
|
-
f"run `
|
|
341
|
+
f"run `{refresh_commands(agent).repair}`. ({exc})[/]"
|
|
341
342
|
)
|
|
342
343
|
|
|
343
344
|
|
|
@@ -6,6 +6,7 @@ from pathlib import Path
|
|
|
6
6
|
import typer
|
|
7
7
|
|
|
8
8
|
from agentpack.commands._shared import console, _root
|
|
9
|
+
from agentpack.core.command_surface import refresh_command_args
|
|
9
10
|
from agentpack.core.context_pack import load_pack_metadata
|
|
10
11
|
from agentpack.core.thread_context import resolve_thread_option, thread_paths
|
|
11
12
|
from agentpack.integrations.platform import cli_module_argv
|
|
@@ -42,9 +43,7 @@ def register(app: typer.Typer) -> None:
|
|
|
42
43
|
if workspace:
|
|
43
44
|
argv.extend(["--workspace", workspace])
|
|
44
45
|
else:
|
|
45
|
-
argv = cli_module_argv(
|
|
46
|
-
if budget:
|
|
47
|
-
argv.extend(["--budget", str(budget)])
|
|
46
|
+
argv = cli_module_argv(*refresh_command_args(agent, mode, budget))
|
|
48
47
|
if thread_id:
|
|
49
48
|
argv.extend(["--thread", thread_id])
|
|
50
49
|
result = subprocess.run(argv, cwd=root)
|
|
@@ -4,6 +4,7 @@ import typer
|
|
|
4
4
|
import shutil
|
|
5
5
|
|
|
6
6
|
from agentpack.core.config import load_config
|
|
7
|
+
from agentpack.core.command_surface import refresh_commands
|
|
7
8
|
from agentpack.core.ignore import load_spec
|
|
8
9
|
from agentpack.core.scanner import scan
|
|
9
10
|
from agentpack.core.snapshot import build_snapshot
|
|
@@ -98,4 +99,4 @@ def _print_deep_health(root, meta: dict | None) -> None:
|
|
|
98
99
|
if not check.ok:
|
|
99
100
|
failing.append(check)
|
|
100
101
|
if failing:
|
|
101
|
-
console.print(f" [yellow]![/]
|
|
102
|
+
console.print(f" [yellow]![/] Repair: {refresh_commands(agent).repair}")
|
|
@@ -7,6 +7,7 @@ from pathlib import Path
|
|
|
7
7
|
import typer
|
|
8
8
|
|
|
9
9
|
from agentpack.commands._shared import console, _root
|
|
10
|
+
from agentpack.core.command_surface import refresh_command_args
|
|
10
11
|
from agentpack.core.thread_context import resolve_thread_option, thread_paths
|
|
11
12
|
from agentpack.integrations.platform import cli_module_argv
|
|
12
13
|
from agentpack.session.state import TASK_FILE
|
|
@@ -47,7 +48,7 @@ def set_task(
|
|
|
47
48
|
task_text: str = typer.Argument(..., help="Task text to write."),
|
|
48
49
|
thread: str = typer.Option("", "--thread", help="Use thread-scoped task state."),
|
|
49
50
|
pack: bool = typer.Option(False, "--pack", help="Run agentpack pack after writing the task."),
|
|
50
|
-
guard: bool = typer.Option(False, "--guard", help="Run
|
|
51
|
+
guard: bool = typer.Option(False, "--guard", help="Run the installed refresh/repair command after writing."),
|
|
51
52
|
agent: str = typer.Option("auto", "--agent", help="Agent to pass to pack/guard."),
|
|
52
53
|
mode: str = typer.Option("balanced", "--mode", help="Pack/guard mode."),
|
|
53
54
|
) -> None:
|
|
@@ -63,7 +64,7 @@ def set_task(
|
|
|
63
64
|
|
|
64
65
|
thread_id = _thread_id(root, thread)
|
|
65
66
|
if guard:
|
|
66
|
-
_run_cli(
|
|
67
|
+
_run_cli(refresh_command_args(agent, mode), thread_id=thread_id)
|
|
67
68
|
elif pack:
|
|
68
69
|
_run_cli(["pack", "--agent", agent, "--task", "auto", "--mode", mode], thread_id=thread_id)
|
|
69
70
|
|
|
@@ -10,6 +10,7 @@ import typer
|
|
|
10
10
|
|
|
11
11
|
from agentpack.commands._shared import console, _root, run_refresh
|
|
12
12
|
from agentpack.commands.guard import _context_is_fresh
|
|
13
|
+
from agentpack.core.command_surface import refresh_commands
|
|
13
14
|
from agentpack.core.config import load_config
|
|
14
15
|
from agentpack.core.loop_protocol import (
|
|
15
16
|
LoopCommandResult,
|
|
@@ -317,7 +318,7 @@ def _loop_finish_blockers(
|
|
|
317
318
|
{
|
|
318
319
|
"kind": "stale_context",
|
|
319
320
|
"message": f"Context is stale: {reason}",
|
|
320
|
-
"command": "
|
|
321
|
+
"command": refresh_commands("auto").repair,
|
|
321
322
|
}
|
|
322
323
|
)
|
|
323
324
|
return blockers
|
|
@@ -434,6 +435,7 @@ def _read_task(root: Path, thread: str) -> str:
|
|
|
434
435
|
|
|
435
436
|
def _refresh_loop_context(root: Path, agent: str, mode: str, budget: int, thread_id: str | None) -> LoopCommandResult:
|
|
436
437
|
stats = run_refresh(root, agent, mode, budget, thread_id=thread_id)
|
|
438
|
+
command = refresh_commands(agent).primary
|
|
437
439
|
if stats is None:
|
|
438
|
-
return LoopCommandResult(command=
|
|
439
|
-
return LoopCommandResult(command=
|
|
440
|
+
return LoopCommandResult(command=command, returncode=1, output_excerpt="context refresh failed")
|
|
441
|
+
return LoopCommandResult(command=command, returncode=0, output_excerpt=json.dumps(stats, sort_keys=True))
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import shutil
|
|
4
|
+
import subprocess
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Iterable
|
|
7
|
+
|
|
8
|
+
from agentpack import __version__
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(frozen=True)
|
|
12
|
+
class RefreshCommands:
|
|
13
|
+
primary: str
|
|
14
|
+
context_missing: str
|
|
15
|
+
thread_auto: str | None
|
|
16
|
+
repair: str
|
|
17
|
+
used_guard: bool
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def available_cli_commands() -> tuple[str, ...]:
|
|
21
|
+
"""Return command names registered by the importable AgentPack CLI."""
|
|
22
|
+
try:
|
|
23
|
+
import typer.main
|
|
24
|
+
|
|
25
|
+
from agentpack.cli import app
|
|
26
|
+
|
|
27
|
+
click_cmd = typer.main.get_command(app)
|
|
28
|
+
return tuple(sorted(click_cmd.commands))
|
|
29
|
+
except Exception:
|
|
30
|
+
return ()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def has_cli_command(command: str) -> bool:
|
|
34
|
+
return command in available_cli_commands()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def refresh_commands(agent: str = "auto") -> RefreshCommands:
|
|
38
|
+
if has_cli_command("guard"):
|
|
39
|
+
base = f"agentpack guard --agent {agent} --repair-stale --refresh-context"
|
|
40
|
+
return RefreshCommands(
|
|
41
|
+
primary=base,
|
|
42
|
+
context_missing=base,
|
|
43
|
+
thread_auto=f"AGENTPACK_THREAD_ID=<stable-id> {base} --thread auto",
|
|
44
|
+
repair=base,
|
|
45
|
+
used_guard=True,
|
|
46
|
+
)
|
|
47
|
+
pack = f"agentpack pack --agent {agent} --task auto"
|
|
48
|
+
return RefreshCommands(
|
|
49
|
+
primary=pack,
|
|
50
|
+
context_missing='printf "%s\\n" "<task>" > .agentpack/task.md && ' + pack,
|
|
51
|
+
thread_auto=None,
|
|
52
|
+
repair="agentpack repair --agent " + agent if has_cli_command("repair") else pack,
|
|
53
|
+
used_guard=False,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def refresh_command_args(agent: str = "auto", mode: str = "balanced", budget: int = 0) -> list[str]:
|
|
58
|
+
"""Return CLI argv parts for refreshing context with the current command surface."""
|
|
59
|
+
if has_cli_command("guard"):
|
|
60
|
+
args = ["guard", "--agent", agent, "--repair-stale", "--refresh-context", "--mode", mode]
|
|
61
|
+
else:
|
|
62
|
+
args = ["pack", "--agent", agent, "--task", "auto", "--mode", mode]
|
|
63
|
+
if budget:
|
|
64
|
+
args.extend(["--budget", str(budget)])
|
|
65
|
+
return args
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def fallback_agent_guidance() -> str:
|
|
69
|
+
return (
|
|
70
|
+
"If AgentPack tools are unavailable or context looks stale/wrong-worktree, "
|
|
71
|
+
"do not trust old pack output. Use direct `rg`, PR diff inspection, and target-file reads, "
|
|
72
|
+
"then run focused validation."
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def installed_cli_status() -> dict[str, object]:
|
|
77
|
+
binary = shutil.which("agentpack")
|
|
78
|
+
status: dict[str, object] = {
|
|
79
|
+
"agentpack_version": __version__,
|
|
80
|
+
"binary": binary,
|
|
81
|
+
"importable_commands": list(available_cli_commands()),
|
|
82
|
+
}
|
|
83
|
+
if not binary:
|
|
84
|
+
status["available"] = False
|
|
85
|
+
status["repair_command"] = "pipx install agentpack-cli"
|
|
86
|
+
return status
|
|
87
|
+
try:
|
|
88
|
+
version = subprocess.run(
|
|
89
|
+
[binary, "--version"],
|
|
90
|
+
capture_output=True,
|
|
91
|
+
text=True,
|
|
92
|
+
timeout=5,
|
|
93
|
+
)
|
|
94
|
+
help_result = subprocess.run(
|
|
95
|
+
[binary, "--help"],
|
|
96
|
+
capture_output=True,
|
|
97
|
+
text=True,
|
|
98
|
+
timeout=5,
|
|
99
|
+
)
|
|
100
|
+
except (OSError, subprocess.TimeoutExpired) as exc:
|
|
101
|
+
status["available"] = False
|
|
102
|
+
status["error"] = str(exc)
|
|
103
|
+
status["repair_command"] = "pipx upgrade agentpack-cli"
|
|
104
|
+
return status
|
|
105
|
+
status["available"] = version.returncode == 0
|
|
106
|
+
status["installed_version"] = (version.stdout.strip() or version.stderr.strip())
|
|
107
|
+
status["help_commands"] = _commands_from_help(help_result.stdout + "\n" + help_result.stderr)
|
|
108
|
+
status["repair_command"] = "pipx upgrade agentpack-cli"
|
|
109
|
+
return status
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _commands_from_help(text: str) -> list[str]:
|
|
113
|
+
commands: set[str] = set()
|
|
114
|
+
known = set(available_cli_commands())
|
|
115
|
+
for line in text.splitlines():
|
|
116
|
+
stripped = line.strip()
|
|
117
|
+
if not stripped:
|
|
118
|
+
continue
|
|
119
|
+
first = stripped.split()[0].strip("`")
|
|
120
|
+
if first in known:
|
|
121
|
+
commands.add(first)
|
|
122
|
+
return sorted(commands)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def missing_commands(commands: Iterable[str]) -> list[str]:
|
|
126
|
+
available = set(available_cli_commands())
|
|
127
|
+
return sorted({cmd for cmd in commands if cmd and cmd not in available})
|
|
@@ -91,7 +91,18 @@ def save_pack_metadata(
|
|
|
91
91
|
"concurrent_context": concurrent_context or {},
|
|
92
92
|
}
|
|
93
93
|
if freshness:
|
|
94
|
-
for key in (
|
|
94
|
+
for key in (
|
|
95
|
+
"agentpack_version",
|
|
96
|
+
"source_command",
|
|
97
|
+
"cwd",
|
|
98
|
+
"git_root",
|
|
99
|
+
"worktree_path",
|
|
100
|
+
"git_sha",
|
|
101
|
+
"git_branch",
|
|
102
|
+
"task_source",
|
|
103
|
+
"changed_files_source",
|
|
104
|
+
"task_class",
|
|
105
|
+
):
|
|
95
106
|
if key in freshness:
|
|
96
107
|
meta[key] = freshness[key]
|
|
97
108
|
path = metadata_path or _metadata_path(root)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any, Literal
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
Variant = Literal["baseline", "agentpack"]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass(frozen=True)
|
|
13
|
+
class E2ERunMetrics:
|
|
14
|
+
case_id: str
|
|
15
|
+
variant: Variant
|
|
16
|
+
task_success: bool | None = None
|
|
17
|
+
validation_passed: bool | None = None
|
|
18
|
+
token_usage: int | None = None
|
|
19
|
+
estimated_cost_usd: float | None = None
|
|
20
|
+
turns: int | None = None
|
|
21
|
+
tool_calls: int | None = None
|
|
22
|
+
time_to_first_correct_file_seconds: float | None = None
|
|
23
|
+
wall_time_seconds: float | None = None
|
|
24
|
+
final_edited_files: list[str] = field(default_factory=list)
|
|
25
|
+
expected_files: list[str] = field(default_factory=list)
|
|
26
|
+
agentpack_noise: list[str] = field(default_factory=list)
|
|
27
|
+
|
|
28
|
+
def to_record(self) -> dict[str, Any]:
|
|
29
|
+
return {
|
|
30
|
+
"case_id": self.case_id,
|
|
31
|
+
"variant": self.variant,
|
|
32
|
+
"task_success": self.task_success,
|
|
33
|
+
"validation_passed": self.validation_passed,
|
|
34
|
+
"token_usage": self.token_usage,
|
|
35
|
+
"estimated_cost_usd": self.estimated_cost_usd,
|
|
36
|
+
"turns": self.turns,
|
|
37
|
+
"tool_calls": self.tool_calls,
|
|
38
|
+
"time_to_first_correct_file_seconds": self.time_to_first_correct_file_seconds,
|
|
39
|
+
"wall_time_seconds": self.wall_time_seconds,
|
|
40
|
+
"final_edited_files": self.final_edited_files,
|
|
41
|
+
"expected_files": self.expected_files,
|
|
42
|
+
"edited_expected_overlap": sorted(set(self.final_edited_files) & set(self.expected_files)),
|
|
43
|
+
"unexpected_edited_files": sorted(set(self.final_edited_files) - set(self.expected_files)),
|
|
44
|
+
"missing_expected_files": sorted(set(self.expected_files) - set(self.final_edited_files)),
|
|
45
|
+
"agentpack_noise": self.agentpack_noise,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def append_e2e_result(path: Path, metrics: E2ERunMetrics) -> None:
|
|
50
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
51
|
+
with path.open("a", encoding="utf-8") as handle:
|
|
52
|
+
handle.write(json.dumps(metrics.to_record(), sort_keys=True) + "\n")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def e2e_scaffold_markdown() -> str:
|
|
56
|
+
return """# AgentPack E2E Benchmark Scaffold
|
|
57
|
+
|
|
58
|
+
Compare the same real task in two variants:
|
|
59
|
+
|
|
60
|
+
- baseline: agent runs without AgentPack context/routing.
|
|
61
|
+
- agentpack: agent starts with AgentPack route/context guidance.
|
|
62
|
+
|
|
63
|
+
Required metrics:
|
|
64
|
+
|
|
65
|
+
- task success
|
|
66
|
+
- tests or validation pass
|
|
67
|
+
- token usage and estimated cost
|
|
68
|
+
- turns and tool calls
|
|
69
|
+
- time-to-first-correct-file
|
|
70
|
+
- wall time
|
|
71
|
+
- final edited files vs expected files
|
|
72
|
+
- AgentPack noise or slowdown cases
|
|
73
|
+
|
|
74
|
+
Keep file-selection benchmarks as scoped ranking evidence. Do not claim cost, turn, or task-success gains until this E2E data exists.
|
|
75
|
+
"""
|
|
@@ -33,7 +33,7 @@ Pack repo context and immediately start working on the task.
|
|
|
33
33
|
If a session is already running (`.agentpack/session.json` exists and `"active": true`):
|
|
34
34
|
|
|
35
35
|
1. If the user gives a new coding task, write a one-line summary to `.agentpack/task.md`.
|
|
36
|
-
2. Run `agentpack
|
|
36
|
+
2. Run `agentpack pack --agent claude --task auto` unless watch mode already refreshed after the task write.
|
|
37
37
|
3. Read `.agentpack/context.md` — context now matches the current task.
|
|
38
38
|
4. Proceed with the task using the context you just read.
|
|
39
39
|
|
|
@@ -72,21 +72,21 @@ Then use normal prompts — context stays current while `watch` is running.
|
|
|
72
72
|
|
|
73
73
|
```bash
|
|
74
74
|
printf '%s\n' "<task>" > .agentpack/task.md
|
|
75
|
-
agentpack
|
|
75
|
+
agentpack pack --agent claude --task auto --mode balanced
|
|
76
76
|
```
|
|
77
77
|
|
|
78
78
|
Then read `.agentpack/context.claude.md` in full.
|
|
79
79
|
|
|
80
80
|
## Thread Mode (explicit opt-in)
|
|
81
81
|
|
|
82
|
-
Plain `agentpack pack
|
|
82
|
+
Plain `agentpack pack` and `agentpack status` use the legacy global files:
|
|
83
83
|
`.agentpack/task.md`, `.agentpack/context.md`, and `.agentpack/pack_metadata.json`.
|
|
84
84
|
|
|
85
85
|
When multiple agents work in the same repo, opt into scoped state:
|
|
86
86
|
|
|
87
87
|
```bash
|
|
88
88
|
export AGENTPACK_THREAD_ID=codex-local
|
|
89
|
-
agentpack
|
|
89
|
+
agentpack pack --agent claude --task auto --thread auto
|
|
90
90
|
```
|
|
91
91
|
|
|
92
92
|
Thread mode writes `.agentpack/threads/<id>/task.md`, `context.md`, `context.claude.md`,
|
|
@@ -122,12 +122,12 @@ test -f .agentpack/config.toml || "$AGENTPACK_BIN" init --yes
|
|
|
122
122
|
|
|
123
123
|
**Session active** (`.agentpack/session.json` exists, `"active": true`):
|
|
124
124
|
- Update `.agentpack/task.md` if task changed
|
|
125
|
-
- Run `"$AGENTPACK_BIN"
|
|
125
|
+
- Run `"$AGENTPACK_BIN" pack --agent claude --task auto` unless watch already refreshed it
|
|
126
126
|
- Read `.agentpack/context.md`
|
|
127
127
|
- Proceed immediately
|
|
128
128
|
|
|
129
129
|
**No session**:
|
|
130
|
-
- Run `"$AGENTPACK_BIN" session start` or `"$AGENTPACK_BIN"
|
|
130
|
+
- Run `"$AGENTPACK_BIN" session start` or `"$AGENTPACK_BIN" pack --agent claude --task auto`
|
|
131
131
|
- Read the context file
|
|
132
132
|
- Proceed
|
|
133
133
|
|
|
@@ -145,7 +145,7 @@ Do not say "context pack ready" and stop. Do not tell the user to run more comma
|
|
|
145
145
|
|
|
146
146
|
If `"$AGENTPACK_BIN" status` exits non-zero or context seems unrelated to the task:
|
|
147
147
|
- Run `"$AGENTPACK_BIN" session refresh` (if session active)
|
|
148
|
-
- Or run `"$AGENTPACK_BIN"
|
|
148
|
+
- Or run `"$AGENTPACK_BIN" pack --agent claude --task auto` (manual mode)
|
|
149
149
|
- Re-read the context, then proceed
|
|
150
150
|
|
|
151
151
|
Do not ask the user — just refresh and proceed.
|