agent-debrief 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.
Files changed (199) hide show
  1. agent_debrief-0.1.0/.gitignore +39 -0
  2. agent_debrief-0.1.0/CONTRIBUTING.md +42 -0
  3. agent_debrief-0.1.0/LICENSE +21 -0
  4. agent_debrief-0.1.0/PKG-INFO +169 -0
  5. agent_debrief-0.1.0/README.md +139 -0
  6. agent_debrief-0.1.0/apps/web/index.html +18 -0
  7. agent_debrief-0.1.0/apps/web/package.json +32 -0
  8. agent_debrief-0.1.0/apps/web/src/App.tsx +25 -0
  9. agent_debrief-0.1.0/apps/web/src/components/ClaimList.tsx +43 -0
  10. agent_debrief-0.1.0/apps/web/src/components/CodeBlock.tsx +81 -0
  11. agent_debrief-0.1.0/apps/web/src/components/ConfirmDialog.tsx +85 -0
  12. agent_debrief-0.1.0/apps/web/src/components/ErrorBoundary.tsx +30 -0
  13. agent_debrief-0.1.0/apps/web/src/components/Icon.tsx +87 -0
  14. agent_debrief-0.1.0/apps/web/src/components/LevelSelector.tsx +39 -0
  15. agent_debrief-0.1.0/apps/web/src/components/Modal.tsx +108 -0
  16. agent_debrief-0.1.0/apps/web/src/components/PageHeader.tsx +21 -0
  17. agent_debrief-0.1.0/apps/web/src/components/References.tsx +46 -0
  18. agent_debrief-0.1.0/apps/web/src/components/States.tsx +122 -0
  19. agent_debrief-0.1.0/apps/web/src/components/TabNav.tsx +62 -0
  20. agent_debrief-0.1.0/apps/web/src/components/TaskRow.tsx +32 -0
  21. agent_debrief-0.1.0/apps/web/src/components/badges.tsx +130 -0
  22. agent_debrief-0.1.0/apps/web/src/components/evidence.tsx +168 -0
  23. agent_debrief-0.1.0/apps/web/src/features/conversations/AskTab.tsx +286 -0
  24. agent_debrief-0.1.0/apps/web/src/features/dashboard/AgentCard.tsx +149 -0
  25. agent_debrief-0.1.0/apps/web/src/features/dashboard/DashboardView.tsx +151 -0
  26. agent_debrief-0.1.0/apps/web/src/features/learning/LearnTab.tsx +228 -0
  27. agent_debrief-0.1.0/apps/web/src/features/sessions/EventsInspector.tsx +93 -0
  28. agent_debrief-0.1.0/apps/web/src/features/sessions/LlmContextModal.tsx +52 -0
  29. agent_debrief-0.1.0/apps/web/src/features/sessions/TaskContext.tsx +17 -0
  30. agent_debrief-0.1.0/apps/web/src/features/sessions/TaskGate.tsx +69 -0
  31. agent_debrief-0.1.0/apps/web/src/features/sessions/eventSummary.test.ts +26 -0
  32. agent_debrief-0.1.0/apps/web/src/features/sessions/eventSummary.ts +39 -0
  33. agent_debrief-0.1.0/apps/web/src/features/summary/SummaryTab.tsx +352 -0
  34. agent_debrief-0.1.0/apps/web/src/features/visual-flow/FlowNodeCard.tsx +66 -0
  35. agent_debrief-0.1.0/apps/web/src/features/visual-flow/FlowTab.tsx +217 -0
  36. agent_debrief-0.1.0/apps/web/src/features/visual-flow/NodePanel.tsx +123 -0
  37. agent_debrief-0.1.0/apps/web/src/features/visual-flow/layout.test.ts +114 -0
  38. agent_debrief-0.1.0/apps/web/src/features/visual-flow/layout.ts +102 -0
  39. agent_debrief-0.1.0/apps/web/src/features/voice/TalkTab.tsx +355 -0
  40. agent_debrief-0.1.0/apps/web/src/features/voice/speaker.ts +123 -0
  41. agent_debrief-0.1.0/apps/web/src/hooks/queries.ts +83 -0
  42. agent_debrief-0.1.0/apps/web/src/hooks/useAnalyze.ts +15 -0
  43. agent_debrief-0.1.0/apps/web/src/hooks/useDocumentTitle.ts +13 -0
  44. agent_debrief-0.1.0/apps/web/src/hooks/useEventStream.test.ts +53 -0
  45. agent_debrief-0.1.0/apps/web/src/hooks/useEventStream.ts +119 -0
  46. agent_debrief-0.1.0/apps/web/src/layouts/AppLayout.tsx +77 -0
  47. agent_debrief-0.1.0/apps/web/src/lib/format.test.ts +82 -0
  48. agent_debrief-0.1.0/apps/web/src/lib/format.ts +136 -0
  49. agent_debrief-0.1.0/apps/web/src/lib/status.ts +67 -0
  50. agent_debrief-0.1.0/apps/web/src/lib/verification.test.ts +51 -0
  51. agent_debrief-0.1.0/apps/web/src/lib/verification.ts +108 -0
  52. agent_debrief-0.1.0/apps/web/src/main.tsx +24 -0
  53. agent_debrief-0.1.0/apps/web/src/pages/DashboardPage.tsx +18 -0
  54. agent_debrief-0.1.0/apps/web/src/pages/NotFoundPage.tsx +22 -0
  55. agent_debrief-0.1.0/apps/web/src/pages/ProjectsPage.tsx +45 -0
  56. agent_debrief-0.1.0/apps/web/src/pages/SessionDetailPage.tsx +101 -0
  57. agent_debrief-0.1.0/apps/web/src/pages/SessionsPage.tsx +63 -0
  58. agent_debrief-0.1.0/apps/web/src/pages/SettingsPage.tsx +427 -0
  59. agent_debrief-0.1.0/apps/web/src/pages/TaskPage.tsx +207 -0
  60. agent_debrief-0.1.0/apps/web/src/services/api.test.ts +92 -0
  61. agent_debrief-0.1.0/apps/web/src/services/api.ts +194 -0
  62. agent_debrief-0.1.0/apps/web/src/services/queryClient.ts +41 -0
  63. agent_debrief-0.1.0/apps/web/src/stores/createStore.ts +36 -0
  64. agent_debrief-0.1.0/apps/web/src/stores/live.ts +36 -0
  65. agent_debrief-0.1.0/apps/web/src/styles/base.css +317 -0
  66. agent_debrief-0.1.0/apps/web/src/styles/components.css +694 -0
  67. agent_debrief-0.1.0/apps/web/src/styles/features.css +609 -0
  68. agent_debrief-0.1.0/apps/web/src/styles/tokens.css +134 -0
  69. agent_debrief-0.1.0/apps/web/src/types/index.ts +2 -0
  70. agent_debrief-0.1.0/apps/web/tsconfig.json +28 -0
  71. agent_debrief-0.1.0/apps/web/tsconfig.node.json +13 -0
  72. agent_debrief-0.1.0/apps/web/vite-env.d.ts +37 -0
  73. agent_debrief-0.1.0/apps/web/vite.config.ts +66 -0
  74. agent_debrief-0.1.0/backend/agent_debrief/__init__.py +3 -0
  75. agent_debrief-0.1.0/backend/agent_debrief/__main__.py +18 -0
  76. agent_debrief-0.1.0/backend/agent_debrief/ai/__init__.py +1 -0
  77. agent_debrief-0.1.0/backend/agent_debrief/ai/orchestrator.py +57 -0
  78. agent_debrief-0.1.0/backend/agent_debrief/ai/prompts/__init__.py +1 -0
  79. agent_debrief-0.1.0/backend/agent_debrief/ai/prompts/workflows.py +66 -0
  80. agent_debrief-0.1.0/backend/agent_debrief/ai/providers/__init__.py +1 -0
  81. agent_debrief-0.1.0/backend/agent_debrief/ai/providers/anthropic.py +60 -0
  82. agent_debrief-0.1.0/backend/agent_debrief/ai/providers/base.py +56 -0
  83. agent_debrief-0.1.0/backend/agent_debrief/ai/providers/openai_compat.py +87 -0
  84. agent_debrief-0.1.0/backend/agent_debrief/ai/providers/registry.py +32 -0
  85. agent_debrief-0.1.0/backend/agent_debrief/ai/structured_outputs/__init__.py +1 -0
  86. agent_debrief-0.1.0/backend/agent_debrief/ai/structured_outputs/schemas.py +73 -0
  87. agent_debrief-0.1.0/backend/agent_debrief/analysis/__init__.py +1 -0
  88. agent_debrief-0.1.0/backend/agent_debrief/analysis/architecture_analyzer.py +105 -0
  89. agent_debrief-0.1.0/backend/agent_debrief/analysis/ast_analyzer.py +319 -0
  90. agent_debrief-0.1.0/backend/agent_debrief/analysis/diff_analyzer.py +360 -0
  91. agent_debrief-0.1.0/backend/agent_debrief/analysis/evidence_engine.py +158 -0
  92. agent_debrief-0.1.0/backend/agent_debrief/analysis/git_utils.py +213 -0
  93. agent_debrief-0.1.0/backend/agent_debrief/analysis/relationship_analyzer.py +299 -0
  94. agent_debrief-0.1.0/backend/agent_debrief/analysis/risk_analyzer.py +142 -0
  95. agent_debrief-0.1.0/backend/agent_debrief/analysis/symbol_diff.py +64 -0
  96. agent_debrief-0.1.0/backend/agent_debrief/analysis/symbol_indexer.py +141 -0
  97. agent_debrief-0.1.0/backend/agent_debrief/analysis/task_analyzer.py +178 -0
  98. agent_debrief-0.1.0/backend/agent_debrief/analysis/test_results.py +105 -0
  99. agent_debrief-0.1.0/backend/agent_debrief/api/__init__.py +1 -0
  100. agent_debrief-0.1.0/backend/agent_debrief/api/app.py +105 -0
  101. agent_debrief-0.1.0/backend/agent_debrief/api/routes/__init__.py +1 -0
  102. agent_debrief-0.1.0/backend/agent_debrief/api/routes/core.py +88 -0
  103. agent_debrief-0.1.0/backend/agent_debrief/api/routes/stream.py +78 -0
  104. agent_debrief-0.1.0/backend/agent_debrief/api/routes/tasks.py +132 -0
  105. agent_debrief-0.1.0/backend/agent_debrief/api/security.py +108 -0
  106. agent_debrief-0.1.0/backend/agent_debrief/cli/__init__.py +1 -0
  107. agent_debrief-0.1.0/backend/agent_debrief/cli/app.py +454 -0
  108. agent_debrief-0.1.0/backend/agent_debrief/cli/hook.py +50 -0
  109. agent_debrief-0.1.0/backend/agent_debrief/communication/__init__.py +1 -0
  110. agent_debrief-0.1.0/backend/agent_debrief/communication/chat.py +260 -0
  111. agent_debrief-0.1.0/backend/agent_debrief/communication/common.py +76 -0
  112. agent_debrief-0.1.0/backend/agent_debrief/communication/concepts_catalog.py +389 -0
  113. agent_debrief-0.1.0/backend/agent_debrief/communication/flow.py +277 -0
  114. agent_debrief-0.1.0/backend/agent_debrief/communication/retrieval.py +134 -0
  115. agent_debrief-0.1.0/backend/agent_debrief/communication/summary.py +198 -0
  116. agent_debrief-0.1.0/backend/agent_debrief/communication/tutor.py +110 -0
  117. agent_debrief-0.1.0/backend/agent_debrief/communication/voice.py +177 -0
  118. agent_debrief-0.1.0/backend/agent_debrief/config/__init__.py +14 -0
  119. agent_debrief-0.1.0/backend/agent_debrief/config/secrets.py +66 -0
  120. agent_debrief-0.1.0/backend/agent_debrief/config/settings.py +92 -0
  121. agent_debrief-0.1.0/backend/agent_debrief/database/__init__.py +3 -0
  122. agent_debrief-0.1.0/backend/agent_debrief/database/connection.py +121 -0
  123. agent_debrief-0.1.0/backend/agent_debrief/database/migrations/0001_initial.sql +226 -0
  124. agent_debrief-0.1.0/backend/agent_debrief/demo.py +300 -0
  125. agent_debrief-0.1.0/backend/agent_debrief/events/__init__.py +1 -0
  126. agent_debrief-0.1.0/backend/agent_debrief/events/correlator.py +128 -0
  127. agent_debrief-0.1.0/backend/agent_debrief/events/deduplicator.py +26 -0
  128. agent_debrief-0.1.0/backend/agent_debrief/events/ingestion.py +211 -0
  129. agent_debrief-0.1.0/backend/agent_debrief/events/normalizer.py +213 -0
  130. agent_debrief-0.1.0/backend/agent_debrief/events/redaction.py +107 -0
  131. agent_debrief-0.1.0/backend/agent_debrief/events/schemas.py +44 -0
  132. agent_debrief-0.1.0/backend/agent_debrief/integrations/__init__.py +1 -0
  133. agent_debrief-0.1.0/backend/agent_debrief/integrations/base.py +41 -0
  134. agent_debrief-0.1.0/backend/agent_debrief/integrations/claude/__init__.py +1 -0
  135. agent_debrief-0.1.0/backend/agent_debrief/integrations/claude/adapter.py +105 -0
  136. agent_debrief-0.1.0/backend/agent_debrief/integrations/claude/hooks.py +186 -0
  137. agent_debrief-0.1.0/backend/agent_debrief/integrations/claude/transcript.py +211 -0
  138. agent_debrief-0.1.0/backend/agent_debrief/integrations/codex/__init__.py +0 -0
  139. agent_debrief-0.1.0/backend/agent_debrief/integrations/codex/adapter.py +34 -0
  140. agent_debrief-0.1.0/backend/agent_debrief/integrations/cursor/__init__.py +0 -0
  141. agent_debrief-0.1.0/backend/agent_debrief/integrations/cursor/adapter.py +32 -0
  142. agent_debrief-0.1.0/backend/agent_debrief/integrations/registry.py +22 -0
  143. agent_debrief-0.1.0/backend/agent_debrief/main.py +25 -0
  144. agent_debrief-0.1.0/backend/agent_debrief/models/__init__.py +1 -0
  145. agent_debrief-0.1.0/backend/agent_debrief/models/api.py +515 -0
  146. agent_debrief-0.1.0/backend/agent_debrief/models/common.py +103 -0
  147. agent_debrief-0.1.0/backend/agent_debrief/models/understanding.py +99 -0
  148. agent_debrief-0.1.0/backend/agent_debrief/paths.py +60 -0
  149. agent_debrief-0.1.0/backend/agent_debrief/repositories/__init__.py +37 -0
  150. agent_debrief-0.1.0/backend/agent_debrief/repositories/analysis.py +137 -0
  151. agent_debrief-0.1.0/backend/agent_debrief/repositories/base.py +17 -0
  152. agent_debrief-0.1.0/backend/agent_debrief/repositories/events.py +70 -0
  153. agent_debrief-0.1.0/backend/agent_debrief/repositories/explanations.py +117 -0
  154. agent_debrief-0.1.0/backend/agent_debrief/repositories/jobs.py +106 -0
  155. agent_debrief-0.1.0/backend/agent_debrief/repositories/sessions.py +75 -0
  156. agent_debrief-0.1.0/backend/agent_debrief/repositories/tasks.py +121 -0
  157. agent_debrief-0.1.0/backend/agent_debrief/repositories/workspaces.py +37 -0
  158. agent_debrief-0.1.0/backend/agent_debrief/services/__init__.py +1 -0
  159. agent_debrief-0.1.0/backend/agent_debrief/services/agent_service.py +70 -0
  160. agent_debrief-0.1.0/backend/agent_debrief/services/analysis_runner.py +62 -0
  161. agent_debrief-0.1.0/backend/agent_debrief/services/analysis_service.py +337 -0
  162. agent_debrief-0.1.0/backend/agent_debrief/services/errors.py +40 -0
  163. agent_debrief-0.1.0/backend/agent_debrief/services/settings_service.py +76 -0
  164. agent_debrief-0.1.0/backend/agent_debrief/services/task_service.py +445 -0
  165. agent_debrief-0.1.0/backend/agent_debrief/understanding/__init__.py +1 -0
  166. agent_debrief-0.1.0/backend/agent_debrief/understanding/context_builder.py +128 -0
  167. agent_debrief-0.1.0/backend/agent_debrief/understanding/knowledge_graph.py +75 -0
  168. agent_debrief-0.1.0/backend/agent_debrief/understanding/task_understanding.py +91 -0
  169. agent_debrief-0.1.0/backend/agent_debrief/util.py +65 -0
  170. agent_debrief-0.1.0/backend/agent_debrief/web_dist/assets/FlowTab-BnuhLJ6X.css +1 -0
  171. agent_debrief-0.1.0/backend/agent_debrief/web_dist/assets/FlowTab-DxkwVXsJ.js +23 -0
  172. agent_debrief-0.1.0/backend/agent_debrief/web_dist/assets/index-97ryKr0Z.css +1 -0
  173. agent_debrief-0.1.0/backend/agent_debrief/web_dist/assets/index-DhBchsMz.js +71 -0
  174. agent_debrief-0.1.0/backend/agent_debrief/web_dist/index.html +19 -0
  175. agent_debrief-0.1.0/backend/agent_debrief/workers/__init__.py +1 -0
  176. agent_debrief-0.1.0/backend/agent_debrief/workers/worker.py +72 -0
  177. agent_debrief-0.1.0/backend/tests/conftest.py +55 -0
  178. agent_debrief-0.1.0/backend/tests/test_analysis.py +277 -0
  179. agent_debrief-0.1.0/backend/tests/test_api.py +282 -0
  180. agent_debrief-0.1.0/backend/tests/test_cli.py +97 -0
  181. agent_debrief-0.1.0/backend/tests/test_communication.py +379 -0
  182. agent_debrief-0.1.0/backend/tests/test_events.py +195 -0
  183. agent_debrief-0.1.0/backend/tests/test_integration_claude.py +114 -0
  184. agent_debrief-0.1.0/docs/api-specification.md +102 -0
  185. agent_debrief-0.1.0/docs/architecture.md +88 -0
  186. agent_debrief-0.1.0/docs/development.md +72 -0
  187. agent_debrief-0.1.0/docs/event-contracts.md +80 -0
  188. agent_debrief-0.1.0/docs/images/dashboard.jpg +0 -0
  189. agent_debrief-0.1.0/docs/images/summary.jpg +0 -0
  190. agent_debrief-0.1.0/docs/images/visual-flow.jpg +0 -0
  191. agent_debrief-0.1.0/docs/installation.md +122 -0
  192. agent_debrief-0.1.0/docs/security.md +80 -0
  193. agent_debrief-0.1.0/examples/README.md +32 -0
  194. agent_debrief-0.1.0/examples/sample_fastapi_app/app/__init__.py +0 -0
  195. agent_debrief-0.1.0/examples/sample_fastapi_app/app/main.py +8 -0
  196. agent_debrief-0.1.0/examples/sample_fastapi_app/tests/test_health.py +7 -0
  197. agent_debrief-0.1.0/package.json +19 -0
  198. agent_debrief-0.1.0/pyproject.toml +84 -0
  199. agent_debrief-0.1.0/scripts/verify_clean_install.py +119 -0
