briar-cli 1.1.45__tar.gz → 1.1.46__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 (429) hide show
  1. {briar_cli-1.1.45 → briar_cli-1.1.46}/.gitignore +3 -0
  2. {briar_cli-1.1.45 → briar_cli-1.1.46}/PKG-INFO +59 -29
  3. {briar_cli-1.1.45 → briar_cli-1.1.46}/README.md +58 -28
  4. {briar_cli-1.1.45 → briar_cli-1.1.46}/pyproject.toml +1 -1
  5. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/cli.py +45 -0
  6. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/commands/extract.py +20 -0
  7. briar_cli-1.1.46/src/briar/config.py +208 -0
  8. briar_cli-1.1.46/src/briar/extract/canonical.py +251 -0
  9. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/runbook/executor.py +6 -0
  10. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/_composer.py +24 -1
  11. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/sources/base.py +11 -12
  12. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/sources/jira.py +3 -9
  13. briar_cli-1.1.46/src/briar/infer.py +79 -0
  14. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/conftest.py +9 -1
  15. briar_cli-1.1.46/tests/unit/extract/test_canonical.py +112 -0
  16. briar_cli-1.1.46/tests/unit/extract/test_legacy_flag_notice.py +54 -0
  17. briar_cli-1.1.46/tests/unit/iac/test_scaffold_shared_filters.py +57 -0
  18. briar_cli-1.1.46/tests/unit/test_config.py +124 -0
  19. briar_cli-1.1.46/tests/unit/test_infer.py +84 -0
  20. {briar_cli-1.1.45 → briar_cli-1.1.46}/LICENSE +0 -0
  21. {briar_cli-1.1.45 → briar_cli-1.1.46}/agents/README.md +0 -0
  22. {briar_cli-1.1.45 → briar_cli-1.1.46}/examples/all_features.yaml +0 -0
  23. {briar_cli-1.1.45 → briar_cli-1.1.46}/examples/multi_company.env.example +0 -0
  24. {briar_cli-1.1.45 → briar_cli-1.1.46}/examples/multi_company.yaml +0 -0
  25. {briar_cli-1.1.45 → briar_cli-1.1.46}/examples/simple-single-repo.yaml +0 -0
  26. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/__init__.py +0 -0
  27. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/__main__.py +0 -0
  28. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/_http_retry.py +0 -0
  29. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/_registry.py +0 -0
  30. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/agent/__init__.py +0 -0
  31. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/agent/_enums.py +0 -0
  32. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/agent/_llm.py +0 -0
  33. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/agent/_llms/__init__.py +0 -0
  34. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/agent/_llms/anthropic_llm.py +0 -0
  35. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/agent/_llms/bedrock.py +0 -0
  36. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/agent/_llms/gemini.py +0 -0
  37. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/agent/_llms/openai_llm.py +0 -0
  38. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/agent/runner.py +0 -0
  39. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/agent/tools.py +0 -0
  40. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/auth/__init__.py +0 -0
  41. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/auth/_acquirer.py +0 -0
  42. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/auth/_acquirers/__init__.py +0 -0
  43. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/auth/_acquirers/aws_sso.py +0 -0
  44. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/auth/_acquirers/aws_static.py +0 -0
  45. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/auth/_acquirers/bitbucket.py +0 -0
  46. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/auth/_acquirers/fireflies.py +0 -0
  47. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/auth/_acquirers/github_device.py +0 -0
  48. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/auth/_acquirers/github_pat.py +0 -0
  49. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/auth/_acquirers/jira_session.py +0 -0
  50. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/auth/_acquirers/jira_token.py +0 -0
  51. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/auth/_acquirers/linear.py +0 -0
  52. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/auth/_prompt.py +0 -0
  53. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/commands/__init__.py +0 -0
  54. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/commands/_enums.py +0 -0
  55. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/commands/agent.py +0 -0
  56. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/commands/auth.py +0 -0
  57. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/commands/base.py +0 -0
  58. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/commands/context.py +0 -0
  59. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/commands/dashboard.py +0 -0
  60. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/commands/iac.py +0 -0
  61. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/commands/journal.py +0 -0
  62. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/commands/plan.py +0 -0
  63. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/commands/runbook.py +0 -0
  64. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/commands/secrets.py +0 -0
  65. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/commands/telemetry.py +0 -0
  66. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/commands/version.py +0 -0
  67. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/credentials/__init__.py +0 -0
  68. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/credentials/_aws.py +0 -0
  69. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/credentials/_bootstrap.py +0 -0
  70. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/credentials/_bootstraps/__init__.py +0 -0
  71. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/credentials/_bootstraps/envfile.py +0 -0
  72. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/credentials/_paths.py +0 -0
  73. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/credentials/_store.py +0 -0
  74. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/credentials/aws_secrets.py +0 -0
  75. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/credentials/envfile.py +0 -0
  76. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/credentials/ssm.py +0 -0
  77. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/credentials/vault.py +0 -0
  78. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/dashboard/__init__.py +0 -0
  79. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/dashboard/collectors.py +0 -0
  80. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/dashboard/server.py +0 -0
  81. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/dashboard/templates/_macros.html +0 -0
  82. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/dashboard/templates/index.html +0 -0
  83. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/decorators.py +0 -0
  84. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/env_vars.py +0 -0
  85. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/error_policy.py +0 -0
  86. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/errors.py +0 -0
  87. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/__init__.py +0 -0
  88. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/_cloud.py +0 -0
  89. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/_clouds/__init__.py +0 -0
  90. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/_clouds/aws.py +0 -0
  91. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/_clouds/azure.py +0 -0
  92. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/_clouds/gcp.py +0 -0
  93. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/_gh.py +0 -0
  94. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/_meeting.py +0 -0
  95. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/_meetings/__init__.py +0 -0
  96. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/_meetings/fireflies.py +0 -0
  97. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/_provider.py +0 -0
  98. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/_providers/__init__.py +0 -0
  99. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/_providers/bitbucket.py +0 -0
  100. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/_providers/github.py +0 -0
  101. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/_time_util.py +0 -0
  102. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/_tracker.py +0 -0
  103. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/_trackers/__init__.py +0 -0
  104. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/_trackers/_jira_auth.py +0 -0
  105. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/_trackers/bitbucket.py +0 -0
  106. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/_trackers/github_issues.py +0 -0
  107. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/_trackers/jira.py +0 -0
  108. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/_trackers/linear.py +0 -0
  109. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/_user_filter.py +0 -0
  110. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/active_tickets.py +0 -0
  111. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/active_work.py +0 -0
  112. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/aws_infra.py +0 -0
  113. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/aws_services/__init__.py +0 -0
  114. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/aws_services/base.py +0 -0
  115. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/aws_services/ecs.py +0 -0
  116. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/aws_services/lambda_.py +0 -0
  117. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/aws_services/logs.py +0 -0
  118. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/aws_services/rds.py +0 -0
  119. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/aws_services/sqs.py +0 -0
  120. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/aws_services/tagging.py +0 -0
  121. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/base.py +0 -0
  122. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/ci_health.py +0 -0
  123. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/claude_md.py +0 -0
  124. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/code_hotspots.py +0 -0
  125. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/code_scanning.py +0 -0
  126. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/codebase_conventions.py +0 -0
  127. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/commit_message_quality.py +0 -0
  128. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/composer.py +0 -0
  129. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/defect_hotspots.py +0 -0
  130. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/dependency_health.py +0 -0
  131. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/github_deployments.py +0 -0
  132. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/language_detectors/__init__.py +0 -0
  133. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/meeting_context.py +0 -0
  134. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/meeting_digest.py +0 -0
  135. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/pr_archaeology.py +0 -0
  136. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/pr_hygiene.py +0 -0
  137. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/pr_review_context.py +0 -0
  138. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/release_cadence.py +0 -0
  139. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/repo_governance.py +0 -0
  140. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/revert_signals.py +0 -0
  141. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/review_nits.py +0 -0
  142. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/reviewer_profile.py +0 -0
  143. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/stale_prs.py +0 -0
  144. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/test_discipline.py +0 -0
  145. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/ticket_archaeology.py +0 -0
  146. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/ticket_context.py +0 -0
  147. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/extract/todo_density.py +0 -0
  148. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/formatting/__init__.py +0 -0
  149. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/formatting/base.py +0 -0
  150. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/formatting/csv.py +0 -0
  151. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/formatting/json.py +0 -0
  152. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/formatting/quiet.py +0 -0
  153. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/formatting/table.py +0 -0
  154. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/formatting/yaml.py +0 -0
  155. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/__init__.py +0 -0
  156. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/config_file.py +0 -0
  157. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/models.py +0 -0
  158. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/runbook/__init__.py +0 -0
  159. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/runbook/models.py +0 -0
  160. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/runbook/scheduler.py +0 -0
  161. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/__init__.py +0 -0
  162. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/_knowledge.py +0 -0
  163. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/archetypes/__init__.py +0 -0
  164. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/archetypes/base.py +0 -0
  165. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/archetypes/engineer.py +0 -0
  166. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/archetypes/pr_ci_fixer.py +0 -0
  167. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/archetypes/pr_conflict_resolver.py +0 -0
  168. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/archetypes/pr_fixer.py +0 -0
  169. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/archetypes/triager.py +0 -0
  170. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/base.py +0 -0
  171. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/implementation.py +0 -0
  172. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/pr_fixes.py +0 -0
  173. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/rules/__init__.py +0 -0
  174. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/rules/ai_prefix_on_comments.md +0 -0
  175. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/rules/base.py +0 -0
  176. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/rules/commit_as_human.md +0 -0
  177. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/rules/minimum_correct_fix.md +0 -0
  178. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/rules/no_force_push.md +0 -0
  179. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/rules/no_new_pr_creation.md +0 -0
  180. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/rules/no_workflow_file_edits.md +0 -0
  181. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/rules/read_all_comments_first.md +0 -0
  182. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/rules/skip_approved_green_prs.md +0 -0
  183. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/shapes/__init__.py +0 -0
  184. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/sources/__init__.py +0 -0
  185. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/sources/aws.py +0 -0
  186. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/sources/bitbucket.py +0 -0
  187. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/sources/github.py +0 -0
  188. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/sources/sentry.py +0 -0
  189. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/triggers/__init__.py +0 -0
  190. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/triggers/base.py +0 -0
  191. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/triggers/bitbucket_webhook.py +0 -0
  192. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/triggers/github_webhook.py +0 -0
  193. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/triggers/manual.py +0 -0
  194. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/iac/scaffold/triggers/schedule_cron.py +0 -0
  195. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/journal/__init__.py +0 -0
  196. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/journal/_journal.py +0 -0
  197. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/journal/_render.py +0 -0
  198. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/journal/models.py +0 -0
  199. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/journal/sinks/__init__.py +0 -0
  200. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/journal/sinks/base.py +0 -0
  201. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/journal/sinks/file.py +0 -0
  202. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/journal/store/__init__.py +0 -0
  203. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/journal/store/base.py +0 -0
  204. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/journal/store/file.py +0 -0
  205. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/log_context.py +0 -0
  206. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/logging.py +0 -0
  207. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/mcp/__init__.py +0 -0
  208. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/mcp/_errors.py +0 -0
  209. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/mcp/_manager.py +0 -0
  210. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/mcp/_tool.py +0 -0
  211. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/mcp/defaults.py +0 -0
  212. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/messaging/__init__.py +0 -0
  213. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/messaging/_jira_creds.py +0 -0
  214. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/messaging/_writer.py +0 -0
  215. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/messaging/bitbucket_pr_comment.py +0 -0
  216. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/messaging/github_pr_comment.py +0 -0
  217. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/messaging/jira_comment.py +0 -0
  218. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/messaging/jira_transition.py +0 -0
  219. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/messaging/slack_channel.py +0 -0
  220. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/messaging/telegram_chat.py +0 -0
  221. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/notify/__init__.py +0 -0
  222. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/notify/_sink.py +0 -0
  223. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/notify/email.py +0 -0
  224. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/notify/pagerduty.py +0 -0
  225. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/notify/slack.py +0 -0
  226. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/notify/telegram.py +0 -0
  227. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/pagination.py +0 -0
  228. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/plan/__init__.py +0 -0
  229. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/plan/_board.py +0 -0
  230. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/plan/_boards/__init__.py +0 -0
  231. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/plan/_boards/github_project.py +0 -0
  232. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/plan/_boards/jira_board.py +0 -0
  233. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/plan/_enums.py +0 -0
  234. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/plan/_json_utils.py +0 -0
  235. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/plan/_models.py +0 -0
  236. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/plan/_replan.py +0 -0
  237. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/plan/_selector.py +0 -0
  238. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/plan/_status.py +0 -0
  239. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/plan/_store.py +0 -0
  240. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/plan/_synthesize.py +0 -0
  241. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/plan/_writeback.py +0 -0
  242. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/storage/__init__.py +0 -0
  243. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/storage/_models.py +0 -0
  244. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/storage/base.py +0 -0
  245. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/storage/file.py +0 -0
  246. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/storage/postgres.py +0 -0
  247. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/telemetry/__init__.py +0 -0
  248. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/telemetry/_config.py +0 -0
  249. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/telemetry/_scrubber.py +0 -0
  250. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/telemetry/_sinks/__init__.py +0 -0
  251. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/telemetry/_sinks/base.py +0 -0
  252. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/telemetry/_sinks/file.py +0 -0
  253. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/telemetry/_sinks/noop.py +0 -0
  254. {briar_cli-1.1.45 → briar_cli-1.1.46}/src/briar/telemetry/_sinks/sentry.py +0 -0
  255. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/__init__.py +0 -0
  256. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/integration/__init__.py +0 -0
  257. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/integration/conftest.py +0 -0
  258. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/integration/mcp_echo_server.py +0 -0
  259. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/integration/test_acquirer_real.py +0 -0
  260. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/integration/test_agent_loop_real.py +0 -0
  261. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/integration/test_auth_login_real.py +0 -0
  262. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/integration/test_cli_extract_real.py +0 -0
  263. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/integration/test_cli_smoke_subprocess.py +0 -0
  264. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/integration/test_extract_aws_real.py +0 -0
  265. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/integration/test_extract_github_real.py +0 -0
  266. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/integration/test_extract_jira_real.py +0 -0
  267. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/integration/test_llm_real.py +0 -0
  268. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/integration/test_local_commands_real.py +0 -0
  269. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/integration/test_mcp_live_real.py +0 -0
  270. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/integration/test_messaging_bitbucket_real.py +0 -0
  271. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/integration/test_messaging_github_inline_real.py +0 -0
  272. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/integration/test_messaging_jira_real.py +0 -0
  273. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/integration/test_messaging_real.py +0 -0
  274. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/integration/test_notify_real.py +0 -0
  275. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/integration/test_plan_llm_real.py +0 -0
  276. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/integration/test_registry_contract.py +0 -0
  277. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/integration/test_tracker_real.py +0 -0
  278. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/test_abstractions.py +0 -0
  279. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/test_dashboard.py +0 -0
  280. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/test_extract.py +0 -0
  281. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/test_extract_meetings.py +0 -0
  282. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/test_formatting.py +0 -0
  283. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/test_journal.py +0 -0
  284. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/test_knowledge_splicer.py +0 -0
  285. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/test_log_context.py +0 -0
  286. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/test_plan.py +0 -0
  287. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/test_plan_run.py +0 -0
  288. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/test_rules_registry.py +0 -0
  289. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/test_scaffold.py +0 -0
  290. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/test_scheduler.py +0 -0
  291. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/test_smart_scheduler.py +0 -0
  292. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/test_user_filter.py +0 -0
  293. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/__init__.py +0 -0
  294. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/agent/__init__.py +0 -0
  295. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/agent/conftest.py +0 -0
  296. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/agent/test_anthropic_llm.py +0 -0
  297. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/agent/test_bedrock_llm.py +0 -0
  298. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/agent/test_gemini_llm.py +0 -0
  299. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/agent/test_llm_registry.py +0 -0
  300. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/agent/test_openai_llm.py +0 -0
  301. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/agent/test_runner_loop.py +0 -0
  302. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/agent/test_runner_mcp.py +0 -0
  303. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/agent/test_tools.py +0 -0
  304. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/auth/__init__.py +0 -0
  305. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/auth/test_aws_sso.py +0 -0
  306. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/auth/test_aws_static.py +0 -0
  307. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/auth/test_github_device.py +0 -0
  308. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/auth/test_jira_session.py +0 -0
  309. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/auth/test_prompt.py +0 -0
  310. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/__init__.py +0 -0
  311. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_agent_cmd.py +0 -0
  312. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_agent_mcp_defaults.py +0 -0
  313. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_agent_params.py +0 -0
  314. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_auth.py +0 -0
  315. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_auth_cmd.py +0 -0
  316. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_auth_params.py +0 -0
  317. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_cli.py +0 -0
  318. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_cmd_creds.py +0 -0
  319. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_context.py +0 -0
  320. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_context_params.py +0 -0
  321. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_dashboard_cmd.py +0 -0
  322. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_dashboard_params.py +0 -0
  323. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_extract.py +0 -0
  324. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_extract_params.py +0 -0
  325. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_journal.py +0 -0
  326. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_journal_params.py +0 -0
  327. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_plan_cmd.py +0 -0
  328. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_plan_params.py +0 -0
  329. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_plan_run_params.py +0 -0
  330. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_runbook.py +0 -0
  331. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_runbook_params.py +0 -0
  332. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_scaffold.py +0 -0
  333. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_scaffold_implementation_params.py +0 -0
  334. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_scaffold_pr_fixes_params.py +0 -0
  335. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_secrets.py +0 -0
  336. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_secrets_params.py +0 -0
  337. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_telemetry_cmd.py +0 -0
  338. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/commands/test_telemetry_params.py +0 -0
  339. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/credentials/__init__.py +0 -0
  340. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/credentials/test_envfile.py +0 -0
  341. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/dashboard/__init__.py +0 -0
  342. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/dashboard/test_log_collectors.py +0 -0
  343. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/dashboard/test_server.py +0 -0
  344. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/dashboard/test_server_render.py +0 -0
  345. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/__init__.py +0 -0
  346. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_active_work.py +0 -0
  347. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_aws_infra.py +0 -0
  348. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_aws_services.py +0 -0
  349. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_ci_health.py +0 -0
  350. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_claude_md.py +0 -0
  351. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_cloud_aws.py +0 -0
  352. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_cloud_azure.py +0 -0
  353. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_cloud_gcp.py +0 -0
  354. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_cloud_registry.py +0 -0
  355. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_code_hotspots.py +0 -0
  356. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_code_scanning.py +0 -0
  357. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_commit_message_quality.py +0 -0
  358. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_composer_inventory.py +0 -0
  359. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_defect_hotspots.py +0 -0
  360. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_dependency_health.py +0 -0
  361. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_gh_facade.py +0 -0
  362. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_github_deployments.py +0 -0
  363. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_meeting_context_gaps.py +0 -0
  364. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_pr_archaeology_gaps.py +0 -0
  365. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_pr_hygiene.py +0 -0
  366. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_provider_bitbucket.py +0 -0
  367. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_provider_github.py +0 -0
  368. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_release_cadence.py +0 -0
  369. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_repo_governance.py +0 -0
  370. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_revert_signals.py +0 -0
  371. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_review_nits.py +0 -0
  372. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_reviewer_profile.py +0 -0
  373. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_stale_prs.py +0 -0
  374. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_test_discipline.py +0 -0
  375. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_ticket_archaeology.py +0 -0
  376. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_ticket_context.py +0 -0
  377. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_todo_density.py +0 -0
  378. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_tracker_bitbucket.py +0 -0
  379. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_tracker_github_issues.py +0 -0
  380. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_tracker_jira.py +0 -0
  381. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_tracker_linear.py +0 -0
  382. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/extract/test_user_filter_branches.py +0 -0
  383. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/iac/__init__.py +0 -0
  384. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/iac/test_every_parser.py +0 -0
  385. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/iac/test_mcp_schema.py +0 -0
  386. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/iac/test_runbook_executor.py +0 -0
  387. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/iac/test_runbook_scheduler.py +0 -0
  388. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/journal/__init__.py +0 -0
  389. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/journal/test_facade.py +0 -0
  390. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/mcp/__init__.py +0 -0
  391. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/mcp/test_mcp_aws_env_bridge.py +0 -0
  392. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/mcp/test_mcp_tool.py +0 -0
  393. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/messaging/__init__.py +0 -0
  394. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/messaging/test_bitbucket_pr_comment.py +0 -0
  395. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/messaging/test_github_pr_comment.py +0 -0
  396. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/messaging/test_jira_comment.py +0 -0
  397. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/messaging/test_jira_transition.py +0 -0
  398. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/messaging/test_slack_channel.py +0 -0
  399. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/messaging/test_telegram_chat.py +0 -0
  400. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/messaging/test_writer_helpers.py +0 -0
  401. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/notify/__init__.py +0 -0
  402. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/notify/test_email.py +0 -0
  403. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/notify/test_pagerduty.py +0 -0
  404. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/notify/test_slack_and_telegram.py +0 -0
  405. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/plan/__init__.py +0 -0
  406. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/plan/test_board_github_project.py +0 -0
  407. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/plan/test_board_jira.py +0 -0
  408. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/plan/test_board_registry.py +0 -0
  409. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/plan/test_models.py +0 -0
  410. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/plan/test_plan_helpers_edges.py +0 -0
  411. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/plan/test_selector_branches.py +0 -0
  412. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/plan/test_status.py +0 -0
  413. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/plan/test_writeback_branches.py +0 -0
  414. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/storage/__init__.py +0 -0
  415. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/storage/test_backends.py +0 -0
  416. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/telemetry/__init__.py +0 -0
  417. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/telemetry/test_command_span.py +0 -0
  418. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/telemetry/test_config.py +0 -0
  419. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/telemetry/test_scrubber.py +0 -0
  420. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/test_decorators.py +0 -0
  421. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/test_env_vars.py +0 -0
  422. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/test_error_policy.py +0 -0
  423. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/test_errors.py +0 -0
  424. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/test_file_tool_sandbox.py +0 -0
  425. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/test_formatting.py +0 -0
  426. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/test_http_retry.py +0 -0
  427. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/test_log_context.py +0 -0
  428. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/test_pagination.py +0 -0
  429. {briar_cli-1.1.45 → briar_cli-1.1.46}/tests/unit/test_runner_dispatch.py +0 -0
