@jaguilar87/gaia 5.0.0-rc1

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 (609) hide show
  1. package/.claude-plugin/marketplace.json +33 -0
  2. package/.claude-plugin/plugin.json +26 -0
  3. package/ARCHITECTURE.md +335 -0
  4. package/CHANGELOG.md +1212 -0
  5. package/CODE_OF_CONDUCT.md +11 -0
  6. package/CONTRIBUTING.md +146 -0
  7. package/INSTALL.md +436 -0
  8. package/LICENSE +21 -0
  9. package/README.md +222 -0
  10. package/SECURITY.md +47 -0
  11. package/agents/README.md +78 -0
  12. package/agents/cloud-troubleshooter.md +73 -0
  13. package/agents/developer.md +65 -0
  14. package/agents/gaia-operator.md +64 -0
  15. package/agents/gaia-orchestrator.md +237 -0
  16. package/agents/gaia-planner.md +53 -0
  17. package/agents/gaia-system.md +70 -0
  18. package/agents/gitops-operator.md +61 -0
  19. package/agents/terraform-architect.md +63 -0
  20. package/bin/README.md +106 -0
  21. package/bin/cli/__init__.py +1 -0
  22. package/bin/cli/approvals.py +740 -0
  23. package/bin/cli/cleanup.py +562 -0
  24. package/bin/cli/context.py +283 -0
  25. package/bin/cli/doctor.py +628 -0
  26. package/bin/cli/history.py +305 -0
  27. package/bin/cli/memory.py +464 -0
  28. package/bin/cli/metrics.py +1068 -0
  29. package/bin/cli/plans.py +515 -0
  30. package/bin/cli/status.py +302 -0
  31. package/bin/cli/update.py +382 -0
  32. package/bin/gaia +112 -0
  33. package/bin/gaia-cleanup.js +531 -0
  34. package/bin/gaia-doctor.js +635 -0
  35. package/bin/gaia-evidence +126 -0
  36. package/bin/gaia-history.js +251 -0
  37. package/bin/gaia-metrics.js +1278 -0
  38. package/bin/gaia-review.js +269 -0
  39. package/bin/gaia-scan +44 -0
  40. package/bin/gaia-scan.py +589 -0
  41. package/bin/gaia-skills-diagnose.js +929 -0
  42. package/bin/gaia-status.js +278 -0
  43. package/bin/gaia-uninstall.js +111 -0
  44. package/bin/gaia-update.js +816 -0
  45. package/bin/pre-publish-validate.js +610 -0
  46. package/bin/python-detect.js +60 -0
  47. package/commands/README.md +64 -0
  48. package/commands/gaia.md +37 -0
  49. package/commands/scan-project.md +67 -0
  50. package/config/README.md +71 -0
  51. package/config/cloud/aws.json +134 -0
  52. package/config/cloud/gcp.json +139 -0
  53. package/config/context-contracts.json +158 -0
  54. package/config/crons-schema.md +81 -0
  55. package/config/git_standards.json +72 -0
  56. package/config/surface-routing.json +421 -0
  57. package/config/universal-rules.json +102 -0
  58. package/dist/gaia-ops/.claude-plugin/plugin.json +24 -0
  59. package/dist/gaia-ops/README.md +80 -0
  60. package/dist/gaia-ops/agents/cloud-troubleshooter.md +73 -0
  61. package/dist/gaia-ops/agents/developer.md +65 -0
  62. package/dist/gaia-ops/agents/gaia-operator.md +64 -0
  63. package/dist/gaia-ops/agents/gaia-orchestrator.md +237 -0
  64. package/dist/gaia-ops/agents/gaia-planner.md +53 -0
  65. package/dist/gaia-ops/agents/gaia-system.md +70 -0
  66. package/dist/gaia-ops/agents/gitops-operator.md +61 -0
  67. package/dist/gaia-ops/agents/terraform-architect.md +63 -0
  68. package/dist/gaia-ops/commands/gaia.md +37 -0
  69. package/dist/gaia-ops/config/README.md +71 -0
  70. package/dist/gaia-ops/config/cloud/aws.json +134 -0
  71. package/dist/gaia-ops/config/cloud/gcp.json +139 -0
  72. package/dist/gaia-ops/config/context-contracts.json +158 -0
  73. package/dist/gaia-ops/config/crons-schema.md +81 -0
  74. package/dist/gaia-ops/config/git_standards.json +72 -0
  75. package/dist/gaia-ops/config/surface-routing.json +421 -0
  76. package/dist/gaia-ops/config/universal-rules.json +102 -0
  77. package/dist/gaia-ops/hooks/adapters/__init__.py +52 -0
  78. package/dist/gaia-ops/hooks/adapters/base.py +219 -0
  79. package/dist/gaia-ops/hooks/adapters/channel.py +17 -0
  80. package/dist/gaia-ops/hooks/adapters/claude_code.py +1890 -0
  81. package/dist/gaia-ops/hooks/adapters/types.py +194 -0
  82. package/dist/gaia-ops/hooks/adapters/utils.py +25 -0
  83. package/dist/gaia-ops/hooks/hooks.json +163 -0
  84. package/dist/gaia-ops/hooks/modules/__init__.py +15 -0
  85. package/dist/gaia-ops/hooks/modules/agents/__init__.py +29 -0
  86. package/dist/gaia-ops/hooks/modules/agents/contract_validator.py +647 -0
  87. package/dist/gaia-ops/hooks/modules/agents/response_contract.py +496 -0
  88. package/dist/gaia-ops/hooks/modules/agents/skill_injection_verifier.py +120 -0
  89. package/dist/gaia-ops/hooks/modules/agents/state_tracker.py +267 -0
  90. package/dist/gaia-ops/hooks/modules/agents/task_info_builder.py +74 -0
  91. package/dist/gaia-ops/hooks/modules/agents/transcript_analyzer.py +458 -0
  92. package/dist/gaia-ops/hooks/modules/agents/transcript_reader.py +152 -0
  93. package/dist/gaia-ops/hooks/modules/audit/__init__.py +28 -0
  94. package/dist/gaia-ops/hooks/modules/audit/event_detector.py +168 -0
  95. package/dist/gaia-ops/hooks/modules/audit/logger.py +131 -0
  96. package/dist/gaia-ops/hooks/modules/audit/metrics.py +134 -0
  97. package/dist/gaia-ops/hooks/modules/audit/workflow_auditor.py +611 -0
  98. package/dist/gaia-ops/hooks/modules/audit/workflow_recorder.py +296 -0
  99. package/dist/gaia-ops/hooks/modules/context/__init__.py +11 -0
  100. package/dist/gaia-ops/hooks/modules/context/agentic_loop_detector.py +165 -0
  101. package/dist/gaia-ops/hooks/modules/context/anchor_tracker.py +317 -0
  102. package/dist/gaia-ops/hooks/modules/context/compact_context_builder.py +218 -0
  103. package/dist/gaia-ops/hooks/modules/context/context_freshness.py +145 -0
  104. package/dist/gaia-ops/hooks/modules/context/context_injector.py +558 -0
  105. package/dist/gaia-ops/hooks/modules/context/context_writer.py +530 -0
  106. package/dist/gaia-ops/hooks/modules/context/contracts_loader.py +161 -0
  107. package/dist/gaia-ops/hooks/modules/core/__init__.py +40 -0
  108. package/dist/gaia-ops/hooks/modules/core/hook_entry.py +78 -0
  109. package/dist/gaia-ops/hooks/modules/core/paths.py +160 -0
  110. package/dist/gaia-ops/hooks/modules/core/plugin_mode.py +149 -0
  111. package/dist/gaia-ops/hooks/modules/core/plugin_setup.py +577 -0
  112. package/dist/gaia-ops/hooks/modules/core/state.py +179 -0
  113. package/dist/gaia-ops/hooks/modules/core/stdin.py +24 -0
  114. package/dist/gaia-ops/hooks/modules/events/__init__.py +1 -0
  115. package/dist/gaia-ops/hooks/modules/events/event_writer.py +210 -0
  116. package/dist/gaia-ops/hooks/modules/memory/__init__.py +8 -0
  117. package/dist/gaia-ops/hooks/modules/memory/episode_writer.py +216 -0
  118. package/dist/gaia-ops/hooks/modules/orchestrator/__init__.py +1 -0
  119. package/dist/gaia-ops/hooks/modules/orchestrator/delegate_mode.py +122 -0
  120. package/dist/gaia-ops/hooks/modules/scanning/__init__.py +8 -0
  121. package/dist/gaia-ops/hooks/modules/scanning/scan_trigger.py +84 -0
  122. package/dist/gaia-ops/hooks/modules/security/__init__.py +120 -0
  123. package/dist/gaia-ops/hooks/modules/security/approval_cleanup.py +87 -0
  124. package/dist/gaia-ops/hooks/modules/security/approval_constants.py +23 -0
  125. package/dist/gaia-ops/hooks/modules/security/approval_grants.py +1638 -0
  126. package/dist/gaia-ops/hooks/modules/security/approval_messages.py +71 -0
  127. package/dist/gaia-ops/hooks/modules/security/approval_scopes.py +222 -0
  128. package/dist/gaia-ops/hooks/modules/security/blocked_commands.py +595 -0
  129. package/dist/gaia-ops/hooks/modules/security/blocked_message_formatter.py +87 -0
  130. package/dist/gaia-ops/hooks/modules/security/command_semantics.py +181 -0
  131. package/dist/gaia-ops/hooks/modules/security/composition_rules.py +547 -0
  132. package/dist/gaia-ops/hooks/modules/security/flag_classifiers.py +873 -0
  133. package/dist/gaia-ops/hooks/modules/security/gitops_validator.py +179 -0
  134. package/dist/gaia-ops/hooks/modules/security/mutative_verbs.py +1131 -0
  135. package/dist/gaia-ops/hooks/modules/security/network_hosts.py +481 -0
  136. package/dist/gaia-ops/hooks/modules/security/prompt_validator.py +40 -0
  137. package/dist/gaia-ops/hooks/modules/security/shell_unwrapper.py +165 -0
  138. package/dist/gaia-ops/hooks/modules/security/tiers.py +196 -0
  139. package/dist/gaia-ops/hooks/modules/session/__init__.py +10 -0
  140. package/dist/gaia-ops/hooks/modules/session/pending_scanner.py +174 -0
  141. package/dist/gaia-ops/hooks/modules/session/session_context_writer.py +100 -0
  142. package/dist/gaia-ops/hooks/modules/session/session_event_injector.py +160 -0
  143. package/dist/gaia-ops/hooks/modules/session/session_manager.py +31 -0
  144. package/dist/gaia-ops/hooks/modules/session/session_registry.py +232 -0
  145. package/dist/gaia-ops/hooks/modules/tools/__init__.py +29 -0
  146. package/dist/gaia-ops/hooks/modules/tools/bash_validator.py +1008 -0
  147. package/dist/gaia-ops/hooks/modules/tools/cloud_pipe_validator.py +231 -0
  148. package/dist/gaia-ops/hooks/modules/tools/hook_response.py +55 -0
  149. package/dist/gaia-ops/hooks/modules/tools/shell_parser.py +227 -0
  150. package/dist/gaia-ops/hooks/modules/tools/stage_decomposer.py +315 -0
  151. package/dist/gaia-ops/hooks/modules/tools/task_validator.py +294 -0
  152. package/dist/gaia-ops/hooks/modules/validation/__init__.py +23 -0
  153. package/dist/gaia-ops/hooks/modules/validation/commit_validator.py +380 -0
  154. package/dist/gaia-ops/hooks/post_compact.py +43 -0
  155. package/dist/gaia-ops/hooks/post_tool_use.py +54 -0
  156. package/dist/gaia-ops/hooks/pre_compact.py +60 -0
  157. package/dist/gaia-ops/hooks/pre_tool_use.py +413 -0
  158. package/dist/gaia-ops/hooks/session_start.py +81 -0
  159. package/dist/gaia-ops/hooks/stop_hook.py +82 -0
  160. package/dist/gaia-ops/hooks/subagent_start.py +71 -0
  161. package/dist/gaia-ops/hooks/subagent_stop.py +295 -0
  162. package/dist/gaia-ops/hooks/task_completed.py +70 -0
  163. package/dist/gaia-ops/hooks/user_prompt_submit.py +246 -0
  164. package/dist/gaia-ops/settings.json +72 -0
  165. package/dist/gaia-ops/skills/README.md +154 -0
  166. package/dist/gaia-ops/skills/agent-protocol/SKILL.md +93 -0
  167. package/dist/gaia-ops/skills/agent-protocol/examples.md +223 -0
  168. package/dist/gaia-ops/skills/agent-response/SKILL.md +69 -0
  169. package/dist/gaia-ops/skills/agentic-loop/SKILL.md +80 -0
  170. package/dist/gaia-ops/skills/agentic-loop/reference.md +378 -0
  171. package/dist/gaia-ops/skills/blog-writing/SKILL.md +98 -0
  172. package/dist/gaia-ops/skills/blog-writing/reference.md +130 -0
  173. package/dist/gaia-ops/skills/brief-spec/SKILL.md +182 -0
  174. package/dist/gaia-ops/skills/command-execution/SKILL.md +64 -0
  175. package/dist/gaia-ops/skills/command-execution/reference.md +83 -0
  176. package/dist/gaia-ops/skills/context-updater/SKILL.md +87 -0
  177. package/dist/gaia-ops/skills/context-updater/examples.md +71 -0
  178. package/dist/gaia-ops/skills/developer-patterns/SKILL.md +50 -0
  179. package/dist/gaia-ops/skills/developer-patterns/reference.md +112 -0
  180. package/dist/gaia-ops/skills/execution/SKILL.md +99 -0
  181. package/dist/gaia-ops/skills/fast-queries/SKILL.md +43 -0
  182. package/dist/gaia-ops/skills/gaia-compact/SKILL.md +74 -0
  183. package/dist/gaia-ops/skills/gaia-patterns/SKILL.md +108 -0
  184. package/dist/gaia-ops/skills/gaia-patterns/reference.md +395 -0
  185. package/dist/gaia-ops/skills/gaia-planner/SKILL.md +37 -0
  186. package/dist/gaia-ops/skills/gaia-planner/reference.md +107 -0
  187. package/dist/gaia-ops/skills/gaia-release/SKILL.md +82 -0
  188. package/dist/gaia-ops/skills/gaia-release/reference.md +102 -0
  189. package/dist/gaia-ops/skills/gaia-self-check/SKILL.md +114 -0
  190. package/dist/gaia-ops/skills/gaia-self-check/reference.md +453 -0
  191. package/dist/gaia-ops/skills/gaia-verify/SKILL.md +77 -0
  192. package/dist/gaia-ops/skills/gaia-verify/reference.md +80 -0
  193. package/dist/gaia-ops/skills/git-conventions/SKILL.md +47 -0
  194. package/dist/gaia-ops/skills/gitops-patterns/SKILL.md +60 -0
  195. package/dist/gaia-ops/skills/gitops-patterns/reference.md +183 -0
  196. package/dist/gaia-ops/skills/gmail-policy/SKILL.md +200 -0
  197. package/dist/gaia-ops/skills/gmail-policy/reference.md +150 -0
  198. package/dist/gaia-ops/skills/gmail-triage/SKILL.md +100 -0
  199. package/dist/gaia-ops/skills/gws-setup/SKILL.md +99 -0
  200. package/dist/gaia-ops/skills/gws-setup/reference.md +73 -0
  201. package/dist/gaia-ops/skills/investigation/SKILL.md +100 -0
  202. package/dist/gaia-ops/skills/memory-curation/SKILL.md +83 -0
  203. package/dist/gaia-ops/skills/memory-search/SKILL.md +88 -0
  204. package/dist/gaia-ops/skills/orchestrator-approval/SKILL.md +160 -0
  205. package/dist/gaia-ops/skills/orchestrator-approval/reference.md +174 -0
  206. package/dist/gaia-ops/skills/pending-approvals/SKILL.md +72 -0
  207. package/dist/gaia-ops/skills/pending-approvals/reference.md +214 -0
  208. package/dist/gaia-ops/skills/readme-writing/SKILL.md +71 -0
  209. package/dist/gaia-ops/skills/readme-writing/reference.md +188 -0
  210. package/dist/gaia-ops/skills/reference.md +135 -0
  211. package/dist/gaia-ops/skills/request-approval/SKILL.md +140 -0
  212. package/dist/gaia-ops/skills/request-approval/examples.md +140 -0
  213. package/dist/gaia-ops/skills/request-approval/reference.md +57 -0
  214. package/dist/gaia-ops/skills/schedule-task/SKILL.md +64 -0
  215. package/dist/gaia-ops/skills/schedule-task/reference.md +233 -0
  216. package/dist/gaia-ops/skills/security-tiers/SKILL.md +141 -0
  217. package/dist/gaia-ops/skills/security-tiers/destructive-commands-reference.md +623 -0
  218. package/dist/gaia-ops/skills/security-tiers/reference.md +39 -0
  219. package/dist/gaia-ops/skills/skill-creation/SKILL.md +92 -0
  220. package/dist/gaia-ops/skills/skill-creation/reference.md +29 -0
  221. package/dist/gaia-ops/skills/terraform-patterns/SKILL.md +89 -0
  222. package/dist/gaia-ops/skills/terraform-patterns/reference.md +93 -0
  223. package/dist/gaia-ops/tools/__init__.py +9 -0
  224. package/dist/gaia-ops/tools/agentic-loop/decide-status.py +210 -0
  225. package/dist/gaia-ops/tools/agentic-loop/parse-metric.py +106 -0
  226. package/dist/gaia-ops/tools/agentic-loop/record-iteration.py +221 -0
  227. package/dist/gaia-ops/tools/context/README.md +132 -0
  228. package/dist/gaia-ops/tools/context/__init__.py +42 -0
  229. package/dist/gaia-ops/tools/context/_paths.py +20 -0
  230. package/dist/gaia-ops/tools/context/context_provider.py +721 -0
  231. package/dist/gaia-ops/tools/context/context_section_reader.py +342 -0
  232. package/dist/gaia-ops/tools/context/deep_merge.py +159 -0
  233. package/dist/gaia-ops/tools/context/pending_updates.py +760 -0
  234. package/dist/gaia-ops/tools/context/surface_router.py +278 -0
  235. package/dist/gaia-ops/tools/fast-queries/README.md +65 -0
  236. package/dist/gaia-ops/tools/fast-queries/__init__.py +30 -0
  237. package/dist/gaia-ops/tools/fast-queries/appservices/quicktriage_devops_developer.sh +75 -0
  238. package/dist/gaia-ops/tools/fast-queries/cloud/aws/quicktriage_aws_troubleshooter.sh +32 -0
  239. package/dist/gaia-ops/tools/fast-queries/cloud/gcp/quicktriage_gcp_troubleshooter.sh +88 -0
  240. package/dist/gaia-ops/tools/fast-queries/gitops/quicktriage_gitops_operator.sh +48 -0
  241. package/dist/gaia-ops/tools/fast-queries/run_triage.sh +59 -0
  242. package/dist/gaia-ops/tools/fast-queries/terraform/quicktriage_terraform_architect.sh +80 -0
  243. package/dist/gaia-ops/tools/gaia_simulator/__init__.py +33 -0
  244. package/dist/gaia-ops/tools/gaia_simulator/cli.py +354 -0
  245. package/dist/gaia-ops/tools/gaia_simulator/extractor.py +457 -0
  246. package/dist/gaia-ops/tools/gaia_simulator/reporter.py +258 -0
  247. package/dist/gaia-ops/tools/gaia_simulator/routing_simulator.py +334 -0
  248. package/dist/gaia-ops/tools/gaia_simulator/runner.py +539 -0
  249. package/dist/gaia-ops/tools/gaia_simulator/skills_mapper.py +264 -0
  250. package/dist/gaia-ops/tools/memory/README.md +0 -0
  251. package/dist/gaia-ops/tools/memory/__init__.py +20 -0
  252. package/dist/gaia-ops/tools/memory/backfill_fts5.py +107 -0
  253. package/dist/gaia-ops/tools/memory/conflict_detector.py +295 -0
  254. package/dist/gaia-ops/tools/memory/episodic.py +1210 -0
  255. package/dist/gaia-ops/tools/memory/git_invalidator.py +262 -0
  256. package/dist/gaia-ops/tools/memory/paths.py +102 -0
  257. package/dist/gaia-ops/tools/memory/scoring.py +193 -0
  258. package/dist/gaia-ops/tools/memory/search_store.py +360 -0
  259. package/dist/gaia-ops/tools/persist_transcript_analysis.py +85 -0
  260. package/dist/gaia-ops/tools/review/__init__.py +1 -0
  261. package/dist/gaia-ops/tools/review/review_engine.py +157 -0
  262. package/dist/gaia-ops/tools/scan/__init__.py +35 -0
  263. package/dist/gaia-ops/tools/scan/config.py +247 -0
  264. package/dist/gaia-ops/tools/scan/merge.py +212 -0
  265. package/dist/gaia-ops/tools/scan/orchestrator.py +549 -0
  266. package/dist/gaia-ops/tools/scan/registry.py +127 -0
  267. package/dist/gaia-ops/tools/scan/scanners/__init__.py +18 -0
  268. package/dist/gaia-ops/tools/scan/scanners/base.py +137 -0
  269. package/dist/gaia-ops/tools/scan/scanners/environment.py +349 -0
  270. package/dist/gaia-ops/tools/scan/scanners/git.py +570 -0
  271. package/dist/gaia-ops/tools/scan/scanners/infrastructure.py +875 -0
  272. package/dist/gaia-ops/tools/scan/scanners/orchestration.py +600 -0
  273. package/dist/gaia-ops/tools/scan/scanners/stack.py +1085 -0
  274. package/dist/gaia-ops/tools/scan/scanners/tools.py +260 -0
  275. package/dist/gaia-ops/tools/scan/setup.py +686 -0
  276. package/dist/gaia-ops/tools/scan/tests/__init__.py +1 -0
  277. package/dist/gaia-ops/tools/scan/tests/conftest.py +796 -0
  278. package/dist/gaia-ops/tools/scan/tests/test_environment.py +323 -0
  279. package/dist/gaia-ops/tools/scan/tests/test_git.py +419 -0
  280. package/dist/gaia-ops/tools/scan/tests/test_infrastructure.py +382 -0
  281. package/dist/gaia-ops/tools/scan/tests/test_integration.py +920 -0
  282. package/dist/gaia-ops/tools/scan/tests/test_merge.py +269 -0
  283. package/dist/gaia-ops/tools/scan/tests/test_orchestration.py +304 -0
  284. package/dist/gaia-ops/tools/scan/tests/test_stack.py +604 -0
  285. package/dist/gaia-ops/tools/scan/tests/test_tools.py +349 -0
  286. package/dist/gaia-ops/tools/scan/ui.py +624 -0
  287. package/dist/gaia-ops/tools/scan/verify.py +270 -0
  288. package/dist/gaia-ops/tools/scan/walk.py +118 -0
  289. package/dist/gaia-ops/tools/scan/workspace.py +85 -0
  290. package/dist/gaia-ops/tools/validation/README.md +244 -0
  291. package/dist/gaia-ops/tools/validation/__init__.py +17 -0
  292. package/dist/gaia-ops/tools/validation/approval_gate.py +321 -0
  293. package/dist/gaia-ops/tools/validation/validate_skills.py +189 -0
  294. package/dist/gaia-security/.claude-plugin/plugin.json +24 -0
  295. package/dist/gaia-security/README.md +90 -0
  296. package/dist/gaia-security/config/universal-rules.json +102 -0
  297. package/dist/gaia-security/hooks/adapters/__init__.py +52 -0
  298. package/dist/gaia-security/hooks/adapters/base.py +219 -0
  299. package/dist/gaia-security/hooks/adapters/channel.py +17 -0
  300. package/dist/gaia-security/hooks/adapters/claude_code.py +1890 -0
  301. package/dist/gaia-security/hooks/adapters/types.py +194 -0
  302. package/dist/gaia-security/hooks/adapters/utils.py +25 -0
  303. package/dist/gaia-security/hooks/hooks.json +84 -0
  304. package/dist/gaia-security/hooks/modules/__init__.py +15 -0
  305. package/dist/gaia-security/hooks/modules/agents/__init__.py +29 -0
  306. package/dist/gaia-security/hooks/modules/agents/contract_validator.py +647 -0
  307. package/dist/gaia-security/hooks/modules/agents/response_contract.py +496 -0
  308. package/dist/gaia-security/hooks/modules/agents/skill_injection_verifier.py +120 -0
  309. package/dist/gaia-security/hooks/modules/agents/state_tracker.py +267 -0
  310. package/dist/gaia-security/hooks/modules/agents/task_info_builder.py +74 -0
  311. package/dist/gaia-security/hooks/modules/agents/transcript_analyzer.py +458 -0
  312. package/dist/gaia-security/hooks/modules/agents/transcript_reader.py +152 -0
  313. package/dist/gaia-security/hooks/modules/audit/__init__.py +28 -0
  314. package/dist/gaia-security/hooks/modules/audit/event_detector.py +168 -0
  315. package/dist/gaia-security/hooks/modules/audit/logger.py +131 -0
  316. package/dist/gaia-security/hooks/modules/audit/metrics.py +134 -0
  317. package/dist/gaia-security/hooks/modules/audit/workflow_auditor.py +611 -0
  318. package/dist/gaia-security/hooks/modules/audit/workflow_recorder.py +296 -0
  319. package/dist/gaia-security/hooks/modules/context/__init__.py +11 -0
  320. package/dist/gaia-security/hooks/modules/context/agentic_loop_detector.py +165 -0
  321. package/dist/gaia-security/hooks/modules/context/anchor_tracker.py +317 -0
  322. package/dist/gaia-security/hooks/modules/context/compact_context_builder.py +218 -0
  323. package/dist/gaia-security/hooks/modules/context/context_freshness.py +145 -0
  324. package/dist/gaia-security/hooks/modules/context/context_injector.py +558 -0
  325. package/dist/gaia-security/hooks/modules/context/context_writer.py +530 -0
  326. package/dist/gaia-security/hooks/modules/context/contracts_loader.py +161 -0
  327. package/dist/gaia-security/hooks/modules/core/__init__.py +40 -0
  328. package/dist/gaia-security/hooks/modules/core/hook_entry.py +78 -0
  329. package/dist/gaia-security/hooks/modules/core/paths.py +160 -0
  330. package/dist/gaia-security/hooks/modules/core/plugin_mode.py +149 -0
  331. package/dist/gaia-security/hooks/modules/core/plugin_setup.py +577 -0
  332. package/dist/gaia-security/hooks/modules/core/state.py +179 -0
  333. package/dist/gaia-security/hooks/modules/core/stdin.py +24 -0
  334. package/dist/gaia-security/hooks/modules/events/__init__.py +1 -0
  335. package/dist/gaia-security/hooks/modules/events/event_writer.py +210 -0
  336. package/dist/gaia-security/hooks/modules/memory/__init__.py +8 -0
  337. package/dist/gaia-security/hooks/modules/memory/episode_writer.py +216 -0
  338. package/dist/gaia-security/hooks/modules/orchestrator/__init__.py +1 -0
  339. package/dist/gaia-security/hooks/modules/orchestrator/delegate_mode.py +122 -0
  340. package/dist/gaia-security/hooks/modules/scanning/__init__.py +8 -0
  341. package/dist/gaia-security/hooks/modules/scanning/scan_trigger.py +84 -0
  342. package/dist/gaia-security/hooks/modules/security/__init__.py +120 -0
  343. package/dist/gaia-security/hooks/modules/security/approval_cleanup.py +87 -0
  344. package/dist/gaia-security/hooks/modules/security/approval_constants.py +23 -0
  345. package/dist/gaia-security/hooks/modules/security/approval_grants.py +1638 -0
  346. package/dist/gaia-security/hooks/modules/security/approval_messages.py +71 -0
  347. package/dist/gaia-security/hooks/modules/security/approval_scopes.py +222 -0
  348. package/dist/gaia-security/hooks/modules/security/blocked_commands.py +595 -0
  349. package/dist/gaia-security/hooks/modules/security/blocked_message_formatter.py +87 -0
  350. package/dist/gaia-security/hooks/modules/security/command_semantics.py +181 -0
  351. package/dist/gaia-security/hooks/modules/security/composition_rules.py +547 -0
  352. package/dist/gaia-security/hooks/modules/security/flag_classifiers.py +873 -0
  353. package/dist/gaia-security/hooks/modules/security/gitops_validator.py +179 -0
  354. package/dist/gaia-security/hooks/modules/security/mutative_verbs.py +1131 -0
  355. package/dist/gaia-security/hooks/modules/security/network_hosts.py +481 -0
  356. package/dist/gaia-security/hooks/modules/security/prompt_validator.py +40 -0
  357. package/dist/gaia-security/hooks/modules/security/shell_unwrapper.py +165 -0
  358. package/dist/gaia-security/hooks/modules/security/tiers.py +196 -0
  359. package/dist/gaia-security/hooks/modules/session/__init__.py +10 -0
  360. package/dist/gaia-security/hooks/modules/session/pending_scanner.py +174 -0
  361. package/dist/gaia-security/hooks/modules/session/session_context_writer.py +100 -0
  362. package/dist/gaia-security/hooks/modules/session/session_event_injector.py +160 -0
  363. package/dist/gaia-security/hooks/modules/session/session_manager.py +31 -0
  364. package/dist/gaia-security/hooks/modules/session/session_registry.py +232 -0
  365. package/dist/gaia-security/hooks/modules/tools/__init__.py +29 -0
  366. package/dist/gaia-security/hooks/modules/tools/bash_validator.py +1008 -0
  367. package/dist/gaia-security/hooks/modules/tools/cloud_pipe_validator.py +231 -0
  368. package/dist/gaia-security/hooks/modules/tools/hook_response.py +55 -0
  369. package/dist/gaia-security/hooks/modules/tools/shell_parser.py +227 -0
  370. package/dist/gaia-security/hooks/modules/tools/stage_decomposer.py +315 -0
  371. package/dist/gaia-security/hooks/modules/tools/task_validator.py +294 -0
  372. package/dist/gaia-security/hooks/modules/validation/__init__.py +23 -0
  373. package/dist/gaia-security/hooks/modules/validation/commit_validator.py +380 -0
  374. package/dist/gaia-security/hooks/post_tool_use.py +54 -0
  375. package/dist/gaia-security/hooks/pre_tool_use.py +413 -0
  376. package/dist/gaia-security/hooks/session_start.py +81 -0
  377. package/dist/gaia-security/hooks/stop_hook.py +82 -0
  378. package/dist/gaia-security/hooks/user_prompt_submit.py +246 -0
  379. package/dist/gaia-security/settings.json +58 -0
  380. package/git-hooks/commit-msg +41 -0
  381. package/hooks/README.md +100 -0
  382. package/hooks/adapters/__init__.py +52 -0
  383. package/hooks/adapters/base.py +219 -0
  384. package/hooks/adapters/channel.py +17 -0
  385. package/hooks/adapters/claude_code.py +1890 -0
  386. package/hooks/adapters/types.py +194 -0
  387. package/hooks/adapters/utils.py +25 -0
  388. package/hooks/elicitation_result.py +179 -0
  389. package/hooks/hooks.json +84 -0
  390. package/hooks/modules/README.md +189 -0
  391. package/hooks/modules/__init__.py +15 -0
  392. package/hooks/modules/agents/__init__.py +29 -0
  393. package/hooks/modules/agents/contract_validator.py +647 -0
  394. package/hooks/modules/agents/response_contract.py +496 -0
  395. package/hooks/modules/agents/skill_injection_verifier.py +120 -0
  396. package/hooks/modules/agents/state_tracker.py +267 -0
  397. package/hooks/modules/agents/task_info_builder.py +74 -0
  398. package/hooks/modules/agents/transcript_analyzer.py +458 -0
  399. package/hooks/modules/agents/transcript_reader.py +152 -0
  400. package/hooks/modules/audit/__init__.py +28 -0
  401. package/hooks/modules/audit/event_detector.py +168 -0
  402. package/hooks/modules/audit/logger.py +131 -0
  403. package/hooks/modules/audit/metrics.py +134 -0
  404. package/hooks/modules/audit/workflow_auditor.py +611 -0
  405. package/hooks/modules/audit/workflow_recorder.py +296 -0
  406. package/hooks/modules/context/__init__.py +11 -0
  407. package/hooks/modules/context/agentic_loop_detector.py +165 -0
  408. package/hooks/modules/context/anchor_tracker.py +317 -0
  409. package/hooks/modules/context/compact_context_builder.py +218 -0
  410. package/hooks/modules/context/context_freshness.py +145 -0
  411. package/hooks/modules/context/context_injector.py +558 -0
  412. package/hooks/modules/context/context_writer.py +530 -0
  413. package/hooks/modules/context/contracts_loader.py +161 -0
  414. package/hooks/modules/core/__init__.py +40 -0
  415. package/hooks/modules/core/hook_entry.py +78 -0
  416. package/hooks/modules/core/paths.py +160 -0
  417. package/hooks/modules/core/plugin_mode.py +149 -0
  418. package/hooks/modules/core/plugin_setup.py +577 -0
  419. package/hooks/modules/core/state.py +179 -0
  420. package/hooks/modules/core/stdin.py +24 -0
  421. package/hooks/modules/events/__init__.py +1 -0
  422. package/hooks/modules/events/event_writer.py +210 -0
  423. package/hooks/modules/evidence/__init__.py +34 -0
  424. package/hooks/modules/evidence/assertions.py +137 -0
  425. package/hooks/modules/evidence/index_writer.py +57 -0
  426. package/hooks/modules/evidence/loader.py +126 -0
  427. package/hooks/modules/evidence/runner.py +241 -0
  428. package/hooks/modules/memory/__init__.py +8 -0
  429. package/hooks/modules/memory/episode_writer.py +216 -0
  430. package/hooks/modules/orchestrator/__init__.py +1 -0
  431. package/hooks/modules/orchestrator/delegate_mode.py +122 -0
  432. package/hooks/modules/scanning/__init__.py +8 -0
  433. package/hooks/modules/scanning/scan_trigger.py +84 -0
  434. package/hooks/modules/security/__init__.py +120 -0
  435. package/hooks/modules/security/approval_cleanup.py +87 -0
  436. package/hooks/modules/security/approval_constants.py +23 -0
  437. package/hooks/modules/security/approval_grants.py +1638 -0
  438. package/hooks/modules/security/approval_messages.py +71 -0
  439. package/hooks/modules/security/approval_scopes.py +222 -0
  440. package/hooks/modules/security/blocked_commands.py +595 -0
  441. package/hooks/modules/security/blocked_message_formatter.py +87 -0
  442. package/hooks/modules/security/command_semantics.py +181 -0
  443. package/hooks/modules/security/composition_rules.py +547 -0
  444. package/hooks/modules/security/flag_classifiers.py +873 -0
  445. package/hooks/modules/security/gitops_validator.py +179 -0
  446. package/hooks/modules/security/mutative_verbs.py +1131 -0
  447. package/hooks/modules/security/network_hosts.py +481 -0
  448. package/hooks/modules/security/prompt_validator.py +40 -0
  449. package/hooks/modules/security/shell_unwrapper.py +165 -0
  450. package/hooks/modules/security/tiers.py +196 -0
  451. package/hooks/modules/session/__init__.py +10 -0
  452. package/hooks/modules/session/pending_scanner.py +174 -0
  453. package/hooks/modules/session/session_context_writer.py +100 -0
  454. package/hooks/modules/session/session_event_injector.py +160 -0
  455. package/hooks/modules/session/session_manager.py +31 -0
  456. package/hooks/modules/session/session_registry.py +232 -0
  457. package/hooks/modules/tools/__init__.py +29 -0
  458. package/hooks/modules/tools/bash_validator.py +1008 -0
  459. package/hooks/modules/tools/cloud_pipe_validator.py +231 -0
  460. package/hooks/modules/tools/hook_response.py +55 -0
  461. package/hooks/modules/tools/shell_parser.py +227 -0
  462. package/hooks/modules/tools/stage_decomposer.py +315 -0
  463. package/hooks/modules/tools/task_validator.py +294 -0
  464. package/hooks/modules/validation/__init__.py +23 -0
  465. package/hooks/modules/validation/commit_validator.py +380 -0
  466. package/hooks/post_compact.py +43 -0
  467. package/hooks/post_tool_use.py +54 -0
  468. package/hooks/pre_compact.py +60 -0
  469. package/hooks/pre_tool_use.py +413 -0
  470. package/hooks/session_start.py +81 -0
  471. package/hooks/stop_hook.py +82 -0
  472. package/hooks/subagent_start.py +71 -0
  473. package/hooks/subagent_stop.py +295 -0
  474. package/hooks/task_completed.py +70 -0
  475. package/hooks/user_prompt_submit.py +246 -0
  476. package/index.js +83 -0
  477. package/package.json +99 -0
  478. package/pyproject.toml +32 -0
  479. package/skills/README.md +154 -0
  480. package/skills/agent-protocol/SKILL.md +93 -0
  481. package/skills/agent-protocol/examples.md +223 -0
  482. package/skills/agent-response/SKILL.md +69 -0
  483. package/skills/agentic-loop/SKILL.md +80 -0
  484. package/skills/agentic-loop/reference.md +378 -0
  485. package/skills/blog-writing/SKILL.md +98 -0
  486. package/skills/blog-writing/reference.md +130 -0
  487. package/skills/brief-spec/SKILL.md +182 -0
  488. package/skills/command-execution/SKILL.md +64 -0
  489. package/skills/command-execution/reference.md +83 -0
  490. package/skills/context-updater/SKILL.md +87 -0
  491. package/skills/context-updater/examples.md +71 -0
  492. package/skills/developer-patterns/SKILL.md +50 -0
  493. package/skills/developer-patterns/reference.md +112 -0
  494. package/skills/execution/SKILL.md +99 -0
  495. package/skills/fast-queries/SKILL.md +43 -0
  496. package/skills/gaia-compact/SKILL.md +74 -0
  497. package/skills/gaia-patterns/SKILL.md +108 -0
  498. package/skills/gaia-patterns/reference.md +395 -0
  499. package/skills/gaia-planner/SKILL.md +37 -0
  500. package/skills/gaia-planner/reference.md +107 -0
  501. package/skills/gaia-release/SKILL.md +82 -0
  502. package/skills/gaia-release/reference.md +102 -0
  503. package/skills/gaia-self-check/SKILL.md +114 -0
  504. package/skills/gaia-self-check/reference.md +453 -0
  505. package/skills/gaia-verify/SKILL.md +77 -0
  506. package/skills/gaia-verify/reference.md +80 -0
  507. package/skills/git-conventions/SKILL.md +47 -0
  508. package/skills/gitops-patterns/SKILL.md +60 -0
  509. package/skills/gitops-patterns/reference.md +183 -0
  510. package/skills/gmail-policy/SKILL.md +200 -0
  511. package/skills/gmail-policy/reference.md +150 -0
  512. package/skills/gmail-triage/SKILL.md +100 -0
  513. package/skills/gws-setup/SKILL.md +99 -0
  514. package/skills/gws-setup/reference.md +73 -0
  515. package/skills/investigation/SKILL.md +100 -0
  516. package/skills/memory-curation/SKILL.md +83 -0
  517. package/skills/memory-search/SKILL.md +88 -0
  518. package/skills/orchestrator-approval/SKILL.md +160 -0
  519. package/skills/orchestrator-approval/reference.md +174 -0
  520. package/skills/pending-approvals/SKILL.md +72 -0
  521. package/skills/pending-approvals/reference.md +214 -0
  522. package/skills/readme-writing/SKILL.md +71 -0
  523. package/skills/readme-writing/reference.md +188 -0
  524. package/skills/reference.md +135 -0
  525. package/skills/request-approval/SKILL.md +140 -0
  526. package/skills/request-approval/examples.md +140 -0
  527. package/skills/request-approval/reference.md +57 -0
  528. package/skills/schedule-task/SKILL.md +64 -0
  529. package/skills/schedule-task/reference.md +233 -0
  530. package/skills/security-tiers/SKILL.md +141 -0
  531. package/skills/security-tiers/destructive-commands-reference.md +623 -0
  532. package/skills/security-tiers/reference.md +39 -0
  533. package/skills/skill-creation/SKILL.md +92 -0
  534. package/skills/skill-creation/reference.md +29 -0
  535. package/skills/terraform-patterns/SKILL.md +89 -0
  536. package/skills/terraform-patterns/reference.md +93 -0
  537. package/templates/README.md +69 -0
  538. package/templates/managed-settings.template.json +43 -0
  539. package/tools/__init__.py +9 -0
  540. package/tools/agentic-loop/decide-status.py +210 -0
  541. package/tools/agentic-loop/parse-metric.py +106 -0
  542. package/tools/agentic-loop/record-iteration.py +221 -0
  543. package/tools/context/README.md +132 -0
  544. package/tools/context/__init__.py +42 -0
  545. package/tools/context/_paths.py +20 -0
  546. package/tools/context/context_provider.py +721 -0
  547. package/tools/context/context_section_reader.py +342 -0
  548. package/tools/context/deep_merge.py +159 -0
  549. package/tools/context/pending_updates.py +760 -0
  550. package/tools/context/surface_router.py +278 -0
  551. package/tools/fast-queries/README.md +65 -0
  552. package/tools/fast-queries/__init__.py +30 -0
  553. package/tools/fast-queries/appservices/quicktriage_devops_developer.sh +75 -0
  554. package/tools/fast-queries/cloud/aws/quicktriage_aws_troubleshooter.sh +32 -0
  555. package/tools/fast-queries/cloud/gcp/quicktriage_gcp_troubleshooter.sh +88 -0
  556. package/tools/fast-queries/gitops/quicktriage_gitops_operator.sh +48 -0
  557. package/tools/fast-queries/run_triage.sh +59 -0
  558. package/tools/fast-queries/terraform/quicktriage_terraform_architect.sh +80 -0
  559. package/tools/gaia_simulator/__init__.py +33 -0
  560. package/tools/gaia_simulator/cli.py +354 -0
  561. package/tools/gaia_simulator/extractor.py +457 -0
  562. package/tools/gaia_simulator/reporter.py +258 -0
  563. package/tools/gaia_simulator/routing_simulator.py +334 -0
  564. package/tools/gaia_simulator/runner.py +539 -0
  565. package/tools/gaia_simulator/skills_mapper.py +264 -0
  566. package/tools/memory/README.md +0 -0
  567. package/tools/memory/__init__.py +20 -0
  568. package/tools/memory/backfill_fts5.py +107 -0
  569. package/tools/memory/conflict_detector.py +295 -0
  570. package/tools/memory/episodic.py +1210 -0
  571. package/tools/memory/git_invalidator.py +262 -0
  572. package/tools/memory/paths.py +102 -0
  573. package/tools/memory/scoring.py +193 -0
  574. package/tools/memory/search_store.py +360 -0
  575. package/tools/persist_transcript_analysis.py +85 -0
  576. package/tools/review/__init__.py +1 -0
  577. package/tools/review/review_engine.py +157 -0
  578. package/tools/scan/__init__.py +35 -0
  579. package/tools/scan/config.py +247 -0
  580. package/tools/scan/merge.py +212 -0
  581. package/tools/scan/orchestrator.py +549 -0
  582. package/tools/scan/registry.py +127 -0
  583. package/tools/scan/scanners/__init__.py +18 -0
  584. package/tools/scan/scanners/base.py +137 -0
  585. package/tools/scan/scanners/environment.py +349 -0
  586. package/tools/scan/scanners/git.py +570 -0
  587. package/tools/scan/scanners/infrastructure.py +875 -0
  588. package/tools/scan/scanners/orchestration.py +600 -0
  589. package/tools/scan/scanners/stack.py +1085 -0
  590. package/tools/scan/scanners/tools.py +260 -0
  591. package/tools/scan/setup.py +686 -0
  592. package/tools/scan/tests/__init__.py +1 -0
  593. package/tools/scan/tests/conftest.py +796 -0
  594. package/tools/scan/tests/test_environment.py +323 -0
  595. package/tools/scan/tests/test_git.py +419 -0
  596. package/tools/scan/tests/test_infrastructure.py +382 -0
  597. package/tools/scan/tests/test_integration.py +920 -0
  598. package/tools/scan/tests/test_merge.py +269 -0
  599. package/tools/scan/tests/test_orchestration.py +304 -0
  600. package/tools/scan/tests/test_stack.py +604 -0
  601. package/tools/scan/tests/test_tools.py +349 -0
  602. package/tools/scan/ui.py +624 -0
  603. package/tools/scan/verify.py +270 -0
  604. package/tools/scan/walk.py +118 -0
  605. package/tools/scan/workspace.py +85 -0
  606. package/tools/validation/README.md +244 -0
  607. package/tools/validation/__init__.py +17 -0
  608. package/tools/validation/approval_gate.py +321 -0
  609. package/tools/validation/validate_skills.py +189 -0