@@ -0,0 +1,39 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .venv/
6
+ .pytest_cache/
7
+ .ruff_cache/
8
+ .mypy_cache/
9
+ dist/
10
+ build/
11
+ uv.lock.bak
12
+
13
+ # Node
14
+ node_modules/
15
+ apps/web/dist/
16
+ *.tsbuildinfo
17
+
18
+ # Built frontend that ships inside the Python wheel (produced by `npm run build:web`)
19
+ backend/agent_debrief/web_dist/
20
+
21
+ # Local data / secrets — never commit
22
+ .agent-debrief/
23
+ *.sqlite
24
+ *.sqlite-wal
25
+ *.sqlite-shm
26
+ .env
27
+ .env.*
28
+ !.env.example
29
+ secrets.json
30
+ token
31
+
32
+ # Editors / OS
33
+ .vscode/
34
+ .idea/
35
+ .DS_Store
36
+ Thumbs.db
37
+
38
+ # Stray Windows cache folder (created by an unexpanded %SystemDrive% path)
39
+ %SystemDrive%/
@@ -0,0 +1,42 @@
1
+ # Contributing
2
+
3
+ Thanks for helping make AI-written code easier to understand. This project's one rule: **an explanation must
4
+ point at evidence, and must never present a guess as a fact.** Please read [docs/development.md](docs/development.md)
5
+ for setup, conventions and how to add concepts, risks, languages and agents.
6
+
7
+ ## Quick start
8
+
9
+ ```bash
10
+ uv sync && npm install && npm run build:web
11
+ uv run pytest && uv run ruff check backend
12
+ npm run typecheck && npm run test:web
13
+ ```
14
+
15
+ ## Before you open a pull request
16
+
17
+ - Tests added or updated; the whole suite passes (`uv run pytest`, `npm run test:web`).
18
+ - `uv run ruff check backend` and `npm run typecheck` are clean.
19
+ - API shape changes update **both** `backend/agent_debrief/models/` and `packages/shared-types/src/index.ts`,
20
+ and `docs/api-specification.md`.
21
+ - New facts carry a verification status (`verified` / `agent_reported` / `inferred` / `unverified`) and an evidence
22
+ record. Heuristics are `inferred`; unresolvable relationships produce no edge.
23
+ - Anything that can send data off the machine is documented in `docs/security.md`.
24
+ - Do not claim support for an agent or language until it has been tested on a clean environment.
25
+
26
+ ## Good first contributions
27
+
28
+ - More concepts in `communication/concepts_catalog.py` (with tests).
29
+ - Risk heuristics in `analysis/risk_analyzer.py`.
30
+ - Real-world Claude Code transcripts/hook payload shapes that the parser mishandles (please redact secrets).
31
+ - Tree-sitter based analysis for another language behind the existing `ModuleInfo` shape.
32
+ - Codex / Cursor adapters (see `docs/event-contracts.md#adding-an-agent`).
33
+
34
+ ## Reporting bugs
35
+
36
+ Run `agent-debrief doctor` and include its output, your OS, Python version and whether the task was captured by
37
+ hooks or imported. Please **redact** anything sensitive from logs/payloads. For security issues use a private
38
+ advisory (see `docs/security.md`).
39
+
40
+ ## License
41
+
42
+ By contributing you agree your contribution is licensed under the MIT License.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Agent Debrief contributors
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,169 @@
1
+ Metadata-Version: 2.5
2
+ Name: agent-debrief
3
+ Version: 0.1.0
4
+ Summary: Understand what your AI coding agent actually built — summaries, flows, lessons, voice and Q&A, all backed by evidence.
5
+ Project-URL: Homepage, https://github.com/kishore600/agent-debrief
6
+ Project-URL: Repository, https://github.com/kishore600/agent-debrief
7
+ Project-URL: Issues, https://github.com/kishore600/agent-debrief/issues
8
+ Project-URL: Documentation, https://github.com/kishore600/agent-debrief/tree/main/docs
9
+ Author: Agent Debrief contributors
10
+ License: MIT
11
+ License-File: LICENSE
12
+ Keywords: ai,claude-code,code-understanding,coding-agent,developer-tools
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Software Development
22
+ Requires-Python: >=3.11
23
+ Requires-Dist: fastapi>=0.115
24
+ Requires-Dist: httpx>=0.27
25
+ Requires-Dist: pydantic>=2.7
26
+ Requires-Dist: rich>=13.7
27
+ Requires-Dist: typer>=0.12
28
+ Requires-Dist: uvicorn>=0.30
29
+ Description-Content-Type: text/markdown
30
+
31
+ # Agent Debrief
32
+
33
+ **Understand what your AI coding agent actually built.**
34
+
35
+ AI coding agents finish tasks faster than you can read the diff. Agent Debrief connects to your agent,
36
+ records what it did, analyses the resulting code, and explains it five ways — every explanation tied to
37
+ evidence, and every claim labelled as *verified*, *agent-reported*, *inferred* or *unverified*.
38
+
39
+ | | Experience | What you get |
40
+ |---|---|---|
41
+ | 1 | **Quick Summary** | The completed task in ~30 seconds: ≤5 bullets, files, tests, risks, remaining work |
42
+ | 2 | **Visual Flow** | The application flow (entry → handler → logic → data → response) and the agent's own execution flow |
43
+ | 3 | **Teach Me** | The technical concepts the code uses, one at a time, at beginner / developer / advanced level |
44
+ | 4 | **Talk to Me** | A spoken explanation you can interrupt, continue and question (optional, browser speech) |
45
+ | 5 | **Ask Questions** | Evidence-backed answers: direct answer → code references → flow → limitations |
46
+
47
+ ![Dashboard](docs/images/dashboard.jpg)
48
+ ![Summary](docs/images/summary.jpg)
49
+ ![Visual flow](docs/images/visual-flow.jpg)
50
+
51
+ *Screenshots show the built-in **simulated** demo session (`agent-debrief demo`), not a real agent run.*
52
+
53
+ ## Status
54
+
55
+ `v0.1.0` — **Claude Code + Python.** Local-first, no account, no external database.
56
+
57
+ | Area | State |
58
+ |---|---|
59
+ | Claude Code integration (hooks + transcript) | Implemented. Verified against simulated hook payloads and transcripts; **please test it on your machine** and report problems (see [Known limitations](#known-limitations)). |
60
+ | Python analysis (AST, calls, routes, architecture) | Implemented and tested |
61
+ | Codex, Cursor | **Not supported.** Documented placeholders only. |
62
+ | Other languages | Not yet (changed non-Python files are listed, not analysed) |
63
+ | AI explanations | Optional. Works fully offline with template-based explanations; add an API key for AI-written ones |
64
+
65
+ ## Install
66
+
67
+ Requires **Python 3.11+** and **git**. Node.js is *not* needed to use the tool.
68
+
69
+ ```bash
70
+ # recommended
71
+ uv tool install agent-debrief # or: pipx install agent-debrief
72
+
73
+ agent-debrief init
74
+ agent-debrief connect claude # asks before touching ~/.claude/settings.json
75
+ agent-debrief serve # opens http://127.0.0.1:8765
76
+ ```
77
+
78
+ `debrief` is a short alias for `agent-debrief`. For installing from a source checkout and for Windows, macOS and
79
+ Linux details, see [docs/installation.md](docs/installation.md).
80
+
81
+ Want to look around first? `agent-debrief demo` creates a throw-away project and replays a *simulated*
82
+ Claude Code session so you can explore every tab without running an agent.
83
+
84
+ ## How it works
85
+
86
+ ```
87
+ Claude Code ──hooks──▶ event pipeline ──▶ SQLite ──▶ analysis worker ──▶ task understanding ──▶ 5 experiences
88
+ (redact, normalize, (git baseline diff, (one common, (local web UI)
89
+ correlate, dedupe) AST, relationships, evidence-linked
90
+ evidence, risks) model)
91
+ ```
92
+
93
+ 1. **Hooks** (`SessionStart`, `UserPromptSubmit`, `PreToolUse`, `PostToolUse`, `Stop`, `SessionEnd`) call a tiny
94
+ command that stores each event — secrets redacted — straight into a local SQLite file. The hook never
95
+ prints, never blocks and always exits 0.
96
+ 2. When the prompt is submitted, a **baseline** of your git working tree is snapshotted. After the agent stops,
97
+ only changes *since that baseline* are attributed to the task — a dirty tree is never blamed on the agent.
98
+ 3. The **understanding engine** parses changed Python (AST), resolves calls, classifies architecture layers,
99
+ parses test output, flags risky patterns and attaches an evidence record to every fact.
100
+ 4. The **communication engine** turns that one model into the five experiences. With an AI provider configured,
101
+ an LLM rewrites the wording — but it can only cite real evidence, cannot add flow edges, and any claim naming
102
+ something that is not in the evidence is downgraded to *unverified*.
103
+
104
+ Details: [docs/architecture.md](docs/architecture.md) · [docs/event-contracts.md](docs/event-contracts.md) ·
105
+ [docs/api-specification.md](docs/api-specification.md) · [docs/security.md](docs/security.md)
106
+
107
+ ## Trust model
108
+
109
+ Every statement carries one of four labels:
110
+
111
+ | Label | Meaning |
112
+ |---|---|
113
+ | **Verified** | Observed directly: a git diff, an AST fact, a recorded tool call, parsed test output |
114
+ | **Agent reported** | The agent said so; not independently checked |
115
+ | **Inferred** | An LLM/heuristic interpretation that cites real evidence — never presented as fact |
116
+ | **Unverified** | No usable evidence — a hypothesis |
117
+
118
+ "Completed" always means *the agent stopped*; Agent Debrief never re-runs your tests or your code.
119
+
120
+ ## Privacy
121
+
122
+ Local-first. Nothing leaves your machine unless **you** configure an AI provider, and then only the redacted
123
+ context shown by *AI context* on every task (you can turn off sending code and prompts separately). Hook
124
+ installation is explicit and reversible (`agent-debrief disconnect`), and you can delete a session or all data
125
+ from the UI or the CLI. See [docs/security.md](docs/security.md).
126
+
127
+ ## Commands
128
+
129
+ | Command | |
130
+ |---|---|
131
+ | `agent-debrief init` | Create the data directory, config and database |
132
+ | `agent-debrief connect claude` | Install the Claude Code hooks (backs up your settings first) |
133
+ | `agent-debrief status` | Integrations, captured data, AI provider |
134
+ | `agent-debrief sessions` | List captured tasks (`--available` lists importable Claude transcripts) |
135
+ | `agent-debrief import` | Import past Claude Code sessions from transcripts |
136
+ | `agent-debrief analyze <task>` | Analyse a task from the terminal (`latest` works) |
137
+ | `agent-debrief serve` | Start the web interface (loopback only) |
138
+ | `agent-debrief doctor` | Diagnose configuration, including a real hook self-test |
139
+ | `agent-debrief disconnect` / `uninstall` | Remove the hooks (`--purge-data` removes everything) |
140
+ | `agent-debrief demo` | Explore with a simulated session |
141
+
142
+ ## Known limitations
143
+
144
+ - **Real Claude Code runs are not part of the automated tests.** The hook and transcript code follows the
145
+ documented formats and is tested with realistic simulated payloads; the transcript format is not a stable public
146
+ contract. `agent-debrief doctor` and the log at `<data dir>/logs/hook.log` help diagnose mismatches.
147
+ - Hooks start a short Python process on state-changing tool calls and on every completed tool call
148
+ (typically tens of milliseconds each). `doctor` prints the measured time.
149
+ - Static analysis is Python-only. Calls through unknown objects are not resolved (no edge is drawn) rather than guessed.
150
+ - "Why did the agent do X?" can only be answered when the agent said why; events record *what*, not *why*.
151
+ - Speech uses your browser's Web Speech API (quality and availability vary; Chrome/Edge/Safari). It is optional.
152
+ - Codex and Cursor adapters are planned (release 0.6).
153
+
154
+ ## Development
155
+
156
+ ```bash
157
+ git clone https://github.com/kishore600/agent-debrief.git && cd agent-debrief
158
+ uv sync
159
+ npm install && npm run build:web # builds the UI into the Python package
160
+ uv run agent-debrief init && uv run agent-debrief serve
161
+ uv run pytest # backend tests
162
+ npm run typecheck && npm run test:web
163
+ ```
164
+
165
+ See [CONTRIBUTING.md](CONTRIBUTING.md) and [docs/development.md](docs/development.md).
166
+
167
+ ## License
168
+
169
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,139 @@
1
+ # Agent Debrief
2
+
3
+ **Understand what your AI coding agent actually built.**
4
+
5
+ AI coding agents finish tasks faster than you can read the diff. Agent Debrief connects to your agent,
6
+ records what it did, analyses the resulting code, and explains it five ways — every explanation tied to
7
+ evidence, and every claim labelled as *verified*, *agent-reported*, *inferred* or *unverified*.
8
+
9
+ | | Experience | What you get |
10
+ |---|---|---|
11
+ | 1 | **Quick Summary** | The completed task in ~30 seconds: ≤5 bullets, files, tests, risks, remaining work |
12
+ | 2 | **Visual Flow** | The application flow (entry → handler → logic → data → response) and the agent's own execution flow |
13
+ | 3 | **Teach Me** | The technical concepts the code uses, one at a time, at beginner / developer / advanced level |
14
+ | 4 | **Talk to Me** | A spoken explanation you can interrupt, continue and question (optional, browser speech) |
15
+ | 5 | **Ask Questions** | Evidence-backed answers: direct answer → code references → flow → limitations |
16
+
17
+ ![Dashboard](docs/images/dashboard.jpg)
18
+ ![Summary](docs/images/summary.jpg)
19
+ ![Visual flow](docs/images/visual-flow.jpg)
20
+
21
+ *Screenshots show the built-in **simulated** demo session (`agent-debrief demo`), not a real agent run.*
22
+
23
+ ## Status
24
+
25
+ `v0.1.0` — **Claude Code + Python.** Local-first, no account, no external database.
26
+
27
+ | Area | State |
28
+ |---|---|
29
+ | Claude Code integration (hooks + transcript) | Implemented. Verified against simulated hook payloads and transcripts; **please test it on your machine** and report problems (see [Known limitations](#known-limitations)). |
30
+ | Python analysis (AST, calls, routes, architecture) | Implemented and tested |
31
+ | Codex, Cursor | **Not supported.** Documented placeholders only. |
32
+ | Other languages | Not yet (changed non-Python files are listed, not analysed) |
33
+ | AI explanations | Optional. Works fully offline with template-based explanations; add an API key for AI-written ones |
34
+
35
+ ## Install
36
+
37
+ Requires **Python 3.11+** and **git**. Node.js is *not* needed to use the tool.
38
+
39
+ ```bash
40
+ # recommended
41
+ uv tool install agent-debrief # or: pipx install agent-debrief
42
+
43
+ agent-debrief init
44
+ agent-debrief connect claude # asks before touching ~/.claude/settings.json
45
+ agent-debrief serve # opens http://127.0.0.1:8765
46
+ ```
47
+
48
+ `debrief` is a short alias for `agent-debrief`. For installing from a source checkout and for Windows, macOS and
49
+ Linux details, see [docs/installation.md](docs/installation.md).
50
+
51
+ Want to look around first? `agent-debrief demo` creates a throw-away project and replays a *simulated*
52
+ Claude Code session so you can explore every tab without running an agent.
53
+
54
+ ## How it works
55
+
56
+ ```
57
+ Claude Code ──hooks──▶ event pipeline ──▶ SQLite ──▶ analysis worker ──▶ task understanding ──▶ 5 experiences
58
+ (redact, normalize, (git baseline diff, (one common, (local web UI)
59
+ correlate, dedupe) AST, relationships, evidence-linked
60
+ evidence, risks) model)
61
+ ```
62
+
63
+ 1. **Hooks** (`SessionStart`, `UserPromptSubmit`, `PreToolUse`, `PostToolUse`, `Stop`, `SessionEnd`) call a tiny
64
+ command that stores each event — secrets redacted — straight into a local SQLite file. The hook never
65
+ prints, never blocks and always exits 0.
66
+ 2. When the prompt is submitted, a **baseline** of your git working tree is snapshotted. After the agent stops,
67
+ only changes *since that baseline* are attributed to the task — a dirty tree is never blamed on the agent.
68
+ 3. The **understanding engine** parses changed Python (AST), resolves calls, classifies architecture layers,
69
+ parses test output, flags risky patterns and attaches an evidence record to every fact.
70
+ 4. The **communication engine** turns that one model into the five experiences. With an AI provider configured,
71
+ an LLM rewrites the wording — but it can only cite real evidence, cannot add flow edges, and any claim naming
72
+ something that is not in the evidence is downgraded to *unverified*.
73
+
74
+ Details: [docs/architecture.md](docs/architecture.md) · [docs/event-contracts.md](docs/event-contracts.md) ·
75
+ [docs/api-specification.md](docs/api-specification.md) · [docs/security.md](docs/security.md)
76
+
77
+ ## Trust model
78
+
79
+ Every statement carries one of four labels:
80
+
81
+ | Label | Meaning |
82
+ |---|---|
83
+ | **Verified** | Observed directly: a git diff, an AST fact, a recorded tool call, parsed test output |
84
+ | **Agent reported** | The agent said so; not independently checked |
85
+ | **Inferred** | An LLM/heuristic interpretation that cites real evidence — never presented as fact |
86
+ | **Unverified** | No usable evidence — a hypothesis |
87
+
88
+ "Completed" always means *the agent stopped*; Agent Debrief never re-runs your tests or your code.
89
+
90
+ ## Privacy
91
+
92
+ Local-first. Nothing leaves your machine unless **you** configure an AI provider, and then only the redacted
93
+ context shown by *AI context* on every task (you can turn off sending code and prompts separately). Hook
94
+ installation is explicit and reversible (`agent-debrief disconnect`), and you can delete a session or all data
95
+ from the UI or the CLI. See [docs/security.md](docs/security.md).
96
+
97
+ ## Commands
98
+
99
+ | Command | |
100
+ |---|---|
101
+ | `agent-debrief init` | Create the data directory, config and database |
102
+ | `agent-debrief connect claude` | Install the Claude Code hooks (backs up your settings first) |
103
+ | `agent-debrief status` | Integrations, captured data, AI provider |
104
+ | `agent-debrief sessions` | List captured tasks (`--available` lists importable Claude transcripts) |
105
+ | `agent-debrief import` | Import past Claude Code sessions from transcripts |
106
+ | `agent-debrief analyze <task>` | Analyse a task from the terminal (`latest` works) |
107
+ | `agent-debrief serve` | Start the web interface (loopback only) |
108
+ | `agent-debrief doctor` | Diagnose configuration, including a real hook self-test |
109
+ | `agent-debrief disconnect` / `uninstall` | Remove the hooks (`--purge-data` removes everything) |
110
+ | `agent-debrief demo` | Explore with a simulated session |
111
+
112
+ ## Known limitations
113
+
114
+ - **Real Claude Code runs are not part of the automated tests.** The hook and transcript code follows the
115
+ documented formats and is tested with realistic simulated payloads; the transcript format is not a stable public
116
+ contract. `agent-debrief doctor` and the log at `<data dir>/logs/hook.log` help diagnose mismatches.
117
+ - Hooks start a short Python process on state-changing tool calls and on every completed tool call
118
+ (typically tens of milliseconds each). `doctor` prints the measured time.
119
+ - Static analysis is Python-only. Calls through unknown objects are not resolved (no edge is drawn) rather than guessed.
120
+ - "Why did the agent do X?" can only be answered when the agent said why; events record *what*, not *why*.
121
+ - Speech uses your browser's Web Speech API (quality and availability vary; Chrome/Edge/Safari). It is optional.
122
+ - Codex and Cursor adapters are planned (release 0.6).
123
+
124
+ ## Development
125
+
126
+ ```bash
127
+ git clone https://github.com/kishore600/agent-debrief.git && cd agent-debrief
128
+ uv sync
129
+ npm install && npm run build:web # builds the UI into the Python package
130
+ uv run agent-debrief init && uv run agent-debrief serve
131
+ uv run pytest # backend tests
132
+ npm run typecheck && npm run test:web
133
+ ```
134
+
135
+ See [CONTRIBUTING.md](CONTRIBUTING.md) and [docs/development.md](docs/development.md).
136
+
137
+ ## License
138
+
139
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,18 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <meta name="color-scheme" content="light dark" />
7
+ <meta name="description" content="Understand what your AI coding agent actually built." />
8
+ <title>Agent Debrief</title>
9
+ <link
10
+ rel="icon"
11
+ href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='8' fill='%234f46e5'/%3E%3Cpath d='M9 11h14M9 16h9M9 21h14' stroke='white' stroke-width='2.4' stroke-linecap='round'/%3E%3C/svg%3E"
12
+ />
13
+ </head>
14
+ <body>
15
+ <div id="root"></div>
16
+ <script type="module" src="/src/main.tsx"></script>
17
+ </body>
18
+ </html>
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@agent-debrief/web",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "description": "Agent Debrief local web interface (React + TypeScript).",
7
+ "scripts": {
8
+ "dev": "vite",
9
+ "build": "tsc -p tsconfig.json --noEmit && vite build",
10
+ "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.node.json --noEmit",
11
+ "test": "vitest run",
12
+ "preview": "vite preview"
13
+ },
14
+ "dependencies": {
15
+ "@agent-debrief/shared-types": "*",
16
+ "@dagrejs/dagre": "1.1.8",
17
+ "@tanstack/react-query": "5.106.1",
18
+ "@xyflow/react": "12.12.1",
19
+ "react": "18.3.1",
20
+ "react-dom": "18.3.1",
21
+ "react-router-dom": "6.30.6"
22
+ },
23
+ "devDependencies": {
24
+ "@types/node": "20.19.43",
25
+ "@types/react": "18.3.31",
26
+ "@types/react-dom": "18.3.7",
27
+ "@vitejs/plugin-react": "4.7.0",
28
+ "typescript": "5.9.3",
29
+ "vite": "5.4.21",
30
+ "vitest": "2.1.9"
31
+ }
32
+ }
@@ -0,0 +1,25 @@
1
+ import { Route, Routes } from "react-router-dom";
2
+ import { AppLayout } from "@/layouts/AppLayout";
3
+ import { DashboardPage } from "@/pages/DashboardPage";
4
+ import { NotFoundPage } from "@/pages/NotFoundPage";
5
+ import { ProjectsPage } from "@/pages/ProjectsPage";
6
+ import { SessionDetailPage } from "@/pages/SessionDetailPage";
7
+ import { SessionsPage } from "@/pages/SessionsPage";
8
+ import { SettingsPage } from "@/pages/SettingsPage";
9
+ import { TaskPage } from "@/pages/TaskPage";
10
+
11
+ export function App() {
12
+ return (
13
+ <Routes>
14
+ <Route element={<AppLayout />}>
15
+ <Route index element={<DashboardPage />} />
16
+ <Route path="sessions" element={<SessionsPage />} />
17
+ <Route path="sessions/:id" element={<SessionDetailPage />} />
18
+ <Route path="projects" element={<ProjectsPage />} />
19
+ <Route path="settings" element={<SettingsPage />} />
20
+ <Route path="tasks/:taskId/:tab?" element={<TaskPage />} />
21
+ <Route path="*" element={<NotFoundPage />} />
22
+ </Route>
23
+ </Routes>
24
+ );
25
+ }
@@ -0,0 +1,43 @@
1
+ import type { Claim } from "@agent-debrief/shared-types";
2
+ import { VerificationBadge } from "./badges";
3
+ import { EvidenceChips } from "./evidence";
4
+ import { Icon } from "./Icon";
5
+
6
+ export function UnverifiedMentions({ mentions }: { mentions: readonly string[] }) {
7
+ if (mentions.length === 0) return null;
8
+ return (
9
+ <p className="mention-warning" role="note">
10
+ <Icon name="alert" size={13} /> Not found in this task's evidence:{" "}
11
+ {mentions.map((m, i) => (
12
+ <span key={m}>
13
+ {i > 0 ? ", " : ""}
14
+ <code>{m}</code>
15
+ </span>
16
+ ))}
17
+ </p>
18
+ );
19
+ }
20
+
21
+ export function ClaimItem({ claim }: { claim: Claim }) {
22
+ return (
23
+ <div className="claim">
24
+ <div>{claim.text}</div>
25
+ <div className="row" style={{ gap: "0.5rem" }}>
26
+ <VerificationBadge status={claim.verification_status} compact />
27
+ <EvidenceChips ids={claim.evidence_ids} />
28
+ </div>
29
+ <UnverifiedMentions mentions={claim.unverified_mentions} />
30
+ </div>
31
+ );
32
+ }
33
+
34
+ export function ClaimList({ claims, empty }: { claims: readonly Claim[]; empty?: string }) {
35
+ if (claims.length === 0) return empty ? <p className="muted" style={{ padding: "0.9rem 1.1rem" }}>{empty}</p> : null;
36
+ return (
37
+ <div>
38
+ {claims.map((claim, i) => (
39
+ <ClaimItem key={i} claim={claim} />
40
+ ))}
41
+ </div>
42
+ );
43
+ }
@@ -0,0 +1,81 @@
1
+ import { useState } from "react";
2
+ import { Icon } from "./Icon";
3
+
4
+ interface CodeBlockProps {
5
+ code: string;
6
+ caption?: string;
7
+ /** Show line numbers starting here. */
8
+ startLine?: number | null;
9
+ language?: string | null;
10
+ maxHeight?: number;
11
+ }
12
+
13
+ export function CodeBlock({ code, caption, startLine, language, maxHeight }: CodeBlockProps) {
14
+ const [copied, setCopied] = useState(false);
15
+ const lines = code.replace(/\n$/, "").split("\n");
16
+
17
+ const copy = async () => {
18
+ try {
19
+ await navigator.clipboard.writeText(code);
20
+ setCopied(true);
21
+ window.setTimeout(() => setCopied(false), 1500);
22
+ } catch {
23
+ // Clipboard may be unavailable (insecure context); ignore.
24
+ }
25
+ };
26
+
27
+ return (
28
+ <figure style={{ margin: 0 }}>
29
+ <div className="code-caption">
30
+ <span className="mono break">{caption ?? language ?? ""}</span>
31
+ <button type="button" className="btn btn--ghost btn--sm" onClick={copy}>
32
+ <Icon name={copied ? "check" : "file"} size={14} />
33
+ {copied ? "Copied" : "Copy"}
34
+ </button>
35
+ </div>
36
+ <div className="code" style={maxHeight ? { maxHeight } : undefined} tabIndex={0} role="region" aria-label={caption ?? "Code"}>
37
+ <pre>
38
+ <code style={{ background: "none", padding: 0 }}>
39
+ {lines.map((line, i) => (
40
+ <span key={i} style={{ display: "block" }}>
41
+ {startLine != null ? <span className="ln">{startLine + i}</span> : null}
42
+ {line || " "}
43
+ </span>
44
+ ))}
45
+ </code>
46
+ </pre>
47
+ </div>
48
+ </figure>
49
+ );
50
+ }
51
+
52
+ /** Unified diff with +/- colouring. Colour is reinforced by the leading +/- characters. */
53
+ export function DiffView({ diff, truncated }: { diff: string; truncated?: boolean }) {
54
+ const lines = diff.replace(/\n$/, "").split("\n");
55
+ return (
56
+ <figure style={{ margin: 0 }}>
57
+ <div className="code" tabIndex={0} role="region" aria-label="Unified diff">
58
+ <pre style={{ padding: "0.5rem 0" }}>
59
+ {lines.map((line, i) => {
60
+ let cls = "diff-line";
61
+ if (line.startsWith("@@")) cls += " diff-line--hunk";
62
+ else if (line.startsWith("+++") || line.startsWith("---") || line.startsWith("diff ") || line.startsWith("index "))
63
+ cls += " diff-line--meta";
64
+ else if (line.startsWith("+")) cls += " diff-line--add";
65
+ else if (line.startsWith("-")) cls += " diff-line--del";
66
+ return (
67
+ <span key={i} className={cls}>
68
+ {line || " "}
69
+ </span>
70
+ );
71
+ })}
72
+ </pre>
73
+ </div>
74
+ {truncated ? (
75
+ <p className="faint small" style={{ marginTop: 6 }}>
76
+ Diff truncated — only the first part is shown.
77
+ </p>
78
+ ) : null}
79
+ </figure>
80
+ );
81
+ }