@azure-id/orc 1.4.1 → 1.5.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 (47) hide show
  1. package/CHANGELOG.md +3154 -2907
  2. package/README-id.md +39 -2
  3. package/README.md +647 -631
  4. package/bin/cli.js +42495 -36866
  5. package/bin/mockrun-catalog.js +4 -0
  6. package/bin/verify-contracts.js +4475 -4410
  7. package/bin/verify-package.js +21 -2
  8. package/bin/webui/api.js +1388 -1283
  9. package/bin/webui/app.html +9 -0
  10. package/bin/webui/css/04-motion.css +18 -0
  11. package/bin/webui/css/06-responsive.css +17 -1
  12. package/bin/webui/css/panels/hookui.css +220 -41
  13. package/bin/webui/css/panels/test.css +132 -0
  14. package/bin/webui/fixtures/index.js +23 -1
  15. package/bin/webui/fixtures/test.js +547 -0
  16. package/bin/webui/i18n/en/common.json +1 -0
  17. package/bin/webui/i18n/en/hookui.json +17 -3
  18. package/bin/webui/i18n/en/nav.json +1 -0
  19. package/bin/webui/i18n/en/overview.json +4 -0
  20. package/bin/webui/i18n/en/test.json +141 -0
  21. package/bin/webui/i18n/en/tour.json +1 -1
  22. package/bin/webui/i18n/id/common.json +1 -0
  23. package/bin/webui/i18n/id/hookui.json +17 -3
  24. package/bin/webui/i18n/id/nav.json +1 -0
  25. package/bin/webui/i18n/id/overview.json +4 -0
  26. package/bin/webui/i18n/id/test.json +141 -0
  27. package/bin/webui/i18n/id/tour.json +1 -1
  28. package/bin/webui/js/01-i18n.js +1 -0
  29. package/bin/webui/js/panels/challenge.js +8 -3
  30. package/bin/webui/js/panels/hookui.js +586 -208
  31. package/bin/webui/js/panels/overview.js +10 -0
  32. package/bin/webui/js/panels/test.js +733 -0
  33. package/bin/webui/serve.js +572 -557
  34. package/mock-run/orc-test.md +327 -0
  35. package/package.json +1 -1
  36. package/templates/agents/MODEL-MAPPING.md +2 -0
  37. package/templates/agents/orc-test-designer-opus-5-high.md +158 -0
  38. package/templates/agents/orc-test-interpreter-opus-5-low.md +130 -0
  39. package/templates/commands/orc-test.md +66 -0
  40. package/templates/hooks/README.md +8 -1
  41. package/templates/hooks/orc-statusline.js +15 -4
  42. package/templates/hooks/orc-subagent-line.js +5 -2
  43. package/templates/skills/_shared/extra-dispatch.md +1346 -1337
  44. package/templates/skills/_shared/live-target.md +188 -0
  45. package/templates/skills/_shared/phases/trace.md +2 -2
  46. package/templates/skills/_shared/wait.md +241 -240
  47. package/templates/skills/orc-test/SKILL.md +233 -0
@@ -0,0 +1,66 @@
1
+ ---
2
+ description: Run the tests against the real running system — happy path to security — and report only what was observed
3
+ ---
4
+
5
+ Use the **orc-test** skill. Standalone — no plan, no build, no code written into
6
+ your project.
7
+
8
+ Every other ORC lane reasons about your system. This one **runs it**:
9
+
10
+ > **A test that ran is a FACT; a test that was written is an OPINION.**
11
+
12
+ ORC already has a lane that WRITES tests and never runs them (Phase 6.5,
13
+ `test-generator/`). This is the mirror image, and the two never mix: `/orc-test`
14
+ writes nothing into your test tree and runs everything.
15
+
16
+ **It never edits the system it is testing.** If the server will not come up, it
17
+ prints exactly what it ran and the tail of the output, and hands back. You fix
18
+ it, and re-run for free — the same shape as `/orc-challenge`, and for the same
19
+ reason: a session that just fixed the code cannot be trusted to measure it.
20
+
21
+ **It never reports a result it did not observe.** Three verdicts and no fourth:
22
+ `pass` (observed, matched), `fail` (observed, did not match), and `unknown` —
23
+ not observed. `unknown` keeps its slot in the report and never becomes a pass.
24
+ A flake is recorded, never retried away: there is no retry count, because if the
25
+ same case answers differently twice, *that instability is the finding*.
26
+
27
+ One pass:
28
+
29
+ 1. **Target** — `orc test init <slug>` asks what it must not guess: back end or
30
+ front end, local or remote, the base URL. On a remote target it also requires
31
+ `--authorized "<who authorized this, and where it is recorded>"`, stored
32
+ verbatim and reprinted at the head of every report. ORC cannot verify
33
+ authorization and does not pretend to — it makes the assertion impossible to
34
+ skip. Frozen, and never asked again.
35
+ 2. **Surface** — free, deterministic: an OpenAPI or GraphQL spec on disk, the
36
+ same spec at the target, route extraction by framework fingerprint, FE router
37
+ config. Anything ambiguous comes back as `unresolved[]` and is never guessed.
38
+ The **code-vs-live diff** is a first-class output: routes that answer live and
39
+ exist in no source file are zombie APIs.
40
+ 3. **Flow** — it digs the repo for how a request reaches your endpoint: the
41
+ route registration, the middleware in order, the handler, what it writes, what
42
+ must be true first, which fields name an object, and the login flow itself.
43
+ 4. **Environment** (local only) — it brings the system up and waits for health.
44
+ Five states, one next action each.
45
+ 5. **Cases** — the CLI derives the bulk for free: equivalence partitions,
46
+ boundary values, method and content-type negatives, stateful create → read →
47
+ update → delete sequences. An agent fills only what a schema cannot know.
48
+ 6. **Run** — paced, capped, and fenced to the frozen origin. A 429 is a RESULT,
49
+ not an error: it means rate limiting works. Every case leaves its exact
50
+ request, its exact response and a reproducible `curl`, with every credential
51
+ redacted **before the bytes reach disk**.
52
+ 7. **Report** — `orc/orc-test/<slug>/REPORT.md`, written for someone who does
53
+ not read code.
54
+
55
+ The security tier is a **closed set** mapped to the OWASP API Security Top 10
56
+ (2023), and it demonstrates a CONDITION rather than an extraction — confirming
57
+ an exploit is your decision on your authority. With one identity, BOLA and BFLA
58
+ report `UNCHECKABLE`, which keeps its slot and never becomes a pass.
59
+
60
+ **The run folder is never staged.** Evidence contains real response bodies from
61
+ a real system. The lane offers you the one `.gitignore` line; it does not edit
62
+ `.gitignore` itself.
63
+
64
+ Read the state back any time without this lane: `orc test status <slug>`.
65
+
66
+ The slug to open or reopen (or nothing, and it will ask): $ARGUMENTS
@@ -205,12 +205,19 @@ them where you want them. One rule decides where a component may go:
205
205
  > A line may hold a component only if every line above it holds at least one.
