@khoavu882/doflow 2.0.0-beta.5 → 2.0.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 (494) hide show
  1. package/README.md +16 -16
  2. package/bin/doflow.js +22 -12
  3. package/core/.antigravity-plugin/plugin.json +1 -2
  4. package/core/.claude-plugin/plugin.json +1 -1
  5. package/core/.codex-plugin/plugin.json +1 -1
  6. package/core/.plugin/plugin.json +1 -1
  7. package/core/harnesses/claude/hooks/lib.sh +43 -24
  8. package/core/harnesses/claude/hooks/mcp-tool-guard.sh +4 -1
  9. package/core/harnesses/claude/hooks/permission-audit.sh +3 -0
  10. package/core/harnesses/claude/hooks/post-compact.sh +35 -32
  11. package/core/harnesses/claude/hooks/post-edit-lint.sh +2 -0
  12. package/core/harnesses/claude/hooks/post-shell-observe.sh +48 -0
  13. package/core/harnesses/claude/hooks/post-tool-failure.sh +3 -0
  14. package/core/harnesses/claude/hooks/pre-compact.sh +23 -27
  15. package/core/harnesses/claude/hooks/pre-implement-gate.sh +4 -1
  16. package/core/harnesses/claude/hooks/session-end.sh +23 -10
  17. package/core/harnesses/claude/hooks/skill-config-audit.sh +3 -0
  18. package/core/harnesses/claude/settings/settings.json +26 -9
  19. package/core/harnesses/claude/statusline/doflow-statusline.sh +1 -0
  20. package/core/harnesses/codex/agents/core-implementer.toml +1 -0
  21. package/core/harnesses/codex/agents/delivery-lead.toml +10 -0
  22. package/core/harnesses/codex/agents/quality-guardian.toml +1 -1
  23. package/core/harnesses/codex/agents/research-writer.toml +1 -1
  24. package/core/harnesses/codex/agents/reviewer.toml +10 -0
  25. package/core/harnesses/codex/agents/spec-analyst.toml +1 -1
  26. package/core/harnesses/codex/agents/system-architect.toml +1 -1
  27. package/core/harnesses/codex/hooks/hooks.json +0 -10
  28. package/core/harnesses/codex/hooks/lib.sh +44 -25
  29. package/core/harnesses/codex/hooks/mcp-tool-guard.sh +4 -1
  30. package/core/harnesses/codex/hooks/post-edit-lint.impl.sh +3 -1
  31. package/core/harnesses/codex/hooks/pre-compact.impl.sh +29 -26
  32. package/core/harnesses/codex/hooks/pre-implement-gate.sh +4 -1
  33. package/core/harnesses/codex/hooks/session-end.impl.sh +23 -10
  34. package/core/harnesses/codex/hooks/subagent-audit.sh +1 -0
  35. package/core/harnesses/copilot/hooks/doflow-lib.sh +94 -0
  36. package/core/harnesses/copilot/hooks/doflow-mcp-tool-guard.sh +9 -0
  37. package/core/harnesses/copilot/hooks/doflow-pre-implement-gate.sh +9 -0
  38. package/core/harnesses/copilot/hooks/doflow-session-start.sh +9 -0
  39. package/core/harnesses/copilot/hooks/doflow-stop-check.sh +9 -0
  40. package/core/harnesses/copilot/hooks/doflow-subagent-start.sh +9 -0
  41. package/core/harnesses/copilot/hooks/doflow-subagent-stop.sh +9 -0
  42. package/core/harnesses/copilot/hooks/doflow.json +51 -0
  43. package/core/harnesses/kiro/agents/doflow.json +1 -11
  44. package/core/harnesses/kiro/hooks/doflow.json +0 -10
  45. package/core/harnesses/kiro/hooks/lib.sh +26 -6
  46. package/core/harnesses/kiro/hooks/mcp-tool-guard.sh +8 -3
  47. package/core/harnesses/kiro/hooks/pre-implement-gate.sh +8 -3
  48. package/core/harnesses/kiro/hooks/session-start.sh +1 -0
  49. package/core/harnesses/kiro/hooks/stop-check.sh +1 -0
  50. package/core/harnesses/pi/extensions/doflow-guard.js +11 -2
  51. package/core/harnesses/shared/hooks/ENVELOPE_MIGRATION.md +1 -2
  52. package/core/harnesses/shared/hooks/adapters/antigravity.js +1 -1
  53. package/core/harnesses/shared/hooks/bridge/bridge.sh +126 -23
  54. package/core/harnesses/shared/hooks/bridge/envelope.jq +87 -18
  55. package/core/harnesses/shared/hooks/bridge/observe-model.sh +75 -0
  56. package/core/harnesses/shared/hooks/bridge/respond.sh +16 -2
  57. package/core/harnesses/shared/hooks/policies/capture-failure.sh +49 -16
  58. package/core/harnesses/shared/hooks/policies/compact-text.sh +46 -0
  59. package/core/harnesses/shared/hooks/policies/contract.sh +3 -0
  60. package/core/harnesses/shared/hooks/policies/deny-json.sh +20 -7
  61. package/core/harnesses/shared/hooks/policies/emission-rules.sh +37 -0
  62. package/core/harnesses/shared/hooks/policies/emission.jq +209 -0
  63. package/core/harnesses/shared/hooks/policies/emission.sh +383 -0
  64. package/core/harnesses/shared/hooks/policies/identity.sh +177 -0
  65. package/core/harnesses/shared/hooks/policies/lib.sh +63 -40
  66. package/core/harnesses/shared/hooks/policies/mcp-policy.conf +1 -1
  67. package/core/harnesses/shared/hooks/policies/mcp-tool-guard.sh +7 -8
  68. package/core/harnesses/shared/hooks/policies/pre-implementation-gate.sh +132 -57
  69. package/core/harnesses/shared/hooks/policies/session-context.sh +30 -1
  70. package/core/harnesses/shared/hooks/policies/stop-check.sh +27 -15
  71. package/core/harnesses/shared/hooks/policies/subagent-audit.sh +6 -3
  72. package/core/harnesses/shared/hooks/policies/summary-store.sh +347 -0
  73. package/core/harnesses/shared/hooks/policies/user-prompt-submit.sh +60 -155
  74. package/core/harnesses/shared/hooks/stream-hook-runner.js +58 -20
  75. package/core/harnesses/shared/locator/doflow-run +2 -3
  76. package/core/registry/advice.json +3 -3
  77. package/core/registry/assets.json +55 -82
  78. package/core/registry/capabilities.json +12 -0
  79. package/core/registry/contracts.json +58 -31
  80. package/core/registry/contribution-points.json +35 -0
  81. package/core/registry/gates.json +32 -0
  82. package/core/registry/guidance-caps.json +40 -0
  83. package/core/registry/harnesses.json +1445 -366
  84. package/core/registry/intake.json +53 -0
  85. package/core/registry/lifecycle.json +599 -996
  86. package/core/registry/mcp.json +5 -1
  87. package/core/registry/models.json +7 -1
  88. package/core/registry/package-templates/README.md +19 -0
  89. package/core/registry/package-templates/agent/files/agent.md +9 -0
  90. package/core/registry/package-templates/agent/template.json +4 -0
  91. package/core/registry/package-templates/capability-provider/files/provider.json +9 -0
  92. package/core/registry/package-templates/capability-provider/template.json +11 -0
  93. package/core/registry/package-templates/debate-preset/files/preset.json +26 -0
  94. package/core/registry/package-templates/debate-preset/template.json +4 -0
  95. package/core/registry/package-templates/intake-category/files/category.json +8 -0
  96. package/core/registry/package-templates/intake-category/template.json +4 -0
  97. package/core/registry/package-templates/review-preset/files/preset.json +30 -0
  98. package/core/registry/package-templates/review-preset/template.json +4 -0
  99. package/core/registry/package-templates/skill/files/SKILL.md +8 -0
  100. package/core/registry/package-templates/skill/template.json +4 -0
  101. package/core/registry/package-templates/worker/files/worker.json +92 -0
  102. package/core/registry/package-templates/worker/template.json +11 -0
  103. package/core/registry/packages/doflow/doflow-package.json +15 -0
  104. package/core/registry/packages/doflow/presets/debate-3.json +26 -0
  105. package/core/registry/protocols.json +61 -0
  106. package/core/registry/routes.json +17 -0
  107. package/core/registry/rules.json +431 -0
  108. package/core/registry/settings.json +272 -0
  109. package/core/registry/storage.json +687 -31
  110. package/core/registry/telemetry.json +236 -0
  111. package/core/registry/transcripts.json +142 -0
  112. package/core/registry/verification.json +76 -6
  113. package/core/registry/workflows.json +55 -0
  114. package/core/shared/agent-specs/core-implementer.md +3 -0
  115. package/core/shared/agent-specs/delivery-lead.md +68 -0
  116. package/core/shared/agent-specs/quality-guardian.md +5 -1
  117. package/core/shared/agent-specs/research-writer.md +10 -3
  118. package/core/shared/agent-specs/reviewer.md +53 -0
  119. package/core/shared/agent-specs/spec-analyst.md +5 -6
  120. package/core/shared/agent-specs/system-architect.md +5 -1
  121. package/core/shared/guidance/DOFLOW_CORE.md +1 -5
  122. package/core/shared/guidance/modes/MODE_DeepResearch.md +1 -1
  123. package/core/shared/guidance/modes/MODE_Orchestration.md +4 -3
  124. package/core/shared/guidance/modes/MODE_Task_Management.md +14 -14
  125. package/core/shared/guidance/pointers/codex.md +1 -4
  126. package/core/shared/guidance/references/ARTIFACT_FORMAT.md +30 -16
  127. package/core/shared/guidance/references/ARTIFACT_VOICE.md +3 -2
  128. package/core/shared/guidance/references/CONSTITUTION_BASE.md +17 -15
  129. package/core/shared/guidance/references/DIAGRAM_GUIDE.md +1 -1
  130. package/core/shared/guidance/references/DOFLOW_CHAIN.md +17 -19
  131. package/core/shared/guidance/references/EVIDENCE_LEDGER.md +7 -8
  132. package/core/shared/guidance/references/MODEL_SELECTION.md +5 -3
  133. package/core/shared/guidance/references/ORCHESTRATION.md +3 -2
  134. package/core/shared/guidance/references/WORKFLOW_HANDOFF.md +19 -1
  135. package/core/shared/guidance/rules/RULES.md +45 -0
  136. package/core/shared/scripts/doflow/bash/do-args.sh +37 -0
  137. package/core/shared/scripts/doflow/bash/do-exec-paths.sh +4 -0
  138. package/core/shared/scripts/doflow/bash/do-git-state.sh +15 -4
  139. package/core/shared/scripts/doflow/bash/do-parallel-check.sh +4 -0
  140. package/core/shared/scripts/doflow/bash/do-paths.sh +40 -2
  141. package/core/shared/scripts/doflow/bash/do-prereqs.sh +2 -1
  142. package/core/shared/scripts/doflow/bash/do-review-package.sh +4 -0
  143. package/core/shared/scripts/doflow/bash/do-task-brief.sh +58 -16
  144. package/core/shared/scripts/doflow/bash/render-audit.sh +26 -2
  145. package/core/shared/scripts/doflow/bash/render-diagrams.sh +1 -0
  146. package/core/shared/scripts/doflow/bash/render-puml.sh +2 -1
  147. package/core/shared/scripts/doflow/bash/validate-artifacts.sh +49 -5
  148. package/core/shared/scripts/doflow/bin/doflow-run +152 -34
  149. package/core/shared/skills/do/SKILL.md +14 -12
  150. package/core/shared/skills/do/references/advice_calls.md +26 -0
  151. package/core/shared/skills/do/references/pm_routing.md +1 -2
  152. package/core/shared/skills/do/references/program_mode.md +31 -0
  153. package/core/shared/skills/do-brainstorm/SKILL.md +45 -97
  154. package/core/shared/skills/do-brainstorm/references/handoff_branches.md +36 -0
  155. package/core/shared/skills/do-brainstorm/references/intent_seed.md +21 -0
  156. package/core/shared/skills/do-brainstorm/references/round_log.md +17 -0
  157. package/core/shared/skills/do-code-review/SKILL.md +48 -148
  158. package/core/shared/skills/do-code-review/content-types/markdown.md +24 -2
  159. package/core/shared/skills/do-code-review/references/tools.md +90 -0
  160. package/core/shared/skills/do-code-review/scripts/doc_quality_checker.py +549 -7
  161. package/core/shared/skills/do-design/SKILL.md +23 -20
  162. package/core/shared/skills/do-diagnose/SKILL.md +18 -6
  163. package/core/shared/skills/do-document/SKILL.md +12 -1
  164. package/core/shared/skills/do-document/references/deep_research.md +1 -2
  165. package/core/shared/skills/do-document/references/embedded-research.md +19 -7
  166. package/core/shared/skills/do-document/references/implementation-flow.md +5 -6
  167. package/core/shared/skills/do-execute-plan/SKILL.md +19 -60
  168. package/core/shared/skills/do-execute-plan/references/handoff_record.md +7 -2
  169. package/core/shared/skills/do-execute-plan/references/parallel_dispatch.md +13 -0
  170. package/core/shared/skills/do-execute-plan/references/readiness_gate.md +26 -1
  171. package/core/shared/skills/do-execute-plan/references/run_position.md +16 -2
  172. package/core/shared/skills/do-execute-plan/references/scaffold.md +17 -9
  173. package/core/shared/skills/do-execute-plan/references/state_checkpoint.md +11 -0
  174. package/core/shared/skills/do-execute-plan/references/task_attempts.md +78 -24
  175. package/core/shared/skills/do-flow/SKILL.md +10 -11
  176. package/core/shared/skills/do-flow/references/task_classes.md +5 -5
  177. package/core/shared/skills/do-git/SKILL.md +4 -0
  178. package/core/shared/skills/do-implement/SKILL.md +13 -14
  179. package/core/shared/skills/do-plan/SKILL.md +34 -20
  180. package/core/shared/skills/do-test/SKILL.md +7 -4
  181. package/core/shared/templates/doflow/constitution-template.md +9 -3
  182. package/core/shared/templates/doflow/data-model-template.md +1 -1
  183. package/core/shared/templates/doflow/design-template.md +113 -16
  184. package/core/shared/templates/doflow/plan-template.md +11 -10
  185. package/core/shared/templates/doflow/question-log-template.md +14 -2
  186. package/core/shared/templates/doflow/requirement-template.md +1 -1
  187. package/core/shared/workflows/do-flow-chain.md +2 -0
  188. package/core/worker-evidence/antigravity/checks.json +14 -0
  189. package/core/worker-evidence/codex/2026-10-18-cli-check.json +107 -0
  190. package/core/worker-evidence/codex/2026-10-18-live-run-edit.json +73 -0
  191. package/core/worker-evidence/codex/2026-10-18-live-run-read-only.json +62 -0
  192. package/core/worker-evidence/codex/2026-10-24-cli-check.json +126 -0
  193. package/core/worker-evidence/codex/checks.json +38 -0
  194. package/package.json +10 -6
  195. package/src/adapters/antigravity/index.js +143 -66
  196. package/src/adapters/claude/index.js +46 -5
  197. package/src/adapters/codex/agents.js +25 -15
  198. package/src/adapters/codex/hooks.js +39 -3
  199. package/src/adapters/codex/index.js +61 -13
  200. package/src/adapters/codex/native-projection.js +6 -2
  201. package/src/adapters/copilot/index.js +58 -23
  202. package/src/adapters/copy-tree.js +291 -46
  203. package/src/adapters/guidance-manifest.js +71 -0
  204. package/src/adapters/guidance-pointer.js +19 -0
  205. package/src/adapters/hook-commands.js +6 -10
  206. package/src/adapters/index.js +1 -0
  207. package/src/adapters/kiro/index.js +23 -12
  208. package/src/adapters/opencode/index.js +8 -8
  209. package/src/adapters/pi/hooks.js +2 -1
  210. package/src/adapters/pi/index.js +14 -7
  211. package/src/adapters/resolve-source.js +26 -2
  212. package/src/cli/commands/install.js +2 -1
  213. package/src/cli/commands/reconcile.js +53 -9
  214. package/src/cli/commands/remove.js +2 -2
  215. package/src/cli/commands/rollback.js +6 -3
  216. package/src/cli/commands/self-update.js +18 -9
  217. package/src/cli/commands/status.js +22 -3
  218. package/src/cli/commands/ui.js +99 -0
  219. package/src/cli/commands/update.js +2 -1
  220. package/src/cli/index.js +337 -32
  221. package/src/cli/runtime-commands.js +220 -60
  222. package/src/cli/shared.js +0 -2
  223. package/src/helper/git.js +1 -1
  224. package/src/helper/guardrails.js +1 -1
  225. package/src/helper/marker-merge.js +31 -13
  226. package/src/helper/package-ids.js +37 -0
  227. package/src/helper/semver.js +94 -0
  228. package/src/install/backup.js +105 -15
  229. package/src/install/context.js +1 -1
  230. package/src/install/targets.js +31 -16
  231. package/src/lifecycle/coverage.js +4 -16
  232. package/src/lifecycle/hook-tier.js +160 -0
  233. package/src/lifecycle/index.js +412 -78
  234. package/src/lifecycle/retired-harnesses.js +318 -0
  235. package/src/lifecycle/view.js +35 -15
  236. package/src/registry/index.js +551 -26
  237. package/src/registry/worker-ids.js +45 -0
  238. package/src/release/build-package.js +0 -3
  239. package/src/release/docs-blocks.js +472 -0
  240. package/src/release/preflight.js +425 -0
  241. package/src/release/rehearse.js +401 -0
  242. package/src/release/release-workflow.js +733 -0
  243. package/src/release/sync-plugin-versions.js +43 -7
  244. package/src/runtime/advice/bench-gate.js +25 -0
  245. package/src/runtime/advice/cli.js +59 -16
  246. package/src/runtime/advice/client.js +32 -9
  247. package/src/runtime/advice/config.js +98 -133
  248. package/src/runtime/advice/doctor.js +1 -1
  249. package/src/runtime/advice/elevation.js +97 -0
  250. package/src/runtime/advice/endpoint-guard.js +9 -3
  251. package/src/runtime/advice/mode.js +37 -0
  252. package/src/runtime/advice/record.js +18 -5
  253. package/src/runtime/advice/registry.js +4 -1
  254. package/src/runtime/advice/shadow-config.js +229 -0
  255. package/src/runtime/advice/shadow-dispatcher.js +276 -0
  256. package/src/runtime/brief-rules.js +81 -0
  257. package/src/runtime/brief-tools.js +111 -34
  258. package/src/runtime/candidate.js +20 -11
  259. package/src/runtime/capabilities/executor.js +450 -0
  260. package/src/runtime/capabilities/loopback.js +41 -0
  261. package/src/runtime/capabilities/sanitizer.js +88 -0
  262. package/src/runtime/capability-router.js +135 -3
  263. package/src/runtime/checkouts.js +73 -11
  264. package/src/runtime/claims.js +13 -7
  265. package/src/runtime/cli.js +196 -19
  266. package/src/runtime/config-home.js +42 -0
  267. package/src/runtime/context/arbitrate.js +767 -0
  268. package/src/runtime/context/delivery-store.js +4 -6
  269. package/src/runtime/context/emission-rules.js +118 -0
  270. package/src/runtime/context/identity.js +227 -0
  271. package/src/runtime/context/pointer.js +67 -12
  272. package/src/runtime/context/primary-command.js +117 -0
  273. package/src/runtime/context/primary.js +344 -0
  274. package/src/runtime/context/summary-store.js +655 -0
  275. package/src/runtime/context-pack.js +158 -79
  276. package/src/runtime/decision-register.js +13 -4
  277. package/src/runtime/dispatch/admission.js +392 -0
  278. package/src/runtime/dispatch/attempt-end.js +274 -0
  279. package/src/runtime/dispatch/command.js +628 -0
  280. package/src/runtime/dispatch/controls.js +904 -0
  281. package/src/runtime/dispatch/envelope.js +276 -0
  282. package/src/runtime/dispatch/grants.js +310 -0
  283. package/src/runtime/dispatch/integrate.js +617 -0
  284. package/src/runtime/dispatch/loop.js +1835 -0
  285. package/src/runtime/dispatch/store.js +352 -0
  286. package/src/runtime/dispatch/verify-run.js +201 -0
  287. package/src/runtime/evidence-ledger.js +52 -7
  288. package/src/runtime/failure/capture.js +3 -1
  289. package/src/runtime/failure/cli.js +25 -9
  290. package/src/runtime/failure/home.js +57 -30
  291. package/src/runtime/failure/store.js +7 -2
  292. package/src/runtime/feature-pointer.js +174 -0
  293. package/src/runtime/feature-resolve.js +13 -2
  294. package/src/runtime/fleet/command.js +77 -0
  295. package/src/runtime/fleet/projects.js +178 -0
  296. package/src/runtime/fleet/tree.js +383 -0
  297. package/src/runtime/freshness.js +33 -3
  298. package/src/runtime/git-memo.js +46 -0
  299. package/src/runtime/guidance/ablation.js +427 -0
  300. package/src/runtime/health.js +624 -18
  301. package/src/runtime/history-compactor.js +13 -3
  302. package/src/runtime/implementation-gate.js +281 -26
  303. package/src/runtime/intake/engine.js +677 -0
  304. package/src/runtime/intake/index.js +136 -0
  305. package/src/runtime/intake/manifest.js +140 -0
  306. package/src/runtime/intake/taxonomy.js +206 -0
  307. package/src/runtime/inventory/coverage.js +1 -1
  308. package/src/runtime/inventory/index.js +1 -1
  309. package/src/runtime/inventory/precedence.js +2 -2
  310. package/src/runtime/inventory/siblings.js +6 -4
  311. package/src/runtime/knowledge/code-corpus.js +277 -0
  312. package/src/runtime/knowledge/code-lexical.js +130 -0
  313. package/src/runtime/knowledge/code-retrieval.js +307 -0
  314. package/src/runtime/knowledge/code-validation.js +106 -0
  315. package/src/runtime/knowledge/gp3-gate.js +74 -0
  316. package/src/runtime/knowledge/graph-adapter.js +288 -0
  317. package/src/runtime/knowledge/graph-fallback.js +394 -0
  318. package/src/runtime/knowledge/hybrid.js +136 -8
  319. package/src/runtime/knowledge/retrieval.js +34 -1
  320. package/src/runtime/knowledge/rtk-compress.js +77 -0
  321. package/src/runtime/knowledge/semble-bridge.py +106 -0
  322. package/src/runtime/knowledge/semble-lifecycle.js +114 -0
  323. package/src/runtime/knowledge/semble-provider.js +365 -0
  324. package/src/runtime/lifecycle/cli.js +88 -10
  325. package/src/runtime/lifecycle/event-store.js +8 -6
  326. package/src/runtime/lifecycle/followup.js +38 -7
  327. package/src/runtime/lifecycle/overview.js +26 -2
  328. package/src/runtime/lifecycle/report-store.js +8 -10
  329. package/src/runtime/lifecycle/retention.js +95 -31
  330. package/src/runtime/lifecycle/root.js +9 -1
  331. package/src/runtime/lifecycle/status.js +34 -17
  332. package/src/runtime/lifecycle/store-upkeep.js +56 -7
  333. package/src/runtime/mask.js +134 -7
  334. package/src/runtime/mcp-consultations.js +40 -6
  335. package/src/runtime/model-router.js +79 -7
  336. package/src/runtime/models/catalogue.js +191 -0
  337. package/src/runtime/models/command.js +153 -0
  338. package/src/runtime/off-words.js +12 -0
  339. package/src/runtime/outcome.js +2 -2
  340. package/src/runtime/packages/command.js +1009 -0
  341. package/src/runtime/packages/contributions.js +116 -0
  342. package/src/runtime/packages/digest.js +132 -0
  343. package/src/runtime/packages/fetch.js +182 -0
  344. package/src/runtime/packages/grants.js +192 -0
  345. package/src/runtime/packages/index-file.js +134 -0
  346. package/src/runtime/packages/instruction.js +90 -0
  347. package/src/runtime/packages/manifest.js +331 -0
  348. package/src/runtime/packages/points.js +487 -0
  349. package/src/runtime/packages/programs.js +216 -0
  350. package/src/runtime/packages/scaffold.js +277 -0
  351. package/src/runtime/packages/source.js +90 -0
  352. package/src/runtime/packages/state.js +164 -0
  353. package/src/runtime/packages/store.js +449 -0
  354. package/src/runtime/packages/tar.js +106 -0
  355. package/src/runtime/packages/view.js +406 -0
  356. package/src/runtime/plan-check.js +59 -0
  357. package/src/runtime/plan-content.js +324 -0
  358. package/src/runtime/policy-init.js +118 -0
  359. package/src/runtime/profiles/doctor.js +96 -0
  360. package/src/runtime/profiles/resolve.js +244 -0
  361. package/src/runtime/profiles/rollback.js +254 -0
  362. package/src/runtime/profiles/sampler.js +41 -0
  363. package/src/runtime/readiness-record.js +16 -11
  364. package/src/runtime/readiness.js +46 -5
  365. package/src/runtime/research-request.js +50 -25
  366. package/src/runtime/retrieval-plan.js +10 -30
  367. package/src/runtime/retrieval-record.js +75 -5
  368. package/src/runtime/review/command.js +246 -0
  369. package/src/runtime/review/dominance.js +68 -0
  370. package/src/runtime/review/findings.js +434 -0
  371. package/src/runtime/review/identity.js +255 -0
  372. package/src/runtime/review/protocol-command.js +109 -0
  373. package/src/runtime/review/protocols.js +405 -0
  374. package/src/runtime/review/resolve-protocol.js +302 -0
  375. package/src/runtime/review/start.js +530 -0
  376. package/src/runtime/roadmap/attendance.js +137 -0
  377. package/src/runtime/roadmap/facts.js +479 -0
  378. package/src/runtime/roadmap/gates.js +273 -0
  379. package/src/runtime/roadmap/loop.js +1719 -0
  380. package/src/runtime/roadmap/merge.js +390 -0
  381. package/src/runtime/roadmap/rows.js +1122 -0
  382. package/src/runtime/roadmap/seed.js +1063 -0
  383. package/src/runtime/roadmap/worktree-cleanup.js +147 -0
  384. package/src/runtime/rules-report.js +336 -0
  385. package/src/runtime/scaffold/artifacts.js +60 -9
  386. package/src/runtime/scaffold/generate.js +21 -9
  387. package/src/runtime/settings/autopilot.js +106 -0
  388. package/src/runtime/settings/cli.js +280 -0
  389. package/src/runtime/settings/config-write.js +314 -0
  390. package/src/runtime/settings/files.js +271 -0
  391. package/src/runtime/settings/legacy.js +154 -0
  392. package/src/runtime/settings/lexical.js +56 -0
  393. package/src/runtime/settings/prepared-run.js +269 -0
  394. package/src/runtime/settings/project-layers.js +118 -0
  395. package/src/runtime/settings/refs.js +288 -0
  396. package/src/runtime/settings/registry.js +553 -0
  397. package/src/runtime/settings/resolve.js +713 -0
  398. package/src/runtime/settings/shared.js +37 -0
  399. package/src/runtime/settings/worker-billing.js +107 -0
  400. package/src/runtime/settings/write.js +269 -0
  401. package/src/runtime/slot-command.js +78 -0
  402. package/src/runtime/slots.js +671 -0
  403. package/src/runtime/source-version.js +1 -0
  404. package/src/runtime/state-root.js +217 -0
  405. package/src/runtime/storage/cli.js +12 -5
  406. package/src/runtime/storage/engine.js +9 -2
  407. package/src/runtime/storage/registry.js +14 -1
  408. package/src/runtime/storage/roots.js +66 -16
  409. package/src/runtime/storage/rules.js +82 -10
  410. package/src/runtime/storage/upkeep.js +10 -2
  411. package/src/runtime/storage/work-status.js +245 -26
  412. package/src/runtime/task-attempts.js +589 -69
  413. package/src/runtime/task-classifier.js +85 -14
  414. package/src/runtime/task-graph.js +373 -0
  415. package/src/runtime/task-run.js +778 -0
  416. package/src/runtime/task-scope.js +176 -55
  417. package/src/runtime/task-sources.js +147 -0
  418. package/src/runtime/task-state.js +373 -64
  419. package/src/runtime/team/admission.js +301 -0
  420. package/src/runtime/team/envelope.js +324 -0
  421. package/src/runtime/team/review-guard.js +156 -0
  422. package/src/runtime/trace/analyze.js +427 -0
  423. package/src/runtime/trace/baseline.js +770 -0
  424. package/src/runtime/trace/ledger.js +63 -140
  425. package/src/runtime/trace/otlp-export.js +568 -0
  426. package/src/runtime/trace/otlp-map.js +481 -0
  427. package/src/runtime/trace/spans.js +745 -0
  428. package/src/runtime/trace/telemetry.js +225 -0
  429. package/src/runtime/trace/views.js +1 -0
  430. package/src/runtime/transcripts/command.js +98 -0
  431. package/src/runtime/transcripts/cursor.js +326 -0
  432. package/src/runtime/transcripts/read.js +126 -0
  433. package/src/runtime/transcripts/readers/claude-jsonl.js +74 -0
  434. package/src/runtime/transcripts/readers/codex-rollout.js +70 -0
  435. package/src/runtime/transcripts/readers/copilot-events.js +90 -0
  436. package/src/runtime/transcripts/readers/kiro-jsonl.js +77 -0
  437. package/src/runtime/transcripts/readers/pi-jsonl.js +59 -0
  438. package/src/runtime/transcripts/registry.js +161 -0
  439. package/src/runtime/transcripts/stats.js +161 -0
  440. package/src/runtime/verb-view.js +267 -0
  441. package/src/runtime/verification/check-key.js +628 -0
  442. package/src/runtime/verification/contract-runner.js +546 -11
  443. package/src/runtime/verification/engine.js +499 -54
  444. package/src/runtime/verification/impact.js +617 -0
  445. package/src/runtime/verification/inflight.js +205 -0
  446. package/src/runtime/verification/registry.js +176 -0
  447. package/src/runtime/verification/reuse.js +184 -0
  448. package/src/runtime/verification/telemetry-emit.js +254 -0
  449. package/src/runtime/verification/test-selection.js +67 -7
  450. package/src/runtime/worker/active.js +90 -0
  451. package/src/runtime/worker/cancel.js +222 -0
  452. package/src/runtime/worker/catalogue.js +122 -0
  453. package/src/runtime/worker/command.js +677 -0
  454. package/src/runtime/worker/evidence.js +288 -0
  455. package/src/runtime/worker/launch.js +256 -0
  456. package/src/runtime/worker/models.js +137 -0
  457. package/src/runtime/worker/parsers.js +218 -0
  458. package/src/runtime/worker/probes/index.js +706 -0
  459. package/src/runtime/worker/process-tree.js +415 -0
  460. package/src/runtime/worker/quota.js +43 -0
  461. package/src/runtime/worker/readiness.js +713 -0
  462. package/src/runtime/worker/run-store.js +166 -0
  463. package/src/runtime/worker/supervisor.js +541 -0
  464. package/src/runtime/worker/worktree-check.js +252 -0
  465. package/src/runtime/workflow-engine.js +5 -1
  466. package/src/runtime/workflow-orchestrator.js +610 -67
  467. package/src/runtime/worktree.js +149 -22
  468. package/src/state/index.js +1 -1
  469. package/src/state/lockfile.js +64 -10
  470. package/src/state/run-lock.js +1 -1
  471. package/types/node-commonjs.d.ts +106 -7
  472. package/core/harnesses/claude/hooks/pre-bash-guard.sh +0 -10
  473. package/core/harnesses/codex/hooks/pre-bash-guard.sh +0 -10
  474. package/core/harnesses/gemini/hooks/hooks.json +0 -77
  475. package/core/harnesses/gemini/hooks/lib.sh +0 -302
  476. package/core/harnesses/gemini/hooks/mcp-tool-guard.sh +0 -10
  477. package/core/harnesses/gemini/hooks/post-edit-lint.sh +0 -39
  478. package/core/harnesses/gemini/hooks/pre-bash-guard.sh +0 -10
  479. package/core/harnesses/gemini/hooks/pre-compact.sh +0 -38
  480. package/core/harnesses/gemini/hooks/pre-implement-gate.sh +0 -10
  481. package/core/harnesses/gemini/hooks/session-end.impl.sh +0 -89
  482. package/core/harnesses/gemini/hooks/session-end.sh +0 -5
  483. package/core/harnesses/gemini/hooks/session-start.sh +0 -7
  484. package/core/harnesses/gemini/settings/adapter-defaults.json +0 -4
  485. package/core/harnesses/kiro/hooks/pre-bash-guard.sh +0 -24
  486. package/core/harnesses/shared/hooks/policies/blocked-patterns.conf +0 -91
  487. package/core/harnesses/shared/hooks/policies/pre-bash-guard.sh +0 -378
  488. package/core/shared/guidance/FLAGS.md +0 -25
  489. package/core/shared/guidance/rules/RULE_01_SAFETY.md +0 -25
  490. package/core/shared/guidance/rules/RULE_02_WORKFLOW.md +0 -23
  491. package/core/shared/guidance/rules/RULE_03_QUALITY.md +0 -14
  492. package/core/shared/guidance/rules/RULE_04_QUESTIONS.md +0 -46
  493. package/src/adapters/gemini/hooks.js +0 -251
  494. package/src/adapters/gemini/index.js +0 -429
