@ngockhoale/ukit 3.0.0 → 3.0.2

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 (445) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/manifests/documentation.yaml +75 -64
  3. package/manifests/engineConformance.yaml +32 -0
  4. package/manifests/hostCapabilities.yaml +2 -2
  5. package/manifests/instructionRules.yaml +55 -55
  6. package/manifests/platform.full.yaml +30 -4
  7. package/manifests/platform.user.yaml +4 -4
  8. package/package.json +8 -7
  9. package/scripts/bench/v3-ceremony.mjs +214 -0
  10. package/scripts/install/sync-installed-mirror.mjs +3 -3
  11. package/scripts/perf/audit-perf.mjs +9 -9
  12. package/scripts/perf/perf-findings.json +4 -4
  13. package/scripts/perf/perf-measure.md +20 -20
  14. package/src/cli/commands/doctor.js +38 -2
  15. package/src/core/buildPlan.js +3 -3
  16. package/src/core/compact/contextBudget.js +2 -2
  17. package/src/core/compact/threshold.js +3 -3
  18. package/src/core/docContracts.js +17 -17
  19. package/src/core/ensureGitignore.js +1 -1
  20. package/src/core/executionContracts.js +42 -2
  21. package/src/core/fileOps.js +3 -3
  22. package/src/core/gatewayProbe.js +2 -2
  23. package/src/core/gatewayResilienceEnv.js +2 -2
  24. package/src/core/handoffDocValidator.js +152 -0
  25. package/src/core/output/index.js +1 -1
  26. package/src/core/paths.js +2 -1
  27. package/src/core/reviewPanelAggregate.js +120 -0
  28. package/src/core/runInstallPipeline.js +6 -4
  29. package/src/core/runtimeConfig.js +13 -6
  30. package/src/core/sensitiveValueScanner.js +1 -1
  31. package/src/core/taskBudgetValidator.js +1 -1
  32. package/src/core/unattendedDoctor.js +1 -1
  33. package/src/core/update.js +1 -1
  34. package/src/index/buildIndex.js +2 -2
  35. package/src/index/impactCatalog.js +12 -12
  36. package/src/index/taskRouting.js +263 -5
  37. package/src/render/instructionRenderer.js +7 -7
  38. package/src/skill/auditSkill.js +1 -1
  39. package/{templates → template_project}/.claude/agents/code-reviewer.md +25 -0
  40. package/{templates → template_project}/.claude/agents/handoff-planner.md +17 -2
  41. package/{templates → template_project}/.claude/commands/ukit/handoff-create.md +1 -1
  42. package/{templates → template_project}/.claude/commands/ukit/handoff-fullstack.md +26 -6
  43. package/{templates → template_project}/.claude/commands/ukit/handoff-review.md +31 -6
  44. package/{templates → template_project}/.claude/hooks/handoff-model-guard.sh +1 -1
  45. package/{templates → template_project}/.claude/hooks/skill-router.sh +3 -3
  46. package/{templates → template_project}/.claude/skills/skill-quality/SKILL.md +1 -1
  47. package/{templates → template_project}/.claude/skills/skill-quality/pressure-scenario-template.md +1 -1
  48. package/template_project/.claude/ukit/index/handoff-doc-validator.mjs +193 -0
  49. package/{templates → template_project}/.claude/ukit/index/lib/index-core.mjs +12 -12
  50. package/template_project/.claude/ukit/index/review-panel-aggregate.mjs +174 -0
  51. package/{templates → template_project}/.claude/ukit/index/route-task.mjs +408 -12
  52. package/{templates → template_project}/.claude/ukit/index/unic-gateway.mjs +1 -1
  53. package/{templates → template_project}/.claude/ukit/runtime/execution-ledger.mjs +14 -5
  54. package/{templates → template_project}/.claude/ukit/runtime/safe-patch-core.mjs +3 -3
  55. package/{templates → template_project}/.claude/ukit/runtime/sensitive-value-scanner.mjs +1 -1
  56. package/{templates → template_project}/.claude/ukit/runtime/stop-coordinator.mjs +187 -8
  57. package/{templates → template_project}/.claude/ukit/runtime/task-watchdog.mjs +1 -1
  58. package/{templates → template_project}/.gitignore +2 -2
  59. package/{templates → template_project}/.omp/RULES.md +1 -1
  60. package/{templates → template_project}/.omp/agents/code-reviewer.md +27 -0
  61. package/{templates → template_project}/.omp/agents/handoff-planner.md +17 -2
  62. package/{templates → template_project}/.omp/config.yml +3 -3
  63. package/{templates → template_project}/AGENTS.md +2 -2
  64. package/{templates → template_project}/CLAUDE.md +2 -2
  65. package/{templates → template_project}/docs/AI_HANDOFF/RULES.md +1 -1
  66. package/{templates → template_project}/docs/UKIT_INTERNALS.md +3 -3
  67. package/{templates → template_project}/instructions/core.md +1 -1
  68. package/{templates → template_project}/instructions/layout.yaml +8 -8
  69. package/{templates → template_project}/instructions/overlays/claude.md +1 -1
  70. package/{templates → template_project}/instructions/overlays/repo.md +1 -1
  71. package/{templates → template_project}/ukit/storage/config.json +4 -1
  72. package/template_project/ukit/storage/memory/projects/.gitkeep +2 -0
  73. package/templates/ukit/storage/memory/projects/.gitkeep +0 -2
  74. /package/{templates → template_project}/.claude/agents/bug-debugger.md +0 -0
  75. /package/{templates → template_project}/.claude/agents/feature-implementer.md +0 -0
  76. /package/{templates → template_project}/.claude/agents/ukit-small-task-maintainer.md +0 -0
  77. /package/{templates → template_project}/.claude/agents/ukit-vision-analyst.md +0 -0
  78. /package/{templates → template_project}/.claude/commands/ukit/handoff-clear.md +0 -0
  79. /package/{templates → template_project}/.claude/commands/ukit/handoff-implement.md +0 -0
  80. /package/{templates → template_project}/.claude/commands/ukit/handoff-status.md +0 -0
  81. /package/{templates → template_project}/.claude/config/providers.md +0 -0
  82. /package/{templates → template_project}/.claude/hooks/auto-allow-bash.sh +0 -0
  83. /package/{templates → template_project}/.claude/hooks/auto-prune-bash.sh +0 -0
  84. /package/{templates → template_project}/.claude/hooks/block-dangerous.mjs +0 -0
  85. /package/{templates → template_project}/.claude/hooks/block-dangerous.sh +0 -0
  86. /package/{templates → template_project}/.claude/hooks/completion-gate.sh +0 -0
  87. /package/{templates → template_project}/.claude/hooks/compress-output.sh +0 -0
  88. /package/{templates → template_project}/.claude/hooks/context-hardcap-gate.sh +0 -0
  89. /package/{templates → template_project}/.claude/hooks/context-window-guard.sh +0 -0
  90. /package/{templates → template_project}/.claude/hooks/handoff-resume.sh +0 -0
  91. /package/{templates → template_project}/.claude/hooks/post-edit-verify.sh +0 -0
  92. /package/{templates → template_project}/.claude/hooks/pre-edit-backup.sh +0 -0
  93. /package/{templates → template_project}/.claude/hooks/project-important.sh +0 -0
  94. /package/{templates → template_project}/.claude/hooks/protect-files.sh +0 -0
  95. /package/{templates → template_project}/.claude/hooks/record-execution.mjs +0 -0
  96. /package/{templates → template_project}/.claude/hooks/record-execution.sh +0 -0
  97. /package/{templates → template_project}/.claude/hooks/reinject-context.sh +0 -0
  98. /package/{templates → template_project}/.claude/hooks/reset-compact-pressure.sh +0 -0
  99. /package/{templates → template_project}/.claude/hooks/sensitive-data-guard.mjs +0 -0
  100. /package/{templates → template_project}/.claude/hooks/sensitive-data-guard.sh +0 -0
  101. /package/{templates → template_project}/.claude/hooks/session-episode.sh +0 -0
  102. /package/{templates → template_project}/.claude/hooks/session-start.md +0 -0
  103. /package/{templates → template_project}/.claude/hooks/stale-spec-guard.sh +0 -0
  104. /package/{templates → template_project}/.claude/hooks/task-watchdog.sh +0 -0
  105. /package/{templates → template_project}/.claude/hooks/verification-guard.sh +0 -0
  106. /package/{templates → template_project}/.claude/hooks/vision-router.sh +0 -0
  107. /package/{templates → template_project}/.claude/settings.json +0 -0
  108. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +0 -0
  109. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +0 -0
  110. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +0 -0
  111. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +0 -0
  112. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +0 -0
  113. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +0 -0
  114. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +0 -0
  115. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +0 -0
  116. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +0 -0
  117. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +0 -0
  118. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +0 -0
  119. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +0 -0
  120. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +0 -0
  121. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +0 -0
  122. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +0 -0
  123. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +0 -0
  124. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +0 -0
  125. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +0 -0
  126. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +0 -0
  127. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +0 -0
  128. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +0 -0
  129. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +0 -0
  130. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +0 -0
  131. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +0 -0
  132. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +0 -0
  133. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +0 -0
  134. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +0 -0
  135. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +0 -0
  136. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +0 -0
  137. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +0 -0
  138. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +0 -0
  139. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/mce/mc.xsd +0 -0
  140. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/microsoft/wml-2010.xsd +0 -0
  141. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/microsoft/wml-2012.xsd +0 -0
  142. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/microsoft/wml-2018.xsd +0 -0
  143. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/microsoft/wml-cex-2018.xsd +0 -0
  144. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/microsoft/wml-cid-2016.xsd +0 -0
  145. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +0 -0
  146. /package/{templates → template_project}/.claude/skills/_shared/ooxml/schemas/microsoft/wml-symex-2015.xsd +0 -0
  147. /package/{templates → template_project}/.claude/skills/_shared/ooxml/scripts/pack.py +0 -0
  148. /package/{templates → template_project}/.claude/skills/_shared/ooxml/scripts/unpack.py +0 -0
  149. /package/{templates → template_project}/.claude/skills/_shared/ooxml/scripts/validate.py +0 -0
  150. /package/{templates → template_project}/.claude/skills/_shared/ooxml/scripts/validation/__init__.py +0 -0
  151. /package/{templates → template_project}/.claude/skills/_shared/ooxml/scripts/validation/base.py +0 -0
  152. /package/{templates → template_project}/.claude/skills/_shared/ooxml/scripts/validation/docx.py +0 -0
  153. /package/{templates → template_project}/.claude/skills/_shared/ooxml/scripts/validation/pptx.py +0 -0
  154. /package/{templates → template_project}/.claude/skills/_shared/ooxml/scripts/validation/redlining.py +0 -0
  155. /package/{templates → template_project}/.claude/skills/backend-api/SKILL.md +0 -0
  156. /package/{templates → template_project}/.claude/skills/canvas-design/LICENSE.txt +0 -0
  157. /package/{templates → template_project}/.claude/skills/canvas-design/SKILL.md +0 -0
  158. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  159. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +0 -0
  160. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  161. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  162. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  163. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  164. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +0 -0
  165. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  166. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  167. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  168. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  169. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +0 -0
  170. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  171. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
  172. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  173. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
  174. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/Lora-OFL.txt +0 -0
  175. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
  176. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +0 -0
  177. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  178. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
  179. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/Outfit-OFL.txt +0 -0
  180. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
  181. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
  182. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/Tektur-OFL.txt +0 -0
  183. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
  184. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +0 -0
  185. /package/{templates → template_project}/.claude/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  186. /package/{templates → template_project}/.claude/skills/canvas-design/philosophy-examples.md +0 -0
  187. /package/{templates → template_project}/.claude/skills/code-review/SKILL.md +0 -0
  188. /package/{templates → template_project}/.claude/skills/debugging-toolkit/SKILL.md +0 -0
  189. /package/{templates → template_project}/.claude/skills/debugging-toolkit/reference-tables.md +0 -0
  190. /package/{templates → template_project}/.claude/skills/delivery/SKILL.md +0 -0
  191. /package/{templates → template_project}/.claude/skills/discover-security/SKILL.md +0 -0
  192. /package/{templates → template_project}/.claude/skills/docker-packaging/SKILL.md +0 -0
  193. /package/{templates → template_project}/.claude/skills/docs-manager/SKILL.md +0 -0
  194. /package/{templates → template_project}/.claude/skills/docs-manager/conventions-and-examples.md +0 -0
  195. /package/{templates → template_project}/.claude/skills/docs-manager/init-project-docs.sh +0 -0
  196. /package/{templates → template_project}/.claude/skills/docs-manager/templates/README.md.template +0 -0
  197. /package/{templates → template_project}/.claude/skills/docs-manager/templates/agent-roles.md.template +0 -0
  198. /package/{templates → template_project}/.claude/skills/docs-manager/templates/coding-conventions.md.template +0 -0
  199. /package/{templates → template_project}/.claude/skills/docs-manager/templates/memory.md.template +0 -0
  200. /package/{templates → template_project}/.claude/skills/docs-manager/templates/onboarding.md.template +0 -0
  201. /package/{templates → template_project}/.claude/skills/docs-manager/templates/project.md.template +0 -0
  202. /package/{templates → template_project}/.claude/skills/docs-quality/SKILL.md +0 -0
  203. /package/{templates → template_project}/.claude/skills/docx/LICENSE.txt +0 -0
  204. /package/{templates → template_project}/.claude/skills/docx/SKILL.md +0 -0
  205. /package/{templates → template_project}/.claude/skills/docx/docx-js.md +0 -0
  206. /package/{templates → template_project}/.claude/skills/docx/ooxml.md +0 -0
  207. /package/{templates → template_project}/.claude/skills/docx/redlining-reference.md +0 -0
  208. /package/{templates → template_project}/.claude/skills/docx/scripts/__init__.py +0 -0
  209. /package/{templates → template_project}/.claude/skills/docx/scripts/document.py +0 -0
  210. /package/{templates → template_project}/.claude/skills/docx/scripts/templates/comments.xml +0 -0
  211. /package/{templates → template_project}/.claude/skills/docx/scripts/templates/commentsExtended.xml +0 -0
  212. /package/{templates → template_project}/.claude/skills/docx/scripts/templates/commentsExtensible.xml +0 -0
  213. /package/{templates → template_project}/.claude/skills/docx/scripts/templates/commentsIds.xml +0 -0
  214. /package/{templates → template_project}/.claude/skills/docx/scripts/templates/people.xml +0 -0
  215. /package/{templates → template_project}/.claude/skills/docx/scripts/utilities.py +0 -0
  216. /package/{templates → template_project}/.claude/skills/duraone/SKILL.md +0 -0
  217. /package/{templates → template_project}/.claude/skills/duraone/references/backend.md +0 -0
  218. /package/{templates → template_project}/.claude/skills/duraone/references/frontend.md +0 -0
  219. /package/{templates → template_project}/.claude/skills/duraone/references/sql.md +0 -0
  220. /package/{templates → template_project}/.claude/skills/duraone/references/workflow.md +0 -0
  221. /package/{templates → template_project}/.claude/skills/executing-plans/SKILL.md +0 -0
  222. /package/{templates → template_project}/.claude/skills/file-organizer/SKILL.md +0 -0
  223. /package/{templates → template_project}/.claude/skills/file-organizer/examples-and-practices.md +0 -0
  224. /package/{templates → template_project}/.claude/skills/frontend/SKILL.md +0 -0
  225. /package/{templates → template_project}/.claude/skills/frontend-design/LICENSE.txt +0 -0
  226. /package/{templates → template_project}/.claude/skills/frontend-design/SKILL.md +0 -0
  227. /package/{templates → template_project}/.claude/skills/frontend-vue/SKILL.md +0 -0
  228. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Control/Box.vue +0 -0
  229. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Control/Button.vue +0 -0
  230. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Control/ButtonBar.vue +0 -0
  231. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Control/ButtonFloat.vue +0 -0
  232. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Control/CheckButton.vue +0 -0
  233. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Control/Checkbox.vue +0 -0
  234. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Control/Datetime.vue +0 -0
  235. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Control/Dropdownlist.vue +0 -0
  236. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Control/Input.vue +0 -0
  237. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Control/Label.vue +0 -0
  238. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Control/Master/BoxColumn.vue +0 -0
  239. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Control/Popup/Confirm.vue +0 -0
  240. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Control/Popup/Info.vue +0 -0
  241. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Control/Popup/ModalInfo.vue +0 -0
  242. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Control/Popup/Reject.vue +0 -0
  243. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Control/Tag.vue +0 -0
  244. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Control/Upload.vue +0 -0
  245. /package/{templates → template_project}/.claude/skills/frontend-vue/components/ControlMobile/Dropdownlist.vue +0 -0
  246. /package/{templates → template_project}/.claude/skills/frontend-vue/components/ControlMobile/PagingBar.vue +0 -0
  247. /package/{templates → template_project}/.claude/skills/frontend-vue/components/ControlMobile/UploadImage.vue +0 -0
  248. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Grid/AG.vue +0 -0
  249. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Grid/AntTable.vue +0 -0
  250. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Grid/CustomDropdownEditor.vue +0 -0
  251. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Grid/CustomDropdownEditorEnable.vue +0 -0
  252. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Grid/HtmlTable.vue +0 -0
  253. /package/{templates → template_project}/.claude/skills/frontend-vue/components/PDFViewer.vue +0 -0
  254. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Panel/FormView.vue +0 -0
  255. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Partial/Footer.vue +0 -0
  256. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Partial/Header.vue +0 -0
  257. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Partial/Sidebar.vue +0 -0
  258. /package/{templates → template_project}/.claude/skills/frontend-vue/components/Template.vue +0 -0
  259. /package/{templates → template_project}/.claude/skills/frontend-vue/components/View/Form.vue +0 -0
  260. /package/{templates → template_project}/.claude/skills/frontend-vue/composables/indexDBStore.js +0 -0
  261. /package/{templates → template_project}/.claude/skills/frontend-vue/composables/masterApi.js +0 -0
  262. /package/{templates → template_project}/.claude/skills/frontend-vue/composables/state.js +0 -0
  263. /package/{templates → template_project}/.claude/skills/frontend-vue/composables/useRequest.js +0 -0
  264. /package/{templates → template_project}/.claude/skills/frontend-vue/composables/useSession.js +0 -0
  265. /package/{templates → template_project}/.claude/skills/frontend-vue/composables/useTranslation.js +0 -0
  266. /package/{templates → template_project}/.claude/skills/frontend-vue/composables/useWebSocket.js +0 -0
  267. /package/{templates → template_project}/.claude/skills/frontend-vue/composables/userObj.js +0 -0
  268. /package/{templates → template_project}/.claude/skills/frontend-vue/composables/utils.js +0 -0
  269. /package/{templates → template_project}/.claude/skills/frontend-vue/reference/composables-example.vue +0 -0
  270. /package/{templates → template_project}/.claude/skills/frontend-vue/reference/form-example.vue +0 -0
  271. /package/{templates → template_project}/.claude/skills/frontend-vue/reference/grid-example.vue +0 -0
  272. /package/{templates → template_project}/.claude/skills/frontend-vue/reference/masterdata-example/[id].vue +0 -0
  273. /package/{templates → template_project}/.claude/skills/frontend-vue/reference/masterdata-example/index.vue +0 -0
  274. /package/{templates → template_project}/.claude/skills/frontend-vue/reference/popup-example.vue +0 -0
  275. /package/{templates → template_project}/.claude/skills/next-step/SKILL.md +0 -0
  276. /package/{templates → template_project}/.claude/skills/pdf/LICENSE.txt +0 -0
  277. /package/{templates → template_project}/.claude/skills/pdf/SKILL.md +0 -0
  278. /package/{templates → template_project}/.claude/skills/pdf/forms.md +0 -0
  279. /package/{templates → template_project}/.claude/skills/pdf/reference.md +0 -0
  280. /package/{templates → template_project}/.claude/skills/pdf/scripts/check_bounding_boxes.py +0 -0
  281. /package/{templates → template_project}/.claude/skills/pdf/scripts/check_bounding_boxes_test.py +0 -0
  282. /package/{templates → template_project}/.claude/skills/pdf/scripts/check_fillable_fields.py +0 -0
  283. /package/{templates → template_project}/.claude/skills/pdf/scripts/convert_pdf_to_images.py +0 -0
  284. /package/{templates → template_project}/.claude/skills/pdf/scripts/create_validation_image.py +0 -0
  285. /package/{templates → template_project}/.claude/skills/pdf/scripts/extract_form_field_info.py +0 -0
  286. /package/{templates → template_project}/.claude/skills/pdf/scripts/fill_fillable_fields.py +0 -0
  287. /package/{templates → template_project}/.claude/skills/pdf/scripts/fill_pdf_form_with_annotations.py +0 -0
  288. /package/{templates → template_project}/.claude/skills/pdf-processing/SKILL.md +0 -0
  289. /package/{templates → template_project}/.claude/skills/pdf-processing-pro/FORMS.md +0 -0
  290. /package/{templates → template_project}/.claude/skills/pdf-processing-pro/OCR.md +0 -0
  291. /package/{templates → template_project}/.claude/skills/pdf-processing-pro/SKILL.md +0 -0
  292. /package/{templates → template_project}/.claude/skills/pdf-processing-pro/TABLES.md +0 -0
  293. /package/{templates → template_project}/.claude/skills/pdf-processing-pro/scripts/analyze_form.py +0 -0
  294. /package/{templates → template_project}/.claude/skills/pdf-processing-pro/workflows-and-troubleshooting.md +0 -0
  295. /package/{templates → template_project}/.claude/skills/postgres/SKILL.md +0 -0
  296. /package/{templates → template_project}/.claude/skills/postgres/reference/fn_get_examples.sql +0 -0
  297. /package/{templates → template_project}/.claude/skills/postgres/reference/fn_rpt_examples.sql +0 -0
  298. /package/{templates → template_project}/.claude/skills/postgres/reference/utility_functions.sql +0 -0
  299. /package/{templates → template_project}/.claude/skills/pptx/LICENSE.txt +0 -0
  300. /package/{templates → template_project}/.claude/skills/pptx/SKILL.md +0 -0
  301. /package/{templates → template_project}/.claude/skills/pptx/design-references.md +0 -0
  302. /package/{templates → template_project}/.claude/skills/pptx/html2pptx.md +0 -0
  303. /package/{templates → template_project}/.claude/skills/pptx/ooxml.md +0 -0
  304. /package/{templates → template_project}/.claude/skills/pptx/scripts/html2pptx.js +0 -0
  305. /package/{templates → template_project}/.claude/skills/pptx/scripts/inventory.py +0 -0
  306. /package/{templates → template_project}/.claude/skills/pptx/scripts/rearrange.py +0 -0
  307. /package/{templates → template_project}/.claude/skills/pptx/scripts/replace.py +0 -0
  308. /package/{templates → template_project}/.claude/skills/pptx/scripts/thumbnail.py +0 -0
  309. /package/{templates → template_project}/.claude/skills/pptx/template-replacement-reference.md +0 -0
  310. /package/{templates → template_project}/.claude/skills/pptx/utilities.md +0 -0
  311. /package/{templates → template_project}/.claude/skills/principle-attack-the-premise/SKILL.md +0 -0
  312. /package/{templates → template_project}/.claude/skills/principle-boundary-discipline/SKILL.md +0 -0
  313. /package/{templates → template_project}/.claude/skills/principle-encode-lessons-in-structure/SKILL.md +0 -0
  314. /package/{templates → template_project}/.claude/skills/principle-fix-root-causes/SKILL.md +0 -0
  315. /package/{templates → template_project}/.claude/skills/principle-foundational-thinking/SKILL.md +0 -0
  316. /package/{templates → template_project}/.claude/skills/principle-guard-the-context-window/SKILL.md +0 -0
  317. /package/{templates → template_project}/.claude/skills/principle-laziness-protocol/SKILL.md +0 -0
  318. /package/{templates → template_project}/.claude/skills/principle-migrate-callers-then-delete-legacy-apis/SKILL.md +0 -0
  319. /package/{templates → template_project}/.claude/skills/principle-minimize-reader-load/SKILL.md +0 -0
  320. /package/{templates → template_project}/.claude/skills/principle-model-the-domain/SKILL.md +0 -0
  321. /package/{templates → template_project}/.claude/skills/principle-never-block-on-the-human/SKILL.md +0 -0
  322. /package/{templates → template_project}/.claude/skills/principle-prove-it-works/SKILL.md +0 -0
  323. /package/{templates → template_project}/.claude/skills/principle-sequence-verifiable-units/SKILL.md +0 -0
  324. /package/{templates → template_project}/.claude/skills/principle-subtract-before-you-add/SKILL.md +0 -0
  325. /package/{templates → template_project}/.claude/skills/principle-test-behavior-not-implementation/SKILL.md +0 -0
  326. /package/{templates → template_project}/.claude/skills/project-learning/SKILL.md +0 -0
  327. /package/{templates → template_project}/.claude/skills/repo-maintenance/SKILL.md +0 -0
  328. /package/{templates → template_project}/.claude/skills/research/EXAMPLES.md +0 -0
  329. /package/{templates → template_project}/.claude/skills/research/REFERENCE.md +0 -0
  330. /package/{templates → template_project}/.claude/skills/research/SKILL.md +0 -0
  331. /package/{templates → template_project}/.claude/skills/root-cause-tracing/SKILL.md +0 -0
  332. /package/{templates → template_project}/.claude/skills/root-cause-tracing/diagrams.md +0 -0
  333. /package/{templates → template_project}/.claude/skills/root-cause-tracing/find-polluter.sh +0 -0
  334. /package/{templates → template_project}/.claude/skills/sharing-skills/SKILL.md +0 -0
  335. /package/{templates → template_project}/.claude/skills/sharing-skills/complete-example.md +0 -0
  336. /package/{templates → template_project}/.claude/skills/skill-quality/rationalization-table-template.md +0 -0
  337. /package/{templates → template_project}/.claude/skills/skill-quality/trigger-accuracy-template.md +0 -0
  338. /package/{templates → template_project}/.claude/skills/sql-optimization-patterns/SKILL.md +0 -0
  339. /package/{templates → template_project}/.claude/skills/sql-optimization-patterns/references/advanced-techniques.md +0 -0
  340. /package/{templates → template_project}/.claude/skills/sql-optimization-patterns/references/core-concepts.md +0 -0
  341. /package/{templates → template_project}/.claude/skills/sql-optimization-patterns/references/query-patterns.md +0 -0
  342. /package/{templates → template_project}/.claude/skills/subagent-driven-development/SKILL.md +0 -0
  343. /package/{templates → template_project}/.claude/skills/subagent-driven-development/example-workflow.md +0 -0
  344. /package/{templates → template_project}/.claude/skills/systematic-debugging/CREATION-LOG.md +0 -0
  345. /package/{templates → template_project}/.claude/skills/systematic-debugging/SKILL.md +0 -0
  346. /package/{templates → template_project}/.claude/skills/systematic-debugging/reference-tables.md +0 -0
  347. /package/{templates → template_project}/.claude/skills/systematic-debugging/test-academic.md +0 -0
  348. /package/{templates → template_project}/.claude/skills/systematic-debugging/test-pressure-1.md +0 -0
  349. /package/{templates → template_project}/.claude/skills/systematic-debugging/test-pressure-2.md +0 -0
  350. /package/{templates → template_project}/.claude/skills/systematic-debugging/test-pressure-3.md +0 -0
  351. /package/{templates → template_project}/.claude/skills/test-driven-development/SKILL.md +0 -0
  352. /package/{templates → template_project}/.claude/skills/test-driven-development/reference-tables.md +0 -0
  353. /package/{templates → template_project}/.claude/skills/testing-anti-patterns/SKILL.md +0 -0
  354. /package/{templates → template_project}/.claude/skills/testing-anti-patterns/reference-tables.md +0 -0
  355. /package/{templates → template_project}/.claude/skills/testing-quality/SKILL.md +0 -0
  356. /package/{templates → template_project}/.claude/skills/update-status/SKILL.md +0 -0
  357. /package/{templates → template_project}/.claude/skills/verification-before-completion/SKILL.md +0 -0
  358. /package/{templates → template_project}/.claude/skills/verification-before-completion/key-patterns.md +0 -0
  359. /package/{templates → template_project}/.claude/skills/webapp-testing/LICENSE.txt +0 -0
  360. /package/{templates → template_project}/.claude/skills/webapp-testing/SKILL.md +0 -0
  361. /package/{templates → template_project}/.claude/skills/webapp-testing/examples/console_logging.py +0 -0
  362. /package/{templates → template_project}/.claude/skills/webapp-testing/examples/element_discovery.py +0 -0
  363. /package/{templates → template_project}/.claude/skills/webapp-testing/examples/static_html_automation.py +0 -0
  364. /package/{templates → template_project}/.claude/skills/webapp-testing/scripts/with_server.py +0 -0
  365. /package/{templates → template_project}/.claude/ukit/index/anchor-search.mjs +0 -0
  366. /package/{templates → template_project}/.claude/ukit/index/build-index.mjs +0 -0
  367. /package/{templates → template_project}/.claude/ukit/index/cache-utils.mjs +0 -0
  368. /package/{templates → template_project}/.claude/ukit/index/extract-image.mjs +0 -0
  369. /package/{templates → template_project}/.claude/ukit/index/impact-context.mjs +0 -0
  370. /package/{templates → template_project}/.claude/ukit/index/post-edit-verify.mjs +0 -0
  371. /package/{templates → template_project}/.claude/ukit/index/pre-edit-backup.mjs +0 -0
  372. /package/{templates → template_project}/.claude/ukit/index/provision-worktree.mjs +0 -0
  373. /package/{templates → template_project}/.claude/ukit/index/query-index.mjs +0 -0
  374. /package/{templates → template_project}/.claude/ukit/index/refresh-index.mjs +0 -0
  375. /package/{templates → template_project}/.claude/ukit/index/reset-auto-permissions.mjs +0 -0
  376. /package/{templates → template_project}/.claude/ukit/index/resolve-context.mjs +0 -0
  377. /package/{templates → template_project}/.claude/ukit/index/route-catalog.mjs +0 -0
  378. /package/{templates → template_project}/.claude/ukit/index/safe-patch.mjs +0 -0
  379. /package/{templates → template_project}/.claude/ukit/index/stale-spec-check.mjs +0 -0
  380. /package/{templates → template_project}/.claude/ukit/index/task-budget-validator.mjs +0 -0
  381. /package/{templates → template_project}/.claude/ukit/index/triage.mjs +0 -0
  382. /package/{templates → template_project}/.claude/ukit/index/verify-context.mjs +0 -0
  383. /package/{templates → template_project}/.claude/ukit/runtime/async-lock.mjs +0 -0
  384. /package/{templates → template_project}/.claude/ukit/runtime/compact-threshold.mjs +0 -0
  385. /package/{templates → template_project}/.claude/ukit/runtime/context-capacity.mjs +0 -0
  386. /package/{templates → template_project}/.claude/ukit/runtime/hook-chain-budget.mjs +0 -0
  387. /package/{templates → template_project}/.claude/ukit/runtime/hook-chain-runner.mjs +0 -0
  388. /package/{templates → template_project}/.claude/ukit/runtime/hook-field-salvage.mjs +0 -0
  389. /package/{templates → template_project}/.claude/ukit/runtime/hook-input.mjs +0 -0
  390. /package/{templates → template_project}/.claude/ukit/runtime/hook-input.sh +0 -0
  391. /package/{templates → template_project}/.claude/ukit/runtime/hook-payload-store.mjs +0 -0
  392. /package/{templates → template_project}/.claude/ukit/runtime/hook-process.mjs +0 -0
  393. /package/{templates → template_project}/.claude/ukit/runtime/hook-telemetry.mjs +0 -0
  394. /package/{templates → template_project}/.claude/ukit/runtime/hook-telemetry.sh +0 -0
  395. /package/{templates → template_project}/.claude/ukit/runtime/output-compression.mjs +0 -0
  396. /package/{templates → template_project}/.claude/ukit/runtime/project-important.mjs +0 -0
  397. /package/{templates → template_project}/.claude/ukit/runtime/reinject-context.mjs +0 -0
  398. /package/{templates → template_project}/.claude/ukit/runtime/text-profile.mjs +0 -0
  399. /package/{templates → template_project}/.claude/ukit/runtime/token-utils.mjs +0 -0
  400. /package/{templates → template_project}/.claude/ukit/runtime/transcript-tail.mjs +0 -0
  401. /package/{templates → template_project}/.claude/ukit/skill-router-state.json +0 -0
  402. /package/{templates → template_project}/.codex/README.md +0 -0
  403. /package/{templates → template_project}/.codex/settings.json +0 -0
  404. /package/{templates → template_project}/.omp/AGENTS.md +0 -0
  405. /package/{templates → template_project}/.omp/README.md +0 -0
  406. /package/{templates → template_project}/.omp/agents/bug-debugger.md +0 -0
  407. /package/{templates → template_project}/.omp/agents/feature-implementer.md +0 -0
  408. /package/{templates → template_project}/.omp/agents/ukit-small-task-maintainer.md +0 -0
  409. /package/{templates → template_project}/.omp/agents/ukit-vision-analyst.md +0 -0
  410. /package/{templates → template_project}/.omp/hooks/pre/ukit-bridge.js +0 -0
  411. /package/{templates → template_project}/.ukit/storage/cache/hook-latency/unknown.jsonl +0 -0
  412. /package/{templates → template_project}/PROJECT_IMPORTANT.md +0 -0
  413. /package/{templates → template_project}/adapter-presets/claude/settings.local.json +0 -0
  414. /package/{templates → template_project}/adapter-presets/codex/settings.local.json +0 -0
  415. /package/{templates → template_project}/docs/AI_HANDOFF/ACTIVE.md +0 -0
  416. /package/{templates → template_project}/docs/AI_HANDOFF/HISTORY.md +0 -0
  417. /package/{templates → template_project}/docs/AI_HANDOFF/INDEX.md +0 -0
  418. /package/{templates → template_project}/docs/AI_HANDOFF/PLAN.md +0 -0
  419. /package/{templates → template_project}/docs/AI_HANDOFF/SPEC.md +0 -0
  420. /package/{templates → template_project}/docs/AI_HANDOFF/archive/.gitkeep +0 -0
  421. /package/{templates → template_project}/docs/AI_HANDOFF/tasks/.gitkeep +0 -0
  422. /package/{templates → template_project}/docs/AI_HANDOFF/tasks/_TEMPLATE.md +0 -0
  423. /package/{templates → template_project}/docs/BUGFIX.md +0 -0
  424. /package/{templates → template_project}/docs/BUG_INDEX.md +0 -0
  425. /package/{templates → template_project}/docs/BUG_METRICS.md +0 -0
  426. /package/{templates → template_project}/docs/BUG_TEMPLATE.md +0 -0
  427. /package/{templates → template_project}/docs/CODE_MAP.md +0 -0
  428. /package/{templates → template_project}/docs/MEMORY.md +0 -0
  429. /package/{templates → template_project}/docs/PROJECT.md +0 -0
  430. /package/{templates → template_project}/docs/PROMPT_CACHING.md +0 -0
  431. /package/{templates → template_project}/docs/WORKLOG.md +0 -0
  432. /package/{templates → template_project}/instructions/overlays/agents.md +0 -0
  433. /package/{templates → template_project}/instructions/overlays/omp-rules.md +0 -0
  434. /package/{templates → template_project}/instructions/repo-vars.yaml +0 -0
  435. /package/{templates → template_project}/ukit/README.md +0 -0
  436. /package/{templates → template_project}/ukit/storage/cache/compact-history.json +0 -0
  437. /package/{templates → template_project}/ukit/storage/cache/compact-pressure.json +0 -0
  438. /package/{templates → template_project}/ukit/storage/cache/output-history.json +0 -0
  439. /package/{templates → template_project}/ukit/storage/cache/prompt-cache.json +0 -0
  440. /package/{templates → template_project}/ukit/storage/memory/sessions/.gitkeep +0 -0
  441. /package/{templates → template_project}/ukit/storage/memory/user.json +0 -0
  442. /package/{templates/user → template_user}/README.md +0 -0
  443. /package/{templates/user → template_user}/playbooks/bug-fix.md +0 -0
  444. /package/{templates/user → template_user}/playbooks/issue-implementation.md +0 -0
  445. /package/{templates/user → template_user}/storage/config.json +0 -0
