devcouncil 0.3.1 → 0.4.1

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 (366) hide show
  1. package/README.md +92 -33
  2. package/package.json +6 -2
  3. package/packages/codeintel-grammars/hatch_build.py +43 -0
  4. package/packages/codeintel-grammars/pyproject.toml +16 -0
  5. package/packages/codeintel-grammars/src/devcouncil_codeintel_grammars/__init__.py +93 -0
  6. package/pyproject.toml +99 -4
  7. package/src/devcouncil/app/config.py +512 -20
  8. package/src/devcouncil/app/events.py +4 -23
  9. package/src/devcouncil/app/orchestrator.py +5 -0
  10. package/src/devcouncil/app/run_context.py +3 -3
  11. package/src/devcouncil/assets/__init__.py +4 -1
  12. package/src/devcouncil/assets/vendor/force-graph.min.js +5 -0
  13. package/src/devcouncil/campaign/__init__.py +71 -0
  14. package/src/devcouncil/campaign/bloom.py +137 -0
  15. package/src/devcouncil/campaign/dashboard.py +123 -0
  16. package/src/devcouncil/campaign/mailbox.py +305 -0
  17. package/src/devcouncil/campaign/notify.py +91 -0
  18. package/src/devcouncil/campaign/orchestrator.py +592 -0
  19. package/src/devcouncil/campaign/prompts/coordinator.md +29 -0
  20. package/src/devcouncil/campaign/prompts/director.md +21 -0
  21. package/src/devcouncil/campaign/prompts/protocol.md +46 -0
  22. package/src/devcouncil/campaign/prompts/reviewer.md +24 -0
  23. package/src/devcouncil/campaign/prompts/worker.md +24 -0
  24. package/src/devcouncil/campaign/roles.py +202 -0
  25. package/src/devcouncil/campaign/watcher.py +153 -0
  26. package/src/devcouncil/cli/commands/agents.py +24 -17
  27. package/src/devcouncil/cli/commands/artifacts.py +36 -27
  28. package/src/devcouncil/cli/commands/ast.py +12 -3
  29. package/src/devcouncil/cli/commands/baseline.py +21 -12
  30. package/src/devcouncil/cli/commands/boot.py +218 -0
  31. package/src/devcouncil/cli/commands/campaign.py +302 -0
  32. package/src/devcouncil/cli/commands/check.py +225 -12
  33. package/src/devcouncil/cli/commands/config.py +221 -74
  34. package/src/devcouncil/cli/commands/cost.py +137 -28
  35. package/src/devcouncil/cli/commands/dashboard.py +12 -4
  36. package/src/devcouncil/cli/commands/debug_cmd.py +249 -0
  37. package/src/devcouncil/cli/commands/design.py +27 -17
  38. package/src/devcouncil/cli/commands/doctor.py +790 -8
  39. package/src/devcouncil/cli/commands/evidence.py +41 -20
  40. package/src/devcouncil/cli/commands/export.py +73 -0
  41. package/src/devcouncil/cli/commands/gaps.py +175 -0
  42. package/src/devcouncil/cli/commands/gated_write.py +76 -0
  43. package/src/devcouncil/cli/commands/go.py +220 -68
  44. package/src/devcouncil/cli/commands/graph_cmd.py +1192 -0
  45. package/src/devcouncil/cli/commands/handoff.py +45 -34
  46. package/src/devcouncil/cli/commands/hook.py +630 -85
  47. package/src/devcouncil/cli/commands/init.py +89 -30
  48. package/src/devcouncil/cli/commands/integrate.py +296 -1385
  49. package/src/devcouncil/cli/commands/lease.py +120 -0
  50. package/src/devcouncil/cli/commands/logs.py +12 -5
  51. package/src/devcouncil/cli/commands/lsp.py +40 -5
  52. package/src/devcouncil/cli/commands/map.py +317 -74
  53. package/src/devcouncil/cli/commands/mcp_server.py +12 -2
  54. package/src/devcouncil/cli/commands/okf.py +44 -6
  55. package/src/devcouncil/cli/commands/plan.py +184 -69
  56. package/src/devcouncil/cli/commands/prompt.py +26 -17
  57. package/src/devcouncil/cli/commands/provenance.py +79 -0
  58. package/src/devcouncil/cli/commands/repair.py +60 -49
  59. package/src/devcouncil/cli/commands/report.py +148 -40
  60. package/src/devcouncil/cli/commands/requirements.py +104 -0
  61. package/src/devcouncil/cli/commands/reset_demo_state.py +13 -4
  62. package/src/devcouncil/cli/commands/rollback.py +46 -35
  63. package/src/devcouncil/cli/commands/run.py +173 -8
  64. package/src/devcouncil/cli/commands/runs.py +298 -68
  65. package/src/devcouncil/cli/commands/scaffold.py +33 -12
  66. package/src/devcouncil/cli/commands/semantic.py +29 -14
  67. package/src/devcouncil/cli/commands/setup.py +103 -93
  68. package/src/devcouncil/cli/commands/shell.py +51 -42
  69. package/src/devcouncil/cli/commands/show.py +56 -42
  70. package/src/devcouncil/cli/commands/skills.py +29 -20
  71. package/src/devcouncil/cli/commands/status.py +80 -67
  72. package/src/devcouncil/cli/commands/task_gate.py +295 -0
  73. package/src/devcouncil/cli/commands/tasks.py +248 -19
  74. package/src/devcouncil/cli/commands/trace.py +14 -8
  75. package/src/devcouncil/cli/commands/verify.py +33 -8
  76. package/src/devcouncil/cli/commands/version.py +14 -6
  77. package/src/devcouncil/cli/commands/watch.py +56 -40
  78. package/src/devcouncil/cli/commands/watch_fs.py +30 -19
  79. package/src/devcouncil/cli/commands/wiki.py +278 -0
  80. package/src/devcouncil/cli/main.py +58 -1
  81. package/src/devcouncil/codeintel/__init__.py +16 -0
  82. package/src/devcouncil/codeintel/build_control.py +429 -0
  83. package/src/devcouncil/codeintel/build_worker.py +78 -0
  84. package/src/devcouncil/codeintel/debug/__init__.py +17 -0
  85. package/src/devcouncil/codeintel/debug/broker.py +114 -0
  86. package/src/devcouncil/codeintel/debug/broker_client.py +61 -0
  87. package/src/devcouncil/codeintel/debug/consent.py +36 -0
  88. package/src/devcouncil/codeintel/debug/discovery.py +132 -0
  89. package/src/devcouncil/codeintel/debug/fingerprint.py +85 -0
  90. package/src/devcouncil/codeintel/debug/protocol.py +259 -0
  91. package/src/devcouncil/codeintel/debug/python_trace_runner.py +81 -0
  92. package/src/devcouncil/codeintel/debug/session.py +238 -0
  93. package/src/devcouncil/codeintel/debug/tracing.py +201 -0
  94. package/src/devcouncil/codeintel/languages/__init__.py +17 -0
  95. package/src/devcouncil/codeintel/languages/generic_extractor.py +236 -0
  96. package/src/devcouncil/codeintel/languages/registry.py +149 -0
  97. package/src/devcouncil/codeintel/languages/workers.py +245 -0
  98. package/src/devcouncil/codeintel/query/__init__.py +5 -0
  99. package/src/devcouncil/codeintel/query/engine.py +289 -0
  100. package/src/devcouncil/codeintel/resolution/__init__.py +6 -0
  101. package/src/devcouncil/codeintel/resolution/abstract_state.py +301 -0
  102. package/src/devcouncil/codeintel/resolution/frameworks/__init__.py +33 -0
  103. package/src/devcouncil/codeintel/resolution/frameworks/base.py +46 -0
  104. package/src/devcouncil/codeintel/resolution/frameworks/di.py +56 -0
  105. package/src/devcouncil/codeintel/resolution/frameworks/events.py +45 -0
  106. package/src/devcouncil/codeintel/resolution/frameworks/routes.py +88 -0
  107. package/src/devcouncil/codeintel/resolution/semantic.py +887 -0
  108. package/src/devcouncil/codeintel/service.py +104 -0
  109. package/src/devcouncil/codeintel/store/__init__.py +15 -0
  110. package/src/devcouncil/codeintel/store/sqlite.py +1565 -0
  111. package/src/devcouncil/codeintel/sync/__init__.py +19 -0
  112. package/src/devcouncil/codeintel/sync/coordinator.py +430 -0
  113. package/src/devcouncil/codeintel/sync/incremental.py +484 -0
  114. package/src/devcouncil/codeintel/sync/lease.py +96 -0
  115. package/src/devcouncil/codeintel/sync/scope.py +98 -0
  116. package/src/devcouncil/council/__init__.py +4 -0
  117. package/src/devcouncil/council/prompts/__init__.py +4 -0
  118. package/src/devcouncil/domain/checkpoint_refs.py +17 -0
  119. package/src/devcouncil/domain/evidence.py +1 -0
  120. package/src/devcouncil/domain/gap.py +10 -0
  121. package/src/devcouncil/domain/requirement.py +5 -1
  122. package/src/devcouncil/domain/task.py +43 -2
  123. package/src/devcouncil/execution/checkpoints.py +25 -31
  124. package/src/devcouncil/execution/context_builder.py +15 -44
  125. package/src/devcouncil/execution/fs_watcher.py +64 -0
  126. package/src/devcouncil/execution/gated_write.py +203 -0
  127. package/src/devcouncil/execution/handoff.py +2 -1
  128. package/src/devcouncil/execution/hook_policy.py +19 -5
  129. package/src/devcouncil/execution/lease_ops.py +177 -0
  130. package/src/devcouncil/execution/lease_validation.py +71 -0
  131. package/src/devcouncil/execution/patch.py +3 -0
  132. package/src/devcouncil/execution/permissions.py +1 -0
  133. package/src/devcouncil/execution/policy_engine.py +205 -10
  134. package/src/devcouncil/execution/prompt_builder.py +278 -33
  135. package/src/devcouncil/execution/run_trace.py +356 -0
  136. package/src/devcouncil/execution/shell_session.py +46 -5
  137. package/src/devcouncil/execution/stop_gate.py +746 -0
  138. package/src/devcouncil/execution/stop_gate_history.py +113 -0
  139. package/src/devcouncil/execution/stop_gate_state.py +54 -0
  140. package/src/devcouncil/execution/stop_gate_verify_cache.py +69 -0
  141. package/src/devcouncil/execution/task_gate_ops.py +590 -0
  142. package/src/devcouncil/execution/task_runner.py +19 -0
  143. package/src/devcouncil/executors/advisor_tool.py +315 -0
  144. package/src/devcouncil/executors/agent_registry.py +125 -17
  145. package/src/devcouncil/executors/claude_sdk.py +376 -0
  146. package/src/devcouncil/executors/coding_cli.py +724 -25
  147. package/src/devcouncil/executors/mini_swe.py +50 -8
  148. package/src/devcouncil/executors/native/agent.py +224 -19
  149. package/src/devcouncil/executors/openhands.py +50 -8
  150. package/src/devcouncil/executors/transient_retry.py +99 -0
  151. package/src/devcouncil/gating/checks/clean_git.py +5 -2
  152. package/src/devcouncil/gating/checks/planned_files_check.py +38 -11
  153. package/src/devcouncil/gating/checks/secret_scan_check.py +2 -2
  154. package/src/devcouncil/gating/policy.py +46 -2
  155. package/src/devcouncil/indexing/ast_matcher.py +41 -4
  156. package/src/devcouncil/indexing/graph/__init__.py +78 -0
  157. package/src/devcouncil/indexing/graph/api_routes.py +522 -0
  158. package/src/devcouncil/indexing/graph/build.py +862 -0
  159. package/src/devcouncil/indexing/graph/cache.py +329 -0
  160. package/src/devcouncil/indexing/graph/communities.py +28 -0
  161. package/src/devcouncil/indexing/graph/cypher.py +107 -0
  162. package/src/devcouncil/indexing/graph/embeddings.py +194 -0
  163. package/src/devcouncil/indexing/graph/export.py +381 -0
  164. package/src/devcouncil/indexing/graph/export_links.py +81 -0
  165. package/src/devcouncil/indexing/graph/extract_python.py +307 -0
  166. package/src/devcouncil/indexing/graph/extract_ts.py +1205 -0
  167. package/src/devcouncil/indexing/graph/intel.py +668 -0
  168. package/src/devcouncil/indexing/graph/liveness.py +992 -0
  169. package/src/devcouncil/indexing/graph/okf_export.py +65 -0
  170. package/src/devcouncil/indexing/graph/pdg/__init__.py +67 -0
  171. package/src/devcouncil/indexing/graph/pdg/build.py +11 -0
  172. package/src/devcouncil/indexing/graph/pdg/cdg.py +41 -0
  173. package/src/devcouncil/indexing/graph/pdg/cfg.py +199 -0
  174. package/src/devcouncil/indexing/graph/pdg/query.py +21 -0
  175. package/src/devcouncil/indexing/graph/pdg/reaching_def.py +126 -0
  176. package/src/devcouncil/indexing/graph/pdg/schema.py +253 -0
  177. package/src/devcouncil/indexing/graph/pdg/taint.py +154 -0
  178. package/src/devcouncil/indexing/graph/query.py +302 -0
  179. package/src/devcouncil/indexing/graph/resolve.py +1020 -0
  180. package/src/devcouncil/indexing/graph/schema.py +103 -0
  181. package/src/devcouncil/indexing/graph_index.py +20 -29
  182. package/src/devcouncil/indexing/lsp.py +57 -25
  183. package/src/devcouncil/indexing/lsp_client.py +577 -0
  184. package/src/devcouncil/indexing/map_artifacts.py +355 -0
  185. package/src/devcouncil/indexing/map_refresh.py +141 -0
  186. package/src/devcouncil/indexing/repo_mapper.py +1509 -138
  187. package/src/devcouncil/indexing/semantic_index.py +12 -6
  188. package/src/devcouncil/indexing/subsystem_map.py +163 -0
  189. package/src/devcouncil/indexing/ts_imports.py +343 -0
  190. package/src/devcouncil/indexing/viz.py +964 -0
  191. package/src/devcouncil/indexing/walk.py +52 -0
  192. package/src/devcouncil/indexing/wiring.py +1776 -0
  193. package/src/devcouncil/integrations/actions.py +27 -4
  194. package/src/devcouncil/integrations/check.py +211 -16
  195. package/src/devcouncil/integrations/claude_assets.py +209 -12
  196. package/src/devcouncil/integrations/clients/__init__.py +1 -0
  197. package/src/devcouncil/integrations/clients/aider.py +52 -0
  198. package/src/devcouncil/integrations/clients/antigravity.py +87 -0
  199. package/src/devcouncil/integrations/clients/claude.py +339 -0
  200. package/src/devcouncil/integrations/clients/codex.py +39 -0
  201. package/src/devcouncil/integrations/clients/common.py +332 -0
  202. package/src/devcouncil/integrations/clients/cursor.py +164 -0
  203. package/src/devcouncil/integrations/clients/gemini.py +49 -0
  204. package/src/devcouncil/integrations/clients/grok.py +105 -0
  205. package/src/devcouncil/integrations/clients/hooks.py +500 -0
  206. package/src/devcouncil/integrations/clients/opencode.py +96 -0
  207. package/src/devcouncil/integrations/clients/warp.py +75 -0
  208. package/src/devcouncil/integrations/code_review_graph.py +2 -2
  209. package/src/devcouncil/integrations/github.py +73 -7
  210. package/src/devcouncil/integrations/integration_cli.py +197 -0
  211. package/src/devcouncil/integrations/mcp/handlers/__init__.py +1 -0
  212. package/src/devcouncil/integrations/mcp/handlers/ast_lsp.py +77 -0
  213. package/src/devcouncil/integrations/mcp/handlers/checkout.py +50 -0
  214. package/src/devcouncil/integrations/mcp/handlers/cli_gate.py +43 -0
  215. package/src/devcouncil/integrations/mcp/handlers/codeintel.py +182 -0
  216. package/src/devcouncil/integrations/mcp/handlers/debug.py +236 -0
  217. package/src/devcouncil/integrations/mcp/handlers/evidence.py +70 -0
  218. package/src/devcouncil/integrations/mcp/handlers/git.py +281 -0
  219. package/src/devcouncil/integrations/mcp/handlers/graph.py +34 -0
  220. package/src/devcouncil/integrations/mcp/handlers/handoff.py +53 -0
  221. package/src/devcouncil/integrations/mcp/handlers/knowledge.py +28 -0
  222. package/src/devcouncil/integrations/mcp/handlers/lease.py +70 -0
  223. package/src/devcouncil/integrations/mcp/handlers/live.py +108 -0
  224. package/src/devcouncil/integrations/mcp/handlers/map.py +676 -0
  225. package/src/devcouncil/integrations/mcp/handlers/next_task.py +35 -0
  226. package/src/devcouncil/integrations/mcp/handlers/policy.py +80 -0
  227. package/src/devcouncil/integrations/mcp/handlers/prompts.py +168 -0
  228. package/src/devcouncil/integrations/mcp/handlers/provenance.py +87 -0
  229. package/src/devcouncil/integrations/mcp/handlers/read.py +103 -0
  230. package/src/devcouncil/integrations/mcp/handlers/router_cache.py +53 -0
  231. package/src/devcouncil/integrations/mcp/handlers/run.py +53 -0
  232. package/src/devcouncil/integrations/mcp/handlers/runs.py +69 -0
  233. package/src/devcouncil/integrations/mcp/handlers/scope.py +56 -0
  234. package/src/devcouncil/integrations/mcp/handlers/status.py +199 -0
  235. package/src/devcouncil/integrations/mcp/handlers/task.py +88 -0
  236. package/src/devcouncil/integrations/mcp/handlers/tool_specs.py +922 -0
  237. package/src/devcouncil/integrations/mcp/handlers/trace.py +65 -0
  238. package/src/devcouncil/integrations/mcp/handlers/verify.py +45 -0
  239. package/src/devcouncil/integrations/mcp/handlers/wiki.py +53 -0
  240. package/src/devcouncil/integrations/mcp/handlers/write.py +69 -0
  241. package/src/devcouncil/integrations/mcp/server.py +265 -2391
  242. package/src/devcouncil/integrations/mcp/util.py +325 -0
  243. package/src/devcouncil/integrations/setup.py +152 -0
  244. package/src/devcouncil/knowledge/fetch.py +4 -0
  245. package/src/devcouncil/knowledge/knowledge_select.py +38 -0
  246. package/src/devcouncil/knowledge/okf.py +2 -1
  247. package/src/devcouncil/knowledge/resource_discovery.py +40 -0
  248. package/src/devcouncil/knowledge/wiki.py +643 -0
  249. package/src/devcouncil/knowledge/wiki_read.py +87 -0
  250. package/src/devcouncil/live/cards.py +7 -7
  251. package/src/devcouncil/live/models.py +4 -1
  252. package/src/devcouncil/live/reviewer.py +90 -11
  253. package/src/devcouncil/live/signals.py +4 -2
  254. package/src/devcouncil/live/summary.py +21 -3
  255. package/src/devcouncil/live/tasks.py +12 -3
  256. package/src/devcouncil/live/transcripts.py +69 -2
  257. package/src/devcouncil/llm/cache.py +5 -6
  258. package/src/devcouncil/llm/model_defaults.yaml +10 -10
  259. package/src/devcouncil/llm/provider.py +647 -73
  260. package/src/devcouncil/llm/router.py +271 -46
  261. package/src/devcouncil/llm/semantic_bridge.py +614 -0
  262. package/src/devcouncil/optimization/gepa_agent.py +6 -4
  263. package/src/devcouncil/optimization/skillopt.py +9 -5
  264. package/src/devcouncil/planning/arbiter_service.py +12 -3
  265. package/src/devcouncil/planning/correction_manifest.py +107 -10
  266. package/src/devcouncil/planning/plan_difficulty.py +69 -0
  267. package/src/devcouncil/planning/plan_service.py +5 -2
  268. package/src/devcouncil/planning/planned_files_reconcile.py +191 -0
  269. package/src/devcouncil/planning/prompt_enhancer_service.py +6 -5
  270. package/src/devcouncil/planning/question_conversion.py +56 -0
  271. package/src/devcouncil/planning/spec_service.py +9 -3
  272. package/src/devcouncil/repo/ci_scaffold.py +197 -1
  273. package/src/devcouncil/repo/gitignore.py +1 -2
  274. package/src/devcouncil/reporting/evidence_export.py +124 -0
  275. package/src/devcouncil/reporting/evidence_html.py +210 -0
  276. package/src/devcouncil/reporting/json_report.py +16 -12
  277. package/src/devcouncil/reporting/markdown_report.py +38 -9
  278. package/src/devcouncil/reporting/mcp_resources.py +142 -0
  279. package/src/devcouncil/reporting/report_builder.py +40 -4
  280. package/src/devcouncil/reporting/task_provenance.py +42 -0
  281. package/src/devcouncil/reporting/verdict.py +75 -0
  282. package/src/devcouncil/skills/library/README.md +1 -0
  283. package/src/devcouncil/skills/library/devcouncil-hero-loop.md +109 -0
  284. package/src/devcouncil/skills/library/devcouncil-verification.md +109 -0
  285. package/src/devcouncil/skills/library/devcouncil.md +93 -0
  286. package/src/devcouncil/skills/registry.py +43 -12
  287. package/src/devcouncil/storage/db.py +57 -11
  288. package/src/devcouncil/storage/models.py +6 -0
  289. package/src/devcouncil/storage/native.py +5 -3
  290. package/src/devcouncil/storage/repositories.py +50 -18
  291. package/src/devcouncil/telemetry/context.py +28 -0
  292. package/src/devcouncil/telemetry/cost.py +4 -5
  293. package/src/devcouncil/telemetry/logging_setup.py +78 -11
  294. package/src/devcouncil/telemetry/model_pricing.yaml +7 -0
  295. package/src/devcouncil/telemetry/stages.py +27 -2
  296. package/src/devcouncil/telemetry/tracker.py +50 -13
  297. package/src/devcouncil/ui/dashboard.py +120 -8
  298. package/src/devcouncil/utils/fsio.py +58 -0
  299. package/src/devcouncil/utils/git_snapshot.py +112 -0
  300. package/src/devcouncil/utils/json_persist.py +53 -0
  301. package/src/devcouncil/utils/proc.py +89 -0
  302. package/src/devcouncil/verification/acceptance_compiler.py +36 -13
  303. package/src/devcouncil/verification/ad_hoc_check.py +95 -3
  304. package/src/devcouncil/verification/checks/__init__.py +41 -0
  305. package/src/devcouncil/verification/checks/acceptance.py +39 -0
  306. package/src/devcouncil/verification/checks/acceptance_corpus.py +194 -0
  307. package/src/devcouncil/verification/checks/acceptance_evidence.py +239 -0
  308. package/src/devcouncil/verification/checks/command_evidence.py +148 -0
  309. package/src/devcouncil/verification/checks/compiled_acceptance.py +179 -0
  310. package/src/devcouncil/verification/checks/corpus_stale.py +124 -0
  311. package/src/devcouncil/verification/checks/corpus_verification.py +9 -0
  312. package/src/devcouncil/verification/checks/dead_symbols.py +360 -0
  313. package/src/devcouncil/verification/checks/diff_coverage_gate.py +101 -0
  314. package/src/devcouncil/verification/checks/doc_code_ref.py +79 -0
  315. package/src/devcouncil/verification/checks/liveness_ratchet.py +336 -0
  316. package/src/devcouncil/verification/checks/orphan_diff.py +104 -0
  317. package/src/devcouncil/verification/checks/planned_files.py +98 -0
  318. package/src/devcouncil/verification/checks/semantic_diff.py +241 -0
  319. package/src/devcouncil/verification/checks/stale_map.py +80 -0
  320. package/src/devcouncil/verification/checks/stub_scan.py +71 -0
  321. package/src/devcouncil/verification/checks/subsystem_boundary.py +103 -0
  322. package/src/devcouncil/verification/checks/wiring.py +216 -0
  323. package/src/devcouncil/verification/claims/__init__.py +23 -0
  324. package/src/devcouncil/verification/claims/checks.py +395 -0
  325. package/src/devcouncil/verification/claims/mapper.py +168 -0
  326. package/src/devcouncil/verification/claims/models.py +39 -0
  327. package/src/devcouncil/verification/claims/transcript.py +92 -0
  328. package/src/devcouncil/verification/claims/verdict.py +88 -0
  329. package/src/devcouncil/verification/command_evidence.py +170 -0
  330. package/src/devcouncil/verification/command_malformation.py +147 -0
  331. package/src/devcouncil/verification/command_runner.py +164 -0
  332. package/src/devcouncil/verification/coverage_measurement.py +292 -0
  333. package/src/devcouncil/verification/diff_coverage.py +151 -0
  334. package/src/devcouncil/verification/difficulty.py +296 -0
  335. package/src/devcouncil/verification/effort_heuristics.py +178 -0
  336. package/src/devcouncil/verification/gap_ids.py +63 -0
  337. package/src/devcouncil/verification/gate_cache.py +194 -0
  338. package/src/devcouncil/verification/gate_selector.py +344 -0
  339. package/src/devcouncil/verification/git_diff_fallback.py +272 -0
  340. package/src/devcouncil/verification/implementation_reviewer.py +13 -0
  341. package/src/devcouncil/verification/incremental_check.py +241 -0
  342. package/src/devcouncil/verification/next_actions.py +60 -1
  343. package/src/devcouncil/verification/rigor_analytics.py +130 -0
  344. package/src/devcouncil/verification/sandbox.py +38 -11
  345. package/src/devcouncil/verification/stub_detector.py +369 -0
  346. package/src/devcouncil/verification/test_resolver.py +67 -1
  347. package/src/devcouncil/verification/verifier.py +137 -1666
  348. package/src/devcouncil/verification/verify_orchestration.py +610 -0
  349. package/src/devcouncil/verification/verify_setup.py +176 -0
  350. package/src/devcouncil/verification/wiki_refresh.py +208 -0
  351. package/src/semantic_layer/__init__.py +58 -0
  352. package/src/semantic_layer/benchmark.py +75 -0
  353. package/src/semantic_layer/cache.py +290 -0
  354. package/src/semantic_layer/compressor.py +137 -0
  355. package/src/semantic_layer/config.py +75 -0
  356. package/src/semantic_layer/embeddings.py +69 -0
  357. package/src/semantic_layer/llm_backends.py +99 -0
  358. package/src/semantic_layer/pipeline.py +111 -0
  359. package/src/semantic_layer/router.py +128 -0
  360. package/src/semantic_layer/tuner.py +72 -0
  361. package/uv.lock +973 -9
  362. package/src/devcouncil/artifacts/migrations.py +0 -20
  363. package/src/devcouncil/artifacts/schemas.py +0 -23
  364. package/src/devcouncil/artifacts/serializer.py +0 -21
  365. package/src/devcouncil/integrations/gitnexus.py +0 -70
  366. package/src/devcouncil/integrations/graphify.py +0 -34
