mednotes-opencode 0.1.0

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 (430) hide show
  1. package/.opencode/agents/med-chat-triager.md +204 -0
  2. package/.opencode/agents/med-flashcard-maker.md +63 -0
  3. package/.opencode/agents/med-knowledge-architect.md +230 -0
  4. package/.opencode/agents/med-link-graph-curator.md +177 -0
  5. package/.opencode/agents/med-publish-guard.md +62 -0
  6. package/.opencode/commands/flashcards.md +25 -0
  7. package/.opencode/commands/mednotes/create.md +25 -0
  8. package/.opencode/commands/mednotes/enrich.md +27 -0
  9. package/.opencode/commands/mednotes/fix-wiki.md +27 -0
  10. package/.opencode/commands/mednotes/history.md +22 -0
  11. package/.opencode/commands/mednotes/link-body.md +25 -0
  12. package/.opencode/commands/mednotes/link-related.md +27 -0
  13. package/.opencode/commands/mednotes/link.md +27 -0
  14. package/.opencode/commands/mednotes/pdf-library.md +27 -0
  15. package/.opencode/commands/mednotes/process-chats.md +23 -0
  16. package/.opencode/commands/mednotes/setup.md +21 -0
  17. package/.opencode/commands/mednotes/status.md +27 -0
  18. package/.opencode/commands/mednotes/telemetry.md +27 -0
  19. package/.opencode/commands/report.md +26 -0
  20. package/.opencode/mednotes/AGENTS.md +57 -0
  21. package/.opencode/mednotes/agents/med-chat-triager.md +197 -0
  22. package/.opencode/mednotes/agents/med-flashcard-maker.md +56 -0
  23. package/.opencode/mednotes/agents/med-knowledge-architect.md +224 -0
  24. package/.opencode/mednotes/agents/med-link-graph-curator.md +171 -0
  25. package/.opencode/mednotes/agents/med-publish-guard.md +55 -0
  26. package/.opencode/mednotes/contracts/.gitkeep +1 -0
  27. package/.opencode/mednotes/contracts/agents.json +116 -0
  28. package/.opencode/mednotes/contracts/opencode-plugin.json +70 -0
  29. package/.opencode/mednotes/docs/agent-prompt-hardening.md +567 -0
  30. package/.opencode/mednotes/docs/agent-role-contracts.md +94 -0
  31. package/.opencode/mednotes/docs/anki-mcp-twenty-rules.md +214 -0
  32. package/.opencode/mednotes/docs/anki-templates/README.md +39 -0
  33. package/.opencode/mednotes/docs/anki-templates/cloze.back.html +23 -0
  34. package/.opencode/mednotes/docs/anki-templates/cloze.front.html +14 -0
  35. package/.opencode/mednotes/docs/anki-templates/qa.back.html +24 -0
  36. package/.opencode/mednotes/docs/anki-templates/qa.front.html +14 -0
  37. package/.opencode/mednotes/docs/anki-templates/style.css +182 -0
  38. package/.opencode/mednotes/docs/atomicity-splitting-policy.md +113 -0
  39. package/.opencode/mednotes/docs/extension-docs.md +40 -0
  40. package/.opencode/mednotes/docs/flashcard-ingestion.md +278 -0
  41. package/.opencode/mednotes/docs/knowledge-architect.md +208 -0
  42. package/.opencode/mednotes/docs/merge-policy.md +110 -0
  43. package/.opencode/mednotes/docs/public-vocabulary.md +104 -0
  44. package/.opencode/mednotes/docs/semantic-linker.md +141 -0
  45. package/.opencode/mednotes/docs/taxonomy-policy.md +90 -0
  46. package/.opencode/mednotes/docs/triage-policy.md +187 -0
  47. package/.opencode/mednotes/docs/vault-version-control.md +758 -0
  48. package/.opencode/mednotes/docs/vocabulary-db-recovery.md +58 -0
  49. package/.opencode/mednotes/docs/workflow-output-contract.md +779 -0
  50. package/.opencode/mednotes/hooks/hooks.json +79 -0
  51. package/.opencode/mednotes/package-lock.json +6361 -0
  52. package/.opencode/mednotes/package.json +15 -0
  53. package/.opencode/mednotes/pyproject.toml +48 -0
  54. package/.opencode/mednotes/scripts/bootstrap_windows_python_uv.cmd +13 -0
  55. package/.opencode/mednotes/scripts/bootstrap_windows_python_uv.ps1 +172 -0
  56. package/.opencode/mednotes/scripts/enrich_notes.py +23 -0
  57. package/.opencode/mednotes/scripts/full_reset_windows_python_uv.cmd +13 -0
  58. package/.opencode/mednotes/scripts/hooks/antigravity_hook_status.mjs +212 -0
  59. package/.opencode/mednotes/scripts/hooks/mednotes_hook/adapters/antigravity.mjs +169 -0
  60. package/.opencode/mednotes/scripts/hooks/mednotes_hook/adapters/harness_payload.mjs +103 -0
  61. package/.opencode/mednotes/scripts/hooks/mednotes_hook/adapters/opencode_plugin.mjs +341 -0
  62. package/.opencode/mednotes/scripts/hooks/mednotes_hook/adapters/opencode_user_config_sync.mjs +177 -0
  63. package/.opencode/mednotes/scripts/hooks/mednotes_hook/anki_preflight.mjs +214 -0
  64. package/.opencode/mednotes/scripts/hooks/mednotes_hook/cli.mjs +143 -0
  65. package/.opencode/mednotes/scripts/hooks/mednotes_hook/diagnostics.mjs +11 -0
  66. package/.opencode/mednotes/scripts/hooks/mednotes_hook/domain/agent_directive_core.mjs +160 -0
  67. package/.opencode/mednotes/scripts/hooks/mednotes_hook/fsm_directive.mjs +1470 -0
  68. package/.opencode/mednotes/scripts/hooks/mednotes_hook/hook_errors.mjs +120 -0
  69. package/.opencode/mednotes/scripts/hooks/mednotes_hook/retention.mjs +114 -0
  70. package/.opencode/mednotes/scripts/hooks/mednotes_hook/runtime.mjs +174 -0
  71. package/.opencode/mednotes/scripts/hooks/mednotes_hook/telemetry_capture.mjs +511 -0
  72. package/.opencode/mednotes/scripts/hooks/mednotes_hook/vault_guard.mjs +624 -0
  73. package/.opencode/mednotes/scripts/hooks/mednotes_hook.mjs +5 -0
  74. package/.opencode/mednotes/scripts/mednotes/_runtime_paths.py +24 -0
  75. package/.opencode/mednotes/scripts/mednotes/anki_model_validator.py +18 -0
  76. package/.opencode/mednotes/scripts/mednotes/capture_extension_diff.py +1562 -0
  77. package/.opencode/mednotes/scripts/mednotes/feedback_report.py +16 -0
  78. package/.opencode/mednotes/scripts/mednotes/flashcard_index.py +18 -0
  79. package/.opencode/mednotes/scripts/mednotes/flashcard_pipeline.py +18 -0
  80. package/.opencode/mednotes/scripts/mednotes/flashcard_report.py +18 -0
  81. package/.opencode/mednotes/scripts/mednotes/flashcard_sources.py +18 -0
  82. package/.opencode/mednotes/scripts/mednotes/obsidian/README.md +6 -0
  83. package/.opencode/mednotes/scripts/mednotes/obsidian_note_utils.py +20 -0
  84. package/.opencode/mednotes/scripts/mednotes/pdf_library/cli.py +16 -0
  85. package/.opencode/mednotes/scripts/mednotes/project_fsm.py +229 -0
  86. package/.opencode/mednotes/scripts/mednotes/setup_telemetry_email.py +404 -0
  87. package/.opencode/mednotes/scripts/mednotes/sync_anki_twenty_rules.py +18 -0
  88. package/.opencode/mednotes/scripts/mednotes/sync_opencode_user_config.py +36 -0
  89. package/.opencode/mednotes/scripts/mednotes/wiki/cli.py +20 -0
  90. package/.opencode/mednotes/scripts/mednotes/wiki_graph.py +18 -0
  91. package/.opencode/mednotes/scripts/mednotes/wiki_tree.py +134 -0
  92. package/.opencode/mednotes/scripts/reset_windows_python_uv.ps1 +625 -0
  93. package/.opencode/mednotes/scripts/run_python.mjs +109 -0
  94. package/.opencode/mednotes/scripts/vault/vault_commit.ps1 +19 -0
  95. package/.opencode/mednotes/scripts/vault/vault_commit.sh +18 -0
  96. package/.opencode/mednotes/scripts/vault/vault_git.ps1 +19 -0
  97. package/.opencode/mednotes/scripts/vault/vault_git.py +3107 -0
  98. package/.opencode/mednotes/scripts/vault/vault_git.sh +18 -0
  99. package/.opencode/mednotes/scripts/vault/vault_precommit.ps1 +19 -0
  100. package/.opencode/mednotes/scripts/vault/vault_precommit.sh +18 -0
  101. package/.opencode/mednotes/skills/THIRD_PARTY_NOTICES.md +45 -0
  102. package/.opencode/mednotes/skills/create-medical-flashcards/SKILL.md +113 -0
  103. package/.opencode/mednotes/skills/create-medical-note/SKILL.md +90 -0
  104. package/.opencode/mednotes/skills/enrich-medical-note/SKILL.md +120 -0
  105. package/.opencode/mednotes/skills/fix-medical-wiki/SKILL.md +559 -0
  106. package/.opencode/mednotes/skills/link-medical-wiki/SKILL.md +224 -0
  107. package/.opencode/mednotes/skills/obsidian-cli/SKILL.md +118 -0
  108. package/.opencode/mednotes/skills/obsidian-markdown/SKILL.md +207 -0
  109. package/.opencode/mednotes/skills/obsidian-markdown/references/CALLOUTS.md +58 -0
  110. package/.opencode/mednotes/skills/obsidian-markdown/references/EMBEDS.md +63 -0
  111. package/.opencode/mednotes/skills/obsidian-markdown/references/PROPERTIES.md +61 -0
  112. package/.opencode/mednotes/skills/obsidian-ops/SKILL.md +136 -0
  113. package/.opencode/mednotes/skills/pdf-library/SKILL.md +45 -0
  114. package/.opencode/mednotes/skills/process-medical-chats/SKILL.md +246 -0
  115. package/.opencode/mednotes/skills/workflow-report/SKILL.md +100 -0
  116. package/.opencode/mednotes/src/mednotes/__init__.py +5 -0
  117. package/.opencode/mednotes/src/mednotes/domains/__init__.py +5 -0
  118. package/.opencode/mednotes/src/mednotes/domains/flashcards/README.md +26 -0
  119. package/.opencode/mednotes/src/mednotes/domains/flashcards/__init__.py +2 -0
  120. package/.opencode/mednotes/src/mednotes/domains/flashcards/build_demo_apkg.py +177 -0
  121. package/.opencode/mednotes/src/mednotes/domains/flashcards/contracts.py +385 -0
  122. package/.opencode/mednotes/src/mednotes/domains/flashcards/flashcards_machine.py +522 -0
  123. package/.opencode/mednotes/src/mednotes/domains/flashcards/fsm.py +817 -0
  124. package/.opencode/mednotes/src/mednotes/domains/flashcards/index.py +630 -0
  125. package/.opencode/mednotes/src/mednotes/domains/flashcards/install_models.py +445 -0
  126. package/.opencode/mednotes/src/mednotes/domains/flashcards/model.py +359 -0
  127. package/.opencode/mednotes/src/mednotes/domains/flashcards/obsidian_links.py +135 -0
  128. package/.opencode/mednotes/src/mednotes/domains/flashcards/obsidian_note_utils.py +546 -0
  129. package/.opencode/mednotes/src/mednotes/domains/flashcards/pipeline.py +580 -0
  130. package/.opencode/mednotes/src/mednotes/domains/flashcards/report.py +510 -0
  131. package/.opencode/mednotes/src/mednotes/domains/flashcards/sources.py +682 -0
  132. package/.opencode/mednotes/src/mednotes/domains/flashcards/sync_rules.py +184 -0
  133. package/.opencode/mednotes/src/mednotes/domains/history/__init__.py +1 -0
  134. package/.opencode/mednotes/src/mednotes/domains/history/history_fsm.py +852 -0
  135. package/.opencode/mednotes/src/mednotes/domains/history/history_machine.py +453 -0
  136. package/.opencode/mednotes/src/mednotes/domains/setup/__init__.py +7 -0
  137. package/.opencode/mednotes/src/mednotes/domains/setup/setup_fsm.py +808 -0
  138. package/.opencode/mednotes/src/mednotes/domains/setup/setup_machine.py +973 -0
  139. package/.opencode/mednotes/src/mednotes/domains/wiki/README.md +64 -0
  140. package/.opencode/mednotes/src/mednotes/domains/wiki/__init__.py +1 -0
  141. package/.opencode/mednotes/src/mednotes/domains/wiki/api.py +668 -0
  142. package/.opencode/mednotes/src/mednotes/domains/wiki/batch_state.py +102 -0
  143. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/__init__.py +1 -0
  144. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/atomicity/__init__.py +1 -0
  145. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/atomicity/atomicity.py +877 -0
  146. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/body_link/__init__.py +1 -0
  147. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/body_link/body_linker.py +1562 -0
  148. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/effects/__init__.py +1 -0
  149. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/effects/effect_adapters.py +949 -0
  150. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/effects/fix_wiki_runtime_adapters.py +433 -0
  151. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/graph/__init__.py +1 -0
  152. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/graph/coverage.py +413 -0
  153. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/graph/graph.py +396 -0
  154. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/graph/graph_fixes.py +161 -0
  155. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/hygiene/__init__.py +1 -0
  156. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/hygiene/hygiene.py +483 -0
  157. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/illustrate/__init__.py +2 -0
  158. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/illustrate/anchors.py +185 -0
  159. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/illustrate/core/__init__.py +0 -0
  160. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/illustrate/core/cache.py +223 -0
  161. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/illustrate/core/config.py +131 -0
  162. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/illustrate/core/download.py +224 -0
  163. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/illustrate/core/frontmatter.py +59 -0
  164. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/illustrate/core/insert.py +227 -0
  165. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/illustrate/core/local_import.py +54 -0
  166. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/illustrate/sources/__init__.py +42 -0
  167. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/illustrate/sources/web_profiles.py +99 -0
  168. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/illustrate/sources/web_search.py +203 -0
  169. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/illustrate/sources/wikimedia.py +102 -0
  170. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/markdown/__init__.py +1 -0
  171. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/markdown/markdown_db_adapter.mjs +434 -0
  172. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/markdown/markdown_node_runtime.py +274 -0
  173. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/markdown/markdown_query.py +227 -0
  174. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/notes/__init__.py +1 -0
  175. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/notes/artifacts.py +605 -0
  176. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/notes/canonical_merge.py +277 -0
  177. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/notes/markdown_zones.py +85 -0
  178. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/notes/meaning_planner.py +307 -0
  179. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/notes/note_iter.py +67 -0
  180. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/notes/note_merge.py +278 -0
  181. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/notes/note_plan.py +409 -0
  182. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/notes/note_policy.py +22 -0
  183. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/notes/note_style/__init__.py +79 -0
  184. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/notes/note_style/fixes.py +264 -0
  185. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/notes/note_style/frontmatter.py +435 -0
  186. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/notes/note_style/models.py +208 -0
  187. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/notes/note_style/prompts.py +37 -0
  188. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/notes/note_style/tables.py +236 -0
  189. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/notes/note_style/validate.py +404 -0
  190. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/notes/provenance.py +478 -0
  191. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/notes/raw_chats.py +273 -0
  192. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/notes/sources_backfill.py +235 -0
  193. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/pdf/__init__.py +10 -0
  194. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/pdf/anchors.py +16 -0
  195. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/pdf/captions.py +47 -0
  196. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/pdf/cli.py +179 -0
  197. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/pdf/cloud.py +52 -0
  198. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/pdf/config.py +196 -0
  199. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/pdf/context_packets.py +76 -0
  200. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/pdf/db.py +81 -0
  201. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/pdf/doctor.py +102 -0
  202. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/pdf/figure_ids.py +42 -0
  203. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/pdf/ingest.py +326 -0
  204. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/pdf/insert.py +316 -0
  205. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/pdf/mentions.py +57 -0
  206. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/pdf/ocr.py +71 -0
  207. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/pdf/paths.py +35 -0
  208. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/pdf/pdf_engine.py +77 -0
  209. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/pdf/schema.py +155 -0
  210. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/pdf/search.py +188 -0
  211. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/pdf/tui/__init__.py +1 -0
  212. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/pdf/tui/app.py +89 -0
  213. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/pdf/tui/image_backend.py +29 -0
  214. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/pdf/tui/state.py +65 -0
  215. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/publish/__init__.py +1 -0
  216. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/publish/publish.py +1139 -0
  217. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/publish/publish_receipts.py +365 -0
  218. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/publish/publish_recovery.py +240 -0
  219. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/quality/__init__.py +1 -0
  220. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/quality/agent_behavior_corpus.py +2069 -0
  221. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/quality/agent_report_validation.py +4448 -0
  222. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/quality/agent_run_audit.py +852 -0
  223. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/quality/architect_prompt_eval.py +341 -0
  224. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/quality/body_linker_eval.py +240 -0
  225. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/quality/curator_output_validation.py +175 -0
  226. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/quality/curator_prompt_eval.py +865 -0
  227. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/quality/triager_prompt_eval.py +1295 -0
  228. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/related_notes/__init__.py +1 -0
  229. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/related_notes/related_notes.py +1920 -0
  230. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/related_notes/related_notes_headless.py +1186 -0
  231. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/specialist/__init__.py +1 -0
  232. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/specialist/plan_attestation.py +148 -0
  233. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/specialist/specialist_receipts.py +360 -0
  234. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/specialist/specialist_runtime.py +52 -0
  235. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/specialist/specialist_task_runner.py +2470 -0
  236. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/style/__init__.py +1 -0
  237. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/style/style.py +1952 -0
  238. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/subagents/__init__.py +1 -0
  239. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/subagents/agents.py +1767 -0
  240. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/vocabulary/__init__.py +1 -0
  241. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/vocabulary/alias_projection.py +331 -0
  242. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/vocabulary/link_terms.py +151 -0
  243. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/vocabulary/llm_disambiguation.py +182 -0
  244. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/vocabulary/taxonomy/__init__.py +116 -0
  245. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/vocabulary/taxonomy/audit.py +201 -0
  246. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/vocabulary/taxonomy/migration.py +314 -0
  247. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/vocabulary/taxonomy/normalize.py +72 -0
  248. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/vocabulary/taxonomy/policy.py +135 -0
  249. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/vocabulary/taxonomy/resolve.py +413 -0
  250. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/vocabulary/taxonomy/schema.py +157 -0
  251. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/vocabulary/taxonomy/status.py +137 -0
  252. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/vocabulary/vocabulary_bootstrap.py +509 -0
  253. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/vocabulary/vocabulary_curator_batch.py +1115 -0
  254. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/vocabulary/vocabulary_ingestion.py +632 -0
  255. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/vocabulary/vocabulary_map.py +930 -0
  256. package/.opencode/mednotes/src/mednotes/domains/wiki/capabilities/vocabulary/vocabulary_recovery.py +1388 -0
  257. package/.opencode/mednotes/src/mednotes/domains/wiki/cli.py +6665 -0
  258. package/.opencode/mednotes/src/mednotes/domains/wiki/common.py +69 -0
  259. package/.opencode/mednotes/src/mednotes/domains/wiki/config.py +210 -0
  260. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/__init__.py +74 -0
  261. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/agent_report.py +242 -0
  262. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/agent_run_audit.py +196 -0
  263. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/agents.py +601 -0
  264. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/curator.py +256 -0
  265. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/effect_payloads.py +519 -0
  266. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/happy_path.py +190 -0
  267. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/link_git.py +110 -0
  268. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/link_runtime_artifact.py +52 -0
  269. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/note_plan.py +75 -0
  270. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/paths.py +114 -0
  271. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/public_report.py +53 -0
  272. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/publish.py +111 -0
  273. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/raw_coverage.py +217 -0
  274. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/related_notes.py +136 -0
  275. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/related_notes_headless.py +153 -0
  276. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/related_notes_runtime.py +395 -0
  277. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/schema_registry.py +637 -0
  278. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/specialist.py +432 -0
  279. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/status.py +62 -0
  280. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/style_rewrite.py +568 -0
  281. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/vocabulary_ingestion.py +223 -0
  282. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/workflow_blockers.py +510 -0
  283. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/workflow_guardrails.py +637 -0
  284. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/workflow_outcomes.py +121 -0
  285. package/.opencode/mednotes/src/mednotes/domains/wiki/contracts/workflow_receipts.py +100 -0
  286. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/__init__.py +1 -0
  287. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/enrich/__init__.py +1 -0
  288. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/enrich/__main__.py +4 -0
  289. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/enrich/cli.py +275 -0
  290. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/enrich/workflow/__init__.py +2 -0
  291. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/enrich/workflow/candidates.py +193 -0
  292. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/enrich/workflow/cli.py +189 -0
  293. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/enrich/workflow/gemini.py +220 -0
  294. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/enrich/workflow/inputs.py +120 -0
  295. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/enrich/workflow/models.py +34 -0
  296. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/enrich/workflow/parsing.py +48 -0
  297. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/enrich/workflow/prompts.py +216 -0
  298. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/enrich/workflow/quality.py +54 -0
  299. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/enrich/workflow/reporting.py +24 -0
  300. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/enrich/workflow/runner.py +433 -0
  301. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/enrich/workflow/utils.py +39 -0
  302. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/enrich/workflow/vault_guard_bridge.py +17 -0
  303. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/fix_wiki/__init__.py +1 -0
  304. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/fix_wiki/fix_wiki_context_packets.py +454 -0
  305. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/fix_wiki/fix_wiki_decision_projection.py +133 -0
  306. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/fix_wiki/fix_wiki_effects.py +1260 -0
  307. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/fix_wiki/fix_wiki_fsm.py +2768 -0
  308. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/fix_wiki/fix_wiki_machine.py +1588 -0
  309. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/fix_wiki/fix_wiki_plan.py +306 -0
  310. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/fix_wiki/fix_wiki_primary_objective.py +316 -0
  311. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/fix_wiki/fix_wiki_problem.py +153 -0
  312. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/fix_wiki/fix_wiki_receipt_evidence.py +306 -0
  313. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/fix_wiki/fix_wiki_states.py +290 -0
  314. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/fix_wiki/fix_wiki_user_report.py +342 -0
  315. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/fix_wiki/health.py +6332 -0
  316. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/link/__init__.py +1 -0
  317. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/link/link_fsm.py +1119 -0
  318. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/link/link_git.py +638 -0
  319. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/link/link_machine.py +1106 -0
  320. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/link/link_retry_governance.py +374 -0
  321. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/link/link_runtime_result.py +485 -0
  322. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/link/link_triggers.py +183 -0
  323. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/link/linking.py +2758 -0
  324. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/link/reference_repair.py +718 -0
  325. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/link/related_notes_fsm.py +1855 -0
  326. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/link_related/__init__.py +1 -0
  327. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/link_related/link_related_machine.py +834 -0
  328. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/process_chats/__init__.py +1 -0
  329. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/process_chats/process_chats_fsm.py +1592 -0
  330. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/process_chats/process_chats_machine.py +3097 -0
  331. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/process_chats/process_chats_primary_objective.py +28 -0
  332. package/.opencode/mednotes/src/mednotes/domains/wiki/flows/process_chats/process_chats_runtime_result.py +185 -0
  333. package/.opencode/mednotes/src/mednotes/domains/wiki/performance.py +97 -0
  334. package/.opencode/mednotes/src/mednotes/kernel/__init__.py +6 -0
  335. package/.opencode/mednotes/src/mednotes/kernel/agent_directive.py +336 -0
  336. package/.opencode/mednotes/src/mednotes/kernel/base.py +51 -0
  337. package/.opencode/mednotes/src/mednotes/kernel/blockers.py +39 -0
  338. package/.opencode/mednotes/src/mednotes/kernel/effect_executor.py +55 -0
  339. package/.opencode/mednotes/src/mednotes/kernel/effect_intent.py +69 -0
  340. package/.opencode/mednotes/src/mednotes/kernel/effects.py +160 -0
  341. package/.opencode/mednotes/src/mednotes/kernel/errors.py +38 -0
  342. package/.opencode/mednotes/src/mednotes/kernel/fsm_event.py +35 -0
  343. package/.opencode/mednotes/src/mednotes/kernel/fsm_model.py +55 -0
  344. package/.opencode/mednotes/src/mednotes/kernel/fsm_transition_result.py +75 -0
  345. package/.opencode/mednotes/src/mednotes/kernel/guardrails.py +188 -0
  346. package/.opencode/mednotes/src/mednotes/kernel/progress.py +319 -0
  347. package/.opencode/mednotes/src/mednotes/kernel/public_report.py +346 -0
  348. package/.opencode/mednotes/src/mednotes/kernel/state_machine.py +164 -0
  349. package/.opencode/mednotes/src/mednotes/kernel/workflow.py +619 -0
  350. package/.opencode/mednotes/src/mednotes/platform/__init__.py +5 -0
  351. package/.opencode/mednotes/src/mednotes/platform/backup_policy.py +382 -0
  352. package/.opencode/mednotes/src/mednotes/platform/feedback/__init__.py +62 -0
  353. package/.opencode/mednotes/src/mednotes/platform/feedback/cli.py +275 -0
  354. package/.opencode/mednotes/src/mednotes/platform/feedback/contracts.py +83 -0
  355. package/.opencode/mednotes/src/mednotes/platform/feedback/core.py +4168 -0
  356. package/.opencode/mednotes/src/mednotes/platform/feedback/integrity.py +989 -0
  357. package/.opencode/mednotes/src/mednotes/platform/feedback/operational_contract.py +2293 -0
  358. package/.opencode/mednotes/src/mednotes/platform/feedback/telemetry.py +875 -0
  359. package/.opencode/mednotes/src/mednotes/platform/feedback/telemetry_config.py +65 -0
  360. package/.opencode/mednotes/src/mednotes/platform/opencode_runtime_config.py +182 -0
  361. package/.opencode/mednotes/src/mednotes/platform/paths/__init__.py +1560 -0
  362. package/.opencode/mednotes/src/mednotes/platform/secrets.py +89 -0
  363. package/.opencode/mednotes/src/mednotes/platform/user_config.py +103 -0
  364. package/.opencode/mednotes/src/mednotes/platform/vault_guard.py +214 -0
  365. package/.opencode/mednotes/uv.lock +932 -0
  366. package/.opencode/mednotes.generated.json +395 -0
  367. package/.opencode/opencode.json +31 -0
  368. package/.opencode/plugins/mednotes-fsm.mjs +7 -0
  369. package/.opencode/plugins/mednotes_hook/adapters/antigravity.mjs +169 -0
  370. package/.opencode/plugins/mednotes_hook/adapters/harness_payload.mjs +103 -0
  371. package/.opencode/plugins/mednotes_hook/adapters/opencode_plugin.mjs +341 -0
  372. package/.opencode/plugins/mednotes_hook/adapters/opencode_user_config_sync.mjs +177 -0
  373. package/.opencode/plugins/mednotes_hook/anki_preflight.mjs +214 -0
  374. package/.opencode/plugins/mednotes_hook/cli.mjs +143 -0
  375. package/.opencode/plugins/mednotes_hook/diagnostics.mjs +11 -0
  376. package/.opencode/plugins/mednotes_hook/domain/agent_directive_core.mjs +160 -0
  377. package/.opencode/plugins/mednotes_hook/fsm_directive.mjs +1470 -0
  378. package/.opencode/plugins/mednotes_hook/hook_errors.mjs +120 -0
  379. package/.opencode/plugins/mednotes_hook/retention.mjs +114 -0
  380. package/.opencode/plugins/mednotes_hook/runtime.mjs +174 -0
  381. package/.opencode/plugins/mednotes_hook/telemetry_capture.mjs +511 -0
  382. package/.opencode/plugins/mednotes_hook/vault_guard.mjs +624 -0
  383. package/AGENTS.md +57 -0
  384. package/README.md +194 -0
  385. package/adapters/antigravity/agents.json +80 -0
  386. package/adapters/antigravity/templates/med-chat-triager.md +214 -0
  387. package/adapters/antigravity/templates/med-flashcard-maker.md +72 -0
  388. package/adapters/antigravity/templates/med-knowledge-architect.md +241 -0
  389. package/adapters/antigravity/templates/med-link-graph-curator.md +187 -0
  390. package/adapters/antigravity/templates/med-publish-guard.md +71 -0
  391. package/adapters/gemini-cli/gemini-extension.json +14 -0
  392. package/adapters/gemini-cli/package.json +15 -0
  393. package/adapters/gemini-cli/pyproject.toml +48 -0
  394. package/bin/mednotes-opencode.mjs +155 -0
  395. package/contracts/agents.json +116 -0
  396. package/core/agents/med-chat-triager.md +197 -0
  397. package/core/agents/med-flashcard-maker.md +56 -0
  398. package/core/agents/med-knowledge-architect.md +224 -0
  399. package/core/agents/med-link-graph-curator.md +171 -0
  400. package/core/agents/med-publish-guard.md +55 -0
  401. package/core/commands/flashcards.toml +22 -0
  402. package/core/commands/mednotes/create.toml +22 -0
  403. package/core/commands/mednotes/enrich.toml +24 -0
  404. package/core/commands/mednotes/fix-wiki.toml +24 -0
  405. package/core/commands/mednotes/history.toml +19 -0
  406. package/core/commands/mednotes/link-body.toml +22 -0
  407. package/core/commands/mednotes/link-related.toml +24 -0
  408. package/core/commands/mednotes/link.toml +24 -0
  409. package/core/commands/mednotes/pdf-library.toml +24 -0
  410. package/core/commands/mednotes/process-chats.toml +20 -0
  411. package/core/commands/mednotes/setup.toml +18 -0
  412. package/core/commands/mednotes/status.toml +24 -0
  413. package/core/commands/mednotes/telemetry.toml +24 -0
  414. package/core/commands/report.toml +23 -0
  415. package/core/skills/THIRD_PARTY_NOTICES.md +45 -0
  416. package/core/skills/create-medical-flashcards/SKILL.md +113 -0
  417. package/core/skills/create-medical-note/SKILL.md +90 -0
  418. package/core/skills/enrich-medical-note/SKILL.md +120 -0
  419. package/core/skills/fix-medical-wiki/SKILL.md +559 -0
  420. package/core/skills/link-medical-wiki/SKILL.md +224 -0
  421. package/core/skills/obsidian-cli/SKILL.md +118 -0
  422. package/core/skills/obsidian-markdown/SKILL.md +207 -0
  423. package/core/skills/obsidian-markdown/references/CALLOUTS.md +58 -0
  424. package/core/skills/obsidian-markdown/references/EMBEDS.md +63 -0
  425. package/core/skills/obsidian-markdown/references/PROPERTIES.md +61 -0
  426. package/core/skills/obsidian-ops/SKILL.md +136 -0
  427. package/core/skills/pdf-library/SKILL.md +45 -0
  428. package/core/skills/process-medical-chats/SKILL.md +246 -0
  429. package/core/skills/workflow-report/SKILL.md +100 -0
  430. package/package.json +45 -0
