brigade-cli 0.9.2__tar.gz → 0.9.3__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 (235) hide show
  1. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/PKG-INFO +1 -1
  2. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/pyproject.toml +1 -1
  3. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/__init__.py +1 -1
  4. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/operator_cmd.py +29 -0
  5. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/scrub.py +32 -3
  6. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/hermes/memory-handoff.harness.json +1 -1
  7. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/hermes/model-lanes.harness.json +1 -1
  8. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/hermes/workspace.harness.json +1 -1
  9. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/memory/chat-memory-sweep.example.json +1 -1
  10. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/memory/memory-care.example.json +1 -1
  11. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/policies/personal.json +1 -1
  12. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/policies/public-content.json +1 -1
  13. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/policies/public-repo.json +1 -1
  14. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade_cli.egg-info/PKG-INFO +1 -1
  15. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_operator_cmd.py +20 -0
  16. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_scrub.py +57 -0
  17. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/LICENSE +0 -0
  18. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/MANIFEST.in +0 -0
  19. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/QUICKSTART.md +0 -0
  20. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/README.md +0 -0
  21. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/setup.cfg +0 -0
  22. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/__main__.py +0 -0
  23. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/aboyeur.py +0 -0
  24. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/add.py +0 -0
  25. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/agents.py +0 -0
  26. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/budgets.py +0 -0
  27. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/budgets_cmd.py +0 -0
  28. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/center_cmd.py +0 -0
  29. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/chat_cmd.py +0 -0
  30. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/cli.py +0 -0
  31. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/config.py +0 -0
  32. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/context_cmd.py +0 -0
  33. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/daily_cmd.py +0 -0
  34. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/doctor.py +0 -0
  35. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/dogfood_cmd.py +0 -0
  36. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/fragments.py +0 -0
  37. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/handoff.py +0 -0
  38. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/handoff_cmd.py +0 -0
  39. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/hermes_adapter.py +0 -0
  40. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/ingest.py +0 -0
  41. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/install.py +0 -0
  42. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/learn_cmd.py +0 -0
  43. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/managed.py +0 -0
  44. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/memory_cmd.py +0 -0
  45. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/notifications_cmd.py +0 -0
  46. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/pantry_cmd.py +0 -0
  47. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/phases_cmd.py +0 -0
  48. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/proc.py +0 -0
  49. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/projects_cmd.py +0 -0
  50. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/prompt.py +0 -0
  51. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/py.typed +0 -0
  52. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/reconfigure.py +0 -0
  53. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/registry.py +0 -0
  54. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/release_cmd.py +0 -0
  55. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/repos_cmd.py +0 -0
  56. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/research/__init__.py +0 -0
  57. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/research/config.py +0 -0
  58. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/research/engine.py +0 -0
  59. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/research/extract.py +0 -0
  60. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/research/handoff.py +0 -0
  61. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/research/llm.py +0 -0
  62. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/research/registry.py +0 -0
  63. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/research/report.py +0 -0
  64. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/research/sources/__init__.py +0 -0
  65. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/research/sources/cli.py +0 -0
  66. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/research/sources/local.py +0 -0
  67. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/research/sources/web.py +0 -0
  68. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/research/types.py +0 -0
  69. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/research_cmd.py +0 -0
  70. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/roadmap_cmd.py +0 -0
  71. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/roster.py +0 -0
  72. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/roster_cmd.py +0 -0
  73. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/runbook_cmd.py +0 -0
  74. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/runs_cmd.py +0 -0
  75. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/security_cmd.py +0 -0
  76. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/selection.py +0 -0
  77. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/skills_cmd.py +0 -0
  78. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/station.py +0 -0
  79. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/status.py +0 -0
  80. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/adal/memory-handoffs/TEMPLATE.md +0 -0
  81. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/aider/memory-handoffs/TEMPLATE.md +0 -0
  82. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/antigravity/memory-handoffs/TEMPLATE.md +0 -0
  83. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/claude/memory-handoffs/TEMPLATE.md +0 -0
  84. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/codex/memory-handoffs/TEMPLATE.md +0 -0
  85. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/continue/memory-handoffs/TEMPLATE.md +0 -0
  86. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/copilot/memory-handoffs/TEMPLATE.md +0 -0
  87. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/cursor/memory-handoffs/TEMPLATE.md +0 -0
  88. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/depth/repo.json +0 -0
  89. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/depth/workspace.json +0 -0
  90. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/generic/harness-adapter-checklist.md +0 -0
  91. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/generic/memory-contract.md +0 -0
  92. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/goose/memory-handoffs/TEMPLATE.md +0 -0
  93. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/handoff/handoff-sources.example.json +0 -0
  94. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/handoff/openclaw-ingest-receipt.example.json +0 -0
  95. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/harnesses/adal.json +0 -0
  96. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/harnesses/aider.json +0 -0
  97. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/harnesses/antigravity.json +0 -0
  98. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/harnesses/claude.json +0 -0
  99. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/harnesses/codex.json +0 -0
  100. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/harnesses/continue.json +0 -0
  101. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/harnesses/copilot.json +0 -0
  102. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/harnesses/cursor.json +0 -0
  103. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/harnesses/goose.json +0 -0
  104. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/harnesses/hermes.json +0 -0
  105. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/harnesses/kimi.json +0 -0
  106. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/harnesses/openclaw.json +0 -0
  107. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/harnesses/opencode.json +0 -0
  108. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/harnesses/openhands.json +0 -0
  109. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/harnesses/pi.json +0 -0
  110. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/harnesses/qwen.json +0 -0
  111. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/hermes/README.md +0 -0
  112. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/hermes/memory-handoffs/TEMPLATE.md +0 -0
  113. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/hooks/pre-push +0 -0
  114. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/includes/publisher.json +0 -0
  115. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/kimi/memory-handoffs/TEMPLATE.md +0 -0
  116. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/memory/cards/backup-restic.md +0 -0
  117. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/memory/cards/chat-surface-crawlers.md +0 -0
  118. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/memory/cards/content-safety.md +0 -0
  119. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/memory/cards/handoff-flow.md +0 -0
  120. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/memory/cards/memory-architecture.md +0 -0
  121. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/memory/cards/memory-care-staleness.md +0 -0
  122. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/memory/cards/memory-scanner.md +0 -0
  123. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/memory/cards/multi-workspace-handoff-admin.md +0 -0
  124. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/memory/cards/obsidian-notes.md +0 -0
  125. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/memory/cards/pipeline-standups.md +0 -0
  126. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/memory/cards/tokenjuice-output-compaction.md +0 -0
  127. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/openclaw/README.md +0 -0
  128. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/openclaw/acp-escalation.openclaw.json +0 -0
  129. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/openclaw/memory-sweep-cron.openclaw.json +0 -0
  130. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/openclaw/model-aliases.openclaw.json +0 -0
  131. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/openclaw/ollama-memory-search.openclaw.json +0 -0
  132. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/opencode/memory-handoffs/TEMPLATE.md +0 -0
  133. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/openhands/memory-handoffs/TEMPLATE.md +0 -0
  134. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/pi/memory-handoffs/TEMPLATE.md +0 -0
  135. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/qwen/memory-handoffs/TEMPLATE.md +0 -0
  136. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/scripts/backup-restic.sh +0 -0
  137. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/skills/note/SKILL.md +0 -0
  138. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/workspace/AGENTS.md +0 -0
  139. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/workspace/CLAUDE.md +0 -0
  140. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/workspace/HEARTBEAT.md +0 -0
  141. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/workspace/IDENTITY.md +0 -0
  142. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/workspace/INSTALL_FOR_AGENTS.md +0 -0
  143. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/workspace/MEMORY.md +0 -0
  144. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/workspace/SAFETY_RULES.md +0 -0
  145. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/workspace/SOUL.md +0 -0
  146. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/workspace/TOOLS.md +0 -0
  147. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/workspace/USER.md +0 -0
  148. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/workspace/rules/acceptance-driven-work.md +0 -0
  149. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates/workspace/rules/issue-tdd-loop.md +0 -0
  150. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/templates.py +0 -0
  151. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/toml_compat.py +0 -0
  152. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/tools_cmd.py +0 -0
  153. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/untrusted.py +0 -0
  154. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/untrusted_cmd.py +0 -0
  155. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade/work_cmd.py +0 -0
  156. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade_cli.egg-info/SOURCES.txt +0 -0
  157. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade_cli.egg-info/dependency_links.txt +0 -0
  158. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade_cli.egg-info/entry_points.txt +0 -0
  159. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade_cli.egg-info/requires.txt +0 -0
  160. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/src/brigade_cli.egg-info/top_level.txt +0 -0
  161. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_aboyeur.py +0 -0
  162. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_add.py +0 -0
  163. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_agents.py +0 -0
  164. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_budgets.py +0 -0
  165. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_cli_alias.py +0 -0
  166. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_cli_help.py +0 -0
  167. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_config.py +0 -0
  168. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_doctor.py +0 -0
  169. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_dogfood_cmd.py +0 -0
  170. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_fragments.py +0 -0
  171. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_gitignore.py +0 -0
  172. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_handoff.py +0 -0
  173. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_handoff_cmd.py +0 -0
  174. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_ingest.py +0 -0
  175. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_init.py +0 -0
  176. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_install.py +0 -0
  177. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_managed.py +0 -0
  178. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_memory_cmd.py +0 -0
  179. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_neutrality.py +0 -0
  180. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_notifications_cmd.py +0 -0
  181. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_pantry_cmd.py +0 -0
  182. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_phase100_cmd.py +0 -0
  183. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_phase101_cmd.py +0 -0
  184. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_phase165_cmd.py +0 -0
  185. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_phase36_cmd.py +0 -0
  186. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_phase37_cmd.py +0 -0
  187. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_phase38_cmd.py +0 -0
  188. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_phase39_cmd.py +0 -0
  189. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_phase40_cmd.py +0 -0
  190. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_phase41_cmd.py +0 -0
  191. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_phase42_cmd.py +0 -0
  192. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_phase43_cmd.py +0 -0
  193. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_phase44_cmd.py +0 -0
  194. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_phase45_cmd.py +0 -0
  195. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_phase46_50_cmd.py +0 -0
  196. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_phase51_55_cmd.py +0 -0
  197. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_phase56_60_cmd.py +0 -0
  198. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_phase96_cmd.py +0 -0
  199. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_phase97_cmd.py +0 -0
  200. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_phase98_cmd.py +0 -0
  201. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_phase99_cmd.py +0 -0
  202. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_privacy_regression.py +0 -0
  203. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_proc.py +0 -0
  204. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_prompt.py +0 -0
  205. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_reconfigure.py +0 -0
  206. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_registry.py +0 -0
  207. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_release_cmd.py +0 -0
  208. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_repos_cmd.py +0 -0
  209. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_research_cli_sources.py +0 -0
  210. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_research_cmd.py +0 -0
  211. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_research_config.py +0 -0
  212. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_research_engine.py +0 -0
  213. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_research_extract.py +0 -0
  214. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_research_handoff.py +0 -0
  215. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_research_llm.py +0 -0
  216. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_research_local_sources.py +0 -0
  217. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_research_registry.py +0 -0
  218. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_research_report.py +0 -0
  219. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_research_types.py +0 -0
  220. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_research_web.py +0 -0
  221. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_roadmap_cmd.py +0 -0
  222. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_roster.py +0 -0
  223. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_roster_cmd.py +0 -0
  224. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_run_cli.py +0 -0
  225. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_runbook_cmd.py +0 -0
  226. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_runs_cmd.py +0 -0
  227. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_security_cmd.py +0 -0
  228. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_selection.py +0 -0
  229. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_skills_cmd.py +0 -0
  230. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_station.py +0 -0
  231. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_status.py +0 -0
  232. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_toml_compat.py +0 -0
  233. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_untrusted.py +0 -0
  234. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_untrusted_cmd.py +0 -0
  235. {brigade_cli-0.9.2 → brigade_cli-0.9.3}/tests/test_work_cmd.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: brigade-cli
