@azure-id/orc 0.55.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (449) hide show
  1. package/CHANGELOG.md +2017 -0
  2. package/README-id.md +521 -0
  3. package/README.md +485 -0
  4. package/bin/build-agents.js +86 -0
  5. package/bin/cli.js +29050 -0
  6. package/bin/mockrun-catalog.js +267 -0
  7. package/bin/onboarding-content.js +172 -0
  8. package/bin/pricing.json +200 -0
  9. package/bin/providers.json +437 -0
  10. package/bin/ui.js +95 -0
  11. package/bin/verify-contracts.js +3277 -0
  12. package/bin/verify-package.js +498 -0
  13. package/bin/webui/api.js +1163 -0
  14. package/bin/webui/app.html +198 -0
  15. package/bin/webui/css/00-tokens.css +92 -0
  16. package/bin/webui/css/01-base.css +42 -0
  17. package/bin/webui/css/02-shell.css +103 -0
  18. package/bin/webui/css/03-components.css +462 -0
  19. package/bin/webui/css/04-motion.css +91 -0
  20. package/bin/webui/css/05-tour.css +100 -0
  21. package/bin/webui/css/06-responsive.css +108 -0
  22. package/bin/webui/css/panels/boundary.css +26 -0
  23. package/bin/webui/css/panels/challenge.css +151 -0
  24. package/bin/webui/css/panels/crosslink.css +194 -0
  25. package/bin/webui/css/panels/docs.css +254 -0
  26. package/bin/webui/css/panels/experiment.css +23 -0
  27. package/bin/webui/css/panels/extra.css +536 -0
  28. package/bin/webui/css/panels/flow.css +177 -0
  29. package/bin/webui/css/panels/handoff.css +67 -0
  30. package/bin/webui/css/panels/knowledge.css +86 -0
  31. package/bin/webui/css/panels/learn.css +154 -0
  32. package/bin/webui/css/panels/maintenance.css +55 -0
  33. package/bin/webui/css/panels/mockrun.css +268 -0
  34. package/bin/webui/css/panels/overview.css +100 -0
  35. package/bin/webui/css/panels/pact.css +43 -0
  36. package/bin/webui/css/panels/runs.css +105 -0
  37. package/bin/webui/css/panels/settings.css +227 -0
  38. package/bin/webui/css/panels/stats.css +87 -0
  39. package/bin/webui/fixtures/boundary.js +92 -0
  40. package/bin/webui/fixtures/challenge.js +825 -0
  41. package/bin/webui/fixtures/crosslink.js +31 -0
  42. package/bin/webui/fixtures/docs.js +982 -0
  43. package/bin/webui/fixtures/extra.js +1934 -0
  44. package/bin/webui/fixtures/flow.js +81 -0
  45. package/bin/webui/fixtures/handoff.js +35 -0
  46. package/bin/webui/fixtures/index.js +486 -0
  47. package/bin/webui/fixtures/knowledge.js +291 -0
  48. package/bin/webui/fixtures/maintenance.js +42 -0
  49. package/bin/webui/fixtures/mockrun.js +36 -0
  50. package/bin/webui/fixtures/pact.js +111 -0
  51. package/bin/webui/fixtures/runs.js +109 -0
  52. package/bin/webui/fixtures/settings.js +78 -0
  53. package/bin/webui/fixtures/shell.js +48 -0
  54. package/bin/webui/fixtures/stats.js +104 -0
  55. package/bin/webui/i18n/TERMS.md +134 -0
  56. package/bin/webui/i18n/en/banner.json +29 -0
  57. package/bin/webui/i18n/en/boundary.json +20 -0
  58. package/bin/webui/i18n/en/challenge.json +106 -0
  59. package/bin/webui/i18n/en/common.json +69 -0
  60. package/bin/webui/i18n/en/crosslink.json +69 -0
  61. package/bin/webui/i18n/en/docs.json +175 -0
  62. package/bin/webui/i18n/en/experiment.json +17 -0
  63. package/bin/webui/i18n/en/extra.json +313 -0
  64. package/bin/webui/i18n/en/flow.json +30 -0
  65. package/bin/webui/i18n/en/handoff.json +37 -0
  66. package/bin/webui/i18n/en/knowledge.json +141 -0
  67. package/bin/webui/i18n/en/learn.json +16 -0
  68. package/bin/webui/i18n/en/maintenance.json +52 -0
  69. package/bin/webui/i18n/en/mockrun.json +19 -0
  70. package/bin/webui/i18n/en/nav.json +19 -0
  71. package/bin/webui/i18n/en/overview.json +89 -0
  72. package/bin/webui/i18n/en/pact.json +36 -0
  73. package/bin/webui/i18n/en/runs.json +51 -0
  74. package/bin/webui/i18n/en/settings.json +49 -0
  75. package/bin/webui/i18n/en/stats.json +69 -0
  76. package/bin/webui/i18n/en/tour.json +33 -0
  77. package/bin/webui/i18n/id/banner.json +29 -0
  78. package/bin/webui/i18n/id/boundary.json +20 -0
  79. package/bin/webui/i18n/id/challenge.json +106 -0
  80. package/bin/webui/i18n/id/common.json +70 -0
  81. package/bin/webui/i18n/id/crosslink.json +69 -0
  82. package/bin/webui/i18n/id/docs.json +175 -0
  83. package/bin/webui/i18n/id/experiment.json +17 -0
  84. package/bin/webui/i18n/id/extra.json +313 -0
  85. package/bin/webui/i18n/id/flow.json +30 -0
  86. package/bin/webui/i18n/id/handoff.json +37 -0
  87. package/bin/webui/i18n/id/knowledge.json +141 -0
  88. package/bin/webui/i18n/id/learn.json +16 -0
  89. package/bin/webui/i18n/id/maintenance.json +52 -0
  90. package/bin/webui/i18n/id/mockrun.json +19 -0
  91. package/bin/webui/i18n/id/nav.json +19 -0
  92. package/bin/webui/i18n/id/overview.json +89 -0
  93. package/bin/webui/i18n/id/pact.json +36 -0
  94. package/bin/webui/i18n/id/runs.json +51 -0
  95. package/bin/webui/i18n/id/settings.json +49 -0
  96. package/bin/webui/i18n/id/stats.json +69 -0
  97. package/bin/webui/i18n/id/tour.json +33 -0
  98. package/bin/webui/js/00-core.js +115 -0
  99. package/bin/webui/js/01-i18n.js +149 -0
  100. package/bin/webui/js/02-ui.js +211 -0
  101. package/bin/webui/js/03-md.js +286 -0
  102. package/bin/webui/js/04-router.js +51 -0
  103. package/bin/webui/js/05-banners.js +172 -0
  104. package/bin/webui/js/06-edit.js +183 -0
  105. package/bin/webui/js/90-tour.js +488 -0
  106. package/bin/webui/js/91-shortcuts.js +126 -0
  107. package/bin/webui/js/99-boot.js +118 -0
  108. package/bin/webui/js/panels/boundary.js +104 -0
  109. package/bin/webui/js/panels/challenge.js +781 -0
  110. package/bin/webui/js/panels/crosslink.js +654 -0
  111. package/bin/webui/js/panels/docs.js +1338 -0
  112. package/bin/webui/js/panels/experiment.js +98 -0
  113. package/bin/webui/js/panels/extra.js +3011 -0
  114. package/bin/webui/js/panels/flow.js +297 -0
  115. package/bin/webui/js/panels/handoff.js +169 -0
  116. package/bin/webui/js/panels/knowledge.js +890 -0
  117. package/bin/webui/js/panels/learn.js +220 -0
  118. package/bin/webui/js/panels/maintenance.js +235 -0
  119. package/bin/webui/js/panels/mockrun.js +227 -0
  120. package/bin/webui/js/panels/overview.js +447 -0
  121. package/bin/webui/js/panels/pact.js +189 -0
  122. package/bin/webui/js/panels/runs.js +416 -0
  123. package/bin/webui/js/panels/settings.js +573 -0
  124. package/bin/webui/js/panels/stats.js +378 -0
  125. package/bin/webui/serve.js +557 -0
  126. package/mock-run/INDEX.md +106 -0
  127. package/mock-run/a-normal-day.md +587 -0
  128. package/mock-run/context-combiner.md +100 -0
  129. package/mock-run/extra-recovery.md +330 -0
  130. package/mock-run/extra-slots.md +177 -0
  131. package/mock-run/media/README.md +43 -0
  132. package/mock-run/orc-aftermath.md +392 -0
  133. package/mock-run/orc-boundary.md +356 -0
  134. package/mock-run/orc-brainstorm.md +177 -0
  135. package/mock-run/orc-budget.md +534 -0
  136. package/mock-run/orc-challenge-council.md +262 -0
  137. package/mock-run/orc-challenge.md +416 -0
  138. package/mock-run/orc-cli.md +200 -0
  139. package/mock-run/orc-diy.md +129 -0
  140. package/mock-run/orc-doc.md +448 -0
  141. package/mock-run/orc-explain.md +86 -0
  142. package/mock-run/orc-export.md +423 -0
  143. package/mock-run/orc-extra.md +392 -0
  144. package/mock-run/orc-fast.md +106 -0
  145. package/mock-run/orc-grill.md +151 -0
  146. package/mock-run/orc-handoff.md +480 -0
  147. package/mock-run/orc-pact.md +421 -0
  148. package/mock-run/orc-pattern.md +112 -0
  149. package/mock-run/orc-plan.md +108 -0
  150. package/mock-run/orc-pr-setup.md +126 -0
  151. package/mock-run/orc-quick.md +113 -0
  152. package/mock-run/orc-route.md +93 -0
  153. package/mock-run/orc-ui.md +125 -0
  154. package/mock-run/orc-ultra.md +103 -0
  155. package/mock-run/orc.md +157 -0
  156. package/mock-run/the-example-project.md +55 -0
  157. package/package.json +39 -0
  158. package/templates/agents/MODEL-MAPPING.md +168 -0
  159. package/templates/agents/orc-advisor-fable-5.md +50 -0
  160. package/templates/agents/orc-advisor-opus-5-xhigh.md +56 -0
  161. package/templates/agents/orc-analyst-fable-5.md +115 -0
  162. package/templates/agents/orc-analyze-mini-opus-5-med.md +60 -0
  163. package/templates/agents/orc-analyze-mini-sonnet-5-high.md +58 -0
  164. package/templates/agents/orc-challenge-advisor-opus-5-med.md +75 -0
  165. package/templates/agents/orc-challenge-contrarian-opus-5-high.md +110 -0
  166. package/templates/agents/orc-challenge-executor-opus-5-med.md +114 -0
  167. package/templates/agents/orc-challenge-expansionist-opus-5-med.md +112 -0
  168. package/templates/agents/orc-challenge-judge-opus-5-high.md +132 -0
  169. package/templates/agents/orc-challenge-outsider-opus-5-low.md +109 -0
  170. package/templates/agents/orc-challenge-principles-opus-5-high.md +109 -0
  171. package/templates/agents/orc-challenge-reader-opus-5-low.md +90 -0
  172. package/templates/agents/orc-claude-writer-opus-4-8-high.md +53 -0
  173. package/templates/agents/orc-claude-writer-opus-5-med.md +55 -0
  174. package/templates/agents/orc-context-combiner-opus-5-high.md +88 -0
  175. package/templates/agents/orc-doc-checker-opus-5-low.md +108 -0
  176. package/templates/agents/orc-doc-writer-opus-5-med.md +134 -0
  177. package/templates/agents/orc-executor-haiku-4-5.md +113 -0
  178. package/templates/agents/orc-executor-opus-4-7-high.md +114 -0
  179. package/templates/agents/orc-executor-opus-4-7-med.md +114 -0
  180. package/templates/agents/orc-executor-opus-4-8-high.md +114 -0
  181. package/templates/agents/orc-executor-opus-5-high.md +114 -0
  182. package/templates/agents/orc-executor-opus-5-low.md +114 -0
  183. package/templates/agents/orc-executor-opus-5-med.md +114 -0
  184. package/templates/agents/orc-executor-sonnet-4-6-high.md +114 -0
  185. package/templates/agents/orc-executor-sonnet-4-6-med.md +114 -0
  186. package/templates/agents/orc-executor-sonnet-5-high.md +114 -0
  187. package/templates/agents/orc-judge-fable-5.md +79 -0
  188. package/templates/agents/orc-judge-opus-5-xhigh.md +85 -0
  189. package/templates/agents/orc-learn-writer-opus-5-low.md +73 -0
  190. package/templates/agents/orc-pattern-codifier-opus-5-med.md +65 -0
  191. package/templates/agents/orc-pattern-codifier-sonnet-5-high.md +63 -0
  192. package/templates/agents/orc-planner-fable-5.md +152 -0
  193. package/templates/agents/orc-planner-mini-opus-5-med.md +69 -0
  194. package/templates/agents/orc-planner-mini-sonnet-5-high.md +67 -0
  195. package/templates/agents/orc-planner-opus-5-med.md +160 -0
  196. package/templates/agents/orc-retro-opus-5-med.md +73 -0
  197. package/templates/agents/orc-retro-sonnet-5-high.md +72 -0
  198. package/templates/agents/orc-reviewer-fable-5.md +57 -0
  199. package/templates/agents/orc-reviewer-opus-5-med.md +60 -0
  200. package/templates/agents/orc-scout-opus-5-low.md +40 -0
  201. package/templates/agents/orc-scout-sonnet-4-6-high.md +39 -0
  202. package/templates/agents/orc-system-analyst-opus-5-high.md +120 -0
  203. package/templates/agents/orc-test-author-opus-5-med.md +71 -0
  204. package/templates/agents/orc-trace-writer-haiku-4-5.md +107 -0
  205. package/templates/agents/orc-verifier-opus-5-med.md +69 -0
  206. package/templates/agents/orc-wiki-scanner-opus-4-8-high.md +79 -0
  207. package/templates/agents/orc-wiki-scanner-opus-5-med.md +81 -0
  208. package/templates/agents/orc-wiki-scanner-sonnet-5-high.md +106 -0
  209. package/templates/commands/orc-aftermath.md +49 -0
  210. package/templates/commands/orc-analyze.md +21 -0
  211. package/templates/commands/orc-boundary.md +46 -0
  212. package/templates/commands/orc-brainstorm.md +51 -0
  213. package/templates/commands/orc-budget.md +54 -0
  214. package/templates/commands/orc-challenge.md +58 -0
  215. package/templates/commands/orc-claude.md +14 -0
  216. package/templates/commands/orc-diy.md +13 -0
  217. package/templates/commands/orc-doc.md +128 -0
  218. package/templates/commands/orc-explain.md +20 -0
  219. package/templates/commands/orc-export.md +46 -0
  220. package/templates/commands/orc-fast.md +15 -0
  221. package/templates/commands/orc-grill.md +40 -0
  222. package/templates/commands/orc-handoff.md +52 -0
  223. package/templates/commands/orc-learn.md +17 -0
  224. package/templates/commands/orc-mini.md +12 -0
  225. package/templates/commands/orc-pact.md +44 -0
  226. package/templates/commands/orc-pattern.md +15 -0
  227. package/templates/commands/orc-plan.md +22 -0
  228. package/templates/commands/orc-poly.md +21 -0
  229. package/templates/commands/orc-pr-driver.md +30 -0
  230. package/templates/commands/orc-pr-setup.md +31 -0
  231. package/templates/commands/orc-quick.md +33 -0
  232. package/templates/commands/orc-retro.md +17 -0
  233. package/templates/commands/orc-route.md +41 -0
  234. package/templates/commands/orc-ultra.md +17 -0
  235. package/templates/commands/orc-verify.md +11 -0
  236. package/templates/commands/orc-wiki.md +42 -0
  237. package/templates/commands/orc.md +16 -0
  238. package/templates/hooks/orc-effort-guard.js +178 -0
  239. package/templates/hooks/orc-statusline.js +305 -0
  240. package/templates/hooks/orc-trace.js +471 -0
  241. package/templates/hooks/orc-update-lib.js +125 -0
  242. package/templates/skills/_shared/README.md +50 -0
  243. package/templates/skills/_shared/detecting-artifacts.md +90 -0
  244. package/templates/skills/_shared/drift-recovery.md +98 -0
  245. package/templates/skills/_shared/extra-dispatch.md +1051 -0
  246. package/templates/skills/_shared/fable5-override.md +56 -0
  247. package/templates/skills/_shared/fallback-handoff.md +42 -0
  248. package/templates/skills/_shared/gh-stack-commands.md +65 -0
  249. package/templates/skills/_shared/gotchas.md +177 -0
  250. package/templates/skills/_shared/interview.md +144 -0
  251. package/templates/skills/_shared/lane-suspend.md +82 -0
  252. package/templates/skills/_shared/opus5-only.md +131 -0
  253. package/templates/skills/_shared/pr-templates.md +106 -0
  254. package/templates/skills/_shared/read-ladder.md +54 -0
  255. package/templates/skills/_shared/return-validation.md +145 -0
  256. package/templates/skills/_shared/smoke-gate.md +28 -0
  257. package/templates/skills/_shared/stack-plan.md +135 -0
  258. package/templates/skills/_shared/untrusted-input.md +63 -0
  259. package/templates/skills/context-combiner/SKILL.md +187 -0
  260. package/templates/skills/context-combiner/schemas/combined-report.md +78 -0
  261. package/templates/skills/context-combiner/schemas/combined-requirement-spec.md +87 -0
  262. package/templates/skills/orc/README.md +150 -0
  263. package/templates/skills/orc/SKILL.md +526 -0
  264. package/templates/skills/orc/config.md +389 -0
  265. package/templates/skills/orc/examples/full-run-mock.md +73 -0
  266. package/templates/skills/orc/references/analyst-gates.md +124 -0
  267. package/templates/skills/orc/references/effort-and-mode.md +224 -0
  268. package/templates/skills/orc/references/house-rules.md +20 -0
  269. package/templates/skills/orc/references/intake.md +120 -0
  270. package/templates/skills/orc/references/log-protocol.md +39 -0
  271. package/templates/skills/orc/references/pattern-gate.md +89 -0
  272. package/templates/skills/orc/references/plan-handoff.md +84 -0
  273. package/templates/skills/orc/references/preflight-report.md +220 -0
  274. package/templates/skills/orc/references/security-checklist.md +39 -0
  275. package/templates/skills/orc/references/stop-and-resume.md +160 -0
  276. package/templates/skills/orc/references/trace-protocol.md +314 -0
  277. package/templates/skills/orc/references/ultra-mode.md +123 -0
  278. package/templates/skills/orc/references/wave-grouping.md +121 -0
  279. package/templates/skills/orc/references/wiki-consult.md +177 -0
  280. package/templates/skills/orc/schemas/checkpoint.md +122 -0
  281. package/templates/skills/orc/schemas/intent-spec.md +42 -0
  282. package/templates/skills/orc/schemas/planning-output.md +279 -0
  283. package/templates/skills/orc/subskills/orc-checkpoint/SKILL.md +55 -0
  284. package/templates/skills/orc/subskills/orc-execution/SKILL.md +72 -0
  285. package/templates/skills/orc/subskills/orc-execution/core.md +151 -0
  286. package/templates/skills/orc/subskills/orc-execution/subagent.md +13 -0
  287. package/templates/skills/orc/subskills/orc-planner/SKILL.md +264 -0
  288. package/templates/skills/orc/subskills/orc-planner-mini/SKILL.md +121 -0
  289. package/templates/skills/orc/subskills/orc-pr/SKILL.md +51 -0
  290. package/templates/skills/orc/subskills/orc-pr/pr.md +22 -0
  291. package/templates/skills/orc/subskills/orc-pr/stack-gate.md +108 -0
  292. package/templates/skills/orc/subskills/orc-review-verify/SKILL.md +76 -0
  293. package/templates/skills/orc/subskills/orc-review-verify/core.md +135 -0
  294. package/templates/skills/orc/subskills/orc-review-verify/subagent.md +7 -0
  295. package/templates/skills/orc/subskills/orc-testgen/SKILL.md +45 -0
  296. package/templates/skills/orc/subskills/orc-testgen/core.md +59 -0
  297. package/templates/skills/orc/subskills/orc-testgen/subagent.md +7 -0
  298. package/templates/skills/orc-advisor/SKILL.md +60 -0
  299. package/templates/skills/orc-aftermath/SKILL.md +136 -0
  300. package/templates/skills/orc-aftermath/references/report.md +95 -0
  301. package/templates/skills/orc-analyze/SKILL.md +220 -0
  302. package/templates/skills/orc-analyze/examples/analyze-mock.md +42 -0
  303. package/templates/skills/orc-analyze/references/branching.md +51 -0
  304. package/templates/skills/orc-analyze/references/deep-mode.md +27 -0
  305. package/templates/skills/orc-analyze/references/thin-input.md +77 -0
  306. package/templates/skills/orc-analyze/schemas/report-audit.md +83 -0
  307. package/templates/skills/orc-analyze/schemas/report-prose.md +63 -0
  308. package/templates/skills/orc-analyze/schemas/report-requirement.md +78 -0
  309. package/templates/skills/orc-analyze/schemas/requirement-spec.md +77 -0
  310. package/templates/skills/orc-analyze-mini/SKILL.md +112 -0
  311. package/templates/skills/orc-analyze-mini/examples/quick-analysis-mock.md +31 -0
  312. package/templates/skills/orc-boundary/SKILL.md +208 -0
  313. package/templates/skills/orc-boundary/references/card.md +78 -0
  314. package/templates/skills/orc-boundary/references/gate.md +113 -0
  315. package/templates/skills/orc-brainstorm/SKILL.md +339 -0
  316. package/templates/skills/orc-brainstorm/references/brainstorm-doc.md +133 -0
  317. package/templates/skills/orc-brainstorm/references/lenses.md +152 -0
  318. package/templates/skills/orc-budget/SKILL.md +225 -0
  319. package/templates/skills/orc-budget/references/corpus.md +87 -0
  320. package/templates/skills/orc-challenge/README.md +142 -0
  321. package/templates/skills/orc-challenge/SKILL.md +255 -0
  322. package/templates/skills/orc-challenge/examples/code-module.md +110 -0
  323. package/templates/skills/orc-challenge/examples/council-full-roster.md +273 -0
  324. package/templates/skills/orc-challenge/examples/tsd-two-iterations.md +213 -0
  325. package/templates/skills/orc-challenge/references/conservation.md +107 -0
  326. package/templates/skills/orc-challenge/references/council.md +315 -0
  327. package/templates/skills/orc-challenge/references/cycle-state.md +185 -0
  328. package/templates/skills/orc-challenge/references/dimensions.md +121 -0
  329. package/templates/skills/orc-challenge/references/fix-brief.md +130 -0
  330. package/templates/skills/orc-challenge/references/intake.md +171 -0
  331. package/templates/skills/orc-challenge/references/kinds.md +44 -0
  332. package/templates/skills/orc-challenge/references/plain-english.md +98 -0
  333. package/templates/skills/orc-challenge/references/rubric.md +109 -0
  334. package/templates/skills/orc-challenge/references/sealed-slice.md +97 -0
  335. package/templates/skills/orc-challenge/references/verdict-doc.md +154 -0
  336. package/templates/skills/orc-claude/SKILL.md +199 -0
  337. package/templates/skills/orc-claude/examples/claude-run-mock.md +65 -0
  338. package/templates/skills/orc-claude/references/refresh.md +76 -0
  339. package/templates/skills/orc-claude/references/template.md +109 -0
  340. package/templates/skills/orc-diy/README.md +142 -0
  341. package/templates/skills/orc-diy/SKILL.md +70 -0
  342. package/templates/skills/orc-diy/references/blocks/analyze.md +24 -0
  343. package/templates/skills/orc-diy/references/blocks/execution.md +42 -0
  344. package/templates/skills/orc-diy/references/blocks/extra.md +55 -0
  345. package/templates/skills/orc-diy/references/blocks/header.md +55 -0
  346. package/templates/skills/orc-diy/references/blocks/mock-example.md +22 -0
  347. package/templates/skills/orc-diy/references/blocks/pattern.md +18 -0
  348. package/templates/skills/orc-diy/references/blocks/planning.md +34 -0
  349. package/templates/skills/orc-diy/references/blocks/review.md +18 -0
  350. package/templates/skills/orc-diy/references/blocks/scoring.md +16 -0
  351. package/templates/skills/orc-diy/references/blocks/security.md +25 -0
  352. package/templates/skills/orc-diy/references/blocks/ship.md +25 -0
  353. package/templates/skills/orc-diy/references/blocks/summary.md +18 -0
  354. package/templates/skills/orc-diy/references/blocks/testgen.md +17 -0
  355. package/templates/skills/orc-diy/references/blocks/trace.md +28 -0
  356. package/templates/skills/orc-diy/references/blocks/verify.md +25 -0
  357. package/templates/skills/orc-diy/references/blocks/wiki.md +26 -0
  358. package/templates/skills/orc-diy/references/compile.md +59 -0
  359. package/templates/skills/orc-diy/references/flow-schema.md +100 -0
  360. package/templates/skills/orc-diy/references/locked-blocks.md +37 -0
  361. package/templates/skills/orc-doc/README.md +229 -0
  362. package/templates/skills/orc-doc/SKILL.md +444 -0
  363. package/templates/skills/orc-doc/examples/orc-doc-prd-run.md +325 -0
  364. package/templates/skills/orc-doc/references/chunking.md +527 -0
  365. package/templates/skills/orc-doc/references/gates.md +311 -0
  366. package/templates/skills/orc-doc/references/generation-rules.md +122 -0
  367. package/templates/skills/orc-doc/references/house-rules.md +170 -0
  368. package/templates/skills/orc-doc/references/import-targets.md +40 -0
  369. package/templates/skills/orc-doc/references/plain-language.md +66 -0
  370. package/templates/skills/orc-doc/references/portable-markdown.md +74 -0
  371. package/templates/skills/orc-doc/references/resume-protocol.md +228 -0
  372. package/templates/skills/orc-doc/references/templates/collaboration.md +118 -0
  373. package/templates/skills/orc-doc/references/templates/prd.md +133 -0
  374. package/templates/skills/orc-doc/references/templates/report.md +102 -0
  375. package/templates/skills/orc-doc/references/templates/tsd.md +122 -0
  376. package/templates/skills/orc-doc/references/templates/workflow.md +112 -0
  377. package/templates/skills/orc-explain/SKILL.md +57 -0
  378. package/templates/skills/orc-export/SKILL.md +154 -0
  379. package/templates/skills/orc-fast/SKILL.md +188 -0
  380. package/templates/skills/orc-grill/SKILL.md +207 -0
  381. package/templates/skills/orc-grill/references/grill-doc.md +105 -0
  382. package/templates/skills/orc-handoff/SKILL.md +204 -0
  383. package/templates/skills/orc-handoff/references/handoff-log.md +67 -0
  384. package/templates/skills/orc-handoff/references/surfaces.md +88 -0
  385. package/templates/skills/orc-judge/SKILL.md +82 -0
  386. package/templates/skills/orc-learn/SKILL.md +156 -0
  387. package/templates/skills/orc-learn/examples/learn-run-mock.md +61 -0
  388. package/templates/skills/orc-learn/references/deepen.md +70 -0
  389. package/templates/skills/orc-learn/references/refresh.md +65 -0
  390. package/templates/skills/orc-learn/references/template-knowledge.md +83 -0
  391. package/templates/skills/orc-learn/references/template-learning.md +67 -0
  392. package/templates/skills/orc-mini/SKILL.md +226 -0
  393. package/templates/skills/orc-mini/examples/mini-run-mock.md +50 -0
  394. package/templates/skills/orc-pact/SKILL.md +218 -0
  395. package/templates/skills/orc-pact/references/gate.md +70 -0
  396. package/templates/skills/orc-pact/references/ledger.md +99 -0
  397. package/templates/skills/orc-pattern/SKILL.md +124 -0
  398. package/templates/skills/orc-pattern/references/INDEX.md +73 -0
  399. package/templates/skills/orc-pattern/references/be-django.md +80 -0
  400. package/templates/skills/orc-pattern/references/be-express.md +82 -0
  401. package/templates/skills/orc-pattern/references/be-fastapi.md +107 -0
  402. package/templates/skills/orc-pattern/references/be-go.md +96 -0
  403. package/templates/skills/orc-pattern/references/be-nestjs.md +86 -0
  404. package/templates/skills/orc-pattern/references/be-postgres.md +98 -0
  405. package/templates/skills/orc-pattern/references/fe-a11y.md +36 -0
  406. package/templates/skills/orc-pattern/references/fe-angular.md +87 -0
  407. package/templates/skills/orc-pattern/references/fe-nextjs.md +65 -0
  408. package/templates/skills/orc-pattern/references/fe-perf.md +39 -0
  409. package/templates/skills/orc-pattern/references/fe-react.md +83 -0
  410. package/templates/skills/orc-pattern/references/fe-vue.md +75 -0
  411. package/templates/skills/orc-pattern/schemas/pattern-doc.md +62 -0
  412. package/templates/skills/orc-poly/SKILL.md +216 -0
  413. package/templates/skills/orc-poly/examples/poly-run-mock.md +51 -0
  414. package/templates/skills/orc-poly/references/gather.md +70 -0
  415. package/templates/skills/orc-poly/references/poly-spec.md +84 -0
  416. package/templates/skills/orc-pr-driver/README.md +349 -0
  417. package/templates/skills/orc-pr-driver/SKILL.md +167 -0
  418. package/templates/skills/orc-pr-driver/references/conflict-playbook.md +78 -0
  419. package/templates/skills/orc-pr-driver/references/green-gate.md +105 -0
  420. package/templates/skills/orc-pr-driver/references/orc-run-split.md +99 -0
  421. package/templates/skills/orc-pr-setup/README.md +436 -0
  422. package/templates/skills/orc-pr-setup/SKILL.md +184 -0
  423. package/templates/skills/orc-pr-setup/references/certainty-gate.md +66 -0
  424. package/templates/skills/orc-pr-setup/references/layer-taxonomy.md +67 -0
  425. package/templates/skills/orc-quick/README.md +423 -0
  426. package/templates/skills/orc-quick/SKILL.md +306 -0
  427. package/templates/skills/orc-quick/references/context-doc.md +114 -0
  428. package/templates/skills/orc-quick/references/dispatch-gate.md +163 -0
  429. package/templates/skills/orc-quick/references/gh-mode.md +127 -0
  430. package/templates/skills/orc-retro/SKILL.md +222 -0
  431. package/templates/skills/orc-retro/examples/retro-mock.md +171 -0
  432. package/templates/skills/orc-route/SKILL.md +165 -0
  433. package/templates/skills/orc-verify/SKILL.md +86 -0
  434. package/templates/skills/orc-verify/examples/verify-mock.md +33 -0
  435. package/templates/skills/orc-wiki/README.md +325 -0
  436. package/templates/skills/orc-wiki/SKILL.md +322 -0
  437. package/templates/skills/orc-wiki/examples/wiki-run-mock.md +37 -0
  438. package/templates/skills/orc-wiki/references/claude-md-injection.md +61 -0
  439. package/templates/skills/orc-wiki/references/crosslink-compile.md +39 -0
  440. package/templates/skills/orc-wiki/references/crosslink-kinds.md +57 -0
  441. package/templates/skills/orc-wiki/references/crosslink.md +284 -0
  442. package/templates/skills/orc-wiki/references/extra.md +79 -0
  443. package/templates/skills/orc-wiki/references/integrity-check.md +86 -0
  444. package/templates/skills/orc-wiki/references/orientation.md +51 -0
  445. package/templates/skills/orc-wiki/references/partial-refresh.md +203 -0
  446. package/templates/skills/orc-wiki/references/pattern-prewarm.md +19 -0
  447. package/templates/skills/orc-wiki/references/staleness.md +288 -0
  448. package/templates/skills/orc-wiki/schemas/crosslink-tag.md +166 -0
  449. package/templates/skills/orc-wiki/schemas/wiki-doc.md +120 -0
