opencode-agent-skill 15.1.1 → 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.
@@ -7,7 +7,8 @@ import { taskFiles } from "./task-graph.mjs"
7
7
  import { buildSemanticIndexCached, querySemanticIndex } from "./semantic-index.mjs"
8
8
  import { queryContextHierarchy } from "./hierarchical-context.mjs"
9
9
  import { rankContextGraph } from "./context-graph-rank.mjs"
10
- import { runtimeWorkspaceSnapshot } from "./workspace-fingerprint.mjs"
10
+ import { runtimeWorkspaceSnapshot, workspaceStatusEntries } from "./workspace-fingerprint.mjs"
11
+ import { sourceFacingPaths, sourceGitPathspecs } from "./runtime-artifacts.mjs"
11
12
 
12
13
  const ROOT_INSTRUCTIONS = [
13
14
  "AGENTS.md",
@@ -29,6 +30,14 @@ function unique(values) {
29
30
  return [...new Set(values.filter(Boolean))]
30
31
  }
31
32
 
33
+ function boundedFailure(component, error, impact = "evidence") {
34
+ return {
35
+ component,
36
+ impact,
37
+ message: String(error instanceof Error ? error.message : error || "unknown failure").slice(0, 500),
38
+ }
39
+ }
40
+
32
41
  function safeFull(root, relative) {
33
42
  const base = path.resolve(root)
34
43
  const full = path.resolve(base, relative)
@@ -149,18 +158,22 @@ function symbolHits(source, terms, limit = 12) {
149
158
  function gitChangedFiles(root) {
150
159
  const result = spawnSync(
151
160
  "git",
152
- ["status", "--porcelain=v1", "--untracked-files=all"],
161
+ [
162
+ "status",
163
+ "--porcelain=v1",
164
+ "-z",
165
+ "--untracked-files=all",
166
+ "--",
167
+ ...sourceGitPathspecs(),
168
+ ],
153
169
  { cwd: root, encoding: "utf8", maxBuffer: 4 * 1024 * 1024 },
154
170
  )
155
171
  if (result.status !== 0) return []
156
- return unique(
157
- result.stdout
158
- .split(/\r?\n/)
159
- .filter(Boolean)
160
- .map((line) => line.slice(3).trim())
161
- .map((value) => value.includes(" -> ") ? value.split(" -> ").at(-1) : value)
162
- .map((value) => value.replaceAll("\\", "/")),
163
- )
172
+ return unique(sourceFacingPaths(
173
+ workspaceStatusEntries(result.stdout)
174
+ .filter((entry) => entry.renameSource !== true)
175
+ .map((entry) => entry.file),
176
+ ))
164
177
  }
165
178
 
166
179
  async function nearbyInstructions(root, declared) {
@@ -272,11 +285,15 @@ export async function buildContextManifest(root, task, options = {}) {
272
285
  ...(task?.verification || []),
273
286
  ].filter(Boolean).join(" ")
274
287
 
288
+ const contextDiagnostics = []
275
289
  const semanticSnapshot = await buildSemanticIndexCached(root, {
276
290
  maxFiles: options.semanticMaxFiles ?? 6000,
277
291
  maxDepth: options.semanticMaxDepth ?? 14,
278
292
  workspaceFingerprint: reusableWorkspaceFingerprint,
279
- }).catch(() => null)
293
+ }).catch((error) => {
294
+ contextDiagnostics.push(boundedFailure("semantic-snapshot", error, "performance"))
295
+ return null
296
+ })
280
297
 
281
298
  const useGraph = strategy.includes("graph")
282
299
  const [hierarchy, semantic, graph, instructions] = await Promise.all([
@@ -285,19 +302,31 @@ export async function buildContextManifest(root, task, options = {}) {
285
302
  maxScopes: options.hierarchyMaxScopes ?? 6,
286
303
  maxFiles: options.semanticMaxFiles ?? 6000,
287
304
  builtIndex: semanticSnapshot || undefined,
288
- }).catch(() => null),
305
+ }).catch((error) => {
306
+ contextDiagnostics.push(boundedFailure("hierarchy", error))
307
+ return null
308
+ }),
289
309
  querySemanticIndex(root, queryText, {
290
310
  limit: 32,
291
311
  maxFiles: options.semanticMaxFiles ?? 6000,
292
312
  builtIndex: semanticSnapshot || undefined,
293
- }).catch(() => null),
313
+ }).catch((error) => {
314
+ contextDiagnostics.push(boundedFailure("semantic-query", error))
315
+ return null
316
+ }),
294
317
  useGraph