206
206
 
207
207
  So line 1 must hold something before line 2 can, and line 2 before line 3. Each
208
- line holds at most five components. The panel will not let you make an illegal
208
+ line holds at most six components. The panel will not let you make an illegal
209
209
  move, and it tells you why.
210
210
 
211
211
  Every component can be changed: its words, its colour, its shape, how wide it
212
212
  is, and when it is allowed to disappear.
213
213
 
214
+ **The shape decides what the other settings can do.** Only these shapes print a
215
+ short name in front of the value: `plain`, `label-value`, `bracket`, `angle`,
216
+ `badge`, `pill` and `stack`. A bar, an icon and a bare value have no room for
217
+ one, so the panel switches the Name box off for them and says so. The same is
218
+ true of the number settings: a bar has a width and a colour ramp, and no number
219
+ format at all.
220
+
214
221
  **Three things a terminal cannot do**, said plainly so you do not look for them:
215
222
 
216
223
  | You may want | What you get |
@@ -1147,16 +1147,27 @@ function custom(d, ctx) {
1147
1147
  if (!engine.BINDINGS[b]) return slFallback(orcDir, "statusline-layout-skew");
1148
1148
  }
1149
1149
 
1150
- // Rung 5. The cheap shape guard: at most three lines, at most five
1150
+ // Rung 5. The cheap shape guard: at most three lines, at most `max_per_line`
1151
1151
  // components on any of them, and the dense-prefix rule —
1152
1152
  // A line may hold a component only if every line above it holds at least one.
1153
+ //
1154
+ // THE CAP AND THE COUNTING RULE ARE BOTH THE COMPILER'S (v1.4.2). This held
1155
+ // its own `5` and counted EVERY item op, so it disagreed with the validator
1156
+ // twice: it bounced a legal six-part line, and it bounced a legal five plus
1157
+ // a spacer. Both fell silently back to the shipped lines with the reason
1158
+ // only in a ledger file, which reads exactly like "my sixth part reset the
1159
+ // bar to the default". The cap rides on the lock (already gated on
1160
+ // `orc_version` at rung 3, so a stale copy cannot outlive its build) and
1161
+ // the compiler marks a structural op `s` — this cannot know that on its
1162
+ // own, because a compiled op carries an INSTANCE id and never a type.
1153
1163
  if (!Array.isArray(prog.lines) || prog.lines.length > 3)
1154
1164
  return slFallback(orcDir, "statusline-layout-invalid");
1165
+ const cap = Number(lock.max_per_line) > 0 ? Number(lock.max_per_line) : 6;
1155
1166
  let seenEmpty = false;
1156
1167
  for (const l of prog.lines) {
1157
- const n = (l.ops || []).filter((o) => o.op === "item").length;
1158
- if (n > 5) return slFallback(orcDir, "statusline-layout-invalid");
1159
- if (n === 0) seenEmpty = true;
1168
+ const ops = (l.ops || []).filter((o) => o.op === "item");
1169
+ if (ops.filter((o) => !o.s).length > cap) return slFallback(orcDir, "statusline-layout-invalid");
1170
+ if (ops.length === 0) seenEmpty = true;
1160
1171
  else if (seenEmpty) return slFallback(orcDir, "statusline-layout-invalid");
1161
1172
  }
1162
1173
 
@@ -182,10 +182,13 @@ function render(d, tasks) {
182
182
 
183
183
  // Rung 5. A subagent row is ONE line by construction — Claude Code renders
184
184
  // one row per task — so the board's three-line shape does not apply and the
185
- // cheap guard is simply "one line, at most five things on it".
185
+ // cheap guard is simply "one line, at most `max_per_line` things on it".
186
186
  if (!Array.isArray(prog.lines) || !prog.lines.length) return null;
187
187
  const line = prog.lines[0];
188
- if ((line.ops || []).filter((o) => o.op === "item").length > 5) return null;
188
+ // The same cap, from the same place, counted the same way (v1.4.2). A
189
+ // hardcoded number here is a second idea of how much one line may say.
190
+ const cap = Number(lock && lock.max_per_line) > 0 ? Number(lock.max_per_line) : 6;
191
+ if ((line.ops || []).filter((o) => o.op === "item" && !o.s).length > cap) return null;
189
192
 
190
193
  // Rung 6. One row per task, each rendered with THAT TASK bound.
191
194
  const now = Date.now();