@@ -0,0 +1,781 @@
1
+ "use strict";
2
+ /* panels/challenge.js — orc ui client
3
+ The iteration timeline, the convergence chart, the findings.
4
+
5
+ Loaded by app.html in the order its numeric prefix names. Classic
6
+ script, no import/export: an ES module import carries no query string,
7
+ and every static request here needs the per-launch session token. */
8
+
9
+
10
+ PANELS.challenge = function (host) {
11
+ head(host, t("challenge.title"), t("challenge.sub"));
12
+ const body = el("div", "stack");
13
+ host.append(body);
14
+ renderChallenge(body);
15
+ };
16
+
17
+ async function renderChallenge(body) {
18
+ body.replaceChildren(skeleton(5));
19
+ let d;
20
+ try {
21
+ d = (await read("/api/challenge")).data;
22
+ } catch (e) {
23
+ body.replaceChildren(failBox(e));
24
+ return;
25
+ }
26
+ const out = frag();
27
+
28
+ if (!d || !d.cycles || !d.cycles.length) {
29
+ const c = card(t("challenge.title"));
30
+ c.append(empty(t("challenge.none"), t("challenge.noneHint")));
31
+ c.append(laneCommand("/orc-challenge", t("challenge.cmdWhy")));
32
+ out.append(c);
33
+ body.replaceChildren(out);
34
+ return;
35
+ }
36
+
37
+ const sum = card(t("challenge.summary"));
38
+ const chips = el("div", "row-actions");
39
+ for (const s of Object.keys(CH_STATE_KIND)) {
40
+ const n = d.cycles.filter((c) => c.state === s).length;
41
+ if (!n) continue;
42
+ chips.append(chip(`${n} ${s}`, CH_STATE_KIND[s], s === CH_PULSE));
43
+ }
44
+ sum.append(chips);
45
+ sum.append(el("div", "note", t("challenge.contract")));
46
+ out.append(sum);
47
+
48
+ const list = el("div", "run-list ch-list");
49
+ const rows = [];
50
+ const setOpen = (entry, open) => {
51
+ entry.row.classList.toggle("open", open);
52
+ entry.head.setAttribute("aria-expanded", String(open));
53
+ if (open && !entry.loaded) {
54
+ entry.loaded = true;
55
+ loadChallengeDetail(entry.pane, entry.slug, body);
56
+ }
57
+ };
58
+ const collapseAll = (except) => {
59
+ for (const r of rows) if (r.row !== except) setOpen(r, false);
60
+ };
61
+
62
+ for (const c of d.cycles) {
63
+ const row = el("div", "run-row");
64
+ const headBtn = el("button", "run-card");
65
+ headBtn.type = "button";
66
+ headBtn.setAttribute("aria-expanded", "false");
67
+ headBtn.append(el("span", "run-caret", "▸"));
68
+ // The CLI's own state words. Never a friendlier synonym.
69
+ headBtn.append(chip(c.state, CH_STATE_KIND[c.state] || "", c.state === CH_PULSE));
70
+ if (c.stalled) headBtn.append(chip(t("challenge.stalledChip"), "warn"));
71
+ if (c.no_template) headBtn.append(chip(t("challenge.noTemplateChip"), "warn"));
72
+ const mid = el("div", "run-mid");
73
+ mid.append(el("div", "run-slug", c.slug));
74
+ mid.append(el("div", "run-where", `${c.kind} · ${tn(c.iterations, "challenge.iterN")}`));
75
+ headBtn.append(mid);
76
+ headBtn.append(el("div", "run-age", c.blocking ? tn(c.blocking, "challenge.blockingN") : t("challenge.noBlocking")));
77
+
78
+ const pane = el("div", "run-pane stack stack-sm");
79
+ pane.append(skeleton(4));
80
+ const inner = el("div", "run-body-inner");
81
+ inner.append(pane);
82
+ const fold = el("div", "run-body");
83
+ fold.append(inner);
84
+
85
+ const entry = { row, head: headBtn, pane, slug: c.slug, loaded: false };
86
+ rows.push(entry);
87
+ headBtn.addEventListener("click", () => {
88
+ const isOpen = row.classList.contains("open");
89
+ collapseAll(row);
90
+ setOpen(entry, !isOpen);
91
+ });
92
+ row.append(headBtn, fold);
93
+ list.append(row);
94
+ }
95
+ out.append(list);
96
+ out.append(laneCommand("/orc-challenge", t("challenge.cmdWhy")));
97
+ body.replaceChildren(out);
98
+ }
99
+
100
+ // PROGRESSIVE DISCLOSURE, in the order a human reads: the goal, then the state
101
+ // and the timeline, then the reader's score and the dimension strip, then the
102
+ // findings, then the raw verdict last and collapsed. Nobody should have to
103
+ // scroll past a wall of findings to learn what the document was for.
104
+ async function loadChallengeDetail(pane, slug, body) {
105
+ let s;
106
+ let show = null;
107
+ let diff = null;
108
+ let roles = null;
109
+ try {
110
+ s = (await read("/api/challenge/one?slug=" + encodeURIComponent(slug))).data;
111
+ show = (await read("/api/challenge/show?slug=" + encodeURIComponent(slug)).catch(() => ({ data: null }))).data;
112
+ diff = (await read("/api/challenge/diff?slug=" + encodeURIComponent(slug)).catch(() => ({ data: null }))).data;
113
+ // THE CATALOGUE. The panel names no lens, no class and no disposition
114
+ // itself — it draws what `orc challenge roles --json` returns, exactly as
115
+ // the Flow stepper draws `orc diy show --json`'s steps[].
116
+ roles = (await read("/api/challenge/roles").catch(() => ({ data: null }))).data;
117
+ } catch (e) {
118
+ pane.replaceChildren(failBox(e));
119
+ return;
120
+ }
121
+ const out = frag();
122
+
123
+ // --- 1. the goal block, ABOVE everything. It is the first thing a reader
124
+ // needs in order to read anything below it.
125
+ const g = card(t("challenge.goalTitle") + " v" + s.goals.version);
126
+ g.append(
127
+ kvList([
128
+ [t("challenge.field.goal"), s.goals.goal],
129
+ [t("challenge.field.audience"), s.goals.audience],
130
+ [t("challenge.field.done"), s.goals.done_means],
131
+ [t("challenge.field.outOfScope"), (s.goals.out_of_scope || []).join(" · ")],
132
+ [t("challenge.field.context"), (s.goals.context_refs || []).join(" · ")],
133
+ ])
134
+ );
135
+ g.append(el("div", "note", t("challenge.goalNote")));
136
+ out.append(g);
137
+
138
+ // --- 1b. THE COUNCIL, directly under the goal (v0.49.1). One row per roster
139
+ // lens. A NOT-RUN row KEEPS ITS SLOT and carries its reason, and a
140
+ // NOT-SELECTED row renders muted with the line that would add it —
141
+ // filtering either out makes "the contrarian found nothing" and "the
142
+ // contrarian never ran" look identical.
143
+ out.append(challengeCouncilCard(s, roles, show));
144
+
145
+ // --- 1c. PREMISE CHALLENGES. When one is open this is the LOUDEST card on
146
+ // the panel and it sits above the findings, because a premise disputes the
147
+ // yardstick every finding below it was measured against.
148
+ const premiseCard = challengePremiseCard(s, slug, body);
149
+ if (premiseCard) out.append(premiseCard);
150
+
151
+ // --- 2. the state, and its ONE next action
152
+ const st = card(null);
153
+ const stRow = el("div", "row-actions");
154
+ stRow.append(chip(s.state, CH_STATE_KIND[s.state] || "", s.state === CH_PULSE));
155
+ stRow.append(el("span", "note", s.why));
156
+ st.append(stRow);
157
+ st.append(challengeNextAction(s, diff, body));
158
+ out.append(st);
159
+
160
+ // --- 3. the timeline (the hero) + the convergence chart
161
+ if (s.convergence && s.convergence.length) {
162
+ const tl = card(t("challenge.timeline"));
163
+ tl.append(challengeTimeline(s));
164
+ tl.append(challengeConvergence(s));
165
+ if (s.stalled) tl.append(el("div", "note bad", t("challenge.stalledNote", { n: s.convergence.length })));
166
+ out.append(tl);
167
+ } else {
168
+ const tl = card(t("challenge.timeline"));
169
+ tl.append(empty(t("challenge.noIterations"), t("challenge.noIterationsHint", { slug: s.slug })));
170
+ out.append(tl);
171
+ }
172
+
173
+ // --- 4. the reader's comprehension score — the most legible thing here to a
174
+ // non-engineer, so it sits high.
175
+ const last = show && show.iterations && show.iterations[0];
176
+ if (last && last.reader) {
177
+ const rc = card(t("challenge.readerTitle"));
178
+ const big = el("div", "ch-score");
179
+ big.append(el("span", "ch-score-num", String(last.reader.score || "—")));
180
+ big.append(el("span", "note", t("challenge.readerSub", { asked: last.reader.asked, answered: last.reader.answered })));
181
+ rc.append(big);
182
+ rc.append(el("div", "note", t("challenge.readerNote")));
183
+ out.append(rc);
184
+ }
185
+
186
+ // --- 5. the dimension strip. A NOT-CHECKED chip KEEPS ITS SLOT and carries
187
+ // its reason; a 0-finding dimension keeps its slot too.
188
+ const dc = card(t("challenge.dimensions"));
189
+ const strip = el("div", "row-actions");
190
+ for (const dim of s.dimensions || []) {
191
+ const label =
192
+ dim.status === "CHECKED"
193
+ ? `${dim.id} ${dim.findings}${dim.score ? " · " + dim.score : ""}`
194
+ : `${dim.id} ${dim.status}`;
195
+ const c = chip(label, CH_DIM_KIND[dim.status] || "");
196
+ if (dim.reason) {
197
+ c.title = dim.reason;
198
+ // A reason on hover only is a reason a screen reader never gets.
199
+ c.setAttribute("aria-label", `${dim.id} ${dim.status} — ${dim.reason}`);
200
+ }
201
+ strip.append(c);
202
+ }
203
+ dc.append(strip);
204
+ dc.append(el("div", "note", t("challenge.dimNote")));
205
+ out.append(dc);
206
+
207
+ // --- 6. the findings
208
+ if (last && last.findings && last.findings.length) {
209
+ const fc = card(t("challenge.findings"), challengeReportBtn(slug, body));
210
+ for (const f of last.findings) {
211
+ const box = el("div", "ch-finding");
212
+ const hdr = el("div", "row-actions");
213
+ hdr.append(chip(f.severity, CH_SEV_KIND[f.severity] || ""));
214
+ hdr.append(el("span", "mono dim", f.id));
215
+ hdr.append(chip(f.dimension, ""));
216
+ // The RAISER. An adopted council finding keeps the raiser's id, so this
217
+ // chip is how a user finds out whether a lens is earning its dispatch.
218
+ // The word is the CLI's own lens id — never a friendlier synonym.
219
+ if (f.lens && f.lens !== "judge") hdr.append(chip(f.lens, "info"));
220
+ if ((f.corroborated_by || []).length)
221
+ hdr.append(chip(t("challenge.alsoFoundBy", { lenses: f.corroborated_by.join(", ") }), "info"));
222
+ if (f.outcome) hdr.append(chip(f.outcome, f.outcome === "resolved" ? "ok" : f.outcome === "still-open" ? "warn" : ""));
223
+ if (show.accepted && show.accepted[f.id]) hdr.append(chip(t("challenge.acceptedBadge"), "ok"));
224
+ if (show.rebuttals && show.rebuttals[f.id]) hdr.append(chip(t("challenge.rebuttedBadge"), "info"));
225
+ box.append(hdr);
226
+ box.append(el("div", "ch-anchor mono", f.anchor || "—"));
227
+ if (f.quote) box.append(el("blockquote", "ch-quote", f.quote));
228
+ const rows = [];
229
+ if (f.what_is_wrong) rows.push([t("challenge.field.wrong"), f.what_is_wrong]);
230
+ if (f.consequence) rows.push([t("challenge.field.consequence"), f.consequence]);
231
+ if (f.acceptance_line) rows.push([t("challenge.field.fixedWhen"), f.acceptance_line]);
232
+ if (f.serves) rows.push([t("challenge.field.serves"), f.serves]);
233
+ if (f.lens && f.lens !== "judge")
234
+ rows.push([t("challenge.field.raisedBy"), t("challenge.raisedAdopted", { lens: f.lens })]);
235
+ if (f.disposition) rows.push([t("challenge.field.disposition"), f.disposition]);
236
+ if (f.superseded_by) rows.push([t("challenge.field.supersededBy"), f.superseded_by]);
237
+ if (f.reason) rows.push([t("challenge.field.reason"), f.reason]);
238
+ box.append(kvList(rows));
239
+ if (show.accepted && show.accepted[f.id])
240
+ box.append(el("div", "note ok", t("challenge.acceptedNote", { reason: show.accepted[f.id].reason })));
241
+ if (show.rebuttals && show.rebuttals[f.id])
242
+ box.append(el("div", "note", t("challenge.rebuttedNote", { reason: show.rebuttals[f.id].reason, status: show.rebuttals[f.id].status })));
243
+ // Both escape valves are FREE, so both are buttons — and both refuse
244
+ // without a reason, which the CLI decides, not this form.
245
+ if (!f.outcome || f.outcome === "still-open") {
246
+ const acts = el("div", "row-actions");
247
+ if (!(show.accepted && show.accepted[f.id]))
248
+ acts.append(challengeValveBtn("accept", slug, f.id, body));
249
+ if (!(show.rebuttals && show.rebuttals[f.id]))
250
+ acts.append(challengeValveBtn("rebut", slug, f.id, body));
251
+ box.append(acts);
252
+ }
253
+ fc.append(box);
254
+ }
255
+ if (last.dropped && last.dropped.length)
256
+ fc.append(el("div", "note", t("challenge.dropped", { n: last.dropped.length, ids: last.dropped.map((x) => x.id).join(", ") })));
257
+ out.append(fc);
258
+ }
259
+
260
+ // --- 6b. OPPORTUNITIES. Its own card, visually distinct from findings, and
261
+ // with NO SEVERITY COLOUR anywhere in it: an opportunity never blocks, and
262
+ // colouring it like a defect is exactly the confusion the class split
263
+ // exists to prevent.
264
+ const oppCard = challengeOpportunityCard(s, slug, body);
265
+ if (oppCard) out.append(oppCard);
266
+
267
+ // --- 7. events, collapsed
268
+ if (show && show.events && show.events.length)
269
+ out.append(
270
+ collapsible({
271
+ title: t("challenge.events"),
272
+ count: String(show.events.length),
273
+ collapsed: true,
274
+ content: kvList(show.events.map((e) => [e.at, `${e.kind} — ${e.detail}`])),
275
+ })
276
+ );
277
+
278
+ pane.replaceChildren(out);
279
+ }
280
+
281
+ // EVERY STATE ANSWERS "so what do I do now?" — the one next action, inline.
282
+ function challengeNextAction(s, diff, body) {
283
+ const wrap = el("div", "stack stack-sm");
284
+ if (s.state === "MISSING-REVISION") {
285
+ wrap.append(el("div", "note bad", t("challenge.missingRevision", { path: s.revision.expected })));
286
+ if (diff && diff.candidates && diff.candidates.length) {
287
+ const ul = el("ul", "file-list");
288
+ for (const c of diff.candidates) {
289
+ const li = el("li");
290
+ li.append(el("span", "mono", c.path));
291
+ li.append(el("span", "note", ` +${c.added} −${c.removed}`));
292
+ ul.append(li);
293
+ }
294
+ wrap.append(ul);
295
+ // It LISTS, it does not adopt. So the panel offers the recorded escape as
296
+ // a COMMAND — picking one for the user is the exact thing the CLI refuses.
297
+ wrap.append(el("div", "note", t("challenge.candidatesNote")));
298
+ wrap.append(el("pre", "cmd", `orc challenge expect ${s.slug} --set <path>`));
299
+ }
300
+ return wrap;
301
+ }
302
+ if (s.state === "TAMPERED") {
303
+ wrap.append(el("div", "note bad", t("challenge.tamperedNote")));
304
+ return wrap;
305
+ }
306
+ if (s.state === "PASSED" || s.state === "STALE-PASS") {
307
+ wrap.append(el("div", "note", s.state === "PASSED" ? t("challenge.passedNote") : t("challenge.stalePassNote")));
308
+ wrap.append(el("pre", "cmd", `git add orc/orc-challenge/${s.slug}/`));
309
+ return wrap;
310
+ }
311
+ if (s.state === "AWAITING-FIX") {
312
+ wrap.append(el("div", "note", t("challenge.awaitingFixNote")));
313
+ wrap.append(challengeCopyPrompt(s));
314
+ return wrap;
315
+ }
316
+ // AWAITING-JUDGE and AWAITING-RECHECK both need a paid run.
317
+ wrap.append(laneCommand(s.next || `/orc-challenge ${s.slug}`, t("challenge.paidWhy")));
318
+ return wrap;
319
+ }
320
+
321
+ // Copying is FREE, so it is a button. The prompt is assembled from the CLI's own
322
+ // fields — the expected path, the slug, the frozen goal file — never from a
323
+ // second idea of where anything lives.
324
+ function challengeCopyPrompt(s) {
325
+ const prompt = [
326
+ `Fix the findings in orc/orc-challenge/${s.slug}/fix-brief.md.`,
327
+ "",
328
+ `Artifact: ${(s.artifacts[0] || {}).path || ""}`,
329
+ `Goal: orc/orc-challenge/${s.slug}/goals.md (read this first)`,
330
+ "",
331
+ `Write the revised version to: ${s.revision.expected}`,
332
+ "",
333
+ "Rules:",
334
+ "- Change the artifact only. Do not edit anything under orc/orc-challenge/.",
335
+ "- Do not mark findings resolved. The next judgement decides that.",
336
+ "- If you think a finding is wrong, do not argue with it here —",
337
+ ` run: orc challenge rebut ${s.slug} <id> "why"`,
338
+ "",
339
+ "When you are done, start ANOTHER new session and run:",
340
+ ` /orc-challenge ${s.slug}`,
341
+ ].join("\n");
342
+ const box = el("div", "lane-cmd");
343
+ box.append(el("div", "lane-cmd-head", t("challenge.pasteHead")));
344
+ box.append(el("pre", "cmd ch-prompt", prompt));
345
+ const b = el("button", "btn btn-sm", t("challenge.copyPrompt"));
346
+ b.type = "button";
347
+ b.addEventListener("click", () => copy(prompt, t("challenge.copyPrompt")));
348
+ box.append(b);
349
+ return box;
350
+ }
351
+
352
+ function challengeReportBtn(slug, body) {
353
+ const b = el("button", "btn btn-ghost btn-sm", t("challenge.reRender"));
354
+ b.type = "button";
355
+ b.addEventListener("click", async () => {
356
+ const r = await post("/api/challenge/report", { slug });
357
+ toast(r.ok ? t("challenge.reportOk") : t("common.writeFail"), r.ok ? "ok" : "bad", r.output);
358
+ renderChallenge(body);
359
+ });
360
+ return b;
361
+ }
362
+
363
+ // KEYS ARE WRITTEN OUT IN FULL, never assembled from a fragment — the i18n rule.
364
+ // A dotted key built by concatenation is a key no lint can find and no
365
+ // translator can see.
366
+ const CH_VALVE = {
367
+ accept: {
368
+ btn: "challenge.acceptBtn",
369
+ title: "challenge.acceptTitle",
370
+ body: "challenge.acceptBody",
371
+ note: "challenge.acceptNote",
372
+ go: "challenge.acceptGo",
373
+ ok: "challenge.acceptOk",
374
+ route: "/api/challenge/accept",
375
+ },
376
+ rebut: {
377
+ btn: "challenge.rebutBtn",
378
+ title: "challenge.rebutTitle",
379
+ body: "challenge.rebutBody",
380
+ note: "challenge.rebutNote",
381
+ go: "challenge.rebutGo",
382
+ ok: "challenge.rebutOk",
383
+ route: "/api/challenge/rebut",
384
+ },
385
+ };
386
+
387
+ // A COUNT IS NOT CONSENT, and neither is a click: a reason is mandatory, and the
388
+ // exact command is on screen the whole time — the CLI refuses without one too,
389
+ // so this form has no second idea of what a valid acceptance is.
390
+ function challengeValveBtn(which, slug, id, body) {
391
+ const K = CH_VALVE[which];
392
+ const b = el("button", "btn btn-ghost btn-sm", t(K.btn));
393
+ b.type = "button";
394
+ b.addEventListener("click", () => {
395
+ const wrap = frag();
396
+ wrap.append(el("p", null, t(K.body, { id })));
397
+ const input = el("input", "text-input");
398
+ input.type = "text";
399
+ input.placeholder = t("challenge.reasonPlaceholder");
400
+ wrap.append(input);
401
+ const cmd = el("pre", "cmd", `orc challenge ${which} ${slug} ${id} "…"`);
402
+ wrap.append(cmd);
403
+ wrap.append(el("div", "note", t(K.note)));
404
+ const m = modal({
405
+ title: t(K.title),
406
+ body: wrap,
407
+ actions: {
408
+ [t("common.cancel")]: null,
409
+ [t(K.go)]: async () => {
410
+ const reason = input.value.trim();
411
+ if (!reason) return toast(t("challenge.needReason"), "bad");
412
+ const r = await post(K.route, { slug, id, reason });
413
+ toast(r.ok ? t(K.ok) : t("common.writeFail"), r.ok ? "ok" : "bad", r.output);
414
+ renderChallenge(body);
415
+ },
416
+ },
417
+ });
418
+ input.addEventListener("input", () => {
419
+ cmd.textContent = `orc challenge ${which} ${slug} ${id} "${input.value || "…"}"`;
420
+ });
421
+ requestAnimationFrame(() => input.focus());
422
+ return m;
423
+ });
424
+ return b;
425
+ }
426
+
427
+ /* ONE reason prompt for the two council writes (v0.49.1).
428
+
429
+ Both `premise --dismiss` and `opportunity --take|--drop` REFUSE without a
430
+ reason, and the refusal is the CLI's, not this form's — so the button submits
431
+ whatever was typed and reports what came back. A reason recorded here stays
432
+ visible in the report forever, which is the point of demanding one. */
433
+ function challengeReasonPrompt({ title, note, onSubmit }) {
434
+ const wrap = frag();
435
+ const input = el("input", "text-input");
436
+ input.type = "text";
437
+ input.placeholder = t("challenge.reasonPlaceholder");
438
+ wrap.append(input);
439
+ wrap.append(el("div", "note", note));
440
+ const m = modal({
441
+ title,
442
+ body: wrap,
443
+ actions: {
444
+ [t("common.cancel")]: null,
445
+ [t("common.confirm")]: async () => {
446
+ const reason = input.value.trim();
447
+ if (!reason) return toast(t("challenge.needReason"), "bad");
448
+ await onSubmit(reason);
449
+ },
450
+ },
451
+ });
452
+ requestAnimationFrame(() => input.focus());
453
+ return m;
454
+ }
455
+
456
+ /* THE ITERATION TIMELINE — the hero.
457
+
458
+ GEOMETRY IS SOLVED FROM THE BOX SIZE, never expressed as a fraction of the
459
+ container (the VAULT / ringRadii lesson from Crosslink): a node box is a fixed
460
+ size, the rail is the bounding box of what was PLACED, and too many iterations
461
+ SCROLLS rather than being squeezed. A `regoal` or `retemplate` draws a VERSION
462
+ BREAK, because a comparison across one is not a comparison. */
463
+ const CH_NODE = { W: 92, H: 62, GAP: 30, PAD: 16, BREAK: 22 };
464
+
465
+ function challengeTimeline(s) {
466
+ const iters = s.convergence || [];
467
+ const box = el("div", "ch-rail-wrap");
468
+ // Where a version break falls: between iteration i-1 and i, when either frozen
469
+ // yardstick's version number changed.
470
+ // v0.49.1 adds a THIRD trigger: comparing an iteration judged by three lenses
471
+ // to one judged by six is not a comparison.
472
+ const breakBefore = iters.map((it, i) =>
473
+ i === 0
474
+ ? false
475
+ : it.graded_against !== iters[i - 1].graded_against ||
476
+ it.graded_against_goal !== iters[i - 1].graded_against_goal ||
477
+ (it.graded_against_council || 1) !== (iters[i - 1].graded_against_council || 1)
478
+ );
479
+ const xs = [];
480
+ let x = CH_NODE.PAD;
481
+ for (let i = 0; i < iters.length; i++) {
482
+ if (breakBefore[i]) x += CH_NODE.BREAK;
483
+ xs.push(x);
484
+ x += CH_NODE.W + CH_NODE.GAP;
485
+ }
486
+ const width = (xs.length ? xs[xs.length - 1] + CH_NODE.W : 0) + CH_NODE.PAD;
487
+ const height = CH_NODE.H + 2 * CH_NODE.PAD + 18;
488
+
489
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
490
+ svg.setAttribute("class", "ch-rail");
491
+ // The canvas is the bounding box of what was PLACED, and it keeps its aspect:
492
+ // a stretched viewBox squashes every label and every stroke.
493
+ svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
494
+ svg.setAttribute("width", String(width));
495
+ svg.setAttribute("height", String(height));
496
+ svg.setAttribute("role", "img");
497
+ svg.setAttribute("aria-label", t("challenge.timelineAria", { n: iters.length }));
498
+
499
+ const mk = (name, attrs, text) => {
500
+ const n = document.createElementNS("http://www.w3.org/2000/svg", name);
501
+ for (const k of Object.keys(attrs)) n.setAttribute(k, String(attrs[k]));
502
+ if (text !== undefined) n.textContent = text;
503
+ return n;
504
+ };
505
+
506
+ for (let i = 0; i < iters.length; i++) {
507
+ const it = iters[i];
508
+ const cx = xs[i];
509
+ const cy = CH_NODE.PAD;
510
+ if (i > 0) {
511
+ const prevEnd = xs[i - 1] + CH_NODE.W;
512
+ svg.append(mk("line", { x1: prevEnd, y1: cy + CH_NODE.H / 2, x2: cx, y2: cy + CH_NODE.H / 2, class: "ch-rail-link" }));
513
+ if (breakBefore[i]) {
514
+ const bx = (prevEnd + cx) / 2;
515
+ svg.append(mk("line", { x1: bx, y1: cy - 6, x2: bx, y2: cy + CH_NODE.H + 6, class: "ch-rail-break" }));
516
+ // The label names WHICH yardstick moved. `c2` is a council change; a
517
+ // bare version number is a goal change, as it always was.
518
+ const prev = iters[i - 1];
519
+ const label =
520
+ (it.graded_against_council || 1) !== (prev.graded_against_council || 1)
521
+ ? `c${it.graded_against_council || 1}`
522
+ : `v${it.graded_against_goal}`;
523
+ svg.append(mk("text", { x: bx, y: cy + CH_NODE.H + 18, class: "ch-rail-breaklabel", "text-anchor": "middle" }, label));
524
+ }
525
+ }
526
+ const g = mk("g", { class: "ch-rail-node" + (it.passed ? " pass" : " fail"), style: `animation-delay:${i * 40}ms` });
527
+ g.append(mk("rect", { x: cx, y: cy, width: CH_NODE.W, height: CH_NODE.H, rx: 10, class: "ch-rail-box" }));
528
+ g.append(mk("text", { x: cx + CH_NODE.W / 2, y: cy + 24, class: "ch-rail-n", "text-anchor": "middle" }, String(it.n)));
529
+ g.append(
530
+ mk("text", { x: cx + CH_NODE.W / 2, y: cy + 44, class: "ch-rail-verdict", "text-anchor": "middle" }, it.passed ? "PASS" : `FAIL ${it.blocking}`)
531
+ );
532
+ svg.append(g);
533
+ }
534
+ box.append(svg);
535
+ return box;
536
+ }
537
+
538
+ /* THE CONVERGENCE CHART — blocking findings per iteration, stacked by severity,
539
+ the same visual family as the budget cost bar. THIS IS THE PAYOFF PICTURE: you
540
+ can see a cycle converging, or not. It draws left to right on open, once,
541
+ because the SHAPE of the trend is the information. */
542
+ function challengeConvergence(s) {
543
+ const iters = s.convergence || [];
544
+ const wrap = el("div", "ch-conv");
545
+ const max = Math.max(1, ...iters.map((i) => ["P0", "P1", "P2", "P3"].reduce((n, k) => n + ((i.severities || {})[k] || 0), 0)));
546
+ for (const it of iters) {
547
+ const rowEl = el("div", "ch-conv-row");
548
+ rowEl.append(el("span", "ch-conv-n", String(it.n)));
549
+ const bar = el("div", "ch-conv-bar");
550
+ for (const sev of ["P0", "P1", "P2", "P3"]) {
551
+ const n = (it.severities || {})[sev] || 0;
552
+ if (!n) continue;
553
+ const seg = el("div", "ch-conv-seg ch-sev-" + sev.toLowerCase());
554
+ seg.style.setProperty("--w", ((n / max) * 100).toFixed(2) + "%");
555
+ seg.title = `${sev} ${n}`;
556
+ bar.append(seg);
557
+ }
558
+ rowEl.append(bar);
559
+ rowEl.append(el("span", "ch-conv-blocking", String(it.blocking)));
560
+ wrap.append(rowEl);
561
+ }
562
+ // THE PER-LENS LEGEND (v0.49.1). The stacking stays severity — do not add a
563
+ // second dimension to a bar that works — so "which lens is earning its money"
564
+ // gets its own row underneath. The counts and the prefixes are the CLI's.
565
+ const counts = s.lens_counts || {};
566
+ const lenses = Object.keys(counts);
567
+ if (lenses.length) {
568
+ const legend = el("div", "ch-lens-legend");
569
+ for (const lens of lenses) {
570
+ const item = el("span", "ch-lens-legend-item");
571
+ item.append(el("span", "mono", lens));
572
+ item.append(el("span", "ch-lens-legend-n", String(counts[lens])));
573
+ legend.append(item);
574
+ }
575
+ wrap.append(legend);
576
+ }
577
+ wrap.append(el("div", "note", t("challenge.convNote")));
578
+ return wrap;
579
+ }
580
+
581
+ /* THE COUNCIL CARD (v0.49.1).
582
+
583
+ THE PANEL DERIVES NOTHING HERE. It does not name a lens, does not know which
584
+ class blocks, does not compute a disposition and does not decide the roster
585
+ suggestion — every one of those comes from `orc challenge roles --json` and
586
+ `orc challenge status --json`. Same rule as the Flow stepper: a second idea of
587
+ what the council is, is exactly the drift this panel exists to make
588
+ impossible.
589
+
590
+ A NOT-RUN row KEEPS ITS SLOT with its reason, and a NOT-SELECTED row renders
591
+ muted with the one line that would add it. */
592
+ function challengeCouncilCard(s, roles, show) {
593
+ const c = card(t("challenge.council") + (s.council_version ? " v" + s.council_version : ""));
594
+ if (s.council_unset) {
595
+ c.append(empty(t("challenge.councilUnset"), t("challenge.councilUnsetHint")));
596
+ c.append(laneCommand(`/orc-challenge ${s.slug}`, t("challenge.councilUnsetWhy")));
597
+ return c;
598
+ }
599
+ const ran = (s.council || []).filter((r) => r.status === "RAN").length;
600
+ const selected = (s.council || []).filter((r) => r.selected).length;
601
+ const head = el("div", "row-actions");
602
+ head.append(chip(t("challenge.councilRan", { ran, of: selected }), ran === selected ? "ok" : "warn"));
603
+ c.append(head);
604
+
605
+ for (const r of s.council || []) {
606
+ const row = el("div", "ch-lens-row" + (r.selected ? "" : " row-muted"));
607
+ const top = el("div", "row-actions");
608
+ top.append(chip(r.status, r.status === "RAN" ? "ok" : r.status === "NOT-RUN" ? "warn" : ""));
609
+ top.append(el("span", "ch-lens-name", r.display));
610
+ // `class` is the CLI's word — finding | opportunity | premise. It is never
611
+ // translated: a translated class word is a class that does not exist.
612
+ top.append(chip(r.class, r.class === "finding" ? "" : "info"));
613
+ if (!r.blocks) top.append(chip(t("challenge.neverBlocks"), "info"));
614
+ row.append(top);
615
+ row.append(el("div", "mono dim ch-lens-agent", r.agent + " · " + r.effort));
616
+ row.append(el("div", "note", r.why));
617
+ if (r.status === "RAN" && r.raised !== undefined)
618
+ row.append(
619
+ el(
620
+ "div",
621
+ "note",
622
+ t("challenge.lensCounts", {
623
+ raised: r.raised,
624
+ adopted: r.adopted || 0,
625
+ merged: r.merged || 0,
626
+ rejected: r.rejected || 0,
627
+ outOfGoal: r.out_of_goal || 0,
628
+ })
629
+ )
630
+ );
631
+ // Rule 15: a selected role is never silently absent.
632
+ if (r.status === "NOT-RUN" && r.reason) row.append(el("div", "note warn", t("challenge.lensNotRun", { reason: r.reason })));
633
+ if (r.status === "NOT-SELECTED" && r.add_with) {
634
+ row.append(el("div", "note", t("challenge.lensNotSelected")));
635
+ row.append(el("pre", "cmd", r.add_with));
636
+ }
637
+ // THE MONDAY-MORNING LIST — the single most legible artifact this lane
638
+ // produces for a non-engineer, so it sits high, inside the council card.
639
+ if ((r.monday_morning || []).length) {
640
+ const ol = el("ol", "ch-monday");
641
+ for (const step of r.monday_morning) ol.append(el("li", null, step));
642
+ row.append(el("div", "ch-monday-head", t("challenge.mondayMorning")));
643
+ row.append(ol);
644
+ }
645
+ c.append(row);
646
+ }
647
+ c.append(el("div", "note", t("challenge.councilNote")));
648
+ void roles;
649
+ void show;
650
+ return c;
651
+ }
652
+
653
+ /* PREMISE CHALLENGES — the loudest card here when one is open, because a premise
654
+ disputes the frozen goal that every finding below was measured against.
655
+
656
+ Two resolutions, and NEITHER IS AUTOMATIC: dismiss (free, a real write, so a
657
+ button) or change the goal (a copy-able command, because it needs a FILE the
658
+ panel must not invent). */
659
+ function challengePremiseCard(s, slug, body) {
660
+ const all = Object.entries(s.premises || {});
661
+ if (!all.length) return null;
662
+ const open = all.filter(([, q]) => q.status === "open");
663
+ const c = card(t("challenge.premises"));
664
+ if (open.length) c.classList.add("ch-premise-loud");
665
+ for (const [id, q] of all) {
666
+ const box = el("div", "ch-premise");
667
+ const hdr = el("div", "row-actions");
668
+ hdr.append(el("span", "mono dim", id));
669
+ hdr.append(chip(t("challenge.disputes", { what: q.disputes }), q.status === "open" ? "bad" : ""));
670
+ hdr.append(chip(q.status, q.status === "open" ? "warn" : ""));
671
+ box.append(hdr);
672
+ if (q.quote) box.append(el("blockquote", "ch-quote", q.quote));
673
+ const rows = [];
674
+ if (q.reframe) rows.push([t("challenge.field.reframe"), q.reframe]);
675
+ if (q.what_changes) rows.push([t("challenge.field.whatChanges"), q.what_changes]);
676
+ if (q.cheapest_test) rows.push([t("challenge.field.cheapestTest"), q.cheapest_test]);
677
+ if (q.reason) rows.push([t("challenge.field.reason"), q.reason]);
678
+ box.append(kvList(rows));
679
+ if (q.status === "open") {
680
+ const acts = el("div", "row-actions");
681
+ const dismiss = el("button", "btn btn-sm", t("challenge.dismissPremise"));
682
+ dismiss.type = "button";
683
+ dismiss.addEventListener("click", () => challengeReasonPrompt({
684
+ title: t("challenge.dismissPremise"),
685
+ note: t("challenge.dismissPremiseNote"),
686
+ onSubmit: async (reason) => {
687
+ const r = await post("/api/challenge/premise", { slug, id, reason });
688
+ toast(r.command, r.ok ? "ok" : "bad", r.output);
689
+ renderChallenge(body);
690
+ },
691
+ }));
692
+ acts.append(dismiss);
693
+ box.append(acts);
694
+ // Adopting needs a goals FILE, so it is a command and never a button.
695
+ box.append(laneCommand(`orc challenge goals ${slug} --set <path> --reason "…"`, t("challenge.adoptPremiseWhy")));
696
+ }
697
+ c.append(box);
698
+ }
699
+ c.append(el("div", "note", t("challenge.premiseNote")));
700
+ return c;
701
+ }
702
+
703
+ /* OPPORTUNITIES — no severity colour anywhere in this card. An opportunity never
704
+ blocks, and every one of them carries a first step and a route. */
705
+ function challengeOpportunityCard(s, slug, body) {
706
+ const all = Object.entries(s.opportunities || {});
707
+ if (!all.length) return null;
708
+ const c = card(t("challenge.opportunities"));
709
+ c.append(el("div", "note", t("challenge.opportunityNote")));
710
+ for (const [id, o] of all) {
711
+ const box = el("div", "ch-opportunity");
712
+ const hdr = el("div", "row-actions");
713
+ hdr.append(el("span", "mono dim", id));
714
+ hdr.append(chip(o.status, ""));
715
+ // The route is the CLI's own word — it is the lane this belongs in next.
716
+ if (o.route && o.route !== "none") hdr.append(chip(o.route, "info"));
717
+ box.append(hdr);
718
+ const rows = [];
719
+ if (o.what) rows.push([t("challenge.field.what"), o.what]);
720
+ if (o.upside) rows.push([t("challenge.field.upside"), o.upside]);
721
+ if (o.first_step) rows.push([t("challenge.field.firstStep"), o.first_step]);
722
+ if (o.anchor) rows.push([t("challenge.field.anchor"), o.anchor]);
723
+ if (o.confidence) rows.push([t("challenge.field.confidence"), o.confidence]);
724
+ if (o.resolved_reason) rows.push([t("challenge.field.reason"), o.resolved_reason]);
725
+ box.append(kvList(rows));
726
+ if (o.status === "open") {
727
+ const acts = el("div", "row-actions");
728
+ for (const take of [true, false]) {
729
+ const b = el("button", "btn btn-sm" + (take ? "" : " btn-ghost"), take ? t("challenge.takeOpportunity") : t("challenge.dropOpportunity"));
730
+ b.type = "button";
731
+ b.addEventListener("click", () => challengeReasonPrompt({
732
+ title: take ? t("challenge.takeOpportunity") : t("challenge.dropOpportunity"),
733
+ note: t("challenge.opportunityReasonNote"),
734
+ onSubmit: async (reason) => {
735
+ const r = await post("/api/challenge/opportunity", { slug, id, take, reason });
736
+ toast(r.command, r.ok ? "ok" : "bad", r.output);
737
+ renderChallenge(body);
738
+ },
739
+ }));
740
+ acts.append(b);
741
+ }
742
+ box.append(acts);
743
+ }
744
+ c.append(box);
745
+ }
746
+ return c;
747
+ }
748
+
749
+ /* A paid action is a COMMAND, never a button. This renders one, with the reason
750
+ it is not a button — making the boundary visible rather than hiding it. */
751
+ function laneCommand(cmd, why) {
752
+ const box = el("div", "lane-cmd");
753
+ box.append(el("div", "lane-cmd-head", t("common.runInClaude")));
754
+ const row = el("div", "row-actions");
755
+ row.append(el("pre", "cmd", cmd));
756
+ const b = el("button", "btn btn-ghost btn-sm", t("common.copy"));
757
+ b.type = "button";
758
+ b.addEventListener("click", () => copy(cmd, cmd));
759
+ row.append(b);
760
+ box.append(row);
761
+ if (why) box.append(el("div", "note", why));
762
+ return box;
763
+ }
764
+
765
+ /* ==================================================================== DOCS == */
766
+ /*
767
+ THE PANEL DERIVES NOTHING. Not the section order, not a line range, not a
768
+ state word, not the batching, not a lint rule name, not the completion
769
+ verdict. It draws `orc doc … --json`. (The Flow-stepper rule: a second idea
770
+ of the pipeline is exactly the drift this panel exists to make impossible.)
771
+
772
+ THE FREE/PAID LINE, visible rather than hidden: `list`, `status`, `map`,
773
+ `lint`, `plan` and `assemble` are deterministic and cost no model tokens, so
774
+ each is a real BUTTON. Writing a section, checking a range and editing one all
775
+ cost model tokens, so they are copy-able commands and there is no route for
776
+ any of them.
777
+
778
+ AND IT IS A PLAN PREVIEW, NOT A LIVE MONITOR. The server cannot see a running
779
+ session, so the wave card says so in one line. Claiming live status would be
780
+ this panel's first lie.
781
+ */