@azure-id/orc 2.1.1 → 2.2.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.
- package/CHANGELOG.md +320 -0
- package/README.md +48 -23
- package/bin/build-agents.js +207 -205
- package/bin/cli.js +48188 -47417
- package/bin/fix.js +21 -18
- package/bin/graph-extract.js +314 -6
- package/bin/graph-gain.js +83 -2
- package/bin/graph-map.js +23 -1
- package/bin/graph-notes.js +1 -1
- package/bin/graph-query.js +1362 -37
- package/bin/graph-resolve.js +1 -1
- package/bin/graph-shard.js +29 -6
- package/bin/graph-signals.js +5 -3
- package/bin/graph.js +7 -3
- package/bin/habit.js +1 -1
- package/bin/pricing.json +8 -1
- package/bin/trace-write.js +40 -11
- package/bin/verify-contracts.js +5661 -5552
- package/bin/verify-package.js +716 -716
- package/bin/webui/api.js +8 -0
- package/bin/webui/fixtures/extra.js +2036 -2036
- package/bin/webui/fixtures/flow.js +1 -1
- package/bin/webui/fixtures/index.js +2 -2
- package/bin/webui/fixtures/knowledge.js +8 -1
- package/bin/webui/fixtures/pact.js +112 -111
- package/bin/webui/fixtures/stats.js +2 -2
- package/bin/webui/i18n/en/knowledge.json +2 -0
- package/bin/webui/i18n/id/knowledge.json +2 -0
- package/bin/webui/js/panels/knowledge.js +17 -0
- package/guides/code-graph-benefit.md +116 -0
- package/guides/configuration.md +150 -0
- package/guides/documents.md +262 -0
- package/guides/extra-models.md +448 -0
- package/guides/habits-and-gotchas.md +152 -0
- package/guides/knowledge-reads.md +190 -0
- package/guides/model-selection.md +186 -0
- package/guides/rules.md +305 -0
- package/guides/status-line.md +344 -0
- package/mock-run/orc-cli.md +3 -2
- package/mock-run/orc-doc.md +452 -448
- package/mock-run/orc.md +157 -157
- package/package.json +2 -1
- package/templates/agents/MODEL-MAPPING.md +176 -176
- package/templates/agents/{orc-executor-haiku-4-5.md → orc-executor-haiku-5-high.md} +21 -8
- package/templates/agents/orc-executor-opus-4-7-high.md +17 -5
- package/templates/agents/orc-executor-opus-4-7-med.md +17 -5
- package/templates/agents/orc-executor-opus-4-8-high.md +17 -5
- package/templates/agents/orc-executor-opus-5-high.md +17 -5
- package/templates/agents/orc-executor-opus-5-low.md +17 -5
- package/templates/agents/orc-executor-opus-5-med.md +17 -5
- package/templates/agents/orc-executor-sonnet-4-6-high.md +17 -5
- package/templates/agents/orc-executor-sonnet-5-high.md +17 -5
- package/templates/agents/orc-executor-sonnet-5-low.md +17 -5
- package/templates/agents/orc-executor-sonnet-5-med.md +17 -5
- package/templates/agents/{orc-graph-noter-sonnet-4-6-med.md → orc-graph-noter-haiku-5-high.md} +4 -4
- package/templates/agents/orc-planner-mini-opus-5-med.md +3 -1
- package/templates/agents/orc-planner-mini-sonnet-5-high.md +3 -1
- package/templates/agents/orc-planner-opus-5-med.md +3 -1
- package/templates/agents/{orc-trace-writer-haiku-4-5.md → orc-trace-writer-haiku-5-high.md} +4 -3
- package/templates/commands/orc-doc.md +128 -128
- package/templates/commands/orc-export.md +51 -46
- package/templates/hooks/README.md +8 -3
- package/templates/hooks/orc-effort-guard.js +105 -27
- package/templates/hooks/orc-graph-hook.js +252 -4
- package/templates/hooks/orc-statusline.js +13 -6
- package/templates/hooks/orc-trace.js +1 -1
- package/templates/skills/_shared/README.md +2 -2
- package/templates/skills/_shared/code-graph.md +185 -251
- package/templates/skills/_shared/extra-dispatch.md +1331 -1331
- package/templates/skills/_shared/lane-contract.md +7 -3
- package/templates/skills/_shared/opus5-only.md +137 -137
- package/templates/skills/_shared/phases/execution.md +13 -11
- package/templates/skills/_shared/phases/planning.md +27 -9
- package/templates/skills/_shared/phases/preflight.md +3 -3
- package/templates/skills/_shared/phases/review.md +4 -3
- package/templates/skills/_shared/phases/ship.md +7 -10
- package/templates/skills/_shared/phases/summary.md +2 -3
- package/templates/skills/_shared/phases/trace-verbs.md +21 -16
- package/templates/skills/_shared/phases/trace.md +3 -3
- package/templates/skills/_shared/phases/wiki-consult.md +2 -2
- package/templates/skills/_shared/pr-templates.md +108 -106
- package/templates/skills/_shared/read-ladder.md +8 -2
- package/templates/skills/_shared/return-validation.md +10 -6
- package/templates/skills/_shared/review-slice.md +1 -1
- package/templates/skills/_shared/stack-plan.md +135 -135
- package/templates/skills/_shared/wait.md +14 -2
- package/templates/skills/context-combiner/SKILL.md +2 -2
- package/templates/skills/orc/SKILL.md +227 -227
- package/templates/skills/orc/config.md +2 -2
- package/templates/skills/orc/examples/full-run-mock.md +74 -74
- package/templates/skills/orc/schemas/planning-output.md +3 -0
- package/templates/skills/orc-aftermath/SKILL.md +15 -15
- package/templates/skills/orc-analyze/SKILL.md +2 -2
- package/templates/skills/orc-analyze-mini/SKILL.md +2 -2
- package/templates/skills/orc-boundary/SKILL.md +15 -15
- package/templates/skills/orc-boundary/references/card.md +81 -78
- package/templates/skills/orc-boundary/references/gate.md +113 -113
- package/templates/skills/orc-brainstorm/SKILL.md +15 -15
- package/templates/skills/orc-budget/SKILL.md +15 -15
- package/templates/skills/orc-challenge/README.md +1 -1
- package/templates/skills/orc-challenge/SKILL.md +16 -16
- package/templates/skills/orc-challenge/examples/council-full-roster.md +1 -1
- package/templates/skills/orc-claude/SKILL.md +4 -4
- package/templates/skills/orc-claude/examples/claude-run-mock.md +1 -1
- package/templates/skills/orc-diy/SKILL.md +2 -2
- package/templates/skills/orc-diy/references/blocks/wiki.md +26 -26
- package/templates/skills/orc-diy/references/flow-schema.md +2 -2
- package/templates/skills/orc-doc/README.md +2 -2
- package/templates/skills/orc-doc/SKILL.md +501 -490
- package/templates/skills/orc-doc/examples/orc-doc-prd-run.md +12 -1
- package/templates/skills/orc-doc/references/chunking.md +6 -4
- package/templates/skills/orc-doc/references/gates.md +311 -311
- package/templates/skills/orc-doc/references/resume-protocol.md +229 -228
- package/templates/skills/orc-explain/SKILL.md +88 -88
- package/templates/skills/orc-export/SKILL.md +190 -187
- package/templates/skills/orc-fast/SKILL.md +213 -210
- package/templates/skills/orc-grill/SKILL.md +245 -245
- package/templates/skills/orc-handoff/SKILL.md +11 -11
- package/templates/skills/orc-learn/SKILL.md +13 -13
- package/templates/skills/orc-learn/examples/learn-run-mock.md +2 -2
- package/templates/skills/orc-mini/SKILL.md +12 -12
- package/templates/skills/orc-mini/examples/mini-run-mock.md +4 -5
- package/templates/skills/orc-pact/SKILL.md +15 -15
- package/templates/skills/orc-pact/references/gate.md +70 -70
- package/templates/skills/orc-pattern/SKILL.md +3 -3
- package/templates/skills/orc-poly/SKILL.md +4 -4
- package/templates/skills/orc-poly/examples/poly-run-mock.md +51 -51
- package/templates/skills/orc-pr-driver/SKILL.md +4 -3
- package/templates/skills/orc-pr-driver/references/orc-run-split.md +108 -99
- package/templates/skills/orc-pr-setup/SKILL.md +2 -2
- package/templates/skills/orc-quick/README.md +535 -536
- package/templates/skills/orc-quick/SKILL.md +29 -32
- package/templates/skills/orc-quick/references/context-doc.md +145 -145
- package/templates/skills/orc-quick/references/dispatch-gate.md +220 -220
- package/templates/skills/orc-quick/references/gh-mode.md +2 -1
- package/templates/skills/orc-quick/references/look.md +34 -12
- package/templates/skills/orc-retro/SKILL.md +2 -2
- package/templates/skills/orc-retro/examples/retro-mock.md +2 -2
- package/templates/skills/orc-route/SKILL.md +2 -2
- package/templates/skills/orc-test/SKILL.md +6 -3
- package/templates/skills/orc-verify/SKILL.md +2 -2
- package/templates/skills/orc-wait/SKILL.md +10 -2
- package/templates/skills/orc-wiki/SKILL.md +4 -4
- package/templates/skills/orc-wiki/references/pattern-prewarm.md +19 -19
- package/templates/agents/orc-executor-sonnet-4-6-med.md +0 -155
package/bin/graph-resolve.js
CHANGED
|
@@ -53,7 +53,7 @@ const G = require("./graph.js");
|
|
|
53
53
|
|
|
54
54
|
// 3 (v1.8.2 W1): ROUTE rows. A 1.8.1 cache is refused by the schema check and
|
|
55
55
|
// recomputed on read until the next `update` rewrites it — no answer changes.
|
|
56
|
-
const RESOLVE_SCHEMA =
|
|
56
|
+
const RESOLVE_SCHEMA = 4;
|
|
57
57
|
const CONFIDENT = new Set(["LOCAL", "IMPORT", "UNIQUE", "ROUTE"]);
|
|
58
58
|
const NAMES_PER_KEY = 5;
|
|
59
59
|
|
package/bin/graph-shard.js
CHANGED
|
@@ -279,13 +279,36 @@ function fastModel(claudeDir, root, query, opts) {
|
|
|
279
279
|
};
|
|
280
280
|
|
|
281
281
|
// The target's own shard holds its callers AND its ambiguous-caller counts.
|
|
282
|
-
// `ctx` asks for callers of the TARGET and of nothing else, so one shard is
|
|
283
|
-
// the whole reverse half of this card.
|
|
284
282
|
const s0 = shardFor(rel);
|
|
285
|
-
const
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
|
|
283
|
+
const callersRows = Object.create(null);
|
|
284
|
+
const maybeRows = Object.create(null);
|
|
285
|
+
const merged = new Set();
|
|
286
|
+
const merge = (r, sh) => {
|
|
287
|
+
merged.add(r);
|
|
288
|
+
for (const [k, v] of Object.entries(sh.callers || {})) callersRows[k] = v;
|
|
289
|
+
for (const [k, v] of Object.entries(sh.maybe || {})) maybeRows[k] = v;
|
|
290
|
+
};
|
|
291
|
+
merge(rel, s0);
|
|
292
|
+
// R11 (v2.2.0): the card also asks for the callers of the target's CALLERS
|
|
293
|
+
// (the tests that reach it through one). Those rows live in the shard of the
|
|
294
|
+
// caller's file, so that shard is read on first ask. A shard that will not
|
|
295
|
+
// read sends the whole card back to the full model, never a shorter card.
|
|
296
|
+
const ensure = (k) => {
|
|
297
|
+
if (typeof k !== "string" || !k.includes("#")) return;
|
|
298
|
+
const r = k.split("#")[0];
|
|
299
|
+
if (merged.has(r) || !files[r]) return;
|
|
300
|
+
const sh = shardFor(r);
|
|
301
|
+
if (!sh) throw new FastUnavailable("shard-stale:" + r);
|
|
302
|
+
merge(r, sh);
|
|
303
|
+
};
|
|
304
|
+
const lazy = (t) =>
|
|
305
|
+
new Proxy(t, {
|
|
306
|
+
get: (o, k) => (ensure(k), o[k]),
|
|
307
|
+
has: (o, k) => (ensure(k), k in o),
|
|
308
|
+
getOwnPropertyDescriptor: (o, k) => (ensure(k), Reflect.getOwnPropertyDescriptor(o, k)),
|
|
309
|
+
});
|
|
310
|
+
const callersCache = lazy(callersRows);
|
|
311
|
+
const maybeCache = lazy(maybeRows);
|
|
289
312
|
|
|
290
313
|
return {
|
|
291
314
|
model: {
|
package/bin/graph-signals.js
CHANGED
|
@@ -489,12 +489,14 @@ function complexityOf(claudeDir, root, model, rels, opts) {
|
|
|
489
489
|
callerFiles.size >= COMPLEXITY_CALLER_FILES || callersOutside >= COMPLEXITY_CALLERS || risk.length > 0 || cochange.length > 0 ? "recommend-orc" : "mini-ok";
|
|
490
490
|
|
|
491
491
|
const riskText = risk.length ? risk.map((x) => `${x.class}${x.at ? ` (${x.at})` : ""}`).join(", ") : riskGiven ? "none" : "not given";
|
|
492
|
-
|
|
492
|
+
// v2.2.0 (G-15): no co-change row is no segment — `cochange none` was a
|
|
493
|
+
// line about nothing.
|
|
494
|
+
const cochangeText = cochange.length ? ` · cochange ${cochange.map((x) => `${x.path} x${x.count} not in plan`).join(", ")}` : "";
|
|
493
495
|
const maybeText = maybe ? ` · maybe ${maybe}` : "";
|
|
494
496
|
const line =
|
|
495
497
|
verdict === "mini-ok"
|
|
496
|
-
? `complexity: mini-ok — ${rels.length} files · confident callers ${callersOutside} in ${callerFiles.size} files${maybeText} · tests reach ${testsReaching} · risk ${riskText}
|
|
497
|
-
: `complexity: recommend /orc — ${rels.length} files · callers ${callersOutside} in ${callerFiles.size} files${maybeText} · tests reach ${testsReaching} · risk ${riskText}
|
|
498
|
+
? `complexity: mini-ok — ${rels.length} files · confident callers ${callersOutside} in ${callerFiles.size} files${maybeText} · tests reach ${testsReaching} · risk ${riskText}${cochangeText}`
|
|
499
|
+
: `complexity: recommend /orc — ${rels.length} files · callers ${callersOutside} in ${callerFiles.size} files${maybeText} · tests reach ${testsReaching} · risk ${riskText}${cochangeText}`;
|
|
498
500
|
|
|
499
501
|
return {
|
|
500
502
|
verdict,
|
package/bin/graph.js
CHANGED
|
@@ -45,7 +45,7 @@ const SCHEMA = 1;
|
|
|
45
45
|
// symbols, and a `<script setup>` component is one `class`. No record FIELD
|
|
46
46
|
// changed: a 1.9.0 store reads DRIFTED and the next `status --heal`
|
|
47
47
|
// re-extracts once, the same path 1.8.1 → 1.8.2 took.
|
|
48
|
-
const ENGINE = "graph@
|
|
48
|
+
const ENGINE = "graph@7";
|
|
49
49
|
const GIT_MAX_BUFFER = 256 * 1024 * 1024;
|
|
50
50
|
const MAX_BYTES = 512 * 1024;
|
|
51
51
|
const LOCK_STALE_MS = 10 * 60 * 1000;
|
|
@@ -514,7 +514,10 @@ function graphUpdate(claudeDir, root, opts) {
|
|
|
514
514
|
// EW3: how long the last real update took, end to end. A read that may
|
|
515
515
|
// heal uses it as the estimate for the next one — the only honest
|
|
516
516
|
// estimate available, because an update cannot be stopped half way.
|
|
517
|
-
|
|
517
|
+
// v2.2.0 (G-13): a COLD build is not an estimate for an incremental
|
|
518
|
+
// update, so it writes `build_ms` and leaves `update_ms` absent.
|
|
519
|
+
...(first ? {} : { update_ms: unchanged && prevMeta ? prevMeta.update_ms || 0 : 0 }),
|
|
520
|
+
...(prevMeta && prevMeta.build_ms ? { build_ms: prevMeta.build_ms } : {}),
|
|
518
521
|
// A1: computed from the index this update just built, so it costs one
|
|
519
522
|
// pass over what is already in memory and no file is opened for it.
|
|
520
523
|
density: unchanged && prevMeta && prevMeta.density ? prevMeta.density : densityOf(index, filesOut),
|
|
@@ -540,7 +543,8 @@ function graphUpdate(claudeDir, root, opts) {
|
|
|
540
543
|
// so a crash between the two leaves a valid meta that only lacks an
|
|
541
544
|
// estimate, and a missing estimate simply means "heal, and find out".
|
|
542
545
|
if (!unchanged) {
|
|
543
|
-
meta.
|
|
546
|
+
if (first) meta.build_ms = Date.now() - t0;
|
|
547
|
+
else meta.update_ms = Date.now() - t0;
|
|
544
548
|
atomicWrite(p.meta, JSON.stringify(meta, null, 2) + "\n");
|
|
545
549
|
}
|
|
546
550
|
return {
|
package/bin/habit.js
CHANGED
|
@@ -140,7 +140,7 @@ const QUESTION_RE = /(?:^|\s)QUESTION\s+count=(\d+)/;
|
|
|
140
140
|
const AGENT_RE = /^[a-z0-9][a-z0-9.:-]*$/;
|
|
141
141
|
|
|
142
142
|
// v2.1.0 (A1) — ONE agent, ONE spelling. A live gate wrote the same executor
|
|
143
|
-
// three ways (`orc-executor-
|
|
143
|
+
// three ways (`orc-executor-haiku-5-high`, `haiku-5-high`, `haiku`), so a
|
|
144
144
|
// 15-of-15 choice read as 5/7 and was never proposed. A short form is mapped to
|
|
145
145
|
// the full SHIPPED agent name only when it can mean exactly one agent of the
|
|
146
146
|
// gate's role (a family word like `sonnet` is settled by the `offered=` list);
|
package/bin/pricing.json
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"it has no rate for. A pair with no rate reports `usd: null` forever, never a",
|
|
29
29
|
"guess and never a family fallback."
|
|
30
30
|
],
|
|
31
|
-
"as_of": "2026-10-
|
|
31
|
+
"as_of": "2026-10-09",
|
|
32
32
|
"currency": "USD",
|
|
33
33
|
"unit": "per_million_tokens",
|
|
34
34
|
"server_tools": {
|
|
@@ -84,6 +84,12 @@
|
|
|
84
84
|
"cache_read": 0.3,
|
|
85
85
|
"output": 15
|
|
86
86
|
},
|
|
87
|
+
"claude-haiku-5-5": {
|
|
88
|
+
"input": 0.1,
|
|
89
|
+
"cache_write": 0.125,
|
|
90
|
+
"cache_read": 0.01,
|
|
91
|
+
"output": 0.5
|
|
92
|
+
},
|
|
87
93
|
"claude-haiku-4-5": {
|
|
88
94
|
"input": 1,
|
|
89
95
|
"cache_write": 1.25,
|
|
@@ -151,6 +157,7 @@
|
|
|
151
157
|
"claude-sonnet-5-5": 200000,
|
|
152
158
|
"claude-sonnet-5": 200000,
|
|
153
159
|
"claude-sonnet-4-6": 200000,
|
|
160
|
+
"claude-haiku-5-5": 1000000,
|
|
154
161
|
"claude-haiku-4-5": 200000
|
|
155
162
|
},
|
|
156
163
|
"providers": {
|
package/bin/trace-write.js
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
// halves of the trace pair — the `.txt` line and its `.jsonl` row — so the two
|
|
7
7
|
// can never disagree about an event. W0 measured the Haiku writer at 92.4 %
|
|
8
8
|
// (whole phase blocks missing from the `.jsonl`); here parity is by
|
|
9
|
-
// construction. The writer agent `orc-trace-writer-haiku-
|
|
9
|
+
// construction. The writer agent `orc-trace-writer-haiku-5-high` stays as the
|
|
10
10
|
// FALLBACK: a lane dispatches it only when this command exits ≠ 0.
|
|
11
11
|
//
|
|
12
|
-
// The formats are the writer's, not new ones (`agents/orc-trace-writer-haiku-
|
|
12
|
+
// The formats are the writer's, not new ones (`agents/orc-trace-writer-haiku-5-high.md`):
|
|
13
13
|
// .txt [<ts>] <actor padded to 8> <VERB> :: <tail>
|
|
14
14
|
// .jsonl {"ts","actor","phase","verb","tail", …verbatim extra fields}
|
|
15
15
|
// NOTE one line from `decisions`, actor `writer`, the last event's ts
|
|
@@ -179,6 +179,10 @@ function blockScalar(lines, i, style, parentIndent) {
|
|
|
179
179
|
return [text, j - 1];
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
+
// v2.2.0 T13 — a parse error names the line it could not read (trimmed, ≤ 80 chars).
|
|
183
|
+
const quoteLine = (l) => { const t = String(l).trim(); return JSON.stringify(t.length > 80 ? t.slice(0, 79) + "…" : t); };
|
|
184
|
+
const PACKET_SHAPE_HINT = ' — a packet is YAML or JSON, e.g. {"phase":"entry 1","events":[{"ts":"DDMMYY HH:MM:SS.mmm","verb":"NOTE","tail":"…"}]}';
|
|
185
|
+
|
|
182
186
|
function parseYaml(text) {
|
|
183
187
|
const lines = text.split("\n");
|
|
184
188
|
const out = {};
|
|
@@ -187,7 +191,7 @@ function parseYaml(text) {
|
|
|
187
191
|
if (line.trim() === "" || line.trim()[0] === "#") continue;
|
|
188
192
|
if (indentOf(line) !== 0) throw new PacketError(`line ${i + 1}: unexpected indentation`);
|
|
189
193
|
const m = KEY_RE.exec(line);
|
|
190
|
-
if (!m) throw new PacketError(`line ${i + 1}: expected "key: value"`);
|
|
194
|
+
if (!m) throw new PacketError(`line ${i + 1}: expected "key: value", got ${quoteLine(line)}`);
|
|
191
195
|
const key = m[1];
|
|
192
196
|
const rest = stripComment(m[2] || "").trim();
|
|
193
197
|
if (/^[>|][+-]?$/.test(rest)) {
|
|
@@ -250,7 +254,7 @@ function parseYaml(text) {
|
|
|
250
254
|
}
|
|
251
255
|
if (indentOf(n) <= itemIndent) break;
|
|
252
256
|
const nm = KEY_RE.exec(n.trim());
|
|
253
|
-
if (!nm) throw new PacketError(`line ${k + 2}: expected "key: value" inside an item`);
|
|
257
|
+
if (!nm) throw new PacketError(`line ${k + 2}: expected "key: value" inside an item, got ${quoteLine(n)}`);
|
|
254
258
|
k++;
|
|
255
259
|
put(nm[1], nm[2], k);
|
|
256
260
|
}
|
|
@@ -267,7 +271,7 @@ function parseYaml(text) {
|
|
|
267
271
|
if (l.trim() === "" || l.trim()[0] === "#") continue;
|
|
268
272
|
if (indentOf(l) === 0) break;
|
|
269
273
|
const nm = KEY_RE.exec(l.trim());
|
|
270
|
-
if (!nm) throw new PacketError(`line ${k + 1}: expected "key: value" under ${key}`);
|
|
274
|
+
if (!nm) throw new PacketError(`line ${k + 1}: expected "key: value" under ${key}, got ${quoteLine(l)}`);
|
|
271
275
|
map[nm[1]] = scalar(nm[2] || "");
|
|
272
276
|
}
|
|
273
277
|
out[key] = map;
|
|
@@ -381,7 +385,22 @@ function findingOutcomeError(verb, tail) {
|
|
|
381
385
|
}
|
|
382
386
|
|
|
383
387
|
// → { phase, run_meta, events: [{ts, actor, verb, tail, extra}], note } or throws.
|
|
384
|
-
|
|
388
|
+
// v2.2.0 T13 — `laneVerbs(tokenOrLane)` → this lane's verb heads, or null; `laneHint`
|
|
389
|
+
// is the lane token from the trace file name when the packet has no run_meta.
|
|
390
|
+
function unknownVerbFix(pk, traceVerbs, laneVerbs, laneHint) {
|
|
391
|
+
const rm = pk && pk.run_meta && typeof pk.run_meta === "object" ? pk.run_meta : null;
|
|
392
|
+
const lane = (rm && rm.lane) || laneHint || null;
|
|
393
|
+
const own = lane && typeof laneVerbs === "function" ? laneVerbs(String(lane)) : null;
|
|
394
|
+
// T13b — PHASE and ASK are packet verbs for every lane, even when the grammar omits them.
|
|
395
|
+
if (own) {
|
|
396
|
+
if (!own.includes("PHASE")) own.push("PHASE");
|
|
397
|
+
if (!own.includes("ASK")) { const ln = String(lane); const name = /^orc(-|$)/.test(ln) ? ln : ln === "ultra" ? "orc" : `orc-${ln}`; own.push(`ASK <qid> (the ids: orc lane phases ${name} --json → ask_ids)`); }
|
|
398
|
+
}
|
|
399
|
+
const heads = own || Object.keys(traceVerbs).filter((v) => traceVerbs[v].emitter !== "hook" && traceVerbs[v].emitter !== "cli");
|
|
400
|
+
return ` — use "PHASE <name> start|end" for a phase, "NOTE" for free text; ${own ? "this lane's verbs" : "the packet verbs"}: ${heads.join(", ")}`;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
function validatePacket(pk, traceVerbs, laneVerbs, laneHint) {
|
|
385
404
|
if (!pk || typeof pk !== "object" || Array.isArray(pk)) throw new PacketError("the packet is not a map");
|
|
386
405
|
const errs = [];
|
|
387
406
|
const events = Array.isArray(pk.events) ? pk.events : [];
|
|
@@ -395,10 +414,11 @@ function validatePacket(pk, traceVerbs) {
|
|
|
395
414
|
const word = verb.split(/\s+/)[0];
|
|
396
415
|
if (!word) return errs.push(`${at} has no verb`);
|
|
397
416
|
const d = Object.prototype.hasOwnProperty.call(traceVerbs, word) ? traceVerbs[word] : null;
|
|
398
|
-
if (!d) return errs.push(`${at}: unknown verb ${word} — not in the CLOSED set (trace-verbs.md)`);
|
|
417
|
+
if (!d) return errs.push(`${at}: unknown verb ${word} — not in the CLOSED set (trace-verbs.md)${unknownVerbFix(pk, traceVerbs, laneVerbs, laneHint)}`);
|
|
399
418
|
if (d.emitter === "hook") return errs.push(`${at}: ${word} is written by the hook, never by a packet`);
|
|
400
|
-
// v2.1.0 W6 — `FIX` is written by `orc fix record` itself.
|
|
401
|
-
|
|
419
|
+
// v2.1.0 W6 — `FIX` is written by `orc fix record` itself; v2.1.2 F11 —
|
|
420
|
+
// `WAIT` by `orc wait`. The verb's owner file says which command.
|
|
421
|
+
if (d.emitter === "cli") return errs.push(`${at}: ${word} is written by the CLI itself (see ${d.owner}), never by a packet`);
|
|
402
422
|
const ts = e.ts == null ? "" : String(e.ts).trim();
|
|
403
423
|
if (!TS_RE.test(ts)) errs.push(`${at} (${word}): ts "${ts}" is not DDMMYY HH:MM:SS.mmm — the event's REAL time, never "now"`);
|
|
404
424
|
const actor = e.actor == null || e.actor === "" ? "orc" : String(e.actor).trim();
|
|
@@ -727,11 +747,20 @@ function traceCmd(deps) {
|
|
|
727
747
|
return fail(1, "unreadable", `cannot read the packet (${e.code || e.message})`);
|
|
728
748
|
}
|
|
729
749
|
let v;
|
|
750
|
+
let laneHint = null;
|
|
751
|
+
try {
|
|
752
|
+
const ld0 = deps.resolveLogDir(deps.resolveClaudeDir());
|
|
753
|
+
const cur0 = fs.readFileSync(path.join(ld0, ".current"), "utf8").trim();
|
|
754
|
+
laneHint = (/(?:^|[\/])run-([a-z0-9]+)-/.exec(cur0) || [])[1] || null;
|
|
755
|
+
} catch (_) {}
|
|
730
756
|
try {
|
|
731
|
-
|
|
757
|
+
const pk0 = parsePacket(text);
|
|
758
|
+
if (!laneHint && pk0 && typeof pk0.run === "string") laneHint = (/(?:^|[\/])run-([a-z0-9]+)-/.exec(pk0.run) || [])[1] || null;
|
|
759
|
+
v = validatePacket(pk0, deps.TRACE_VERBS, deps.laneVerbsFor, laneHint);
|
|
732
760
|
} catch (e) {
|
|
733
761
|
if (!(e instanceof PacketError)) throw e;
|
|
734
|
-
|
|
762
|
+
const hint = /expected "key: value"|not valid JSON|unexpected indentation/.test(e.message) ? PACKET_SHAPE_HINT : "";
|
|
763
|
+
return fail(2, "invalid", `${e.message} — nothing written${hint}`, { errors: e.errors || [e.message] });
|
|
735
764
|
}
|
|
736
765
|
// An ASK is checked against the habit registry AS IT ARRIVES (eval E2): a live lane
|
|
737
766
|
// wrote its own option names and extra text, and the habit engine then counted
|