3
- Version: 0.9.2
3
+ Version: 0.9.3
4
4
  Summary: AI agent memory, handoffs, and local guardrails for Codex, Claude Code, OpenCode, Hermes, and OpenClaw.
5
5
  Author-email: Solomon Neas <srneas@gmail.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "brigade-cli"
7
- version = "0.9.2"
7
+ version = "0.9.3"
8
8
  description = "AI agent memory, handoffs, and local guardrails for Codex, Claude Code, OpenCode, Hermes, and OpenClaw."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -1,3 +1,3 @@
1
1
  """Brigade: local operator-system CLI for agent workspaces."""
2
2
 
3
- __version__ = "0.9.2"
3
+ __version__ = "0.9.3"
@@ -2505,6 +2505,35 @@ def verify_harness_payload(target: Path, *, harness: str) -> dict[str, Any]:
2505
2505
  else:
2506
2506
  checks.append({"status": "warn", "name": "handoff_inbox_gitignored", "detail": f"gitignore status: {gitignored}"})
2507
2507
 
2508
+ # The managed .gitignore un-ignores each inbox's TEMPLATE.md so the format
2509
+ # travels with the repo. Git cannot re-include a file whose parent dir is
2510
+ # excluded by another source (commonly a global gitignore with a bare
2511
+ # `.claude/` or `.codex/` entry), and that shadowing is otherwise silent.
2512
+ template_path = inbox_path / "TEMPLATE.md"
2513
+ if template_path.is_file():
2514
+ template_ignored = dogfood_cmd._check_git_ignored(target, template_path)
2515
+ if template_ignored == "yes":
2516
+ inbox_root = inbox_rel.split("/")[0]
2517
+ checks.append(
2518
+ {
2519
+ "status": "warn",
2520
+ "name": "handoff_template_shadowed",
2521
+ "detail": (
2522
+ f"{inbox_rel}/TEMPLATE.md is gitignored despite the managed un-ignore rule; "
2523
+ f"an external ignore source (often a global gitignore entry like `{inbox_root}/`) "
2524
+ "is shadowing it, so the template will not travel with the repo"
2525
+ ),
2526
+ }
2527
+ )
2528
+ else:
2529
+ checks.append(
2530
+ {
2531
+ "status": "ok",
2532
+ "name": "handoff_template_shadowed",
2533
+ "detail": f"{inbox_rel}/TEMPLATE.md is visible to git",
2534
+ }
2535
+ )
2536
+
2508
2537
  lint_results = [
2509
2538
  result
2510
2539
  for result in health.lint
@@ -27,6 +27,7 @@ def hook_status(target: Path, policy: str = "public-repo") -> dict[str, Any]:
27
27
  target = target.expanduser().resolve()
28
28
  hook = target / "hooks" / "pre-push"
29
29
  hooks_path = _git_config(target, "core.hooksPath")
30
+ local_hooks_path = _git_config(target, "core.hooksPath", local_only=True)
30
31
  git_hook = _git_pre_push_hook(target)
31
32
  configured_hook = _configured_pre_push_hook(target, hooks_path)
32
33
  active_hook = configured_hook if hooks_path else git_hook
@@ -40,6 +41,15 @@ def hook_status(target: Path, policy: str = "public-repo") -> dict[str, Any]:
40
41
  hook_mode = "configured-hooks-path"
41
42
  elif hook_enabled:
42
43
  hook_mode = "git-hooks"
44
+ # A core.hooksPath inherited from global/system git config can point at a
45
+ # personal pre-push that has nothing to do with content-guard. Reporting
46
+ # that as "installed" is a false positive; only trust an inherited hook
47
+ # when it actually runs content-guard.
48
+ hook_inherited = bool(hooks_path) and not local_hooks_path
49
+ if hook_mode == "configured-hooks-path" and hook_inherited and active_hook is not None:
50
+ if not _hook_runs_content_guard(active_hook):
51
+ hook_mode = "external-hooks-path"
52
+ hook_enabled = False
43
53
  try:
44
54
  resolved_policy = str(policy_path(target, policy))
45
55
  except ValueError as exc:
@@ -53,7 +63,17 @@ def hook_status(target: Path, policy: str = "public-repo") -> dict[str, Any]:
53
63
  if not policy_exists:
54
64
  checks.append({"status": "warn", "name": "content_guard_policy_missing", "detail": f"policy not found: {resolved_policy}"})
55
65
  suggestions.append(f"brigade scrub --target . --policy {policy} --dry-run")
56
- if not hook_enabled:
66
+ if hook_mode == "external-hooks-path":
67
+ checks.append(
68
+ {
69
+ "status": "warn",
70
+ "name": "content_guard_hook_unrelated",
71
+ "detail": "the active pre-push comes from a global core.hooksPath outside this repo and does not run content-guard; the repo's hook is not active",
72
+ }
73
+ )
74
+ if hook.is_file():
75
+ suggestions.append("git config core.hooksPath hooks")
76
+ elif not hook_enabled:
57
77
  checks.append({"status": "warn", "name": "content_guard_hook_not_enabled", "detail": "no executable pre-push hook found in the active Git hooks path"})
58
78
  if hook.is_file():
59
79
  suggestions.append("git config core.hooksPath hooks")
@@ -85,10 +105,19 @@ def hook_status(target: Path, policy: str = "public-repo") -> dict[str, Any]:
85
105
  }
