dsh-harbor-evolution 0.3.0 → 0.3.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/README.md CHANGED
@@ -9,7 +9,7 @@ The package gives DSH four deterministic Harbor tools and bundles the model- and
9
9
  Requirements: Docker, Node.js 22+, pnpm, and [uv](https://docs.astral.sh/uv/). Run this from the business Agent workspace:
10
10
 
11
11
  ```bash
12
- npx dsh-harbor-evolution@0.3.0 setup --project-root "$PWD"
12
+ npx --yes dsh-harbor-evolution@latest setup --project-root "$PWD"
13
13
  ```
14
14
 
15
15
  The setup command installs both required runtimes:
@@ -22,7 +22,7 @@ It then stores the absolute Harbor executable paths and `projectRoot` in the pro
22
22
  The default profile is `web`. Use `--profile headless` only when that is the profile you actually run. See all options with:
23
23
 
24
24
  ```bash
25
- npx dsh-harbor-evolution@0.3.0 setup --help
25
+ npx --yes dsh-harbor-evolution@latest setup --help
26
26
  ```
27
27
 
28
28
  Stop any old DSH process and run the exact restart command printed by setup. Then invoke:
@@ -60,9 +60,11 @@ Keep `pythonPath` empty for the published Python package. `candidatePath`, `data
60
60
  For source development from the repository:
61
61
 
62
62
  ```bash
63
- ./hse dsh-install web
63
+ ./hse dsh-install-source web
64
64
  ```
65
65
 
66
+ Do not use `dsh plugin add ./packages/dsh-plugin` directly from a fresh checkout. pnpm records a `link:` dependency, and Node resolves imports from the real checkout path. The source installer first runs the package's locked `npm ci`, then links it and installs the local Python Adapter. Normal users should always use the registry-backed setup command above.
67
+
66
68
  See the [complete DSH Web quickstart](https://github.com/istarwyh/harbor-self-evolving/blob/main/docs/dsh-web-quickstart.md) for UI verification, first evaluation, Candidate comparison, and troubleshooting.
67
69
 
68
70
  The Plugin never deploys a Candidate or mutates the active Champion. Existing CI/CD remains responsible for building, deploying, and promoting the exact evaluated artifact.
package/lib/setup.js CHANGED
@@ -2,6 +2,7 @@ import { mkdir, readFile, rename, stat, writeFile } from 'node:fs/promises'
2
2
  import os from 'node:os'
3
3
  import path from 'node:path'
4
4
  import process from 'node:process'
5
+ import { fileURLToPath } from 'node:url'
5
6
 
6
7
  import { runProcess } from './process.js'
7
8
 
@@ -94,6 +95,26 @@ export function resolveSetupOptions(raw = {}, environment = {}) {
94
95
  }
95
96
  }
96
97
 
98
+ export async function resolveLocalPluginDirectory(pluginSpec, cwd = process.cwd()) {
99
+ let candidate
100
+ if (pluginSpec.startsWith('file://')) candidate = fileURLToPath(pluginSpec)
101
+ else if (pluginSpec.startsWith('file:')) candidate = path.resolve(cwd, pluginSpec.slice(5))
102
+ else if (!pluginSpec.startsWith('github:') && !pluginSpec.startsWith('git+')) {
103
+ candidate = path.resolve(cwd, pluginSpec)
104
+ }
105
+ if (!candidate) return undefined
106
+
107
+ try {
108
+ const details = await stat(candidate)
109
+ if (!details.isDirectory()) return undefined
110
+ const manifest = JSON.parse(await readFile(path.join(candidate, 'package.json'), 'utf8'))
111
+ return manifest.name === 'dsh-harbor-evolution' ? candidate : undefined
112
+ } catch (error) {
113
+ if (error.code === 'ENOENT' || error instanceof SyntaxError) return undefined
114
+ throw error
115
+ }
116
+ }
117
+
97
118
  function quoted(value) {
98
119
  return JSON.stringify(value)
99
120
  }
@@ -215,6 +236,19 @@ export async function setupIntegration(raw = {}, dependencies = {}) {
215
236
  warnings.push(`Docker is not ready; installation can finish, but Harbor Jobs will fail until it is available. ${processFailure(error)}`)
216
237
  }
217
238
 
239
+ const localPluginDir = await resolveLocalPluginDirectory(
240
+ config.pluginSpec,
241
+ dependencies.cwd ?? process.cwd(),
242
+ )
243
+ if (localPluginDir) {
244
+ progress('Preparing dependencies for the linked DSH plugin checkout...')
245
+ await requireCommand(run, 'npm')
246
+ // Node resolves a symlinked package from its real checkout path. Install
247
+ // the complete locked graph there so runtime dependencies and host peers
248
+ // do not disappear behind the profile's `link:` entry.
249
+ await run('npm', ['ci', '--ignore-scripts'], { cwd: localPluginDir })
250
+ }
251
+
218
252
  progress('2/4 Installing the Harbor Python runtime...')
219
253
  await mkdir(config.runtimeDir, { recursive: true })
220
254
  await run('uv', ['venv', '--python', '3.12', '--allow-existing', config.venvDir])
@@ -229,7 +263,7 @@ export async function setupIntegration(raw = {}, dependencies = {}) {
229
263
  try {
230
264
  await run('pnpm', [
231
265
  '--silent', 'dlx', `@deepseek-ai/dsh@${DSH_VERSION}`,
232
- 'plugin', '--profile', config.profile, 'add', '-w', config.pluginSpec,
266
+ 'plugin', '--profile', config.profile, 'add', '-w', '--save-exact', config.pluginSpec,
233
267
  ], { env: { ...env, DSH_HOME: config.dshHome } })
234
268
  } catch (error) {
235
269
  throw new Error(processFailure(error))
@@ -246,6 +280,7 @@ export async function setupIntegration(raw = {}, dependencies = {}) {
246
280
 
247
281
  return {
248
282
  ...config,
283
+ localPluginDir,
249
284
  patchChanged,
250
285
  harborVersion: harborVersion.stdout.trim() || harborVersion.stderr.trim(),
251
286
  warnings,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-harbor-evolution",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "DeepSeek Harness plugin and bundled Skill for safely evolving Cordis Candidates with Harbor.",
5
5
  "type": "module",
6
6
  "main": "index.js",