295
318
  ? buildRepoGraphCached(root, {
296
319
  maxFiles: options.maxFiles ?? 2500,
297
320
  workspaceFingerprint: reusableWorkspaceFingerprint,
298
- }).catch(() => ({ nodes: [], edges: [], hotspots: [], scannedFiles: 0, truncated: false }))
321
+ }).catch((error) => {
322
+ contextDiagnostics.push(boundedFailure("repo-graph", error))
323
+ return { nodes: [], edges: [], hotspots: [], scannedFiles: 0, truncated: false }
324
+ })
299
325
  : Promise.resolve({ nodes: [], edges: [], hotspots: [], scannedFiles: 0, truncated: false }),
300
- nearbyInstructions(root, declared).catch(() => []),
326
+ nearbyInstructions(root, declared).catch((error) => {
327
+ contextDiagnostics.push(boundedFailure("instructions", error))
328
+ return []
329
+ }),
301
330
  ])
302
331
  const hierarchyScopes = hierarchy?.scopes?.map((item) => item.path) || []
303
332
 
@@ -402,11 +431,8 @@ export async function buildContextManifest(root, task, options = {}) {
402
431
  ...instructions,
403
432
  ])
404
433
 
405
- const files = []
406
- for (const file of priority) {
407
- const info = await fileInfo(root, file)
408
- if (info) files.push(info)
409
- }
434
+ const files = (await Promise.all(priority.map((file) => fileInfo(root, file))))
435
+ .filter(Boolean)
410
436
 
411
437
  let remaining = budget
412
438
  const categoryRemaining = {
@@ -436,9 +462,18 @@ export async function buildContextManifest(root, task, options = {}) {
436
462
  })
437
463
  }
438
464
 
