agentcam 0.1.0__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.
@@ -0,0 +1,47 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ test:
14
+ runs-on: ${{ matrix.os }}
15
+ strategy:
16
+ fail-fast: false
17
+ matrix:
18
+ os: [ubuntu-latest, macos-latest, windows-latest]
19
+ python-version: ["3.11", "3.12"]
20
+
21
+ steps:
22
+ - uses: actions/checkout@v4
23
+
24
+ - name: Set up Python ${{ matrix.python-version }}
25
+ uses: actions/setup-python@v5
26
+ with:
27
+ python-version: ${{ matrix.python-version }}
28
+
29
+ - name: Install agentcam + dev deps
30
+ run: |
31
+ python -m pip install --upgrade pip
32
+ python -m pip install -e ".[dev]"
33
+
34
+ - name: Show environment
35
+ run: |
36
+ python --version
37
+ git --version
38
+ agentcam version
39
+
40
+ - name: Configure git identity (needed by tmp_git_repo fixture)
41
+ run: |
42
+ git config --global user.email "ci@example.com"
43
+ git config --global user.name "CI"
44
+ git config --global commit.gpgsign false
45
+
46
+ - name: Run pytest
47
+ run: python -m pytest -v --maxfail=5
@@ -0,0 +1,22 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.pyo
4
+ *.pyd
5
+ .pytest_cache/
6
+ *.egg-info/
7
+ .venv/
8
+ .venv*/
9
+ venv/
10
+ env/
11
+ dist/
12
+ build/
13
+ .coverage
14
+ .coverage.*
15
+ htmlcov/
16
+ .ruff_cache/
17
+ .mypy_cache/
18
+ .tox/
19
+ *.swp
20
+ *.swo
21
+ .DS_Store
22
+ Thumbs.db
@@ -0,0 +1,156 @@
1
+ # Changelog
2
+
3
+ All notable changes to agentcam are recorded here. Format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) loosely.
5
+ Versioning follows [SemVer](https://semver.org/) once 1.0.0 ships;
6
+ 0.x is unstable on purpose.
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Renamed (2026-05-16)
11
+
12
+ - **Package + CLI renamed `agentbox` → `agentcam`** (PyPI name `agentbox`
13
+ was taken; `agentcam` is available on PyPI and free of prominent GitHub
14
+ collisions). Source dir `src/agentbox/` → `src/agentcam/`; CLI entry
15
+ `agentbox` → `agentcam`; artifact path `<git_dir>/agentbox/runs/` →
16
+ `<git_dir>/agentcam/runs/`. All 25 files updated; 171 tests still pass.
17
+ - GitHub repo renamed `agent-run-flight-recorder` → `agentcam`.
18
+ Old URL auto-redirects via GitHub.
19
+
20
+ ### Hardening (post-source-review fixes, 2026-05-16)
21
+
22
+ - **report.py**: `cf.rename_from` now passes through secret-like-filename
23
+ redaction; `git diff --check` output now passes through a new
24
+ `_redact_filenames_in_diff_check` helper; report `Logs` and
25
+ `Local Artifacts` sections show paths relative to git_root instead of
26
+ absolute (no longer leaks username + repo location).
27
+ - **redaction.py**: `StreamingRedactor` now keeps a 1024-char reserve on
28
+ force-flush so a token straddling the SOFT_FLUSH boundary can reassemble;
29
+ `feed()` strips NUL bytes after decode (catches UTF-16LE / NUL-interleaved
30
+ output); added `URL_BASIC_AUTH` pattern to redact `https://user:pass@host`;
31
+ all secret-like patterns now case-insensitive.
32
+ - **scanner.py**: secret-like basename patterns all case-insensitive
33
+ (catches `.ENV`, `ID_RSA`, `.NPMRC` on case-insensitive filesystems).
34
+ - **runner.py**: `proc.wait()` wrapped in try/except KeyboardInterrupt /
35
+ finally — Ctrl+C now escalates wait→terminate→kill and always joins tee
36
+ threads (so logs flush). New `_escape_for_cmd_shim` helper caret-escapes
37
+ `& | < > ^` and doubles `%` for the Windows `.cmd` / `.bat` shim path.
38
+ - **+21 regression tests** covering each fix.
39
+ - **External confirm-review**: Codex confirmed all 9 fixes OK with NO
40
+ BLOCKERS (direct `codex exec`, after three attempts via the
41
+ `codex-rescue` subagent forwarder hung in session deadlocks).
42
+ - **Cross-platform validation (partial)**: pytest now passes on Linux
43
+ (WSL Ubuntu, Python 3.12.3) too — 172/172 (POSIX signal test runs there).
44
+ Total coverage: Windows 171/172 + Linux 172/172. macOS still untested
45
+ (no local hardware; CI yaml covers it pending future GH push).
46
+ - **POSIX risks documented for v0.2** (Codex cross-platform risk
47
+ assessment): SIGINT process-group leak, non-UTF8 filename decoding,
48
+ POSIX exec permission. See ROADMAP v0.2 "POSIX hardening" entry and
49
+ `docs/design.md` caveat 3.
50
+ - **GitHub Actions matrix green (6/6 jobs)** on push to main:
51
+ Linux / macOS / Windows × Python 3.11 / 3.12 all pass.
52
+ Repo: https://github.com/shihchengwei-lab/agentcam (renamed from agent-run-flight-recorder on 2026-05-16)
53
+
54
+ ## [0.1.0] — 2026-05-16
55
+
56
+ First release. The whole point of v0.1 is "wrap one agent run, produce a
57
+ report, do not lie about what we don't know."
58
+
59
+ ### Added
60
+
61
+ - **`agentcam version`** — print version and exit
62
+ - **`agentcam run -- <argv...>`** — wrap an argv-style command, record
63
+ before/after git state, tee stdout/stderr, generate Markdown report
64
+
65
+ #### What gets recorded per run
66
+
67
+ - `stdout.log` / `stderr.log` — raw bytes from the subprocess, preserved
68
+ for forensic review
69
+ - `stdout.redacted.log` / `stderr.redacted.log` — secrets stripped
70
+ (best-effort) via streaming buffer (handles tokens cut at chunk
71
+ boundaries and multi-line PEM blocks)
72
+ - `manifest.json` — machine-readable run metadata
73
+ - `AGENT_RUN_REPORT.md` — human-readable report
74
+
75
+ All artifacts live under `<git_dir>/agentcam/runs/<run_id>/` so git itself
76
+ cannot stage them.
77
+
78
+ #### Risk heuristics in this release
79
+
80
+ - **HIGH**: tracked file deletions; sensitive path segments (`auth`,
81
+ `login`, `oauth`, `session`, `jwt`, `permission`, `migration`, `secret`,
82
+ `credential`, `terraform`, `kubernetes`, `helm`, etc.); sensitive
83
+ basenames / extensions (`.env`, `.env.*`, `*.pem`, `*.key`, `id_rsa*`,
84
+ `schema.prisma`, `fly.toml`, `vercel.json`, `.tf`, `.tfvars`); GitHub
85
+ Actions workflow paths; output-pattern hits like `git reset --hard`,
86
+ `rm -rf /`, `chmod 777`, `curl ... | sh`, PowerShell
87
+ `Remove-Item -Recurse -Force`, `Invoke-Expression`, conflict markers,
88
+ `git push --force`.
89
+ - **MEDIUM**: dependency manifest changes (`package.json`, `pyproject.toml`,
90
+ `Dockerfile`, etc.); output mentions of `tests failed`, `lint error`,
91
+ `build failed`, `panic`, `segmentation fault`.
92
+ - No LOW level — filename-only heuristics for "trivial" changes are
93
+ unreliable.
94
+
95
+ #### Redaction
96
+
97
+ - Streaming redactor handles tokens split across read chunks and PEM
98
+ blocks split across multiple lines (PKCS#8 / RSA / EC / ED25519 /
99
+ ENCRYPTED / OPENSSH).
100
+ - Secret-like filenames (`.env`, `*.pem`, `id_rsa`, `*credential*`,
101
+ `*secret*`) are redacted in every Markdown surface (Changed Files, Risk
102
+ Flags evidence, Diff Stat, Rollback Notes, Command field).
103
+ - Argv redaction also runs on each argv element (catches
104
+ `--api-key sk-...` and `--config .env.production`).
105
+
106
+ #### Exit code
107
+
108
+ - Wrapper exits `0` iff subprocess returncode is `0`, `1` otherwise.
109
+ - Original returncode, platform, and a human interpretation (POSIX signal
110
+ name; common Windows NTSTATUS like `STATUS_ACCESS_VIOLATION`) all go to
111
+ `manifest.exit_detail` and the `Exit Code Detail` report section.
112
+ - Run-id collision (same millisecond, same slug, all hex retries
113
+ exhausted) exits with `2` — distinct from "subprocess failed" `1`.
114
+
115
+ ### Tests
116
+
117
+ - 159 unit + e2e tests across 8 test modules
118
+ - Cross-platform: passes on Windows (POSIX-only signal test skipped)
119
+ - e2e suite uses real subprocesses + real git repos via
120
+ `tmp_git_repo` fixture
121
+ - Regression guards for every blocker found during two rounds of Codex
122
+ adversarial review (PEM cross-chunk, exit-code 256-not-zero, segment vs.
123
+ substring matching, staged-only diff visible, output evidence does not
124
+ echo raw matched text, etc.)
125
+
126
+ ### Documentation
127
+
128
+ - `README.md` — quick start, install, threat model, known limitations,
129
+ hacking
130
+ - `docs/design.md` — 22 decisions in "decision / why / why not" format
131
+ - `examples/risky-auth-change/` — one committed sample report and scenario
132
+ description
133
+ - `SECURITY.md` — vulnerability disclosure policy, scope, threat model
134
+
135
+ ### Known limitations (v0.1)
136
+
137
+ - Not a sandbox; not a pre-execution gate; not a compliance product.
138
+ - Best-effort redaction; new secret formats may slip through.
139
+ - No interactive TUI rendering guarantee.
140
+ - No submodule / sparse-checkout special handling.
141
+ - Windows console encoding fallback may degrade live terminal display
142
+ (raw log on disk is unaffected).
143
+ - `Tests / Build / Lint observed` always reports `unknown` — heuristic
144
+ detection deferred to a future release.
145
+
146
+ ### Out of scope (deliberately, see `docs/design.md` "Out-of-scope reminders")
147
+
148
+ - Sandbox / process isolation
149
+ - Pre-execution blocking / approval gating
150
+ - Auto-rollback / `git clean -fd` suggestions
151
+ - Cloud upload / telemetry of any kind
152
+ - VS Code / IDE integration
153
+ - GitHub App / GitHub Action (deferred to v0.2 if v0.1 finds users)
154
+ - Custom YAML risk rules
155
+ - Multi-run dashboard
156
+ - Hosted SaaS dashboard
agentcam-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 shihchengwei
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,313 @@
1
+ Metadata-Version: 2.4
2
+ Name: agentcam
3
+ Version: 0.1.0
4
+ Summary: Local-first CLI wrapper that records what your AI coding agent changed in your repo.
5
+ Author-email: shihchengwei <shihchengwei@gmail.com>
6
+ License: MIT
7
+ License-File: LICENSE
8
+ Keywords: claude-code,codex,coding-agent,flight-recorder,observability
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Software Development :: Quality Assurance
17
+ Requires-Python: >=3.11
18
+ Provides-Extra: dev
19
+ Requires-Dist: pytest-timeout>=2.2; extra == 'dev'
20
+ Requires-Dist: pytest>=7.4; extra == 'dev'
21
+ Description-Content-Type: text/markdown
22
+
23
+ # agentcam
24
+
25
+ [![CI](https://github.com/shihchengwei-lab/agentcam/actions/workflows/ci.yml/badge.svg)](https://github.com/shihchengwei-lab/agentcam/actions/workflows/ci.yml)
26
+
27
+ > Local-first CLI wrapper that records what your AI coding agent changed in your repo and generates a Markdown run report after each run.
28
+
29
+ agentcam does **not** replace Claude Code, Codex, OpenHands, Aider, or any
30
+ other coding agent. It wraps them.
31
+
32
+ ```bash
33
+ agentcam run -- claude "fix the failing tests"
34
+ agentcam run -- codex "add input validation to login form"
35
+ agentcam run -- bash -lc "npm run build && npm test"
36
+ ```
37
+
38
+ After each run, you get an `AGENT_RUN_REPORT.md` answering three questions:
39
+
40
+ 1. **What did the agent change?** — exact file list, diff stat, staged vs.
41
+ unstaged vs. untracked, before/after HEAD.
42
+ 2. **Where should I look first?** — heuristic risk flags for auth paths,
43
+ secrets, deletions, dangerous shell strings (`rm -rf /`, `git reset
44
+ --hard`, conflict markers), dependency manifests.
45
+ 3. **How do I roll back if something's wrong?** — situation-aware rollback
46
+ notes (no blanket `git reset --hard` suggestions).
47
+
48
+ See [`examples/risky-auth-change/expected-report.md`](examples/risky-auth-change/expected-report.md)
49
+ for what a report looks like when the agent touches a sensitive area.
50
+
51
+ ---
52
+
53
+ ## What this is NOT
54
+
55
+ This is a **flight recorder**, not a governance platform.
56
+
57
+ - Not a sandbox.
58
+ - Not a pre-execution gate. agentcam does not block dangerous commands; it
59
+ records that they happened and flags them for review *after*.
60
+ - Not a security scanner. The risk flags are heuristics ("look here"), not
61
+ verdicts ("this is bad").
62
+ - Not an audit / compliance tool. The Markdown report is for the developer
63
+ reviewing the diff, not for a SOC2 evidence pipeline.
64
+ - Not a SaaS. There is no account, no upload, no telemetry. Everything
65
+ stays under `.git/agentcam/runs/` on your machine.
66
+
67
+ ---
68
+
69
+ ## Install
70
+
71
+ agentcam needs Python ≥ 3.11 and `git`.
72
+
73
+ ```bash
74
+ pipx install agentcam
75
+ ```
76
+
77
+ (Once published to PyPI. For now, install from source — see "Hacking"
78
+ below.)
79
+
80
+ Verify:
81
+
82
+ ```bash
83
+ agentcam version
84
+ # agentcam 0.1.0
85
+ ```
86
+
87
+ ---
88
+
89
+ ## Quick start
90
+
91
+ Inside any git repository:
92
+
93
+ ```bash
94
+ agentcam run -- bash -lc "echo hello > demo.txt"
95
+ ```
96
+
97
+ agentcam will:
98
+
99
+ 1. snapshot git state (HEAD, branch, staged / unstaged / untracked)
100
+ 2. run your command, tee-ing stdout and stderr to logs (raw + redacted)
101
+ 3. snapshot git state again
102
+ 4. scan for risk flags (path patterns, output patterns, deletions)
103
+ 5. write `AGENT_RUN_REPORT.md` and `manifest.json` under
104
+ `.git/agentcam/runs/<run_id>/`
105
+ 6. exit with 0 if your command succeeded, 1 otherwise
106
+
107
+ stdout and stderr stream live to your terminal — agentcam does not buffer
108
+ them.
109
+
110
+ ### Wrapping Claude Code
111
+
112
+ ```bash
113
+ agentcam run --name claude-fix-tests -- claude "fix the failing tests"
114
+ ```
115
+
116
+ ### Wrapping Codex
117
+
118
+ ```bash
119
+ agentcam run --name codex-add-validation -- codex "add input validation to login form"
120
+ ```
121
+
122
+ ### Wrapping anything (with shell features)
123
+
124
+ agentcam runs the command with `shell=False`. If you need pipes, redirects,
125
+ variable expansion, wrap your own shell explicitly:
126
+
127
+ ```bash
128
+ agentcam run -- bash -lc "npm run build 2>&1 | tee build.log"
129
+ agentcam run -- pwsh -Command "Get-Process | Out-File procs.txt"
130
+ agentcam run -- cmd /c "dir > files.txt"
131
+ ```
132
+
133
+ This is a deliberate constraint — see [`docs/design.md` § 4](docs/design.md).
134
+
135
+ ---
136
+
137
+ ## Where the artifacts live
138
+
139
+ ```
140
+ .git/
141
+ └── agentcam/
142
+ └── runs/
143
+ └── 20260516-143000-451-claude-rate-limit-login/
144
+ ├── AGENT_RUN_REPORT.md # human-readable, share-friendly
145
+ ├── manifest.json # machine-readable
146
+ ├── stdout.log # raw stdout (KEEP PRIVATE)
147
+ ├── stderr.log # raw stderr (KEEP PRIVATE)
148
+ ├── stdout.redacted.log # secrets stripped (best-effort)
149
+ └── stderr.redacted.log
150
+ ```
151
+
152
+ Output lives under `.git/` on purpose — git doesn't track its own
153
+ internals, so agent invocations of `git add .` cannot stage agentcam's
154
+ output by accident.
155
+
156
+ > **Warning about raw logs.** Raw logs preserve the original stdout /
157
+ > stderr for forensic review. They will *not* be picked up by `git push`,
158
+ > but they *will* travel with `.git/` if you:
159
+ >
160
+ > - sync your repo via OneDrive / Dropbox / iCloud Drive
161
+ > - back up your machine (Time Machine, Windows File History)
162
+ > - zip the entire repo to share with someone
163
+ >
164
+ > The `AGENT_RUN_REPORT.md` only links to the redacted logs.
165
+
166
+ ---
167
+
168
+ ## Risk flags (heuristics)
169
+
170
+ Two levels: **HIGH** and **MEDIUM**. There is no LOW — filename-only
171
+ heuristics for "trivial" changes are unreliable, and we don't pretend.
172
+
173
+ **HIGH** — flagged for any of:
174
+
175
+ - A tracked file was deleted.
176
+ - File path contains a sensitive segment: `auth`, `login`, `oauth`,
177
+ `session`, `jwt`, `permission`, `middleware`, `migration`, `secret`,
178
+ `credential`, `terraform`, `kubernetes`, `helm`, etc.
179
+ - Sensitive basename / extension: `.env`, `.env.*`, `*.pem`, `*.key`,
180
+ `id_rsa*`, `schema.prisma`, `fly.toml`, `vercel.json`, `.tf`, `.tfvars`,
181
+ GitHub Actions workflows.
182
+ - stdout / stderr contains a high-risk command pattern:
183
+ `git reset --hard`, `rm -rf /...`, `chmod 777`, `curl ... | sh`,
184
+ PowerShell `Remove-Item -Recurse -Force ...`, `Invoke-Expression`,
185
+ conflict markers, `git push --force`.
186
+
187
+ **MEDIUM** — flagged for any of:
188
+
189
+ - Dependency manifest changed: `package.json`, `pyproject.toml`,
190
+ `requirements.txt`, `Dockerfile`, `docker-compose.*`, etc.
191
+ - stdout / stderr mentions `tests failed`, `lint error`, `build failed`,
192
+ `panic`, `segmentation fault`.
193
+
194
+ **Path matching is segment-based.** Segment `auth` matches
195
+ `src/auth/login.py` and `auth.ts`, but does NOT match `author.md` or
196
+ `authorization-docs/x.md`. See [`docs/design.md` § 7](docs/design.md).
197
+
198
+ **Evidence never includes raw matched text.** Risk Flags cite the pattern
199
+ name and a line number (`stdout.log line 42`), never the matched
200
+ substring. Secrets that happen to land near a risk pattern in output do
201
+ not leak through the report.
202
+
203
+ For the full rule list and rationale, see
204
+ [`docs/design.md` § 7, § 12, § 15](docs/design.md).
205
+
206
+ ---
207
+
208
+ ## Secret redaction (best-effort)
209
+
210
+ Patterns redacted in the redacted log:
211
+
212
+ - AWS access / secret keys (`AKIA…`, `aws_secret_access_key=…`)
213
+ - GitHub PAT (`ghp_…`, `gho_…`, etc.)
214
+ - OpenAI / Anthropic-shaped API keys (`sk-…`)
215
+ - Slack tokens (`xoxa-…`, `xoxb-…`, etc.)
216
+ - npm / GitLab tokens (`npm_…`, `glpat-…`)
217
+ - JWT (`eyJ…`)
218
+ - `Bearer …` headers
219
+ - env-style assignments where the key name looks like a secret
220
+ (`OPENAI_API_KEY=…`, `*_TOKEN=…`, `*_PASSWORD=…`, `*_CREDENTIAL=…`)
221
+ - PEM private key blocks — multi-line, including PKCS#8 / RSA / EC /
222
+ ED25519 / OPENSSH
223
+
224
+ We **do not** promise to catch every secret. New token formats appear all
225
+ the time. The raw log on disk is the forensic backstop: if redaction
226
+ missed something, you can find it there.
227
+
228
+ `Command:` field, `Changed Files`, `Diff Stat`, and `Risk Flags evidence`
229
+ in the markdown report also pass through redaction — a literal
230
+ `.env.production` in argv or in a diff stat shows up as
231
+ `<redacted-secret-filename>`.
232
+
233
+ ---
234
+
235
+ ## Local-only, no telemetry
236
+
237
+ agentcam makes no network calls. It does not phone home. There is no
238
+ account, no upload, no opt-in or opt-out toggle for telemetry — because
239
+ there is no telemetry to toggle.
240
+
241
+ If you ever observe an outbound connection from agentcam, that's a bug;
242
+ please file an issue.
243
+
244
+ ---
245
+
246
+ ## Known limitations
247
+
248
+ - **Not a sandbox.** agentcam does not isolate the wrapped command from
249
+ your filesystem, network, or credentials.
250
+ - **Does not block.** High-risk patterns are recorded *after* they happen;
251
+ agentcam does not approve or deny commands.
252
+ - **Does not see inside the agent.** agentcam observes only what reaches
253
+ stdout / stderr and what changes in the git working tree. The agent's
254
+ internal tool calls (file reads, web requests, model calls) are
255
+ invisible.
256
+ - **Best-effort redaction.** New secret formats may slip through. Do not
257
+ rely on agentcam alone for credential hygiene.
258
+ - **No interactive TUI guarantee.** Agents that draw full-screen TUIs
259
+ (curses-style) may render imperfectly through the wrapper. Their
260
+ side-effects on the repo are still recorded correctly.
261
+ - **No submodule traversal.** Running inside a submodule treats it as an
262
+ independent repo. Superproject context is not analyzed.
263
+ - **No sparse-checkout special handling.** Reports reflect what
264
+ `git status --porcelain=v1 -z` shows.
265
+ - **Windows console encoding can degrade live terminal display.** Raw
266
+ bytes are always preserved on disk; only the live forwarding to the
267
+ terminal may fall back to UTF-8 lossy decode (recorded as
268
+ `terminal_forward_degraded` in the manifest).
269
+
270
+ For the full list of "things we deliberately did NOT do," see the
271
+ "Out-of-scope reminders" at the bottom of [`docs/design.md`](docs/design.md).
272
+
273
+ ---
274
+
275
+ ## Hacking
276
+
277
+ ```bash
278
+ git clone <this repo>
279
+ cd flight_recorder
280
+ python -m venv .venv
281
+
282
+ # Windows (Git Bash / PowerShell)
283
+ .venv/Scripts/python -m pip install -e ".[dev]"
284
+ .venv/Scripts/python -m pytest
285
+
286
+ # macOS / Linux
287
+ .venv/bin/python -m pip install -e ".[dev]"
288
+ .venv/bin/python -m pytest
289
+ ```
290
+
291
+ The codebase is intentionally small (one source module per concern):
292
+
293
+ ```
294
+ src/agentcam/
295
+ ├── cli.py # argparse + orchestrator
296
+ ├── runner.py # threads-based tee + exit code interpretation
297
+ ├── git_state.py # porcelain parser + git_dir resolver
298
+ ├── paths.py # run_id + collision-safe directory creation
299
+ ├── redaction.py # streaming secret redactor
300
+ ├── scanner.py # path + output risk patterns
301
+ ├── report.py # AGENT_RUN_REPORT.md generator
302
+ └── models.py # dataclass definitions
303
+ ```
304
+
305
+ Read [`docs/design.md`](docs/design.md) before changing anything — it
306
+ records why each module is shaped the way it is, including the "we
307
+ considered X and rejected it because Y" cases.
308
+
309
+ ---
310
+
311
+ ## License
312
+
313
+ MIT. See [`LICENSE`](LICENSE).