dsh-harbor-evolution 0.8.2 → 0.8.3

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 CHANGED
@@ -14,8 +14,8 @@ npx --yes dsh-harbor-evolution@latest setup --project-root "$PWD"
14
14
 
15
15
  The setup command installs both required runtimes:
16
16
 
17
- - `harbor-dsh-evolution==0.8.2` in a managed Python environment.
18
- - `dsh-harbor-evolution@0.8.2` in the selected DSH profile.
17
+ - `harbor-dsh-evolution==0.8.3` in a managed Python environment.
18
+ - `dsh-harbor-evolution@0.8.3` in the selected DSH profile.
19
19
 
20
20
  It then stores the absolute Harbor executable paths and a fallback `projectRoot` in the profile's `harbor-evolution` block and verifies the integration. Agent Tool calls always use the calling session's absolute working directory as their project root; the configured value remains the Web Workbench and non-Agent fallback. Existing unrelated profile entries are preserved, and rerunning setup updates the same block.
21
21
 
package/lib/evolution.js CHANGED
@@ -154,6 +154,15 @@ async function cliJson(config, args, { allowedExitCodes = [0], input } = {}) {
154
154
  }
155
155
  }
156
156
 
157
+ export function historicalDockerBlockers(value) {
158
+ const findings = Array.isArray(value?.findings) ? value.findings : []
159
+ return findings.filter(item => (
160
+ item?.level === 'error'
161
+ && typeof item.code === 'string'
162
+ && item.code.startsWith('DOCKER_')
163
+ ))
164
+ }
165
+
157
166
  export async function inspectEvaluator(config, args = {}) {
158
167
  const stack = resolveWithin(config.projectRoot, args.stackPath ?? '.harbor/evaluation-stack.yml', 'stackPath')
159
168
  return cliJson(config, [
@@ -467,6 +476,16 @@ export async function runHistoricalEvaluation(config, args, modelRuntime) {
467
476
  ])
468
477
  const dataset = resolveWithin(projectRoot, materialized.dataset_path ?? output, 'historicalDataset')
469
478
  const stack = resolveWithin(projectRoot, materialized.stack_path, 'historicalStack')
479
+ // Fail fast on Docker runtime blockers (e.g. an unresolvable credential
480
+ // helper) before Harbor creates a Job whose Trials would all fail during
481
+ // environment setup and only report missing downstream artifacts.
482
+ const dockerCheck = await cliJson(config, ['docker-check'], { allowedExitCodes: [0, 2] })
483
+ const dockerBlockers = historicalDockerBlockers(dockerCheck)
484
+ if (dockerBlockers.length) {
485
+ throw new Error(
486
+ `HISTORICAL_DOCKER_PREFLIGHT_FAILED: Docker runtime preflight blocked the Historical Job:\n${dockerBlockers.map(item => `${item.code}: ${item.message}`).join('\n')}`,
487
+ )
488
+ }
470
489
  const batch = JSON.parse(await readFile(batchPath, 'utf8'))
471
490
  const jobs = resolveWithin(projectRoot, config.jobsDir, 'jobsDir')
472
491
  const jobName = args.jobName ?? makeHistoricalJobName(batch)
package/lib/process.js CHANGED
@@ -1,10 +1,36 @@
1
1
  import { spawn } from 'node:child_process'
2
+ import { existsSync } from 'node:fs'
3
+ import path from 'node:path'
4
+
5
+ const DOCKER_DESKTOP_BIN = '/Applications/Docker.app/Contents/Resources/bin'
6
+
7
+ /**
8
+ * On macOS, Docker Desktop keeps `docker-credential-desktop` (and the other
9
+ * credential helpers) inside the app bundle, outside the default PATH that a
10
+ * GUI-launched Harness inherits. A missing helper makes `docker build`/`pull`
11
+ * fail with `exec: "docker-credential-desktop": executable file not found in
12
+ * $PATH` even though the CLI and daemon are reachable. Prepend that directory
13
+ * to PATH for every child process we spawn so Harbor inherits a resolvable
14
+ * helper. The change is macOS-only, existence-checked, and idempotent.
15
+ */
16
+ export function dockerDesktopAwareEnv(env, {
17
+ platform = process.platform,
18
+ pathExists = existsSync,
19
+ } = {}) {
20
+ const base = env ?? process.env
21
+ if (platform !== 'darwin') return base
22
+ if (!pathExists(DOCKER_DESKTOP_BIN)) return base
23
+ const current = String(base.PATH ?? '')
24
+ const segments = current.split(path.delimiter).filter(Boolean)
25
+ if (segments.includes(DOCKER_DESKTOP_BIN)) return base
26
+ return { ...base, PATH: [DOCKER_DESKTOP_BIN, ...segments].join(path.delimiter) }
27
+ }
2
28
 
3
29
  export function runProcess(command, args, options = {}) {
4
30
  return new Promise((resolve, reject) => {
5
31
  const child = spawn(command, args, {
6
32
  cwd: options.cwd,
7
- env: options.env ?? process.env,
33
+ env: dockerDesktopAwareEnv(options.env ?? process.env),
8
34
  shell: false,
9
35
  stdio: [options.input === undefined ? 'ignore' : 'pipe', 'pipe', 'pipe'],
10
36
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-harbor-evolution",
3
- "version": "0.8.2",
3
+ "version": "0.8.3",
4
4
  "description": "DeepSeek Harness plugin and Skill for Harbor Candidate and Historical Session evaluation workflows.",
5
5
  "type": "module",
6
6
  "main": "index.js",