@ngockhoale/ukit 3.4.47 → 3.4.48

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 (62) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/manifests/documentation.yaml +22 -0
  3. package/manifests/platform.full.yaml +27 -0
  4. package/package.json +4 -1
  5. package/scripts/dev/worktree-preflight.mjs +20 -1
  6. package/src/core/diffPlan.js +38 -12
  7. package/src/core/executionContracts.js +67 -16
  8. package/src/core/metadata.js +4 -0
  9. package/src/core/runInstallPipeline.js +19 -2
  10. package/src/core/runtimeConfig.js +1 -1
  11. package/src/index/playbookRegistry.js +22 -3
  12. package/src/index/taskRouting.js +2 -2
  13. package/template_project/.claude/agents/bug-debugger.md +1 -0
  14. package/template_project/.claude/agents/code-reviewer.md +1 -0
  15. package/template_project/.claude/agents/feature-implementer.md +1 -0
  16. package/template_project/.claude/agents/handoff-planner.md +1 -0
  17. package/template_project/.claude/agents/ukit-small-task-maintainer.md +1 -0
  18. package/template_project/.claude/hooks/completion-gate.sh +1 -1
  19. package/template_project/.claude/hooks/delegation-gate.mjs +343 -0
  20. package/template_project/.claude/hooks/skill-router.sh +147 -6
  21. package/template_project/.claude/settings.json +8 -8
  22. package/template_project/.claude/ukit/index/playbook-registry.mjs +22 -3
  23. package/template_project/.claude/ukit/index/route-resolver.mjs +67 -15
  24. package/template_project/.claude/ukit/index/route-task.mjs +115 -37
  25. package/template_project/.claude/ukit/index/tier-lane.mjs +202 -0
  26. package/template_project/.claude/ukit/runtime/cron-operation-adapter.mjs +3 -1
  27. package/template_project/.claude/ukit/runtime/execution-ledger.mjs +306 -20
  28. package/template_project/.claude/ukit/runtime/hook-chain-runner.mjs +8 -0
  29. package/template_project/.claude/ukit/runtime/loop-state.mjs +3 -1
  30. package/template_project/.claude/ukit/runtime/observability-emit.mjs +38 -0
  31. package/template_project/.claude/ukit/runtime/playbook-execution.mjs +704 -0
  32. package/template_project/.claude/ukit/runtime/stop-coordinator.mjs +79 -3
  33. package/template_project/.omp/agents/bug-debugger.md +1 -0
  34. package/template_project/.omp/agents/code-reviewer.md +1 -0
  35. package/template_project/.omp/agents/feature-implementer.md +1 -0
  36. package/template_project/.omp/agents/handoff-planner.md +1 -0
  37. package/template_project/.omp/agents/ukit-small-task-maintainer.md +1 -0
  38. package/template_project/.omp/hooks/pre/ukit-bridge.js +254 -7
  39. package/template_project/ukit/storage/config.json +1 -1
  40. package/scripts/bench/data-foundation.mjs +0 -929
  41. package/scripts/bench/decision-runtime-baseline.mjs +0 -427
  42. package/scripts/bench/decision-runtime-variant.mjs +0 -626
  43. package/scripts/bench/goldTasks.json +0 -38
  44. package/scripts/bench/memory-ablation.mjs +0 -495
  45. package/scripts/bench/memory-baseline.mjs +0 -596
  46. package/scripts/bench/memory-bench.mjs +0 -661
  47. package/scripts/bench/memory-canary.mjs +0 -331
  48. package/scripts/bench/memory-corpus.mjs +0 -354
  49. package/scripts/bench/memory-gate.mjs +0 -389
  50. package/scripts/bench/memory-metrics.mjs +0 -179
  51. package/scripts/bench/outline-savings.mjs +0 -107
  52. package/scripts/bench/parallel-agents.mjs +0 -224
  53. package/scripts/bench/recorder-overhead.mjs +0 -204
  54. package/scripts/bench/runGold.mjs +0 -238
  55. package/scripts/bench/sqlite-spike.mjs +0 -451
  56. package/scripts/bench/subagent-orchestrator-corpus.mjs +0 -275
  57. package/scripts/bench/subagent-orchestrator-eval.mjs +0 -565
  58. package/scripts/bench/v3-ceremony.mjs +0 -220
  59. package/scripts/perf/audit-perf.mjs +0 -1195
  60. package/scripts/perf/diff-perf-findings.mjs +0 -136
  61. package/scripts/perf/perf-findings.json +0 -474
  62. package/scripts/perf/perf-measure.md +0 -271