@@ -31,3 +31,6 @@ config.json
31
31
 
32
32
  # Real-company runbooks + planning docs — kept local, not for public repo
33
33
  runbooks/
34
+
35
+ # Local Claude Code workspace (worktrees, caches)
36
+ .claude/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: briar-cli
3
- Version: 1.1.45
3
+ Version: 1.1.46
4
4
  Summary: Terminal client for the Briar agent-orchestration API.
5
5
  Project-URL: Homepage, https://usebriar.com
6
6
  Project-URL: Source, https://github.com/iklobato/briar
@@ -129,7 +129,7 @@ export ANTHROPIC_API_KEY=sk-ant-... # LLM key comes from the environment
129
129
  # 2. Mine a repo's PR history into a knowledge blob
130
130
  briar extract --company acme \
131
131
  --include pr-archaeology \
132
- --pr-repo acme-co/acme-app --pr-max 50
132
+ --repo acme-co/acme-app --max 50
133
133
 
134
134
  # 3. Read it back
135
135
  briar context get knowledge:acme
@@ -137,6 +137,30 @@ briar context get knowledge:acme
137
137
 
138
138
  > **Telemetry:** `briar` ships with opt-out error/usage analytics (Sentry). No prompts, file contents, ticket keys, repo names, paths, or secret values ever leave the machine. Turn it off any time with `briar telemetry off`, `BRIAR_TELEMETRY=off`, or `DO_NOT_TRACK=1`.
