@azure-id/orc 1.5.0 → 1.7.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 (74) hide show
  1. package/CHANGELOG.md +185 -0
  2. package/README-id.md +206 -125
  3. package/README.md +270 -57
  4. package/bin/cli.js +1676 -2
  5. package/bin/mockrun-catalog.js +272 -267
  6. package/bin/verify-contracts.js +4485 -4449
  7. package/bin/verify-package.js +9 -0
  8. package/bin/webui/api.js +26 -0
  9. package/bin/webui/app.html +10 -0
  10. package/bin/webui/css/panels/knowledge.css +30 -0
  11. package/bin/webui/css/panels/rules.css +145 -0
  12. package/bin/webui/fixtures/index.js +27 -0
  13. package/bin/webui/fixtures/rules.js +1002 -0
  14. package/bin/webui/fixtures/wiki-one.js +198 -0
  15. package/bin/webui/i18n/en/knowledge.json +127 -117
  16. package/bin/webui/i18n/en/nav.json +1 -0
  17. package/bin/webui/i18n/en/overview.json +1 -0
  18. package/bin/webui/i18n/en/rules.json +55 -0
  19. package/bin/webui/i18n/id/knowledge.json +127 -117
  20. package/bin/webui/i18n/id/nav.json +1 -0
  21. package/bin/webui/i18n/id/overview.json +1 -0
  22. package/bin/webui/i18n/id/rules.json +55 -0
  23. package/bin/webui/js/01-i18n.js +1 -0
  24. package/bin/webui/js/panels/knowledge.js +117 -1
  25. package/bin/webui/js/panels/overview.js +8 -0
  26. package/bin/webui/js/panels/rules.js +351 -0
  27. package/mock-run/INDEX.md +107 -106
  28. package/mock-run/orc-rules.md +254 -0
  29. package/package.json +1 -1
  30. package/templates/commands/orc-rules.md +66 -0
  31. package/templates/commands/orc-wiki.md +23 -1
  32. package/templates/hooks/README.md +110 -1
  33. package/templates/hooks/orc-read-gate.js +279 -0
  34. package/templates/skills/_shared/README.md +61 -54
  35. package/templates/skills/_shared/phases/README.md +1 -0
  36. package/templates/skills/_shared/phases/preflight.md +20 -0
  37. package/templates/skills/_shared/phases/rules.md +154 -0
  38. package/templates/skills/_shared/return-validation.md +28 -0
  39. package/templates/skills/_shared/rules/CREDITS.md +141 -0
  40. package/templates/skills/_shared/rules/INDEX.md +107 -0
  41. package/templates/skills/_shared/rules/code.md +229 -0
  42. package/templates/skills/_shared/rules/delivery.md +114 -0
  43. package/templates/skills/_shared/rules/ui.md +139 -0
  44. package/templates/skills/_shared/rules/writing.md +223 -0
  45. package/templates/skills/context-combiner/SKILL.md +9 -1
  46. package/templates/skills/orc/SKILL.md +7 -0
  47. package/templates/skills/orc-aftermath/SKILL.md +7 -0
  48. package/templates/skills/orc-analyze/SKILL.md +7 -0
  49. package/templates/skills/orc-analyze-mini/SKILL.md +9 -1
  50. package/templates/skills/orc-boundary/SKILL.md +7 -0
  51. package/templates/skills/orc-brainstorm/SKILL.md +7 -0
  52. package/templates/skills/orc-budget/SKILL.md +7 -0
  53. package/templates/skills/orc-challenge/SKILL.md +7 -0
  54. package/templates/skills/orc-claude/SKILL.md +7 -0
  55. package/templates/skills/orc-diy/SKILL.md +7 -0
  56. package/templates/skills/orc-explain/SKILL.md +7 -0
  57. package/templates/skills/orc-export/SKILL.md +7 -0
  58. package/templates/skills/orc-fast/SKILL.md +7 -0
  59. package/templates/skills/orc-grill/SKILL.md +7 -0
  60. package/templates/skills/orc-handoff/SKILL.md +9 -1
  61. package/templates/skills/orc-learn/SKILL.md +7 -0
  62. package/templates/skills/orc-mini/SKILL.md +7 -0
  63. package/templates/skills/orc-pact/SKILL.md +7 -0
  64. package/templates/skills/orc-poly/SKILL.md +7 -0
  65. package/templates/skills/orc-pr-driver/SKILL.md +9 -1
  66. package/templates/skills/orc-pr-setup/SKILL.md +9 -1
  67. package/templates/skills/orc-quick/SKILL.md +7 -0
  68. package/templates/skills/orc-retro/SKILL.md +7 -0
  69. package/templates/skills/orc-route/SKILL.md +7 -0
  70. package/templates/skills/orc-test/SKILL.md +7 -0
  71. package/templates/skills/orc-verify/SKILL.md +7 -0
  72. package/templates/skills/orc-wiki/SKILL.md +15 -0
  73. package/templates/skills/orc-wiki/references/partial-refresh.md +68 -0
  74. package/templates/skills/orc-wiki/references/phases/phase-0.md +15 -1