@@ -0,0 +1,601 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Literal
4
+
5
+ from pydantic import Field, model_validator
6
+
7
+ from mednotes.domains.wiki.contracts.note_plan import MeaningClaim, TriageNotePlan, TriageNotePlanItem
8
+ from mednotes.kernel.agent_directive import AgentDirective
9
+ from mednotes.kernel.base import ContractModel, JsonValue
10
+ from mednotes.kernel.guardrails import OperationalErrorContext
11
+ from mednotes.kernel.public_report import WorkflowReports
12
+ from mednotes.kernel.workflow import HumanDecisionPacket, WorkflowDecisionSummary
13
+
14
+ SubagentPhase = Literal[
15
+ "triage",
16
+ "architect",
17
+ "style-rewrite",
18
+ "note-merge",
19
+ "atomicity-split",
20
+ "vocabulary-curation",
21
+ "vocabulary_curation",
22
+ "atomicity_split",
23
+ ]
24
+ SubagentName = Literal["med-chat-triager", "med-knowledge-architect", "med-link-graph-curator"]
25
+
26
+
27
+ class ExpectedOutputSchema(ContractModel):
28
+ schema_: str = Field(alias="schema", pattern=r"^medical-notes-workbench\..+\.v[0-9]+$")
29
+ description: str = Field(min_length=1)
30
+
31
+
32
+ class SubagentOutputContract(ContractModel):
33
+ schema_: Literal["medical-notes-workbench.subagent-output-contract.v1"] = Field(alias="schema")
34
+ write_markdown_to: str | None = None
35
+ subagent_must_create_attestation: bool = False
36
+ subagent_must_create_specialist_task_run_receipt: bool = False
37
+ parent_must_not_fabricate_specialist_task_run_receipt: bool = False
38
+ parent_may_call_specialist_task_receipt_finalizer: bool = False
39
+ official_receipt_finalizers: list[str] = Field(default_factory=list)
40
+ missing_specialist_task_run_receipt_action: str | None = None
41
+ parent_only_fields: list[str] = Field(default_factory=list)
42
+ runner_only_fields: list[str] = Field(default_factory=list)
43
+ attestation_created_by: str | None = None
44
+
45
+
46
+ class SubagentContextDocs(ContractModel):
47
+ schema_: Literal["medical-notes-workbench.subagent-context-docs.v1"] = Field(alias="schema")
48
+ required_read_files: list[str] = Field(default_factory=list)
49
+ forbidden_discovery_roots: list[str] = Field(default_factory=list)
50
+ agent_instruction: str = ""
51
+
52
+
53
+ class SubagentPlanAttestation(ContractModel):
54
+ schema_: Literal["medical-notes-workbench.subagent-plan-attestation.v1"] = Field(alias="schema")
55
+ phase: SubagentPhase
56
+ plan_schema: Literal[
57
+ "medical-notes-workbench.subagent-plan.v1",
58
+ "medical-notes-workbench.vocabulary-curator-batch-plan.v1",
59
+ "medical-notes-workbench.atomicity-split-plan.v1",
60
+ ]
61
+ plan_hash: str = Field(pattern=r"^sha256:[0-9a-f]{64}$")
62
+ attestation_kind: Literal["workbench_hmac_sha256.v1"]
63
+ created_by: Literal["plan-subagents"]
64
+ issued_at: str = Field(min_length=1)
65
+ nonce: str = Field(min_length=16)
66
+ signature: str = Field(pattern=r"^hmac-sha256:[0-9a-f]{64}$")
67
+
68
+
69
+ class SubagentStyleIssue(ContractModel):
70
+ """Style-audit issue copied into a work item as evidence, not state."""
71
+
72
+ code: str = ""
73
+ message: str = ""
74
+ severity: str = ""
75
+ line: int | None = None
76
+ section: str | None = None
77
+ suggested_visual: str | None = None
78
+ reason: str | None = None
79
+
80
+
81
+ class SubagentPathCaseCheck(ContractModel):
82
+ """Filesystem preflight result used by vocabulary-curator work items."""
83
+
84
+ status: str = ""
85
+ expected_path: str = ""
86
+ actual_path: str = ""
87
+
88
+
89
+ class SubagentArtifactItem(ContractModel):
90
+ kind: str = ""
91
+ chat_id: str = ""
92
+ source_url: str = ""
93
+ manifest: str = ""
94
+ file: str = ""
95
+ sha256: str = ""
96
+ turn_index: str = ""
97
+ mime_type: str = ""
98
+ caption: str = ""
99
+
100
+
101
+ class SubagentArtifactManifest(ContractModel):
102
+ schema_: str = Field(default="", alias="schema")
103
+ path: str = ""
104
+ chat_id: str = ""
105
+ source_url: str = ""
106
+ saved_count: int = Field(default=0, ge=0)
107
+ artifacts: list[SubagentArtifactItem] = Field(default_factory=list)
108
+
109
+
110
+ class SubagentPlanSource(ContractModel):
111
+ raw_file: str = Field(min_length=1)
112
+ note_plan_item_id: str = ""
113
+ planned_title: str = ""
114
+ fonte_id: str = ""
115
+ work_id: str = ""
116
+ titulo_triagem: str = ""
117
+ note_plan_item: TriageNotePlanItem | None = None
118
+
119
+
120
+ class SubagentCanonicalMergePlan(ContractModel):
121
+ schema_: Literal["medical-notes-workbench.canonical-merge-plan.v1"] = Field(alias="schema")
122
+ target_kind: Literal["new_wiki_note", "existing_wiki_note"]
123
+ target_title: str = Field(min_length=1)
124
+ target_key: str = ""
125
+ requested_title: str = ""
126
+ target_path: str = ""
127
+ existing_paths: list[str] = Field(default_factory=list)
128
+ sources: list[SubagentPlanSource] = Field(default_factory=list)
129
+ required_delta_per_source: bool = False
130
+ required_multi_reference_provenance: bool = False
131
+
132
+
133
+ class SubagentPlannedMatch(ContractModel):
134
+ raw_file: str = ""
135
+ work_id: str = ""
136
+ id: str = ""
137
+ title: str = ""
138
+
139
+
140
+ class SubagentDuplicateTarget(ContractModel):
141
+ id: str = ""
142
+ title: str = ""
143
+ target_key: str = Field(min_length=1)
144
+ conflict_type: Literal["ambiguous_existing_wiki_note", "existing_wiki_note", "planned_in_batch"]
145
+ existing_paths: list[str] = Field(default_factory=list)
146
+ planned_matches: list[SubagentPlannedMatch] = Field(default_factory=list)
147
+
148
+
149
+ class SubagentPromptIdentitySource(ContractModel):
150
+ path: str = Field(min_length=1)
151
+ exists: bool = False
152
+ sha256: str = ""
153
+ byte_count: int = Field(default=0, ge=0)
154
+ word_count: int = Field(default=0, ge=0)
155
+
156
+
157
+ class SubagentPromptIdentity(ContractModel):
158
+ schema_: str = Field(default="", alias="schema")
159
+ agent: SubagentName | str = ""
160
+ aggregate_hash: str = ""
161
+ sources: list[SubagentPromptIdentitySource] = Field(default_factory=list)
162
+
163
+
164
+ class SubagentDifficultyRoute(ContractModel):
165
+ route: str = ""
166
+ max_turns: int = Field(default=0, ge=0)
167
+ focus: list[str] = Field(default_factory=list)
168
+ efficiency_rule: str = ""
169
+
170
+
171
+ class SubagentCuratorQualityRubric(ContractModel):
172
+ primary_meaning_atomicity: str = ""
173
+ atomicity_signal: str = ""
174
+ alias_precision: str = ""
175
+ link_policy_conservatism: str = ""
176
+ defer_when_uncertain: str = ""
177
+ evidence_redaction: str = ""
178
+
179
+
180
+ class SubagentCuratorOutputContract(ContractModel):
181
+ must_include: list[str] = Field(default_factory=list)
182
+ must_not_include: list[str] = Field(default_factory=list)
183
+
184
+
185
+ class SubagentMaxTurnsPolicy(ContractModel):
186
+ max_turns: int = Field(default=0, ge=0)
187
+ on_exhaustion: str = ""
188
+
189
+
190
+ class SubagentErrorContext(ContractModel):
191
+ """Actionable context passed to a subagent without requiring a full blocker."""
192
+
193
+ phase: str = ""
194
+ blocked_reason: str = ""
195
+ root_cause: str = ""
196
+ affected_artifact: str = ""
197
+ error_summary: str = ""
198
+ suggested_fix: str = ""
199
+ next_action: str = ""
200
+ retry_scope: str = ""
201
+ human_decision_required: bool = False
202
+ missing_inputs: list[str] = Field(default_factory=list)
203
+ details: JsonValue = None
204
+
205
+
206
+ class SubagentAtomicitySchemaHint(ContractModel):
207
+ title: str = ""
208
+ target_path: str = ""
209
+ content_path: str = ""
210
+
211
+
212
+ class SubagentSemanticSignal(ContractModel):
213
+ """Atomicity evidence stays structured, but domain scoring is validated downstream."""
214
+
215
+ score: float | int | None = None
216
+ fragment_risk: str = ""
217
+ evidence: list[dict[str, JsonValue]] = Field(default_factory=list)
218
+ concepts: list[dict[str, JsonValue]] = Field(default_factory=list)
219
+ audit: dict[str, JsonValue] | None = None
220
+
221
+
222
+ class SubagentBatchRef(ContractModel):
223
+ batch: int = Field(ge=1)
224
+ max_concurrency: int = Field(ge=0)
225
+ item_count: int = Field(ge=0)
226
+ owner_keys: list[str] = Field(default_factory=list)
227
+ work_ids: list[str] = Field(default_factory=list)
228
+
229
+
230
+ class SubagentSourceAudit(ContractModel):
231
+ schema_: str = Field(default="", alias="schema")
232
+ wiki_dir: str = ""
233
+ file_count: int = Field(default=0, ge=0)
234
+ error_count: int = Field(default=0, ge=0)
235
+ warning_count: int = Field(default=0, ge=0)
236
+
237
+
238
+ class SubagentCandidateTarget(ContractModel):
239
+ path: str = ""
240
+ title: str = ""
241
+ confidence: str = ""
242
+
243
+
244
+ class SubagentMeaningPlannerWorkItem(ContractModel):
245
+ work_id: str = Field(min_length=1)
246
+ action: str = ""
247
+ target_kind: str = ""
248
+ raw_file: str = ""
249
+ note_plan_item_id: str = ""
250
+ meaning_claim: MeaningClaim | None = None
251
+ target_path: str = ""
252
+ agent: SubagentName | str = ""
253
+ item_type: str = ""
254
+ launchable: bool = False
255
+ owner_key: str = ""
256
+ temp_dir: str = ""
257
+ temp_output: str = ""
258
+
259
+
260
+ class SubagentDiagnosticContext(ContractModel):
261
+ root_cause_code: str = ""
262
+ error_context: SubagentErrorContext | OperationalErrorContext | None = None
263
+ details: dict[str, JsonValue] = Field(default_factory=dict)
264
+
265
+
266
+ class SubagentBlockedItem(ContractModel):
267
+ """Non-launchable item explaining why planning could not emit work."""
268
+
269
+ work_id: str = Field(min_length=1)
270
+ phase: SubagentPhase | None = None
271
+ agent: SubagentName | None = None
272
+ item_type: str = ""
273
+ raw_file: str = ""
274
+ owner_key: str = ""
275
+ source_work_id: str = ""
276
+ titulo_triagem: str = ""
277
+ fonte_id: str = ""
278
+ blocked_reason: str = Field(min_length=1)
279
+ reason: str = ""
280
+ next_action: str = ""
281
+ launchable: Literal[False] = False
282
+ write_policy: str = "no_temp_note"
283
+ target_key: str = ""
284
+ target_title: str = ""
285
+ duplicate_targets: list[SubagentDuplicateTarget] = Field(default_factory=list)
286
+ planned_matches: list[SubagentPlannedMatch] = Field(default_factory=list)
287
+ canonical_merge: SubagentCanonicalMergePlan | None = None
288
+ human_decision_packet: HumanDecisionPacket | None = None
289
+ human_decision_packets: list[HumanDecisionPacket] = Field(default_factory=list)
290
+ note_plan_error: str = ""
291
+ note_plan: TriageNotePlan | None = None
292
+ note_plan_item_id: str = ""
293
+ meaning_claim: MeaningClaim | None = None
294
+ candidate_targets: list[SubagentCandidateTarget] = Field(default_factory=list)
295
+ meaning_planner_work_items: list[SubagentMeaningPlannerWorkItem] = Field(default_factory=list)
296
+ note_plan_item_count: int = Field(default=0, ge=0)
297
+ note_plan_planned_meaning_count: int = Field(default=0, ge=0)
298
+ note_plan_attach_count: int = Field(default=0, ge=0)
299
+ note_plan_not_a_note_count: int = Field(default=0, ge=0)
300
+ note_plan_needs_context_count: int = Field(default=0, ge=0)
301
+
302
+
303
+ class SubagentWorkItem(ContractModel):
304
+ schema_: str | None = Field(default=None, alias="schema")
305
+ work_id: str = Field(min_length=1)
306
+ phase: SubagentPhase
307
+ agent: SubagentName
308
+ app: str | None = None
309
+ workflow: str | None = None
310
+ source_workflow: str | None = None
311
+ action: str | None = None
312
+ expected_output_schema: ExpectedOutputSchema
313
+ subagent_output_contract: SubagentOutputContract | None = None
314
+ item_type: str | None = None
315
+ mode: str | None = None
316
+ unit: str | None = None
317
+ owner_key: str | None = None
318
+ raw_file: str | None = None
319
+ titulo_triagem: str | None = None
320
+ fonte_id: str | None = None
321
+ source_work_id: str | None = None
322
+ temp_dir: str | None = None
323
+ triager_output_path: str | None = None
324
+ note_plan_path: str | None = None
325
+ triager_eval_path: str | None = None
326
+ meaning_claim: MeaningClaim | None = None
327
+ note_plan_item_count: int = Field(default=0, ge=0)
328
+ note_plan_planned_meaning_count: int = Field(default=0, ge=0)
329
+ note_plan_attach_count: int = Field(default=0, ge=0)
330
+ note_plan_not_a_note_count: int = Field(default=0, ge=0)
331
+ note_plan_needs_context_count: int = Field(default=0, ge=0)
332
+ note_path: str | None = None
333
+ note_path_exists: bool | None = None
334
+ path_case_check: SubagentPathCaseCheck | None = None
335
+ target_path: str | None = None
336
+ target_hash_before: str | None = None
337
+ title: str | None = None
338
+ rewrite_prompt: str | None = None
339
+ model_policy: str | None = None
340
+ required_model_tier: str | None = None
341
+ preferred_model_tier: str | None = None
342
+ context_docs: SubagentContextDocs | None = None
343
+ errors: list[SubagentStyleIssue] = Field(default_factory=list)
344
+ warnings: list[SubagentStyleIssue] = Field(default_factory=list)
345
+ temp_output: str | None = None
346
+ output_receipt_path: str | None = None
347
+ output_attestation_path: str | None = None
348
+ specialist_task_run_receipt_path: str | None = None
349
+ merge_action: str | None = None
350
+ target_kind: str | None = None
351
+ target_title: str | None = None
352
+ requested_title: str | None = None
353
+ target_key: str | None = None
354
+ existing_paths: list[str] = Field(default_factory=list)
355
+ source_count: int | None = Field(default=None, ge=0)
356
+ raw_files: list[str] = Field(default_factory=list)
357
+ sources: list[SubagentPlanSource] = Field(default_factory=list)
358
+ canonical_merge_plan: SubagentCanonicalMergePlan | None = None
359
+ artifact_manifest_count: int = Field(default=0, ge=0)
360
+ artifact_count: int = Field(default=0, ge=0)
361
+ artifact_manifests: list[SubagentArtifactManifest] = Field(default_factory=list)
362
+ apply_command: str | None = None
363
+ blocked_reason: str | None = None
364
+ duplicate_targets: list[SubagentDuplicateTarget] = Field(default_factory=list)
365
+ planned_matches: list[SubagentPlannedMatch] = Field(default_factory=list)
366
+ reason: str | None = None
367
+ next_action: str | None = None
368
+ canonical_merge: SubagentCanonicalMergePlan | None = None
369
+ human_decision_packet: HumanDecisionPacket | None = None
370
+ human_decision_packets: list[HumanDecisionPacket] = Field(default_factory=list)
371
+ launchable: bool | None = None
372
+ write_policy: str | None = None
373
+ note_plan_error: str | None = None
374
+ note_plan: TriageNotePlan | None = None
375
+ planned_title: str | None = None
376
+ note_plan_item_id: str | None = None
377
+ note_plan_item: TriageNotePlanItem | None = None
378
+ meaning_planner_work_items: list[SubagentMeaningPlannerWorkItem] = Field(default_factory=list)
379
+ artifact_manifest_error: str | None = None
380
+ db_path: str | None = None
381
+ content_hash: str | None = None
382
+ queue_flags: list[str] = Field(default_factory=list)
383
+ output_path: str | None = None
384
+ prompt_identity: SubagentPromptIdentity | None = None
385
+ difficulty_route: SubagentDifficultyRoute | None = None
386
+ quality_rubric: SubagentCuratorQualityRubric | None = None
387
+ output_contract: SubagentCuratorOutputContract | None = None
388
+ allowed_actions: list[str] = Field(default_factory=list)
389
+ forbidden_actions: list[str] = Field(default_factory=list)
390
+ stop_conditions: list[str] = Field(default_factory=list)
391
+ retry_scope: str | None = None
392
+ max_turns_policy: SubagentMaxTurnsPolicy | None = None
393
+ error_context: SubagentErrorContext | None = None
394
+ instructions: list[str] = Field(default_factory=list)
395
+ source_path: str | None = None
396
+ source_hash: str | None = None
397
+ bundle_output_path: str | None = None
398
+ temp_markdown_dir: str | None = None
399
+ semantic_signal: SubagentSemanticSignal | None = None
400
+ atomicity_decision: str | None = None
401
+ allowed_strategies: list[str] = Field(default_factory=list)
402
+ required_bundle_fields: list[str] = Field(default_factory=list)
403
+ replacement_source_schema: SubagentAtomicitySchemaHint | None = None
404
+ created_notes_item_schema: SubagentAtomicitySchemaHint | None = None
405
+
406
+ @model_validator(mode="after")
407
+ def agent_matches_phase(self) -> SubagentWorkItem:
408
+ expected = {
409
+ "triage": "med-chat-triager",
410
+ "architect": "med-knowledge-architect",
411
+ "style-rewrite": "med-knowledge-architect",
412
+ "note-merge": "med-knowledge-architect",
413
+ "atomicity-split": "med-knowledge-architect",
414
+ "atomicity_split": "med-knowledge-architect",
415
+ "vocabulary-curation": "med-link-graph-curator",
416
+ "vocabulary_curation": "med-link-graph-curator",
417
+ }[self.phase]
418
+ if self.agent != expected:
419
+ raise ValueError("subagent agent must match phase")
420
+ if self.phase == "style-rewrite":
421
+ contract = self.subagent_output_contract
422
+ if contract is None:
423
+ raise ValueError("style-rewrite work items require subagent_output_contract")
424
+ if contract.write_markdown_to != "temp_output":
425
+ raise ValueError("style-rewrite subagent must write Markdown only to temp_output")
426
+ if contract.subagent_must_create_attestation:
427
+ raise ValueError("style-rewrite subagent must not create output attestation")
428
+ if contract.subagent_must_create_specialist_task_run_receipt:
429
+ raise ValueError("style-rewrite subagent must not create specialist task run receipt")
430
+ if not contract.parent_must_not_fabricate_specialist_task_run_receipt:
431
+ raise ValueError("style-rewrite parent must not fabricate specialist task run receipt")
432
+ if not contract.parent_may_call_specialist_task_receipt_finalizer:
433
+ raise ValueError("style-rewrite parent must call the official specialist receipt finalizer")
434
+ if "finalize-agy-specialist-task" not in contract.official_receipt_finalizers:
435
+ raise ValueError("style-rewrite AGY receipt finalizer must be declared")
436
+ if "finalize-opencode-specialist-task" not in contract.official_receipt_finalizers:
437
+ raise ValueError("style-rewrite OpenCode receipt finalizer must be declared")
438
+ if contract.missing_specialist_task_run_receipt_action != "run_official_receipt_finalizer_or_stop":
439
+ raise ValueError("style-rewrite missing specialist receipt action must run finalizer or stop")
440
+ if "output_attestation_path" not in contract.parent_only_fields:
441
+ raise ValueError("style-rewrite output_attestation_path must be parent-only")
442
+ if "specialist_task_run_receipt_path" not in contract.runner_only_fields:
443
+ raise ValueError("style-rewrite specialist_task_run_receipt_path must be runner-only")
444
+ if contract.attestation_created_by != "finalize-style-rewrite-output":
445
+ raise ValueError("style-rewrite attestation must be created by finalize-style-rewrite-output")
446
+ return self
447
+
448
+
449
+ class SpecialistContinuationWorkItem(ContractModel):
450
+ work_id: str = Field(min_length=1)
451
+ phase: Literal["style-rewrite"] = "style-rewrite"
452
+ agent: Literal["med-knowledge-architect"] = "med-knowledge-architect"
453
+ item_type: str = ""
454
+ target_path: str = Field(min_length=1)
455
+ target_hash_before: str = Field(pattern=r"^sha256:[0-9a-f]{64}$")
456
+ title: str = ""
457
+ rewrite_prompt: str = Field(min_length=1)
458
+ model_policy: str = "medical_specialist_authoring.v1"
459
+ required_model_tier: str = Field(min_length=1)
460
+ preferred_model_tier: str = ""
461
+ temp_output: str = Field(min_length=1)
462
+ specialist_task_run_receipt_path: str = Field(min_length=1)
463
+ subagent_output_contract: SubagentOutputContract
464
+
465
+
466
+ class SubagentBatchPlan(ContractModel):
467
+ schema_: Literal[
468
+ "medical-notes-workbench.subagent-plan.v1",
469
+ "medical-notes-workbench.vocabulary-curator-batch-plan.v1",
470
+ "medical-notes-workbench.atomicity-split-plan.v1",
471
+ ] = Field(alias="schema")
472
+ workflow: str | None = None
473
+ phase: SubagentPhase
474
+ status: Literal["ready", "skipped", "blocked", "completed", "ready_with_blockers"]
475
+ process_chats_terminal_state: Literal["no_pending"] | None = None
476
+ skipped_reason: str = ""
477
+ blocked_reason: str = ""
478
+ next_action: str = ""
479
+ required_inputs: list[str] = Field(default_factory=list)
480
+ human_decision_required: bool = False
481
+ human_decision_packet: HumanDecisionPacket | None = None
482
+ human_decision_packets: list[HumanDecisionPacket] = Field(default_factory=list)
483
+ decision_summary: WorkflowDecisionSummary | None = None
484
+ diagnostic_context: SubagentDiagnosticContext | None = None
485
+ reports: WorkflowReports | None = None
486
+ agent: SubagentName | None = None
487
+ mode: str | None = None
488
+ item_type: str | None = None
489
+ unit: str | None = None
490
+ batch_id: str | None = None
491
+ db_path: str | None = None
492
+ source_fix_wiki_plan_path: str | None = None
493
+ source_plan_hash: str | None = None
494
+ source_snapshot_hash: str | None = None
495
+ prompt_identity: SubagentPromptIdentity | None = None
496
+ prompt_eval_report_path: str | None = None
497
+ max_concurrency: int = Field(default=0, ge=0)
498
+ item_count: int = Field(ge=0)
499
+ total_available_count: int = Field(default=0, ge=0)
500
+ blocked_item_count: int = Field(ge=0)
501
+ blocked_items: list[SubagentBlockedItem] = Field(default_factory=list)
502
+ canonical_merge_item_count: int = Field(default=0, ge=0)
503
+ limit: int | None = Field(default=None, ge=1)
504
+ truncated: bool = False
505
+ parallel_safe: bool = False
506
+ launch_source: str | None = None
507
+ batch_contract: str | None = None
508
+ work_items: list[SubagentWorkItem] = Field(default_factory=list)
509
+ batches: list[SubagentBatchRef] = Field(default_factory=list)
510
+ rules: list[str] = Field(default_factory=list)
511
+ serial_after: list[str] = Field(default_factory=list)
512
+ source_audit: SubagentSourceAudit | None = None
513
+ parent_applies_outputs: bool = False
514
+ canonical_parent_commands: list[str] = Field(default_factory=list)
515
+ agent_directive: AgentDirective | None = None
516
+ plan_attestation: SubagentPlanAttestation | None = None
517
+
518
+ @model_validator(mode="after")
519
+ def counts_and_parent_commands_must_match(self) -> SubagentBatchPlan:
520
+ if self.item_count != len(self.work_items):
521
+ raise ValueError("item_count must match work_items length")
522
+ if self.status == "ready" and self.item_count == 0:
523
+ raise ValueError("ready subagent plans require work_items")
524
+ if self.parent_applies_outputs and not self.canonical_parent_commands:
525
+ raise ValueError("parent_applies_outputs requires canonical_parent_commands")
526
+ return self
527
+
528
+
529
+ class NextSpecialistTask(ContractModel):
530
+ schema_: Literal["medical-notes-workbench.next-specialist-task.v1"] = Field(
531
+ alias="schema",
532
+ serialization_alias="schema",
533
+ )
534
+ kind: Literal["call_specialist_model"] = "call_specialist_model"
535
+ work_id: str = Field(min_length=1)
536
+ agent: SubagentName
537
+ title: str = ""
538
+ execution_mode: Literal["parallel_authoring_serial_apply"] = "parallel_authoring_serial_apply"
539
+ authoring_mode: Literal["parallel"] = "parallel"
540
+ authoring_max_concurrency: int = Field(default=1, ge=1)
541
+ apply_mode: Literal["serial"] = "serial"
542
+ serial_apply_required: bool = True
543
+ wait_for_all_authoring_outputs_before_apply: bool = True
544
+ current_batch_items: list[SpecialistContinuationWorkItem] = Field(default_factory=list, max_length=1)
545
+ agent_instruction: str = Field(min_length=1)
546
+
547
+ @model_validator(mode="after")
548
+ def specialist_work_item_is_actionable(self) -> NextSpecialistTask:
549
+ if self.current_batch_items and self.current_batch_items[0].work_id != self.work_id:
550
+ raise ValueError("next specialist task current_batch_items[0].work_id must match work_id")
551
+ return self
552
+
553
+
554
+ class PlanOutputReceiptWorkItem(ContractModel):
555
+ work_id: str = Field(min_length=1)
556
+ phase: SubagentPhase
557
+ agent: SubagentName
558
+ title: str = ""
559
+ item_type: str = ""
560
+
561
+
562
+ class PlanOutputReceipt(ContractModel):
563
+ schema_: Literal["medical-notes-workbench.plan-output-receipt.v1"] = Field(
564
+ alias="schema",
565
+ serialization_alias="schema",
566
+ )
567
+ phase: Literal["plan-subagents"]
568
+ status: Literal["written", "blocked"]
569
+ blocked_reason: str = ""
570
+ next_action: str = ""
571
+ required_inputs: list[str] = Field(default_factory=list)
572
+ human_decision_required: bool = False
573
+ plan_path: str = Field(min_length=1)
574
+ plan_schema: str = Field(min_length=1)
575
+ plan_phase: SubagentPhase
576
+ plan_attestation: SubagentPlanAttestation | None = None
577
+ plan_hash: str = ""
578
+ plan_status: str = Field(min_length=1)
579
+ item_count: int = Field(ge=0)
580
+ blocked_item_count: int = Field(ge=0)
581
+ batch_id: str = ""
582
+ current_batch_items: list[PlanOutputReceiptWorkItem] = Field(default_factory=list)
583
+ agent_directive: AgentDirective | None = None
584
+ error_context: OperationalErrorContext | None = None
585
+
586
+ @model_validator(mode="after")
587
+ def receipt_matches_status(self) -> PlanOutputReceipt:
588
+ if self.status == "blocked":
589
+ if not self.blocked_reason:
590
+ raise ValueError("blocked plan output receipt requires blocked_reason")
591
+ if not self.next_action:
592
+ raise ValueError("blocked plan output receipt requires next_action")
593
+ if (
594
+ self.status == "written"
595
+ and self.plan_status == "ready"
596
+ and self.plan_phase == "style-rewrite"
597
+ and self.current_batch_items
598
+ and self.agent_directive is None
599
+ ):
600
+ raise ValueError("ready written plan output receipt requires agent_directive")
601
+ return self