@@ -0,0 +1,246 @@
1
+ 'use strict';
2
+
3
+ // TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
4
+
5
+ const fs = require('node:fs');
6
+ const path = require('node:path');
7
+ const { spawnSync } = require('node:child_process');
8
+ const { validateFindings, countFindings, reviewAdvisories, invalidProjectCandidate, invalidPresetCandidate, telemetryProtocol } = require('./findings.js');
9
+ const { resolveActiveFeature } = require('../feature-resolve.js');
10
+ const { TelemetryWriter } = require('../trace/telemetry.js');
11
+ const { finishRuntime } = require('../cli-result.js');
12
+ const { handleReviewStart, validSlug } = require('./start.js');
13
+ const { crossCheckAuthor, authoringIdentities } = require('./identity.js');
14
+ const { isQualifiedId } = require('../../helper/package-ids.js');
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+ const TELEMETRY_COUNT_KEYS = Object.freeze([
23
+ 'rounds', 'seats', 'seat_findings', 'converged', 'blocker', 'should_fix', 'note',
24
+ 'open', 'fixed', 'refuted', 'user_accepted', 'pre_existing', 'escaped', 'confirmed',
25
+ 'plausible', 'unverified_blockers', 'bug_classes',
26
+ ]);
27
+
28
+ // Inherited location variables would point the check at another repository (C-8).
29
+ const GIT_LOCATION_KEYS = Object.freeze([
30
+ 'GIT_DIR', 'GIT_WORK_TREE', 'GIT_INDEX_FILE', 'GIT_OBJECT_DIRECTORY', 'GIT_COMMON_DIR',
31
+ 'GIT_ALTERNATE_OBJECT_DIRECTORIES',
32
+ ]);
33
+
34
+ function defaultGit(args , cwd , env ) {
35
+ const gitEnv = { ...env };
36
+ for (const key of GIT_LOCATION_KEYS) delete gitEnv[key];
37
+ return spawnSync('git', ['-C', cwd, ...args], { cwd, env: gitEnv, stdio: 'ignore' });
38
+ }
39
+
40
+ /** The project's `review.sameFamily` (119 L-C3), read for the checkout the verb runs in. A settings view that cannot
41
+ * load, or an invalid project or local value for the key (C-6: the resolver would fall back to the default without a
42
+ * word), is `warn` plus `unread`; the caller turns `unread` into an error. Never a crash, never a silent `refuse`. */
43
+ function readSameFamily(load , cwd , env ) {
44
+ try {
45
+ const resolution = load({ projectRoot: path.resolve(cwd), env }).get('review.sameFamily');
46
+ if (invalidProjectCandidate(resolution)) return { value: 'warn', unread: true };
47
+ return { value: resolution.value === 'refuse' ? 'refuse' : 'warn', unread: false };
48
+ } catch {
49
+ return { value: 'warn', unread: true };
50
+ }
51
+ }
52
+
53
+ /** The effective `review.preset` (C-2 closure), read for the checkout the verb runs in. A settings view that cannot
54
+ * load, or an invalid user, project or local value (the resolver would fall back to `auto` without a word), is `unread`;
55
+ * the caller turns `unread` into an error, so a broken setting never relaxes the check. */
56
+ function readPreset(load , cwd , env ) {
57
+ try {
58
+ const resolution = load({ projectRoot: path.resolve(cwd), env }).get('review.preset');
59
+ if (invalidPresetCandidate(resolution)) return { value: 'auto', unread: true };
60
+ return { value: typeof resolution.value === 'string' ? resolution.value : 'auto', unread: false };
61
+ } catch {
62
+ return { value: 'auto', unread: true };
63
+ }
64
+ }
65
+
66
+ // A preset id: a core one as protocols.ts validates it (`^[a-z][a-z0-9-]*$`), or a package preset's qualified id
67
+ // (`<package>.<preset>`, 122 IC-003). Whether it is available and strict enough is the resolver's answer (IC-014).
68
+ const CORE_PRESET_ID = /^[a-z][a-z0-9-]*$/;
69
+ const presetIdShape = (value ) => typeof value === 'string' && (CORE_PRESET_ID.test(value) || isQualifiedId(value));
70
+
71
+ function usage(message , json , out ) {
72
+ out(json
73
+ ? JSON.stringify({ ok: false, error: 'usage', message })
74
+ : `doflow review: ${message}`);
75
+ return finishRuntime(2);
76
+ }
77
+
78
+ function hasValue(value ) {
79
+ return value !== undefined && value !== null;
80
+ }
81
+
82
+ function emptyValue(value ) {
83
+ return typeof value === 'string' && value.trim().length === 0;
84
+ }
85
+
86
+ function handleReviewCommand({
87
+ action,
88
+ slug,
89
+ path: recordPath,
90
+ base,
91
+ preset,
92
+ adviceClient,
93
+ json = false,
94
+ cwd = process.cwd(),
95
+ env = process.env,
96
+ git = defaultGit,
97
+ loadSettings = (options ) => require('../settings/resolve.js').loadSettings(options),
98
+ writer,
99
+ resolve = resolveActiveFeature,
100
+ out = (line ) => console.log(line),
101
+ } = {}) {
102
+ if (action !== 'check' && action !== 'start') return usage('action must be check or start', json, out);
103
+ if (emptyValue(slug) || emptyValue(recordPath) || emptyValue(base) || emptyValue(preset)) return usage('flag values must not be empty', json, out);
104
+ if (action === 'start') {
105
+ // 095b IC-001: the start verb reads no record path, and the slug becomes a file name.
106
+ if (hasValue(recordPath)) return usage('--path is not valid with --action start', json, out);
107
+ if ((hasValue(slug) && !validSlug(slug)) || (hasValue(base) && typeof base !== 'string')) {
108
+ return usage('--slug must be a plain feature name and --base a string', json, out);
109
+ }
110
+ if (hasValue(preset) && !presetIdShape(preset)) {
111
+ return usage('--preset must be a preset id (lower-case letters, digits and hyphens, or <package>.<preset> for a package preset)', json, out);
112
+ }
113
+ return handleReviewStart({ slug: hasValue(slug) ? slug : null, base: hasValue(base) ? base : null, preset: hasValue(preset) ? preset : null, json, cwd, env, resolve, adviceClient, out });
114
+ }
115
+ if (hasValue(base)) return usage('--base is valid only with --action start', json, out);
116
+ if (hasValue(preset)) return usage('--preset is valid only with --action start', json, out);
117
+ if (hasValue(slug) && hasValue(recordPath)) return usage('use either --slug or --path, not both', json, out);
118
+ if ((hasValue(slug) && typeof slug !== 'string') || (hasValue(recordPath) && typeof recordPath !== 'string')) {
119
+ return usage('--slug and --path values must be strings', json, out);
120
+ }
121
+
122
+ const telemetryWriter = writer || new TelemetryWriter({ env, start: cwd });
123
+ let file = null;
124
+ let resolverMessage = null;
125
+ if (hasValue(recordPath)) {
126
+ file = path.resolve(cwd, recordPath);
127
+ } else {
128
+ let feature ;
129
+ try {
130
+ feature = (resolve )({ projectRoot: cwd, slug: hasValue(slug) ? slug : null });
131
+ } catch (error ) {
132
+ feature = { error: 'resolver-failed', message: error?.message || String(error) };
133
+ }
134
+ if (feature?.error || typeof feature?.featureFolder !== 'string' || !feature.featureFolder) {
135
+ resolverMessage = typeof feature?.message === 'string' && feature.message
136
+ ? feature.message
137
+ : (typeof feature?.error === 'string' && feature.error ? feature.error : 'feature could not be resolved');
138
+ } else {
139
+ file = path.resolve(feature.featureFolder, 'review', 'findings.json');
140
+ }
141
+ }
142
+
143
+ const errors = [];
144
+ const errorDetails = new Map ();
145
+ const ancestryAdvisories = [];
146
+ const identityAdvisories = [];
147
+ let sameFamily = 'warn';
148
+ let reviewPreset = 'auto';
149
+ let authors = [];
150
+ let record = null;
151
+ if (file === null) {
152
+ errors.push('missing');
153
+ errorDetails.set('missing', resolverMessage || 'feature record could not be located');
154
+ } else {
155
+ let raw ;
156
+ try {
157
+ raw = fs.readFileSync(file, 'utf8');
158
+ } catch (error ) {
159
+ if (error?.code === 'ENOENT') errors.push('missing');
160
+ else errors.push('unreadable');
161
+ if (error?.message) errorDetails.set(errors[0], error.message);
162
+ raw = '';
163
+ }
164
+
165
+ if (errors.length === 0) {
166
+ // Settings are read only for a record that declares an author: nothing else depends on them (L-C3).
167
+ let peek = null;
168
+ try { peek = JSON.parse(raw); } catch { /* validateFindings reports `json` */ }
169
+ if (peek !== null && typeof peek === 'object' && Object.hasOwn(peek, 'author')) {
170
+ const read = readSameFamily(loadSettings, cwd, env);
171
+ sameFamily = read.value;
172
+ if (read.unread) errors.push('same-family-setting-unread');
173
+ }
174
+ // A record that omits `protocol` is held to the effective `review.preset` (C-2 closure), so it is read for every record.
175
+ if (peek !== null && typeof peek === 'object') {
176
+ const read = readPreset(loadSettings, cwd, env);
177
+ reviewPreset = read.value;
178
+ if (read.unread) errors.push('review-preset-setting-unread');
179
+ }
180
+ authors = authoringIdentities({ slug: peek?.slug, cwd, env, record: peek, fsImpl: fs });
181
+ const validation = validateFindings(raw, { sameFamily, preset: reviewPreset, authors });
182
+ for (const error of validation.errors) errors.push(error); // a spread overflows the stack at ~200k errors (C-6)
183
+ if (!validation.errors.includes('json')) {
184
+ try { record = JSON.parse(raw); } catch { record = null; }
185
+ }
186
+ if (validation.ok && record) {
187
+ if (Object.hasOwn(record, 'author')) identityAdvisories.push(...crossCheckAuthor({ record, cwd, env }));
188
+ for (const finding of record.converged) {
189
+ if (typeof finding.preExistingAt !== 'string') continue;
190
+ let status ;
191
+ try {
192
+ status = (git )(
193
+ ['merge-base', '--is-ancestor', finding.preExistingAt, record.reviewedHead],
194
+ path.dirname(file),
195
+ env,
196
+ )?.status;
197
+ } catch {
198
+ status = null;
199
+ }
200
+ if (status === 1) errors.push(`preExistingAt-not-ancestor:${finding.id}`);
201
+ else if (status !== 0) ancestryAdvisories.push(`ancestry-unchecked:${finding.id}`);
202
+ }
203
+ }
204
+ }
205
+ }
206
+
207
+ const advisories = (record && validateFindings(record, { sameFamily, preset: reviewPreset, authors }).ok
208
+ ? reviewAdvisories(record, { sameFamily, authors }).concat(identityAdvisories)
209
+ : []).concat(ancestryAdvisories).sort();
210
+ const valid = errors.length === 0;
211
+ const counts = valid && record ? countFindings(record) : null;
212
+ const result = { schema: 1, path: file, valid, errors, advisories, counts };
213
+
214
+ if (json) {
215
+ out(JSON.stringify(result));
216
+ } else {
217
+ out(`review check: ${valid ? 'valid' : 'invalid'} (${errors.length} errors, ${advisories.length} advisories)`);
218
+ for (const error of errors) {
219
+ const detail = errorDetails.get(error);
220
+ out(`error: ${error}${detail ? `: ${detail}` : ''}`);
221
+ }
222
+ for (const advisory of advisories) out(`advisory: ${advisory}`);
223
+ if (counts) out(Object.entries(counts).map(([key, value]) => `${key}=${value}`).join(' '));
224
+ }
225
+
226
+ // Only a validated slug is a feature slug; an invalid record's slug can hold anything (C-1, IC-004).
227
+ const task = valid && record && typeof record.slug === 'string' ? record.slug : null;
228
+ const telemetryRecord = {
229
+ kind: 'review.run',
230
+ task,
231
+ depth: null,
232
+ risk: null,
233
+ protocol: null,
234
+ head: null,
235
+ ...Object.fromEntries(TELEMETRY_COUNT_KEYS.map((key) => [key, null])),
236
+ advisories: advisories.length,
237
+ errors: errors.length,
238
+ };
239
+ if (counts && record) Object.assign(telemetryRecord, counts, { depth: record.depth ?? null, risk: record.risk ?? null, protocol: telemetryProtocol(record.protocol?.id), head: record.reviewedHead });
240
+ try { telemetryWriter.write([telemetryRecord]); } catch { /* telemetry never changes the check result */ }
241
+
242
+ return finishRuntime(valid ? 0 : 1);
243
+ }
244
+
245
+ module.exports = { handleReviewCommand };
246
+
@@ -0,0 +1,68 @@
1
+ 'use strict';
2
+
3
+ // 122 IC-014: `dominates(P, B, context)`, the strictness comparison between two protocol presets. Pure:
4
+ // no filesystem, no throw. P dominates B when every field that makes a review or debate stricter is at
5
+ // least as strict in P. `context` carries the ordered core tiers (models.json `dispatchTiers.tiers`,
6
+ // loosest first) and the synthesizer lattice (protocols.json `synthesizerStrength`). An unknown tier or
7
+ // synthesizer has no rank and never dominates: no `indexOf` of -1 is read as a rank.
8
+
9
+ const FAMILY_STRICTNESS = { any: 0, 'different-from-author': 1 };
10
+
11
+ const isObject = (value ) => value !== null && typeof value === 'object' && !Array.isArray(value);
12
+
13
+ /** A rank from `ranks`, or null when `key` has none. */
14
+ function rankOf(ranks , key ) {
15
+ return typeof key === 'string' && Object.hasOwn(ranks, key) && Number.isInteger(ranks[key]) ? ranks[key] : null;
16
+ }
17
+
18
+ /** True when seat `p` covers seat `b`: a lens superset, a family at least as strict, a tier at least as high. */
19
+ function seatCovers(p , b , tierRank ) {
20
+ if (!isObject(p) || !isObject(b) || !isObject(p.model) || !isObject(b.model)) return false;
21
+ const pLenses = new Set(Array.isArray(p.lenses) ? p.lenses : []);
22
+ if (!(Array.isArray(b.lenses) ? b.lenses : []).every((lens ) => pLenses.has(lens))) return false;
23
+ const pFamily = rankOf(FAMILY_STRICTNESS, p.model.family ?? 'any');
24
+ const bFamily = rankOf(FAMILY_STRICTNESS, b.model.family ?? 'any');
25
+ if (pFamily === null || bFamily === null || pFamily < bFamily) return false;
26
+ const pTier = rankOf(tierRank, p.model.tier);
27
+ const bTier = rankOf(tierRank, b.model.tier);
28
+ return pTier !== null && bTier !== null && pTier >= bTier;
29
+ }
30
+
31
+ /**
32
+ * True when every B seat maps to a distinct P seat that covers it: a maximum bipartite matching by
33
+ * augmenting paths (Kuhn), so a first-fit choice never hides a matching that exists. Seats are few.
34
+ */
35
+ function seatsMatch(pSeats , bSeats , tierRank ) {
36
+ if (bSeats.length > pSeats.length) return false;
37
+ const covers = bSeats.map((b) => pSeats.map((p) => seatCovers(p, b, tierRank)));
38
+ const owner = new Array(pSeats.length).fill(-1); // P seat index -> B seat index
39
+ const augment = (bi , seen ) => {
40
+ for (let pi = 0; pi < pSeats.length; pi++) {
41
+ if (!covers[bi][pi] || seen[pi]) continue;
42
+ seen[pi] = true;
43
+ if (owner[pi] === -1 || augment(owner[pi], seen)) { owner[pi] = bi; return true; }
44
+ }
45
+ return false;
46
+ };
47
+ return bSeats.every((_, bi) => augment(bi, new Array(pSeats.length).fill(false)));
48
+ }
49
+
50
+ function dominates(P , B , context = {}) {
51
+ if (!isObject(P) || !isObject(B) || !isObject(context)) return false;
52
+ const { tiers, synthesizerStrength } = context;
53
+ if (!Array.isArray(tiers) || !isObject(synthesizerStrength)) return false;
54
+ const tierRank = Object.fromEntries(tiers.map((tier , i ) => [tier, i]));
55
+
56
+ if (P.kind !== B.kind || P.decider !== B.decider) return false;
57
+ if (!Array.isArray(P.seats) || !Array.isArray(B.seats) || !seatsMatch(P.seats, B.seats, tierRank)) return false;
58
+ if (!isObject(P.rounds) || !isObject(B.rounds)) return false;
59
+ for (const field of ['default', 'min']) {
60
+ if (!Number.isInteger(P.rounds[field]) || !Number.isInteger(B.rounds[field]) || P.rounds[field] < B.rounds[field]) return false;
61
+ }
62
+ if (B.crossAnswer === true && P.crossAnswer !== true) return false;
63
+ const pSynth = rankOf(synthesizerStrength, P.synthesizer);
64
+ const bSynth = rankOf(synthesizerStrength, B.synthesizer);
65
+ return pSynth !== null && bSynth !== null && pSynth >= bSynth;
66
+ }
67
+
68
+ module.exports = { dominates };