@@ -11,6 +11,8 @@ import {
11
11
  EXECUTION_CONTRACTS,
12
12
  EXECUTION_MODE_ORDER,
13
13
  MODEL_TIER_BY_CONTRACT,
14
+ ROUTE_EFFORTS,
15
+ resolveModelTier,
14
16
  } from '../core/executionContracts.js';
15
17
  import { resolveModelRoles, readMergedRuntimeConfig } from '../core/runtimeConfig.js';
16
18
  import { resolvePlaybook } from '../core/userPlaybooks.js';
@@ -18,7 +20,7 @@ import { resolvePlaybook } from '../core/userPlaybooks.js';
18
20
  // --- v3 route-side advisory blocks (docs/pstack/SPEC-playbook-todo.md, ------------------
19
21
  // SPEC-principle-index.md, SPEC-model-roles.md). All three are additive stdout text —
20
22
  // they never change mode selection. Static text is byte-stable for prompt-cache reuse.
21
- // Mirrored literally in templates/.claude/ukit/index/route-task.mjs (parity-locked by
23
+ // Mirrored literally in template_project/.claude/ukit/index/route-task.mjs (parity-locked by
22
24
  // tests/consistency/executionContractSync.test.js).
23
25
 
24
26
  // SPEC-playbook-todo §2.1: numbered step lists the model copies verbatim into its todo
