{"id":50483298,"url":"https://github.com/gabrimatic/agent-flight-recorder","last_synced_at":"2026-06-01T19:30:52.570Z","repository":{"id":357094502,"uuid":"1235001110","full_name":"gabrimatic/agent-flight-recorder","owner":"gabrimatic","description":"Black-box recorder for coding-agent code changes.","archived":false,"fork":false,"pushed_at":"2026-05-11T09:06:55.000Z","size":69,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-11T10:43:18.589Z","etag":null,"topics":["code-review","coding-agents","devtools","github-actions","python","security"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gabrimatic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-10T23:00:23.000Z","updated_at":"2026-05-11T09:07:00.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/gabrimatic/agent-flight-recorder","commit_stats":null,"previous_names":["gabrimatic/agent-flight-recorder"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/gabrimatic/agent-flight-recorder","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gabrimatic%2Fagent-flight-recorder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gabrimatic%2Fagent-flight-recorder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gabrimatic%2Fagent-flight-recorder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gabrimatic%2Fagent-flight-recorder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gabrimatic","download_url":"https://codeload.github.com/gabrimatic/agent-flight-recorder/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gabrimatic%2Fagent-flight-recorder/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33790684,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-01T02:00:06.963Z","response_time":115,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["code-review","coding-agents","devtools","github-actions","python","security"],"created_at":"2026-06-01T19:30:50.878Z","updated_at":"2026-06-01T19:30:52.561Z","avatar_url":"https://github.com/gabrimatic.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Agent Flight Recorder\n\nAgent Flight Recorder (`afr`) records local receipts for coding-agent code changes.\n\nRun it around an agent, test command, or CI diff to capture what changed, which commands ran, whether tests were recorded, and which risky areas need human review before merge.\n\nIt is built for the moment after you delegate work to an agent and need receipts before trusting the result.\n\nIt stays local and deterministic: no runtime dependencies, no remote scoring, no hidden model judgment.\n\n## Requirements\n\n- Python 3.10+\n- git\n- a git repository\n\nRuntime dependencies: none beyond Python and git.\n\n## What `afr` Records\n\n`afr` creates a local `.agent-flight` folder containing:\n\n```text\n.agent-flight/\n  config.json                 # tracked project config\n  pr-report.md                # latest markdown report\n  manifest.json               # latest machine-readable manifest\n  sessions/\u003csession-id\u003e/\n    manifest.json\n    before-inventory.json\n    after-inventory.json\n    pr-report.md\n    commands/\n      cmd-0001.stdout.log\n      cmd-0001.stderr.log\n```\n\nThe manifest records:\n\n- session id, branch, commit, start/end time\n- redacted command lines run through the recorder\n- command exit codes\n- stdout/stderr logs, redacted by default and bounded by a configurable byte limit\n- changed files\n- binary files\n- dependency manifest changes\n- auth, payment, database, crypto, secret, infrastructure, and CI-sensitive changes\n- possible secret leaks\n- dangerous added lines such as destructive SQL or `curl | sh`\n- whether a successful test command was recorded\n- a risk score from 0 to 100, with severity floors for high and critical findings\n\n## What `afr` Cannot Prove\n\nAgent Flight Recorder is review evidence, not proof that a change is correct.\n\nIt cannot observe commands that run outside `afr`. If you run `npm test` in another terminal without `afr run -- npm test`, the manifest will not know.\n\nIt also cannot guarantee that code is safe, correct, non-malicious, or produced by the recorded process. The useful promise is narrower: it records the process you choose to run through it and turns that process into deterministic review evidence.\n\n## Setup\n\nPreferred local checkout:\n\n```bash\npython afr.py doctor\npython afr.py init\n```\n\nUse the module form from a checkout:\n\n```bash\nPYTHONPATH=src python -m agent_flight_recorder doctor\n```\n\nInstall as a Python package:\n\n```bash\npip install .\nafr doctor\n```\n\n## Quick start\n\nInside a git repository:\n\n```bash\nafr init\n```\n\nWrap a coding-agent command:\n\n```bash\nafr start -- agent-cli\n```\n\nWrap a real agent run:\n\n```bash\nafr start -- agent-cli --workdir \"$PWD\" \"make the requested change, then run tests\"\n```\n\nWrap a non-interactive command and capture logs:\n\n```bash\nafr start -- python scripts/refactor.py\n```\n\nStart a manual session:\n\n```bash\nafr start --note \"auth refactor\"\n# do work\nafr run -- python -m unittest\nafr stop\n```\n\nPrint the latest report:\n\n```bash\nafr report\n```\n\nAnalyze the current diff in CI or locally:\n\n```bash\nafr analyze --base-ref origin/main --output .agent-flight/pr-report.md\nafr verify --max-score 79\n```\n\n## Commands\n\n### `afr init`\n\nCreates `.agent-flight/config.json` and `.agent-flight/.gitignore`.\n\n```bash\nafr init\nafr init --force\n```\n\n### `afr start`\n\nTwo modes exist.\n\nManual session:\n\n```bash\nafr start --session-id my-session --note \"agent did auth migration\"\n# make changes\nafr run -- python -m unittest\nafr stop\n```\n\nWrapped command session:\n\n```bash\nafr start -- python -c \"from pathlib import Path; Path('x.py').write_text('print(1)')\"\n```\n\nBy default, wrapped commands have stdout/stderr captured and redacted. For interactive tools that need direct terminal access:\n\n```bash\nafr start --interactive -- agent-cli\n```\n\nWhen `--interactive` is used, the command inherits the terminal. The command line and exit code are still recorded, but stdout/stderr are not captured.\n\nRecorded command metadata is redacted before it is written to the manifest. Secret-looking flag values such as `--api-key \u003cvalue\u003e`, `--token=\u003cvalue\u003e`, `PASSWORD=\u003cvalue\u003e`, and common key formats are replaced in reports and manifests.\n\nCaptured stdout and stderr are capped by `max_command_output_bytes` in `.agent-flight/config.json`. Truncated logs include an explicit `[afr: ... truncated ...]` marker.\n\n### `afr run`\n\nRuns and records a command inside an active manual session.\n\n```bash\nafr run -- npm test\nafr run -- flutter test\nafr run -- python -m unittest\n```\n\n### `afr stop`\n\nStops the active manual session, compares before/after repository inventory, runs the risk engine, writes the manifest, and writes `.agent-flight/pr-report.md`.\n\n### `afr analyze`\n\nAnalyzes the current git diff without an active session. This is best for CI.\n\n```bash\nafr analyze --base-ref origin/main\nafr analyze --output .agent-flight/pr-report.md\nafr analyze --base-ref origin/main --json --output manifest.json\n```\n\nIf no base ref is provided, `afr` tries `AFR_BASE_REF`, then `origin/main`, `origin/master`, `main`, `master`, then `HEAD~1`. If you pass a base ref explicitly, it must resolve; a typo fails instead of silently analyzing the wrong range.\n\n### `afr verify`\n\nFails with exit code 1 if the manifest violates merge-gate rules.\n\n```bash\nafr verify --max-score 79\nafr verify --max-level medium\nafr verify --require-tests-for-high-risk\nafr verify --require-command-log\n```\n\n`--max-score 79` means critical risk fails. `--max-score 50` means high and critical risk fail.\n\nFailed recorded commands are high risk even if no files changed. This keeps failed agent runs from passing strict merge gates.\n\n### `afr report`\n\nPrints the latest markdown report, or writes markdown/JSON to a file.\n\n```bash\nafr report\nafr report --format json\nafr report --session-id afr-20260509-120000-abcd1234\nafr report --output report.md\n```\n\n### `afr doctor`\n\nPrints environment diagnostics.\n\n```bash\nafr doctor\nafr doctor --json\n```\n\n## GitHub Action\n\nAdd this to `.github/workflows/agent-flight.yml`:\n\n```yaml\nname: Agent Flight Recorder\n\non:\n  pull_request:\n\njobs:\n  agent-flight:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          fetch-depth: 0\n      - uses: gabrimatic/agent-flight-recorder@v0\n        with:\n          max_score: \"79\"\n          require_tests_for_high_risk: \"false\"\n          require_command_log: \"false\"\n```\n\nFor a stricter gate:\n\n```yaml\n      - uses: gabrimatic/agent-flight-recorder@v0\n        with:\n          max_score: \"50\"\n          require_tests_for_high_risk: \"true\"\n```\n\nTo verify a pre-recorded session manifest instead of analyzing the current diff:\n\n```yaml\n      - uses: gabrimatic/agent-flight-recorder@v0\n        with:\n          manifest: path/to/manifest.json\n          max_score: \"50\"\n          require_tests_for_high_risk: \"true\"\n          require_command_log: \"true\"\n```\n\nWhen `manifest` is set, the action skips `afr analyze`, renders the report from that manifest, and verifies the recorded commands. Use this mode when agent sessions are expected to be recorded with `afr start` or `afr run`.\n\n`require_command_log` is too strict for normal PRs where only diff analysis is expected.\n\n## Report UX\n\n`afr report` prints a markdown review surface that is meant to be pasted into a PR or read in CI logs. It includes:\n\n- risk badge, session id, mode, start/end time\n- repository branch, head, and analysis base ref\n- changed-file and command summaries\n- findings sorted by severity\n- recorded command exits and log paths\n- changed files with status, size, and binary marker\n\nThe report avoids generated-by footers and keeps command output in separate redacted log files.\n\n## Risk scoring\n\nThe risk engine is deterministic and local. It does not need a remote service.\n\nRisk levels:\n\n- low: 0-20\n- medium: 21-50\n- high: 51-79\n- critical: 80-100\n\nThe final score uses the higher of the summed finding score and the strongest severity floor. Medium findings make the manifest at least medium risk, high findings make it at least high risk, and critical findings make it at least critical risk.\n\nSignals include:\n\n- source files changed without a recorded successful test command\n- source files changed without test files changing\n- auth/authorization/session/JWT/OAuth code changed\n- billing/payment/subscription/pricing code changed\n- database migrations or schema changed\n- cryptography/secret/key-management code changed\n- infrastructure, YAML, Docker, CI, Terraform, or Kubernetes files changed\n- dependency manifests or lockfiles changed\n- binary files changed\n- large change sets\n- possible secrets in changed files\n- dangerous added lines\n- failed recorded commands\n- no command log\n\nAdjust rules in `.agent-flight/config.json`.\n\n## Configuration\n\n`afr init` creates the default config.\n\nImportant keys:\n\n```json\n{\n  \"max_hash_bytes\": 10485760,\n  \"max_text_scan_bytes\": 2000000,\n  \"redact_command_output\": true,\n  \"exclude_globs\": [\".git/**\", \".agent-flight/**\", \"node_modules/**\", \"build/**\"],\n  \"test_command_patterns\": [\"pytest\", \"npm test\", \"make test\", \"go test\", \"flutter test\"],\n  \"test_file_globs\": [\"tests/**\", \"**/*.test.*\", \"**/*_test.*\"],\n  \"risk_thresholds\": {\n    \"medium\": 21,\n    \"high\": 51,\n    \"critical\": 80\n  }\n}\n```\n\nConfig validation is strict. List fields must contain strings, byte limits and thresholds must be integers, and each risk zone needs an `id` plus a string-list `patterns` value.\n\n## Privacy and security\n\n- Session data stays local by default.\n- `.agent-flight/sessions/`, `.agent-flight/manifest.json`, and active-session state are ignored by `.agent-flight/.gitignore`.\n- Command stdout/stderr are redacted by default using local regex rules.\n- Changed files are scanned locally for possible secrets.\n- Secret findings include redacted previews only.\n- No network calls are made by the tool.\n\nIf you commit generated reports, inspect them first. They may contain file paths, command lines, or other project-sensitive metadata.\n\n## Edge cases handled\n\n- Git repositories with unborn or detached HEADs.\n- Manual sessions and one-shot wrapped sessions.\n- Interactive commands with inherited terminal.\n- Untracked files.\n- Deleted files.\n- Symlinks.\n- Binary files.\n- Large files with hash truncation.\n- Missing config, with automatic default generation.\n- Missing base refs in CI, with fallback refs.\n- Explicit invalid base refs fail instead of falling back.\n- Failed child commands, while still writing a high-risk manifest.\n- Interrupted CLI, with exit code 130.\n\n## Why This Is Different From Review Bots\n\nMost bots look only at the final diff.\n\nAgent Flight Recorder records the surrounding process: what command was delegated, what changed, what validation ran, and which risky areas deserve human attention.\n\nThat does not make the change safe. It gives the reviewer the missing context.\n\n## Development\n\nRun tests:\n\n```bash\nmake test\n```\n\nRun the project check:\n\n```bash\nmake check\n```\n\nRun the recommended release-style check:\n\n```bash\nmake test\nuvx ruff check .\nuvx mypy src\npython -m build\ngitleaks detect --no-git --source . --redact --verbose\n```\n\nPackage builds use `python -m build`; install `build` in your development environment if that module is missing.\n\nRun directly from source:\n\n```bash\nPYTHONPATH=src python -m agent_flight_recorder doctor\n```\n\n## License\n\nMIT.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgabrimatic%2Fagent-flight-recorder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgabrimatic%2Fagent-flight-recorder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgabrimatic%2Fagent-flight-recorder/lists"}