opencode-agent-skill 15.1.0 → 15.1.2
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/README.md +5 -5
- package/docs/V15-MANAGED-RUNTIME.md +18 -0
- package/global-config/agents/verifier.md +6 -2
- package/lib/affected-tests.mjs +28 -7
- package/lib/capability-fabric.mjs +107 -48
- package/lib/code-intelligence/index.mjs +50 -24
- package/lib/code-intelligence/lsp-pool.mjs +831 -0
- package/lib/code-intelligence/lsp-provider.mjs +197 -20
- package/lib/compaction-resume-guard.mjs +76 -4
- package/lib/completion-auditor.mjs +20 -0
- package/lib/context-manifest.mjs +88 -36
- package/lib/decision-policy.mjs +40 -2
- package/lib/evidence-store.mjs +121 -31
- package/lib/executable-probe.mjs +69 -0
- package/lib/execution-contract.mjs +2 -2
- package/lib/hierarchical-context.mjs +31 -3
- package/lib/learning-engine.mjs +164 -65
- package/lib/memory-engine.mjs +177 -95
- package/lib/model-config.mjs +86 -7
- package/lib/performance-fabric.mjs +92 -0
- package/lib/permission-policy.mjs +232 -0
- package/lib/pi-rpc-pool.mjs +220 -24
- package/lib/provider-recovery.mjs +51 -0
- package/lib/repo-graph.mjs +40 -7
- package/lib/repo-inspect.mjs +3 -2
- package/lib/runtime-events.mjs +31 -10
- package/lib/semantic-index.mjs +69 -21
- package/lib/skill-compiler.mjs +84 -18
- package/lib/task-engine.mjs +28 -9
- package/lib/task-policy.mjs +80 -7
- package/lib/trajectory.mjs +25 -1
- package/lib/untrusted-output.mjs +106 -0
- package/lib/workspace-fingerprint.mjs +17 -9
- package/lib/workspace-hygiene.mjs +2 -2
- package/lib/worktree-sandbox.mjs +14 -8
- package/package.json +8 -6
- package/pi/extensions/ues-child-runtime.ts +116 -5
- package/pi/extensions/ues.ts +780 -81
- package/scripts/benchmark-lsp-pool.mjs +128 -0
- package/scripts/check-release-consistency.mjs +16 -4
- package/scripts/check-source-integrity.mjs +118 -6
- package/scripts/run-test-suite.mjs +143 -0
- package/scripts/smoke-package-closure.mjs +4 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { performance } from "node:perf_hooks"
|
|
2
|
+
import { mkdtemp, rm, stat, writeFile } from "node:fs/promises"
|
|
3
|
+
import os from "node:os"
|
|
4
|
+
import path from "node:path"
|
|
5
|
+
import {
|
|
6
|
+
lspPoolStatus,
|
|
7
|
+
resetLspPoolMetrics,
|
|
8
|
+
shutdownLspPool,
|
|
9
|
+
withManagedLspSession,
|
|
10
|
+
} from "../lib/code-intelligence/lsp-pool.mjs"
|
|
11
|
+
|
|
12
|
+
const MOCK_SERVER = `
|
|
13
|
+
let buffer = Buffer.alloc(0)
|
|
14
|
+
function encode(payload) {
|
|
15
|
+
const body = Buffer.from(JSON.stringify(payload), "utf8")
|
|
16
|
+
return Buffer.concat([Buffer.from("Content-Length: " + body.length + "\\r\\n\\r\\n", "ascii"), body])
|
|
17
|
+
}
|
|
18
|
+
function send(payload) { process.stdout.write(encode(payload)) }
|
|
19
|
+
function dispatch(message) {
|
|
20
|
+
const method = String(message?.method || "")
|
|
21
|
+
if (message?.id != null) {
|
|
22
|
+
if (method === "initialize") {
|
|
23
|
+
send({ jsonrpc: "2.0", id: message.id, result: { capabilities: { documentSymbolProvider: true } } })
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
if (method === "textDocument/documentSymbol") {
|
|
27
|
+
send({ jsonrpc: "2.0", id: message.id, result: [{ name: "benchSymbol", kind: 12, range: null, selectionRange: null }] })
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
send({ jsonrpc: "2.0", id: message.id, result: null })
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
if (method === "exit") process.exit(0)
|
|
34
|
+
}
|
|
35
|
+
function parse() {
|
|
36
|
+
while (true) {
|
|
37
|
+
const headerEnd = buffer.indexOf("\\r\\n\\r\\n")
|
|
38
|
+
if (headerEnd < 0) return
|
|
39
|
+
const header = buffer.subarray(0, headerEnd).toString("ascii")
|
|
40
|
+
const match = header.match(/Content-Length:\\s*(\\d+)/i)
|
|
41
|
+
if (!match) { buffer = buffer.subarray(headerEnd + 4); continue }
|
|
42
|
+
const length = Number(match[1])
|
|
43
|
+
const start = headerEnd + 4
|
|
44
|
+
if (buffer.length < start + length) return
|
|
45
|
+
const body = buffer.subarray(start, start + length).toString("utf8")
|
|
46
|
+
buffer = buffer.subarray(start + length)
|
|
47
|
+
try { dispatch(JSON.parse(body)) } catch {}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
process.stdin.on("data", (chunk) => {
|
|
51
|
+
buffer = Buffer.concat([buffer, Buffer.from(chunk)])
|
|
52
|
+
parse()
|
|
53
|
+
})
|
|
54
|
+
`
|
|
55
|
+
|
|
56
|
+
function median(values) {
|
|
57
|
+
const sorted = [...values].sort((a, b) => a - b)
|
|
58
|
+
const middle = Math.floor(sorted.length / 2)
|
|
59
|
+
return sorted.length % 2 ? sorted[middle] : (sorted[middle - 1] + sorted[middle]) / 2
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function main() {
|
|
63
|
+
const root = await mkdtemp(path.join(os.tmpdir(), "ues-lsp-bench-"))
|
|
64
|
+
try {
|
|
65
|
+
resetLspPoolMetrics()
|
|
66
|
+
const server = path.join(root, "mock-lsp.mjs")
|
|
67
|
+
const source = path.join(root, "demo.ts")
|
|
68
|
+
await writeFile(server, MOCK_SERVER, "utf8")
|
|
69
|
+
await writeFile(source, "export const benchmarkValue = 1\n", "utf8")
|
|
70
|
+
|
|
71
|
+
const provider = {
|
|
72
|
+
id: "typescript-benchmark",
|
|
73
|
+
command: process.execPath,
|
|
74
|
+
args: [server],
|
|
75
|
+
languageId: "typescript",
|
|
76
|
+
}
|
|
77
|
+
const target = { base: root, file: source, info: await stat(source) }
|
|
78
|
+
const run = async () => {
|
|
79
|
+
const started = performance.now()
|
|
80
|
+
const result = await withManagedLspSession(
|
|
81
|
+
target,
|
|
82
|
+
provider,
|
|
83
|
+
{ maxServers: 1, maxPerWorkspace: 1, timeoutMs: 2000, startupTimeoutMs: 3000 },
|
|
84
|
+
async (session) => session.request("textDocument/documentSymbol", {
|
|
85
|
+
textDocument: { uri: session.uri },
|
|
86
|
+
}),
|
|
87
|
+
)
|
|
88
|
+
if (!result.ok) throw new Error("LSP benchmark failed: " + String(result.reason || result.error || "unknown"))
|
|
89
|
+
return {
|
|
90
|
+
totalMs: performance.now() - started,
|
|
91
|
+
poolHit: result.meta.poolHit,
|
|
92
|
+
coldStartMs: result.meta.coldStartMs,
|
|
93
|
+
operationDurationMs: result.meta.operationDurationMs,
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const cold = await run()
|
|
98
|
+
const warm = []
|
|
99
|
+
for (let index = 0; index < 8; index += 1) warm.push(await run())
|
|
100
|
+
const warmTotals = warm.map((item) => item.totalMs)
|
|
101
|
+
const status = lspPoolStatus()
|
|
102
|
+
|
|
103
|
+
console.log(JSON.stringify({
|
|
104
|
+
schemaVersion: 1,
|
|
105
|
+
kind: "ues-lsp-pool-benchmark",
|
|
106
|
+
node: process.version,
|
|
107
|
+
platform: process.platform,
|
|
108
|
+
cold: {
|
|
109
|
+
totalMs: Number(cold.totalMs.toFixed(3)),
|
|
110
|
+
coldStartMs: cold.coldStartMs,
|
|
111
|
+
operationDurationMs: cold.operationDurationMs,
|
|
112
|
+
},
|
|
113
|
+
warm: {
|
|
114
|
+
samples: warm.length,
|
|
115
|
+
medianTotalMs: Number(median(warmTotals).toFixed(3)),
|
|
116
|
+
minTotalMs: Number(Math.min(...warmTotals).toFixed(3)),
|
|
117
|
+
maxTotalMs: Number(Math.max(...warmTotals).toFixed(3)),
|
|
118
|
+
allPoolHits: warm.every((item) => item.poolHit === true),
|
|
119
|
+
},
|
|
120
|
+
pool: status.metrics,
|
|
121
|
+
}, null, 2))
|
|
122
|
+
} finally {
|
|
123
|
+
await shutdownLspPool(root)
|
|
124
|
+
await rm(root, { recursive: true, force: true })
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
await main()
|
|
@@ -142,8 +142,20 @@ export function checkReleaseConsistency(root = DEFAULT_ROOT) {
|
|
|
142
142
|
|
|
143
143
|
if (pkg) {
|
|
144
144
|
const scripts = pkg.scripts || {}
|
|
145
|
-
if (scripts.test !== "node
|
|
146
|
-
|
|
145
|
+
if (scripts.test !== "node scripts/run-test-suite.mjs") {
|
|
146
|
+
errors.push("package.json: npm test must run the bounded per-file test runner")
|
|
147
|
+
}
|
|
148
|
+
const focusedPi = String(scripts["test:pi"] || "").trim().split(/\s+/).filter(Boolean)
|
|
149
|
+
if (
|
|
150
|
+
focusedPi[0] !== "node" ||
|
|
151
|
+
focusedPi[1] !== "scripts/run-test-suite.mjs" ||
|
|
152
|
+
!focusedPi.includes("test/pi-package.test.mjs")
|
|
153
|
+
) {
|
|
154
|
+
errors.push("package.json: missing bounded focused test:pi script")
|
|
155
|
+
}
|
|
156
|
+
if (scripts["test:node"] !== "node --test") {
|
|
157
|
+
errors.push("package.json: test:node must preserve raw Node test discovery for diagnosis")
|
|
158
|
+
}
|
|
147
159
|
if (scripts["docs:check"] !== "node scripts/check-release-consistency.mjs") errors.push("package.json: missing docs:check release-consistency script")
|
|
148
160
|
if (scripts["release:check-tag"] !== "node scripts/check-release-tag.mjs") errors.push("package.json: missing release:check-tag script")
|
|
149
161
|
if (scripts["eval:pi"] !== "node scripts/eval-pi.mjs") errors.push("package.json: missing Pi-native eval:pi script")
|
|
@@ -160,10 +172,10 @@ export function checkReleaseConsistency(root = DEFAULT_ROOT) {
|
|
|
160
172
|
]
|
|
161
173
|
if (
|
|
162
174
|
focusedV15[0] !== "node" ||
|
|
163
|
-
focusedV15[1] !== "
|
|
175
|
+
focusedV15[1] !== "scripts/run-test-suite.mjs" ||
|
|
164
176
|
!requiredFocusedV15Tests.every((file) => focusedV15.includes(file))
|
|
165
177
|
) {
|
|
166
|
-
errors.push("package.json: focused eval:v15 must
|
|
178
|
+
errors.push("package.json: focused eval:v15 must use the bounded runner and include the current V15 runtime, disk-safety, intelligence and Pi-package regression set")
|
|
167
179
|
}
|
|
168
180
|
if (!String(scripts.ci || "").includes("npm run integrity")) errors.push("package.json: ci must include source-integrity gate")
|
|
169
181
|
if (scripts["runtime:exports"] !== "node scripts/check-runtime-exports.mjs") errors.push("package.json: missing runtime:exports import/export gate")
|
|
@@ -11,6 +11,23 @@ const CONTRACTS = [
|
|
|
11
11
|
minBytes: 80_000,
|
|
12
12
|
startsWith: "import { spawn }",
|
|
13
13
|
required: [
|
|
14
|
+
"ues_code",
|
|
15
|
+
"UES Code Intelligence Lite",
|
|
16
|
+
"parent-lite",
|
|
17
|
+
"ues-code-result",
|
|
18
|
+
"ues-code-read",
|
|
19
|
+
"PARENT_CODE_VISIBLE_OUTPUT_LIMIT",
|
|
20
|
+
"originalChars: ${originalChars}",
|
|
21
|
+
"bounded: ${bounded}",
|
|
22
|
+
"UES_PARENT_CODE_VISIBLE_OUTPUT_LIMIT",
|
|
23
|
+
"anchored read bounded; exact content preserved",
|
|
24
|
+
"full result preserved; use ues_code context-expand with contextRef",
|
|
25
|
+
"includeSessions",
|
|
26
|
+
"1-based source line",
|
|
27
|
+
"1-based source character/column",
|
|
28
|
+
"controllerStarted",
|
|
29
|
+
"childSpawned",
|
|
30
|
+
"shutdownLspPool",
|
|
14
31
|
'name: "ues_cli"',
|
|
15
32
|
'name: "ues_execute"',
|
|
16
33
|
'name: "ues_dispatch"',
|
|
@@ -35,6 +52,18 @@ const CONTRACTS = [
|
|
|
35
52
|
"void directControllerRunner",
|
|
36
53
|
"UES_AUTO_ADMIT",
|
|
37
54
|
"UES_PARENT_TOOL_NAMES",
|
|
55
|
+
"ALWAYS_ON_PARENT_TOOLS",
|
|
56
|
+
'pi.on("agent_before_settle"',
|
|
57
|
+
"ues-parent-provider-recovery",
|
|
58
|
+
"parentRunToolCalls",
|
|
59
|
+
"parentProviderRecoveryConsecutive",
|
|
60
|
+
"parentProviderRecoveryTotal",
|
|
61
|
+
"parentProviderRecoveryPending",
|
|
62
|
+
"PARENT_PROVIDER_RECOVERY_MAX_CONSECUTIVE",
|
|
63
|
+
"PARENT_PROVIDER_RECOVERY_MAX_TOTAL",
|
|
64
|
+
"Do not restart the task and do not repeat tool calls that already completed",
|
|
65
|
+
'new Set(["ues_code"])',
|
|
66
|
+
'!ALWAYS_ON_PARENT_TOOLS.has(toolName)',
|
|
38
67
|
"pi.getActiveTools",
|
|
39
68
|
"pi.setActiveTools",
|
|
40
69
|
"deactivateParentUesTools",
|
|
@@ -108,7 +137,7 @@ const CONTRACTS = [
|
|
|
108
137
|
file: "pi/extensions/ues-child-runtime.ts",
|
|
109
138
|
minBytes: 6_000,
|
|
110
139
|
startsWith: 'import type { ExtensionAPI }',
|
|
111
|
-
required: [
|
|
140
|
+
required: ["full result preserved; use ues_code context-expand with contextRef", "ues-code-result",
|
|
112
141
|
'pi.on("tool_call"',
|
|
113
142
|
'pi.on("tool_result"',
|
|
114
143
|
'name: "ues_evidence_get"',
|
|
@@ -118,6 +147,7 @@ const CONTRACTS = [
|
|
|
118
147
|
'process.env.UES_CHILD_PROCESS !== "1"',
|
|
119
148
|
"looksLikeLongRunningServiceCommand",
|
|
120
149
|
"stopAllServices",
|
|
150
|
+
"shutdownLspPool",
|
|
121
151
|
"applyAnchoredFileEdits",
|
|
122
152
|
"diagnoseCode",
|
|
123
153
|
"recordVerification",
|
|
@@ -160,7 +190,7 @@ const CONTRACTS = [
|
|
|
160
190
|
file: "lib/task-engine.mjs",
|
|
161
191
|
minBytes: 45_000,
|
|
162
192
|
startsWith: "import ",
|
|
163
|
-
required: ["workspaceFingerprint", "initWork", "finalizeWork"],
|
|
193
|
+
required: ["workspaceFingerprint", "initWork", "finalizeWork", "UES_RUNTIME_DIRS", "sourceGitPathspecs", "Fast common path: resolve worktree identity and HEAD in one Git process"],
|
|
164
194
|
},
|
|
165
195
|
{
|
|
166
196
|
file: "lib/model-performance.mjs",
|
|
@@ -293,6 +323,9 @@ const CONTRACTS = [
|
|
|
293
323
|
startsWith: "import ",
|
|
294
324
|
required: [
|
|
295
325
|
"class RpcWorker",
|
|
326
|
+
"reservations",
|
|
327
|
+
"this.reserve(key)",
|
|
328
|
+
"reservedWorkers",
|
|
296
329
|
"steerActive",
|
|
297
330
|
"abortActive",
|
|
298
331
|
"abortTransport",
|
|
@@ -336,12 +369,14 @@ const CONTRACTS = [
|
|
|
336
369
|
startsWith: "import ",
|
|
337
370
|
required: [
|
|
338
371
|
"runtimeWorkspaceFingerprint",
|
|
372
|
+
"Fast common path",
|
|
373
|
+
'["rev-parse", "--is-inside-work-tree", "HEAD"]',
|
|
339
374
|
"runtimeWorkspaceSnapshot",
|
|
340
375
|
"changedFiles",
|
|
341
376
|
"cacheable",
|
|
342
377
|
"untrackedContentDigest",
|
|
343
378
|
"untracked-total-too-large",
|
|
344
|
-
"
|
|
379
|
+
"sourceGitPathspecs",
|
|
345
380
|
"runtime-artifacts.mjs",
|
|
346
381
|
],
|
|
347
382
|
},
|
|
@@ -396,13 +431,46 @@ const CONTRACTS = [
|
|
|
396
431
|
file: "lib/code-intelligence/index.mjs",
|
|
397
432
|
minBytes: 4_000,
|
|
398
433
|
startsWith: "import ",
|
|
399
|
-
required: ["readAnchoredCode", "applyAnchoredFileEdits", "searchCodeIntelligence", "diagnoseCode"],
|
|
434
|
+
required: ["runtimeCacheHit", "runtimeWorkspaceSnapshot", "buildSemanticIndexCached", "readAnchoredCode", "applyAnchoredFileEdits", "searchCodeIntelligence", "diagnoseCode", "runSupervisedProcess", "resolveWindowsCommand", "hardTimeoutMs: 20_000", "idleTimeoutMs: 10_000"],
|
|
435
|
+
forbidden: ["spawnSync"],
|
|
400
436
|
},
|
|
401
437
|
{
|
|
402
438
|
file: "lib/code-intelligence/lsp-provider.mjs",
|
|
403
439
|
minBytes: 5_000,
|
|
404
440
|
startsWith: "import ",
|
|
405
|
-
required: ["diagnoseCode", "lspProviderStatus", "publishDiagnostics"],
|
|
441
|
+
required: ["diagnoseCode", "lspProviderStatus", "lspPersistencePolicy", "short-lived-default", "pi-child-runtime", "publishDiagnostics", "withManagedLspSession", "fallbackFrom", "shutdownLspPool", "resolveTypeScriptTsserverFallback", "clearTypeScriptTsserverFallbackCache", "UES_LSP_PROVIDER_PROBE_TTL_MS", "UES_TYPESCRIPT_TSSERVER_PATH", "initializationOptions", "fallbackPath", "resolveWindowsCommand"],
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
file: "lib/code-intelligence/lsp-pool.mjs",
|
|
445
|
+
minBytes: 12_000,
|
|
446
|
+
startsWith: "import ",
|
|
447
|
+
required: ["averageTotalLatencyMs", "averageAcquisitionLatencyMs", "totalDurationMs", "acquisitionDurationMs",
|
|
448
|
+
"withManagedLspSession",
|
|
449
|
+
'this.request("shutdown"',
|
|
450
|
+
"closedNaturally",
|
|
451
|
+
"shutdownLspPool",
|
|
452
|
+
"lspPoolStatus",
|
|
453
|
+
"pool-capacity-busy",
|
|
454
|
+
"bounded-restart",
|
|
455
|
+
"config-changed",
|
|
456
|
+
"textDocument/didChange",
|
|
457
|
+
"UES_LSP_MAX_SERVERS",
|
|
458
|
+
"UES_LSP_IDLE_TTL_MS",
|
|
459
|
+
"resolveWindowsCommand",
|
|
460
|
+
"managed-lsp-request-rejected",
|
|
461
|
+
"STARTUPS",
|
|
462
|
+
"startupJoins",
|
|
463
|
+
"withPoolMutation",
|
|
464
|
+
"capacitySessionsForWorkspace",
|
|
465
|
+
"initializationOptions",
|
|
466
|
+
"JSON.stringify(provider?.initializationOptions || null)",
|
|
467
|
+
"Promise.all(candidates.map",
|
|
468
|
+
"Promise.all(found.map",
|
|
469
|
+
"sessionCount",
|
|
470
|
+
"sessionsIncluded",
|
|
471
|
+
"Config discovery is on every managed-LSP acquisition",
|
|
472
|
+
],
|
|
473
|
+
forbidden: ["\\nimport { resolveWindowsCommand }"],
|
|
406
474
|
},
|
|
407
475
|
{
|
|
408
476
|
file: "lib/execution-contract.mjs",
|
|
@@ -657,6 +725,20 @@ const CONTRACTS = [
|
|
|
657
725
|
],
|
|
658
726
|
},
|
|
659
727
|
|
|
728
|
+
{
|
|
729
|
+
file: "scripts/run-test-suite.mjs",
|
|
730
|
+
minBytes: 3_000,
|
|
731
|
+
startsWith: "import ",
|
|
732
|
+
required: [
|
|
733
|
+
"runSupervisedProcess",
|
|
734
|
+
"UES_TEST_FILE_TIMEOUT_MS",
|
|
735
|
+
"UES_TEST_CONCURRENCY",
|
|
736
|
+
"HANG/TIMEOUT",
|
|
737
|
+
"hardTimeoutMs: timeoutMs",
|
|
738
|
+
"UES_BOUNDED_TEST_RUNNER",
|
|
739
|
+
"Failing or leaking test files",
|
|
740
|
+
],
|
|
741
|
+
},
|
|
660
742
|
{
|
|
661
743
|
file: "scripts/eval-pi.mjs",
|
|
662
744
|
minBytes: 15_000,
|
|
@@ -670,11 +752,36 @@ const CONTRACTS = [
|
|
|
670
752
|
"UES_EVAL_DIRECT_TELEMETRY",
|
|
671
753
|
],
|
|
672
754
|
},
|
|
755
|
+
{
|
|
756
|
+
file: "lib/semantic-index.mjs",
|
|
757
|
+
minBytes: 10_000,
|
|
758
|
+
startsWith: "import ",
|
|
759
|
+
required: [
|
|
760
|
+
"UES_RUNTIME_DIRS",
|
|
761
|
+
"runtime-artifacts.mjs",
|
|
762
|
+
"...UES_RUNTIME_DIRS",
|
|
763
|
+
"buildSemanticIndexCached",
|
|
764
|
+
"RUNTIME_SEMANTIC_INFLIGHT",
|
|
765
|
+
],
|
|
766
|
+
},
|
|
767
|
+
{
|
|
768
|
+
file: "lib/context-manifest.mjs",
|
|
769
|
+
minBytes: 12_000,
|
|
770
|
+
startsWith: "import ",
|
|
771
|
+
required: [
|
|
772
|
+
"contextQuality",
|
|
773
|
+
"degradedComponents",
|
|
774
|
+
"semantic-snapshot",
|
|
775
|
+
"semantic-query",
|
|
776
|
+
"repo-graph",
|
|
777
|
+
"boundedFailure",
|
|
778
|
+
],
|
|
779
|
+
},
|
|
673
780
|
{
|
|
674
781
|
file: "lib/affected-tests.mjs",
|
|
675
782
|
minBytes: 7_500,
|
|
676
783
|
startsWith: "import ",
|
|
677
|
-
required: ["resolveAffectedTests", "clearAffectedTestCache", "AFFECTED_TEST_CACHE.set", "return result"],
|
|
784
|
+
required: ["UES_RUNTIME_DIRS", "isUesRuntimeArtifactPath", "runtime-artifacts.mjs", "resolveAffectedTests", "clearAffectedTestCache", "AFFECTED_TEST_CACHE.set", "return result"],
|
|
678
785
|
},
|
|
679
786
|
]
|
|
680
787
|
|
|
@@ -702,6 +809,11 @@ for (const contract of CONTRACTS) {
|
|
|
702
809
|
problems.push(`${contract.file}: missing integrity marker ${JSON.stringify(marker)}`)
|
|
703
810
|
}
|
|
704
811
|
}
|
|
812
|
+
for (const marker of contract.forbidden || []) {
|
|
813
|
+
if (source.includes(marker)) {
|
|
814
|
+
problems.push(`${contract.file}: forbidden integrity marker ${JSON.stringify(marker)}`)
|
|
815
|
+
}
|
|
816
|
+
}
|
|
705
817
|
}
|
|
706
818
|
|
|
707
819
|
assert.deepEqual(
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { readdir } from "node:fs/promises"
|
|
2
|
+
import os from "node:os"
|
|
3
|
+
import path from "node:path"
|
|
4
|
+
import { fileURLToPath } from "node:url"
|
|
5
|
+
import { runSupervisedProcess } from "../lib/process-supervisor.mjs"
|
|
6
|
+
|
|
7
|
+
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..")
|
|
8
|
+
const testRoot = path.join(root, "test")
|
|
9
|
+
|
|
10
|
+
function bounded(value, fallback, min, max) {
|
|
11
|
+
const parsed = Number(value)
|
|
12
|
+
if (!Number.isFinite(parsed)) return fallback
|
|
13
|
+
return Math.max(min, Math.min(max, Math.trunc(parsed)))
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async function walk(dir) {
|
|
17
|
+
const entries = await readdir(dir, { withFileTypes: true })
|
|
18
|
+
const output = []
|
|
19
|
+
for (const entry of entries) {
|
|
20
|
+
const absolute = path.join(dir, entry.name)
|
|
21
|
+
if (entry.isDirectory()) output.push(...await walk(absolute))
|
|
22
|
+
else if (entry.isFile() && entry.name.endsWith(".test.mjs")) output.push(absolute)
|
|
23
|
+
}
|
|
24
|
+
return output
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function relative(file) {
|
|
28
|
+
return path.relative(root, file).replaceAll("\\", "/")
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function selectedFiles(allFiles) {
|
|
32
|
+
const positional = process.argv.slice(2).filter((arg) => !arg.startsWith("--"))
|
|
33
|
+
if (!positional.length) return allFiles
|
|
34
|
+
const requested = new Set(positional.map((item) => path.resolve(root, item)))
|
|
35
|
+
return allFiles.filter((file) => requested.has(path.resolve(file)))
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function parseFlag(name, fallback) {
|
|
39
|
+
const direct = process.argv.find((arg) => arg.startsWith(name + "="))
|
|
40
|
+
if (!direct) return fallback
|
|
41
|
+
return direct.slice(name.length + 1)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const cpuDefault = Math.max(2, Math.min(6, os.availableParallelism?.() || os.cpus().length || 4))
|
|
45
|
+
const concurrency = bounded(
|
|
46
|
+
parseFlag("--concurrency", process.env.UES_TEST_CONCURRENCY),
|
|
47
|
+
cpuDefault,
|
|
48
|
+
1,
|
|
49
|
+
12,
|
|
50
|
+
)
|
|
51
|
+
const timeoutMs = bounded(
|
|
52
|
+
parseFlag("--timeout-ms", process.env.UES_TEST_FILE_TIMEOUT_MS),
|
|
53
|
+
45_000,
|
|
54
|
+
5_000,
|
|
55
|
+
10 * 60_000,
|
|
56
|
+
)
|
|
57
|
+
const files = selectedFiles((await walk(testRoot)).sort((a, b) => relative(a).localeCompare(relative(b))))
|
|
58
|
+
|
|
59
|
+
if (!files.length) {
|
|
60
|
+
console.error("No matching test files.")
|
|
61
|
+
process.exitCode = 2
|
|
62
|
+
} else {
|
|
63
|
+
console.log(`UES bounded test runner: ${files.length} files; concurrency=${concurrency}; perFileTimeoutMs=${timeoutMs}`)
|
|
64
|
+
|
|
65
|
+
let cursor = 0
|
|
66
|
+
let passed = 0
|
|
67
|
+
const failures = []
|
|
68
|
+
const startedAt = Date.now()
|
|
69
|
+
|
|
70
|
+
async function worker(workerId) {
|
|
71
|
+
while (true) {
|
|
72
|
+
const index = cursor++
|
|
73
|
+
if (index >= files.length) return
|
|
74
|
+
const file = files[index]
|
|
75
|
+
const label = relative(file)
|
|
76
|
+
const ordinal = index + 1
|
|
77
|
+
console.log(`[${ordinal}/${files.length}] RUN ${label}`)
|
|
78
|
+
|
|
79
|
+
const result = await runSupervisedProcess(
|
|
80
|
+
process.execPath,
|
|
81
|
+
["--test", file],
|
|
82
|
+
{
|
|
83
|
+
cwd: root,
|
|
84
|
+
hardTimeoutMs: timeoutMs,
|
|
85
|
+
idleTimeoutMs: 0,
|
|
86
|
+
killGraceMs: 500,
|
|
87
|
+
drainTimeoutMs: 2_000,
|
|
88
|
+
stdoutLimit: 8 * 1024 * 1024,
|
|
89
|
+
stderrLimit: 4 * 1024 * 1024,
|
|
90
|
+
env: {
|
|
91
|
+
...process.env,
|
|
92
|
+
UES_BOUNDED_TEST_RUNNER: "1",
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
if (result.exitCode === 0 && !result.stopReason) {
|
|
98
|
+
passed += 1
|
|
99
|
+
console.log(`[${ordinal}/${files.length}] PASS ${label} (${result.durationMs}ms)`)
|
|
100
|
+
continue
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const timedOut = result.stopReason === "hard-timeout"
|
|
104
|
+
const reason = timedOut
|
|
105
|
+
? `HANG/TIMEOUT after ${timeoutMs}ms`
|
|
106
|
+
: result.stopReason
|
|
107
|
+
? `STOPPED: ${result.stopReason}`
|
|
108
|
+
: `EXIT ${result.exitCode}`
|
|
109
|
+
failures.push({
|
|
110
|
+
file: label,
|
|
111
|
+
reason,
|
|
112
|
+
exitCode: result.exitCode,
|
|
113
|
+
stopReason: result.stopReason,
|
|
114
|
+
durationMs: result.durationMs,
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
console.error(`[${ordinal}/${files.length}] FAIL ${label}: ${reason}`)
|
|
118
|
+
const stdout = String(result.stdout || "").trim()
|
|
119
|
+
const stderr = String(result.stderr || "").trim()
|
|
120
|
+
if (stdout) console.error("\n--- stdout: " + label + " ---\n" + stdout.slice(-64_000))
|
|
121
|
+
if (stderr) console.error("\n--- stderr: " + label + " ---\n" + stderr.slice(-32_000))
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, files.length) }, (_, index) => worker(index + 1)))
|
|
126
|
+
|
|
127
|
+
const durationMs = Date.now() - startedAt
|
|
128
|
+
console.log("")
|
|
129
|
+
console.log("UES bounded test summary")
|
|
130
|
+
console.log(`files: ${files.length}`)
|
|
131
|
+
console.log(`pass: ${passed}`)
|
|
132
|
+
console.log(`fail: ${failures.length}`)
|
|
133
|
+
console.log(`duration_ms: ${durationMs}`)
|
|
134
|
+
|
|
135
|
+
if (failures.length) {
|
|
136
|
+
console.error("")
|
|
137
|
+
console.error("Failing or leaking test files:")
|
|
138
|
+
for (const failure of failures) {
|
|
139
|
+
console.error(`- ${failure.file}: ${failure.reason}; duration=${failure.durationMs}ms`)
|
|
140
|
+
}
|
|
141
|
+
process.exitCode = 1
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -39,6 +39,8 @@ for (const required of [
|
|
|
39
39
|
"pi/extensions/ues-child-runtime.ts",
|
|
40
40
|
"docs/V14.2-TURBO-WEAK-MODEL-RUNTIME.md",
|
|
41
41
|
"lib/process-supervisor.mjs",
|
|
42
|
+
"lib/executable-probe.mjs",
|
|
43
|
+
"lib/code-intelligence/lsp-pool.mjs",
|
|
42
44
|
"lib/pi-rpc-pool.mjs",
|
|
43
45
|
"lib/adaptive-context-budget.mjs",
|
|
44
46
|
"lib/skill-compiler.mjs",
|
|
@@ -51,6 +53,8 @@ for (const required of [
|
|
|
51
53
|
"lib/runtime-config.mjs",
|
|
52
54
|
"scripts/eval-pi.mjs",
|
|
53
55
|
"scripts/eval-report.mjs",
|
|
56
|
+
"scripts/benchmark-lsp-pool.mjs",
|
|
57
|
+
"scripts/run-test-suite.mjs",
|
|
54
58
|
"evals/live/tasks.json",
|
|
55
59
|
"global-config/AGENTS.md",
|
|
56
60
|
"global-config/commands/run.md",
|