@@ -155,6 +157,29 @@ export const ROUTE_INTENT_KINDS = new Set(['informational', 'delivery', 'mutatio
155
157
  export const ROUTE_MUTABILITIES = new Set(['read-only', 'mutating', 'mixed']);
156
158
  export const ROUTE_RIGOR_LEVELS = new Set(['R0', 'R1', 'R2', 'R3', 'R4']);
157
159
  export const ROUTE_MODEL_TIERS = new Set(['lite', 'code', 'smart']);
160
+ export const ROUTE_RISK_FLOORS = new Set(['none', 'high-risk']);
161
+ // SPEC §5 FR-003: fixed table order — codes are emitted and printed in this order.
162
+ // The first six raise the floor to 'high-risk'; the last two are informational only.
163
+ export const ROUTE_RISK_REASON_CODES = Object.freeze([
164
+ 'security-sensitive',
165
+ 'shared-impact',
166
+ 'public-contract',
167
+ 'schema-change',
168
+ 'destructive-action',
169
+ 'cross-engine',
170
+ 'established-precedent',
171
+ 'explicit-local-target',
172
+ ]);
173
+ const ROUTE_RISK_FLOOR_RAISING_CODES = new Set(ROUTE_RISK_REASON_CODES.slice(0, 6));
174
+ const ROUTE_RISK_ENGINES = ['claude code', 'codex', 'omp'];
175
+
176
+ // FR-004 (M01.3'): Fast Path eligibility vocabulary. The suppressed list is fixed
177
+ // text per SPEC — deliberately not configurable. Reasons are the informational
178
+ // risk codes (the last two ROUTE_RISK_REASON_CODES entries) present on the route.
179
+ const FAST_PATH_MODES = new Set(['tiny-fix', 'local-fix']);
180
+ const FAST_PATH_SUPPRESSED = Object.freeze(['design', 'smart', 'subagents', 'broad-verify']);
181
+ const FAST_PATH_REASON_CODES = new Set(ROUTE_RISK_REASON_CODES.slice(6));
182
+
158
183
  // 'informational' is a real router emission (no completion contract) even though it is
159
184
  // not part of the seven-lane EXECUTION_MODE_ORDER ladder.
160
185
  export const ROUTE_EXECUTION_MODES = [...EXECUTION_MODE_ORDER, 'informational'];
@@ -169,6 +194,163 @@ export function resolveRouteSchemaStage(config = null) {
169
194
  return ROUTE_SCHEMA_STAGES.has(stage) ? stage : 'off';
170
195
  }
171
196
 
197
+ // FR-002: generic stage resolver — every routing.<key>.stage shares the same
198
+ // absent/malformed → 'off' contract. resolveRouteSchemaStage stays as the
199
+ // routeSchema-specific spelling of this helper.
200
+ export function resolveRouteStage(config = null, key) {
201
+ const stage = config?.routing?.[key]?.stage;
202
+ return ROUTE_SCHEMA_STAGES.has(stage) ? stage : 'off';
203
+ }
204
+
205
+ // FR-003 (M01.2'): derive the additive riskFloor from hard signals. Codes are
206
+ // collected in ROUTE_RISK_REASON_CODES table order; the floor is 'high-risk' iff
207
+ // any of the first six (floor-raising) codes fired — informational codes never
208
+ // raise it. Detectors read the normalized signal text (same source the mode
209
+ // ladder uses) plus the raw target path and context preview.
210
+ export function deriveRiskFloor({
211
+ promptText = '',
212
+ commandText = '',
213
+ targetFile = null,
214
+ executionMode = null,
215
+ activeSkillIds = [],
216
+ contextPreview = null,
217
+ } = {}) {
218
+ const signalText = buildRouteSignalText(promptText, commandText);
219
+ const target = String(targetFile || '');
220
+ const skillIds = Array.isArray(activeSkillIds) ? activeSkillIds : [];
221
+ const codes = [];
222
+ if (
223
+ /\b(auth|security|token|permission|secret|credential|password|vulnerab|exploit|xss|injection)\b/i.test(signalText)
224
+ || skillIds.includes('discover-security')
225
+ ) {
226
+ codes.push('security-sensitive');
227
+ }
228
+ if (isSharedImpactFile(targetFile) || executionMode === 'shared-edit' || executionMode === 'map-impact') {
229
+ codes.push('shared-impact');
230
+ }
231
+ if (
232
+ /(^|\/)(package\.json|manifests\/|.*\.d\.ts$|(^|\/)api\/|openapi|swagger)/i.test(target)
233
+ || /\b(public api|breaking change|api contract|semver)\b/i.test(signalText)
234
+ ) {
235
+ codes.push('public-contract');
236
+ }
237
+ if (
238
+ /(^|\/)(migrations?|db|database|prisma|schema)/i.test(target)
239
+ || /\b(migration|migrate|schema|alter table|add column|drop column)\b/i.test(signalText)
240
+ ) {
241
+ codes.push('schema-change');
242
+ }
243
+ if (/\b(delete|drop|truncate|destroy|wipe|uninstall|rm -rf|purge)\b/i.test(signalText)) {
244
+ codes.push('destructive-action');
245
+ }
246
+ const engineHits = ROUTE_RISK_ENGINES.filter(
247
+ (name) => new RegExp(`\\b${name}\\b`, 'i').test(signalText),
248
+ ).length;
249
+ if (
250
+ /\bcross[- ]engine\b|\ball engines\b/i.test(signalText)
251
+ || engineHits >= 2
252
+ || /^template_project\/\.(claude|codex|omp)\//i.test(target)
253
+ ) {
254
+ codes.push('cross-engine');
255
+ }
256
+ if ((contextPreview?.analogFiles?.length ?? 0) > 0 || (contextPreview?.styleFiles?.length ?? 0) > 0) {
257
+ codes.push('established-precedent');
258
+ }
259
+ if (target && !isSharedImpactFile(targetFile)) {
260
+ codes.push('explicit-local-target');
261
+ }
262
+ return {
263
+ floor: codes.some((code) => ROUTE_RISK_FLOOR_RAISING_CODES.has(code)) ? 'high-risk' : 'none',
264
+ codes,
265
+ };
266
+ }
267
+
268
+ // Route-line segment (FR-003): on 'high-risk' only the floor-raising codes print;
269
+ // on 'none' the informational codes do. Empty list → no segment at all.
270
+ function formatRiskFloorSegment(riskFloor = null) {
271
+ if (!riskFloor) {
272
+ return null;
273
+ }
274
+ const printed = riskFloor.floor === 'high-risk'
275
+ ? riskFloor.codes.filter((code) => ROUTE_RISK_FLOOR_RAISING_CODES.has(code))
276
+ : riskFloor.codes;
277
+ return printed.length > 0 ? `risk=${riskFloor.floor}(${printed.join(',')})` : null;
278
+ }
279
+
280
+ // FR-001 (M01.2' limits fragment): compile the contract's numeric budget keys
281
+ // into an advisory map. Only finite numbers survive — a non-numeric or missing
282
+ // key is simply absent. Zero is a real budget ("no read passes"), never
283
+ // filtered. Same key set as the ceremonyBudget.limits builder below.
284
+ export function deriveCeremonyLimits(executionContract = null) {
285
+ if (executionContract === null || typeof executionContract !== 'object') {
286
+ return {};
287
+ }
288
+ return Object.fromEntries(
289
+ ['maxReadPasses', 'maxContextPulls', 'maxReadPassesBeforeReassess']
290
+ .filter((key) => Number.isFinite(executionContract[key]))
291
+ .map((key) => [key, executionContract[key]]),
292
+ );
293
+ }
294
+
295
+ // Route-line segment (FR-002): fixed reads,ctx,reassess order; only present
296
+ // keys print. Empty/absent map → null so the segment never appears.
297
+ export function formatLimitsSegment(limits = null) {
298
+ if (limits === null || typeof limits !== 'object') {
299
+ return null;
300
+ }
301
+ const parts = [
302
+ ['reads', 'maxReadPasses'],
303
+ ['ctx', 'maxContextPulls'],
304
+ ['reassess', 'maxReadPassesBeforeReassess'],
305
+ ]
306
+ .filter(([, key]) => Number.isFinite(limits[key]))
307
+ .map(([label, key]) => `${label}:${limits[key]}`);
308
+ return parts.length > 0 ? `limits=${parts.join(',')}` : null;
309
+ }
310
+
311
+ // FR-004 (M01.3'): Fast Path eligibility predicate. Returns null when no riskFloor
312
+ // was supplied — eligibility must never be derived without the floor check, so a
313
+ // missing floor means "not computed", not "none". Eligible iff the lane is
314
+ // tiny-fix/local-fix, exactly one local target is known, the floor is 'none',
315
+ // a bounded verification path exists (targeted commands or the tiny-fix
316
+ // 'minimal-or-targeted' contract policy), and the target is not shared-impact.
317
+ export function deriveFastPath({
318
+ executionMode = null,
319
+ targetFile = null,
320
+ riskFloor = null,
321
+ verificationRecommendation = null,
322
+ contextPreview = null,
323
+ } = {}) {
324
+ if (!riskFloor) {
325
+ return null;
326
+ }
327
+ const reasons = (riskFloor.codes ?? []).filter((code) => FAST_PATH_REASON_CODES.has(code));
328
+ const hasLocalTarget = Boolean(targetFile) || contextPreview?.primaryTargets?.length === 1;
329
+ const hasBoundedVerification = (verificationRecommendation?.commands?.length ?? 0) > 0
330
+ || buildExecutionContract(executionMode)?.verificationPolicy === 'minimal-or-targeted';
331
+ const eligible = FAST_PATH_MODES.has(executionMode)
332
+ && hasLocalTarget
333
+ && riskFloor.floor === 'none'
334
+ && hasBoundedVerification
335
+ && !isSharedImpactFile(targetFile);
336
+ return {
337
+ eligible,
338
+ suppressed: eligible ? [...FAST_PATH_SUPPRESSED] : [],
339
+ reasons,
340
+ };
341
+ }
342
+
343
+ // Route-line segment (FR-004): emitted only for eligible routes — ineligible
344
+ // routes keep the routeSummary.fastPath field for telemetry but stay silent.
345
+ function formatFastPathSegment(fastPath = null) {
346
+ if (!fastPath?.eligible) {
347
+ return null;
348
+ }
349
+ const reasons = fastPath.reasons?.length ? ` (${fastPath.reasons.join(',')})` : '';
350
+ return `fastPath=on | suppress: ${FAST_PATH_SUPPRESSED.join(',')}${reasons}`;
351
+ }
352
+
353
+
172
354
 
173
355
  // A bare delivery command ("push this to git", "đẩy bộ này lên git") performs no
174
356
  // repository mutation the ledger could ever receipt. With no edit/review/debug/build
@@ -232,7 +414,12 @@ function buildResolvedRouteFields({
232
414
  executionMode = null,
233
415
  executionContract = null,
234
416
  completionState = null,
417
+ riskFloor = null,
235
418
  } = {}) {
419
+ // Decision table v2 (FR-001/FR-002): tier + effort resolve together from the
420
+ // contract lane and the additive riskFloor. The router cannot observe host
421
+ // binding capabilities, so the emitted pair is advisory text by definition.
422
+ const tierDecision = resolveModelTier({ executionMode, riskFloor });
236
423
  const signalText = buildRouteSignalText(routingContext.promptText, routingContext.commandText);
237
424
  const deliveryOnly = isDeliveryOnlyRequest({
238
425
  signalText,
@@ -254,13 +441,15 @@ function buildResolvedRouteFields({
254
441
  execution: {
255
442
  mode: executionMode,
256
443
  rigor: null,
444
+ riskFloor: riskFloor?.floor ?? null,
257
445
  phase: null,
258
446
  contractVersion: ROUTE_CONTRACT_VERSION,
259
- modelTier: executionContract?.modelTier ?? MODEL_TIER_BY_CONTRACT[executionMode] ?? null,
447
+ modelTier: tierDecision.tier,
448
+ effort: tierDecision.effort,
260
449
  },
261
450
  evidence: {
262
451
  observations: [],
263
- riskSignals: [],
452
+ riskSignals: riskFloor?.codes ?? [],
264
453
  activationReasons: [],
265
454
  suppressionReasons: [],
266
455
  completionRequirements: unique(completionState?.missingEvidence ?? []),
@@ -268,7 +457,13 @@ function buildResolvedRouteFields({
268
457
  ceremonyBudget: {
269
458
  policyVersion: ROUTE_CONTRACT_VERSION,
270
459
  rigor: null,
271
- limits: {},
460
+ limits: riskFloor
461
+ ? Object.fromEntries(
462
+ ['maxReadPasses', 'maxContextPulls', 'maxReadPassesBeforeReassess']
463
+ .filter((key) => typeof executionContract?.[key] === 'number')
464
+ .map((key) => [key, executionContract[key]]),
465
+ )
466
+ : {},
272
467
  consumed: {},
273
468
  exceptions: [],
274
469
  },
@@ -324,12 +519,19 @@ export function validateResolvedRoute(route = null) {
324
519
  if (route.execution.rigor !== null && !ROUTE_RIGOR_LEVELS.has(route.execution.rigor)) {
325
520
  errors.push(`execution.rigor must be null or one of: ${[...ROUTE_RIGOR_LEVELS].join(', ')}.`);
326
521
  }
522
+ if (route.execution.riskFloor !== null && !ROUTE_RISK_FLOORS.has(route.execution.riskFloor)) {
523
+ errors.push(`execution.riskFloor must be null or one of: ${[...ROUTE_RISK_FLOORS].join(', ')}.`);
524
+ }
327
525
  if (route.execution.contractVersion !== ROUTE_CONTRACT_VERSION) {
328
526
  errors.push(`execution.contractVersion must be ${ROUTE_CONTRACT_VERSION}.`);
329
527
  }
330
528
  if (route.execution.modelTier !== null && !ROUTE_MODEL_TIERS.has(route.execution.modelTier)) {
331
529
  errors.push(`execution.modelTier must be null or one of: ${[...ROUTE_MODEL_TIERS].join(', ')}.`);
332
530
  }
531
+ if (route.execution.effort !== null && route.execution.effort !== undefined
532
+ && !ROUTE_EFFORTS.has(route.execution.effort)) {
533
+ errors.push(`execution.effort must be null or one of: ${[...ROUTE_EFFORTS].join(', ')}.`);
534
+ }
333
535
  }
334
536
  if (!isObject(route.evidence)) {
335
537
  errors.push('evidence must be an object.');
@@ -339,6 +541,12 @@ export function validateResolvedRoute(route = null) {
339
541
  errors.push(`evidence.${key} must be an array.`);
340
542
  }
341
543
  }
544
+ if (Array.isArray(route.evidence.riskSignals)
545
+ && route.evidence.riskSignals.some(
546
+ (code) => typeof code !== 'string' || !ROUTE_RISK_REASON_CODES.includes(code),
547
+ )) {
548
+ errors.push(`evidence.riskSignals entries must be one of: ${ROUTE_RISK_REASON_CODES.join(', ')}.`);
549
+ }
342
550
  }
343
551
  if (!isObject(route.ceremonyBudget)) {
344
552
  errors.push('ceremonyBudget must be an object.');
@@ -667,6 +875,48 @@ export function buildRouteSummary({
667
875
  nextActionType: nextAction?.type ?? null,
668
876
  completionState,
669
877
  });
878
+ // FR-003 (M01.2'): riskFloor is a top-level additive field emitted whenever ANY
879
+ // of rigor/fastPath/escalation stages is on — fastPath/escalation consumers read
880
+ // it even when routeSchema is off. All three off → absent, byte-identical route.
881
+ const riskStageOn = ['rigor', 'fastPath', 'escalation']
882
+ .some((key) => resolveRouteStage(runtimeConfig, key) !== 'off');
883
+ const riskFloor = riskStageOn
884
+ ? deriveRiskFloor({
885
+ promptText: routingContext.promptText,
886
+ commandText: routingContext.commandText,
887
+ targetFile: routingContext.targetFile ?? null,
888
+ executionMode,
889
+ activeSkillIds: activeSkills.map((entry) => entry.id),
890
+ contextPreview: contextRecommendation?.preview ?? null,
891
+ })
892
+ : null;
893
+ const riskSegment = formatRiskFloorSegment(riskFloor);
894
+ // FR-003 (M01.2' limits fragment): the rigor advisory — emitted whenever
895
+ // rigor.stage is on, independent of fastPath/escalation. Stage off → no
896
+ // segment, byte-identical route.
897
+ const limitsSegment = resolveRouteStage(runtimeConfig, 'rigor') !== 'off'
898
+ ? formatLimitsSegment(deriveCeremonyLimits(executionContract))
899
+ : null;
900
+ // FR-004 (M01.3'): fastPath is emitted whenever its own stage is on — the field
901
+ // is always set then (eligible or not) so telemetry/harness can read it; the
902
+ // route-line segment prints only for eligible routes.
903
+ const fastPathStage = resolveRouteStage(runtimeConfig, 'fastPath');
904
+ const fastPath = fastPathStage !== 'off'
905
+ ? {
906
+ eligible: false,
907
+ suppressed: [],
908
+ reasons: [],
909
+ ...deriveFastPath({
910
+ executionMode,
911
+ targetFile: routingContext.targetFile ?? null,
912
+ riskFloor,
913
+ verificationRecommendation,
914
+ contextPreview: contextRecommendation?.preview ?? null,
915
+ }),
916
+ stage: fastPathStage,
917
+ }
918
+ : null;
919
+ const fastPathSegment = formatFastPathSegment(fastPath);
670
920
  const resolvedRouteFields = routeSchemaStage !== 'off'
671
921
  ? buildResolvedRouteFields({
672
922
  routingContext,
@@ -674,6 +924,7 @@ export function buildRouteSummary({
674
924
  executionMode,
675
925
  executionContract,
676
926
  completionState,
927
+ riskFloor,
677
928
  })
678
929
  : null;
679
930
  const helperHint = compactHelperHint(
@@ -716,6 +967,9 @@ export function buildRouteSummary({
716
967
  formatCompactSegment('tests', relatedTests),
717
968
  formatCompactSegment('styles', styleFiles),
718
969
  editGuardHint ? `editGuard=${editGuardHint}` : null,
970
+ riskSegment,
971
+ limitsSegment,
972
+ fastPathSegment,
719
973
  delegationRecommendation?.hint ? `delegate=${delegationRecommendation.hint}` : null,
720
974
  policyMode ? `policy=${policyMode}` : null,
721
975
  workflowPolicyName ? `workflow=${workflowPolicyName}` : null,
@@ -737,6 +991,10 @@ export function buildRouteSummary({
737
991
  completionState,
738
992
  // M01.1 additive C01 groups — present only when routing.routeSchema.stage != "off".
739
993
  ...(resolvedRouteFields ?? {}),
994
+ // FR-003 additive top-level field — present only when a risk stage is on.
995
+ ...(riskFloor ? { riskFloor } : {}),
996
+ // FR-004 additive top-level field — present only when fastPath stage is on.
997
+ ...(fastPath ? { fastPath } : {}),
740
998
  continuationState,
741
999
  autonomyLevel,
742
1000
  continuousExecution,
@@ -864,7 +1122,7 @@ function deriveExecutionScores({
864
1122
  // asking for an explanation, not a repository change. Routing it to an investigation or
865
1123
  // edit lane fabricates write/verification debt the completion gate then enforces against an
866
1124
  // answer turn. Kept byte-equivalent to the shipped copies in
867
- // templates/.claude/ukit/index/route-task.mjs and templates/.claude/hooks/skill-router.sh;
1125
+ // template_project/.claude/ukit/index/route-task.mjs and template_project/.claude/hooks/skill-router.sh;
868
1126
  // this is the canonical copy those are mirror-tested against. It deliberately ignores
869
1127
  // targetFile: an edit order phrased as a question is caught by implementWords below, while a
870
1128
  // pure targeted question ("how does X work?") is still just a question.
@@ -173,11 +173,11 @@ export function renderAll(layout, sourceTexts, varsByResolve = {}) {
173
173
  }
174
174
 
175
175
  const SOURCE_FILES = {
176
- core: 'templates/instructions/core.md',
177
- 'overlay:claude': 'templates/instructions/overlays/claude.md',
178
- 'overlay:agents': 'templates/instructions/overlays/agents.md',
179
- 'overlay:omp-rules': 'templates/instructions/overlays/omp-rules.md',
180
- 'overlay:repo': 'templates/instructions/overlays/repo.md',
176
+ core: 'template_project/instructions/core.md',
177
+ 'overlay:claude': 'template_project/instructions/overlays/claude.md',
178
+ 'overlay:agents': 'template_project/instructions/overlays/agents.md',
179
+ 'overlay:omp-rules': 'template_project/instructions/overlays/omp-rules.md',
180
+ 'overlay:repo': 'template_project/instructions/overlays/repo.md',
181
181
  };
182
182
 
183
183
  /**
@@ -187,10 +187,10 @@ const SOURCE_FILES = {
187
187
  export async function renderInstructionsFromDisk({ repoRoot, write = true } = {}) {
188
188
  const abs = (p) => path.join(repoRoot, p);
189
189
  const layout = YAML.parse(
190
- fs.readFileSync(abs('templates/instructions/layout.yaml'), 'utf8'),
190
+ fs.readFileSync(abs('template_project/instructions/layout.yaml'), 'utf8'),
191
191
  );
192
192
  const repoVars =
193
- YAML.parse(fs.readFileSync(abs('templates/instructions/repo-vars.yaml'), 'utf8')) || {};
193
+ YAML.parse(fs.readFileSync(abs('template_project/instructions/repo-vars.yaml'), 'utf8')) || {};
194
194
  const pkg = JSON.parse(fs.readFileSync(abs('package.json'), 'utf8'));
195
195
 
196
196
  const sourceTexts = {};
@@ -23,7 +23,7 @@ export async function initSkillAudit({ rootDir = process.cwd(), skillName } = {}
23
23
  const auditDir = getAuditDir(rootDir, skillName);
24
24
  await fs.mkdir(auditDir, { recursive: true });
25
25
 
26
- const templateSourceDir = path.join(rootDir, 'templates/.claude/skills/skill-quality');
26
+ const templateSourceDir = path.join(rootDir, 'template_project/.claude/skills/skill-quality');
27
27
  const copied = [];
28
28
  const skipped = [];
29
29
 
@@ -57,6 +57,8 @@ If any input is missing, return `CHANGES-REQUESTED` with reason "incomplete hand
57
57
  VERDICT: APPROVED | APPROVED-WITH-MINOR | CHANGES-REQUESTED | CRITICAL
58
58
  REVIEWER_MODEL: [model name actually used]
59
59
  EXECUTOR_MODEL: [from executor report]
60
+ PANEL_MEMBER: [panel tier — `smart`/`code`/`lite`, or `solo` when the panel degenerates; `-` outside panel runs]
61
+ AGREEMENT_MAP: [lead member only — finding → panel members reporting it, from review-panel-aggregate.mjs output; `-` otherwise]
60
62
  VERIFICATION_RERUN:
61
63
  command: [exact command]
62
64
  result: [N pass / M fail]
@@ -121,6 +123,29 @@ Same model is the most common silent failure. Do not skip this check.
121
123
  - Keep the verdict block <= 30 lines. Findings are bullet points, not essays.
122
124
  - The same-model refusal above is non-negotiable: bypassing it defeats the entire Quality Gate.
123
125
 
126
+ ## Panel review (diversity review)
127
+
128
+ When the orchestrator spawns you as one member of the `modelRoles['review-panel']`
129
+ panel (`.ukit/storage/config.json` → `modelRoles`, default `['smart','code','lite']`),
130
+ everything above applies unchanged — same Review order, same severity ladder, same
131
+ verdict block — with these additions:
132
+
133
+ - Set `PANEL_MEMBER: <tier>` in the verdict to your panel tier (e.g. `smart`,
134
+ `code`, `lite`). Every member runs the same rubric independently; do not read or
135
+ wait for other members' verdicts.
136
+ - Leave `AGREEMENT_MAP` as `-` unless you are the **lead member** (the first entry in
137
+ `modelRoles['review-panel']` = the judgment tier). After the orchestrator runs
138
+ `node .claude/ukit/index/review-panel-aggregate.mjs <TASK-xxx.md...>` and hands you
139
+ the output, the lead fills `AGREEMENT_MAP` with the emitted finding → members map
140
+ and applies the lead-judgment buckets to every finding: **Act on** / **Consider** /
141
+ **Noted** / **Dismissed**.
142
+ - `consensus≥2 identical findings = high signal`: a finding reported by two or more
143
+ panel members is high-signal and must not be bucketed below **Consider** without a
144
+ stated reason.
145
+ - Degenerate panel: if `modelRoles['review-panel']` is empty or has one entry, the
146
+ panel collapses to a single reviewer — run the normal solo review, set
147
+ `PANEL_MEMBER: solo`, and note the fallback in `NOTES`.
148
+
124
149
  ## Spec/Plan Review (REVIEW_TARGET_TYPE=spec|plan)
125
150
 
126
151
  ### Inputs you expect
@@ -76,7 +76,7 @@ verification — link both files' `## Discussion` threads.
76
76
 
77
77
  ## Phase 0.5 — Write SPEC.md
78
78
 
79
- Write `docs/AI_HANDOFF/SPEC.md` from the template at `templates/docs/AI_HANDOFF/SPEC.md`
79
+ Write `docs/AI_HANDOFF/SPEC.md` from the template at `template_project/docs/AI_HANDOFF/SPEC.md`
80
80
  (15 sections). The spec is the contract executors implement against — concrete enough that
81
81
  nothing is guessed: exact paths, module and API names, schemas, validation rules,
82
82
  permissions, empty/error states, migration behavior, test expectations. Every section is
@@ -135,7 +135,7 @@ Use `_TEMPLATE.md` structure (from pre-read context or file).
135
135
  | Dependencies | `TASK-xxx` or `none` — wave order is inferred from this |
136
136
  | Test Cases | Type \| Test Name \| Expected — ≥1 happy + ≥2 edge cases of different kinds |
137
137
  | Test Files | Exact test file paths to create/modify |
138
- | Verification Commands | Runnable shell commands — MUST include the project's lint/typecheck command if one exists (see §5 rule above). Apply the "Test selection" resolution order from docs/AI_HANDOFF/RULES.md: `src/`/`scripts/` targets → the `tests` array in `.cache/index/tests-map.json`; `templates/.claude/**`/`.claude/**` targets → path convention (hooks → `tests/hooks/` + `tests/handoff/cycle*/`; manifest/settings → `tests/manifest/`; runtime `.mjs` mirrors → `tests/core/*Parity*` + `tests/index/`); if both resolve to fewer than one test file the task MUST fall back to `yarn test:release-core` — never the full suite by default, never an empty selection |
138
+ | Verification Commands | Runnable shell commands — MUST include the project's lint/typecheck command if one exists (see §5 rule above). Apply the "Test selection" resolution order from docs/AI_HANDOFF/RULES.md: `src/`/`scripts/` targets → the `tests` array in `.cache/index/tests-map.json`; `template_project/.claude/**`/`.claude/**` targets → path convention (hooks → `tests/hooks/` + `tests/handoff/cycle*/`; manifest/settings → `tests/manifest/`; runtime `.mjs` mirrors → `tests/core/*Parity*` + `tests/index/`); if both resolve to fewer than one test file the task MUST fall back to `yarn test:release-core` — never the full suite by default, never an empty selection |
139
139
  | Acceptance Criteria | Verifiable checklist |
140
140
 
141
141
  Missing any field → `needs_breakdown`. Never mark incomplete tasks `ready`.
@@ -196,6 +196,21 @@ Status: planning_done — ready for executor
196
196
  ```
197
197
  Wave structure is NOT stored here — inferred from task `Dependencies` fields at runtime.
198
198
 
199
+ **RUN.md** — write the run's `ExitPredicate:` line before iteration 1 (the orchestrator
200
+ keeps it verbatim on every cursor rewrite):
201
+
202
+ ```
203
+ ExitPredicate: all(index:all-done, git:clean)
204
+ ```
205
+
206
+ Grammar: `all(<term>[,<term>...])` or a single term; terms are `index:all-done`,
207
+ `git:clean`, `file-exists:<relpath>` (repo-relative, no `..` segments). Default to
208
+ `all(index:all-done, git:clean)`; add `file-exists:` terms only for artifacts the plan
209
+ itself must produce. The stop gate evaluates this mechanically when the cursor claims
210
+ `Phase: done` — a `done` claim with failing terms is bounced back with the per-term
211
+ state. **Never relax the predicate mid-run**: if the run cannot satisfy it, the plan is
212
+ wrong — fix the plan, not the gate.
213
+
199
214
  ## Self-Audit — run before reporting, every time
200
215
 
201
216
  The downstream pipeline is unattended: an incomplete or wrong plan is not caught by a human
@@ -70,7 +70,7 @@ The planner agent does the following (use Step 1 summary — do NOT re-read file
70
70
  ```
71
71
 
72
72
  3. Write `docs/AI_HANDOFF/SPEC.md` — the detailed implementation spec (BẮT BUỘC before tasks).
73
- Follow `docs/AI_HANDOFF/SPEC.md`'s template sections (or `templates/docs/AI_HANDOFF/SPEC.md`
73
+ Follow `docs/AI_HANDOFF/SPEC.md`'s template sections (or `template_project/docs/AI_HANDOFF/SPEC.md`
74
74
  on a fresh tree): problem/context, goals, non-goals, user journeys, functional requirements
75
75
  with Given/When/Then + error cases, fullstack scope (backend, schema/migrations, API
76
76
  contract, UI+state, integration, security, performance, observability, deploy/rollback),
@@ -59,7 +59,7 @@ resumable. If compaction does happen, the run resumes from the cursor automatica
59
59
 
60
60
  ### Run cursor — write after every step
61
61
 
62
- Maintain `docs/AI_HANDOFF/RUN.md`. Rewrite it (whole file, 6 lines) immediately after every
62
+ Maintain `docs/AI_HANDOFF/RUN.md`. Rewrite it (whole file, 7 lines) immediately after every
63
63
  numbered step completes:
64
64
 
65
65
  ```
@@ -69,9 +69,15 @@ Base: <BASE branch>
69
69
  Phase: <P0|P1|P2|P2.5|P3|I1|I2|I3|I4|R1|R2|R3|R4|R4.5|R5|F|done|blocked>
70
70
  Cursor: wave <N> batch <M> — <what just finished>
71
71
  Next: <the exact next step to run>
72
+ ExitPredicate: all(<term>[,<term>...]) # written once at P2; never relaxed
72
73
  QuietScans: <n>/<required> # only while sweeping for stragglers near the end
73
74
  ```
74
75
 
76
+ `ExitPredicate` grammar: `all(<term>[,<term>...])` or a single term; terms are
77
+ `index:all-done`, `git:clean`, `file-exists:<relpath>`. The stop gate evaluates it
78
+ mechanically when the cursor claims `Phase: done` — a `done` claim with failing terms
79
+ is bounced back with the per-term state. Keep the line verbatim on every rewrite.
80
+
75
81
  This file is the resume contract. It costs one small write per step and is what turns an
76
82
  interrupted run into a continuable one.
77
83
 
@@ -172,9 +178,12 @@ The run must keep itself alive without the human watching.
172
178
 
173
179
  - **Stop gate (Claude Code, automatic):** while `RUN.md` `Phase:` is not `done`/`blocked`,
174
180
  `completion-gate.sh` refuses the stop with the cursor's `Next:` step. Recaps and
175
- premature stops cannot park the run. A stalled-cursor breaker
181
+ premature stops cannot park the run. When RUN.md carries `ExitPredicate:`, a
182
+ `Phase: done` whose predicate fails is refused too — `done` means the predicate
183
+ evaluates true. A stalled-cursor breaker
176
184
  (`handoff.fullstack.stopGateMaxStalledBlocks`, default 12) releases the session if the
177
- cursor has genuinely stopped advancing — the escape hatch, not the norm.
185
+ cursor has genuinely stopped advancing — the escape hatch, not the norm — and its
186
+ release advisory reports the predicate state, so a plateau is visible, not silent.
178
187
  - **Scheduled wakeup (when the harness offers one):** arm it at run start — Claude Code:
179
188
  `CronCreate` a ~`handoff.fullstack.idleWatchdogMin`-minute (default 5) session job with
180
189
  prompt `Resume HANDOFF FULLSTACK from docs/AI_HANDOFF/RUN.md — continue the Next: step`;
@@ -222,7 +231,7 @@ The planner agent does the following (use P1 summary — do NOT re-read files):
222
231
  ```
223
232
 
224
233
  3. **Write `docs/AI_HANDOFF/SPEC.md`** — the detailed implementation spec, from
225
- `templates/docs/AI_HANDOFF/SPEC.md`'s section list (or RULES.md §Spec). It must be
234
+ `template_project/docs/AI_HANDOFF/SPEC.md`'s section list (or RULES.md §Spec). It must be
226
235
  concrete enough that an executor implements without guessing: exact paths, module and
227
236
  API names, schemas, validation rules, permissions, empty/error states, migration
228
237
  behavior, and test expectations — every applicable section filled, open questions
@@ -269,7 +278,13 @@ The planner agent does the following (use P1 summary — do NOT re-read files):
269
278
  ```
270
279
  Then **verify the write** (read back the `Status:` line).
271
280
 
272
- 8. **Report:** task IDs, dependency graph, recovery/superseded tasks, any
281
+ 8. **Write `ExitPredicate:` into `docs/AI_HANDOFF/RUN.md`** — the mechanical definition of
282
+ done for this run: `all(<term>[,<term>...])` over `index:all-done`, `git:clean`,
283
+ `file-exists:<relpath>` (default `all(index:all-done, git:clean)`). Written once,
284
+ before iteration 1, and **never relaxed** — if the run cannot satisfy it, the plan is
285
+ wrong, not the gate. Then **verify the write** (read back the `ExitPredicate:` line).
286
+
287
+ 9. **Report:** task IDs, dependency graph, recovery/superseded tasks, any
273
288
  `needs_breakdown` tasks + reason.
274
289
 
275
290
  ### P2.5 — Independent plan review (strong model, separate agent)
@@ -455,7 +470,12 @@ Worktrees are **always deleted immediately** — no exceptions.
455
470
  A wave boundary is the only safe place to shed context, because everything of value is
456
471
  already on disk (task files hold the full logs, git holds the code). Do all four, in order:
457
472
 
458
- 1. **Checkpoint the code** — one commit per wave, so every wave is independently revertible:
473
+ 1. **Checkpoint the code — commit-if-advanced.** One commit per wave, so every wave is
474
+ independently revertible — but only when the wave's diff advances the run's
475
+ `ExitPredicate` (a task moved toward `done`, a required file appeared, the worktree
476
+ got cleaner). A wave whose diff does not advance the predicate is **discarded**: its
477
+ copied-back changes are reverted and nothing is committed. A plateau is not a stop —
478
+ the run continues to the next wave or fix round; the predicate is never relaxed.
459
479
  ```bash
460
480
  git add -A && git commit -m "handoff: wave <N> — TASK-00x, TASK-00y"
461
481
  ```
@@ -54,9 +54,11 @@ If that diff is empty → handoff-implement was not completed. Report which task
54
54
 
55
55
  **Batch the review set — mandatory.** Read `handoff.maxParallelAgents` from `.ukit/storage/config.json`. If more `pending_review` tasks exist than that, split into consecutive batches of at most that many; finish one batch's verdicts (2a–2d, appended to each task file) before starting the next.
56
56
 
57
- **Claude Code — MANDATORY, do this before anything else:** for each batch, call the Agent tool once per `pending_review` task **in parallel** (at most `handoff.maxParallelAgents`), each with `subagent_type: "code-reviewer"` (omp: the `task` tool with `agent: "code-reviewer"`, likewise invoked once per task in the batch, not once per wave). Reviewer agents only read the diff and append a verdict to their own task file — no worktree, no shared write target — so running them in parallel carries none of Phase 3's file-conflict risk. Do NOT review the diff yourself in the current session — this step is contracted to the strong tier (opus/unic-smart) and MUST differ from the executor's model, which only the spawned agent's frontmatter model guarantees. Pass each agent: the task file path, the executor's report, and the diff.
57
+ **Spawn the review panel — MANDATORY, do this before anything else:** read `modelRoles['review-panel']` from `.ukit/storage/config.json` → `modelRoles` (default `['smart','code','lite']`; omp tier aliases `@smol`/`@default`/`@slow`). For each `pending_review` task in the batch, call the Agent tool **once per panel entry** (in parallel, bounded by `handoff.maxParallelAgents`), each with `subagent_type: "code-reviewer"` (omp: the `task` tool with `agent: "code-reviewer"`, likewise invoked once per panel entry per task) — each member bound to its panel tier and setting `PANEL_MEMBER: <tier>` in its verdict. Reviewer agents only read the diff and append a verdict to their own task file — no worktree, no shared write target — so running them in parallel carries none of Phase 3's file-conflict risk. Do NOT review the diff yourself in the current session — this step is contracted to the panel tiers and MUST differ from the executor's model, which only the spawned agent's frontmatter model guarantees. Pass each agent: the task file path, the executor's report, and the diff.
58
58
 
59
- The spawned reviewer agent performs 2a–2d below per task:
59
+ Degenerate panel: if `modelRoles['review-panel']` is empty or has one entry, spawn a single reviewer and require `PANEL_MEMBER: solo` in its verdict.
60
+
61
+ Each spawned reviewer agent performs 2a–2d below per task:
60
62
 
61
63
  ### 2a — Model isolation check (always first)
62
64
 
@@ -98,6 +100,7 @@ matches the task file's wording.
98
100
  VERDICT: approved | approved_minor | changes_requested | critical_block
99
101
  REVIEWER_MODEL: <your exact model ID>
100
102
  EXECUTOR_MODEL: <from Executor Report>
103
+ PANEL_MEMBER: <panel tier | solo | ->
101
104
  VERIFICATION_RERUN: PASS | FAIL
102
105
  FINDINGS:
103
106
  critical: <file:line — what fails> | none
@@ -116,7 +119,29 @@ BLOCKING: <one line per critical/important finding, or "none">
116
119
  ```
117
120
  Do not paste the diff, the findings prose, or verification logs back into the orchestrator.
118
121
 
119
- ### 2e — Orchestrator updates INDEX.md
122
+ ### 2e — Aggregate the panel + lead bucketing
123
+
124
+ Once every panel member for a task has appended its `## Reviewer Verdict`, run:
125
+
126
+ ```bash
127
+ node .claude/ukit/index/review-panel-aggregate.mjs docs/AI_HANDOFF/tasks/TASK-xxx.md
128
+ ```
129
+
130
+ The script emits an Agreement Map (finding → set of panel members reporting it) and a
131
+ consensus verdict (`approved` when ≥2 members approve and no critical;
132
+ `changes_requested` when ≥1 critical or ≥2 request changes; else `approved_minor`).
133
+ `consensus≥2 identical findings = high signal` — a finding reported by two or more
134
+ members is high-signal. The consensus verdict, not any single member's vote, drives
135
+ `NEXT_STATUS_FOR_INDEX`.
136
+
137
+ Then the **lead member** (first entry in `modelRoles['review-panel']` = the judgment
138
+ tier) applies the lead-judgment buckets to every finding — **Act on** / **Consider** /
139
+ **Noted** / **Dismissed** — and appends a `## Panel Consensus` block to the task file
140
+ carrying the Agreement Map and the bucketed findings. `Act on` findings feed Step 3's
141
+ auto-fix loop; `Consider`/`Noted`/`Dismissed` are advisory. A high-signal finding must
142
+ not be bucketed below `Consider` without a stated reason.
143
+
144
+ ### 2f — Orchestrator updates INDEX.md
120
145
 
121
146
  Set `status = NEXT_STATUS_FOR_INDEX`. Orchestrator writes INDEX, not the reviewer.
122
147
 
@@ -144,7 +169,7 @@ For round in 1..2:
144
169
  ```bash
145
170
  git add -A && git commit -m "handoff: fix round <N> — TASK-00x"
146
171
  ```
147
- 4. Re-review **only the tasks touched this round**, in parallel, per 2a–2e. The reviewer must
172
+ 4. Re-review **only the tasks touched this round**, in parallel, per 2a–2f — panel spawn, aggregation, and lead bucketing included. The reviewers must
148
173
  still differ from the executor model and still re-runs verification itself.
149
174
  5. Update `INDEX.md` and `RUN.md`. Exit when everything is approved.
150
175
 
@@ -190,5 +215,5 @@ Then, as the last line:
190
215
  This is the only place this command may ask for a compaction. All state lives in git,
191
216
  `INDEX.md` and `RUN.md`, so a compacted or fresh session resumes with nothing lost.
192
217
 
193
- > Orchestrator (this session) handles Step 1, 2e, and 3 directly — those are not delegated.
194
- > **For the human operator, on a tool with no agent support (Codex) — not an instruction to the model:** manually switch to the strong model, run 2a–2d per task (one session at a time).
218
+ > Orchestrator (this session) handles Step 1, 2e, 2f, and 3 directly — those are not delegated.
219
+ > **For the human operator, on a tool with no agent support (Codex) — not an instruction to the model:** manually switch to the strong model, run 2a–2d per task (one session at a time, panel members sequentially), then run `review-panel-aggregate.mjs` and apply the lead buckets yourself.