@azure-id/orc 1.9.1 → 2.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 (224) hide show
  1. package/CHANGELOG.md +390 -0
  2. package/README-id.md +20 -36
  3. package/README.md +24 -34
  4. package/bin/build-agents.js +206 -109
  5. package/bin/cli.js +760 -62
  6. package/bin/gotcha-import.js +1081 -0
  7. package/bin/gotcha.js +1286 -0
  8. package/bin/graph-query.js +1 -1
  9. package/bin/graph.js +717 -717
  10. package/bin/habit.js +1453 -0
  11. package/bin/mockrun-catalog.js +281 -276
  12. package/bin/onboarding-content.js +4 -4
  13. package/bin/pricing.json +207 -200
  14. package/bin/run-undo.js +398 -0
  15. package/bin/trace-write.js +657 -0
  16. package/bin/verify-contracts.js +527 -81
  17. package/bin/verify-package.js +58 -11
  18. package/bin/webui/api.js +26 -0
  19. package/bin/webui/app.html +239 -232
  20. package/bin/webui/css/00-tokens.css +110 -92
  21. package/bin/webui/css/04-motion.css +249 -152
  22. package/bin/webui/css/06-responsive.css +203 -178
  23. package/bin/webui/css/panels/behaviour.css +205 -0
  24. package/bin/webui/css/panels/knowledge.css +563 -116
  25. package/bin/webui/fixtures/behaviour.js +532 -0
  26. package/bin/webui/fixtures/extra.js +2036 -2036
  27. package/bin/webui/fixtures/hookui.js +5 -5
  28. package/bin/webui/fixtures/index.js +34 -0
  29. package/bin/webui/fixtures/knowledge.js +7 -1
  30. package/bin/webui/fixtures/settings.js +305 -305
  31. package/bin/webui/fixtures/stats.js +16 -0
  32. package/bin/webui/i18n/en/behaviour.json +143 -0
  33. package/bin/webui/i18n/en/knowledge.json +117 -2
  34. package/bin/webui/i18n/en/nav.json +25 -24
  35. package/bin/webui/i18n/en/tour.json +37 -35
  36. package/bin/webui/i18n/id/behaviour.json +143 -0
  37. package/bin/webui/i18n/id/knowledge.json +117 -2
  38. package/bin/webui/i18n/id/nav.json +25 -24
  39. package/bin/webui/i18n/id/tour.json +37 -35
  40. package/bin/webui/js/01-i18n.js +155 -154
  41. package/bin/webui/js/90-tour.js +498 -494
  42. package/bin/webui/js/91-shortcuts.js +126 -126
  43. package/bin/webui/js/99-boot.js +121 -118
  44. package/bin/webui/js/panels/behaviour.js +1022 -0
  45. package/bin/webui/js/panels/knowledge.js +552 -7
  46. package/bin/webui/js/panels/overview.js +13 -4
  47. package/mock-run/INDEX.md +109 -107
  48. package/mock-run/context-combiner.md +100 -100
  49. package/mock-run/gotcha-import.md +118 -0
  50. package/mock-run/habits.md +129 -0
  51. package/mock-run/orc-budget.md +534 -534
  52. package/mock-run/orc-challenge-council.md +262 -262
  53. package/mock-run/orc-quick.md +6 -1
  54. package/mock-run/orc-ultra.md +103 -103
  55. package/package.json +1 -1
  56. package/templates/agents/MODEL-MAPPING.md +49 -49
  57. package/templates/agents/orc-advisor-opus-5-xhigh.md +50 -56
  58. package/templates/agents/orc-analyze-mini-opus-5-med.md +55 -60
  59. package/templates/agents/orc-analyze-mini-sonnet-5-high.md +55 -58
  60. package/templates/agents/orc-challenge-advisor-opus-5-med.md +75 -75
  61. package/templates/agents/orc-challenge-contrarian-opus-5-high.md +110 -110
  62. package/templates/agents/orc-challenge-executor-opus-5-med.md +114 -114
  63. package/templates/agents/orc-challenge-expansionist-opus-5-med.md +112 -112
  64. package/templates/agents/orc-challenge-judge-opus-5-high.md +132 -132
  65. package/templates/agents/orc-challenge-outsider-opus-5-low.md +109 -109
  66. package/templates/agents/orc-challenge-principles-opus-5-high.md +109 -109
  67. package/templates/agents/orc-challenge-reader-opus-5-low.md +90 -90
  68. package/templates/agents/orc-claude-writer-opus-4-8-high.md +48 -53
  69. package/templates/agents/orc-claude-writer-opus-5-med.md +48 -55
  70. package/templates/agents/orc-context-combiner-opus-5-high.md +78 -88
  71. package/templates/agents/orc-doc-checker-opus-5-low.md +108 -108
  72. package/templates/agents/orc-doc-writer-opus-5-med.md +134 -134
  73. package/templates/agents/orc-executor-haiku-4-5.md +14 -6
  74. package/templates/agents/orc-executor-opus-4-7-high.md +14 -6
  75. package/templates/agents/orc-executor-opus-4-7-med.md +14 -6
  76. package/templates/agents/orc-executor-opus-4-8-high.md +14 -6
  77. package/templates/agents/orc-executor-opus-5-high.md +15 -7
  78. package/templates/agents/orc-executor-opus-5-low.md +15 -7
  79. package/templates/agents/orc-executor-opus-5-med.md +15 -7
  80. package/templates/agents/orc-executor-sonnet-4-6-high.md +14 -6
  81. package/templates/agents/orc-executor-sonnet-4-6-med.md +14 -6
  82. package/templates/agents/orc-executor-sonnet-5-high.md +14 -6
  83. package/templates/agents/orc-graph-noter-sonnet-4-6-med.md +1 -10
  84. package/templates/agents/orc-judge-opus-5-xhigh.md +81 -85
  85. package/templates/agents/orc-learn-writer-opus-5-low.md +67 -73
  86. package/templates/agents/orc-pattern-codifier-opus-5-med.md +58 -65
  87. package/templates/agents/orc-pattern-codifier-sonnet-5-high.md +58 -63
  88. package/templates/agents/orc-planner-mini-opus-5-med.md +4 -7
  89. package/templates/agents/orc-planner-mini-sonnet-5-high.md +2 -3
  90. package/templates/agents/orc-planner-opus-5-med.md +157 -160
  91. package/templates/agents/orc-recon-opus-5-low.md +3 -10
  92. package/templates/agents/orc-recon-sonnet-4-6-med.md +1 -8
  93. package/templates/agents/orc-retro-opus-5-med.md +8 -10
  94. package/templates/agents/orc-retro-sonnet-5-high.md +6 -7
  95. package/templates/agents/orc-reviewer-opus-5-med.md +96 -60
  96. package/templates/agents/orc-scout-opus-5-low.md +35 -40
  97. package/templates/agents/orc-scout-sonnet-4-6-high.md +35 -39
  98. package/templates/agents/orc-system-analyst-opus-5-high.md +115 -120
  99. package/templates/agents/orc-test-author-opus-5-med.md +70 -71
  100. package/templates/agents/orc-test-designer-opus-5-high.md +158 -158
  101. package/templates/agents/orc-test-interpreter-opus-5-low.md +130 -130
  102. package/templates/agents/orc-trace-writer-haiku-4-5.md +3 -7
  103. package/templates/agents/orc-verifier-opus-5-med.md +77 -69
  104. package/templates/agents/orc-wiki-scanner-opus-4-8-high.md +74 -79
  105. package/templates/agents/orc-wiki-scanner-opus-5-med.md +74 -81
  106. package/templates/agents/orc-wiki-scanner-sonnet-5-high.md +97 -106
  107. package/templates/commands/orc-analyze.md +13 -21
  108. package/templates/commands/orc-fast.md +10 -15
  109. package/templates/commands/orc-poly.md +12 -21
  110. package/templates/commands/orc-pr-driver.md +11 -30
  111. package/templates/commands/orc-pr-setup.md +10 -31
  112. package/templates/commands/orc-route.md +11 -41
  113. package/templates/commands/orc-test.md +5 -60
  114. package/templates/commands/orc-ultra.md +17 -17
  115. package/templates/commands/orc-verify.md +11 -11
  116. package/templates/hooks/README.md +36 -2
  117. package/templates/hooks/orc-effort-guard.js +178 -178
  118. package/templates/hooks/orc-session-hook.js +264 -0
  119. package/templates/hooks/orc-statusline.js +9 -7
  120. package/templates/skills/_shared/README.md +9 -0
  121. package/templates/skills/_shared/code-graph.md +48 -56
  122. package/templates/skills/_shared/config-precedence.md +200 -198
  123. package/templates/skills/_shared/extra-dispatch.md +1331 -1346
  124. package/templates/skills/_shared/gotchas.md +228 -177
  125. package/templates/skills/_shared/habits.md +101 -0
  126. package/templates/skills/_shared/lane-contract.md +84 -0
  127. package/templates/skills/_shared/opus5-only.md +8 -8
  128. package/templates/skills/_shared/phases/README.md +142 -83
  129. package/templates/skills/_shared/phases/analyst-gates.md +125 -136
  130. package/templates/skills/_shared/phases/execution.md +8 -14
  131. package/templates/skills/_shared/phases/house-rules.md +27 -32
  132. package/templates/skills/_shared/phases/intake.md +127 -133
  133. package/templates/skills/_shared/phases/mock-example.md +46 -56
  134. package/templates/skills/_shared/phases/plan-handoff.md +91 -97
  135. package/templates/skills/_shared/phases/planning.md +7 -17
  136. package/templates/skills/_shared/phases/preflight.md +19 -42
  137. package/templates/skills/_shared/phases/review.md +23 -27
  138. package/templates/skills/_shared/phases/rules.md +18 -42
  139. package/templates/skills/_shared/phases/scoring.md +55 -65
  140. package/templates/skills/_shared/phases/security-checklist.md +46 -50
  141. package/templates/skills/_shared/phases/security.md +45 -55
  142. package/templates/skills/_shared/phases/ship.md +6 -15
  143. package/templates/skills/_shared/phases/stop-resume.md +2 -5
  144. package/templates/skills/_shared/phases/summary.md +73 -48
  145. package/templates/skills/_shared/phases/testgen.md +41 -51
  146. package/templates/skills/_shared/phases/trace-verbs.md +433 -0
  147. package/templates/skills/_shared/phases/trace.md +136 -367
  148. package/templates/skills/_shared/phases/verify.md +62 -70
  149. package/templates/skills/_shared/phases/wave-grouping.md +128 -133
  150. package/templates/skills/_shared/phases/wiki-consult.md +10 -6
  151. package/templates/skills/_shared/read-ladder.md +2 -55
  152. package/templates/skills/_shared/return-validation.md +17 -70
  153. package/templates/skills/_shared/review-slice.md +79 -0
  154. package/templates/skills/_shared/smoke-gate.md +46 -28
  155. package/templates/skills/context-combiner/SKILL.md +16 -45
  156. package/templates/skills/context-combiner/schemas/combined-report.md +78 -78
  157. package/templates/skills/orc/README.md +2 -2
  158. package/templates/skills/orc/SKILL.md +41 -69
  159. package/templates/skills/orc/config.md +9 -9
  160. package/templates/skills/orc/examples/full-run-mock.md +73 -73
  161. package/templates/skills/orc/references/effort-and-mode.md +222 -222
  162. package/templates/skills/orc/references/pattern-gate.md +89 -89
  163. package/templates/skills/orc/references/phases/intake.md +41 -47
  164. package/templates/skills/orc/references/phases/integration.md +13 -19
  165. package/templates/skills/orc/references/preflight-report.md +10 -11
  166. package/templates/skills/orc/references/ultra-mode.md +11 -9
  167. package/templates/skills/orc/subskills/orc-execution/SKILL.md +27 -73
  168. package/templates/skills/orc/subskills/orc-execution/core.md +12 -99
  169. package/templates/skills/orc/subskills/orc-execution/subagent.md +14 -13
  170. package/templates/skills/orc/subskills/orc-planner/SKILL.md +2 -2
  171. package/templates/skills/orc/subskills/orc-planner-mini/SKILL.md +121 -121
  172. package/templates/skills/orc/subskills/orc-review-verify/SKILL.md +35 -76
  173. package/templates/skills/orc/subskills/orc-review-verify/core.md +52 -135
  174. package/templates/skills/orc/subskills/orc-review-verify/subagent.md +7 -7
  175. package/templates/skills/orc/subskills/orc-testgen/SKILL.md +34 -45
  176. package/templates/skills/orc/subskills/orc-testgen/core.md +20 -59
  177. package/templates/skills/orc/subskills/orc-testgen/subagent.md +7 -7
  178. package/templates/skills/orc-advisor/SKILL.md +56 -60
  179. package/templates/skills/orc-analyze/SKILL.md +32 -68
  180. package/templates/skills/orc-analyze/examples/analyze-mock.md +42 -42
  181. package/templates/skills/orc-analyze/schemas/report-audit.md +84 -83
  182. package/templates/skills/orc-analyze/schemas/report-prose.md +64 -63
  183. package/templates/skills/orc-analyze/schemas/report-requirement.md +78 -78
  184. package/templates/skills/orc-analyze-mini/SKILL.md +35 -70
  185. package/templates/skills/orc-challenge/README.md +142 -142
  186. package/templates/skills/orc-challenge/examples/council-full-roster.md +273 -273
  187. package/templates/skills/orc-challenge/references/council.md +315 -315
  188. package/templates/skills/orc-challenge/references/intake.md +171 -171
  189. package/templates/skills/orc-claude/SKILL.md +14 -14
  190. package/templates/skills/orc-diy/README.md +174 -143
  191. package/templates/skills/orc-diy/SKILL.md +23 -74
  192. package/templates/skills/orc-diy/references/blocks/pattern.md +18 -18
  193. package/templates/skills/orc-diy/references/flow-schema.md +1 -1
  194. package/templates/skills/orc-doc/README.md +229 -229
  195. package/templates/skills/orc-doc/examples/orc-doc-prd-run.md +325 -325
  196. package/templates/skills/orc-doc/references/chunking.md +527 -527
  197. package/templates/skills/orc-fast/SKILL.md +45 -73
  198. package/templates/skills/orc-judge/SKILL.md +77 -82
  199. package/templates/skills/orc-learn/SKILL.md +14 -14
  200. package/templates/skills/orc-learn/examples/learn-run-mock.md +61 -61
  201. package/templates/skills/orc-mini/SKILL.md +65 -113
  202. package/templates/skills/orc-pattern/SKILL.md +27 -48
  203. package/templates/skills/orc-poly/SKILL.md +32 -61
  204. package/templates/skills/orc-pr-driver/SKILL.md +25 -51
  205. package/templates/skills/orc-pr-driver/references/green-gate.md +113 -105
  206. package/templates/skills/orc-pr-setup/SKILL.md +20 -45
  207. package/templates/skills/orc-quick/README.md +43 -2
  208. package/templates/skills/orc-quick/SKILL.md +76 -107
  209. package/templates/skills/orc-quick/references/dispatch-gate.md +16 -5
  210. package/templates/skills/orc-quick/references/gh-mode.md +48 -1
  211. package/templates/skills/orc-quick/references/look.md +3 -1
  212. package/templates/skills/orc-retro/SKILL.md +19 -18
  213. package/templates/skills/orc-retro/examples/retro-mock.md +1 -1
  214. package/templates/skills/orc-route/SKILL.md +25 -45
  215. package/templates/skills/orc-test/SKILL.md +16 -37
  216. package/templates/skills/orc-verify/SKILL.md +21 -39
  217. package/templates/skills/orc-verify/examples/verify-mock.md +33 -33
  218. package/templates/skills/orc-wait/SKILL.md +156 -163
  219. package/templates/skills/orc-wiki/references/extra.md +1 -1
  220. package/templates/skills/orc-wiki/references/phases/phase-0.md +1 -6
  221. package/templates/skills/orc-wiki/references/phases/phase-1.md +1 -6
  222. package/templates/skills/orc-wiki/references/phases/phase-2.md +1 -6
  223. package/templates/skills/orc-wiki/references/phases/phase-3.md +1 -6
  224. package/templates/skills/orc-wiki/references/phases/phase-3c.md +1 -6