465
+ contextDiagnostics.sort((a, b) =>
466
+ a.component.localeCompare(b.component) ||
467
+ a.impact.localeCompare(b.impact) ||
468
+ a.message.localeCompare(b.message)
469
+ )
470
+ const evidenceDegraded = contextDiagnostics.some((item) => item.impact === "evidence")
471
+
439
472
  return {
440
473
  schemaVersion: 4,
441
474
  task: task?.id || null,
475
+ contextQuality: evidenceDegraded ? "degraded" : "full",
476
+ degradedComponents: contextDiagnostics,
442
477
  strategy,
443
478
  queryTerms: terms,
444
479
  declared,
@@ -2,7 +2,7 @@ import { createHash } from "node:crypto"
2
2
  import { spawnSync } from "node:child_process"
3
3
  import { lstatSync, readFileSync, readlinkSync } from "node:fs"
4
4
  import path from "node:path"
5
- import { sourceFacingPaths } from "./runtime-artifacts.mjs"
5
+ import { sourceFacingPaths, sourceGitPathspecs } from "./runtime-artifacts.mjs"
6
6
 
7
7
  const PHASE_HEADING = /^\s*(?:=+\s*)?PHASE\s+(\d+)\s*(?:[—–:-]+)\s*(.+?)\s*$/i
8
8
  const LOCAL_ENV_BASENAME = /^\.env(?:\.[^/\\]+)?$/i
@@ -187,7 +187,7 @@ export function captureInheritedDirtyState(root, options = {}) {
187
187
  ) {
188
188
  statusOutput = workspaceState.statusOutput
189
189
  } else {
190
- const probe = spawnSync("git", ["status", "--porcelain=v1", "-z", "--untracked-files=all"], {
190
+ const probe = spawnSync("git", ["status", "--porcelain=v1", "-z", "--untracked-files=all", "--", ...sourceGitPathspecs()], {
191
191
  cwd: resolved,
192
192
  encoding: "utf8",
193
193
  maxBuffer: 16 * 1024 * 1024,
@@ -5,6 +5,8 @@ import { spawnSync } from "node:child_process"
5
5
  import path from "node:path"
6
6
  import { evidenceExists, putEvidence } from "./evidence-store.mjs"
7
7
  import { buildRepoGraphCached } from "./repo-graph.mjs"
8
+ import { sourceFacingPaths, sourceGitPathspecs } from "./runtime-artifacts.mjs"
9
+ import { workspaceStatusEntries } from "./workspace-fingerprint.mjs"
8
10
 
9
11
  const MEMORY_DIR = ".ues-memory"
10
12
  const MEMORY_FILE = "MEMORY.json"
@@ -671,21 +673,24 @@ export async function memoryStatus(root = process.cwd()) {
671
673
  }
672
674
 
673
675
  function changedFiles(root) {
674
- const result = spawnSync("git", ["status", "--porcelain=v1", "--untracked-files=all"], {
676
+ const result = spawnSync("git", [
677
+ "status",
678
+ "--porcelain=v1",
679
+ "-z",
680
+ "--untracked-files=all",
681
+ "--",
682
+ ...sourceGitPathspecs(),
683
+ ], {
675
684
  cwd: path.resolve(root),
676
685
  encoding: "utf8",
677
686
  windowsHide: true,
678
687
  maxBuffer: 4 * 1024 * 1024,
679
688
  })
680
689
  if (result.status !== 0) return []
681
- return uniq(
682
- String(result.stdout || "")
683
- .split(/\r?\n/)
684
- .filter(Boolean)
685
- .map((line) => line.slice(3).trim())
686
- .map((value) => value.includes(" -> ") ? value.split(" -> ").at(-1) : value)
687
- .map(normalizeFile),
688
- ).slice(0, 80)
690
+ const changed = workspaceStatusEntries(String(result.stdout || ""))
691
+ .filter((entry) => entry.renameSource !== true)
692
+ .map((entry) => normalizeFile(entry.file))
693
+ return uniq(sourceFacingPaths(changed)).slice(0, 80)
689
694
  }
690
695
 
691
696
  function compactVerification(value, limit = 1200) {
@@ -469,6 +469,17 @@ export class PiRpcWorkerPool {
469
469
  constructor(options = {}) {
470
470
  this.maxWorkers = Math.max(1, Math.min(16, Number(options.maxWorkers || 8)))
471
471
  this.workers = new Map()
472
+ this.reservations = new Map()
473
+ }
474
+
475
+ reserve(key) {
476
+ this.reservations.set(key, (this.reservations.get(key) || 0) + 1)
477
+ }
478
+
479
+ release(key) {
480
+ const next = Math.max(0, (this.reservations.get(key) || 0) - 1)
481
+ if (next > 0) this.reservations.set(key, next)
482
+ else this.reservations.delete(key)
472
483
  }
473
484
 
474
485
  async pruneIdleWorkers(protectedKey = null) {
@@ -476,7 +487,7 @@ export class PiRpcWorkerPool {
476
487
  let candidateKey = null
477
488
  let candidate = null
478
489
  for (const [key, worker] of this.workers.entries()) {
479
- if (key === protectedKey) continue
490
+ if (key === protectedKey || this.reservations.has(key)) continue
480
491
  if (!worker || worker.dead) {
481
492
  candidateKey = key
482
493
  candidate = worker
@@ -494,37 +505,56 @@ export class PiRpcWorkerPool {
494
505
  }
495
506
 
496
507
  async run(key, spec, message, options = {}) {
497
- let worker = this.workers.get(key)
498
- let workerReused = Boolean(worker && !worker.dead && worker.runs > 0)
499
- if (options.reuseSession === true && !workerReused) {
500
- const error = new Error("Pi RPC same-session resume unavailable")
501
- error.code = "UES_RPC_SESSION_UNAVAILABLE"
502
- throw error
503
- }
504
- if (!worker || worker.dead) {
505
- if (worker) {
506
- await worker.stop().catch(() => {})
508
+ this.reserve(key)
509
+ let worker = null
510
+ let workerReused = false
511
+ let staleStop = null
512
+
513
+ try {
514
+ worker = this.workers.get(key)
515
+ workerReused = Boolean(worker && !worker.dead && worker.runs > 0)
516
+ if (options.reuseSession === true && !workerReused) {
517
+ const error = new Error("Pi RPC same-session resume unavailable")
518
+ error.code = "UES_RPC_SESSION_UNAVAILABLE"
519
+ throw error
520
+ }
521
+
522
+ if (!worker || worker.dead) {
523
+ const staleWorker = worker
524
+ if (staleWorker) this.workers.delete(key)
525
+
526
+ // Publish the replacement synchronously before any await. Concurrent
527
+ // callers for the same key must see this worker rather than allocate a
528
+ // second untracked process while the stale worker is being reaped.
529
+ worker = new RpcWorker(spec)
530
+ workerReused = false
531
+ this.workers.set(key, worker)
532
+ if (staleWorker) staleStop = staleWorker.stop().catch(() => {})
533
+ } else {
534
+ // Refresh insertion order so the bounded worker map behaves as an LRU.
507
535
  this.workers.delete(key)
536
+ this.workers.set(key, worker)
508
537
  }
509
- worker = new RpcWorker(spec)
510
- workerReused = false
511
- this.workers.set(key, worker)
512
- await this.pruneIdleWorkers(key)
513
- } else {
514
- // Refresh insertion order so the bounded worker map behaves as an LRU.
515
- this.workers.delete(key)
516
- this.workers.set(key, worker)
517
- }
518
538
 
519
- try {
520
- const result = await worker.run(message, options)
539
+ // Queue the run before pruning. The reservation prevents another
540
+ // concurrent key from treating this not-yet-active worker as idle during
541
+ // the small window before RpcWorker.execute sets active=true.
542
+ const runPromise = worker.run(message, options)
521
543
  await this.pruneIdleWorkers(key)
544
+ if (staleStop) await staleStop
545
+
546
+ const result = await runPromise
522
547
  return { ...result, workerReused }
523
548
  } catch (error) {
524
- this.workers.delete(key)
525
- await worker.stop().catch(() => {})
549
+ if (worker && this.workers.get(key) === worker) {
550
+ this.workers.delete(key)
551
+ await worker.stop().catch(() => {})
552
+ }
526
553
  await this.pruneIdleWorkers().catch(() => {})
527
554
  throw error
555
+ } finally {
556
+ this.release(key)
557
+ await this.pruneIdleWorkers(key).catch(() => {})
528
558
  }
529
559
  }
530
560
 
@@ -643,6 +673,7 @@ export class PiRpcWorkerPool {
643
673
  return {
644
674
  workers: this.workers.size,
645
675
  activeWorkers: active.length,
676
+ reservedWorkers: this.reservations.size,
646
677
  keys: [...this.workers.keys()],
647
678
  active,
648
679
  }
@@ -1,12 +1,12 @@
1
1
  import { readFile, readdir, stat } from "node:fs/promises"
2
2
  import path from "node:path"
3
3
  import { runtimeWorkspaceFingerprint } from "./workspace-fingerprint.mjs"
4
+ import { UES_RUNTIME_DIRS } from "./runtime-artifacts.mjs"
4
5
 
5
6
  const SKIP = new Set([
6
7
  ".git", "node_modules", ".next", "dist", "build", "coverage", ".venv", "venv",
7
8
  "Pods", "DerivedData", ".gradle", ".idea", ".cache", ".turbo", "target", "obj",
8
- ".ues-work", ".ues-cache", ".ues-traces", ".ues-learning", ".ues-dashboard",
9
- ".ues-sandboxes", ".ues-memory", ".ues-evals", ".ues-services",
9
+ ...UES_RUNTIME_DIRS,
10
10
  ])
11
11
 
12
12
  const SOURCE_EXTENSIONS = new Set([
@@ -2,11 +2,12 @@ import { existsSync } from "node:fs"
2
2
  import { readFile, readdir, stat } from "node:fs/promises"
3
3
  import path from "node:path"
4
4
  import { spawnSync } from "node:child_process"
5
+ import { UES_RUNTIME_DIRS, sourceGitPathspecs } from "./runtime-artifacts.mjs"
5
6
 
6
7
  const SKIP_DIRS = new Set([
7
8
  ".git", "node_modules", ".next", "dist", "build", "coverage", ".venv", "venv",
8
9
  "Pods", "DerivedData", ".gradle", ".idea", ".cache", ".turbo", "target", "bin", "obj",
9
- ".ues-services",
10
+ ...UES_RUNTIME_DIRS,
10
11
  ])
11
12
 
12
13
  const TEXT_EXTENSIONS = new Set([
@@ -231,7 +232,7 @@ export async function impactMap(root = process.cwd(), query = "") {
231
232
 
232
233
  export async function checkWorkingTree(root = process.cwd()) {
233
234
  root = path.resolve(root)
234
- const status = runGit(root, ["status", "--porcelain=v1", "--branch"])
235
+ const status = runGit(root, ["status", "--porcelain=v1", "--branch", "--", ...sourceGitPathspecs()])
235
236
  if (status.status !== 0) {
236
237
  return { root, git: false, error: (status.stderr || status.stdout || "").trim() }
237
238
  }
@@ -1,6 +1,7 @@
1
1
  import { existsSync } from "node:fs"
2
2
  import { mkdir, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises"
3
3
  import path from "node:path"
4
+ import { UES_RUNTIME_DIRS } from "./runtime-artifacts.mjs"
4
5
 
5
6
  const SCHEMA_VERSION = 1
6
7
  const CACHE_DIR = ".ues-cache"
@@ -12,7 +13,7 @@ const SOURCE_EXTENSIONS = new Set([
12
13
  const SKIP_DIRS = new Set([
13
14
  ".git", "node_modules", ".next", "dist", "build", "coverage", ".venv", "venv",
14
15
  "Pods", "DerivedData", ".gradle", ".idea", ".cache", ".turbo", "target", "obj",
15
- ".ues-work", ".ues-learning", ".ues-memory", ".ues-dashboard", ".ues-sandboxes", ".ues-cache", ".ues-traces", ".ues-services",
16
+ ...UES_RUNTIME_DIRS,
16
17
  ])
17
18
  const STOP_IDENTIFIERS = new Set([
18
19
  "const","let","var","function","class","interface","type","export","import","from","return",
@@ -20,6 +20,7 @@ import { capabilityFabricStatus } from "./capability-fabric.mjs"
20
20
  import { assertActivePlanScope, persistPlanScope } from "./work-plan-scope.mjs"
21
21
  import { classifyDecisionPolicy } from "./decision-policy.mjs"
22
22
  import { readTextAuto } from "./text-encoding.mjs"
23
+ import { UES_RUNTIME_DIRS, sourceGitPathspecs } from "./runtime-artifacts.mjs"
23
24
 
24
25
  const WORK_DIR = ".ues-work"
25
26
  const STATE_SCHEMA = 4
@@ -176,7 +177,7 @@ function gitCapture(root, args) {
176
177
  }
177
178
 
178
179
  const FINGERPRINT_SKIP_DIRS = new Set([
179
- ".git", ".ues-work", ".ues-learning", ".ues-dashboard", ".ues-sandboxes", ".ues-cache", ".ues-traces", ".ues-memory",
180
+ ".git", ...UES_RUNTIME_DIRS,
180
181
  "node_modules", ".next", "dist", "build", "coverage", ".venv", "venv",
181
182
  "Pods", "DerivedData", ".gradle", ".cache", ".turbo", "target", "bin", "obj",
182
183
  ])
@@ -250,17 +251,35 @@ function nonGitWorkspaceFingerprint(root, options = {}) {
250
251
 
251
252
  export function workspaceFingerprint(root) {
252
253
  root = path.resolve(root)
253
- const inside = gitCapture(root, ["rev-parse", "--is-inside-work-tree"])
254
- if (inside.status !== 0) {
255
- return nonGitWorkspaceFingerprint(root)
254
+
255
+ // Fast common path: resolve worktree identity and HEAD in one Git process.
256
+ // Preserve the unborn-HEAD behavior by falling back to separate probes only
257
+ // when the combined command cannot resolve HEAD.
258
+ const identity = gitCapture(root, ["rev-parse", "--is-inside-work-tree", "HEAD"])
259
+ const identityLines = String(identity.stdout || "").trim().split(/\r?\n/).filter(Boolean)
260
+ let insideWorktree = identity.status === 0 && identityLines[0] === "true"
261
+ let headOutput = identity.status === 0 && insideWorktree
262
+ ? (identityLines[1] || "")
263
+ : null
264
+
265
+ if (!insideWorktree) {
266
+ const inside = gitCapture(root, ["rev-parse", "--is-inside-work-tree"])
267
+ if (inside.status !== 0 || String(inside.stdout || "").trim() !== "true") {
268
+ return nonGitWorkspaceFingerprint(root)
269
+ }
270
+ insideWorktree = true
271
+ const head = gitCapture(root, ["rev-parse", "HEAD"])
272
+ headOutput = head.status === 0
273
+ ? head.stdout
274
+ : "ERROR:" + (head.stderr || head.stdout || "")
256
275
  }
257
276
 
258
- const parts = []
277
+ const parts = [String(headOutput || "")]
278
+ const sourcePathspecs = sourceGitPathspecs()
259
279
  const commands = [
260
- ["rev-parse", "HEAD"],
261
- ["status", "--porcelain=v1", "--untracked-files=all", "--", ".", ":(exclude).ues-work", ":(exclude).ues-learning", ":(exclude).ues-dashboard", ":(exclude).ues-sandboxes", ":(exclude).ues-cache", ":(exclude).ues-traces", ":(exclude).ues-memory"],
262
- ["diff", "--binary", "--no-ext-diff", "--", ".", ":(exclude).ues-work", ":(exclude).ues-learning", ":(exclude).ues-dashboard", ":(exclude).ues-sandboxes", ":(exclude).ues-cache", ":(exclude).ues-traces", ":(exclude).ues-memory"],
263
- ["diff", "--cached", "--binary", "--no-ext-diff", "--", ".", ":(exclude).ues-work", ":(exclude).ues-learning", ":(exclude).ues-dashboard", ":(exclude).ues-sandboxes", ":(exclude).ues-cache", ":(exclude).ues-traces", ":(exclude).ues-memory"],
280
+ ["status", "--porcelain=v1", "--untracked-files=all", "--", ...sourcePathspecs],
281
+ ["diff", "--binary", "--no-ext-diff", "--", ...sourcePathspecs],
282
+ ["diff", "--cached", "--binary", "--no-ext-diff", "--", ...sourcePathspecs],
264
283
  ]
265
284
  for (const args of commands) {
266
285
  const result = gitCapture(root, args)
@@ -2,12 +2,9 @@ import { createHash } from "node:crypto"
2
2
  import { lstatSync, readFileSync, readlinkSync } from "node:fs"
3
3
  import { spawnSync } from "node:child_process"
4
4
  import path from "node:path"
5
- import { UES_RUNTIME_DIRS } from "./runtime-artifacts.mjs"
5
+ import { sourceGitPathspecs } from "./runtime-artifacts.mjs"
6
6
 
7
- const RUNTIME_PATHSPECS = [
8
- ".",
9
- ...UES_RUNTIME_DIRS.map((dir) => `:(exclude)${dir}/**`),
10
- ]
7
+ const RUNTIME_PATHSPECS = sourceGitPathspecs()
11
8
 
12
9
  let nonGitNonce = 0
13
10
 
@@ -132,12 +129,23 @@ function nonGitSnapshot(root) {
132
129
 
133
130
  export function captureWorkspaceStateV2(root = process.cwd()) {
134
131
  root = path.resolve(root)
135
- const inside = git(root, ["rev-parse", "--is-inside-work-tree"])
136
- if (inside.status !== 0 || String(inside.stdout || "").trim() !== "true") {
137
- return nonGitSnapshot(root)
132
+
133
+ // Fast common path: resolve worktree identity and HEAD in one Git process.
134
+ // A fallback probe is only needed for an unborn/missing HEAD.
135
+ const identity = git(root, ["rev-parse", "--is-inside-work-tree", "HEAD"])
136
+ const identityLines = String(identity.stdout || "").trim().split(/\r?\n/).filter(Boolean)
137
+ let insideWorktree = identityLines[0] === "true"
138
+ let head = {
139
+ ...identity,
140
+ stdout: identity.status === 0 && insideWorktree ? (identityLines[1] || "") : "",
141
+ }
142
+ if (identity.status !== 0) {
143
+ const inside = git(root, ["rev-parse", "--is-inside-work-tree"])
144
+ insideWorktree = inside.status === 0 && String(inside.stdout || "").trim() === "true"
145
+ head = { ...identity, stdout: "" }
138
146
  }
147
+ if (!insideWorktree) return nonGitSnapshot(root)
139
148
 
140
- const head = git(root, ["rev-parse", "HEAD"])
141
149
  const status = git(root, [
142
150
  "status",
143
151
  "--porcelain=v1",
@@ -4,7 +4,7 @@ import { rm } from "node:fs/promises"
4
4
  import { spawnSync } from "node:child_process"
5
5
  import path from "node:path"
6
6
  import { decodeTextBuffer } from "./text-encoding.mjs"
7
- import { isUesRuntimeArtifactPath, sourceFacingPaths } from "./runtime-artifacts.mjs"
7
+ import { isUesRuntimeArtifactPath, sourceFacingPaths, sourceGitPathspecs } from "./runtime-artifacts.mjs"
8
8
 
9
9
  const CODE_EXTENSIONS = new Set([
10
10
  ".js", ".cjs", ".mjs", ".jsx", ".ts", ".cts", ".mts", ".tsx",
@@ -113,7 +113,7 @@ function gitStatusEntries(root, workspaceState = null) {
113
113
  ) {
114
114
  return parseGitStatusEntries(workspaceState.statusOutput)
115
115
  }
116
- const result = spawnSync("git", ["status", "--porcelain=v1", "-z", "--untracked-files=all"], {
116
+ const result = spawnSync("git", ["status", "--porcelain=v1", "-z", "--untracked-files=all", "--", ...sourceGitPathspecs()], {
117
117
  cwd: resolved,
118
118
  encoding: "utf8",
119
119
  windowsHide: true,
@@ -4,6 +4,7 @@ import { copyFile, mkdir, readFile, readdir, rm, unlink, writeFile } from "node:
4
4
  import { spawnSync } from "node:child_process"
5
5
  import path from "node:path"
6
6
  import { isUesRuntimeArtifactPath, sourceFacingPaths, sourceGitPathspecs } from "./runtime-artifacts.mjs"
7
+ import { workspaceStatusEntries } from "./workspace-fingerprint.mjs"
7
8
 
8
9
  function git(root, args, options = {}) {
9
10
  return spawnSync("git", args, {
@@ -15,15 +16,20 @@ function git(root, args, options = {}) {
15
16
  }
16
17
 
17
18
  function statusFiles(root) {
18
- const result = git(root, ["status", "--porcelain=v1", "--untracked-files=all"])
19
+ const result = git(root, [
20
+ "status",
21
+ "--porcelain=v1",
22
+ "-z",
23
+ "--untracked-files=all",
24
+ "--",
25
+ ...sourceGitPathspecs(),
26
+ ])
19
27
  if (result.status !== 0) throw new Error((result.stderr || result.stdout || "git status failed").trim())
20
- return result.stdout
21
- .split(/\r?\n/)
22
- .filter(Boolean)
23
- .map((line) => line.slice(3).trim())
24
- .map((value) => value.includes(" -> ") ? value.split(" -> ").at(-1) : value)
25
- .map((value) => value.replaceAll("\\", "/"))
26
- .filter((value) => !isUesRuntimeArtifactPath(value))
28
+ return sourceFacingPaths(
29
+ workspaceStatusEntries(result.stdout)
30
+ .filter((entry) => entry.renameSource !== true)
31
+ .map((entry) => entry.file),
32
+ )
27
33
  }
28
34
 
29
35
  function sourceIntentBatches(values, options = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-agent-skill",
3
- "version": "15.1.1",
3
+ "version": "15.1.2",
4
4
  "description": "Pi-native UES coding-agent runtime with adaptive stability, Turbo Fast Path, durable verification, managed services, and weak-model orchestration",
5
5
  "type": "module",
6
6
  "bin": {
@@ -450,9 +450,45 @@ export default function (pi: ExtensionAPI) {
450
450
  throw new Error("unsupported ues_code action");
451
451
  }
452
452
  const encoded = JSON.stringify(result, null, 2);
453
+ const bounded = encoded.length > 32000;
454
+ let contextRef: string | null = null;
455
+ let visible = encoded;
456
+ if (bounded) {
457
+ const preserved = await compactContext(ctx.cwd, encoded, {
458
+ kind: "ues-code-result",
459
+ source: `ues_code:${params.action}`,
460
+ summary: `Full child code-intelligence result for ${params.action}; preserve exact JSON before model-visible bounding`,
461
+ }).catch(() => null);
462
+ contextRef = preserved?.ref || null;
463
+ const metadataFirst = {
464
+ schemaVersion: result?.schemaVersion || 1,
465
+ action: params.action,
466
+ file: result?.file || null,
467
+ available: result?.available ?? null,
468
+ provider: result?.provider || null,
469
+ operation: result?.operation || null,
470
+ reason: result?.reason || null,
471
+ persistent: result?.persistent ?? null,
472
+ pool: result?.pool || result?.lsp?.persistentPool || null,
473
+ bounded: true,
474
+ originalChars: encoded.length,
475
+ contextRef,
476
+ preview: encoded.slice(0, 22000),
477
+ };
478
+ visible = JSON.stringify(metadataFirst, null, 2) +
479
+ "\n...[full result preserved; use ues_code context-expand with contextRef when more evidence is needed]";
480
+ }
453
481
  return {
454
- content: [{ type: "text", text: encoded.length <= 32000 ? encoded : encoded.slice(0, 32000) + "\n...[bounded by ues_code]" }],
455
- details: { action: params.action, bounded: encoded.length > 32000 },
482
+ content: [{ type: "text", text: visible }],
483
+ details: {
484
+ action: params.action,
485
+ bounded,
486
+ originalChars: encoded.length,
487
+ contextRef,
488
+ provider: result?.provider || null,
489
+ persistent: result?.persistent ?? null,
490
+ pool: result?.pool || result?.lsp?.persistentPool || null,
491
+ },
456
492
  };
457
493
  } catch (error) {
458
494
  return {