86
106
 
87
107
 
88
- def _git_config(target: Path, key: str) -> str | None:
108
+ def _hook_runs_content_guard(path: Path) -> bool:
109
+ try:
110
+ text = path.read_text(errors="replace")
111
+ except OSError:
112
+ return False
113
+ return any(marker in text for marker in ("content-guard", "content_guard", "brigade scrub"))
114
+
115
+
116
+ def _git_config(target: Path, key: str, *, local_only: bool = False) -> str | None:
117
+ scope = ["--local"] if local_only else []
89
118
  try:
90
119
  result = subprocess.run(
91
- ["git", "-C", str(target), "config", "--get", key],
120
+ ["git", "-C", str(target), "config", *scope, "--get", key],
92
121
  check=False,
93
122
  stdout=subprocess.PIPE,
94
123
  stderr=subprocess.DEVNULL,
@@ -5,7 +5,7 @@
5
5
  "Describes the handoff inbox + routing targets that Hermes should treat",
6
6
  "as the canonical memory contract."
7
7
  ],
8
- "_brigade_version": "0.9.2",
8
+ "_brigade_version": "0.9.3",
9
9
  "_brigade_status": "experimental",
10
10
  "memory_handoff": {
11
11
  "inbox_dir": ".hermes/memory-handoffs",
@@ -5,7 +5,7 @@
5
5
  "Suggested model lane names. Same shape as the OpenClaw alias map so",
6
6
  "knowledge cards and runbooks can talk about lanes without naming providers."
7
7
  ],