139
139
 
140
+ ### Less typing: shared flags, project config, inference
141
+
142
+ briar resolves every flag through one chain — **CLI flag > env var > project config > built-in default** — so the stable values move off the command line:
143
+
144
+ ```toml
145
+ # .briar.toml (or [tool.briar] in pyproject.toml), searched upward from cwd
146
+ company = "acme"
147
+ store = "postgres"
148
+
149
+ [repo]
150
+ owner = "acme-co"
151
+ repo = "acme-app"
152
+ ```
153
+
154
+ With that file present, and inside the git checkout, the same extract is just:
155
+
156
+ ```bash
157
+ briar extract --include pr-archaeology # company + repo come from config/git
158
+ ```
159
+
160
+ - **Canonical extractor flags.** One shared knob per concept — `--repo`, `--since-days`, `--max`, `--top-n`, `--sample`, `--authors-allow/-block`, `--assignees-allow/-block` — applies to every extractor selected with `--include`. The old per-extractor flags (`--pr-repo`, `--risk-since-days`, …) still work but are hidden from `-h`; run `briar extract --advanced-help` to see them.
161
+ - **Inference.** `--owner`/`--repo` are read from the git `origin` remote when neither the flag nor config supplies them.
162
+ - A per-extractor override always wins over the shared flag when both are given.
163
+
140
164
  ---
