@ngockhoale/ukit 2.4.2 → 2.4.3
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/manifests/platform.full.yaml +19 -111
- package/package.json +2 -1
- package/scripts/index/refresh-index.mjs +47 -22
- package/src/core/compact/threshold.js +36 -6
- package/src/diagnostics/classifyHang.js +246 -0
- package/src/index/buildIndex.js +1033 -62
- package/templates/.claude/hooks/auto-allow-bash.sh +82 -93
- package/templates/.claude/hooks/block-dangerous.sh +31 -5
- package/templates/.claude/hooks/completion-gate.sh +51 -10
- package/templates/.claude/hooks/compress-output.sh +38 -6
- package/templates/.claude/hooks/context-hardcap-gate.sh +35 -6
- package/templates/.claude/hooks/context-window-guard.sh +128 -18
- package/templates/.claude/hooks/handoff-model-guard.sh +31 -5
- package/templates/.claude/hooks/handoff-resume.sh +31 -5
- package/templates/.claude/hooks/post-edit-verify.sh +31 -5
- package/templates/.claude/hooks/pre-edit-backup.sh +31 -5
- package/templates/.claude/hooks/protect-files.sh +31 -5
- package/templates/.claude/hooks/record-execution.sh +31 -5
- package/templates/.claude/hooks/sensitive-data-guard.sh +44 -8
- package/templates/.claude/hooks/skill-router.sh +31 -5
- package/templates/.claude/hooks/stale-spec-guard.sh +31 -5
- package/templates/.claude/hooks/task-watchdog.sh +108 -123
- package/templates/.claude/hooks/verification-guard.sh +107 -112
- package/templates/.claude/hooks/vision-router.sh +49 -13
- package/templates/.claude/settings.json +0 -5
- package/templates/.claude/ukit/index/lib/index-core.mjs +960 -63
- package/templates/.claude/ukit/index/refresh-index.mjs +47 -22
- package/templates/.claude/ukit/index/route-task.mjs +610 -4
- package/templates/.claude/ukit/runtime/async-lock.mjs +340 -0
- package/templates/.claude/ukit/runtime/compact-threshold.mjs +73 -24
- package/templates/.claude/ukit/runtime/context-capacity.mjs +144 -0
- package/templates/.claude/ukit/runtime/execution-ledger.mjs +664 -170
- package/templates/.claude/ukit/runtime/hook-chain-budget.mjs +92 -0
- package/templates/.claude/ukit/runtime/hook-chain-runner.mjs +84 -29
- package/templates/.claude/ukit/runtime/hook-input.sh +85 -5
- package/templates/.claude/ukit/runtime/hook-payload-store.mjs +160 -0
- package/templates/.claude/ukit/runtime/hook-process.mjs +250 -0
- package/templates/.claude/ukit/runtime/hook-telemetry.mjs +255 -0
- package/templates/.claude/ukit/runtime/hook-telemetry.sh +60 -0
- package/templates/.claude/ukit/runtime/stop-coordinator.mjs +509 -0
- package/templates/.claude/ukit/runtime/task-watchdog.mjs +180 -6
- package/templates/.claude/ukit/runtime/transcript-tail.mjs +1 -1
- package/templates/.omp/hooks/pre/ukit-bridge.js +171 -57
|
@@ -22,16 +22,42 @@
|
|
|
22
22
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
23
23
|
# shellcheck source=/dev/null
|
|
24
24
|
if source "$SCRIPT_DIR/../ukit/runtime/hook-input.sh" 2>/dev/null; then
|
|
25
|
+
# TASK-019: arm advisory latency telemetry; the finish row is written by the
|
|
26
|
+
# shared cleanup path before the staged payload is removed. A missing
|
|
27
|
+
# runtime (pre-install tree) simply leaves telemetry off.
|
|
28
|
+
source "$SCRIPT_DIR/../ukit/runtime/hook-telemetry.sh" 2>/dev/null || true
|
|
25
29
|
trap ukit_cleanup_hook_input EXIT
|
|
26
30
|
# Bounded stdin (H01): stage before anything reads it; Node gets a path, never the payload.
|
|
27
31
|
ukit_stage_hook_input 2097152 truncate || exit 0
|
|
28
32
|
else
|
|
29
|
-
# Runtime helper missing (pre-install tree): bounded
|
|
30
|
-
#
|
|
33
|
+
# Runtime helper missing (pre-install tree): the SAME bounded staging,
|
|
34
|
+
# inline - `cat >/dev/null` used to block forever on a producer that never
|
|
35
|
+
# closes the pipe (R4.5). Read cap+1 in the background, bound the wait.
|
|
31
36
|
UKIT_INPUT_FILE="$(mktemp "${TMPDIR:-/tmp}/ukit-hook-in.XXXXXX")"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
37
|
+
if [ -e /dev/fd/0 ]; then
|
|
38
|
+
exec 8<&0
|
|
39
|
+
head -c 2097153 <&8 > "$UKIT_INPUT_FILE" 2>/dev/null &
|
|
40
|
+
else
|
|
41
|
+
head -c 2097153 > "$UKIT_INPUT_FILE" 2>/dev/null &
|
|
42
|
+
fi
|
|
43
|
+
__ukit_reader=$!
|
|
44
|
+
__ukit_stage_ms="${UKIT_HOOK_STAGE_MS:-2000}"
|
|
45
|
+
case "$__ukit_stage_ms" in
|
|
46
|
+
''|*[!0-9]*) __ukit_stage_ms=2000 ;;
|
|
47
|
+
esac
|
|
48
|
+
[ "$__ukit_stage_ms" -gt 0 ] 2>/dev/null || __ukit_stage_ms=2000
|
|
49
|
+
printf -v __ukit_stage_s '%d.%03d' $((__ukit_stage_ms / 1000)) $((__ukit_stage_ms % 1000))
|
|
50
|
+
( sleep "$__ukit_stage_s" 2>/dev/null; kill -9 "$__ukit_reader" 2>/dev/null ) <&- >/dev/null 2>&1 &
|
|
51
|
+
__ukit_waiter=$!
|
|
52
|
+
wait "$__ukit_reader" 2>/dev/null
|
|
53
|
+
__ukit_stage_rc=$?
|
|
54
|
+
kill "$__ukit_waiter" 2>/dev/null
|
|
55
|
+
wait "$__ukit_waiter" 2>/dev/null
|
|
56
|
+
exec 8<&-
|
|
57
|
+
__ukit_size="$(wc -c < "$UKIT_INPUT_FILE" 2>/dev/null | tr -d '[:space:]')"
|
|
58
|
+
# A bounded cut (rc != 0) leaves a short payload that the JSON consumer
|
|
59
|
+
# already degrades on - the shared helper's truncate posture (R4.5).
|
|
60
|
+
if [ "$__ukit_size" -gt 2097152 ]; then
|
|
35
61
|
truncate -s 2097152 "$UKIT_INPUT_FILE" 2>/dev/null
|
|
36
62
|
fi
|
|
37
63
|
trap '[ -n "$UKIT_INPUT_FILE" ] && rm -f "$UKIT_INPUT_FILE"' EXIT
|
|
@@ -41,7 +67,7 @@ PROJECT_ROOT="${CLAUDE_PROJECT_DIR:-$PWD}"
|
|
|
41
67
|
INPUT_FILE="$UKIT_INPUT_FILE" PROJECT_ROOT="$PROJECT_ROOT" node <<'NODE' || true
|
|
42
68
|
const HOOK_DEADLINE_MS = Number.parseInt(process.env.UKIT_HOOK_DEADLINE_MS || '', 10) || 8000;
|
|
43
69
|
setTimeout(() => process.exit(0), HOOK_DEADLINE_MS).unref();
|
|
44
|
-
const fs = require('fs');
|
|
70
|
+
const fs = require('fs').promises;
|
|
45
71
|
const path = require('path');
|
|
46
72
|
const { spawn } = require('child_process');
|
|
47
73
|
const { pathToFileURL } = require('url');
|
|
@@ -59,9 +85,15 @@ process.on('exit', () => {
|
|
|
59
85
|
}
|
|
60
86
|
});
|
|
61
87
|
|
|
62
|
-
|
|
63
|
-
|
|
88
|
+
// TASK-015 fix round 1: every hot-path fs call is awaited. A synchronous read
|
|
89
|
+
// parks the event loop for the whole syscall, so the unref'd self-deadline above
|
|
90
|
+
// could never fire while a project filesystem stalled.
|
|
91
|
+
async function readTextSafe(filePath) {
|
|
92
|
+
try { return await fs.readFile(filePath, 'utf8'); } catch { return ''; }
|
|
93
|
+
}
|
|
94
|
+
|
|
64
95
|
(async () => {
|
|
96
|
+
const rawInput = await readTextSafe(process.env.INPUT_FILE || '');
|
|
65
97
|
const payload = (() => {
|
|
66
98
|
try {
|
|
67
99
|
const parsed = JSON.parse(rawInput);
|
|
@@ -86,7 +118,7 @@ try { rawInput = fs.readFileSync(process.env.INPUT_FILE || '', 'utf8'); } catch
|
|
|
86
118
|
async function detectUnicModeSafe() {
|
|
87
119
|
try {
|
|
88
120
|
const gatewayPath = path.join(projectRoot, '.claude', 'ukit', 'index', 'unic-gateway.mjs');
|
|
89
|
-
|
|
121
|
+
try { await fs.access(gatewayPath); } catch { return null; }
|
|
90
122
|
const mod = await import(pathToFileURL(gatewayPath).href);
|
|
91
123
|
if (typeof mod.detectUnicGateway !== 'function') return null;
|
|
92
124
|
return !!mod.detectUnicGateway({ rootDir: projectRoot })?.unicMode;
|
|
@@ -135,7 +167,7 @@ try { rawInput = fs.readFileSync(process.env.INPUT_FILE || '', 'utf8'); } catch
|
|
|
135
167
|
// pair) and silently skips it. Kept here as a small inline copy rather than
|
|
136
168
|
// a cross-file import — the contract is a few lines, the cost of drift is
|
|
137
169
|
// small, and the hook must stay self-contained (no module resolution).
|
|
138
|
-
function stripPathNoise(raw) {
|
|
170
|
+
async function stripPathNoise(raw) {
|
|
139
171
|
const value = String(raw ?? '').trim();
|
|
140
172
|
if (!value) return value;
|
|
141
173
|
const pairs = { '(': ')', '[': ']', '{': '}', '"': '"', "'": "'" };
|
|
@@ -168,7 +200,8 @@ try { rawInput = fs.readFileSync(process.env.INPUT_FILE || '', 'utf8'); } catch
|
|
|
168
200
|
for (const c of candidates) {
|
|
169
201
|
if (!c) continue;
|
|
170
202
|
try {
|
|
171
|
-
|
|
203
|
+
await fs.access(path.resolve(c));
|
|
204
|
+
return c;
|
|
172
205
|
} catch {
|
|
173
206
|
// ignore
|
|
174
207
|
}
|
|
@@ -236,7 +269,8 @@ try { rawInput = fs.readFileSync(process.env.INPUT_FILE || '', 'utf8'); } catch
|
|
|
236
269
|
// string inside the extractor.
|
|
237
270
|
let extractorJson = null;
|
|
238
271
|
const extractorPath = path.join(projectRoot, '.claude', 'ukit', 'index', 'extract-image.mjs');
|
|
239
|
-
|
|
272
|
+
try {
|
|
273
|
+
await fs.access(extractorPath);
|
|
240
274
|
const args = [extractorPath, '--detect', '--mark-pending', '--json'];
|
|
241
275
|
if (typeof payload?.transcript_path === 'string' && payload.transcript_path.trim()) {
|
|
242
276
|
args.push('--session', payload.transcript_path.trim());
|
|
@@ -248,7 +282,7 @@ try { rawInput = fs.readFileSync(process.env.INPUT_FILE || '', 'utf8'); } catch
|
|
|
248
282
|
// Mirror extractor's resolveRefs input contract: the LLM sometimes leaves
|
|
249
283
|
// trailing punctuation/quotes on a path named in a prompt. Clean before
|
|
250
284
|
// handing off so the hook and the extractor agree on the ref string.
|
|
251
|
-
args.push('--ref', stripPathNoise(ref));
|
|
285
|
+
args.push('--ref', await stripPathNoise(ref));
|
|
252
286
|
}
|
|
253
287
|
let out = null;
|
|
254
288
|
try {
|
|
@@ -260,6 +294,8 @@ try { rawInput = fs.readFileSync(process.env.INPUT_FILE || '', 'utf8'); } catch
|
|
|
260
294
|
const head = typeof out === 'string' && out ? `; output head: ${out.slice(0, 200)}` : '';
|
|
261
295
|
process.stderr.write(`vision-router: extractor call skipped (${err?.message ?? err})${head}\n`);
|
|
262
296
|
}
|
|
297
|
+
} catch {
|
|
298
|
+
// Missing extractor is a normal fail-open condition.
|
|
263
299
|
}
|
|
264
300
|
|
|
265
301
|
// TASK-006 contract: in --mark-pending --json mode `images[]` is the
|
|
@@ -208,11 +208,6 @@
|
|
|
208
208
|
"type": "command",
|
|
209
209
|
"command": "\"$CLAUDE_PROJECT_DIR/.claude/hooks/completion-gate.sh\"",
|
|
210
210
|
"timeout": 4
|
|
211
|
-
},
|
|
212
|
-
{
|
|
213
|
-
"type": "command",
|
|
214
|
-
"command": "\"$CLAUDE_PROJECT_DIR/.claude/hooks/task-watchdog.sh\"",
|
|
215
|
-
"timeout": 4
|
|
216
211
|
}
|
|
217
212
|
]
|
|
218
213
|
}
|