opencode-agent-skill 13.0.0-beta.2 → 14.2.0-beta.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.
Files changed (93) hide show
  1. package/README.md +1556 -607
  2. package/bin/ocskill.mjs +172 -24
  3. package/docs/OPENCODE-COMPAT.md +34 -97
  4. package/docs/PI-COMPAT.md +188 -0
  5. package/docs/V14-CONTEXT-MEMORY-FABRIC.md +70 -0
  6. package/docs/V14.1-QUALITY-PERFORMANCE-FABRIC.md +114 -0
  7. package/docs/V14.2-TURBO-WEAK-MODEL-RUNTIME.md +448 -0
  8. package/evals/v14/tasks.json +46 -0
  9. package/global-config/agents/executor.md +7 -0
  10. package/global-config/agents/visual-verifier.md +22 -3
  11. package/global-config/plugins/ues-router/index.js +13 -8
  12. package/global-config/plugins/ues-router/policy-runtime.js +7 -0
  13. package/global-config/plugins/ues-router/router.js +12 -2
  14. package/global-config/skills/ecommerce-engineering/SKILL.md +1 -1
  15. package/global-config/skills/file-upload-engineering/SKILL.md +1 -1
  16. package/global-config/skills/git-safety/SKILL.md +1 -1
  17. package/global-config/skills/nestjs-engineering/SKILL.md +1 -1
  18. package/global-config/skills/performance-engineering/SKILL.md +1 -1
  19. package/global-config/skills/react-native-engineering/SKILL.md +1 -1
  20. package/global-config/skills/rest-api-design/SKILL.md +1 -1
  21. package/global-config/skills/ui-ux-engineering/SKILL.md +1 -1
  22. package/lib/adaptive-context-budget.mjs +97 -0
  23. package/lib/affected-tests.mjs +260 -0
  24. package/lib/benchmark-confidence.mjs +41 -2
  25. package/lib/browser-mcp-routing.mjs +166 -0
  26. package/lib/capability-fabric.mjs +336 -0
  27. package/lib/capability-registry.mjs +9 -0
  28. package/lib/context-engine-v11.mjs +65 -1
  29. package/lib/context-graph-rank.mjs +118 -0
  30. package/lib/context-manifest.mjs +97 -18
  31. package/lib/control-center.mjs +19 -1
  32. package/lib/dynamic-workflow.mjs +3 -1
  33. package/lib/evidence-store.mjs +82 -1
  34. package/lib/hierarchical-context.mjs +215 -0
  35. package/lib/memory-engine.mjs +465 -0
  36. package/lib/model-performance.mjs +33 -8
  37. package/lib/model-policy.mjs +3 -3
  38. package/lib/orchestrator-policy.mjs +5 -209
  39. package/lib/performance-fabric.mjs +229 -0
  40. package/lib/pi-rpc-pool.mjs +433 -0
  41. package/lib/process-hang-detector.mjs +83 -0
  42. package/lib/process-supervisor.mjs +193 -0
  43. package/lib/prompt-cache.mjs +2 -0
  44. package/lib/repo-graph.mjs +53 -2
  45. package/lib/runtime-config.mjs +31 -0
  46. package/lib/safety.mjs +132 -0
  47. package/lib/semantic-index.mjs +52 -3
  48. package/lib/skill-compiler.mjs +128 -0
  49. package/lib/skill-quality.mjs +48 -2
  50. package/lib/task-engine.mjs +66 -5
  51. package/lib/task-policy.mjs +235 -0
  52. package/lib/verification-broker.mjs +284 -0
  53. package/lib/verification-command.mjs +111 -0
  54. package/lib/windows-shim.mjs +35 -0
  55. package/lib/workspace-fingerprint.mjs +198 -0
  56. package/package.json +52 -42
  57. package/pi/extensions/ues-child-runtime.ts +238 -0
  58. package/pi/extensions/ues.ts +3200 -0
  59. package/pi/prompts/ues-audit.md +9 -0
  60. package/pi/prompts/ues-critique.md +9 -0
  61. package/pi/prompts/ues-debug.md +9 -0
  62. package/pi/prompts/ues-feature.md +9 -0
  63. package/pi/prompts/ues-fix.md +9 -0
  64. package/pi/prompts/ues-plan.md +9 -0
  65. package/pi/prompts/ues-research.md +9 -0
  66. package/pi/prompts/ues-resume.md +9 -0
  67. package/pi/prompts/ues-review.md +7 -0
  68. package/pi/prompts/ues-run.md +17 -0
  69. package/pi/prompts/ues-verify.md +9 -0
  70. package/scripts/check-release-consistency.mjs +119 -185
  71. package/scripts/check-runtime-exports.mjs +66 -0
  72. package/scripts/check-source-integrity.mjs +184 -0
  73. package/scripts/eval-pi.mjs +492 -0
  74. package/scripts/install.mjs +16 -0
  75. package/scripts/smoke-package-closure.mjs +110 -0
  76. package/scripts/smoke-packed-install.mjs +24 -11
  77. package/scripts/smoke-pi-extension.mjs +144 -0
  78. package/scripts/uninstall.mjs +44 -0
  79. package/CHANGELOG.md +0 -415
  80. package/docs/DETERMINISTIC-TOOLS.md +0 -105
  81. package/docs/ENGINEERING-DESIGN.md +0 -194
  82. package/docs/EVALS.md +0 -158
  83. package/docs/GITHUB-RULESET.md +0 -50
  84. package/docs/NPM-PUBLISH.md +0 -116
  85. package/docs/RESEARCH-SOURCES.md +0 -37
  86. package/docs/TRACE-SCHEMA.md +0 -122
  87. package/docs/V11-PERCEPTION-ADAPTIVE-EXECUTION.md +0 -75
  88. package/docs/V11-PERCEPTION-ADAPTIVE.md +0 -220
  89. package/docs/V12-WEAK-MODEL-INTELLIGENCE.md +0 -27
  90. package/docs/V13-PARALLEL-WEAK-MODEL-RUNTIME.md +0 -86
  91. package/docs/V7-INTELLIGENCE-RUNTIME.md +0 -166
  92. package/docs/V8-INTELLIGENCE-RELIABILITY.md +0 -206
  93. package/docs/V9-SPEED-INTELLIGENCE.md +0 -102