@@ -0,0 +1,796 @@
1
+ """
2
+ Shared test fixtures for scan module tests.
3
+
4
+ Provides mock project trees, temporary directories, and common
5
+ test data for scanner unit tests.
6
+ """
7
+
8
+ import json
9
+ import textwrap
10
+ from pathlib import Path
11
+ from typing import Any, Dict
12
+
13
+ import pytest
14
+
15
+
16
+ # ---------------------------------------------------------------------------
17
+ # Basic project fixtures
18
+ # ---------------------------------------------------------------------------
19
+
20
+
21
+ @pytest.fixture
22
+ def tmp_project(tmp_path: Path) -> Path:
23
+ """Create a minimal temporary project directory."""
24
+ return tmp_path
25
+
26
+
27
+ @pytest.fixture
28
+ def empty_project(tmp_path: Path) -> Path:
29
+ """Create an empty temporary project directory."""
30
+ return tmp_path
31
+
32
+
33
+ @pytest.fixture
34
+ def minimal_project(tmp_path: Path) -> Path:
35
+ """Create a minimal project with just a README.md."""
36
+ (tmp_path / "README.md").write_text("# Test Project\n")
37
+ return tmp_path
38
+
39
+
40
+ # ---------------------------------------------------------------------------
41
+ # Language-specific project fixtures
42
+ # ---------------------------------------------------------------------------
43
+
44
+
45
+ @pytest.fixture
46
+ def node_project(tmp_path: Path) -> Path:
47
+ """Create a Node.js project with express + react deps and CI.
48
+
49
+ Includes: package.json (express, react), package-lock.json,
50
+ .github/workflows/ci.yml
51
+ """
52
+ package_json = {
53
+ "name": "test-node-project",
54
+ "version": "1.0.0",
55
+ "description": "A test Node.js project",
56
+ "dependencies": {
57
+ "express": "^4.18.0",
58
+ "react": "^18.2.0",
59
+ },
60
+ "devDependencies": {
61
+ "@nestjs/core": "^10.0.0",
62
+ },
63
+ }
64
+ (tmp_path / "package.json").write_text(json.dumps(package_json, indent=2))
65
+ (tmp_path / "package-lock.json").write_text("{}")
66
+
67
+ # GitHub Actions CI
68
+ workflows_dir = tmp_path / ".github" / "workflows"
69
+ workflows_dir.mkdir(parents=True)
70
+ (workflows_dir / "ci.yml").write_text(
71
+ "name: CI\non: [push]\njobs:\n test:\n runs-on: ubuntu-latest\n"
72
+ )
73
+ return tmp_path
74
+
75
+
76
+ @pytest.fixture
77
+ def python_project(tmp_path: Path) -> Path:
78
+ """Create a Python project with fastapi dep and requirements.txt.
79
+
80
+ Includes: pyproject.toml (fastapi), requirements.txt
81
+ """
82
+ pyproject = textwrap.dedent("""\
83
+ [project]
84
+ name = "test-python-project"
85
+ version = "1.0.0"
86
+ description = "A test Python project"
87
+ dependencies = [
88
+ "fastapi>=0.100.0",
89
+ ]
90
+ """)
91
+ (tmp_path / "pyproject.toml").write_text(pyproject)
92
+ (tmp_path / "requirements.txt").write_text("fastapi>=0.100.0\nuvicorn>=0.23.0\n")
93
+ return tmp_path
94
+
95
+
96
+ @pytest.fixture
97
+ def go_project(tmp_path: Path) -> Path:
98
+ """Create a Go project with go.mod and go.sum.
99
+
100
+ Includes: go.mod with module path, go.sum
101
+ """
102
+ go_mod = textwrap.dedent("""\
103
+ module github.com/example/test-go-project
104
+
105
+ go 1.21
106
+
107
+ require github.com/gin-gonic/gin v1.9.1
108
+ """)
109
+ (tmp_path / "go.mod").write_text(go_mod)
110
+ (tmp_path / "go.sum").write_text("github.com/gin-gonic/gin v1.9.1 h1:abc=\n")
111
+ return tmp_path
112
+
113
+
114
+ @pytest.fixture
115
+ def rust_project(tmp_path: Path) -> Path:
116
+ """Create a Rust project with Cargo.toml and Cargo.lock.
117
+
118
+ Includes: Cargo.toml, Cargo.lock
119
+ """
120
+ cargo_toml = textwrap.dedent("""\
121
+ [package]
122
+ name = "test-rust-project"
123
+ version = "0.1.0"
124
+ description = "A test Rust project"
125
+ edition = "2021"
126
+
127
+ [dependencies]
128
+ serde = "1.0"
129
+ """)
130
+ (tmp_path / "Cargo.toml").write_text(cargo_toml)
131
+ (tmp_path / "Cargo.lock").write_text("# This file is automatically generated\n")
132
+ return tmp_path
133
+
134
+
135
+ @pytest.fixture
136
+ def java_maven_project(tmp_path: Path) -> Path:
137
+ """Create a Java project with pom.xml."""
138
+ pom_xml = textwrap.dedent("""\
139
+ <?xml version="1.0" encoding="UTF-8"?>
140
+ <project>
141
+ <modelVersion>4.0.0</modelVersion>
142
+ <groupId>com.example</groupId>
143
+ <artifactId>test-java-project</artifactId>
144
+ <version>1.0.0</version>
145
+ </project>
146
+ """)
147
+ (tmp_path / "pom.xml").write_text(pom_xml)
148
+ return tmp_path
149
+
150
+
151
+ @pytest.fixture
152
+ def java_gradle_project(tmp_path: Path) -> Path:
153
+ """Create a Java project with build.gradle."""
154
+ (tmp_path / "build.gradle").write_text(
155
+ "plugins { id 'java' }\nversion = '1.0.0'\n"
156
+ )
157
+ return tmp_path
158
+
159
+
160
+ @pytest.fixture
161
+ def php_project(tmp_path: Path) -> Path:
162
+ """Create a PHP project with composer.json."""
163
+ composer_json = {
164
+ "name": "example/test-php-project",
165
+ "description": "A test PHP project",
166
+ "require": {"php": "^8.1"},
167
+ }
168
+ (tmp_path / "composer.json").write_text(json.dumps(composer_json, indent=2))
169
+ return tmp_path
170
+
171
+
172
+ @pytest.fixture
173
+ def ruby_project(tmp_path: Path) -> Path:
174
+ """Create a Ruby project with Gemfile."""
175
+ (tmp_path / "Gemfile").write_text(
176
+ 'source "https://rubygems.org"\ngem "rails", "~> 7.0"\n'
177
+ )
178
+ return tmp_path
179
+
180
+
181
+ @pytest.fixture
182
+ def csharp_project(tmp_path: Path) -> Path:
183
+ """Create a C#/.NET project with .csproj."""
184
+ (tmp_path / "TestProject.csproj").write_text(
185
+ '<Project Sdk="Microsoft.NET.Sdk">\n'
186
+ " <PropertyGroup>\n"
187
+ " <TargetFramework>net8.0</TargetFramework>\n"
188
+ " </PropertyGroup>\n"
189
+ "</Project>\n"
190
+ )
191
+ return tmp_path
192
+
193
+
194
+ # ---------------------------------------------------------------------------
195
+ # Monorepo fixture
196
+ # ---------------------------------------------------------------------------
197
+
198
+
199
+ @pytest.fixture
200
+ def monorepo_project(tmp_path: Path) -> Path:
201
+ """Create a monorepo with React frontend and FastAPI backend.
202
+
203
+ Includes: turbo.json, apps/frontend/package.json (React),
204
+ apps/backend/pyproject.toml (FastAPI)
205
+ """
206
+ # Turbo config
207
+ (tmp_path / "turbo.json").write_text(json.dumps({"pipeline": {}}, indent=2))
208
+
209
+ # Root package.json with workspaces
210
+ root_pkg = {
211
+ "name": "test-monorepo",
212
+ "private": True,
213
+ "workspaces": ["apps/*"],
214
+ }
215
+ (tmp_path / "package.json").write_text(json.dumps(root_pkg, indent=2))
216
+
217
+ # Frontend (React)
218
+ frontend_dir = tmp_path / "apps" / "frontend"
219
+ frontend_dir.mkdir(parents=True)
220
+ frontend_pkg = {
221
+ "name": "@monorepo/frontend",
222
+ "version": "1.0.0",
223
+ "dependencies": {"react": "^18.2.0", "next": "^14.0.0"},
224
+ }
225
+ (frontend_dir / "package.json").write_text(json.dumps(frontend_pkg, indent=2))
226
+
227
+ # Backend (FastAPI)
228
+ backend_dir = tmp_path / "apps" / "backend"
229
+ backend_dir.mkdir(parents=True)
230
+ pyproject = textwrap.dedent("""\
231
+ [project]
232
+ name = "monorepo-backend"
233
+ version = "1.0.0"
234
+ dependencies = [
235
+ "fastapi>=0.100.0",
236
+ ]
237
+ """)
238
+ (backend_dir / "pyproject.toml").write_text(pyproject)
239
+
240
+ return tmp_path
241
+
242
+
243
+ # ---------------------------------------------------------------------------
244
+ # Full DevOps project fixture
245
+ # ---------------------------------------------------------------------------
246
+
247
+
248
+ @pytest.fixture
249
+ def devops_project(tmp_path: Path) -> Path:
250
+ """Create a full DevOps project with infrastructure, GitOps, and CI.
251
+
252
+ Includes: package.json, Dockerfile, terraform/main.tf (GCP provider),
253
+ gitops/clusters/dev/kustomization.yaml (Flux), .github/workflows/ci.yml
254
+ """
255
+ # Application
256
+ pkg = {
257
+ "name": "devops-app",
258
+ "version": "1.0.0",
259
+ "dependencies": {"express": "^4.18.0"},
260
+ }
261
+ (tmp_path / "package.json").write_text(json.dumps(pkg, indent=2))
262
+ (tmp_path / "package-lock.json").write_text("{}")
263
+
264
+ # Dockerfile
265
+ (tmp_path / "Dockerfile").write_text("FROM node:20-alpine\nWORKDIR /app\n")
266
+
267
+ # Terraform with GCP provider
268
+ tf_dir = tmp_path / "terraform"
269
+ tf_dir.mkdir()
270
+ (tf_dir / "main.tf").write_text(
271
+ textwrap.dedent("""\
272
+ provider "google" {
273
+ project = "my-gcp-project"
274
+ region = "us-central1"
275
+ }
276
+
277
+ resource "google_compute_instance" "default" {
278
+ name = "test"
279
+ machine_type = "e2-medium"
280
+ }
281
+ """)
282
+ )
283
+
284
+ # GitOps with Flux (kustomization.yaml with toolkit.fluxcd.io)
285
+ gitops_dir = tmp_path / "gitops" / "clusters" / "dev"
286
+ gitops_dir.mkdir(parents=True)
287
+ (gitops_dir / "kustomization.yaml").write_text(
288
+ textwrap.dedent("""\
289
+ apiVersion: kustomize.toolkit.fluxcd.io/v1
290
+ kind: Kustomization
291
+ metadata:
292
+ name: dev-cluster
293
+ namespace: flux-system
294
+ spec:
295
+ interval: 5m
296
+ path: ./gitops/clusters/dev
297
+ prune: true
298
+ """)
299
+ )
300
+
301
+ # GitHub Actions CI
302
+ workflows_dir = tmp_path / ".github" / "workflows"
303
+ workflows_dir.mkdir(parents=True)
304
+ (workflows_dir / "ci.yml").write_text(
305
+ "name: CI\non: [push]\njobs:\n test:\n runs-on: ubuntu-latest\n"
306
+ )
307
+
308
+ return tmp_path
309
+
310
+
311
+ # ---------------------------------------------------------------------------
312
+ # Git directory fixtures
313
+ # ---------------------------------------------------------------------------
314
+
315
+
316
+ @pytest.fixture
317
+ def git_project_github(tmp_path: Path) -> Path:
318
+ """Create a project with .git directory configured for GitHub.
319
+
320
+ Sets up .git/config with origin remote pointing to github.com,
321
+ .git/HEAD pointing to main, and branch refs.
322
+ """
323
+ git_dir = tmp_path / ".git"
324
+ git_dir.mkdir()
325
+
326
+ # Git config with origin remote
327
+ config_content = textwrap.dedent("""\
328
+ [core]
329
+ repositoryformatversion = 0
330
+ filemode = true
331
+ [remote "origin"]
332
+ url = git@github.com:example/test-project.git
333
+ fetch = +refs/heads/*:refs/remotes/origin/*
334
+ [remote "upstream"]
335
+ url = https://github.com/upstream/test-project.git
336
+ fetch = +refs/heads/*:refs/remotes/upstream/*
337
+ [branch "main"]
338
+ remote = origin
339
+ merge = refs/heads/main
340
+ """)
341
+ (git_dir / "config").write_text(config_content)
342
+
343
+ # HEAD points to main
344
+ (git_dir / "HEAD").write_text("ref: refs/heads/main\n")
345
+
346
+ # Branch refs
347
+ refs_heads = git_dir / "refs" / "heads"
348
+ refs_heads.mkdir(parents=True)
349
+ (refs_heads / "main").write_text("abc123\n")
350
+
351
+ refs_remotes_origin = git_dir / "refs" / "remotes" / "origin"
352
+ refs_remotes_origin.mkdir(parents=True)
353
+ (refs_remotes_origin / "main").write_text("abc123\n")
354
+
355
+ return tmp_path
356
+
357
+
358
+ @pytest.fixture
359
+ def git_project_gitlab(tmp_path: Path) -> Path:
360
+ """Create a project with .git directory configured for GitLab."""
361
+ git_dir = tmp_path / ".git"
362
+ git_dir.mkdir()
363
+
364
+ config_content = textwrap.dedent("""\
365
+ [remote "origin"]
366
+ url = git@gitlab.com:group/project.git
367
+ fetch = +refs/heads/*:refs/remotes/origin/*
368
+ """)
369
+ (git_dir / "config").write_text(config_content)
370
+ (git_dir / "HEAD").write_text("ref: refs/heads/main\n")
371
+
372
+ refs_heads = git_dir / "refs" / "heads"
373
+ refs_heads.mkdir(parents=True)
374
+ (refs_heads / "main").write_text("abc123\n")
375
+
376
+ return tmp_path
377
+
378
+
379
+ @pytest.fixture
380
+ def git_project_bitbucket(tmp_path: Path) -> Path:
381
+ """Create a project with .git directory configured for Bitbucket."""
382
+ git_dir = tmp_path / ".git"
383
+ git_dir.mkdir()
384
+
385
+ config_content = textwrap.dedent("""\
386
+ [remote "origin"]
387
+ url = git@bitbucket.org:team/project.git
388
+ fetch = +refs/heads/*:refs/remotes/origin/*
389
+ """)
390
+ (git_dir / "config").write_text(config_content)
391
+ (git_dir / "HEAD").write_text("ref: refs/heads/master\n")
392
+
393
+ refs_heads = git_dir / "refs" / "heads"
394
+ refs_heads.mkdir(parents=True)
395
+ (refs_heads / "master").write_text("abc123\n")
396
+
397
+ return tmp_path
398
+
399
+
400
+ @pytest.fixture
401
+ def git_project_selfhosted(tmp_path: Path) -> Path:
402
+ """Create a project with .git directory configured for self-hosted Git."""
403
+ git_dir = tmp_path / ".git"
404
+ git_dir.mkdir()
405
+
406
+ config_content = textwrap.dedent("""\
407
+ [remote "origin"]
408
+ url = git@git.internal.company.com:team/project.git
409
+ fetch = +refs/heads/*:refs/remotes/origin/*
410
+ """)
411
+ (git_dir / "config").write_text(config_content)
412
+ (git_dir / "HEAD").write_text("ref: refs/heads/main\n")
413
+
414
+ refs_heads = git_dir / "refs" / "heads"
415
+ refs_heads.mkdir(parents=True)
416
+ (refs_heads / "main").write_text("abc123\n")
417
+
418
+ return tmp_path
419
+
420
+
421
+ @pytest.fixture
422
+ def git_project_gitflow(tmp_path: Path) -> Path:
423
+ """Create a project with gitflow branch strategy.
424
+
425
+ Has: main, develop, feature/xyz, release/1.0
426
+ """
427
+ git_dir = tmp_path / ".git"
428
+ git_dir.mkdir()
429
+
430
+ config_content = textwrap.dedent("""\
431
+ [remote "origin"]
432
+ url = git@github.com:example/gitflow-project.git
433
+ fetch = +refs/heads/*:refs/remotes/origin/*
434
+ """)
435
+ (git_dir / "config").write_text(config_content)
436
+ (git_dir / "HEAD").write_text("ref: refs/heads/develop\n")
437
+
438
+ refs_heads = git_dir / "refs" / "heads"
439
+ refs_heads.mkdir(parents=True)
440
+ (refs_heads / "main").write_text("abc123\n")
441
+ (refs_heads / "develop").write_text("def456\n")
442
+
443
+ feature_dir = refs_heads / "feature"
444
+ feature_dir.mkdir()
445
+ (feature_dir / "xyz").write_text("ghi789\n")
446
+
447
+ release_dir = refs_heads / "release"
448
+ release_dir.mkdir()
449
+ (release_dir / "1.0").write_text("jkl012\n")
450
+
451
+ return tmp_path
452
+
453
+
454
+ # ---------------------------------------------------------------------------
455
+ # Infrastructure-specific fixtures
456
+ # ---------------------------------------------------------------------------
457
+
458
+
459
+ @pytest.fixture
460
+ def terraform_gcp_project(tmp_path: Path) -> Path:
461
+ """Create a project with Terraform GCP provider."""
462
+ (tmp_path / "main.tf").write_text(
463
+ 'provider "google" {\n project = "my-project"\n region = "us-central1"\n}\n'
464
+ )
465
+ return tmp_path
466
+
467
+
468
+ @pytest.fixture
469
+ def terraform_aws_project(tmp_path: Path) -> Path:
470
+ """Create a project with Terraform AWS provider."""
471
+ (tmp_path / "main.tf").write_text(
472
+ 'provider "aws" {\n region = "us-east-1"\n}\n'
473
+ )
474
+ return tmp_path
475
+
476
+
477
+ @pytest.fixture
478
+ def terraform_azure_project(tmp_path: Path) -> Path:
479
+ """Create a project with Terraform Azure provider."""
480
+ (tmp_path / "main.tf").write_text(
481
+ 'provider "azurerm" {\n features {}\n}\n'
482
+ )
483
+ return tmp_path
484
+
485
+
486
+ @pytest.fixture
487
+ def terraform_multicloud_project(tmp_path: Path) -> Path:
488
+ """Create a project with multiple cloud providers."""
489
+ (tmp_path / "gcp.tf").write_text('provider "google" {\n project = "my-project"\n}\n')
490
+ (tmp_path / "aws.tf").write_text('provider "aws" {\n region = "us-east-1"\n}\n')
491
+ return tmp_path
492
+
493
+
494
+ # ---------------------------------------------------------------------------
495
+ # Orchestration-specific fixtures
496
+ # ---------------------------------------------------------------------------
497
+
498
+
499
+ @pytest.fixture
500
+ def k8s_project(tmp_path: Path) -> Path:
501
+ """Create a project with Kubernetes manifests."""
502
+ manifests_dir = tmp_path / "k8s"
503
+ manifests_dir.mkdir()
504
+ (manifests_dir / "deployment.yaml").write_text(
505
+ textwrap.dedent("""\
506
+ apiVersion: apps/v1
507
+ kind: Deployment
508
+ metadata:
509
+ name: test-app
510
+ spec:
511
+ replicas: 2
512
+ """)
513
+ )
514
+ (manifests_dir / "service.yaml").write_text(
515
+ textwrap.dedent("""\
516
+ apiVersion: v1
517
+ kind: Service
518
+ metadata:
519
+ name: test-app
520
+ spec:
521
+ type: ClusterIP
522
+ """)
523
+ )
524
+ return tmp_path
525
+
526
+
527
+ @pytest.fixture
528
+ def helm_project(tmp_path: Path) -> Path:
529
+ """Create a project with Helm chart."""
530
+ chart_dir = tmp_path / "charts" / "myapp"
531
+ chart_dir.mkdir(parents=True)
532
+ (chart_dir / "Chart.yaml").write_text(
533
+ "apiVersion: v2\nname: myapp\nversion: 1.0.0\n"
534
+ )
535
+ return tmp_path
536
+
537
+
538
+ @pytest.fixture
539
+ def flux_project(tmp_path: Path) -> Path:
540
+ """Create a project with Flux GitOps configuration."""
541
+ clusters_dir = tmp_path / "clusters" / "production"
542
+ clusters_dir.mkdir(parents=True)
543
+ (clusters_dir / "kustomization.yaml").write_text(
544
+ textwrap.dedent("""\
545
+ apiVersion: kustomize.toolkit.fluxcd.io/v1
546
+ kind: Kustomization
547
+ metadata:
548
+ name: production
549
+ namespace: flux-system
550
+ spec:
551
+ interval: 5m
552
+ path: ./clusters/production
553
+ """)
554
+ )
555
+ infra_dir = tmp_path / "infrastructure"
556
+ infra_dir.mkdir()
557
+ (infra_dir / "sources.yaml").write_text(
558
+ textwrap.dedent("""\
559
+ apiVersion: source.toolkit.fluxcd.io/v1
560
+ kind: GitRepository
561
+ metadata:
562
+ name: flux-system
563
+ """)
564
+ )
565
+ apps_dir = tmp_path / "apps"
566
+ apps_dir.mkdir()
567
+ return tmp_path
568
+
569
+
570
+ @pytest.fixture
571
+ def argocd_project(tmp_path: Path) -> Path:
572
+ """Create a project with ArgoCD configuration."""
573
+ argo_dir = tmp_path / "argocd"
574
+ argo_dir.mkdir()
575
+ (argo_dir / "application.yaml").write_text(
576
+ textwrap.dedent("""\
577
+ apiVersion: argoproj.io/v1alpha1
578
+ kind: Application
579
+ metadata:
580
+ name: my-app
581
+ spec:
582
+ destination:
583
+ server: https://kubernetes.default.svc
584
+ """)
585
+ )
586
+ return tmp_path
587
+
588
+
589
+ @pytest.fixture
590
+ def istio_project(tmp_path: Path) -> Path:
591
+ """Create a project with Istio service mesh annotations."""
592
+ manifests_dir = tmp_path / "k8s"
593
+ manifests_dir.mkdir()
594
+ (manifests_dir / "deployment.yaml").write_text(
595
+ textwrap.dedent("""\
596
+ apiVersion: apps/v1
597
+ kind: Deployment
598
+ metadata:
599
+ name: test-app
600
+ annotations:
601
+ sidecar.istio.io/inject: "true"
602
+ spec:
603
+ replicas: 1
604
+ """)
605
+ )
606
+ return tmp_path
607
+
608
+
609
+ @pytest.fixture
610
+ def linkerd_project(tmp_path: Path) -> Path:
611
+ """Create a project with Linkerd service mesh annotations."""
612
+ manifests_dir = tmp_path / "k8s"
613
+ manifests_dir.mkdir()
614
+ (manifests_dir / "deployment.yaml").write_text(
615
+ textwrap.dedent("""\
616
+ apiVersion: apps/v1
617
+ kind: Deployment
618
+ metadata:
619
+ name: test-app
620
+ annotations:
621
+ linkerd.io/inject: enabled
622
+ spec:
623
+ replicas: 1
624
+ """)
625
+ )
626
+ return tmp_path
627
+
628
+
629
+ # ---------------------------------------------------------------------------
630
+ # Sample project-context.json fixtures
631
+ # ---------------------------------------------------------------------------
632
+
633
+
634
+ @pytest.fixture
635
+ def sample_project_context() -> Dict[str, Any]:
636
+ """Return a minimal project-context.json structure (v2 format)."""
637
+ return {
638
+ "metadata": {
639
+ "version": "2.0",
640
+ "last_updated": "2026-01-01T00:00:00Z",
641
+ "project_name": "test-project",
642
+ "scan_config": {
643
+ "staleness_hours": 24,
644
+ "last_scan": "2026-01-01T00:00:00Z",
645
+ "scanner_version": "0.1.0",
646
+ },
647
+ },
648
+ "sections": {},
649
+ }
650
+
651
+
652
+ @pytest.fixture
653
+ def sample_project_context_v1() -> Dict[str, Any]:
654
+ """Return a v1-style project-context.json (no scan_config, old sections).
655
+
656
+ This represents existing project-context.json files that were created
657
+ before the gaia-scan system, with agent-enriched data.
658
+ """
659
+ return {
660
+ "metadata": {
661
+ "version": "1.0",
662
+ "last_updated": "2025-12-01T00:00:00Z",
663
+ "project_name": "legacy-project",
664
+ },
665
+ "project_details": {
666
+ "cloud_provider": "gcp",
667
+ "project_id": "my-gcp-project",
668
+ "region": "us-central1",
669
+ "project_root": "specs/",
670
+ },
671
+ "application_architecture": {
672
+ "package_name": "legacy-app",
673
+ "runtime_language": "typescript",
674
+ },
675
+ "development_standards": {
676
+ "python_version": "3.11",
677
+ "node_version": "20",
678
+ },
679
+ "operational_guidelines": {
680
+ "deployment_strategy": "blue-green",
681
+ "rollback_procedure": "manual",
682
+ },
683
+ }
684
+
685
+
686
+ @pytest.fixture
687
+ def sample_project_context_with_sections() -> Dict[str, Any]:
688
+ """Return a project-context.json with scanner + agent-enriched sections."""
689
+ return {
690
+ "metadata": {
691
+ "version": "2.0",
692
+ "last_updated": "2026-01-01T00:00:00Z",
693
+ "project_name": "test-project",
694
+ "scan_config": {
695
+ "staleness_hours": 24,
696
+ "last_scan": "2026-01-01T00:00:00Z",
697
+ "scanner_version": "0.1.0",
698
+ },
699
+ },
700
+ "project_identity": {
701
+ "_source": "scanner:stack",
702
+ "name": "test-project",
703
+ "type": "application",
704
+ },
705
+ "stack": {
706
+ "_source": "scanner:stack",
707
+ "languages": [{"name": "typescript", "manifest": "package.json", "primary": True}],
708
+ "frameworks": [{"name": "express", "language": "typescript", "version": "4.18.0"}],
709
+ "build_tools": [{"name": "npm", "detected_by": "lock_file", "lock_file": "package-lock.json"}],
710
+ },
711
+ "git": {
712
+ "_source": "scanner:git",
713
+ "platform": "github",
714
+ "remotes": [{"name": "origin", "url": "git@github.com:example/test.git", "platform": "github"}],
715
+ "default_branch": "main",
716
+ },
717
+ "environment": {
718
+ "_source": "scanner:environment",
719
+ "os": {"platform": "linux", "architecture": "x64", "wsl": True, "wsl_version": "2"},
720
+ "runtimes": [{"name": "python3", "version": "3.11.5", "path": "/usr/bin/python3"}],
721
+ "env_files": [{"name": ".env", "path": ".env"}],
722
+ "tools": [{"name": "git", "path": "/usr/bin/git", "version": "2.40.0", "category": "git"}],
723
+ "tool_preferences": {"file_viewer": "bat"},
724
+ },
725
+ "infrastructure": {
726
+ "_source": "scanner:infrastructure",
727
+ "cloud_providers": [{"name": "gcp", "detected_by": "terraform_provider"}],
728
+ "iac": [{"tool": "terraform", "base_path": "terraform"}],
729
+ },
730
+ "operational_guidelines": {
731
+ "deployment_strategy": "blue-green",
732
+ "rollback_procedure": "manual",
733
+ },
734
+ "my_custom_notes": {
735
+ "author": "user",
736
+ "notes": "This is a user-custom section",
737
+ },
738
+ }
739
+
740
+
741
+ # ---------------------------------------------------------------------------
742
+ # Helpers
743
+ # ---------------------------------------------------------------------------
744
+
745
+
746
+ def create_git_dir(
747
+ root: Path,
748
+ remote_url: str = "git@github.com:example/test.git",
749
+ default_branch: str = "main",
750
+ extra_remotes: Dict[str, str] | None = None,
751
+ branches: list[str] | None = None,
752
+ ) -> Path:
753
+ """Helper to create a realistic .git directory structure.
754
+
755
+ Args:
756
+ root: Project root path.
757
+ remote_url: URL for the origin remote.
758
+ default_branch: Branch name for HEAD.
759
+ extra_remotes: Additional remotes as {name: url} dict.
760
+ branches: List of branch names to create refs for.
761
+
762
+ Returns:
763
+ Path to the .git directory.
764
+ """
765
+ git_dir = root / ".git"
766
+ git_dir.mkdir(exist_ok=True)
767
+
768
+ # Build config
769
+ config_lines = ['[core]\n repositoryformatversion = 0\n filemode = true\n']
770
+ config_lines.append(
771
+ f'[remote "origin"]\n'
772
+ f" url = {remote_url}\n"
773
+ f" fetch = +refs/heads/*:refs/remotes/origin/*\n"
774
+ )
775
+ if extra_remotes:
776
+ for name, url in extra_remotes.items():
777
+ config_lines.append(
778
+ f'[remote "{name}"]\n'
779
+ f" url = {url}\n"
780
+ f" fetch = +refs/heads/*:refs/remotes/{name}/*\n"
781
+ )
782
+
783
+ (git_dir / "config").write_text("".join(config_lines))
784
+ (git_dir / "HEAD").write_text(f"ref: refs/heads/{default_branch}\n")
785
+
786
+ # Create branch refs
787
+ refs_heads = git_dir / "refs" / "heads"
788
+ refs_heads.mkdir(parents=True, exist_ok=True)
789
+
790
+ all_branches = [default_branch] + (branches or [])
791
+ for branch in all_branches:
792
+ branch_path = refs_heads / branch.replace("/", "/")
793
+ branch_path.parent.mkdir(parents=True, exist_ok=True)
794
+ branch_path.write_text("0" * 40 + "\n")
795
+
796
+ return git_dir