141
165
 
142
166
  ## What you can do
@@ -147,8 +171,8 @@ briar context get knowledge:acme
147
171
  # PRs + AWS infra in one shot, filtered to your team
148
172
  briar extract --company acme \
149
173
  --include pr-archaeology --include aws-infra \
150
- --pr-repo acme-co/acme-app \
151
- --pr-authors-allow alice --pr-authors-allow bob \
174
+ --repo acme-co/acme-app \
175
+ --authors-allow alice --authors-allow bob \
152
176
  --aws-extract-region us-east-1 \
153
177
  --aws-extract-service ecs --aws-extract-service rds
154
178
 
@@ -161,12 +185,11 @@ FIREFLIES_ACME_API_KEY=ff_xxx briar extract --company acme \
161
185
  --include meeting-digest --meeting-since-days 14 \
162
186
  --meeting-attendee-allow alice@acme.com
163
187
 
164
- # Code-quality signal from git history + the repo-host API
165
- briar extract --company acme \
166
- --include defect-hotspots --risk-repo acme-co/acme-app \
167
- --include pr-hygiene --prhygiene-repo acme-co/acme-app \
168
- --include review-nits --nits-repo acme-co/acme-app \
169
- --include ci-health --cihealth-repo acme-co/acme-app
188
+ # Code-quality signal from git history + the repo-host API.
189
+ # One --repo feeds every selected extractor.
190
+ briar extract --company acme --repo acme-co/acme-app \
191
+ --include defect-hotspots --include pr-hygiene \
192
+ --include review-nits --include ci-health
170
193
  ```
171
194
 
172
195
  **Code-quality extractors** (all `--provider github|bitbucket`): `defect-hotspots`
@@ -181,8 +204,8 @@ briar extract --company acme \
181
204
  ```bash