@@ -33,6 +33,7 @@ const required = [
33
33
  "bin/webui/css/panels/overview.css",
34
34
  "bin/webui/css/panels/settings.css",
35
35
  "bin/webui/css/panels/lanes.css",
36
+ "bin/webui/css/panels/rules.css",
36
37
  "bin/webui/css/panels/runs.css",
37
38
  "bin/webui/css/panels/knowledge.css",
38
39
  // No knowledge.css: that panel is composed entirely from shared primitives
@@ -66,6 +67,7 @@ const required = [
66
67
  "bin/webui/js/panels/overview.js",
67
68
  "bin/webui/js/panels/settings.js",
68
69
  "bin/webui/js/panels/lanes.js",
70
+ "bin/webui/js/panels/rules.js",
69
71
  "bin/webui/js/panels/runs.js",
70
72
  "bin/webui/js/panels/knowledge.js",
71
73
  "bin/webui/js/panels/stats.js",
@@ -93,6 +95,8 @@ const required = [
93
95
  "bin/webui/fixtures/shell.js",
94
96
  "bin/webui/fixtures/settings.js",
95
97
  "bin/webui/fixtures/lanes.js",
98
+ "bin/webui/fixtures/rules.js",
99
+ "bin/webui/fixtures/wiki-one.js",
96
100
  "bin/webui/fixtures/knowledge.js",
97
101
  "bin/webui/fixtures/runs.js",
98
102
  "bin/webui/fixtures/stats.js",
@@ -122,6 +126,7 @@ const required = [
122
126
  "bin/webui/i18n/en/overview.json",
123
127
  "bin/webui/i18n/en/settings.json",
124
128
  "bin/webui/i18n/en/lanes.json",
129
+ "bin/webui/i18n/en/rules.json",
125
130
  "bin/webui/i18n/en/runs.json",
126
131
  "bin/webui/i18n/en/knowledge.json",
127
132
  "bin/webui/i18n/en/stats.json",
@@ -147,6 +152,7 @@ const required = [
147
152
  "bin/webui/i18n/id/overview.json",
148
153
  "bin/webui/i18n/id/settings.json",
149
154
  "bin/webui/i18n/id/lanes.json",
155
+ "bin/webui/i18n/id/rules.json",
150
156
  "bin/webui/i18n/id/runs.json",
151
157
  "bin/webui/i18n/id/knowledge.json",
152
158
  "bin/webui/i18n/id/stats.json",
@@ -480,6 +486,9 @@ const required = [
480
486
  // it. Wired even with the board off, because the measurement is handed over
481
487
  // either way.
482
488
  "templates/hooks/orc-subagent-line.js",
489
+ // v1.6.0 — the read gate. The one layer that can refuse an oversized read by
490
+ // the ORCHESTRATOR. Ships wired but OFF; `read_gate` arms it.
491
+ "templates/hooks/orc-read-gate.js",
483
492
  "templates/hooks/orc-trace.js",
484
493
  ];
485
494
 
package/bin/webui/api.js CHANGED
@@ -363,6 +363,21 @@ const READS = {
363
363
  // nothing about a priority, an order, a wave shape or a number.
364
364
  "/api/doc/rules": () => ["doc", "rules"],
365
365
  "/api/doc/rules/one": (q) => ["doc", "rules", String(q.slug || "")],
366
+ // v1.7.0 — the anti-slop rule surface. Five READS. The panel decides nothing:
367
+ // not the precedence order, not a rule's tier, not the override count, and
368
+ // not which of the 65 rules the lint can actually prove.
369
+ //
370
+ // `lint` takes a path from the query string. It is user input like any other,
371
+ // so it is forwarded as ONE argv element and never through a shell — the same
372
+ // reason every other route here spawns an array rather than a string.
373
+ "/api/rules": () => ["rules"],
374
+ "/api/rules/user": () => ["rules", "user"],
375
+ "/api/rules/packs": () => ["rules", "packs"],
376
+ "/api/rules/credits": () => ["rules", "credits"],
377
+ "/api/rules/lint": (q) => ["rules", "lint", String(q.path || ".")],
378
+ // v1.7.0 — the wiki's one-doc-at-a-time probes. Both free, neither scans.
379
+ "/api/wiki/resolve": (q) => ["wiki", "resolve", String(q.topic || "")],
380
+ "/api/wiki/refs": () => ["wiki", "refs", "--check"],
366
381
  "/api/doc/forecast": (q) => ["doc", "forecast", String(q.slug || "")],
367
382
  "/api/doc/cost": (q) => ["doc", "cost", String(q.slug || "")],
368
383
  // v0.50.0 — `orc extra`. Every one is a READ, and every one is a subprocess of
@@ -592,6 +607,17 @@ const WRITES = {
592
607
  // house rule looks like, and the argv is a plain array, so a multi-line value
593
608
  // needs no escaping and no temp file.
594
609
  "/api/doc/rules/setAll": (b) => ["doc", "rules", "set-all", "--text", String(b.text || "")],
610
+ // v1.7.0 — the project's own anti-slop rules. ONE write route, for the same
611
+ // reason the doc ledger has one: it is a plain text config, so the panel
612
+ // writes the whole file from one textarea and the CLI is still the only
613
+ // writer and the only validator.
614
+ //
615
+ // There is deliberately NO route for the SHIPPED packs. They are read-only,
616
+ // `orc rules set --pack …` is refused by name, and a route that existed only
617
+ // to be refused would be a control that lies about what it can do.
618
+ // `--reset` also has no route: throwing away a project's standing rules is a
619
+ // CLI act.
620
+ "/api/rules/setAll": (b) => ["rules", "set-all", "--text", String(b.text || "")],
595
621
  "/api/doc/rules/sync": (b) => ["doc", "rules", String(b.slug), "--sync"],
596
622
  // v0.52.0 (D9) — per document, because a document's voice is the deliverable.
597
623
  // The CLI owns the resolution order and the shadowing announcement; the panel
@@ -25,6 +25,7 @@
25
25
  <link rel="stylesheet" href="css/05-tour.css">
26
26
  <link rel="stylesheet" href="css/panels/settings.css">
27
27
  <link rel="stylesheet" href="css/panels/lanes.css">
28
+ <link rel="stylesheet" href="css/panels/rules.css">
28
29
  <link rel="stylesheet" href="css/panels/runs.css">
29
30
  <link rel="stylesheet" href="css/panels/knowledge.css">
30
31
  <link rel="stylesheet" href="css/panels/stats.css">
@@ -80,6 +81,14 @@
80
81
  which shared phases they run, in order, and which CLI calls they make.
81
82
  -->
82
83
  <li><a href="#/lanes" data-panel="lanes" data-idx="l" data-i18n="nav.lanes">Lanes</a></li>
84
+ <!--
85
+ v1.7.0. Rules sits directly under Lanes because it is the other half of
86
+ the same answer: Lanes says which phases a lane runs, this says which
87
+ rules ride in every slice it builds — and it is the one panel here where
88
+ a project can change what ORC writes, so it belongs with Settings and
89
+ Lanes rather than down among the reading panels.
90
+ -->
91
+ <li><a href="#/rules" data-panel="rules" data-idx="r" data-i18n="nav.rules">Rules</a></li>
83
92
  <li><a href="#/runs" data-panel="runs" data-idx="3" data-i18n="nav.runs">Runs</a></li>
84
93
  <li><a href="#/knowledge" data-panel="knowledge" data-idx="4" data-i18n="nav.knowledge">Knowledge</a></li>
85
94
  <li><a href="#/stats" data-panel="stats" data-idx="5" data-i18n="nav.stats">Stats</a></li>
@@ -197,6 +206,7 @@
197
206
  <script src="js/panels/overview.js"></script>
198
207
  <script src="js/panels/settings.js"></script>
199
208
  <script src="js/panels/lanes.js"></script>
209
+ <script src="js/panels/rules.js"></script>
200
210
  <script src="js/panels/runs.js"></script>
201
211
  <script src="js/panels/knowledge.js"></script>
202
212
  <script src="js/panels/stats.js"></script>
@@ -84,3 +84,33 @@
84
84
  /* --- preview-then-apply --------------------------------------------------- */
85
85
  .kn-prune { margin-top: var(--sp-3); display: grid; gap: var(--sp-2); }
86
86
  .kn-prune-head { font-weight: 600; font-size: 13px; }
87
+
88
+ /* ── one doc at a time (v1.7.0) ───────────────────────────────────────────── */
89
+ /* The resolver and the derived-reference sweep. Both are probes, so the card is
90
+ read-shaped: a row of results, and a command where a lane would have to run. */
91
+ .kn-one-topic { flex: 1 1 260px; min-width: 0; }
92
+ .kn-one-out { margin-top: var(--sp-2); display: flex; flex-direction: column; gap: 4px; }
93
+ .kn-one-cand {
94
+ display: flex;
95
+ flex-wrap: wrap;
96
+ gap: var(--sp-1) var(--sp-2);
97
+ align-items: baseline;
98
+ padding-left: var(--sp-2);
99
+ }
100
+ .kn-one-sweep {
101
+ margin-top: var(--sp-3);
102
+ border-top: 1px solid var(--line-soft);
103
+ padding-top: var(--sp-2);
104
+ }
105
+ .kn-one-ref {
106
+ display: flex;
107
+ flex-wrap: wrap;
108
+ gap: var(--sp-1) var(--sp-2);
109
+ align-items: baseline;
110
+ padding: 3px 0;
111
+ }
112
+ .kn-one-fix { padding-left: var(--sp-4); }
113
+
114
+ @media (max-width: 720px) {
115
+ .kn-one-ref, .kn-one-cand { flex-direction: column; align-items: flex-start; gap: 2px; }
116
+ }
@@ -0,0 +1,145 @@
1
+ /* panels/rules.css — the anti-slop rule surface.
2
+ Classes are namespaced `orule-` rather than `rule-`: the Docs panel already
3
+ owns `.rule-editor` / `.rule-path` / `.rule-boundary` for its own house-rule
4
+ card, and two panels sharing a class name is a coupling nothing declares. */
5
+
6
+ /* ── the precedence ladder ────────────────────────────────────────────────── */
7
+ /* First card on the page, always open. Precedence is the one thing people get
8
+ wrong about this surface, so it is never behind a toggle. */
9
+ .orule-ladder {
10
+ display: flex;
11
+ flex-direction: column;
12
+ gap: var(--sp-2);
13
+ margin: var(--sp-2) 0;
14
+ }
15
+ .orule-ladder-row {
16
+ display: flex;
17
+ gap: var(--sp-2);
18
+ align-items: flex-start;
19
+ padding: var(--sp-2);
20
+ border: 1px solid var(--line-soft);
21
+ border-radius: 6px;
22
+ background: var(--bg-soft, transparent);
23
+ }
24
+ .orule-rank {
25
+ flex: 0 0 auto;
26
+ width: 22px;
27
+ height: 22px;
28
+ display: grid;
29
+ place-items: center;
30
+ border-radius: 50%;
31
+ border: 1px solid var(--line);
32
+ font-size: 12px;
33
+ font-variant-numeric: tabular-nums;
34
+ }
35
+ .orule-ladder-body { flex: 1 1 auto; min-width: 0; }
36
+ .orule-layer { font-weight: 600; }
37
+ .orule-where { word-break: break-all; }
38
+ .orule-house-note {
39
+ border-left: 2px solid var(--accent);
40
+ padding-left: var(--sp-2);
41
+ margin: var(--sp-2) 0;
42
+ }
43
+ .orule-overrides {
44
+ margin-top: var(--sp-3);
45
+ border-top: 1px solid var(--line-soft);
46
+ padding-top: var(--sp-2);
47
+ }
48
+ .orule-override-row {
49
+ display: flex;
50
+ flex-wrap: wrap;
51
+ gap: var(--sp-1) var(--sp-2);
52
+ align-items: baseline;
53
+ padding: 3px 0;
54
+ }
55
+ .orule-boundary {
56
+ margin-top: var(--sp-3);
57
+ border-top: 1px solid var(--line-soft);
58
+ padding-top: var(--sp-2);
59
+ }
60
+
61
+ /* ── the project's own ledger ─────────────────────────────────────────────── */
62
+ .orule-editor {
63
+ width: 100%;
64
+ box-sizing: border-box;
65
+ margin: var(--sp-2) 0 var(--sp-1);
66
+ padding: var(--sp-2);
67
+ font: 12px/1.6 var(--mono);
68
+ color: var(--fg);
69
+ background: var(--bg-code, var(--bg-soft));
70
+ border: 1px solid var(--line);
71
+ border-radius: 6px;
72
+ resize: vertical;
73
+ tab-size: 2;
74
+ }
75
+ .orule-editor::-webkit-scrollbar { width: 9px; }
76
+ .orule-editor::-webkit-scrollbar-track { background: transparent; }
77
+ .orule-editor::-webkit-scrollbar-thumb { background: var(--line); border-radius: 4px; }
78
+ .orule-editor:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
79
+ .orule-path { word-break: break-all; font-family: var(--mono); }
80
+
81
+ /* ── the shipped packs ────────────────────────────────────────────────────── */
82
+ .orule-filters { margin: var(--sp-2) 0; gap: var(--sp-2); }
83
+ .orule-search { flex: 1 1 220px; min-width: 0; }
84
+ .orule-tier { flex: 0 0 auto; }
85
+ .orule-list { display: flex; flex-direction: column; gap: var(--sp-3); }
86
+ .orule-group { border-bottom: 1px solid var(--line-soft); }
87
+ .orule-group:last-child { border-bottom: 0; }
88
+ .orule-group-head {
89
+ display: flex;
90
+ gap: var(--sp-2);
91
+ align-items: baseline;
92
+ font-weight: 600;
93
+ padding: var(--sp-2) 0;
94
+ cursor: pointer;
95
+ list-style: none;
96
+ }
97
+ .orule-group-head::-webkit-details-marker { display: none; }
98
+ /* The marker is drawn rather than inherited, so it points the same way in every
99
+ browser and stays legible at the small size the rail is set in. */
100
+ .orule-group-head::before {
101
+ content: "\25B8";
102
+ display: inline-block;
103
+ width: 10px;
104
+ color: var(--fg-dim, var(--line));
105
+ transition: transform 120ms ease;
106
+ }
107
+ .orule-group[open] > .orule-group-head::before { transform: rotate(90deg); }
108
+ .orule-group-head:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
109
+ .orule-row {
110
+ padding: var(--sp-2) 0;
111
+ border-bottom: 1px solid var(--line-soft);
112
+ }
113
+ .orule-row:last-child { border-bottom: 0; }
114
+ /* A rule the project replaced is SHOWN, dimmed and labelled. Hiding it would
115
+ make an override invisible in the one place it is explained. */
116
+ .orule-row-off { opacity: 0.55; }
117
+ .orule-row-off .orule-title { text-decoration: line-through; }
118
+ .orule-title { font-weight: 600; }
119
+ .orule-body { white-space: pre-wrap; margin-top: 4px; }
120
+
121
+ /* ── credits ──────────────────────────────────────────────────────────────── */
122
+ .orule-credit {
123
+ padding: var(--sp-2) 0;
124
+ border-bottom: 1px solid var(--line-soft);
125
+ }
126
+ .orule-credit:last-child { border-bottom: 0; }
127
+ .orule-credit-who { font-weight: 600; }
128
+ .orule-credit-link { display: block; word-break: break-all; }
129
+
130
+ /* ── the lint ─────────────────────────────────────────────────────────────── */
131
+ .orule-lint-path { flex: 1 1 240px; min-width: 0; }
132
+ .orule-lint-out { margin-top: var(--sp-2); display: flex; flex-direction: column; gap: var(--sp-1); }
133
+ .orule-lint-file { margin-top: var(--sp-2); font-weight: 600; word-break: break-all; }
134
+ .orule-lint-row { padding-left: var(--sp-3); }
135
+ /* The coverage line is the point of the card, not a footnote. */
136
+ .orule-lint-coverage {
137
+ margin-top: var(--sp-3);
138
+ border-top: 1px solid var(--line-soft);
139
+ padding-top: var(--sp-2);
140
+ }
141
+
142
+ @media (max-width: 720px) {
143
+ .orule-ladder-row { flex-direction: column; }
144
+ .orule-filters { flex-direction: column; align-items: stretch; }
145
+ }
@@ -33,6 +33,8 @@ const { exportState, mocks } = require("./maintenance.js");
33
33
  const { chGoals, chDims, challengeRoles, challengeCouncil, challengeCycles, challengeList, challengeShow, challengeDiff, challengeDiffMissing, challengeLint } = require("./challenge.js");
34
34
  const { docList, docParts, docStatuses, docMapSections, docMap, docLint, docPlan, docShow, docSection, docShipped, docShippedDrifted, docNext, docAudit, docJournalRich, docJournalEmpty, docContext, docRules, docRulesFrozen, docForecast, docCost } = require("./docs.js");
35
35
  const { laneList, lanePhases, laneCalls } = require("./lanes.js");
36
+ const { rules, rulesLint } = require("./rules.js");
37
+ const { wikiResolveNew, wikiResolveMatch, wikiResolveAmbiguous, wikiRefs } = require("./wiki-one.js");
36
38
  const { diy } = require("./flow.js");
37
39
  const { crosslink } = require("./crosslink.js");
38
40
  const { mockDetail } = require("./mockrun.js");
@@ -60,6 +62,31 @@ module.exports.get = function get(route, q) {
60
62
  return testShows[(q && q.slug) || ""] || testShowToy;
61
63
  case "/api/test/ui":
62
64
  return testUiTools;
65
+ // v1.7.0 — the rule surface. One override and a lint with findings in BOTH
66
+ // prose and code: a clean ledger renders three of the five cards empty, and
67
+ // an empty card is a card nobody can design.
68
+ case "/api/rules":
69
+ return rules;
70
+ case "/api/rules/user":
71
+ return Object.assign({ ok: true, line: rules.line, boundary: rules.boundary, priorities: rules.priorities, overrides: rules.overrides }, rules.user);
72
+ case "/api/rules/packs":
73
+ return { ok: true, dir: rules.orc.dir, source: rules.orc.source, count: rules.orc.count, read_only: true, packs: rules.orc.packs, tiers: rules.tiers, line: rules.line };
74
+ case "/api/rules/credits":
75
+ return { ok: true, file: rules.orc.credits_file, sources: rules.orc.credits, text: null };
76
+ case "/api/rules/lint":
77
+ return rulesLint;
78
+ // v1.7.0 — the wiki's one-doc probes. The topic PICKS the verdict, so all
79
+ // three are reachable in the panel: type "remittance" for NEW, "invoice"
80
+ // for AMBIGUOUS, anything else for MATCH. A fixture that only ever returned
81
+ // one verdict would leave the other two cards designed blind.
82
+ case "/api/wiki/resolve": {
83
+ const topic = String((q && q.topic) || "").toLowerCase();
84
+ if (topic.includes("remittance") || topic.includes("payout")) return wikiResolveNew;
85
+ if (topic.includes("invoice") || topic.includes("billing")) return wikiResolveAmbiguous;
86
+ return wikiResolveMatch;
87
+ }
88
+ case "/api/wiki/refs":
89
+ return wikiRefs;
63
90
  case "/api/lanes":
64
91
  return laneList;
65
92
  case "/api/lane/phases":