8
- "_brigade_version": "0.9.2",
8
+ "_brigade_version": "0.9.3",
9
9
  "_brigade_status": "experimental",
10
10
  "model_lanes": {
11
11
  "main": "<provider/main-model-id>",
@@ -8,7 +8,7 @@
8
8
  "",
9
9
  "Replace <hermes-config-path> with your Hermes config location."
10
10
  ],
11
- "_brigade_version": "0.9.2",
11
+ "_brigade_version": "0.9.3",
12
12
  "_brigade_status": "experimental",
13
13
  "workspace": {
14
14
  "root": "<workspace-root>",
@@ -1,5 +1,5 @@
1
1
  {
2
- "_brigade_version": "0.9.2",
2
+ "_brigade_version": "0.9.3",
3
3
  "_description": "Example output contract for a nightly chat/session memory sweep. Keep raw chat transcripts in crawler archives; this file contains summaries and local source locators only.",
4
4
  "generated_at": "2026-05-26T22:09:00-04:00",
5
5
  "window": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "_brigade_version": "0.9.2",
2
+ "_brigade_version": "0.9.3",
3
3
  "_description": "Example config for a local memory-care scanner. Brigade does not run this scanner for you; it validates the output with `brigade doctor`.",
4
4
  "cards_glob": "memory/cards/*.md",
5
5
  "decay_dir": ".brigade/memory-care/decay",
@@ -4,7 +4,7 @@
4
4
  "It blocks secrets and attribution trailers, while warning on personal or infrastructure-like context.",
5
5
  "Use via: brigade handoff lint --content-guard --guard-policy personal"
6
6
  ],
7
- "_brigade_version": "0.9.2",
7
+ "_brigade_version": "0.9.3",
8
8
  "categories": {
9
9
  "secret": "block",
10
10
  "private-network": "warn",
@@ -4,7 +4,7 @@
4
4
  "social drafts, and docs that will be published, not just pushed.",
5
5
  "Use via: brigade scrub --policy public-content"
6
6
  ],
7
- "_brigade_version": "0.9.2",
7
+ "_brigade_version": "0.9.3",
8
8
  "categories": {
9
9
  "secret": "block",
10
10
  "private-network": "block",
@@ -4,7 +4,7 @@
4
4
  "Used by brigade pre-push hook and `brigade scrub`.",
5
5
  "Override by pointing CONTENT_GUARD_POLICY at your own copy of this file."
6
6
  ],
7
- "_brigade_version": "0.9.2",
7
+ "_brigade_version": "0.9.3",
8
8
  "categories": {
9
9
  "secret": "block",
10
10
  "private-network": "block",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: brigade-cli
3
- Version: 0.9.2
3
+ Version: 0.9.3
4
4
  Summary: AI agent memory, handoffs, and local guardrails for Codex, Claude Code, OpenCode, Hermes, and OpenClaw.
5
5
  Author-email: Solomon Neas <srneas@gmail.com>
6
6
  License: MIT
@@ -1259,3 +1259,23 @@ def test_operator_quickstart_gitignore_covers_all_selected_inboxes(tmp_path, cap
1259
1259
  gitignore = (tmp_path / ".gitignore").read_text()
1260
1260
  assert ".codex/memory-handoffs/*" in gitignore
1261
1261
  assert ".claude/memory-handoffs/*" in gitignore
1262
+
1263
+
1264
+ def test_verify_harness_warns_when_inbox_template_shadowed_by_external_ignore(tmp_path, capsys):
1265
+ import subprocess
1266
+
1267
+ subprocess.run(["git", "init", "-q", str(tmp_path)], check=True)
1268
+ assert cli.main(["operator", "quickstart", "--target", str(tmp_path), "--harnesses", "codex", "--json"]) == 0
1269
+ capsys.readouterr()
1270
+
1271
+ cli.main(["operator", "verify-harness", "--target", str(tmp_path), "--harness", "codex", "--json"])
1272
+ payload = json.loads(capsys.readouterr().out)
1273
+ shadow = [c for c in payload["checks"] if c["name"] == "handoff_template_shadowed"]
1274
+ assert shadow and shadow[0]["status"] == "ok"
1275
+
1276
+ (tmp_path / ".git" / "info" / "exclude").write_text(".codex/\n")
1277
+ cli.main(["operator", "verify-harness", "--target", str(tmp_path), "--harness", "codex", "--json"])
1278
+ payload = json.loads(capsys.readouterr().out)
1279
+ shadow = [c for c in payload["checks"] if c["name"] == "handoff_template_shadowed"]
1280
+ assert shadow and shadow[0]["status"] == "warn"
1281
+ assert "shadow" in shadow[0]["detail"] or "global" in shadow[0]["detail"]
@@ -134,3 +134,60 @@ def test_scrub_returns_4_on_unsafe_bare_name(tmp_path: Path, monkeypatch):
134
134
  monkeypatch.setenv("CONTENT_GUARD_DIR", str(scanner))
135
135
  rc = scrub_mod.run(target=target, policy="..", dry_run=True)
136
136
  assert rc == 4
137
+
138
+
139
+ def _fake_git_run(target, *, global_hooks, local_hooks_path=None):
140
+ def fake_run(argv, **kwargs):
141
+ if argv[:3] == ["git", "-C", str(target)] and argv[-1] == "core.hooksPath":
142
+ if "--local" in argv:
143
+ class Result:
144
+ returncode = 0 if local_hooks_path else 1
145
+ stdout = local_hooks_path or ""
146
+ return Result()
147
+
148
+ class Result:
149
+ returncode = 0
150
+ stdout = str(global_hooks)
151
+ return Result()
152
+ if argv[:3] == ["git", "-C", str(target)] and argv[-1] == "--git-dir":
153
+ class Result:
154
+ returncode = 0
155
+ stdout = ".git"
156
+ return Result()
157
+ raise AssertionError(argv)
158
+ return fake_run
159
+
160
+
161
+ def test_hook_status_flags_inherited_hookspath_without_content_guard(tmp_path: Path, monkeypatch):
162
+ target = tmp_path / "repo"
163
+ target.mkdir()
164
+ hooks = tmp_path / "global-hooks"
165
+ hooks.mkdir()
166
+ hook = hooks / "pre-push"
167
+ hook.write_text("#!/usr/bin/env bash\necho unrelated personal hook\n")
168
+ hook.chmod(0o755)
169
+ monkeypatch.setenv("CONTENT_GUARD_DIR", str(tmp_path / "content-guard"))
170
+ monkeypatch.setattr(scrub_mod.subprocess, "run", _fake_git_run(target, global_hooks=hooks))
171
+
172
+ status = scrub_mod.hook_status(target, policy="personal")
173
+
174
+ assert status["pre_push_hook_enabled"] is False
175
+ assert status["pre_push_hook_mode"] == "external-hooks-path"
176
+ assert any(check["name"] == "content_guard_hook_unrelated" for check in status["checks"])
177
+
178
+
179
+ def test_hook_status_accepts_inherited_hookspath_running_content_guard(tmp_path: Path, monkeypatch):
180
+ target = tmp_path / "repo"
181
+ target.mkdir()
182
+ hooks = tmp_path / "global-hooks"
183
+ hooks.mkdir()
184
+ hook = hooks / "pre-push"
185
+ hook.write_text("#!/usr/bin/env bash\nexec content-guard scan --policy public-repo\n")
186
+ hook.chmod(0o755)
187
+ monkeypatch.setenv("CONTENT_GUARD_DIR", str(tmp_path / "content-guard"))
188
+ monkeypatch.setattr(scrub_mod.subprocess, "run", _fake_git_run(target, global_hooks=hooks))
189
+
190
+ status = scrub_mod.hook_status(target, policy="personal")
191
+
192
+ assert status["pre_push_hook_enabled"] is True
193
+ assert status["pre_push_hook_mode"] == "configured-hooks-path"
File without changes
File without changes
File without changes
File without changes
File without changes