← back to Ticket System
TK-11372: post-patch blocking audit; split the skills scan to TK-11499
e8d4f1be12021ae395708a12767c7471a1f9190b · 2026-09-11 12:09:03 -0700 · Steve Abrams
Confirms the patch did not close one blocking call while leaving another in a
request path: server.js and lib.js now have zero sync subprocess calls, and
lib.js matters because tickets()/messages() run per request.
Secondary, deliberately NOT folded in: installedSkills() walks 583+22 dirs
with sync readFileSync+statSync, uncached, per GET /api/skills -- measured
mean 58ms / worst 502ms of loop blocking. Two orders of magnitude under the
outage and cannot affect /healthz, so it is filed as TK-11499 rather than
widening a candidate that DTD and Cody already passed byte-for-byte.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PkwT8hDyw7SCCkYBviZTbq
Files touched
A verification/tk11372/post-patch-blocking-audit.json
Diff
commit e8d4f1be12021ae395708a12767c7471a1f9190b
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Fri Sep 11 12:09:03 2026 -0700
TK-11372: post-patch blocking audit; split the skills scan to TK-11499
Confirms the patch did not close one blocking call while leaving another in a
request path: server.js and lib.js now have zero sync subprocess calls, and
lib.js matters because tickets()/messages() run per request.
Secondary, deliberately NOT folded in: installedSkills() walks 583+22 dirs
with sync readFileSync+statSync, uncached, per GET /api/skills -- measured
mean 58ms / worst 502ms of loop blocking. Two orders of magnitude under the
outage and cannot affect /healthz, so it is filed as TK-11499 rather than
widening a candidate that DTD and Cody already passed byte-for-byte.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PkwT8hDyw7SCCkYBviZTbq
---
verification/tk11372/post-patch-blocking-audit.json | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/verification/tk11372/post-patch-blocking-audit.json b/verification/tk11372/post-patch-blocking-audit.json
new file mode 100644
index 00000000..1c5bc7b2
--- /dev/null
+++ b/verification/tk11372/post-patch-blocking-audit.json
@@ -0,0 +1,17 @@
+{
+ "ticket": "TK-11372",
+ "purpose": "Confirm the patch did not fix ONE blocking call while leaving another in a request or timer path — that would have been a false green.",
+ "subprocess_class": {
+ "server.js": "0 execSync / execFileSync / spawnSync remaining",
+ "lib.js": "0 execSync / execFileSync / spawnSync (matters because tickets() and messages() run per request)",
+ "verdict": "COMPLETE — the outage class is fully closed in the patched source"
+ },
+ "secondary_finding_NOT_the_outage_cause": {
+ "what": "installedSkills() at server.js:94 walks ~/.agents/skills (583 dirs) + ~/.codex/skills (22) with a synchronous readFileSync + statSync per dir, uncached, on every GET /api/skills",
+ "measured_blocking_cost": "581 skills found; mean 58.41ms, worst 502.37ms of event-loop blocking per request",
+ "severity": "LOW vs the outage — two orders of magnitude under the ~8s subprocess block, and it cannot affect /healthz. But a board page polling /api/skills injects up to ~0.5s stalls into every other request.",
+ "decision": "NOT folded into this activation. The reviewed candidate is kept byte-identical to what DTD and Cody passed; widening scope here is how false confidence gets introduced. Filed as its own follow-up instead.",
+ "suggested_fix": "cache installedSkills() behind a TTL like getRunning does, or move it to fs.promises"
+ },
+ "cost_usd": 0
+}
← ad5b5cac auto-data-snapshot: 2026-09-11T12:03:30 (1 data files) — dat
·
back to Ticket System
·
TK-11372: ACTIVATED and live-verified; residual symptom spli 97bd9fd6 →