thumbgate 1.34.3 → 1.37.1
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/.agents/skills/cyberstrike-compare-not-clone/SKILL.md +36 -0
- package/.agents/skills/gitlab-sandbox-allowlist-not-trust/SKILL.md +77 -0
- package/.agents/skills/jit-harness-compare-not-clone/SKILL.md +34 -0
- package/.agents/skills/openui-catalog-compose-honesty/SKILL.md +64 -0
- package/.agents/skills/zvec-grep-compare-not-clone/SKILL.md +34 -0
- package/.claude-plugin/plugin.json +1 -1
- package/.well-known/llms.txt +1 -0
- package/.well-known/mcp/server-card.json +1 -1
- package/CONTRIBUTING.md +95 -0
- package/README.md +195 -632
- package/THIRD_PARTY_NOTICES.md +89 -0
- package/adapters/claude/.mcp.json +2 -2
- package/adapters/forge/forge.yaml +3 -3
- package/adapters/future-agi/.mcp.json +8 -0
- package/adapters/future-agi/FUTURE_AGI.md +23 -0
- package/adapters/future-agi/config.toml +3 -0
- package/adapters/future-agi/future-agi-bridge.js +9 -0
- package/adapters/future-agi/opencode.json +8 -0
- package/adapters/herdr/herdr-plugin.toml +18 -0
- package/adapters/mcp/server-stdio.js +238 -25
- package/adapters/opencode/opencode.json +1 -1
- package/adapters/workos/WORKOS.md +52 -0
- package/bin/cli.js +373 -5
- package/bin/futureagi-bridge +9 -0
- package/config/gate-templates.json +653 -4
- package/config/gates/actor-critic-audit.json +34 -0
- package/config/gates/default.json +21 -2
- package/config/gates/five-walls-governance.json +34 -0
- package/config/gates/future-agi-guardrails.json +34 -0
- package/config/gates/radware-threat-defense-2026.json +61 -0
- package/config/gates/simatree-data-governance.json +33 -0
- package/config/mcp-allowlists.json +4 -0
- package/config/merge-quality-checks.json +10 -1
- package/config/model-candidates.json +382 -24
- package/config/model-tiers.json +18 -0
- package/config/post-deploy-marketing-pages.json +10 -0
- package/config/progressive/01-wire-only.json +11 -0
- package/config/progressive/02-dashboard-empty-ok.json +10 -0
- package/config/progressive/03-one-lesson.json +10 -0
- package/config/progressive/04-warn-fires.json +11 -0
- package/config/progressive/05-strict-optional.json +11 -0
- package/config/progressive/README.md +15 -0
- package/config/schemas/broker-execution-receipt.schema.json +139 -0
- package/config/schemas/provider-execution-attestation-v1.schema.json +58 -0
- package/conformance/provider-attestation/vectors.json +320 -0
- package/docs/specs/provider-execution-attestation-v1.md +69 -0
- package/openapi/openapi.yaml +15 -0
- package/package.json +401 -147
- package/public/about.html +2 -2
- package/public/ai-malpractice-prevention.html +7 -7
- package/public/blog/a-10-dollar-vps-is-not-a-computer.html +143 -0
- package/public/blog/a-receipt-is-not-world-state.html +388 -0
- package/public/blog/git-at-agent-scale.html +374 -0
- package/public/blog/no-llm-in-the-gate.html +133 -0
- package/public/blog.html +80 -0
- package/public/case-studies.html +16 -1
- package/public/compare.html +28 -0
- package/public/diagnostic.html +216 -7
- package/public/docs/connectors.html +39 -0
- package/public/federal.html +2 -2
- package/public/founders.html +639 -0
- package/public/index.html +87 -9
- package/public/install.html +8 -8
- package/public/learn.html +39 -0
- package/public/numbers.html +2 -2
- package/public/peter.html +310 -0
- package/public/platform-partners.html +119 -0
- package/public/pricing.html +24 -3
- package/public/privacy.html +117 -0
- package/public/pro.html +17 -0
- package/public/support.html +62 -0
- package/public/terms.html +130 -0
- package/public/third-party-notices.html +95 -0
- package/public/yt.html +351 -0
- package/scripts/action-receipts.js +133 -3
- package/scripts/adaptive-governance-arena.js +349 -0
- package/scripts/admin-override.js +205 -0
- package/scripts/agent-action-inventory.js +869 -0
- package/scripts/agent-audit-trace.js +42 -2
- package/scripts/agent-egress-policy.js +1117 -0
- package/scripts/agent-memory-lifecycle.js +141 -2
- package/scripts/agent-operations-planner.js +441 -1
- package/scripts/agent-readiness.js +68 -0
- package/scripts/agent-security-central.js +647 -0
- package/scripts/allowlist-bridge-honesty.js +417 -0
- package/scripts/async-job-runner.js +102 -11
- package/scripts/audit-trail.js +212 -0
- package/scripts/auto-promote-gates.js +178 -27
- package/scripts/billing.js +1 -1
- package/scripts/broker-execution-receipts.js +719 -0
- package/scripts/budget-aware-gates-proof.js +423 -0
- package/scripts/claude-feedback-sync.js +29 -3
- package/scripts/claw-harness-production.js +237 -0
- package/scripts/cli-progress.js +111 -0
- package/scripts/cli-schema.js +163 -1
- package/scripts/codex-runbook-flywheel.js +318 -0
- package/scripts/context-footprint.js +186 -0
- package/scripts/contextfs.js +143 -61
- package/scripts/dashboard-limits.js +27 -0
- package/scripts/dashboard.js +279 -9
- package/scripts/deepseek-v4-runtime-guardrails.js +72 -6
- package/scripts/docker-sandbox-planner.js +18 -0
- package/scripts/double-blind-eval-protocol.js +252 -0
- package/scripts/edotenv-rl-gateway.js +259 -0
- package/scripts/ensure-production-search-corpus.js +162 -0
- package/scripts/eval-holdout.js +311 -0
- package/scripts/feedback-aggregate.js +21 -2
- package/scripts/feedback-loop.js +87 -5
- package/scripts/feedback-quality.js +9 -0
- package/scripts/file-ledger-lock.js +4 -1
- package/scripts/financial-control-plane.js +41 -1
- package/scripts/find-dormant-requires.js +118 -0
- package/scripts/fs-utils.js +84 -8
- package/scripts/gate-stats.js +2 -2
- package/scripts/gates-engine.js +859 -58
- package/scripts/generate-case-study-outreach.js +24 -15
- package/scripts/git-at-scale.js +628 -0
- package/scripts/governance-conflict-audit.js +1650 -0
- package/scripts/governance-difficulty-curriculum.js +328 -0
- package/scripts/graphrag-retrieval.js +275 -0
- package/scripts/gurobi-optimizer.js +324 -0
- package/scripts/gurobi_optimizer.py +485 -0
- package/scripts/harness-selector.js +82 -1
- package/scripts/hidden-entry-points.js +284 -0
- package/scripts/human-escalation.js +199 -1
- package/scripts/hybrid-feedback-context.js +152 -19
- package/scripts/intent-governed-execution.js +602 -0
- package/scripts/intervention-policy.js +123 -20
- package/scripts/jit-harness-compose.js +628 -0
- package/scripts/jsonl-watcher.js +10 -0
- package/scripts/lesson-embedding-index.js +95 -12
- package/scripts/lesson-retrieval.js +105 -19
- package/scripts/local-model-profile.js +19 -2
- package/scripts/mailer/resend-mailer.js +1 -1
- package/scripts/matryoshka-embedding.js +235 -0
- package/scripts/mcp-oauth.js +42 -4
- package/scripts/mcp-session-handles.js +1016 -0
- package/scripts/mcp-wiring-doctor.js +314 -0
- package/scripts/memory-firewall.js +115 -2
- package/scripts/memory-scope-readiness.js +299 -0
- package/scripts/memory-vs-rag-route.js +161 -0
- package/scripts/model-tier-router.js +148 -21
- package/scripts/nvidia-specdecode-al-doctor.js +536 -0
- package/scripts/openui-catalog-compose-honesty.js +593 -0
- package/scripts/operational-integrity.js +19 -1
- package/scripts/override-audit.js +213 -0
- package/scripts/package-manager-honesty-doctor.js +458 -0
- package/scripts/pr-manager.js +63 -1
- package/scripts/prove-herdr-adapter.js +52 -0
- package/scripts/prove-memory-pyramid-and-symbolic-canvas.js +95 -0
- package/scripts/prove-workos.js +73 -0
- package/scripts/provider-attestation-conformance.js +192 -0
- package/scripts/provider-receipt-contract.js +136 -0
- package/scripts/qwen38-max-cost-optimizer.js +401 -0
- package/scripts/radware-threat-defense.js +280 -0
- package/scripts/rag-embedding-identity.js +221 -0
- package/scripts/rag-precision-guardrails.js +112 -2
- package/scripts/remote-feedback-capture.js +159 -0
- package/scripts/research-agent-harness.js +256 -0
- package/scripts/rsi-safety-hillclimb.js +200 -0
- package/scripts/rule-sprawl.js +188 -0
- package/scripts/schedule-manager.js +147 -0
- package/scripts/self-heal.js +8 -0
- package/scripts/session-lease.js +415 -0
- package/scripts/simatree-data-governance.js +347 -0
- package/scripts/slo-alert-engine.js +172 -7
- package/scripts/solver-parity.js +539 -0
- package/scripts/stealth-memory-injection-gate.js +333 -0
- package/scripts/switchyard-router.js +366 -0
- package/scripts/telemetry-analytics.js +84 -27
- package/scripts/temporal-decay-weighting.js +138 -0
- package/scripts/test-all.js +165 -0
- package/scripts/token-savings.js +42 -0
- package/scripts/tool-kpi-tracker.js +108 -5
- package/scripts/tool-registry.js +193 -5
- package/scripts/universal-claim-evaluator.js +14 -2
- package/scripts/vector-store.js +279 -9
- package/scripts/workflow-notebook.js +391 -0
- package/scripts/workflow-sentinel.js +111 -12
- package/scripts/workos-production-guard.js +260 -0
- package/scripts/workspace-search-route.js +515 -0
- package/server.json +2 -2
- package/src/agent-identity-boundary.js +76 -0
- package/src/agent-retrieval-cache.js +155 -0
- package/src/alert-noise-ledger.js +502 -0
- package/src/api/server.js +802 -185
- package/src/git-fast-cache.js +220 -0
- package/src/git-wal-sync.js +156 -0
- package/src/hash-anchored-edit.js +82 -0
- package/src/hermes-platform-protocol.js +475 -0
- package/src/hermes-sync-plane.js +241 -0
- package/src/index.js +30 -1
- package/src/iso42001-compliance-guard.js +97 -0
- package/src/latency-budget.js +244 -0
- package/src/mcp-writeguard.js +316 -0
- package/src/miminions-adapter.js +106 -0
- package/src/pipeline-compass.js +104 -0
- package/src/ppl-alert-pipeline.js +284 -0
- package/src/rendezvous-router.js +90 -0
- package/src/security-questionnaire.js +195 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* find-dormant-requires — report `const X = require(...)` bindings that are
|
|
4
|
+
* never referenced again in the file.
|
|
5
|
+
*
|
|
6
|
+
* Dependency-free on purpose: this repo has no eslint, no prettier and no lint
|
|
7
|
+
* script across 1,331 JS files (measured 2026-08-27 on d0bb3768), so there is
|
|
8
|
+
* no existing tool to lean on and adding one is a separate decision.
|
|
9
|
+
*
|
|
10
|
+
* Deliberately conservative — it only reports a binding when ALL of these hold,
|
|
11
|
+
* so that acting on the output is safe:
|
|
12
|
+
* - the require is a top-level `const` with a plain identifier or a simple
|
|
13
|
+
* destructuring pattern
|
|
14
|
+
* - the identifier appears exactly once in the file (its own declaration)
|
|
15
|
+
* - the file is not a test fixture and does not use `eval`
|
|
16
|
+
*
|
|
17
|
+
* It does NOT delete anything. Output is a candidate list with file:line.
|
|
18
|
+
*
|
|
19
|
+
* Usage: node scripts/find-dormant-requires.js [--json] [--dir=src]
|
|
20
|
+
*/
|
|
21
|
+
'use strict';
|
|
22
|
+
|
|
23
|
+
const fs = require('node:fs');
|
|
24
|
+
const path = require('node:path');
|
|
25
|
+
const { execFileSync } = require('node:child_process');
|
|
26
|
+
|
|
27
|
+
const ROOT = path.resolve(__dirname, '..');
|
|
28
|
+
const argv = process.argv.slice(2);
|
|
29
|
+
const asJson = argv.includes('--json');
|
|
30
|
+
const dirArg = (argv.find((a) => a.startsWith('--dir=')) || '').slice(6);
|
|
31
|
+
|
|
32
|
+
function tracked() {
|
|
33
|
+
// Invoking `git` by name is intentional: this detector runs inside a
|
|
34
|
+
// developer's repo where git must come from the user's own PATH. Pinning an
|
|
35
|
+
// absolute path would break on machines installing git via brew/apt/scoop/
|
|
36
|
+
// Xcode/Git-for-Windows. The command name ('git') is a hard-coded literal
|
|
37
|
+
// and args is an array, so execFileSync never goes through a shell.
|
|
38
|
+
const out = execFileSync('git', ['ls-files', '*.js'], { cwd: ROOT, encoding: 'utf8' }); // NOSONAR javascript:S4036
|
|
39
|
+
return out
|
|
40
|
+
.split('\n')
|
|
41
|
+
.filter(Boolean)
|
|
42
|
+
.filter((f) => !dirArg || f.startsWith(dirArg))
|
|
43
|
+
.filter((f) => !f.includes('node_modules/'))
|
|
44
|
+
.filter((f) => !f.endsWith('.min.js'));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Escape every RegExp metacharacter, backslash included.
|
|
49
|
+
* The first version escaped only the dollar sign, which CodeQL flagged as
|
|
50
|
+
* incomplete escaping (js/incomplete-sanitization): a backslash would survive
|
|
51
|
+
* into the constructed pattern and corrupt it.
|
|
52
|
+
*/
|
|
53
|
+
function escapeRegExp(text) {
|
|
54
|
+
return String(text).replace(/[.*+?^${}()|[\]\\]/g, (m) => "\\" + m);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// `const NAME = require(` and `const { A, B } = require(`
|
|
58
|
+
const SINGLE = /^\s*const\s+([A-Za-z_$][\w$]*)\s*=\s*require\(/;
|
|
59
|
+
const DESTRUCT = /^\s*const\s*\{([^}]+)\}\s*=\s*require\(/;
|
|
60
|
+
|
|
61
|
+
const findings = [];
|
|
62
|
+
let scanned = 0;
|
|
63
|
+
|
|
64
|
+
for (const rel of tracked()) {
|
|
65
|
+
const abs = path.join(ROOT, rel);
|
|
66
|
+
let src;
|
|
67
|
+
try {
|
|
68
|
+
src = fs.readFileSync(abs, 'utf8');
|
|
69
|
+
} catch {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
scanned++;
|
|
73
|
+
if (src.includes('eval(')) continue; // identifiers may be referenced dynamically
|
|
74
|
+
|
|
75
|
+
const lines = src.split('\n');
|
|
76
|
+
const names = [];
|
|
77
|
+
lines.forEach((line, i) => {
|
|
78
|
+
const s = SINGLE.exec(line);
|
|
79
|
+
if (s) {
|
|
80
|
+
names.push({ name: s[1], line: i + 1 });
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const d = DESTRUCT.exec(line);
|
|
84
|
+
if (d) {
|
|
85
|
+
d[1]
|
|
86
|
+
.split(',')
|
|
87
|
+
.map((p) => p.trim().split(':').pop().trim())
|
|
88
|
+
.filter((p) => /^[A-Za-z_$][\w$]*$/.test(p))
|
|
89
|
+
.forEach((n) => names.push({ name: n, line: i + 1 }));
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
if (!names.length) continue;
|
|
93
|
+
|
|
94
|
+
for (const { name, line } of names) {
|
|
95
|
+
// count whole-word occurrences across the file
|
|
96
|
+
const re = new RegExp(`\\b${escapeRegExp(name)}\\b`, 'g');
|
|
97
|
+
const hits = (src.match(re) || []).length;
|
|
98
|
+
if (hits <= 1) findings.push({ file: rel, line, name });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (asJson) {
|
|
103
|
+
console.log(JSON.stringify({ scanned, findings }, null, 2));
|
|
104
|
+
} else {
|
|
105
|
+
console.log(`scanned ${scanned} tracked .js files`);
|
|
106
|
+
console.log(`dormant require bindings: ${findings.length}\n`);
|
|
107
|
+
const byFile = {};
|
|
108
|
+
for (const f of findings) {
|
|
109
|
+
byFile[f.file] = byFile[f.file] || [];
|
|
110
|
+
byFile[f.file].push(f);
|
|
111
|
+
}
|
|
112
|
+
const sorted = Object.entries(byFile).sort((a, b) => b[1].length - a[1].length);
|
|
113
|
+
for (const [file, list] of sorted.slice(0, 40)) {
|
|
114
|
+
console.log(` ${file}`);
|
|
115
|
+
for (const f of list) console.log(` line ${String(f.line).padStart(4)} ${f.name}`);
|
|
116
|
+
}
|
|
117
|
+
if (sorted.length > 40) console.log(` ... and ${sorted.length - 40} more files`);
|
|
118
|
+
}
|
package/scripts/fs-utils.js
CHANGED
|
@@ -11,6 +11,48 @@
|
|
|
11
11
|
const fs = require('fs');
|
|
12
12
|
const path = require('path');
|
|
13
13
|
|
|
14
|
+
// Shared dashboard/statusline tail. Production feedback JSONL can exceed
|
|
15
|
+
// V8 string limits and starve /v1/dashboard past the authenticated proof budget.
|
|
16
|
+
const DEFAULT_JSONL_TAIL_BYTES = 4 * 1024 * 1024;
|
|
17
|
+
const DEFAULT_JSONL_TAIL_ENTRIES = 20_000;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Read a file, or only its newest `maxBytes` when the file is larger.
|
|
21
|
+
* Incomplete first line after a mid-file seek is dropped.
|
|
22
|
+
* @param {string} filePath
|
|
23
|
+
* @param {number} [maxBytes]
|
|
24
|
+
* @returns {{ text: string, truncated: boolean, size: number }}
|
|
25
|
+
*/
|
|
26
|
+
const HARD_FULL_READ_BYTES = 64 * 1024 * 1024;
|
|
27
|
+
|
|
28
|
+
function readTextTail(filePath, maxBytes) {
|
|
29
|
+
const stats = fs.statSync(filePath);
|
|
30
|
+
const size = stats.size || 0;
|
|
31
|
+
if (size <= 0) return { text: '', truncated: false, size: 0 };
|
|
32
|
+
let budget = Number(maxBytes);
|
|
33
|
+
// budget<=0 historically meant "read entire file". On oversized prod logs that
|
|
34
|
+
// throws "Cannot create a string longer than 0x1fffffe8 characters".
|
|
35
|
+
// Also refuse full reads when size exceeds the hard ceiling even if the caller
|
|
36
|
+
// passed an oversized maxBytes (dashboard_data 503 / V8 string limit).
|
|
37
|
+
if (size > HARD_FULL_READ_BYTES && (!budget || budget >= size || budget > HARD_FULL_READ_BYTES)) {
|
|
38
|
+
budget = DEFAULT_JSONL_TAIL_BYTES;
|
|
39
|
+
}
|
|
40
|
+
if (!budget || size <= budget) {
|
|
41
|
+
return { text: fs.readFileSync(filePath, 'utf-8'), truncated: false, size };
|
|
42
|
+
}
|
|
43
|
+
const fd = fs.openSync(filePath, 'r');
|
|
44
|
+
try {
|
|
45
|
+
const buffer = Buffer.alloc(budget);
|
|
46
|
+
fs.readSync(fd, buffer, 0, budget, size - budget);
|
|
47
|
+
let text = buffer.toString('utf-8');
|
|
48
|
+
const firstNewline = text.indexOf('\n');
|
|
49
|
+
if (firstNewline >= 0) text = text.slice(firstNewline + 1);
|
|
50
|
+
return { text, truncated: true, size };
|
|
51
|
+
} finally {
|
|
52
|
+
fs.closeSync(fd);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
14
56
|
/**
|
|
15
57
|
* Recursively create a directory if it does not exist.
|
|
16
58
|
* @param {string} dirPath
|
|
@@ -40,26 +82,50 @@ function ensureParentDir(filePath) {
|
|
|
40
82
|
* @param {boolean} [options.tail] - Read from the end while preserving chronological order
|
|
41
83
|
* @returns {object[]}
|
|
42
84
|
*/
|
|
85
|
+
function positiveNumber(value) {
|
|
86
|
+
return Math.max(0, Number(value) || 0);
|
|
87
|
+
}
|
|
88
|
+
|
|
43
89
|
function readJsonl(filePath, options = {}) {
|
|
44
90
|
if (!filePath || !fs.existsSync(filePath)) return [];
|
|
45
|
-
const raw = fs.readFileSync(filePath, 'utf-8').trim();
|
|
46
|
-
if (!raw) return [];
|
|
47
|
-
|
|
48
91
|
const normalizedOptions = typeof options === 'number'
|
|
49
92
|
? { maxLines: options, tail: true }
|
|
50
93
|
: (options || {});
|
|
94
|
+
const maxLines = positiveNumber(normalizedOptions.maxLines);
|
|
95
|
+
// Opt-in full reads only. Unbounded readFileSync blows past V8 string limits
|
|
96
|
+
// on production feedback/memory JSONL (dashboard_data 503 / 0x1fffffe8).
|
|
97
|
+
const wantFull = normalizedOptions.full === true;
|
|
98
|
+
let maxBytes = positiveNumber(normalizedOptions.maxBytes);
|
|
99
|
+
if (!wantFull && maxBytes <= 0) {
|
|
100
|
+
maxBytes = (maxLines > 0 || normalizedOptions.tail)
|
|
101
|
+
? DEFAULT_JSONL_TAIL_BYTES
|
|
102
|
+
: DEFAULT_JSONL_TAIL_BYTES;
|
|
103
|
+
}
|
|
104
|
+
if (wantFull) {
|
|
105
|
+
maxBytes = 0; // readTextTail(0) => full file
|
|
106
|
+
}
|
|
107
|
+
let raw = '';
|
|
108
|
+
try {
|
|
109
|
+
raw = readTextTail(filePath, maxBytes).text.trim();
|
|
110
|
+
} catch {
|
|
111
|
+
return [];
|
|
112
|
+
}
|
|
113
|
+
if (!raw) return [];
|
|
51
114
|
let lines = raw.split('\n');
|
|
52
115
|
|
|
53
|
-
|
|
54
|
-
|
|
116
|
+
const effectiveMaxLines = maxLines > 0 ? maxLines : DEFAULT_JSONL_TAIL_ENTRIES;
|
|
117
|
+
if (!wantFull) {
|
|
118
|
+
lines = lines.slice(-effectiveMaxLines);
|
|
119
|
+
} else if (normalizedOptions.tail && maxLines > 0) {
|
|
120
|
+
lines = lines.slice(-maxLines);
|
|
55
121
|
}
|
|
56
122
|
|
|
57
123
|
if (normalizedOptions.reverse) {
|
|
58
124
|
lines = lines.reverse();
|
|
59
125
|
}
|
|
60
126
|
|
|
61
|
-
if (
|
|
62
|
-
lines = lines.slice(0,
|
|
127
|
+
if (wantFull && !normalizedOptions.tail && maxLines > 0) {
|
|
128
|
+
lines = lines.slice(0, maxLines);
|
|
63
129
|
}
|
|
64
130
|
|
|
65
131
|
return lines
|
|
@@ -101,4 +167,14 @@ function readJsonlTail(filePath, limit) {
|
|
|
101
167
|
return readJsonl(filePath, { maxLines: limit, tail: true });
|
|
102
168
|
}
|
|
103
169
|
|
|
104
|
-
module.exports = {
|
|
170
|
+
module.exports = {
|
|
171
|
+
DEFAULT_JSONL_TAIL_BYTES,
|
|
172
|
+
DEFAULT_JSONL_TAIL_ENTRIES,
|
|
173
|
+
ensureDir,
|
|
174
|
+
ensureParentDir,
|
|
175
|
+
readJsonl,
|
|
176
|
+
readJsonlTail,
|
|
177
|
+
readTextTail,
|
|
178
|
+
appendJsonl,
|
|
179
|
+
writeJson,
|
|
180
|
+
};
|
package/scripts/gate-stats.js
CHANGED
|
@@ -39,10 +39,10 @@ function calculateStats() {
|
|
|
39
39
|
// Count total blocks/warns from occurrences in auto-promoted gates
|
|
40
40
|
const totalBlocked = autoGates
|
|
41
41
|
.filter((g) => g.action === 'block')
|
|
42
|
-
.reduce((sum, g) => sum + (g.occurrences || 0), 0);
|
|
42
|
+
.reduce((sum, g) => sum + (Number(g.occurrences) || 0), 0);
|
|
43
43
|
const totalWarned = autoGates
|
|
44
44
|
.filter((g) => g.action === 'warn')
|
|
45
|
-
.reduce((sum, g) => sum + (g.occurrences || 0), 0);
|
|
45
|
+
.reduce((sum, g) => sum + (Number(g.occurrences) || 0), 0);
|
|
46
46
|
|
|
47
47
|
// Top blocked gate. A configured block rule with zero occurrences is not a
|
|
48
48
|
// "top blocker"; only recorded block events should appear here.
|