@@ -0,0 +1,110 @@
1
+ import assert from "node:assert/strict"
2
+ import { existsSync, readFileSync } from "node:fs"
3
+ import path from "node:path"
4
+ import { spawnSync } from "node:child_process"
5
+ import { fileURLToPath } from "node:url"
6
+ import { resolveWindowsCommand } from "../lib/windows-shim.mjs"
7
+
8
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..")
9
+
10
+ function run(executable, args, options = {}) {
11
+ if (process.platform !== "win32") return spawnSync(executable, args, options)
12
+ const resolved = resolveWindowsCommand(executable)
13
+ if (!resolved) {
14
+ return { status: 127, stdout: "", stderr: "Unable to resolve Windows command: " + executable }
15
+ }
16
+ return spawnSync(resolved.executable, [...resolved.argsPrefix, ...args], options)
17
+ }
18
+
19
+ function parseJsonOutput(result, label) {
20
+ assert.equal(result.status, 0, label + " failed: " + String(result.stderr || result.stdout || ""))
21
+ return JSON.parse(String(result.stdout || "").trim())
22
+ }
23
+
24
+ const packed = parseJsonOutput(
25
+ run("npm", ["pack", "--dry-run", "--json", "--ignore-scripts"], {
26
+ cwd: root,
27
+ encoding: "utf8",
28
+ maxBuffer: 8 * 1024 * 1024,
29
+ }),
30
+ "npm pack --dry-run",
31
+ )
32
+
33
+ assert.ok(Array.isArray(packed) && packed.length >= 1, "npm pack did not return package metadata")
34
+ const files = new Set((packed[0].files || []).map((entry) => String(entry.path).replaceAll("\\", "/")))
35
+
36
+ for (const required of [
37
+ "bin/ocskill.mjs",
38
+ "pi/extensions/ues.ts",
39
+ "pi/extensions/ues-child-runtime.ts",
40
+ "docs/V14.2-TURBO-WEAK-MODEL-RUNTIME.md",
41
+ "lib/process-supervisor.mjs",
42
+ "lib/pi-rpc-pool.mjs",
43
+ "lib/adaptive-context-budget.mjs",
44
+ "lib/skill-compiler.mjs",
45
+ "lib/affected-tests.mjs",
46
+ "lib/verification-broker.mjs",
47
+ "lib/verification-command.mjs",
48
+ "lib/task-policy.mjs",
49
+ "lib/model-policy.mjs",
50
+ "lib/context-engine-v11.mjs",
51
+ "lib/runtime-config.mjs",
52
+ "scripts/eval-pi.mjs",
53
+ "scripts/eval-report.mjs",
54
+ "evals/live/tasks.json",
55
+ "global-config/AGENTS.md",
56
+ "global-config/commands/run.md",
57
+ "global-config/plugins/ues-router/index.js",
58
+ ]) {
59
+ assert.ok(files.has(required), "packed package is missing required runtime file: " + required)
60
+ }
61
+
62
+ const controllerStat = (packed[0].files || []).find((entry) => String(entry.path).replaceAll("\\", "/") === "pi/extensions/ues.ts")
63
+ assert.ok(Number(controllerStat?.size || 0) > 80_000, "packed UES controller appears truncated")
64
+
65
+ const childRuntimeStat = (packed[0].files || []).find((entry) => String(entry.path).replaceAll("\\", "/") === "pi/extensions/ues-child-runtime.ts")
66
+ assert.ok(Number(childRuntimeStat?.size || 0) > 6_000, "packed UES child runtime appears truncated")
67
+
68
+ const codeFiles = [...files].filter((file) => /\.(?:mjs|js|ts)$/.test(file))
69
+ const missingRelativeImports = []
70
+
71
+ function resolvePackedImport(fromFile, specifier) {
72
+ const base = path.posix.normalize(path.posix.join(path.posix.dirname(fromFile), specifier))
73
+ const candidates = path.posix.extname(base)
74
+ ? [base]
75
+ : [base, base + ".mjs", base + ".js", base + ".ts", path.posix.join(base, "index.mjs"), path.posix.join(base, "index.js")]
76
+ return candidates.find((candidate) => existsSync(path.join(root, ...candidate.split("/")))) || null
77
+ }
78
+
79
+ for (const file of codeFiles) {
80
+ const absolute = path.join(root, ...file.split("/"))
81
+ if (!existsSync(absolute)) continue
82
+ const source = readFileSync(absolute, "utf8")
83
+ const regex = /(?:\bfrom\s+|\bimport\s*\(\s*|\bimport\s+)[\"'](\.{1,2}\/[^\"']+)[\"']/g
84
+ let match
85
+ while ((match = regex.exec(source))) {
86
+ const resolved = resolvePackedImport(file, match[1])
87
+ if (resolved && !files.has(resolved)) {
88
+ missingRelativeImports.push({ from: file, import: match[1], resolved })
89
+ }
90
+ }
91
+ }
92
+
93
+ assert.deepEqual(
94
+ missingRelativeImports,
95
+ [],
96
+ "packed runtime has relative imports to files excluded from npm package: " + JSON.stringify(missingRelativeImports),
97
+ )
98
+
99
+ const taskPolicy = parseJsonOutput(
100
+ run(process.execPath, [path.join(root, "bin", "ocskill.mjs"), "task-policy", "fix a high-risk authentication bug", "--json"], {
101
+ cwd: root,
102
+ encoding: "utf8",
103
+ maxBuffer: 1024 * 1024,
104
+ }),
105
+ "packaged task-policy smoke",
106
+ )
107
+ assert.equal(taskPolicy.risk, "high")
108
+ assert.equal(taskPolicy.modelTier, "heavy")
109
+
110
+ console.log(`Package closure smoke passed: ${files.size} packed file(s), ${codeFiles.length} code file(s) checked`)
@@ -38,6 +38,7 @@ const temp = await mkdtemp(path.join(os.tmpdir(), "ocskill-pack-smoke-"))
38
38
  const packDir = path.join(temp, "pack")
39
39
  const prefix = path.join(temp, "prefix")
40
40
  const configDir = path.join(temp, "opencode")
41
+ const uesConfigDir = path.join(temp, "ues-config")
41
42
 
42
43
  try {
43
44
  await mkdir(packDir, { recursive: true })
@@ -49,19 +50,13 @@ try {
49
50
  assert.equal(tarballs.length, 1, "expected exactly one packed tarball")
50
51
  const tarball = path.join(packDir, tarballs[0])
51
52
 
52
- const npmVersion = runNpm(["--version"], { cwd: temp })
53
- requireSuccess(npmVersion, "npm --version")
54
- const npmMajor = Number.parseInt(npmVersion.stdout.trim().split(".")[0], 10)
55
- const installArgs = ["install", "-g", tarball, "--prefix", prefix]
56
- if (Number.isFinite(npmMajor) && npmMajor >= 11) {
57
- installArgs.push(`--allow-scripts=${packageName}`)
58
- }
53
+ const installArgs = ["install", "-g", tarball, "--prefix", prefix, "--ignore-scripts"]
59
54
 
60
55
  const install = runNpm(installArgs, {
61
56
  cwd: temp,
62
- env: { ...process.env, OPENCODE_CONFIG_DIR: configDir, UES_OPENCODE_MAJOR: "2" },
57
+ env: process.env,
63
58
  })
64
- requireSuccess(install, "packed global install with automatic OpenCode sync")
59
+ requireSuccess(install, "packed global install")
65
60
 
66
61
  const root = runNpm(["root", "-g", "--prefix", prefix], { cwd: temp })
67
62
  requireSuccess(root, "npm root -g")
@@ -81,7 +76,19 @@ try {
81
76
  assert.equal(packageJson.name, packageName)
82
77
 
83
78
  const cli = path.join(packageDir, "bin", "ocskill.mjs")
84
- const env = { ...process.env, OPENCODE_CONFIG_DIR: configDir }
79
+ const env = {
80
+ ...process.env,
81
+ OPENCODE_CONFIG_DIR: configDir,
82
+ UES_CONFIG_DIR: uesConfigDir,
83
+ UES_OPENCODE_MAJOR: "2",
84
+ }
85
+
86
+ const sync = spawnSync(process.execPath, [cli, "install"], {
87
+ cwd: temp,
88
+ env,
89
+ encoding: "utf8",
90
+ })
91
+ requireSuccess(sync, "explicit legacy OpenCode sync from packed copy")
85
92
 
86
93
  const status = spawnSync(process.execPath, [cli, "status"], {
87
94
  cwd: temp,
@@ -470,7 +477,13 @@ try {
470
477
  encoding: "utf8",
471
478
  })
472
479
  requireSuccess(modelStatus, "ocskill models status from packed copy")
473
- assert.match(modelStatus.stdout, /"enabled": false/)
480
+ const initialModelStatus = JSON.parse(modelStatus.stdout)
481
+ assert.equal(initialModelStatus.enabled, false)
482
+ assert.equal(
483
+ path.resolve(initialModelStatus.file),
484
+ path.resolve(uesConfigDir, ".ues", "model-policy.json"),
485
+ "packed smoke must not read the user's real UES model policy",
486
+ )
474
487
 
475
488
  const modelSet = spawnSync(process.execPath, [cli, "models", "set", "standard", "provider/mid"], {
476
489
  cwd: temp,
@@ -0,0 +1,144 @@
1
+ import assert from "node:assert/strict"
2
+ import { existsSync } from "node:fs"
3
+ import { mkdtemp, rm } from "node:fs/promises"
4
+ import os from "node:os"
5
+ import path from "node:path"
6
+ import { spawnSync } from "node:child_process"
7
+ import { pathToFileURL, fileURLToPath } from "node:url"
8
+ import { resolveWindowsCommand } from "../lib/windows-shim.mjs"
9
+
10
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..")
11
+ const extensionPath = path.join(root, "pi", "extensions", "ues.ts")
12
+ const childRuntimeExtensionPath = path.join(root, "pi", "extensions", "ues-child-runtime.ts")
13
+ const skillsPath = path.join(root, "global-config", "skills")
14
+ const promptsPath = path.join(root, "pi", "prompts")
15
+ const agentDir = path.join(root, ".tmp-pi-agent")
16
+ const PI_SMOKE_VERSION = process.env.UES_PI_SMOKE_VERSION || "0.87.1"
17
+ const TYPEBOX_SMOKE_VERSION = process.env.UES_TYPEBOX_SMOKE_VERSION || "1.3.27"
18
+
19
+ function sanitizedNpmChildEnv(base = process.env) {
20
+ return Object.fromEntries(
21
+ Object.entries(base).filter(([key]) => key.toLowerCase() !== "npm_config_allow_scripts"),
22
+ )
23
+ }
24
+
25
+ function run(executable, args, options = {}) {
26
+ const spawnOptions = executable === "npm"
27
+ ? { ...options, env: sanitizedNpmChildEnv(options.env || process.env) }
28
+ : options
29
+
30
+ if (process.platform !== "win32") return spawnSync(executable, args, spawnOptions)
31
+ const resolved = resolveWindowsCommand(executable)
32
+ if (!resolved) return { status: 127, stdout: "", stderr: "Unable to resolve command: " + executable }
33
+ return spawnSync(resolved.executable, [...resolved.argsPrefix, ...args], spawnOptions)
34
+ }
35
+
36
+ async function importSdkFromDir(nodeModulesRoot) {
37
+ const entry = path.join(
38
+ nodeModulesRoot,
39
+ "@earendil-works",
40
+ "pi-coding-agent",
41
+ "dist",
42
+ "index.js",
43
+ )
44
+ if (!existsSync(entry)) return null
45
+ return import(pathToFileURL(entry).href)
46
+ }
47
+
48
+ async function loadPiSdk() {
49
+ try {
50
+ return {
51
+ sdk: await import("@earendil-works/pi-coding-agent"),
52
+ source: "local-node-modules",
53
+ tempDir: null,
54
+ }
55
+ } catch (error) {
56
+ if (error?.code !== "ERR_MODULE_NOT_FOUND") throw error
57
+ }
58
+
59
+ const globalRoot = run("npm", ["root", "-g"], { encoding: "utf8" })
60
+ if (globalRoot.status === 0) {
61
+ const sdk = await importSdkFromDir(String(globalRoot.stdout || "").trim())
62
+ if (sdk) return { sdk, source: "global-npm", tempDir: null }
63
+ }
64
+
65
+ const tempDir = await mkdtemp(path.join(os.tmpdir(), "ues-pi-smoke-host-"))
66
+ const installed = run(
67
+ "npm",
68
+ [
69
+ "install",
70
+ "--ignore-scripts",
71
+ "--no-package-lock",
72
+ "--no-save",
73
+ `@earendil-works/pi-coding-agent@${PI_SMOKE_VERSION}`,
74
+ `typebox@${TYPEBOX_SMOKE_VERSION}`,
75
+ ],
76
+ {
77
+ cwd: tempDir,
78
+ encoding: "utf8",
79
+ maxBuffer: 8 * 1024 * 1024,
80
+ },
81
+ )
82
+
83
+ if (installed.status !== 0) {
84
+ await rm(tempDir, { recursive: true, force: true }).catch(() => {})
85
+ throw new Error(
86
+ "Unable to provision Pi SDK for smoke test:\n" +
87
+ String(installed.stderr || installed.stdout || "npm install failed"),
88
+ )
89
+ }
90
+
91
+ const sdk = await importSdkFromDir(path.join(tempDir, "node_modules"))
92
+ if (!sdk) {
93
+ await rm(tempDir, { recursive: true, force: true }).catch(() => {})
94
+ throw new Error("Provisioned Pi SDK is missing dist/index.js")
95
+ }
96
+ return { sdk, source: "isolated-temp-install", tempDir }
97
+ }
98
+
99
+ const loaded = await loadPiSdk()
100
+ const { DefaultResourceLoader } = loaded.sdk
101
+
102
+ try {
103
+ const loader = new DefaultResourceLoader({
104
+ cwd: root,
105
+ agentDir,
106
+ additionalExtensionPaths: [extensionPath, childRuntimeExtensionPath],
107
+ additionalSkillPaths: [skillsPath],
108
+ additionalPromptTemplatePaths: [promptsPath],
109
+ })
110
+
111
+ await loader.reload()
112
+ const result = loader.getExtensions()
113
+
114
+ assert.equal(
115
+ result.errors.length,
116
+ 0,
117
+ result.errors.map((entry) => `${entry.path}: ${entry.error}`).join("\n"),
118
+ )
119
+ assert.ok(result.extensions.length >= 2, "Pi did not load the UES controller + child runtime extensions")
120
+
121
+ const skillResult = loader.getSkills()
122
+ assert.equal(
123
+ skillResult.diagnostics.length,
124
+ 0,
125
+ skillResult.diagnostics.map((entry) => `${entry.path || entry.filePath || "skill"}: ${entry.message || entry.error || JSON.stringify(entry)}`).join("\n"),
126
+ )
127
+ assert.ok(skillResult.skills.length >= 40, "Pi did not load the bundled UES skills")
128
+
129
+ const promptResult = loader.getPrompts()
130
+ assert.equal(
131
+ promptResult.diagnostics.length,
132
+ 0,
133
+ promptResult.diagnostics.map((entry) => `${entry.path || entry.filePath || "prompt"}: ${entry.message || entry.error || JSON.stringify(entry)}`).join("\n"),
134
+ )
135
+ assert.ok(promptResult.prompts.length >= 11, "Pi did not load the bundled UES prompts")
136
+
137
+ console.log(
138
+ `Pi package smoke passed via ${loaded.source}: ${result.extensions.length} extension(s), ${skillResult.skills.length} skill(s), ${promptResult.prompts.length} prompt(s) loaded`,
139
+ )
140
+ } finally {
141
+ if (loaded.tempDir) {
142
+ await rm(loaded.tempDir, { recursive: true, force: true }).catch(() => {})
143
+ }
144
+ }
@@ -1,5 +1,49 @@
1
+ import { spawnSync } from "node:child_process"
2
+ import path from "node:path"
3
+ import { fileURLToPath } from "node:url"
1
4
  import { removeResources } from "../lib/installer.mjs"
2
5
 
6
+ const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..")
7
+ const normalizedRoot = packageRoot.replaceAll("\\", "/").toLowerCase()
8
+
9
+ function isPiPackageInstall() {
10
+ return [
11
+ "/.pi/agent/git/",
12
+ "/.pi/agent/npm/",
13
+ "/.pi/git/",
14
+ "/.pi/npm/",
15
+ ].some((marker) => normalizedRoot.includes(marker))
16
+ }
17
+
18
+ function npmGlobalPrefix() {
19
+ if (process.platform === "win32") {
20
+ const result = spawnSync(
21
+ process.env.ComSpec || "cmd.exe",
22
+ ["/d", "/s", "/c", "npm prefix -g"],
23
+ { encoding: "utf8" },
24
+ )
25
+ return result.status === 0 ? result.stdout?.trim() : null
26
+ }
27
+
28
+ const result = spawnSync("npm", ["prefix", "-g"], { encoding: "utf8" })
29
+ return result.status === 0 ? result.stdout?.trim() : null
30
+ }
31
+
32
+ function isGlobalInstall() {
33
+ if (process.env.npm_config_global === "true" || process.env.npm_config_global === "1") {
34
+ return true
35
+ }
36
+
37
+ const prefix = npmGlobalPrefix()
38
+ if (!prefix) return false
39
+ return packageRoot.toLowerCase().startsWith(path.resolve(prefix).toLowerCase())
40
+ }
41
+
42
+ if (isPiPackageInstall() || !isGlobalInstall()) {
43
+ console.log("[ocskill] Non-global/Pi package uninstall detected; leaving OpenCode resources untouched.")
44
+ process.exit(0)
45
+ }
46
+
3
47
  try {
4
48
  const result = await removeResources()
5
49
  for (const warning of result.warnings || []) {