@@ -0,0 +1,922 @@
1
+ """MCP tool schema definitions."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from mcp.types import Tool
6
+
7
+
8
+ def all_tools() -> list[Tool]:
9
+ from devcouncil.integrations.mcp.handlers.codeintel import tools as codeintel_tools
10
+ from devcouncil.integrations.mcp.handlers.debug import tools as debug_tools
11
+
12
+ return [
13
+ *codeintel_tools(),
14
+ *debug_tools(),
15
+ Tool(
16
+ name="devcouncil_status",
17
+ description=(
18
+ "Get a compact project status summary (phase, requirement/task/gap counts). "
19
+ "Default responses stay within a ~32 KB agent context budget; use "
20
+ "devcouncil_get_task / get_gaps / get_next_actions for detail by ID."
21
+ ),
22
+ inputSchema={
23
+ "type": "object",
24
+ "properties": {}
25
+ }
26
+ ),
27
+ Tool(
28
+ name="devcouncil_integration_status",
29
+ description="Get read-only coding CLI integration status, capability rows, detected clients, and recommended executor.",
30
+ inputSchema={"type": "object", "properties": {}},
31
+ ),
32
+ Tool(
33
+ name="devcouncil_report",
34
+ description="Get the full coverage report and a list of all requirements and blocking gaps.",
35
+ inputSchema={
36
+ "type": "object",
37
+ "properties": {}
38
+ }
39
+ ),
40
+ Tool(
41
+ name="devcouncil_get_task",
42
+ description="Get details, constraints, and requirements for a specific implementation task.",
43
+ inputSchema={
44
+ "type": "object",
45
+ "properties": {
46
+ "task_id": {
47
+ "type": "string",
48
+ "description": "The ID of the task, e.g. TASK-001"
49
+ }
50
+ },
51
+ "required": ["task_id"]
52
+ }
53
+ ),
54
+ Tool(
55
+ name="devcouncil_get_gaps",
56
+ description=(
57
+ "Read persisted verification gaps for a task WITHOUT re-running "
58
+ "verification. Returns a compact projection (IDs, severity, type, "
59
+ "file/line) within a ~32 KB context budget; use get_task for full "
60
+ "detail. Cheap and idempotent for resume/repair decisions."
61
+ ),
62
+ inputSchema={
63
+ "type": "object",
64
+ "properties": {
65
+ "task_id": {"type": "string"},
66
+ "blocking_only": {"type": "boolean", "default": False},
67
+ },
68
+ "required": ["task_id"],
69
+ },
70
+ ),
71
+ Tool(
72
+ name="devcouncil_get_next_actions",
73
+ description=(
74
+ "Get the typed next-actions contract for a task from persisted gaps, "
75
+ "WITHOUT re-verifying. Compact by default (gap_id/category/action/file; "
76
+ "~32 KB context budget). Returns blocking next_actions, advisory_actions, "
77
+ "and allowed_next_tools."
78
+ ),
79
+ inputSchema={
80
+ "type": "object",
81
+ "properties": {"task_id": {"type": "string"}},
82
+ "required": ["task_id"],
83
+ },
84
+ ),
85
+ Tool(
86
+ name="devcouncil_get_task_provenance",
87
+ description=(
88
+ "Inspect the recorded audit trail for a task: gated file changes "
89
+ "(write_file/apply_patch and hook events), verification runs, diff-coverage "
90
+ "evidence (was the changed code actually exercised), and the latest "
91
+ "correction manifest. Read-only — lets a developer or agent trust what "
92
+ "actually happened on disk."
93
+ ),
94
+ inputSchema={
95
+ "type": "object",
96
+ "properties": {"task_id": {"type": "string"}},
97
+ "required": ["task_id"],
98
+ },
99
+ ),
100
+ Tool(
101
+ name="devcouncil_live_review",
102
+ description="Get live coding-agent review status, pending signals, critique-card counts, and blockers.",
103
+ inputSchema={
104
+ "type": "object",
105
+ "properties": {
106
+ "task_id": {
107
+ "type": "string",
108
+ "description": "Optional task scope for live-review blocker calculation.",
109
+ }
110
+ },
111
+ },
112
+ ),
113
+ Tool(
114
+ name="devcouncil_live_cards",
115
+ description="List live-review critique cards with optional task, status, verdict, and client filters.",
116
+ inputSchema={
117
+ "type": "object",
118
+ "properties": {
119
+ "task_id": {
120
+ "type": "string",
121
+ "description": "Optional task scope for critique cards.",
122
+ },
123
+ "status": {
124
+ "type": "string",
125
+ "enum": ["open", "resolved", "ignored"],
126
+ "description": "Optional card status filter.",
127
+ },
128
+ "verdict": {
129
+ "type": "string",
130
+ "enum": ["approved", "concerns", "critical"],
131
+ "description": "Optional card verdict filter.",
132
+ },
133
+ "client": {
134
+ "type": "string",
135
+ "description": "Optional coding-agent client filter.",
136
+ },
137
+ "limit": {
138
+ "type": "integer",
139
+ "minimum": 1,
140
+ "maximum": 200,
141
+ "default": 20,
142
+ },
143
+ },
144
+ },
145
+ ),
146
+ Tool(
147
+ name="devcouncil_live_repair_prompt",
148
+ description="Generate a ready-to-paste repair prompt for a live-review critique card.",
149
+ inputSchema={
150
+ "type": "object",
151
+ "properties": {
152
+ "card_id": {
153
+ "type": "string",
154
+ "description": "The critique card ID, e.g. CARD-abc123.",
155
+ }
156
+ },
157
+ "required": ["card_id"],
158
+ },
159
+ ),
160
+ Tool(
161
+ name="devcouncil_live_repair_all",
162
+ description="Generate one repair prompt for all blocking live-review critique cards in scope.",
163
+ inputSchema={
164
+ "type": "object",
165
+ "properties": {
166
+ "task_id": {
167
+ "type": "string",
168
+ "description": "Optional task scope for blocking live-review cards.",
169
+ }
170
+ },
171
+ },
172
+ ),
173
+ Tool(
174
+ name="devcouncil_list_tasks",
175
+ description=(
176
+ "List DevCouncil tasks as compact rows (id/title/status/priority/"
177
+ "requirements/lease) within a ~32 KB context budget. Supports status "
178
+ "filter and limit/offset paging; use get_task for full detail."
179
+ ),
180
+ inputSchema={
181
+ "type": "object",
182
+ "properties": {
183
+ "status": {"type": "string", "description": "Optional status filter (e.g. planned, running, blocked, verified, done)."},
184
+ "limit": {"type": "integer", "description": "Max tasks to return (default 100, max 500)."},
185
+ "offset": {"type": "integer", "description": "Number of tasks to skip (default 0)."},
186
+ },
187
+ },
188
+ ),
189
+ Tool(
190
+ name="devcouncil_get_prompt",
191
+ description="Get the raw implementation prompt for a DevCouncil task.",
192
+ inputSchema={
193
+ "type": "object",
194
+ "properties": {
195
+ "task_id": {"type": "string", "description": "The ID of the task, e.g. TASK-001"},
196
+ },
197
+ "required": ["task_id"],
198
+ },
199
+ ),
200
+ Tool(
201
+ name="devcouncil_tail_trace",
202
+ description="Return recent DevCouncil trace events as JSON.",
203
+ inputSchema={
204
+ "type": "object",
205
+ "properties": {
206
+ "limit": {"type": "integer", "minimum": 1, "maximum": 200, "default": 20},
207
+ },
208
+ },
209
+ ),
210
+ Tool(
211
+ name="devcouncil_policy_check_write",
212
+ description="Check whether a file write is allowed for a task or the active running task.",
213
+ inputSchema={
214
+ "type": "object",
215
+ "properties": {
216
+ "path": {"type": "string", "description": "Repository-relative or absolute path to check."},
217
+ "task_id": {"type": "string", "description": "Optional task ID. Defaults to the running task."},
218
+ },
219
+ "required": ["path"],
220
+ },
221
+ ),
222
+ Tool(
223
+ name="devcouncil_graph_context",
224
+ description="Get optional code-review-graph structural context for changed or planned files.",
225
+ inputSchema={
226
+ "type": "object",
227
+ "properties": {
228
+ "files": {
229
+ "type": "array",
230
+ "items": {"type": "string"},
231
+ "description": "Repository-relative files to contextualize.",
232
+ }
233
+ },
234
+ },
235
+ ),
236
+ Tool(
237
+ name="devcouncil_repo_map",
238
+ description=(
239
+ "Query the repo map summary (languages, subsystems) or one subsystem's "
240
+ "detail (entry_points, critical_files, neighbors, role_files). Optional "
241
+ "path resolves a file to its subsystem area. Includes stale freshness flag."
242
+ ),
243
+ inputSchema={
244
+ "type": "object",
245
+ "properties": {
246
+ "subsystem": {
247
+ "type": "string",
248
+ "description": "Subsystem area prefix to return in detail.",
249
+ },
250
+ "path": {
251
+ "type": "string",
252
+ "description": "Repository-relative file path; resolves to its subsystem area.",
253
+ },
254
+ },
255
+ },
256
+ ),
257
+ Tool(
258
+ name="devcouncil_impact",
259
+ description=(
260
+ "Blast-radius impact for given paths: import dependents, neighbor "
261
+ "subsystem areas, and cross-boundary area pairs from the repo map. "
262
+ "Set precise=true to resolve dependents via live LSP references when "
263
+ "a language server is available (falls back to import-level dependents)."
264
+ ),
265
+ inputSchema={
266
+ "type": "object",
267
+ "properties": {
268
+ "paths": {
269
+ "type": "array",
270
+ "items": {"type": "string"},
271
+ "description": "Repository-relative file paths to analyze.",
272
+ },
273
+ "precise": {
274
+ "type": "boolean",
275
+ "description": (
276
+ "When true, use live LSP textDocument/references for "
277
+ "dependents instead of import-level map edges."
278
+ ),
279
+ "default": False,
280
+ },
281
+ },
282
+ "required": ["paths"],
283
+ },
284
+ ),
285
+ Tool(
286
+ name="devcouncil_liveness",
287
+ description=(
288
+ "Liveness debt from the repo map: unwired candidates, unreachable files, "
289
+ "dead-symbol candidates, and entry roots. Filterable by subsystem area or path prefix. "
290
+ "When a code graph exists, also returns structured confidence-tagged dead_code "
291
+ "(default min_confidence=inferred; pass ambiguous to include all tiers). "
292
+ "Prefer extracted confidence + greps; treat inferred as unconfirmed. "
293
+ "If entry_roots are empty or unreachable_unreliable is true, ignore unreachable_files "
294
+ "and mass inferred dead."
295
+ ),
296
+ inputSchema={
297
+ "type": "object",
298
+ "properties": {
299
+ "area": {
300
+ "type": "string",
301
+ "description": "Optional subsystem area to filter results.",
302
+ },
303
+ "path_prefix": {
304
+ "type": "string",
305
+ "description": "Optional path prefix to filter results.",
306
+ },
307
+ "min_confidence": {
308
+ "type": "string",
309
+ "enum": ["extracted", "inferred", "ambiguous"],
310
+ "description": (
311
+ "Minimum dead_code confidence tier to include "
312
+ "(default: inferred). Prefer extracted for deletion decisions."
313
+ ),
314
+ },
315
+ },
316
+ },
317
+ ),
318
+ Tool(
319
+ name="devcouncil_graph_ingest",
320
+ description="Unified native ingest: codeintel sync, graph export, repo map write.",
321
+ inputSchema={
322
+ "type": "object",
323
+ "properties": {
324
+ "paths": {
325
+ "type": "array",
326
+ "items": {"type": "string"},
327
+ "description": "Optional repository-relative paths; full reconcile when omitted.",
328
+ },
329
+ },
330
+ },
331
+ ),
332
+ Tool(
333
+ name="devcouncil_graph_cypher",
334
+ description="Run a supported Cypher subset over the native code graph store.",
335
+ inputSchema={
336
+ "type": "object",
337
+ "properties": {
338
+ "query": {"type": "string", "description": "MATCH … RETURN … query."},
339
+ },
340
+ "required": ["query"],
341
+ },
342
+ ),
343
+ Tool(
344
+ name="devcouncil_pdg_query",
345
+ description=(
346
+ "Query opt-in PDG control or data dependence for a symbol qualname or file path. "
347
+ "Requires `dev map --pdg` or `dev graph pdg build` first."
348
+ ),
349
+ inputSchema={
350
+ "type": "object",
351
+ "properties": {
352
+ "mode": {
353
+ "type": "string",
354
+ "enum": ["controls", "flows"],
355
+ "description": "controls = CDG edges; flows = reaching-def edges.",
356
+ },
357
+ "target": {
358
+ "type": "string",
359
+ "description": "Symbol qualname or repository-relative file path.",
360
+ },
361
+ "variable": {
362
+ "type": "string",
363
+ "description": "Optional variable filter when mode=flows.",
364
+ },
365
+ },
366
+ "required": ["mode", "target"],
367
+ },
368
+ ),
369
+ Tool(
370
+ name="devcouncil_explain",
371
+ description=(
372
+ "Report heuristic PDG taint findings (source→sink) from the opt-in PDG layer. "
373
+ "Filter by file path and/or taint category."
374
+ ),
375
+ inputSchema={
376
+ "type": "object",
377
+ "properties": {
378
+ "path": {
379
+ "type": "string",
380
+ "description": "Optional repository-relative file path filter.",
381
+ },
382
+ "category": {
383
+ "type": "string",
384
+ "description": "Optional taint category filter (e.g. command-injection).",
385
+ },
386
+ },
387
+ },
388
+ ),
389
+ Tool(
390
+ name="devcouncil_graph_query",
391
+ description=(
392
+ "360° symbol/file query over the code knowledge graph: definition, callers, "
393
+ "callees, and importers. Requires `dev map` (writes .devcouncil/graph/code_graph.json)."
394
+ ),
395
+ inputSchema={
396
+ "type": "object",
397
+ "properties": {
398
+ "name_or_path": {
399
+ "type": "string",
400
+ "description": "Symbol name, qualified id, or file path.",
401
+ },
402
+ },
403
+ "required": ["name_or_path"],
404
+ },
405
+ ),
406
+ Tool(
407
+ name="devcouncil_graph_trace",
408
+ description=(
409
+ "Shortest path between two nodes in the code knowledge graph "
410
+ "(imports/calls/contains)."
411
+ ),
412
+ inputSchema={
413
+ "type": "object",
414
+ "properties": {
415
+ "from": {
416
+ "type": "string",
417
+ "description": "Start node (name or path).",
418
+ },
419
+ "to": {
420
+ "type": "string",
421
+ "description": "End node (name or path).",
422
+ },
423
+ },
424
+ "required": ["from", "to"],
425
+ },
426
+ ),
427
+ Tool(
428
+ name="devcouncil_graph_impact",
429
+ description=(
430
+ "Symbol-level blast radius from the code knowledge graph: map paths "
431
+ "(or working-tree diff) to enclosing symbols, then inbound callers/"
432
+ "importers at depth 1/2/3 with confidence tiers. Distinct from "
433
+ "devcouncil_impact (file-level repo-map dependents)."
434
+ ),
435
+ inputSchema={
436
+ "type": "object",
437
+ "properties": {
438
+ "paths": {
439
+ "type": "array",
440
+ "items": {"type": "string"},
441
+ "description": "Repository-relative file paths to analyze.",
442
+ },
443
+ "diff": {
444
+ "type": "boolean",
445
+ "description": (
446
+ "When true, seed from working-tree changed files "
447
+ "(optionally filtered by paths)."
448
+ ),
449
+ "default": False,
450
+ },
451
+ },
452
+ },
453
+ ),
454
+ Tool(
455
+ name="devcouncil_route_map",
456
+ description=(
457
+ "Map HTTP routes (ROUTE nodes) to handlers, registration owners, "
458
+ "and client fetch/axios/requests/httpx consumers from the code graph."
459
+ ),
460
+ inputSchema={"type": "object", "properties": {}},
461
+ ),
462
+ Tool(
463
+ name="devcouncil_shape_check",
464
+ description=(
465
+ "Compare handler return dict keys vs keys accessed by API consumers "
466
+ "after fetch calls; flags shape mismatches."
467
+ ),
468
+ inputSchema={
469
+ "type": "object",
470
+ "properties": {
471
+ "route": {
472
+ "type": "string",
473
+ "description": "Optional route path or id filter.",
474
+ },
475
+ },
476
+ },
477
+ ),
478
+ Tool(
479
+ name="devcouncil_api_impact",
480
+ description=(
481
+ "API route blast radius: consumers, middleware (registers edges), "
482
+ "response-shape mismatches, and risk tier (high/medium/low/none)."
483
+ ),
484
+ inputSchema={
485
+ "type": "object",
486
+ "properties": {
487
+ "route_or_path": {
488
+ "type": "string",
489
+ "description": "Route path, graph id, or normalized segment.",
490
+ },
491
+ },
492
+ "required": ["route_or_path"],
493
+ },
494
+ ),
495
+ Tool(
496
+ name="devcouncil_lsp_status",
497
+ description=(
498
+ "Return detected language servers and mode (detection-only or client). "
499
+ "Client mode reflects indexing.lsp_refs / live references capability."
500
+ ),
501
+ inputSchema={"type": "object", "properties": {}},
502
+ ),
503
+ Tool(
504
+ name="devcouncil_ast_match",
505
+ description="Search code symbols structurally using optional tree-sitter support and deterministic fallbacks.",
506
+ inputSchema={
507
+ "type": "object",
508
+ "properties": {
509
+ "query": {"type": "string"},
510
+ "language": {"type": "string"},
511
+ "kind": {"type": "string"},
512
+ "limit": {"type": "integer", "minimum": 1, "maximum": 500, "default": 100},
513
+ },
514
+ },
515
+ ),
516
+ Tool(
517
+ name="devcouncil_cli",
518
+ description="Run a safe DevCouncil CLI command for status, tasks, report, map, prompt, show, trace, lsp, or ast.",
519
+ inputSchema={
520
+ "type": "object",
521
+ "properties": {
522
+ "args": {
523
+ "type": "array",
524
+ "items": {"type": "string"},
525
+ "description": "Arguments after the dev command, for example ['status','--json'].",
526
+ }
527
+ },
528
+ "required": ["args"],
529
+ },
530
+ ),
531
+ Tool(
532
+ name="devcouncil_prepare_execution",
533
+ description="Return a task prompt plus planned files and allowed commands for external execution tooling.",
534
+ inputSchema={
535
+ "type": "object",
536
+ "properties": {
537
+ "task_id": {"type": "string", "description": "The ID of the task, e.g. TASK-001"},
538
+ },
539
+ "required": ["task_id"],
540
+ },
541
+ ),
542
+ Tool(
543
+ name="devcouncil_checkout_task",
544
+ description="Acquire a task lease and return scope for MCP write tools.",
545
+ inputSchema={
546
+ "type": "object",
547
+ "properties": {
548
+ "task_id": {"type": "string"},
549
+ "client_id": {"type": "string"},
550
+ "agent": {"type": "string"},
551
+ "force": {"type": "boolean", "default": False},
552
+ },
553
+ "required": ["task_id", "client_id"],
554
+ },
555
+ ),
556
+ Tool(
557
+ name="devcouncil_release_task",
558
+ description="Release a task lease using its token.",
559
+ inputSchema={
560
+ "type": "object",
561
+ "properties": {
562
+ "task_id": {"type": "string"},
563
+ "lease_token": {"type": "string"},
564
+ },
565
+ "required": ["task_id", "lease_token"],
566
+ },
567
+ ),
568
+ Tool(
569
+ name="devcouncil_renew_lease",
570
+ description=(
571
+ "Extend a held task lease's TTL so a long-running agent does not lose it "
572
+ "to expiry. Returns the new expires_at."
573
+ ),
574
+ inputSchema={
575
+ "type": "object",
576
+ "properties": {
577
+ "task_id": {"type": "string"},
578
+ "lease_token": {"type": "string"},
579
+ "ttl_seconds": {"type": "integer"},
580
+ },
581
+ "required": ["task_id", "lease_token"],
582
+ },
583
+ ),
584
+ Tool(
585
+ name="devcouncil_list_leases",
586
+ description=(
587
+ "List task leases for fleet supervision — task_id, owner, agent, "
588
+ "expires_at, and whether each is expired. Defaults to active leases."
589
+ ),
590
+ inputSchema={
591
+ "type": "object",
592
+ "properties": {"active_only": {"type": "boolean", "default": True}},
593
+ },
594
+ ),
595
+ Tool(
596
+ name="devcouncil_update_task_scope",
597
+ description=(
598
+ "Append unique expected tests, allowed commands, or planned files "
599
+ "(modify-op only) for a leased task. Use planned_files to authorize "
600
+ "editing an intended caller when wiring a new module."
601
+ ),
602
+ inputSchema={
603
+ "type": "object",
604
+ "properties": {
605
+ "task_id": {"type": "string"},
606
+ "lease_token": {"type": "string"},
607
+ "expected_tests": {"type": "array", "items": {"type": "string"}},
608
+ "allowed_commands": {"type": "array", "items": {"type": "string"}},
609
+ "planned_files": {
610
+ "type": "array",
611
+ "items": {"type": "string"},
612
+ "description": (
613
+ "Paths to append as modify-op planned files "
614
+ "(secret/restricted paths rejected)."
615
+ ),
616
+ },
617
+ },
618
+ "required": ["task_id", "lease_token"],
619
+ },
620
+ ),
621
+ Tool(
622
+ name="devcouncil_append_evidence",
623
+ description="Append command evidence for a leased task.",
624
+ inputSchema={
625
+ "type": "object",
626
+ "properties": {
627
+ "task_id": {"type": "string"},
628
+ "lease_token": {"type": "string"},
629
+ "command": {"type": "string"},
630
+ "exit_code": {"type": "integer"},
631
+ "summary": {"type": "string"},
632
+ },
633
+ "required": ["task_id", "lease_token", "command", "exit_code", "summary"],
634
+ },
635
+ ),
636
+ Tool(
637
+ name="devcouncil_record_command",
638
+ description="Record a shell command event for a leased task.",
639
+ inputSchema={
640
+ "type": "object",
641
+ "properties": {
642
+ "task_id": {"type": "string"},
643
+ "lease_token": {"type": "string"},
644
+ "command": {"type": "string"},
645
+ "status": {"type": "string", "enum": ["started", "finished", "failed", "blocked"]},
646
+ "exit_code": {"type": "integer"},
647
+ "reason": {"type": "string"},
648
+ },
649
+ "required": ["task_id", "lease_token", "command", "status"],
650
+ },
651
+ ),
652
+ Tool(
653
+ name="devcouncil_write_file",
654
+ description=(
655
+ "Write a file for a leased task through DevCouncil's policy gate. The write "
656
+ "is checked against the task's scope BEFORE it lands (out-of-scope or "
657
+ "protected paths are rejected), applied atomically, and recorded as a "
658
+ "FileChangeEvent. Returns applied_files and rejected_files."
659
+ ),
660
+ inputSchema={
661
+ "type": "object",
662
+ "properties": {
663
+ "task_id": {"type": "string"},
664
+ "lease_token": {"type": "string"},
665
+ "path": {"type": "string"},
666
+ "content": {"type": "string"},
667
+ },
668
+ "required": ["task_id", "lease_token", "path", "content"],
669
+ },
670
+ ),
671
+ Tool(
672
+ name="devcouncil_apply_patch",
673
+ description=(
674
+ "Apply a unified diff for a leased task through DevCouncil's policy gate. "
675
+ "EVERY target file is policy-checked first; if any is out of scope the whole "
676
+ "patch is rejected (never partially applied). Applied atomically via git and "
677
+ "each file recorded as a FileChangeEvent. Returns applied_files/rejected_files."
678
+ ),
679
+ inputSchema={
680
+ "type": "object",
681
+ "properties": {
682
+ "task_id": {"type": "string"},
683
+ "lease_token": {"type": "string"},
684
+ "unified_diff": {"type": "string"},
685
+ },
686
+ "required": ["task_id", "lease_token", "unified_diff"],
687
+ },
688
+ ),
689
+ Tool(
690
+ name="devcouncil_verify_task",
691
+ description="Run verification for a leased task (local sandbox).",
692
+ inputSchema={
693
+ "type": "object",
694
+ "properties": {
695
+ "task_id": {"type": "string"},
696
+ "lease_token": {"type": "string"},
697
+ "sandbox": {"type": "string", "enum": ["local"], "default": "local", "description": "Only 'local' is supported in this build."},
698
+ },
699
+ "required": ["task_id", "lease_token"],
700
+ },
701
+ ),
702
+ Tool(
703
+ name="devcouncil_handoff_agent",
704
+ description="Hand off a task between coding CLI agents.",
705
+ inputSchema={
706
+ "type": "object",
707
+ "properties": {
708
+ "task_id": {"type": "string"},
709
+ "lease_token": {"type": "string"},
710
+ "from_agent": {"type": "string"},
711
+ "to_agent": {"type": "string"},
712
+ "instruction": {"type": "string"},
713
+ },
714
+ "required": ["task_id", "lease_token", "from_agent", "to_agent"],
715
+ },
716
+ ),
717
+ Tool(
718
+ name="devcouncil_read_file",
719
+ description=(
720
+ "Read a repository file (read-only, no lease required) so an MCP-only "
721
+ "agent can inspect content before constructing a diff or overwriting it. "
722
+ "Containment-checked against the project root and refuses secret/credential "
723
+ "paths. When task_id is set, the path must intersect that task's planned "
724
+ "files (fail-closed; never broadens scope). Supports offset/limit or "
725
+ "line_range windowing. Returns content (truncated), sha256, and line_count."
726
+ ),
727
+ inputSchema={
728
+ "type": "object",
729
+ "properties": {
730
+ "path": {"type": "string", "description": "Repository-relative or absolute path inside the project."},
731
+ "task_id": {
732
+ "type": "string",
733
+ "description": (
734
+ "Optional task scope. When set, only planned-file paths for "
735
+ "that task may be read."
736
+ ),
737
+ },
738
+ "offset": {"type": "integer", "minimum": 0, "description": "0-based line offset to start from."},
739
+ "limit": {"type": "integer", "minimum": 1, "description": "Max number of lines to return."},
740
+ "line_range": {
741
+ "type": "string",
742
+ "description": "Inclusive 1-based line range like '10-40' (overrides offset/limit).",
743
+ },
744
+ },
745
+ "required": ["path"],
746
+ },
747
+ ),
748
+ Tool(
749
+ name="devcouncil_get_diff",
750
+ description=(
751
+ "Return the working-tree diff for the project (requires a git repo). When "
752
+ "task_id is given the diff is scoped to that task's planned/changed files. "
753
+ "Set staged=true to include the staged (git diff --cached) changes. Returns "
754
+ "per-file status with additions/deletions and the truncated unified diff."
755
+ ),
756
+ inputSchema={
757
+ "type": "object",
758
+ "properties": {
759
+ "task_id": {"type": "string", "description": "Optional task to scope the diff to its files."},
760
+ "paths": {
761
+ "type": "array",
762
+ "items": {"type": "string"},
763
+ "description": "Optional explicit repo-relative paths to scope the diff to.",
764
+ },
765
+ "staged": {"type": "boolean", "default": False, "description": "Include staged changes."},
766
+ },
767
+ },
768
+ ),
769
+ Tool(
770
+ name="devcouncil_get_evidence",
771
+ description=(
772
+ "Read persisted CommandResult evidence for a task and inline the truncated "
773
+ "stdout/stderr from the stored log files (best-effort; tolerates missing "
774
+ "files). Pairs with verification to close the diagnose leg of the loop."
775
+ ),
776
+ inputSchema={
777
+ "type": "object",
778
+ "properties": {
779
+ "task_id": {"type": "string"},
780
+ "command": {"type": "string", "description": "Optional substring filter on the recorded command."},
781
+ "limit": {"type": "integer", "minimum": 1, "maximum": 100, "default": 20},
782
+ },
783
+ "required": ["task_id"],
784
+ },
785
+ ),
786
+ Tool(
787
+ name="devcouncil_run_command",
788
+ description=(
789
+ "Run a command for a leased task through DevCouncil's allowlist gate. The "
790
+ "command must pass the task's allowed_commands policy (same gate as the "
791
+ "hooks); otherwise it is refused and nothing runs. Executed with a clean "
792
+ "subprocess env and a timeout, recorded as a ShellCommandEvent. Returns "
793
+ "exit_code and truncated stdout/stderr."
794
+ ),
795
+ inputSchema={
796
+ "type": "object",
797
+ "properties": {
798
+ "task_id": {"type": "string"},
799
+ "lease_token": {"type": "string"},
800
+ "command": {"type": "string"},
801
+ },
802
+ "required": ["task_id", "lease_token", "command"],
803
+ },
804
+ ),
805
+ Tool(
806
+ name="devcouncil_list_agent_runs",
807
+ description=(
808
+ "List recorded coding-agent runs (from .devcouncil/runs/*/agent-run.json), "
809
+ "newest first. Each entry includes run_id, task, agent, profile, status, "
810
+ "started time, and an orphaned flag for runs still marked running whose "
811
+ "manifest has gone stale (executor likely crashed). Read-only."
812
+ ),
813
+ inputSchema={
814
+ "type": "object",
815
+ "properties": {
816
+ "status": {"type": "string", "description": "Optional status filter (e.g. running, finished, failed, timeout)."},
817
+ "limit": {"type": "integer", "minimum": 1, "maximum": 500, "default": 20},
818
+ },
819
+ },
820
+ ),
821
+ Tool(
822
+ name="devcouncil_get_run",
823
+ description=(
824
+ "Get the full manifest for a single coding-agent run plus a redacted "
825
+ "transcript tail when a transcript/log file exists in the run directory. "
826
+ "Includes the resolved CLI invocation and an orphaned flag. Read-only."
827
+ ),
828
+ inputSchema={
829
+ "type": "object",
830
+ "properties": {
831
+ "run_id": {"type": "string", "description": "The run id to inspect."},
832
+ },
833
+ "required": ["run_id"],
834
+ },
835
+ ),
836
+ Tool(
837
+ name="devcouncil_next_task",
838
+ description=(
839
+ "Return the highest-priority task that is unblocked (its depends_on are "
840
+ "satisfied) and has no active lease, so an autonomous agent can bootstrap "
841
+ "deterministically instead of racing list_tasks. Includes a blocking-gap "
842
+ "summary and a ready_to_checkout flag."
843
+ ),
844
+ inputSchema={
845
+ "type": "object",
846
+ "properties": {
847
+ "client_id": {"type": "string", "description": "Optional client id (informational)."},
848
+ "status": {"type": "string", "description": "Optional status filter (default planned/ready)."},
849
+ },
850
+ },
851
+ ),
852
+ Tool(
853
+ name="devcouncil_select_knowledge",
854
+ description=(
855
+ "Select the ingested project knowledge (OKF documents and the design "
856
+ "system) that applies to a goal and return it as a ready-to-inject "
857
+ "markdown preamble, so a coding agent can ask 'what project knowledge "
858
+ "applies to <goal>?'. Always-on design knowledge is included; OKF "
859
+ "documents are matched on goal keywords. Returns the matched sources "
860
+ "and the rendered preamble."
861
+ ),
862
+ inputSchema={
863
+ "type": "object",
864
+ "properties": {
865
+ "goal": {"type": "string", "description": "The task or goal to find applicable knowledge for."},
866
+ },
867
+ "required": ["goal"],
868
+ },
869
+ ),
870
+ Tool(
871
+ name="devcouncil_wiki_page",
872
+ description=(
873
+ "Read the generated codebase wiki (OKF bundle under "
874
+ ".devcouncil/knowledge/okf/wiki/). With no arguments, returns the page "
875
+ "index. Pass 'page' (a bundle-relative path like "
876
+ "'subsystems/src-devcouncil-council.md') for one page, or 'query' to "
877
+ "find pages whose title/tags/description match. Read-only; refresh "
878
+ "with `dev wiki update`."
879
+ ),
880
+ inputSchema={
881
+ "type": "object",
882
+ "properties": {
883
+ "page": {"type": "string", "description": "Bundle-relative page path (e.g. subsystems/<slug>.md)."},
884
+ "query": {"type": "string", "description": "Keyword(s) to match against page titles, tags, and descriptions."},
885
+ },
886
+ },
887
+ ),
888
+ Tool(
889
+ name="devcouncil_run_timeline",
890
+ description=(
891
+ "Get a run's full reversible trace (Shepherd-style): manifest, trace "
892
+ "events, git checkpoints (before/after/attempts), diff stat, and whether "
893
+ "the run is reversible. Accepts a run id or task id. Read-only — use "
894
+ "`dev runs revert <ref>` to reverse a run's workspace effects."
895
+ ),
896
+ inputSchema={
897
+ "type": "object",
898
+ "properties": {
899
+ "reference": {"type": "string", "description": "A run id or task id."},
900
+ "limit": {"type": "integer", "minimum": 1, "maximum": 500, "default": 40},
901
+ },
902
+ "required": ["reference"],
903
+ },
904
+ ),
905
+ Tool(
906
+ name="devcouncil_run_supervise",
907
+ description=(
908
+ "Ask the supervisor meta-agent for a keep/revert/repair verdict on a "
909
+ "recorded run, from its manifest, trace events, and diff. Uses the "
910
+ "run_supervisor model role when configured, degrading to deterministic "
911
+ "heuristics. Never modifies the workspace; the verdict is logged to the "
912
+ "trace and reverting stays an explicit separate step."
913
+ ),
914
+ inputSchema={
915
+ "type": "object",
916
+ "properties": {
917
+ "reference": {"type": "string", "description": "A run id or task id."},
918
+ },
919
+ "required": ["reference"],
920
+ },
921
+ ),
922
+ ]