|
1 | | -<!-- Managed by agent: keep sections & order; edit content, not structure. Last updated: 2025-10-09 --> |
| 1 | +<!-- Managed by agent: keep sections & order; edit content, not structure. Last updated: 2025-11-03 --> |
2 | 2 |
|
3 | | -# AI CLI Preparation - Agent Guide (Root) |
| 3 | +# AGENTS.md (root) |
4 | 4 |
|
5 | | -**Thin root file**: See scoped AGENTS.md files for specific areas. |
| 5 | +**Precedence:** The **closest AGENTS.md** to changed files wins. Root holds global defaults only. |
6 | 6 |
|
7 | | -## Precedence & Scoped Files |
| 7 | +## Global rules |
8 | 8 |
|
9 | | -This root AGENTS.md provides global defaults. **Nearest AGENTS.md wins** for specific rules. |
10 | | - |
11 | | -**Scoped files:** |
12 | | -- [scripts/AGENTS.md](scripts/AGENTS.md) - Shell installation scripts |
13 | | - |
14 | | -## Overview |
15 | | - |
16 | | -AI CLI Preparation is an environment audit tool ensuring AI coding agents (like Claude Code) have access to necessary developer tools. It detects 50+ tools, reports versions, and provides installation guidance. |
| 9 | +- Keep PRs small (~≤300 net LOC changed) |
| 10 | +- Conventional Commits: `type(scope): description` |
| 11 | + - Types: feat, fix, docs, chore, test, refactor, perf, style |
| 12 | + - Scopes: audit, catalog, scripts, docs, tests |
| 13 | +- Ask before: heavy dependencies, full rewrites, breaking changes |
| 14 | +- Never commit secrets, PII, or credentials |
17 | 15 |
|
18 | | -**Architecture:** |
19 | | -- **Phase 1 (Complete)**: Tool detection, version auditing, offline-first caching |
20 | | -- **Phase 2 (Planned)**: Context-aware installation/upgrade management (see [docs/PRD.md](docs/PRD.md)) |
| 16 | +## Project overview |
21 | 17 |
|
22 | | -**Tech Stack:** |
23 | | -- Python 3.10+ (standard library only, no external deps for core) |
24 | | -- Make for task automation |
25 | | -- Shell scripts (Bash) for installation |
26 | | -- JSON for caching (latest_versions.json, tools_snapshot.json) |
| 18 | +**AI CLI Preparation v2.0** - Tool version auditing and installation management for AI coding agents. |
27 | 19 |
|
28 | | -**Key Files:** |
29 | | -- `cli_audit.py` (2,375 lines): Main audit engine, 50+ tool definitions |
30 | | -- `smart_column.py`: ANSI/emoji-aware table formatting |
31 | | -- `scripts/`: 13+ installation scripts (install/update/uninstall/reconcile) |
32 | | -- `docs/`: Comprehensive technical documentation (12 files, 189KB) |
| 20 | +**Architecture:** Modular design with 18 specialized Python modules, 67 JSON tool catalogs, and comprehensive testing. |
33 | 21 |
|
34 | | -## Setup |
| 22 | +- **Phase 1 (Complete):** Detection & auditing with modular refactoring |
| 23 | +- **Phase 2 (Complete):** Installation & upgrade management |
| 24 | +- **Entry Point:** `audit.py` (50 lines) → cli_audit package |
35 | 25 |
|
36 | | -**Requirements:** |
37 | | -- Python 3.10+ (Python 3.14.0rc2 tested) |
38 | | -- Standard library only (no pip install needed for core) |
39 | | -- Optional: pyflakes for linting |
| 26 | +## Minimal pre-commit checks |
40 | 27 |
|
41 | | -**First-time setup:** |
42 | 28 | ```bash |
43 | | -# Allow direnv (if using) |
44 | | -direnv allow |
45 | | - |
46 | | -# Show available commands |
47 | | -make help |
| 29 | +# Linting |
| 30 | +make lint # flake8 (required) |
48 | 31 |
|
49 | | -# Update snapshot (requires network) |
50 | | -make update |
| 32 | +# Type checking (optional) |
| 33 | +make lint-types # mypy |
51 | 34 |
|
52 | | -# Run audit from snapshot (fast, offline-capable) |
53 | | -make audit |
54 | | -``` |
| 35 | +# Testing |
| 36 | +./scripts/test_smoke.sh # Smoke tests (required) |
55 | 37 |
|
56 | | -**Environment variables:** |
57 | | -```bash |
58 | | -# See .env.default for all options |
59 | | -CLI_AUDIT_COLLECT=1 # Collect-only mode (write snapshot) |
60 | | -CLI_AUDIT_RENDER=1 # Render-only mode (read snapshot) |
61 | | -CLI_AUDIT_OFFLINE=1 # Offline mode (manual cache only) |
62 | | -CLI_AUDIT_DEBUG=1 # Debug output |
63 | | -CLI_AUDIT_JSON=1 # JSON output |
| 38 | +# Audit validation |
| 39 | +make audit # Verify core workflows |
64 | 40 | ``` |
65 | 41 |
|
66 | | -## Build & Tests |
| 42 | +## Index of scoped AGENTS.md |
67 | 43 |
|
68 | | -**Primary commands:** |
69 | | -```bash |
70 | | -make audit # Render from snapshot (no network, <100ms) |
71 | | -make update # Collect fresh data, write snapshot (~10s) |
72 | | -make audit-offline # Offline audit with hints |
73 | | -make lint # Run pyflakes (if installed) |
74 | | -make upgrade # Interactive upgrade guide |
75 | | -``` |
76 | | - |
77 | | -**Single tool audit:** |
78 | | -```bash |
79 | | -make audit-ripgrep # Audit specific tool |
80 | | -make audit-offline-python-core # Role-based preset |
81 | | -``` |
| 44 | +- **[cli_audit/AGENTS.md](cli_audit/AGENTS.md)** — Python package (18 modules, Phase 1 + Phase 2) |
| 45 | +- **[tests/AGENTS.md](tests/AGENTS.md)** — Test suite (unit, integration, E2E) |
| 46 | +- **[scripts/AGENTS.md](scripts/AGENTS.md)** — Installation scripts (Bash, 25+ scripts) |
82 | 47 |
|
83 | | -**Installation scripts:** |
84 | | -```bash |
85 | | -make install-python # Install Python toolchain (uv) |
86 | | -make install-node # Install Node.js (nvm) |
87 | | -make install-core # Install core tools (fd, fzf, ripgrep, jq, etc.) |
88 | | -``` |
| 48 | +## Quick reference |
89 | 49 |
|
90 | | -**Testing:** |
| 50 | +**Common commands:** |
91 | 51 | ```bash |
92 | | -# Smoke test (verifies table output and JSON format) |
93 | | -./scripts/test_smoke.sh |
94 | | - |
95 | | -# Test single tool detection |
96 | | -CLI_AUDIT_DEBUG=1 python3 cli_audit.py --only ripgrep |
97 | | - |
98 | | -# Validate snapshot |
99 | | -jq '.__meta__' tools_snapshot.json |
100 | | -``` |
101 | | - |
102 | | -**No formal test suite yet** - README acknowledges: "currently ships without tests" |
103 | | -- Smoke tests exist (test_smoke.sh) |
104 | | -- Manual validation workflows documented |
105 | | - |
106 | | -## Code Style |
107 | | - |
108 | | -**Python:** |
109 | | -- PEP 8 style (4-space indent, snake_case) |
110 | | -- Type hints used (`from __future__ import annotations`) |
111 | | -- Frozen dataclasses for immutability (`@dataclass(frozen=True)`) |
112 | | -- Docstrings minimal (focus on inline comments) |
113 | | - |
114 | | -**Formatting:** |
115 | | -- EditorConfig enforced: LF, UTF-8, 4 spaces, trim trailing whitespace |
116 | | -- No auto-formatter configured (manual formatting) |
117 | | -- Lint via pyflakes: `make lint` |
118 | | - |
119 | | -**Shell scripts:** |
120 | | -- Bash with `set -euo pipefail` |
121 | | -- Shellcheck-compliant (best effort) |
122 | | -- Consistent error handling (see scripts/lib/) |
123 | | - |
124 | | -**Conventions:** |
125 | | -- File paths: Absolute paths, no auto-commit |
126 | | -- Functions: Snake_case, descriptive names |
127 | | -- Constants: UPPER_CASE (e.g., MANUAL_LOCK, HINTS_LOCK) |
128 | | -- Lock ordering: MANUAL_LOCK → HINTS_LOCK (enforced for safety) |
129 | | - |
130 | | -## Security |
131 | | - |
132 | | -**Secrets:** |
133 | | -- No secrets in VCS |
134 | | -- GITHUB_TOKEN optional (for GitHub API rate limit increase) |
135 | | -- Set via environment: `export GITHUB_TOKEN=ghp_...` |
136 | | - |
137 | | -**Network:** |
138 | | -- HTTPS-only for upstream queries |
139 | | -- Retry logic with exponential backoff |
140 | | -- Per-origin rate limits (GitHub: 5/min, PyPI: 10/min, crates.io: 5/min) |
141 | | -- Timeout enforcement (default: 3s, configurable) |
142 | | - |
143 | | -**Input validation:** |
144 | | -- Tool names validated against TOOLS registry |
145 | | -- Version strings sanitized (extract_version_number) |
146 | | -- Subprocess calls use lists, not shell=True (where possible) |
147 | | - |
148 | | -**Caching:** |
149 | | -- Atomic file writes prevent corruption |
150 | | -- Offline-first design (committed latest_versions.json) |
151 | | -- No arbitrary code execution (package manager commands only) |
152 | | - |
153 | | -## PR/Commit Checklist |
154 | | - |
155 | | -**Before commit:** |
156 | | -- [ ] Run `make lint` (pyflakes clean) |
157 | | -- [ ] Run `make audit` (verify snapshot renders) |
158 | | -- [ ] Test affected tool: `make audit-<tool>` |
159 | | -- [ ] Update docs if behavior changed (README.md, docs/, scripts/README.md) |
160 | | -- [ ] Add/update smoke test if new output format |
161 | | - |
162 | | -**Commit messages:** |
163 | | -- Conventional Commits format: `type(scope): description` |
164 | | -- Examples: |
165 | | - - `feat(audit): add snapshot-based collect/render modes` |
166 | | - - `fix(locks): enforce MANUAL_LOCK→HINTS_LOCK ordering` |
167 | | - - `docs(prd): add Phase 2 specifications and ADRs` |
168 | | - - `chore(cache): update latest_versions.json` |
169 | | - |
170 | | -**Pull requests:** |
171 | | -- Keep PRs small (~≤300 net LOC changed) |
172 | | -- Link to issue/ticket if exists |
173 | | -- Update CHANGELOG section in PR description |
174 | | -- Ensure CI passes (when added) |
175 | | - |
176 | | -## Good vs Bad Examples |
177 | | - |
178 | | -**Good: Atomic dataclass with type safety** |
179 | | -```python |
180 | | -@dataclass(frozen=True) |
181 | | -class Tool: |
182 | | - name: str |
183 | | - candidates: tuple[str, ...] |
184 | | - source_kind: str # gh|pypi|crates|npm|gnu|skip |
185 | | - source_args: tuple[str, ...] |
186 | | -``` |
187 | | - |
188 | | -**Bad: Mutable dict with unclear types** |
189 | | -```python |
190 | | -# Don't do this |
191 | | -tool = { |
192 | | - 'name': 'ripgrep', |
193 | | - 'candidates': ['rg'], # List instead of tuple |
194 | | - 'source': 'github', # Unclear allowed values |
195 | | -} |
196 | | -``` |
197 | | - |
198 | | -**Good: Lock ordering enforcement** |
199 | | -```python |
200 | | -def update_manual_cache(tool: str, version: str) -> None: |
201 | | - with MANUAL_LOCK: # Acquire first |
202 | | - with HINTS_LOCK: # Then hints |
203 | | - # Safe: consistent ordering prevents deadlock |
204 | | -``` |
205 | | - |
206 | | -**Bad: Lock ordering violation** |
207 | | -```python |
208 | | -def update_cache(tool: str) -> None: |
209 | | - with HINTS_LOCK: # Wrong order! |
210 | | - with MANUAL_LOCK: |
211 | | - # Deadlock risk |
212 | | -``` |
213 | | - |
214 | | -**Good: Parallel execution with isolation** |
215 | | -```python |
216 | | -with ThreadPoolExecutor(max_workers=16) as executor: |
217 | | - futures = [executor.submit(audit_tool, tool) for tool in TOOLS] |
218 | | - for future in as_completed(futures): |
219 | | - result = future.result() # Failures isolated |
220 | | -``` |
| 52 | +make audit # Render from snapshot (<100ms) |
| 53 | +make update # Collect fresh versions (~7s) |
| 54 | +make upgrade # Interactive upgrade guide |
221 | 55 |
|
222 | | -**Bad: Sequential execution** |
223 | | -```python |
224 | | -results = [] |
225 | | -for tool in TOOLS: # Slow: 50 tools * 3s = 150s |
226 | | - results.append(audit_tool(tool)) |
| 56 | +python3 audit.py # Direct invocation |
| 57 | +python3 audit.py --only ripgrep # Single tool audit |
227 | 58 | ``` |
228 | 59 |
|
229 | | -## When Stuck |
230 | | - |
231 | | -**Tool detection failing:** |
232 | | -1. Check PATH: `echo $PATH | tr ':' '\n'` |
233 | | -2. Debug single tool: `CLI_AUDIT_DEBUG=1 python3 cli_audit.py --only <tool>` |
234 | | -3. Check version flag: `<tool> --version` or `<tool> -v` |
235 | | -4. See [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md#version-detection-failures) |
236 | | - |
237 | | -**Network issues:** |
238 | | -1. Increase timeout: `CLI_AUDIT_TIMEOUT_SECONDS=10 make update` |
239 | | -2. More retries: `CLI_AUDIT_HTTP_RETRIES=5 make update` |
240 | | -3. Use offline mode: `make audit-offline` |
241 | | -4. See [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md#network-timeout-issues) |
242 | | - |
243 | | -**Cache corruption:** |
244 | | -1. Remove caches: `rm latest_versions.json tools_snapshot.json` |
245 | | -2. Regenerate: `make update` |
246 | | - |
247 | | -**Installation script fails:** |
248 | | -1. Check permissions: `make scripts-perms` |
249 | | -2. Debug script: `bash -x ./scripts/install_<tool>.sh` |
250 | | -3. See [scripts/README.md](scripts/README.md) for per-script troubleshooting |
| 60 | +**Key files:** |
| 61 | +- `audit.py` — Entry point (50 lines) |
| 62 | +- `cli_audit/` — 18 Python modules (6,608 lines) |
| 63 | +- `catalog/` — 67 JSON tool definitions |
| 64 | +- `latest_versions.json` — Version cache |
| 65 | +- `tools_snapshot.json` — Snapshot data |
251 | 66 |
|
252 | 67 | **Documentation:** |
253 | | -- Start with [docs/QUICK_REFERENCE.md](docs/QUICK_REFERENCE.md) for one-liners |
254 | | -- See [docs/INDEX.md](docs/INDEX.md) for navigation by role/task |
255 | | -- Architecture details: [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) |
256 | | -- API reference: [docs/API_REFERENCE.md](docs/API_REFERENCE.md) |
257 | | - |
258 | | -## House Rules |
259 | | - |
260 | | -**Defaults** (override in scoped AGENTS.md if needed): |
261 | | - |
262 | | -**Commits:** |
263 | | -- Atomic commits (single logical change) |
264 | | -- Conventional Commits: `type(scope): description` |
265 | | -- Keep PRs small (~≤300 net LOC changed) |
266 | | -- Ticket IDs in commits/PRs if exists |
267 | | - |
268 | | -**Type-safety:** |
269 | | -- Use type hints (`from __future__ import annotations`) |
270 | | -- Frozen dataclasses for immutability |
271 | | -- No `Any` unless truly dynamic |
272 | | - |
273 | | -**Design principles:** |
274 | | -- SOLID, KISS, DRY, YAGNI |
275 | | -- Composition > Inheritance |
276 | | -- Law of Demeter (minimal coupling) |
277 | | - |
278 | | -**Dependencies:** |
279 | | -- Standard library preferred (no external Python deps for core) |
280 | | -- Latest stable versions when external deps needed |
281 | | -- Document why in Decision Log (ADRs for Phase 2) |
282 | | - |
283 | | -**Security:** |
284 | | -- No secrets in VCS |
285 | | -- HTTPS-only for network calls |
286 | | -- No arbitrary code execution |
287 | | -- Input validation on external data |
288 | | - |
289 | | -**Documentation currency:** |
290 | | -- Update docs in same PR as behavior changes |
291 | | -- No drift between code and docs |
292 | | -- Document non-obvious decisions in ADRs (see docs/adr/) |
293 | | - |
294 | | -**Testing:** |
295 | | -- Aim for ≥80% coverage on changed code (when test suite added) |
296 | | -- Bugfixes use TDD: failing test first, then fix |
297 | | -- New code paths need tests (future requirement) |
298 | | - |
299 | | -**Current status:** |
300 | | -- Phase 1: Production-ready detection/audit |
301 | | -- Phase 2: Planned installation/upgrade (see [docs/PRD.md](docs/PRD.md)) |
302 | | -- No unit tests yet (acknowledged in README) |
303 | | - |
304 | | ---- |
| 68 | +- `docs/INDEX.md` — Documentation navigation |
| 69 | +- `docs/MIGRATION_GUIDE.md` — v1.x → v2.0 transition |
| 70 | +- `docs/CATALOG_GUIDE.md` — JSON catalog system |
| 71 | +- `docs/ARCHITECTURE.md` — Modular design |
305 | 72 |
|
306 | | -**Quick Start:** New to the project? Start with [README.md](README.md) → [docs/QUICK_REFERENCE.md](docs/QUICK_REFERENCE.md) → [docs/INDEX.md](docs/INDEX.md) |
| 73 | +## When instructions conflict |
307 | 74 |
|
308 | | -**Contributing:** See [docs/DEVELOPER_GUIDE.md](docs/DEVELOPER_GUIDE.md) for detailed contribution guide |
| 75 | +Nearest AGENTS.md wins. User prompts override all files. |
0 commit comments