182
205
  # Merge a knowledge index into CLAUDE.md; full detail lands in
183
206
  # .briar/knowledge/<company>.md for the agent to read when relevant.
184
- briar extract --company acme --include defect-hotspots --include ci-health \
185
- --risk-repo acme-co/acme-app --cihealth-repo acme-co/acme-app \
207
+ briar extract --company acme --repo acme-co/acme-app \
208
+ --include defect-hotspots --include ci-health \
186
209
  --merge-claude-md
187
210
  ```
188
211
 
@@ -254,33 +277,40 @@ Plus `briar context` (local knowledge blobs), `briar dashboard` (read-only HTML
254
277
  ### Repeatable flags — fan out across repos, projects, services
255
278
 
256
279
  Most list-style flags accept multiple occurrences: repeat the flag, once
257
- per value (there's no comma form — `--pr-repo a,b` is one repo named
258
- `a,b`). Mix them to cover a whole fleet in a single command.
280
+ per value (there's no comma form — `--repo a,b` is one repo named `a,b`).
281
+ The canonical `--repo` feeds every extractor selected with `--include`.
259
282
 
260
283
  ```bash
261
- # Mine several repos, keep the team's PRs, drop the bots, across two boards.
262
- # --pr-max applies per repo; author allow/block compose as allow ∩ ¬block.
284
+ # Mine several repos, keep the team's PRs, drop the bots one --repo,
285
+ # every selected extractor. --max applies per repo; author allow/block
286
+ # compose as allow ∩ ¬block.
263
287
  briar extract --company acme \
264
- --include pr-archaeology --include active-tickets \
265
- --tracker jira \
266
- --pr-repo acme-co/web --pr-repo acme-co/api --pr-repo acme-co/mobile \
267
- --pr-max 75 \
268
- --pr-authors-block "dependabot[bot]" --pr-authors-block "renovate[bot]" \
269
- --ticket-project ACME --ticket-project PLAT
270
-
271
- # Scaffold a triage flow from two sources, filtered by author + assignee.
272
- # Each tracker source carries its own repeatable *-authors/assignees-*.
288
+ --include pr-archaeology --include defect-hotspots \
289
+ --repo acme-co/web --repo acme-co/api --repo acme-co/mobile \
290
+ --max 75 \
291
+ --authors-block "dependabot[bot]" --authors-block "renovate[bot]"
292
+
293
+ # Scaffold a triage flow from two sources — one shared author/assignee
294
+ # filter applies to every --source.
273
295
  briar scaffold implementation --prefix acme-triage \
274
296
  --source github --source jira \
275
297
  --owner acme-co --repo acme-app --github-secret-id <uuid> \
276
- --github-authors-block "dependabot[bot]" \
277
- --github-assignees-allow alice --github-assignees-allow bob \
298
+ --authors-block "dependabot[bot]" \
299
+ --assignees-allow alice --assignees-allow bob \
278
300
  --jira-project ACME --jira-project PLAT --jira-secret-id <uuid> \
279
301
  --auth-mode pat
280
302
  ```
281
303
 
282
- The same lists map onto runbook YAML as arrays — e.g. `pr_repo:
283
- [acme-co/web, acme-co/api]` is two `--pr-repo` flags.
304
+ The same lists map onto runbook YAML as arrays — e.g. `repo:
305
+ [acme-co/web, acme-co/api]` under an extractor's `args:`.
306
+
307
+ > **Divergent identifiers in one run.** Some extractors key off a tracker
308
+ > *project* (`active-tickets`, `ticket-archaeology`) rather than an
309
+ > `owner/repo` slug. When you run those alongside repo-based extractors in
310
+ > a single invocation and they need *different* values, reach for the
311
+ > per-extractor override flags (`--ticket-project`, `--pr-repo`, … — listed
312
+ > by `briar extract --advanced-help`), or split into two invocations. The
313
+ > runbook YAML models this cleanly: one `args:` block per extractor.
284
314
 
285
315
  ### Handy patterns
286
316
 
@@ -37,7 +37,7 @@ export ANTHROPIC_API_KEY=sk-ant-... # LLM key comes from the environment
37
37
  # 2. Mine a repo's PR history into a knowledge blob
38
38
  briar extract --company acme \
39
39
  --include pr-archaeology \
40
- --pr-repo acme-co/acme-app --pr-max 50
40
+ --repo acme-co/acme-app --max 50
41
41
 
42
42
  # 3. Read it back
43
43
  briar context get knowledge:acme
@@ -45,6 +45,30 @@ briar context get knowledge:acme
45
45
 
46
46
  > **Telemetry:** `briar` ships with opt-out error/usage analytics (Sentry). No prompts, file contents, ticket keys, repo names, paths, or secret values ever leave the machine. Turn it off any time with `briar telemetry off`, `BRIAR_TELEMETRY=off`, or `DO_NOT_TRACK=1`.
47
47
 
48
+ ### Less typing: shared flags, project config, inference
49
+
50
+ briar resolves every flag through one chain — **CLI flag > env var > project config > built-in default** — so the stable values move off the command line:
51
+
52
+ ```toml
53
+ # .briar.toml (or [tool.briar] in pyproject.toml), searched upward from cwd
54
+ company = "acme"
55
+ store = "postgres"
56
+
57
+ [repo]
58
+ owner = "acme-co"
59
+ repo = "acme-app"
60
+ ```
61
+
62
+ With that file present, and inside the git checkout, the same extract is just:
63
+
64
+ ```bash
65
+ briar extract --include pr-archaeology # company + repo come from config/git
66
+ ```
67
+
68
+ - **Canonical extractor flags.** One shared knob per concept — `--repo`, `--since-days`, `--max`, `--top-n`, `--sample`, `--authors-allow/-block`, `--assignees-allow/-block` — applies to every extractor selected with `--include`. The old per-extractor flags (`--pr-repo`, `--risk-since-days`, …) still work but are hidden from `-h`; run `briar extract --advanced-help` to see them.
69
+ - **Inference.** `--owner`/`--repo` are read from the git `origin` remote when neither the flag nor config supplies them.
70
+ - A per-extractor override always wins over the shared flag when both are given.
71
+
48
72
  ---
49
73
 
50
74
  ## What you can do
@@ -55,8 +79,8 @@ briar context get knowledge:acme
55
79
  # PRs + AWS infra in one shot, filtered to your team
56
80
  briar extract --company acme \
57
81
  --include pr-archaeology --include aws-infra \
58
- --pr-repo acme-co/acme-app \
59
- --pr-authors-allow alice --pr-authors-allow bob \
82
+ --repo acme-co/acme-app \
83
+ --authors-allow alice --authors-allow bob \
60
84
  --aws-extract-region us-east-1 \
61
85
  --aws-extract-service ecs --aws-extract-service rds
62
86
 
@@ -69,12 +93,11 @@ FIREFLIES_ACME_API_KEY=ff_xxx briar extract --company acme \
69
93
  --include meeting-digest --meeting-since-days 14 \
70
94
  --meeting-attendee-allow alice@acme.com
71
95
 
72
- # Code-quality signal from git history + the repo-host API
73
- briar extract --company acme \
74
- --include defect-hotspots --risk-repo acme-co/acme-app \
75
- --include pr-hygiene --prhygiene-repo acme-co/acme-app \
76
- --include review-nits --nits-repo acme-co/acme-app \
77
- --include ci-health --cihealth-repo acme-co/acme-app
96
+ # Code-quality signal from git history + the repo-host API.
97
+ # One --repo feeds every selected extractor.
98
+ briar extract --company acme --repo acme-co/acme-app \
99
+ --include defect-hotspots --include pr-hygiene \
100
+ --include review-nits --include ci-health
78
101
  ```