@@ -1,136 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * diff-perf-findings.mjs — findings-level diff between two audit snapshots
4
- * (TASK-006, SPEC §5 FR-008).
5
- *
6
- * Why a separate script and not a mode of `audit-perf.mjs`: the audit takes live
7
- * measurements, so "compare two snapshots" is a read-only operation that must
8
- * work against archived JSON long after the telemetry that produced it rotated
9
- * away. This script never touches telemetry at all — it reads two reports and
10
- * prints their deltas.
11
- *
12
- * Every snapshot is a point in time over a live dataset (see the O2 finding:
13
- * 30k → 34k rows in two hours), so both snapshots' `generatedAt` /
14
- * `telemetryRows` / `telemetryFiles` provenance is printed before any delta —
15
- * two reports are only comparable once their provenance is known.
16
- *
17
- * Deltas reported, per finding id:
18
- * + <id> added — present in b, absent from a
19
- * - <id> removed — present in a, absent from b (never a crash)
20
- * ~ <id> changed — same id, different status and/or different measured numbers
21
- *
22
- * Usage:
23
- * node scripts/perf/diff-perf-findings.mjs <a.json> <b.json>
24
- *
25
- * Exit: 0 = compared (with or without deltas, including a self-diff); 2 = usage,
26
- * unreadable file, or a report that is not a findings snapshot.
27
- */
28
- import fs from 'node:fs';
29
-
30
- const METRIC_KEYS = ['p50ms', 'p95ms', 'totalMs', 'invocations'];
31
-
32
- function usage() {
33
- process.stderr.write('usage: node scripts/perf/diff-perf-findings.mjs <a.json> <b.json>\n');
34
- }
35
-
36
- function loadSnapshot(file) {
37
- let report;
38
- try {
39
- report = JSON.parse(fs.readFileSync(file, 'utf8'));
40
- } catch (error) {
41
- throw new Error(`cannot read findings snapshot ${file}: ${error.message}`);
42
- }
43
- if (!report || !Array.isArray(report.findings)) {
44
- throw new Error(`${file} is not a findings snapshot (no findings[] array)`);
45
- }
46
- return report;
47
- }
48
-
49
- function formatNumber(value) {
50
- if (typeof value !== 'number' || !Number.isFinite(value)) return 'n/a';
51
- return Number.isInteger(value) ? String(value) : value.toFixed(1);
52
- }
53
-
54
- function provenanceLine(label, file, report) {
55
- const rows = formatNumber(report.telemetryRows);
56
- const files = formatNumber(report.telemetryFiles);
57
- const generatedAt = typeof report.generatedAt === 'string' ? report.generatedAt : 'n/a';
58
- return `${label}: ${file} — generatedAt ${generatedAt}, telemetryRows ${rows} / telemetryFiles ${files}`;
59
- }
60
-
61
- /** Metric drift for one finding pair, as `key a → b` fragments. */
62
- function metricDrift(before, after) {
63
- return METRIC_KEYS
64
- .filter((key) => before[key] !== after[key])
65
- .map((key) => `${key} ${formatNumber(before[key])} → ${formatNumber(after[key])}`);
66
- }
67
-
68
- function diffFindings(a, b) {
69
- const before = new Map(a.findings.map((item) => [item.id, item]));
70
- const after = new Map(b.findings.map((item) => [item.id, item]));
71
- const deltas = [];
72
-
73
- for (const [id, item] of after) {
74
- if (!before.has(id)) {
75
- deltas.push({ kind: 'added', id, line: `+ ${id} added (status ${item.status})` });
76
- continue;
77
- }
78
- const previous = before.get(id);
79
- const drift = metricDrift(previous, item);
80
- if (previous.status !== item.status) {
81
- const suffix = drift.length ? ` (${drift.join(', ')})` : '';
82
- deltas.push({
83
- kind: 'changed',
84
- id,
85
- line: `~ ${id} status ${previous.status} → ${item.status}${suffix}`,
86
- });
87
- } else if (drift.length) {
88
- deltas.push({ kind: 'changed', id, line: `~ ${id} ${drift.join(', ')}` });
89
- }
90
- }
91
-
92
- for (const [id, item] of before) {
93
- if (after.has(id)) continue;
94
- deltas.push({ kind: 'removed', id, line: `- ${id} removed (was ${item.status})` });
95
- }
96
-
97
- return deltas;
98
- }
99
-
100
- function main(argv) {
101
- const [fileA, fileB] = argv;
102
- if (!fileA || !fileB || argv.length > 2) {
103
- usage();
104
- return 2;
105
- }
106
-
107
- let snapshotA;
108
- let snapshotB;
109
- try {
110
- snapshotA = loadSnapshot(fileA);
111
- snapshotB = loadSnapshot(fileB);
112
- } catch (error) {
113
- process.stderr.write(`${error.message}\n`);
114
- return 2;
115
- }
116
-
117
- const deltas = diffFindings(snapshotA, snapshotB);
118
- const count = (kind) => deltas.filter((delta) => delta.kind === kind).length;
119
- const lines = [
120
- '# perf-findings diff',
121
- provenanceLine('a', fileA, snapshotA),
122
- provenanceLine('b', fileB, snapshotB),
123
- '',
124
- ];
125
- if (deltas.length) {
126
- lines.push(...deltas.map((delta) => delta.line), '');
127
- }
128
- lines.push(
129
- `${deltas.length} delta${deltas.length === 1 ? '' : 's'}: `
130
- + `${count('added')} added, ${count('removed')} removed, ${count('changed')} changed`,
131
- );
132
- process.stdout.write(`${lines.join('\n')}\n`);
133
- return 0;
134
- }
135
-
136
- process.exitCode = main(process.argv.slice(2));
@@ -1,474 +0,0 @@
1
- {
2
- "generatedAt": "2026-09-20T23:07:33.744Z",
3
- "schema": "ukit-perf-findings/1",
4
- "telemetryRows": 62854,
5
- "telemetryFiles": 120,
6
- "sources": {
7
- "telemetry": {
8
- "dir": "/Volumes/KHOA_EXTENAL/WORKING_PROJECT/WORKING/UKit/.ukit/storage/cache/hook-latency",
9
- "rows": 62854,
10
- "files": 120
11
- },
12
- "settings": "/Volumes/KHOA_EXTENAL/WORKING_PROJECT/WORKING/UKit/template_project/.claude/settings.json",
13
- "hooksDir": "/Volumes/KHOA_EXTENAL/WORKING_PROJECT/WORKING/UKit/template_project/.claude/hooks",
14
- "benchmarkIterations": 2,
15
- "gitLogWindowDays": 14
16
- },
17
- "findings": [
18
- {
19
- "id": "chain-pretooluse-read-grep-glob",
20
- "area": "hook chain — PreToolUse Read|Grep|Glob — 1 hook",
21
- "evidence": "telemetry",
22
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; measured per-call hook cost for the group's matching tools (n=2340, p50 37ms, 2 hook rows/call; paths: 404 direct / 1936 chain-runner). Hooks: sensitive-data-guard.mjs:8 (18s)",
23
- "p50ms": 37,
24
- "p95ms": 72,
25
- "totalMs": 78128,
26
- "invocations": 2340,
27
- "rootCause": "3 process spawns per call (1 settings rows × 3: wrapper bash + node runtime + advisory telemetry node child), against a measured floor of bash 3.1ms + node 16.1ms + telemetry finish 19.5ms. Measured p50 is under the 50ms hotspot bar; consolidation is still the mechanism that removes the spawns.",
28
- "fixTask": "TASK-234",
29
- "status": "confirmed"
30
- },
31
- {
32
- "id": "chain-pretooluse-edit-write",
33
- "area": "hook chain — PreToolUse Edit|Write — 1 hook",
34
- "evidence": "telemetry",
35
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; measured per-call hook cost for the group's matching tools (n=728, p50 331ms, 6 hook rows/call; paths: 402 direct / 326 chain-runner). Hooks: context-hardcap-gate.sh:8 (73s)",
36
- "p50ms": 331,
37
- "p95ms": 429,
38
- "totalMs": 249733,
39
- "invocations": 728,
40
- "rootCause": "3 process spawns per call (1 settings rows × 3: wrapper bash + node runtime + advisory telemetry node child), against a measured floor of bash 3.1ms + node 16.1ms + telemetry finish 19.5ms. Measured p50 exceeds the 50ms hotspot bar, so the spawn multiplier is the dominant term.",
41
- "fixTask": "TASK-234",
42
- "status": "confirmed"
43
- },
44
- {
45
- "id": "chain-pretooluse-bash",
46
- "area": "hook chain — PreToolUse Bash — 1 hook",
47
- "evidence": "telemetry",
48
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; measured per-call hook cost for the group's matching tools (n=4853, p50 307ms, 6 hook rows/call; paths: 2519 direct / 2334 chain-runner). Hooks: verification-guard.sh:8 (65s)",
49
- "p50ms": 307,
50
- "p95ms": 474,
51
- "totalMs": 1559455,
52
- "invocations": 4853,
53
- "rootCause": "3 process spawns per call (1 settings rows × 3: wrapper bash + node runtime + advisory telemetry node child), against a measured floor of bash 3.1ms + node 16.1ms + telemetry finish 19.5ms. Measured p50 exceeds the 50ms hotspot bar, so the spawn multiplier is the dominant term.",
54
- "fixTask": "TASK-234",
55
- "status": "confirmed"
56
- },
57
- {
58
- "id": "chain-posttooluse-read-grep-glob",
59
- "area": "hook chain — PostToolUse Read|Grep|Glob — 1 hook",
60
- "evidence": "telemetry",
61
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; measured per-call hook cost for the group's matching tools (n=2329, p50 37ms, 2 hook rows/call; paths: 393 direct / 1936 chain-runner). Hooks: record-execution.mjs:8 (18s)",
62
- "p50ms": 37,
63
- "p95ms": 118,
64
- "totalMs": 100380,
65
- "invocations": 2329,
66
- "rootCause": "3 process spawns per call (1 settings rows × 3: wrapper bash + node runtime + advisory telemetry node child), against a measured floor of bash 3.1ms + node 16.1ms + telemetry finish 19.5ms. Measured p50 is under the 50ms hotspot bar; consolidation is still the mechanism that removes the spawns.",
67
- "fixTask": "TASK-234",
68
- "status": "confirmed"
69
- },
70
- {
71
- "id": "chain-posttooluse-edit-write",
72
- "area": "hook chain — PostToolUse Edit|Write — 1 hook",
73
- "evidence": "telemetry",
74
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; measured per-call hook cost for the group's matching tools (n=713, p50 130ms, 3 hook rows/call; paths: 397 direct / 316 chain-runner). Hooks: task-watchdog.sh:8 (34s)",
75
- "p50ms": 130,
76
- "p95ms": 222,
77
- "totalMs": 102401,
78
- "invocations": 713,
79
- "rootCause": "3 process spawns per call (1 settings rows × 3: wrapper bash + node runtime + advisory telemetry node child), against a measured floor of bash 3.1ms + node 16.1ms + telemetry finish 19.5ms. Measured p50 exceeds the 50ms hotspot bar, so the spawn multiplier is the dominant term.",
80
- "fixTask": "TASK-234",
81
- "status": "confirmed"
82
- },
83
- {
84
- "id": "chain-posttooluse-bash",
85
- "area": "hook chain — PostToolUse Bash — 1 hook",
86
- "evidence": "telemetry",
87
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; measured per-call hook cost for the group's matching tools (n=4701, p50 87ms, 2 hook rows/call; paths: 2406 direct / 2295 chain-runner). Hooks: record-execution.mjs:8 (30s)",
88
- "p50ms": 87,
89
- "p95ms": 150,
90
- "totalMs": 449914,
91
- "invocations": 4701,
92
- "rootCause": "3 process spawns per call (1 settings rows × 3: wrapper bash + node runtime + advisory telemetry node child), against a measured floor of bash 3.1ms + node 16.1ms + telemetry finish 19.5ms. Measured p50 exceeds the 50ms hotspot bar, so the spawn multiplier is the dominant term.",
93
- "fixTask": "TASK-234",
94
- "status": "confirmed"
95
- },
96
- {
97
- "id": "chain-userpromptsubmit-all",
98
- "area": "hook chain — UserPromptSubmit (all tools) — 1 hook",
99
- "evidence": "telemetry",
100
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; measured per-call hook cost for the group's matching tools (n=349, p50 291ms, 4 hook rows/call; paths: 200 direct / 149 chain-runner). Hooks: context-window-guard.sh:10 (60s)",
101
- "p50ms": 291,
102
- "p95ms": 582,
103
- "totalMs": 101608,
104
- "invocations": 349,
105
- "rootCause": "3 process spawns per call (1 settings rows × 3: wrapper bash + node runtime + advisory telemetry node child), against a measured floor of bash 3.1ms + node 16.1ms + telemetry finish 19.5ms. Measured p50 exceeds the 50ms hotspot bar, so the spawn multiplier is the dominant term.",
106
- "fixTask": "TASK-234",
107
- "status": "confirmed"
108
- },
109
- {
110
- "id": "chain-stop-all",
111
- "area": "hook chain — Stop (all tools) — 1 hook",
112
- "evidence": "telemetry",
113
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; measured per-call hook cost for the group's matching tools (n=116, p50 81ms, 1 hook rows/call; paths: 113 direct / 3 chain-runner). Hooks: completion-gate.sh:8 (18s)",
114
- "p50ms": 81,
115
- "p95ms": 111,
116
- "totalMs": 9890,
117
- "invocations": 116,
118
- "rootCause": "3 process spawns per call (1 settings rows × 3: wrapper bash + node runtime + advisory telemetry node child), against a measured floor of bash 3.1ms + node 16.1ms + telemetry finish 19.5ms. Measured p50 exceeds the 50ms hotspot bar, so the spawn multiplier is the dominant term.",
119
- "fixTask": "TASK-234",
120
- "status": "confirmed"
121
- },
122
- {
123
- "id": "chain-precompact-all",
124
- "area": "hook chain — PreCompact (all tools) — 1 hook",
125
- "evidence": "telemetry",
126
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; measured per-call hook cost for the group's matching tools (n=6, p50 49ms, 1 hook rows/call; paths: 0 direct / 6 chain-runner). Hooks: reinject-context.sh:8 (18s)",
127
- "p50ms": 49,
128
- "p95ms": 53,
129
- "totalMs": 260,
130
- "invocations": 6,
131
- "rootCause": "3 process spawns per call (1 settings rows × 3: wrapper bash + node runtime + advisory telemetry node child), against a measured floor of bash 3.1ms + node 16.1ms + telemetry finish 19.5ms. Measured p50 is under the 50ms hotspot bar; consolidation is still the mechanism that removes the spawns.",
132
- "fixTask": "TASK-234",
133
- "status": "confirmed"
134
- },
135
- {
136
- "id": "chain-sessionstart-all",
137
- "area": "hook chain — SessionStart (all tools) — 1 hook",
138
- "evidence": "telemetry",
139
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; measured per-call hook cost for the group's matching tools (n=113, p50 119ms, 2 hook rows/call; paths: 38 direct / 75 chain-runner). Hooks: handoff-resume.sh:8 (50s)",
140
- "p50ms": 119,
141
- "p95ms": 289,
142
- "totalMs": 16463,
143
- "invocations": 113,
144
- "rootCause": "3 process spawns per call (1 settings rows × 3: wrapper bash + node runtime + advisory telemetry node child), against a measured floor of bash 3.1ms + node 16.1ms + telemetry finish 19.5ms. Measured p50 exceeds the 50ms hotspot bar, so the spawn multiplier is the dominant term.",
145
- "fixTask": "TASK-234",
146
- "status": "confirmed"
147
- },
148
- {
149
- "id": "chain-sessionend-all",
150
- "area": "hook chain — SessionEnd (all tools) — 1 hook",
151
- "evidence": "telemetry",
152
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; measured per-call hook cost for the group's matching tools (n=1, p50 2020ms, 1 hook rows/call; paths: 0 direct / 1 chain-runner). Hooks: session-episode.sh:8 (18s)",
153
- "p50ms": 2020,
154
- "p95ms": 2020,
155
- "totalMs": 2020,
156
- "invocations": 1,
157
- "rootCause": "3 process spawns per call (1 settings rows × 3: wrapper bash + node runtime + advisory telemetry node child), against a measured floor of bash 3.1ms + node 16.1ms + telemetry finish 19.5ms. Measured p50 exceeds the 50ms hotspot bar, so the spawn multiplier is the dominant term.",
158
- "fixTask": "TASK-234",
159
- "status": "confirmed"
160
- },
161
- {
162
- "id": "hook-hook-chain-runner",
163
- "area": "single hook — hook-chain-runner",
164
- "evidence": "telemetry",
165
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; standalone re-run p50 not benchmarked (script not resolvable from this root)",
166
- "p50ms": 80,
167
- "p95ms": 375,
168
- "totalMs": 1269815,
169
- "invocations": 9453,
170
- "rootCause": "per-invocation cost is dominated by the 3-spawn hook row (wrapper bash 3.1ms + node 16.1ms + telemetry finish 19.5ms), plus this script's own work",
171
- "fixTask": "TASK-234",
172
- "status": "confirmed"
173
- },
174
- {
175
- "id": "hook-skill-router-sh",
176
- "area": "single hook — skill-router.sh",
177
- "evidence": "telemetry",
178
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; standalone re-run p50 not benchmarked (script not resolvable from this root)",
179
- "p50ms": 52,
180
- "p95ms": 134,
181
- "totalMs": 68680,
182
- "invocations": 1089,
183
- "rootCause": "per-invocation cost is dominated by the 3-spawn hook row (wrapper bash 3.1ms + node 16.1ms + telemetry finish 19.5ms), plus this script's own work",
184
- "fixTask": "TASK-234",
185
- "status": "confirmed"
186
- },
187
- {
188
- "id": "hook-vision-router-sh",
189
- "area": "single hook — vision-router.sh",
190
- "evidence": "telemetry",
191
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; standalone re-run p50 not benchmarked (script not resolvable from this root)",
192
- "p50ms": 73,
193
- "p95ms": 220,
194
- "totalMs": 29834,
195
- "invocations": 325,
196
- "rootCause": "per-invocation cost is dominated by the 3-spawn hook row (wrapper bash 3.1ms + node 16.1ms + telemetry finish 19.5ms), plus this script's own work",
197
- "fixTask": "TASK-234",
198
- "status": "confirmed"
199
- },
200
- {
201
- "id": "hook-block-dangerous-sh",
202
- "area": "single hook — block-dangerous.sh",
203
- "evidence": "telemetry",
204
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; standalone re-run p50 not benchmarked (script not resolvable from this root)",
205
- "p50ms": 83,
206
- "p95ms": 237,
207
- "totalMs": 461434,
208
- "invocations": 5107,
209
- "rootCause": "per-invocation cost is dominated by the 3-spawn hook row (wrapper bash 3.1ms + node 16.1ms + telemetry finish 19.5ms), plus this script's own work",
210
- "fixTask": "TASK-234",
211
- "status": "confirmed"
212
- },
213
- {
214
- "id": "hook-context-hardcap-gate-sh",
215
- "area": "single hook — context-hardcap-gate.sh",
216
- "evidence": "telemetry",
217
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; standalone re-run p50 not benchmarked (script not resolvable from this root)",
218
- "p50ms": 55,
219
- "p95ms": 88,
220
- "totalMs": 334184,
221
- "invocations": 5650,
222
- "rootCause": "per-invocation cost is dominated by the 3-spawn hook row (wrapper bash 3.1ms + node 16.1ms + telemetry finish 19.5ms), plus this script's own work",
223
- "fixTask": "TASK-234",
224
- "status": "confirmed"
225
- },
226
- {
227
- "id": "hook-completion-gate-sh",
228
- "area": "single hook — completion-gate.sh",
229
- "evidence": "telemetry",
230
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; standalone re-run p50 not benchmarked (script not resolvable from this root)",
231
- "p50ms": 80,
232
- "p95ms": 108,
233
- "totalMs": 9881,
234
- "invocations": 119,
235
- "rootCause": "per-invocation cost is dominated by the 3-spawn hook row (wrapper bash 3.1ms + node 16.1ms + telemetry finish 19.5ms), plus this script's own work",
236
- "fixTask": "TASK-234",
237
- "status": "confirmed"
238
- },
239
- {
240
- "id": "hook-project-important-tail",
241
- "area": "project-important.sh — PROJECT_IMPORTANT.md injection tail",
242
- "evidence": "telemetry",
243
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; bimodal across 47 invocations: p50 38ms vs p95 61ms vs max 62ms (paths seen: PreToolUse, SessionStart) — a cheap path and an expensive path with no cache between them",
244
- "p50ms": null,
245
- "p95ms": 61,
246
- "totalMs": 1962,
247
- "invocations": 47,
248
- "rootCause": "the renderer re-reads PROJECT_IMPORTANT.md and re-runs its full work (strict UTF-8 decode, control-character validation, sensitive-value scan, envelope render) on every invocation; there is no mtime/content-keyed cache, so repeat runs pay the whole cost instead of replaying the previous result",
249
- "fixTask": "TASK-235",
250
- "status": "confirmed"
251
- },
252
- {
253
- "id": "record-execution-multiplicity",
254
- "area": "record-execution.sh — PostToolUse receipt writer registered in 0 matcher groups",
255
- "evidence": "telemetry",
256
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; measured fire count per tool call = 4 (distribution {\"1\":4873,\"3\":1,\"4\":1} over 4875 calls). The \"once per matching matcher group\" repeat hypothesis is REFUTED: settings.json names the hook in 0 groups, but those matchers are mutually exclusive per tool, so it runs exactly once per call. Its real cost is breadth — highest-invocation hook measured (n=4880, p50 39ms, total 207226ms).",
257
- "p50ms": 39,
258
- "p95ms": 63,
259
- "totalMs": 207226,
260
- "invocations": 4880,
261
- "rootCause": "not a duplication bug: the matchers (Read|Grep|Glob, Edit|Write, Bash) are mutually exclusive, so at most one group fires per tool. The cost is that one full 3-spawn hook row is paid on every tool call of every kind — breadth, not repeats.",
262
- "fixTask": null,
263
- "status": "not-a-bug"
264
- },
265
- {
266
- "id": "index-router-cold-start",
267
- "area": "index/router helpers invoked per prompt (skill-router → resolve-context / route-task / query-index)",
268
- "evidence": "telemetry",
269
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; UserPromptSubmit groups: n=349, p50 291ms, p95 582ms, 4 hook rows/group. Standalone cold starts: skill-router.sh 105.2ms, query-index.mjs 23.6ms, route-task.mjs 26.4ms, resolve-context.mjs 21.9ms",
270
- "p50ms": 291,
271
- "p95ms": 582,
272
- "totalMs": 101608,
273
- "invocations": 349,
274
- "rootCause": "every router helper pays a fresh node cold start (no warm process is reused), and skill-router.sh additionally imports the index core in-process per invocation; the cost is process boot plus module load, not the routing decision itself",
275
- "fixTask": "TASK-234",
276
- "status": "confirmed"
277
- },
278
- {
279
- "id": "c29-c32-hot-path-additions",
280
- "area": "recent hot-path additions — 24 files across 18 commits",
281
- "evidence": "git-log",
282
- "evidenceDetail": "git log --since=14 days ago --diff-filter=A -- template_project/.claude/hooks template_project/.claude/ukit/runtime template_project/.claude/ukit/index: template_project/.claude/hooks/block-dangerous.mjs, template_project/.claude/hooks/record-execution.mjs, template_project/.claude/hooks/sensitive-data-guard.mjs, template_project/.claude/ukit/runtime/hook-field-salvage.mjs, template_project/.claude/hooks/session-episode.sh, template_project/.claude/hooks/project-important.sh, template_project/.claude/hooks/project-important.sh, template_project/.claude/ukit/runtime/project-important.mjs, template_project/.claude/ukit/runtime/sensitive-value-scanner.mjs, template_project/.claude/ukit/runtime/hook-chain-budget.mjs, template_project/.claude/ukit/runtime/stop-coordinator.mjs, template_project/.claude/ukit/runtime/hook-payload-store.mjs, +12 more",
283
- "p50ms": null,
284
- "p95ms": null,
285
- "totalMs": null,
286
- "invocations": 24,
287
- "rootCause": "each added hook file becomes another settings.json row on the event it joins, i.e. another 3-spawn hook row per call (SPEC §1.3 consolidation is what removes them); each added runtime module is an extra cold-start import paid per invocation. The regression is additive spawn count, not one slow file.",
288
- "fixTask": "TASK-234",
289
- "status": "confirmed"
290
- },
291
- {
292
- "id": "existing-chain-runner-baseline",
293
- "area": "hook-chain-runner.mjs — already-consolidated omp path (TASK-234 reuse target)",
294
- "evidence": "telemetry",
295
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; a whole chain of 1 scripts runs in ONE node process at p50 80ms / p95 375ms (n=9453), while a Claude settings group of comparable size pays 3 spawns per script. Nested per-script rows: record-execution.mjs p50 5ms, sensitive-data-guard.mjs p50 4ms, handoff-model-guard.sh p50 39ms, context-hardcap-gate.sh p50 68ms, auto-allow-bash.sh p50 72ms, compress-output.sh p50 73ms",
296
- "p50ms": 80,
297
- "p95ms": 375,
298
- "totalMs": 1269815,
299
- "invocations": 9453,
300
- "rootCause": "no defect — this is the measured proof that one-process-per-group execution is achievable with per-script telemetry intact, so TASK-234 should re-point settings.json at this runner rather than build a new one",
301
- "fixTask": "TASK-234",
302
- "status": "confirmed"
303
- },
304
- {
305
- "id": "process-floor",
306
- "area": "process spawn floor (bash + node + advisory telemetry child)",
307
- "evidence": "micro-benchmark",
308
- "evidenceDetail": "live spawnSync over 2 iterations: bash -c true p50 3.13ms, node -e 0 p50 16.11ms, node hook-telemetry.mjs --finish p50 19.50ms",
309
- "p50ms": 38.73741700000001,
310
- "p95ms": 38.73741700000001,
311
- "totalMs": null,
312
- "invocations": 0,
313
- "rootCause": "each settings.json hook row is a bash wrapper that boots node, then arms a second node child for advisory telemetry; this floor is paid per row, so it multiplies by the row count of the event",
314
- "fixTask": "TASK-234",
315
- "status": "not-a-bug"
316
- },
317
- {
318
- "id": "telemetry-append-overhead",
319
- "area": "telemetry append overhead — appendTelemetryRow, in-process against a throwaway project root",
320
- "evidence": "micro-benchmark",
321
- "evidenceDetail": "appendTelemetryRow over 2 iterations against a temp project root (the audited telemetry dir is never written): p50 0.407ms, p95 0.407ms, max 0.407ms, total 0.464ms; writer template_project/.claude/ukit/runtime/hook-telemetry.mjs",
322
- "p50ms": 0.407125,
323
- "p95ms": 0.407125,
324
- "totalMs": 0.464083,
325
- "invocations": 2,
326
- "rootCause": "one synchronous append costs p50 0.407ms (under the 50ms hotspot bar): the observability layer's own I/O is bounded by a single append plus an amortized 1-in-16 sampled sweep, so it is not the hook chain's dominant term",
327
- "fixTask": null,
328
- "status": "not-a-bug"
329
- },
330
- {
331
- "id": "stdin-stage-vs-exec-split",
332
- "area": "stdin stage vs execution split (O3 — the wall-time tail attributed)",
333
- "evidence": "unavailable",
334
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; no row carries `stdinStageMs` or `stageMs`, so the exec-vs-stage split is unmeasured on this tree. Old rows keep aggregating exactly as before — the fields are additive and optional, so their absence is reported rather than guessed at as 0ms.",
335
- "p50ms": null,
336
- "p95ms": null,
337
- "totalMs": null,
338
- "invocations": 0,
339
- "rootCause": "the split needs rows written after the fields shipped; a dataset predating them yields no numbers at all (null, not zero), which is the null-safe posture the audit reports here",
340
- "fixTask": null,
341
- "status": "deferred"
342
- },
343
- {
344
- "id": "hook-sensitive-data-guard-mjs-8-unmeasured",
345
- "area": "single hook — sensitive-data-guard.mjs:8 (registered in settings.json, no telemetry rows)",
346
- "evidence": "unavailable",
347
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; no row exists for this script, so no per-invocation number is reported. It still costs 3 spawns on its event and is therefore already counted inside that chain's total.",
348
- "p50ms": null,
349
- "p95ms": null,
350
- "totalMs": null,
351
- "invocations": 0,
352
- "rootCause": "no measurement exists for sensitive-data-guard.mjs:8 on this tree — its cost stays unset (evidenced by absence) rather than estimated; the chain it belongs to carries the spawn floor",
353
- "fixTask": null,
354
- "status": "deferred"
355
- },
356
- {
357
- "id": "hook-context-hardcap-gate-sh-8-unmeasured",
358
- "area": "single hook — context-hardcap-gate.sh:8 (registered in settings.json, no telemetry rows)",
359
- "evidence": "unavailable",
360
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; no row exists for this script, so no per-invocation number is reported. It still costs 3 spawns on its event and is therefore already counted inside that chain's total.",
361
- "p50ms": null,
362
- "p95ms": null,
363
- "totalMs": null,
364
- "invocations": 0,
365
- "rootCause": "no measurement exists for context-hardcap-gate.sh:8 on this tree — its cost stays unset (evidenced by absence) rather than estimated; the chain it belongs to carries the spawn floor",
366
- "fixTask": null,
367
- "status": "deferred"
368
- },
369
- {
370
- "id": "hook-verification-guard-sh-8-unmeasured",
371
- "area": "single hook — verification-guard.sh:8 (registered in settings.json, no telemetry rows)",
372
- "evidence": "unavailable",
373
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; no row exists for this script, so no per-invocation number is reported. It still costs 3 spawns on its event and is therefore already counted inside that chain's total.",
374
- "p50ms": null,
375
- "p95ms": null,
376
- "totalMs": null,
377
- "invocations": 0,
378
- "rootCause": "no measurement exists for verification-guard.sh:8 on this tree — its cost stays unset (evidenced by absence) rather than estimated; the chain it belongs to carries the spawn floor",
379
- "fixTask": null,
380
- "status": "deferred"
381
- },
382
- {
383
- "id": "hook-record-execution-mjs-8-unmeasured",
384
- "area": "single hook — record-execution.mjs:8 (registered in settings.json, no telemetry rows)",
385
- "evidence": "unavailable",
386
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; no row exists for this script, so no per-invocation number is reported. It still costs 3 spawns on its event and is therefore already counted inside that chain's total.",
387
- "p50ms": null,
388
- "p95ms": null,
389
- "totalMs": null,
390
- "invocations": 0,
391
- "rootCause": "no measurement exists for record-execution.mjs:8 on this tree — its cost stays unset (evidenced by absence) rather than estimated; the chain it belongs to carries the spawn floor",
392
- "fixTask": null,
393
- "status": "deferred"
394
- },
395
- {
396
- "id": "hook-task-watchdog-sh-8-unmeasured",
397
- "area": "single hook — task-watchdog.sh:8 (registered in settings.json, no telemetry rows)",
398
- "evidence": "unavailable",
399
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; no row exists for this script, so no per-invocation number is reported. It still costs 3 spawns on its event and is therefore already counted inside that chain's total.",
400
- "p50ms": null,
401
- "p95ms": null,
402
- "totalMs": null,
403
- "invocations": 0,
404
- "rootCause": "no measurement exists for task-watchdog.sh:8 on this tree — its cost stays unset (evidenced by absence) rather than estimated; the chain it belongs to carries the spawn floor",
405
- "fixTask": null,
406
- "status": "deferred"
407
- },
408
- {
409
- "id": "hook-context-window-guard-sh-10-unmeasured",
410
- "area": "single hook — context-window-guard.sh:10 (registered in settings.json, no telemetry rows)",
411
- "evidence": "unavailable",
412
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; no row exists for this script, so no per-invocation number is reported. It still costs 3 spawns on its event and is therefore already counted inside that chain's total.",
413
- "p50ms": null,
414
- "p95ms": null,
415
- "totalMs": null,
416
- "invocations": 0,
417
- "rootCause": "no measurement exists for context-window-guard.sh:10 on this tree — its cost stays unset (evidenced by absence) rather than estimated; the chain it belongs to carries the spawn floor",
418
- "fixTask": null,
419
- "status": "deferred"
420
- },
421
- {
422
- "id": "hook-completion-gate-sh-8-unmeasured",
423
- "area": "single hook — completion-gate.sh:8 (registered in settings.json, no telemetry rows)",
424
- "evidence": "unavailable",
425
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; no row exists for this script, so no per-invocation number is reported. It still costs 3 spawns on its event and is therefore already counted inside that chain's total.",
426
- "p50ms": null,
427
- "p95ms": null,
428
- "totalMs": null,
429
- "invocations": 0,
430
- "rootCause": "no measurement exists for completion-gate.sh:8 on this tree — its cost stays unset (evidenced by absence) rather than estimated; the chain it belongs to carries the spawn floor",
431
- "fixTask": null,
432
- "status": "deferred"
433
- },
434
- {
435
- "id": "hook-reinject-context-sh-8-unmeasured",
436
- "area": "single hook — reinject-context.sh:8 (registered in settings.json, no telemetry rows)",
437
- "evidence": "unavailable",
438
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; no row exists for this script, so no per-invocation number is reported. It still costs 3 spawns on its event and is therefore already counted inside that chain's total.",
439
- "p50ms": null,
440
- "p95ms": null,
441
- "totalMs": null,
442
- "invocations": 0,
443
- "rootCause": "no measurement exists for reinject-context.sh:8 on this tree — its cost stays unset (evidenced by absence) rather than estimated; the chain it belongs to carries the spawn floor",
444
- "fixTask": null,
445
- "status": "deferred"
446
- },
447
- {
448
- "id": "hook-handoff-resume-sh-8-unmeasured",
449
- "area": "single hook — handoff-resume.sh:8 (registered in settings.json, no telemetry rows)",
450
- "evidence": "unavailable",
451
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; no row exists for this script, so no per-invocation number is reported. It still costs 3 spawns on its event and is therefore already counted inside that chain's total.",
452
- "p50ms": null,
453
- "p95ms": null,
454
- "totalMs": null,
455
- "invocations": 0,
456
- "rootCause": "no measurement exists for handoff-resume.sh:8 on this tree — its cost stays unset (evidenced by absence) rather than estimated; the chain it belongs to carries the spawn floor",
457
- "fixTask": null,
458
- "status": "deferred"
459
- },
460
- {
461
- "id": "hook-session-episode-sh-8-unmeasured",
462
- "area": "single hook — session-episode.sh:8 (registered in settings.json, no telemetry rows)",
463
- "evidence": "unavailable",
464
- "evidenceDetail": ".ukit/storage/cache/hook-latency — 62854 rows across 120 session files, span 2026-09-17T10:50:18.670Z → 2026-09-20T23:07:33.053Z; no row exists for this script, so no per-invocation number is reported. It still costs 3 spawns on its event and is therefore already counted inside that chain's total.",
465
- "p50ms": null,
466
- "p95ms": null,
467
- "totalMs": null,
468
- "invocations": 0,
469
- "rootCause": "no measurement exists for session-episode.sh:8 on this tree — its cost stays unset (evidenced by absence) rather than estimated; the chain it belongs to carries the spawn floor",
470
- "fixTask": null,
471
- "status": "deferred"
472
- }
473
- ]
474
- }