@@ -1,126 +1,126 @@
1
- "use strict";
2
- /* 91-shortcuts.js — orc ui client
3
- Single keys, and ONLY when you are not typing into something.
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
- /* =============================================================== shortcuts == */
10
-
11
- // Keyboard nav for a panel app that is otherwise all mouse. Deliberately small
12
- // and unmodified: single keys, and ONLY when you are not typing into something.
13
- const SHORTCUTS = () => [
14
- ["1 – 9, 0", t("shortcuts.panels")],
15
- ["d · c · p · b · h · e · m", t("shortcuts.panelsLetters")],
16
- ["/", t("shortcuts.filter")],
17
- ["r", t("shortcuts.reload")],
18
- ["t", t("shortcuts.theme")],
19
- ["l", t("shortcuts.lang")],
20
- ["?", t("shortcuts.list")],
21
- ["Esc", t("shortcuts.escape")],
22
- ];
23
-
24
- // A keystroke must never be stolen from an input, a textarea or a select — that
25
- // is how a UI eats the "r" in the middle of a path somebody is typing.
26
- function typingInto(t) {
27
- return !!t && (t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.tagName === "SELECT" || t.isContentEditable);
28
- }
29
-
30
- function showShortcuts() {
31
- const body = el("div", "stack stack-sm");
32
- const list = el("dl", "kv");
33
- for (const [key, what] of SHORTCUTS()) {
34
- const dt = el("dt");
35
- dt.append(el("kbd", null, key));
36
- list.append(dt, el("dd", null, what));
37
- }
38
- body.append(list);
39
- body.append(el("div", "note", t("shortcuts.note")));
40
- modal({
41
- title: t("shortcuts.title"),
42
- body,
43
- actions: [
44
- // Dismissing the tour must never be a one-way door: it is skippable
45
- // precisely because it can be replayed.
46
- {
47
- label: t("shortcuts.replay"),
48
- onClick: (c) => {
49
- c();
50
- startFirstRunTour(metaInfo.project_root);
51
- },
52
- },
53
- { label: t("common.close"), onClick: (c) => c() },
54
- ],
55
- });
56
- }
57
-
58
- function installShortcuts() {
59
- document.addEventListener("keydown", (e) => {
60
- if (e.metaKey || e.ctrlKey || e.altKey) return;
61
- // A dialog owns the keyboard while it is open; it has its own Esc handler.
62
- if (!$("#modal-host").hidden) return;
63
- // …and so does a blocking tour step. Its own capture-phase handler has
64
- // already swallowed the key by now; this is the second lock on the door.
65
- if (tourActive && tourActive.blocking) return;
66
- if (typingInto(e.target)) return;
67
-
68
- if (e.key >= "0" && e.key <= "9") {
69
- // Matched on data-idx, not on position: the rail's order is HTML's to
70
- // decide, and a positional lookup silently rebinds every key the moment a
71
- // panel is inserted in the middle.
72
- const target = document.querySelector('#nav a[data-idx="' + e.key + '"]');
73
- if (target) {
74
- e.preventDefault();
75
- location.hash = target.getAttribute("href");
76
- }
77
- return;
78
- }
79
- // v0.46.0: the rail outgrew ten digits, so several panels carry a LETTER key.
80
- // Same lookup, same rule — matched on data-idx, never on position — and the
81
- // letters are checked before the r/t/l actions so a rail key can never be
82
- // shadowed by one of them. Adding a panel whose letter collides with an
83
- // action would break the action; p/b/h/m/c/d were free.
84
- //
85
- // The class is derived from the rail rather than re-listed, because that is
86
- // what went wrong the first time: `c` was given to Challenge in the markup
87
- // and never added to a hardcoded `[pbhm]`, so the key did nothing and
88
- // nothing failed. A rail key now works because it is IN THE RAIL.
89
- if (/^[a-z]$/.test(e.key)) {
90
- const target = document.querySelector('#nav a[data-idx="' + e.key + '"]');
91
- if (target) {
92
- e.preventDefault();
93
- location.hash = target.getAttribute("href");
94
- return;
95
- }
96
- }
97
- if (e.key === "/") {
98
- const f = $("#settings-filter");
99
- if (f) {
100
- e.preventDefault();
101
- f.focus();
102
- f.select();
103
- }
104
- return;
105
- }
106
- if (e.key === "r") {
107
- e.preventDefault();
108
- route();
109
- return;
110
- }
111
- if (e.key === "t") {
112
- e.preventDefault();
113
- $("#theme-toggle").click();
114
- return;
115
- }
116
- if (e.key === "l") {
117
- e.preventDefault();
118
- cycleLang();
119
- return;
120
- }
121
- if (e.key === "?") {
122
- e.preventDefault();
123
- showShortcuts();
124
- }
125
- });
126
- }
1
+ "use strict";
2
+ /* 91-shortcuts.js — orc ui client
3
+ Single keys, and ONLY when you are not typing into something.
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
+ /* =============================================================== shortcuts == */
10
+
11
+ // Keyboard nav for a panel app that is otherwise all mouse. Deliberately small
12
+ // and unmodified: single keys, and ONLY when you are not typing into something.
13
+ const SHORTCUTS = () => [
14
+ ["1 – 9, 0", t("shortcuts.panels")],
15
+ ["d · c · p · b · h · e · m · u", t("shortcuts.panelsLetters")],
16
+ ["/", t("shortcuts.filter")],
17
+ ["r", t("shortcuts.reload")],
18
+ ["t", t("shortcuts.theme")],
19
+ ["l", t("shortcuts.lang")],
20
+ ["?", t("shortcuts.list")],
21
+ ["Esc", t("shortcuts.escape")],
22
+ ];
23
+
24
+ // A keystroke must never be stolen from an input, a textarea or a select — that
25
+ // is how a UI eats the "r" in the middle of a path somebody is typing.
26
+ function typingInto(t) {
27
+ return !!t && (t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.tagName === "SELECT" || t.isContentEditable);
28
+ }
29
+
30
+ function showShortcuts() {
31
+ const body = el("div", "stack stack-sm");
32
+ const list = el("dl", "kv");
33
+ for (const [key, what] of SHORTCUTS()) {
34
+ const dt = el("dt");
35
+ dt.append(el("kbd", null, key));
36
+ list.append(dt, el("dd", null, what));
37
+ }
38
+ body.append(list);
39
+ body.append(el("div", "note", t("shortcuts.note")));
40
+ modal({
41
+ title: t("shortcuts.title"),
42
+ body,
43
+ actions: [
44
+ // Dismissing the tour must never be a one-way door: it is skippable
45
+ // precisely because it can be replayed.
46
+ {
47
+ label: t("shortcuts.replay"),
48
+ onClick: (c) => {
49
+ c();
50
+ startFirstRunTour(metaInfo.project_root);
51
+ },
52
+ },
53
+ { label: t("common.close"), onClick: (c) => c() },
54
+ ],
55
+ });
56
+ }
57
+
58
+ function installShortcuts() {
59
+ document.addEventListener("keydown", (e) => {
60
+ if (e.metaKey || e.ctrlKey || e.altKey) return;
61
+ // A dialog owns the keyboard while it is open; it has its own Esc handler.
62
+ if (!$("#modal-host").hidden) return;
63
+ // …and so does a blocking tour step. Its own capture-phase handler has
64
+ // already swallowed the key by now; this is the second lock on the door.
65
+ if (tourActive && tourActive.blocking) return;
66
+ if (typingInto(e.target)) return;
67
+
68
+ if (e.key >= "0" && e.key <= "9") {
69
+ // Matched on data-idx, not on position: the rail's order is HTML's to
70
+ // decide, and a positional lookup silently rebinds every key the moment a
71
+ // panel is inserted in the middle.
72
+ const target = document.querySelector('#nav a[data-idx="' + e.key + '"]');
73
+ if (target) {
74
+ e.preventDefault();
75
+ location.hash = target.getAttribute("href");
76
+ }
77
+ return;
78
+ }
79
+ // v0.46.0: the rail outgrew ten digits, so several panels carry a LETTER key.
80
+ // Same lookup, same rule — matched on data-idx, never on position — and the
81
+ // letters are checked before the r/t/l actions so a rail key can never be
82
+ // shadowed by one of them. Adding a panel whose letter collides with an
83
+ // action would break the action; p/b/h/m/c/d were free.
84
+ //
85
+ // The class is derived from the rail rather than re-listed, because that is
86
+ // what went wrong the first time: `c` was given to Challenge in the markup
87
+ // and never added to a hardcoded `[pbhm]`, so the key did nothing and
88
+ // nothing failed. A rail key now works because it is IN THE RAIL.
89
+ if (/^[a-z]$/.test(e.key)) {
90
+ const target = document.querySelector('#nav a[data-idx="' + e.key + '"]');
91
+ if (target) {
92
+ e.preventDefault();
93
+ location.hash = target.getAttribute("href");
94
+ return;
95
+ }
96
+ }
97
+ if (e.key === "/") {
98
+ const f = $("#settings-filter");
99
+ if (f) {
100
+ e.preventDefault();
101
+ f.focus();
102
+ f.select();
103
+ }
104
+ return;
105
+ }
106
+ if (e.key === "r") {
107
+ e.preventDefault();
108
+ route();
109
+ return;
110
+ }
111
+ if (e.key === "t") {
112
+ e.preventDefault();
113
+ $("#theme-toggle").click();
114
+ return;
115
+ }
116
+ if (e.key === "l") {
117
+ e.preventDefault();
118
+ cycleLang();
119
+ return;
120
+ }
121
+ if (e.key === "?") {
122
+ e.preventDefault();
123
+ showShortcuts();
124
+ }
125
+ });
126
+ }
@@ -1,118 +1,121 @@
1
- "use strict";
2
- /* 99-boot.js — orc ui client
3
- MUST LOAD LAST. `boot()` is the one load-time call in the panel, and it reads
4
- bindings from every file above — a classic-script `const` is in TDZ until its
5
- own file has been evaluated.
6
-
7
- Loaded by app.html in the order its numeric prefix names. Classic
8
- script, no import/export: an ES module import carries no query string,
9
- and every static request here needs the per-launch session token. */
10
-
11
-
12
- /* ================================================================= startup == */
13
-
14
- async function boot() {
15
- // Language first, and English is loaded UNCONDITIONALLY: it is the fallback
16
- // table every other language falls back to, so it must exist before the first
17
- // t() call regardless of which language is selected. If even English cannot be
18
- // fetched, t() returns the key and the page is ugly but functional — never
19
- // blank, and never blocked on a file.
20
- try {
21
- DICT_EN = await loadLang("en");
22
- } catch (_) {
23
- DICT_EN = {};
24
- }
25
- let savedLang = "en";
26
- try {
27
- savedLang = localStorage.getItem(LANG_KEY) || "en";
28
- } catch (_) {}
29
- // No rerender: nothing has been routed yet, and route() is called below.
30
- await setLang(savedLang, { rerender: false });
31
-
32
- // Meta next: it names the project in the rail and tells us whether we are
33
- // looking at fixtures, which must never be mistaken for a real install.
34
- try {
35
- const meta = await api("/api/meta");
36
- metaInfo = meta;
37
- const proj = $("#rail-project");
38
- proj.textContent = meta.fixtures ? t("rail.fixtures") : meta.project_root || "";
39
- proj.title = meta.project_root || "";
40
- $("#rail-version").textContent = (meta.fixtures ? "fixtures · " : "") + "v" + (meta.version || "?");
41
-
42
- // A newer release is worth ONE quiet dot in the rail, on every panel — not a
43
- // banner, not a modal. It links to the panel that can actually install it;
44
- // it never installs anything itself.
45
- versionInfo()
46
- .then((v) => {
47
- if (!v || !v.update_available) return;
48
- const link = el("a", "rail-update", "");
49
- link.href = "#/maintenance";
50
- link.append(el("span", "dot dot-warn"), document.createTextNode(`v${v.latest} available`));
51
- link.title = `You have ${v.version}. Maintenance → upgrade installs ${v.latest}.`;
52
- $("#rail-version").after(link);
53
- })
54
- .catch(() => {});
55
- if (meta.fixtures) {
56
- const b = el("div", "banner");
57
- b.append(el("div", null, t("banner.fixtures")));
58
- $("#banners").append(b);
59
- }
60
- } catch (_) {
61
- document.body.replaceChildren(
62
- (() => {
63
- const e2 = el("div", "empty", t("banner.noToken"));
64
- e2.append(el("div", "note", t("banner.noTokenHint")));
65
- return e2;
66
- })()
67
- );
68
- return;
69
- }
70
-
71
- // Theme: dark-first, remembered, and both painted explicitly.
72
- const saved = localStorage.getItem("orc-ui-theme");
73
- if (saved) document.documentElement.setAttribute("data-theme", saved);
74
- const tt = $("#theme-toggle");
75
- const syncTheme = () => (tt.textContent = document.documentElement.getAttribute("data-theme") === "light" ? t("rail.dark") : t("rail.light"));
76
- syncTheme();
77
- tt.addEventListener("click", () => {
78
- const next = document.documentElement.getAttribute("data-theme") === "light" ? "dark" : "light";
79
- document.documentElement.setAttribute("data-theme", next);
80
- localStorage.setItem("orc-ui-theme", next);
81
- syncTheme();
82
- });
83
-
84
- // Language, right below it in the rail: the same class of control (a
85
- // per-browser display preference), so it lives in the same place and is
86
- // remembered the same way. It never touches project config.
87
- const lb = $("#lang-toggle");
88
- if (lb) lb.addEventListener("click", cycleLang);
89
- applyStaticText();
90
-
91
- installShortcuts();
92
- const help = $("#shortcut-hint");
93
- if (help) help.addEventListener("click", showShortcuts);
94
-
95
- window.addEventListener("hashchange", route);
96
- route();
97
-
98
- // First run for THIS project → the tour. Fixture mode is excluded: a tour of
99
- // canned data would teach the panel using numbers that are not real.
100
- if (!metaInfo.fixtures && !tourSeen(metaInfo.project_root)) {
101
- // Let the first panel finish its fetch, so step one has something to point
102
- // at rather than a skeleton.
103
- setTimeout(() => startFirstRunTour(metaInfo.project_root), 600);
104
- }
105
-
106
- // Heartbeat: no ping from any client for 60s and the server exits, so closing
107
- // this tab shuts down a write surface instead of leaving it holding a token.
108
- const ping = () => api("/api/ping").catch(() => {});
109
- ping();
110
- setInterval(ping, 15000);
111
- window.addEventListener("beforeunload", () => {
112
- try {
113
- navigator.sendBeacon("/api/bye?t=" + encodeURIComponent(TOKEN));
114
- } catch (_) {}
115
- });
116
- }
117
-
118
- boot();
1
+ "use strict";
2
+ /* 99-boot.js — orc ui client
3
+ MUST LOAD LAST. `boot()` is the one load-time call in the panel, and it reads
4
+ bindings from every file above — a classic-script `const` is in TDZ until its
5
+ own file has been evaluated.
6
+
7
+ Loaded by app.html in the order its numeric prefix names. Classic
8
+ script, no import/export: an ES module import carries no query string,
9
+ and every static request here needs the per-launch session token. */
10
+
11
+
12
+ /* ================================================================= startup == */
13
+
14
+ async function boot() {
15
+ // Language first, and English is loaded UNCONDITIONALLY: it is the fallback
16
+ // table every other language falls back to, so it must exist before the first
17
+ // t() call regardless of which language is selected. If even English cannot be
18
+ // fetched, t() returns the key and the page is ugly but functional — never
19
+ // blank, and never blocked on a file.
20
+ try {
21
+ DICT_EN = await loadLang("en");
22
+ } catch (_) {
23
+ DICT_EN = {};
24
+ }
25
+ let savedLang = "en";
26
+ try {
27
+ savedLang = localStorage.getItem(LANG_KEY) || "en";
28
+ } catch (_) {}
29
+ // No rerender: nothing has been routed yet, and route() is called below.
30
+ await setLang(savedLang, { rerender: false });
31
+
32
+ // Meta next: it names the project in the rail and tells us whether we are
33
+ // looking at fixtures, which must never be mistaken for a real install.
34
+ try {
35
+ const meta = await api("/api/meta");
36
+ metaInfo = meta;
37
+ const proj = $("#rail-project");
38
+ proj.textContent = meta.fixtures ? t("rail.fixtures") : meta.project_root || "";
39
+ proj.title = meta.project_root || "";
40
+ $("#rail-version").textContent = (meta.fixtures ? "fixtures · " : "") + "v" + (meta.version || "?");
41
+
42
+ // A newer release is worth ONE quiet dot in the rail, on every panel — not a
43
+ // banner, not a modal. It links to the panel that can actually install it;
44
+ // it never installs anything itself.
45
+ versionInfo()
46
+ .then((v) => {
47
+ if (!v || !v.update_available) return;
48
+ const link = el("a", "rail-update", "");
49
+ link.href = "#/maintenance";
50
+ link.append(el("span", "dot dot-warn"), document.createTextNode(`v${v.latest} available`));
51
+ link.title = `You have ${v.version}. Maintenance → upgrade installs ${v.latest}.`;
52
+ $("#rail-version").after(link);
53
+ })
54
+ .catch(() => {});
55
+ if (meta.fixtures) {
56
+ const b = el("div", "banner");
57
+ b.append(el("div", null, t("banner.fixtures")));
58
+ $("#banners").append(b);
59
+ }
60
+ } catch (_) {
61
+ document.body.replaceChildren(
62
+ (() => {
63
+ const e2 = el("div", "empty", t("banner.noToken"));
64
+ e2.append(el("div", "note", t("banner.noTokenHint")));
65
+ return e2;
66
+ })()
67
+ );
68
+ return;
69
+ }
70
+
71
+ // Theme: dark-first, remembered, and both painted explicitly.
72
+ const saved = localStorage.getItem("orc-ui-theme");
73
+ if (saved) document.documentElement.setAttribute("data-theme", saved);
74
+ const tt = $("#theme-toggle");
75
+ const syncTheme = () => (tt.textContent = document.documentElement.getAttribute("data-theme") === "light" ? t("rail.dark") : t("rail.light"));
76
+ syncTheme();
77
+ tt.addEventListener("click", () => {
78
+ const next = document.documentElement.getAttribute("data-theme") === "light" ? "dark" : "light";
79
+ document.documentElement.setAttribute("data-theme", next);
80
+ localStorage.setItem("orc-ui-theme", next);
81
+ syncTheme();
82
+ });
83
+
84
+ // Language, right below it in the rail: the same class of control (a
85
+ // per-browser display preference), so it lives in the same place and is
86
+ // remembered the same way. It never touches project config.
87
+ const lb = $("#lang-toggle");
88
+ if (lb) lb.addEventListener("click", cycleLang);
89
+ applyStaticText();
90
+
91
+ installShortcuts();
92
+ const help = $("#shortcut-hint");
93
+ if (help) help.addEventListener("click", showShortcuts);
94
+
95
+ window.addEventListener("hashchange", route);
96
+ route();
97
+ // v2.0.0 W7 — a waiting habit proposal is ONE quiet dot on the Behaviour rail
98
+ // link. It is the only place outside that panel that shows habit state.
99
+ behaviourRailDot();
100
+
101
+ // First run for THIS project → the tour. Fixture mode is excluded: a tour of
102
+ // canned data would teach the panel using numbers that are not real.
103
+ if (!metaInfo.fixtures && !tourSeen(metaInfo.project_root)) {
104
+ // Let the first panel finish its fetch, so step one has something to point
105
+ // at rather than a skeleton.
106
+ setTimeout(() => startFirstRunTour(metaInfo.project_root), 600);
107
+ }
108
+
109
+ // Heartbeat: no ping from any client for 60s and the server exits, so closing
110
+ // this tab shuts down a write surface instead of leaving it holding a token.
111
+ const ping = () => api("/api/ping").catch(() => {});
112
+ ping();
113
+ setInterval(ping, 15000);
114
+ window.addEventListener("beforeunload", () => {
115
+ try {
116
+ navigator.sendBeacon("/api/bye?t=" + encodeURIComponent(TOKEN));
117
+ } catch (_) {}
118
+ });
119
+ }
120
+
121
+ boot();