79
102
 
80
103
  **Code-quality extractors** (all `--provider github|bitbucket`): `defect-hotspots`
@@ -89,8 +112,8 @@ briar extract --company acme \
89
112
  ```bash
90
113
  # Merge a knowledge index into CLAUDE.md; full detail lands in
91
114
  # .briar/knowledge/<company>.md for the agent to read when relevant.
92
- briar extract --company acme --include defect-hotspots --include ci-health \
93
- --risk-repo acme-co/acme-app --cihealth-repo acme-co/acme-app \
115
+ briar extract --company acme --repo acme-co/acme-app \
116
+ --include defect-hotspots --include ci-health \
94
117
  --merge-claude-md
95
118
  ```
96
119
 
@@ -162,33 +185,40 @@ Plus `briar context` (local knowledge blobs), `briar dashboard` (read-only HTML
162
185
  ### Repeatable flags — fan out across repos, projects, services
163
186
 
164
187
  Most list-style flags accept multiple occurrences: repeat the flag, once
165
- per value (there's no comma form — `--pr-repo a,b` is one repo named
166
- `a,b`). Mix them to cover a whole fleet in a single command.
188
+ per value (there's no comma form — `--repo a,b` is one repo named `a,b`).
189
+ The canonical `--repo` feeds every extractor selected with `--include`.
167
190
 
168
191
  ```bash
169
- # Mine several repos, keep the team's PRs, drop the bots, across two boards.
170
- # --pr-max applies per repo; author allow/block compose as allow ∩ ¬block.
192
+ # Mine several repos, keep the team's PRs, drop the bots one --repo,
193
+ # every selected extractor. --max applies per repo; author allow/block
194
+ # compose as allow ∩ ¬block.
171
195
  briar extract --company acme \
172
- --include pr-archaeology --include active-tickets \
173
- --tracker jira \
174
- --pr-repo acme-co/web --pr-repo acme-co/api --pr-repo acme-co/mobile \
175
- --pr-max 75 \
176
- --pr-authors-block "dependabot[bot]" --pr-authors-block "renovate[bot]" \
177
- --ticket-project ACME --ticket-project PLAT
178
-
179
- # Scaffold a triage flow from two sources, filtered by author + assignee.
180
- # Each tracker source carries its own repeatable *-authors/assignees-*.
196
+ --include pr-archaeology --include defect-hotspots \
197
+ --repo acme-co/web --repo acme-co/api --repo acme-co/mobile \
198
+ --max 75 \
199
+ --authors-block "dependabot[bot]" --authors-block "renovate[bot]"
200
+
201
+ # Scaffold a triage flow from two sources — one shared author/assignee
202
+ # filter applies to every --source.
181
203
  briar scaffold implementation --prefix acme-triage \
182
204
  --source github --source jira \
183
205
  --owner acme-co --repo acme-app --github-secret-id <uuid> \
184
- --github-authors-block "dependabot[bot]" \
185
- --github-assignees-allow alice --github-assignees-allow bob \
206
+ --authors-block "dependabot[bot]" \
207
+ --assignees-allow alice --assignees-allow bob \
186
208
  --jira-project ACME --jira-project PLAT --jira-secret-id <uuid> \
187
209
  --auth-mode pat
188
210
  ```
189
211
 
190
- The same lists map onto runbook YAML as arrays — e.g. `pr_repo:
191
- [acme-co/web, acme-co/api]` is two `--pr-repo` flags.
212
+ The same lists map onto runbook YAML as arrays — e.g. `repo:
213
+ [acme-co/web, acme-co/api]` under an extractor's `args:`.
214
+
215
+ > **Divergent identifiers in one run.** Some extractors key off a tracker
216
+ > *project* (`active-tickets`, `ticket-archaeology`) rather than an
217
+ > `owner/repo` slug. When you run those alongside repo-based extractors in
218
+ > a single invocation and they need *different* values, reach for the
219
+ > per-extractor override flags (`--ticket-project`, `--pr-repo`, … — listed
220
+ > by `briar extract --advanced-help`), or split into two invocations. The
221
+ > runbook YAML models this cleanly: one `args:` block per extractor.
192
222
 
193
223
  ### Handy patterns
194
224
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "briar-cli"
7
- version = "1.1.45"
7
+ version = "1.1.46"
8
8
  description = "Terminal client for the Briar agent-orchestration API."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -10,6 +10,11 @@ from __future__ import annotations
10
10
 
11
11
  import warnings
12
12
 
13
+ # E402 is expected here: the warnings filter below MUST run before any
14
+ # pydantic-importing module loads, so the rest of the imports follow it.
15
+ # ruff: noqa: E402
16
+
17
+
13
18
  # pydantic's plugin loader scans installed packages for plugins at import
14
19
  # time. When logfire is installed but its pinned opentelemetry-sdk symbol
15
20
  # drifts (ReadableLogRecord was renamed upstream), the loader emits a
@@ -101,6 +106,25 @@ def _build_parser(commands: Dict[str, Command]) -> argparse.ArgumentParser:
101
106
  return parser
102
107
 
103
108
 
109
+ def _warn_legacy_flags(raw_argv: List[str], log: logging.Logger) -> None:
110
+ """One consolidated stderr note when the command line uses a legacy
111
+ per-extractor / per-source flag that a canonical flag now covers.
112
+
113
+ A plain print, NOT a `warnings.warn` — the test suite runs with
114
+ `filterwarnings=error`, and this is user guidance, not a code smell."""
115
+ from briar.extract.canonical import legacy_flag_suggestions
116
+
117
+ suggestions = legacy_flag_suggestions(raw_argv)
118
+ if not suggestions:
119
+ return
120
+ pairs = ", ".join(f"{old} → {new}" for old, new in sorted(suggestions.items()))
121
+ print(
122
+ f"note: these flags are deprecated in favour of shared canonical flags: {pairs}. " "They still work; see `briar extract --advanced-help`.",
123
+ file=sys.stderr,
124
+ )
125
+ log.debug("legacy-flags: %s", pairs)
126
+
127
+
104
128
  def _install_default_journal(log: logging.Logger) -> None:
105
129
  """Install the process-wide default journal. Honours
106
130
  BRIAR_JOURNAL=off to disable entirely; otherwise wires the
@@ -197,6 +221,25 @@ def main(argv: Optional[List[str]] = None) -> int:
197
221
  commands = CommandRegistry.build()
198
222
  parser = _build_parser(commands)
199
223
 
224
+ # Fold project config (.briar.toml / [tool.briar]) + env into the
225
+ # parser defaults so a bare command inherits stable values (company,
226
+ # store, repo, model, …) and explicit flags still override. Skipped
227
+ # for help/usage so `briar -h` touches no config file.
228
+ if not metadata_only:
229
+ from briar.config import apply_config_defaults, load_project_config
230
+
231
+ satisfied = apply_config_defaults(parser, load_project_config())
232
+ if satisfied:
233
+ log.debug("config: satisfied defaults for %s", sorted(set(satisfied)))
234
+
235
+ # Below config in the precedence chain: infer --owner/--repo from
236
+ # the local git `origin` remote for whatever config didn't supply.
237
+ from briar.infer import apply_inference_defaults
238
+
239
+ inferred = apply_inference_defaults(parser, satisfied)
240
+ if inferred:
241
+ log.debug("infer: filled %s from git remote", sorted(set(inferred)))
242
+
200
243
  normalised: List[str] = []
201
244
  for flag, value in kv.items():
202
245
  normalised.extend([flag, value])
@@ -205,6 +248,8 @@ def main(argv: Optional[List[str]] = None) -> int:
205
248
  args = parser.parse_args(normalised)
206
249
  log.debug("dispatching command=%s args=%r", args.command, vars(args))
207
250
 
251
+ _warn_legacy_flags(raw_argv, log)
252
+
208
253
  # Wrap dispatch in a telemetry span so duration + outcome land
209
254
  # in one place. The span captures uncaught exceptions, scrubs
210
255
  # them, and ships an error event — then re-raises into the
@@ -12,6 +12,7 @@ from briar.commands.base import Command
12
12
  from briar.errors import CliError
13
13
  from briar.extract import EXTRACTORS
14
14
  from briar.extract.base import ExtractedSection
15
+ from briar.extract.canonical import AdvancedHelpAction, apply_canonical, hide_canonicalised_flags, register_canonical_flags
15
16
  from briar.extract.claude_md import ClaudeMdMerger
16
17
  from briar.extract.composer import render_json, render_markdown
17
18
  from briar.storage import KNOWLEDGE_STORE_NAMES, make_store
@@ -46,8 +47,12 @@ class CommandExtract(Command):
46
47
  choices=sorted(EXTRACTORS.keys()),
47
48
  help="Which extractor(s) to run (repeatable; default: all available)",
48
49
  )
50
+ # `--store` is the name every other command uses; `--storage` is
51
+ # kept as an alias so existing scripts keep working.
49
52
  parser.add_argument(
53
+ "--store",
50
54
  "--storage",
55
+ dest="storage",
51
56
  default="file",
52
57
  choices=list(KNOWLEDGE_STORE_NAMES),
53
58
  help="Where to write the result (default: file)",
@@ -65,8 +70,20 @@ class CommandExtract(Command):
65
70
  default="./CLAUDE.md",
66
71
  help="CLAUDE.md to merge the knowledge index into (only used with --merge-claude-md)",
67
72
  )
73
+ parser.add_argument(
74
+ "--advanced-help",
75
+ action=AdvancedHelpAction,
76
+ help="Show the full per-extractor override flags and exit.",
77
+ )
78
+ # Canonical flags first (the headline surface), then the
79
+ # per-extractor private flags. The private flags stay registered
80
+ # for back-compat + the rare same-invocation-divergent case, but
81
+ # `hide_canonicalised_flags` suppresses the redundant ones from
82
+ # `-h` so the default help shows just the canonical + core knobs.
83
+ register_canonical_flags(parser)
68
84
  for ext in EXTRACTORS.values():
69
85
  ext.add_arguments(parser)
86
+ hide_canonicalised_flags(parser)
70
87
 
71
88
  def run(self, args: argparse.Namespace) -> int:
72
89
  selected = args.include or list(EXTRACTORS.keys())
@@ -74,6 +91,9 @@ class CommandExtract(Command):
74
91
  sections: List[ExtractedSection] = []
75
92
  for name in selected:
76
93
  ext = EXTRACTORS[name]
94
+ # Fan the canonical flags (--repo, --max, …) out to this
95
+ # extractor's private dests before availability / extraction.
96
+ apply_canonical(args, ext)
77
97
  if not ext.is_available(args):
78
98
  print(f" skipped {name} (not available in this env)")
79
99
  continue
@@ -0,0 +1,208 @@
1
+ """Project config — `.briar.toml` (or `[tool.briar]` in pyproject.toml).
2
+
3
+ Most flags repeat the same stable values on every invocation: the
4
+ company, the store backend, the repo owner/slug, the agent model, the
5
+ git identity. This module lets a project declare them once so the
6
+ day-to-day command stops carrying them.
7
+
8
+ Resolution precedence, highest first:
9
+
10
+ CLI flag > env var > project config > built-in default
11
+
12
+ The mechanism is deliberately boring: `apply_config_defaults` rewrites
13
+ each matching argparse action's `default` (and clears `required` when a
14
+ value is found) BEFORE parsing, so an explicit CLI flag still wins by the
15
+ normal argparse rule "an explicitly-passed option overrides its default".
16
+
17
+ Config layout (`.briar.toml` keys are top-level; in pyproject.toml they
18
+ live under `[tool.briar]`):
19
+
20
+ company = "acme"
21
+ store = "postgres"
22
+ root = "./knowledge"
23
+ tracker = "jira"
24
+
25
+ [repo]
26
+ owner = "acme-co"
27
+ repo = "acme-app"
28
+ provider = "github"
29
+
30
+ [agent]
31
+ model = "claude-sonnet-4-6"
32
+ git_user_name = "acme-bot"
33
+ git_user_email = "bot@acme.com"
34
+ """
35
+
36
+ from __future__ import annotations
37
+
38
+ import argparse
39
+ import logging
40
+ import os
41
+ import tomllib
42
+ from dataclasses import dataclass
43
+ from pathlib import Path
44
+ from typing import Dict, List, Optional, Tuple
45
+
46
+ log = logging.getLogger(__name__)
47
+
48
+ _CONFIG_FILENAME = ".briar.toml"
49
+ _PYPROJECT = "pyproject.toml"
50
+
51
+
52
+ @dataclass(frozen=True)
53
+ class _ConfigSpec:
54
+ """One config-satisfiable flag: the argparse dest it fills, the env
55
+ var that overrides config, and the (section, key) path into the
56
+ config dict. A top-level key uses section=""."""
57
+
58
+ dest: str
59
+ env: Optional[str]
60
+ section: str
61
+ key: str
62
+
63
+
64
+ # The flags a project config / env may satisfy. `storage` is extract's
65
+ # dest for the store backend (aliased --store); `store` covers every
66
+ # other command. `knowledge` is agent's file-root dest, fed by the same
67
+ # `root` config key.
68
+ _CONFIG_SPECS: Tuple[_ConfigSpec, ...] = (
69
+ _ConfigSpec("company", "BRIAR_COMPANY", "", "company"),
70
+ _ConfigSpec("store", "BRIAR_DEFAULT_STORE", "", "store"),
71
+ _ConfigSpec("storage", "BRIAR_DEFAULT_STORE", "", "store"),
72
+ _ConfigSpec("root", None, "", "root"),
73
+ _ConfigSpec("knowledge", None, "", "root"),
74
+ _ConfigSpec("tracker", None, "", "tracker"),
75
+ _ConfigSpec("owner", None, "repo", "owner"),
76
+ _ConfigSpec("repo", None, "repo", "repo"),
77
+ _ConfigSpec("provider", None, "repo", "provider"),
78
+ _ConfigSpec("model", None, "agent", "model"),
79
+ _ConfigSpec("git_user_name", None, "agent", "git_user_name"),
80
+ _ConfigSpec("git_user_email", None, "agent", "git_user_email"),
81
+ )
82
+
83
+
84
+ def find_config_file(start: Optional[Path] = None) -> Optional[Path]:
85
+ """Nearest `.briar.toml` or pyproject.toml carrying `[tool.briar]`,
86
+ searching from `start` (default cwd) up to the filesystem root.
87
+ Returns None when neither is found."""
88
+ here = (start or Path.cwd()).resolve()
89
+ for directory in [here, *here.parents]:
90
+ dedicated = directory / _CONFIG_FILENAME
91
+ if dedicated.is_file():
92
+ return dedicated
93
+ pyproject = directory / _PYPROJECT
94
+ if pyproject.is_file() and _has_tool_briar(pyproject):
95
+ return pyproject
96
+ return None
97
+
98
+
99
+ def _has_tool_briar(pyproject: Path) -> bool:
100
+ try:
101
+ with pyproject.open("rb") as handle:
102
+ return "briar" in tomllib.load(handle).get("tool", {})
103
+ except (OSError, tomllib.TOMLDecodeError):
104
+ return False
105
+
106
+
107
+ def load_project_config(start: Optional[Path] = None) -> Dict[str, object]:
108
+ """The briar config section as a dict, or {} when no config file is
109
+ found / it cannot be parsed. For `.briar.toml` the whole file is the
110
+ section; for pyproject.toml it is `[tool.briar]`."""
111
+ path = find_config_file(start)
112
+ if path is None:
113
+ return {}
114
+ try:
115
+ with path.open("rb") as handle:
116
+ data = tomllib.load(handle)
117
+ except (OSError, tomllib.TOMLDecodeError) as exc:
118
+ log.warning("config: failed to read %s — ignoring (%s)", path, exc)
119
+ return {}
120
+ if path.name == _PYPROJECT:
121
+ return dict(data.get("tool", {}).get("briar", {}))
122
+ return dict(data)
123
+
124
+
125
+ def _config_value(config: Dict[str, object], spec: _ConfigSpec) -> Optional[object]:
126
+ if spec.section:
127
+ section = config.get(spec.section)
128
+ if not isinstance(section, dict):
129
+ return None
130
+ return section.get(spec.key)
131
+ return config.get(spec.key)
132
+
133
+
134
+ def _resolve(spec: _ConfigSpec, config: Dict[str, object]) -> Optional[object]:
135
+ """env wins over config; None when neither provides a value."""
136
+ if spec.env:
137
+ env_value = os.environ.get(spec.env)
138
+ if env_value:
139
+ return env_value
140
+ return _config_value(config, spec)
141
+
142
+
143
+ def _iter_subparsers(parser: argparse.ArgumentParser):
144
+ """Yield every (sub)parser in the tree, including the root."""
145
+ yield parser
146
+ for action in parser._actions:
147
+ if isinstance(action, argparse._SubParsersAction):
148
+ for sub in action.choices.values():
149
+ yield from _iter_subparsers(sub)
150
+
151
+
152
+ def _derive_repo_slug(config: Dict[str, object]) -> Optional[str]:
153
+ """`owner/repo` from the `[repo]` section, or None if incomplete."""
154
+ section = config.get("repo")
155
+ if not isinstance(section, dict):
156
+ return None
157
+ owner, repo = section.get("owner"), section.get("repo")
158
+ if owner and repo:
159
+ return f"{owner}/{repo}"
160
+ return None
161
+
162
+
163
+ def _repo_list_value(config: Dict[str, object]) -> Optional[List[str]]:
164
+ """Value for an append-style `--repo` (the canonical extract flag),
165
+ which wants a list of `owner/repo` slugs: prefer an explicit `repos`
166
+ array, else the single slug derived from `[repo]`."""
167
+ repos = config.get("repos")
168
+ if isinstance(repos, list) and repos:
169
+ return [str(r) for r in repos]
170
+ slug = _derive_repo_slug(config)
171
+ return [slug] if slug else None
172
+
173
+
174
+ def _value_for_action(action: argparse.Action, config: Dict[str, object]) -> Optional[object]:
175
+ """The config/env value appropriate to this action, or None when the
176
+ config does not speak to it. Shape-aware: an append `--repo` gets a
177
+ list of slugs, a scalar `--repo` gets the bare repo name."""
178
+ if action.dest == "repo" and isinstance(action, argparse._AppendAction):
179
+ return _repo_list_value(config)
180
+ for spec in _CONFIG_SPECS:
181
+ if spec.dest == action.dest:
182
+ value = _resolve(spec, config)
183
+ if value is not None:
184
+ return value
185
+ return None
186
+
187
+
188
+ def apply_config_defaults(
189
+ parser: argparse.ArgumentParser,
190
+ config: Optional[Dict[str, object]] = None,
191
+ ) -> List[str]:
192
+ """Fold env + project config into the parser as new defaults so a
193
+ bare command inherits them and an explicit flag still overrides.
194
+
195
+ Mutates matching actions' `default` and clears their `required` when
196
+ a value is found. Returns the list of dests that were satisfied (for
197
+ logging / tests)."""
198
+ resolved = {} if config is None else config
199
+ satisfied: List[str] = []
200
+ for sub in _iter_subparsers(parser):
201
+ for action in sub._actions:
202
+ value = _value_for_action(action, resolved)
203
+ if value is None:
204
+ continue
205
+ action.default = value
206
+ action.required = False
207
+ satisfied.append(action.dest)
208
+ return satisfied