@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.
- package/CHANGELOG.md +390 -0
- package/README-id.md +20 -36
- package/README.md +24 -34
- package/bin/build-agents.js +206 -109
- package/bin/cli.js +760 -62
- package/bin/gotcha-import.js +1081 -0
- package/bin/gotcha.js +1286 -0
- package/bin/graph-query.js +1 -1
- package/bin/graph.js +717 -717
- package/bin/habit.js +1453 -0
- package/bin/mockrun-catalog.js +281 -276
- package/bin/onboarding-content.js +4 -4
- package/bin/pricing.json +207 -200
- package/bin/run-undo.js +398 -0
- package/bin/trace-write.js +657 -0
- package/bin/verify-contracts.js +527 -81
- package/bin/verify-package.js +58 -11
- package/bin/webui/api.js +26 -0
- package/bin/webui/app.html +239 -232
- package/bin/webui/css/00-tokens.css +110 -92
- package/bin/webui/css/04-motion.css +249 -152
- package/bin/webui/css/06-responsive.css +203 -178
- package/bin/webui/css/panels/behaviour.css +205 -0
- package/bin/webui/css/panels/knowledge.css +563 -116
- package/bin/webui/fixtures/behaviour.js +532 -0
- package/bin/webui/fixtures/extra.js +2036 -2036
- package/bin/webui/fixtures/hookui.js +5 -5
- package/bin/webui/fixtures/index.js +34 -0
- package/bin/webui/fixtures/knowledge.js +7 -1
- package/bin/webui/fixtures/settings.js +305 -305
- package/bin/webui/fixtures/stats.js +16 -0
- package/bin/webui/i18n/en/behaviour.json +143 -0
- package/bin/webui/i18n/en/knowledge.json +117 -2
- package/bin/webui/i18n/en/nav.json +25 -24
- package/bin/webui/i18n/en/tour.json +37 -35
- package/bin/webui/i18n/id/behaviour.json +143 -0
- package/bin/webui/i18n/id/knowledge.json +117 -2
- package/bin/webui/i18n/id/nav.json +25 -24
- package/bin/webui/i18n/id/tour.json +37 -35
- package/bin/webui/js/01-i18n.js +155 -154
- package/bin/webui/js/90-tour.js +498 -494
- package/bin/webui/js/91-shortcuts.js +126 -126
- package/bin/webui/js/99-boot.js +121 -118
- package/bin/webui/js/panels/behaviour.js +1022 -0
- package/bin/webui/js/panels/knowledge.js +552 -7
- package/bin/webui/js/panels/overview.js +13 -4
- package/mock-run/INDEX.md +109 -107
- package/mock-run/context-combiner.md +100 -100
- package/mock-run/gotcha-import.md +118 -0
- package/mock-run/habits.md +129 -0
- package/mock-run/orc-budget.md +534 -534
- package/mock-run/orc-challenge-council.md +262 -262
- package/mock-run/orc-quick.md +6 -1
- package/mock-run/orc-ultra.md +103 -103
- package/package.json +1 -1
- package/templates/agents/MODEL-MAPPING.md +49 -49
- package/templates/agents/orc-advisor-opus-5-xhigh.md +50 -56
- package/templates/agents/orc-analyze-mini-opus-5-med.md +55 -60
- package/templates/agents/orc-analyze-mini-sonnet-5-high.md +55 -58
- package/templates/agents/orc-challenge-advisor-opus-5-med.md +75 -75
- package/templates/agents/orc-challenge-contrarian-opus-5-high.md +110 -110
- package/templates/agents/orc-challenge-executor-opus-5-med.md +114 -114
- package/templates/agents/orc-challenge-expansionist-opus-5-med.md +112 -112
- package/templates/agents/orc-challenge-judge-opus-5-high.md +132 -132
- package/templates/agents/orc-challenge-outsider-opus-5-low.md +109 -109
- package/templates/agents/orc-challenge-principles-opus-5-high.md +109 -109
- package/templates/agents/orc-challenge-reader-opus-5-low.md +90 -90
- package/templates/agents/orc-claude-writer-opus-4-8-high.md +48 -53
- package/templates/agents/orc-claude-writer-opus-5-med.md +48 -55
- package/templates/agents/orc-context-combiner-opus-5-high.md +78 -88
- package/templates/agents/orc-doc-checker-opus-5-low.md +108 -108
- package/templates/agents/orc-doc-writer-opus-5-med.md +134 -134
- package/templates/agents/orc-executor-haiku-4-5.md +14 -6
- package/templates/agents/orc-executor-opus-4-7-high.md +14 -6
- package/templates/agents/orc-executor-opus-4-7-med.md +14 -6
- package/templates/agents/orc-executor-opus-4-8-high.md +14 -6
- package/templates/agents/orc-executor-opus-5-high.md +15 -7
- package/templates/agents/orc-executor-opus-5-low.md +15 -7
- package/templates/agents/orc-executor-opus-5-med.md +15 -7
- package/templates/agents/orc-executor-sonnet-4-6-high.md +14 -6
- package/templates/agents/orc-executor-sonnet-4-6-med.md +14 -6
- package/templates/agents/orc-executor-sonnet-5-high.md +14 -6
- package/templates/agents/orc-graph-noter-sonnet-4-6-med.md +1 -10
- package/templates/agents/orc-judge-opus-5-xhigh.md +81 -85
- package/templates/agents/orc-learn-writer-opus-5-low.md +67 -73
- package/templates/agents/orc-pattern-codifier-opus-5-med.md +58 -65
- package/templates/agents/orc-pattern-codifier-sonnet-5-high.md +58 -63
- package/templates/agents/orc-planner-mini-opus-5-med.md +4 -7
- package/templates/agents/orc-planner-mini-sonnet-5-high.md +2 -3
- package/templates/agents/orc-planner-opus-5-med.md +157 -160
- package/templates/agents/orc-recon-opus-5-low.md +3 -10
- package/templates/agents/orc-recon-sonnet-4-6-med.md +1 -8
- package/templates/agents/orc-retro-opus-5-med.md +8 -10
- package/templates/agents/orc-retro-sonnet-5-high.md +6 -7
- package/templates/agents/orc-reviewer-opus-5-med.md +96 -60
- package/templates/agents/orc-scout-opus-5-low.md +35 -40
- package/templates/agents/orc-scout-sonnet-4-6-high.md +35 -39
- package/templates/agents/orc-system-analyst-opus-5-high.md +115 -120
- package/templates/agents/orc-test-author-opus-5-med.md +70 -71
- package/templates/agents/orc-test-designer-opus-5-high.md +158 -158
- package/templates/agents/orc-test-interpreter-opus-5-low.md +130 -130
- package/templates/agents/orc-trace-writer-haiku-4-5.md +3 -7
- package/templates/agents/orc-verifier-opus-5-med.md +77 -69
- package/templates/agents/orc-wiki-scanner-opus-4-8-high.md +74 -79
- package/templates/agents/orc-wiki-scanner-opus-5-med.md +74 -81
- package/templates/agents/orc-wiki-scanner-sonnet-5-high.md +97 -106
- package/templates/commands/orc-analyze.md +13 -21
- package/templates/commands/orc-fast.md +10 -15
- package/templates/commands/orc-poly.md +12 -21
- package/templates/commands/orc-pr-driver.md +11 -30
- package/templates/commands/orc-pr-setup.md +10 -31
- package/templates/commands/orc-route.md +11 -41
- package/templates/commands/orc-test.md +5 -60
- package/templates/commands/orc-ultra.md +17 -17
- package/templates/commands/orc-verify.md +11 -11
- package/templates/hooks/README.md +36 -2
- package/templates/hooks/orc-effort-guard.js +178 -178
- package/templates/hooks/orc-session-hook.js +264 -0
- package/templates/hooks/orc-statusline.js +9 -7
- package/templates/skills/_shared/README.md +9 -0
- package/templates/skills/_shared/code-graph.md +48 -56
- package/templates/skills/_shared/config-precedence.md +200 -198
- package/templates/skills/_shared/extra-dispatch.md +1331 -1346
- package/templates/skills/_shared/gotchas.md +228 -177
- package/templates/skills/_shared/habits.md +101 -0
- package/templates/skills/_shared/lane-contract.md +84 -0
- package/templates/skills/_shared/opus5-only.md +8 -8
- package/templates/skills/_shared/phases/README.md +142 -83
- package/templates/skills/_shared/phases/analyst-gates.md +125 -136
- package/templates/skills/_shared/phases/execution.md +8 -14
- package/templates/skills/_shared/phases/house-rules.md +27 -32
- package/templates/skills/_shared/phases/intake.md +127 -133
- package/templates/skills/_shared/phases/mock-example.md +46 -56
- package/templates/skills/_shared/phases/plan-handoff.md +91 -97
- package/templates/skills/_shared/phases/planning.md +7 -17
- package/templates/skills/_shared/phases/preflight.md +19 -42
- package/templates/skills/_shared/phases/review.md +23 -27
- package/templates/skills/_shared/phases/rules.md +18 -42
- package/templates/skills/_shared/phases/scoring.md +55 -65
- package/templates/skills/_shared/phases/security-checklist.md +46 -50
- package/templates/skills/_shared/phases/security.md +45 -55
- package/templates/skills/_shared/phases/ship.md +6 -15
- package/templates/skills/_shared/phases/stop-resume.md +2 -5
- package/templates/skills/_shared/phases/summary.md +73 -48
- package/templates/skills/_shared/phases/testgen.md +41 -51
- package/templates/skills/_shared/phases/trace-verbs.md +433 -0
- package/templates/skills/_shared/phases/trace.md +136 -367
- package/templates/skills/_shared/phases/verify.md +62 -70
- package/templates/skills/_shared/phases/wave-grouping.md +128 -133
- package/templates/skills/_shared/phases/wiki-consult.md +10 -6
- package/templates/skills/_shared/read-ladder.md +2 -55
- package/templates/skills/_shared/return-validation.md +17 -70
- package/templates/skills/_shared/review-slice.md +79 -0
- package/templates/skills/_shared/smoke-gate.md +46 -28
- package/templates/skills/context-combiner/SKILL.md +16 -45
- package/templates/skills/context-combiner/schemas/combined-report.md +78 -78
- package/templates/skills/orc/README.md +2 -2
- package/templates/skills/orc/SKILL.md +41 -69
- package/templates/skills/orc/config.md +9 -9
- package/templates/skills/orc/examples/full-run-mock.md +73 -73
- package/templates/skills/orc/references/effort-and-mode.md +222 -222
- package/templates/skills/orc/references/pattern-gate.md +89 -89
- package/templates/skills/orc/references/phases/intake.md +41 -47
- package/templates/skills/orc/references/phases/integration.md +13 -19
- package/templates/skills/orc/references/preflight-report.md +10 -11
- package/templates/skills/orc/references/ultra-mode.md +11 -9
- package/templates/skills/orc/subskills/orc-execution/SKILL.md +27 -73
- package/templates/skills/orc/subskills/orc-execution/core.md +12 -99
- package/templates/skills/orc/subskills/orc-execution/subagent.md +14 -13
- package/templates/skills/orc/subskills/orc-planner/SKILL.md +2 -2
- package/templates/skills/orc/subskills/orc-planner-mini/SKILL.md +121 -121
- package/templates/skills/orc/subskills/orc-review-verify/SKILL.md +35 -76
- package/templates/skills/orc/subskills/orc-review-verify/core.md +52 -135
- package/templates/skills/orc/subskills/orc-review-verify/subagent.md +7 -7
- package/templates/skills/orc/subskills/orc-testgen/SKILL.md +34 -45
- package/templates/skills/orc/subskills/orc-testgen/core.md +20 -59
- package/templates/skills/orc/subskills/orc-testgen/subagent.md +7 -7
- package/templates/skills/orc-advisor/SKILL.md +56 -60
- package/templates/skills/orc-analyze/SKILL.md +32 -68
- package/templates/skills/orc-analyze/examples/analyze-mock.md +42 -42
- package/templates/skills/orc-analyze/schemas/report-audit.md +84 -83
- package/templates/skills/orc-analyze/schemas/report-prose.md +64 -63
- package/templates/skills/orc-analyze/schemas/report-requirement.md +78 -78
- package/templates/skills/orc-analyze-mini/SKILL.md +35 -70
- package/templates/skills/orc-challenge/README.md +142 -142
- package/templates/skills/orc-challenge/examples/council-full-roster.md +273 -273
- package/templates/skills/orc-challenge/references/council.md +315 -315
- package/templates/skills/orc-challenge/references/intake.md +171 -171
- package/templates/skills/orc-claude/SKILL.md +14 -14
- package/templates/skills/orc-diy/README.md +174 -143
- package/templates/skills/orc-diy/SKILL.md +23 -74
- package/templates/skills/orc-diy/references/blocks/pattern.md +18 -18
- package/templates/skills/orc-diy/references/flow-schema.md +1 -1
- package/templates/skills/orc-doc/README.md +229 -229
- package/templates/skills/orc-doc/examples/orc-doc-prd-run.md +325 -325
- package/templates/skills/orc-doc/references/chunking.md +527 -527
- package/templates/skills/orc-fast/SKILL.md +45 -73
- package/templates/skills/orc-judge/SKILL.md +77 -82
- package/templates/skills/orc-learn/SKILL.md +14 -14
- package/templates/skills/orc-learn/examples/learn-run-mock.md +61 -61
- package/templates/skills/orc-mini/SKILL.md +65 -113
- package/templates/skills/orc-pattern/SKILL.md +27 -48
- package/templates/skills/orc-poly/SKILL.md +32 -61
- package/templates/skills/orc-pr-driver/SKILL.md +25 -51
- package/templates/skills/orc-pr-driver/references/green-gate.md +113 -105
- package/templates/skills/orc-pr-setup/SKILL.md +20 -45
- package/templates/skills/orc-quick/README.md +43 -2
- package/templates/skills/orc-quick/SKILL.md +76 -107
- package/templates/skills/orc-quick/references/dispatch-gate.md +16 -5
- package/templates/skills/orc-quick/references/gh-mode.md +48 -1
- package/templates/skills/orc-quick/references/look.md +3 -1
- package/templates/skills/orc-retro/SKILL.md +19 -18
- package/templates/skills/orc-retro/examples/retro-mock.md +1 -1
- package/templates/skills/orc-route/SKILL.md +25 -45
- package/templates/skills/orc-test/SKILL.md +16 -37
- package/templates/skills/orc-verify/SKILL.md +21 -39
- package/templates/skills/orc-verify/examples/verify-mock.md +33 -33
- package/templates/skills/orc-wait/SKILL.md +156 -163
- package/templates/skills/orc-wiki/references/extra.md +1 -1
- package/templates/skills/orc-wiki/references/phases/phase-0.md +1 -6
- package/templates/skills/orc-wiki/references/phases/phase-1.md +1 -6
- package/templates/skills/orc-wiki/references/phases/phase-2.md +1 -6
- package/templates/skills/orc-wiki/references/phases/phase-3.md +1 -6
- 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
|
+
}
|
package/bin/webui/js/99-boot.js
CHANGED
|
@@ -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
|
-
//
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
ping
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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();
|