yugoo-design 0.2.0 → 0.2.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.
Files changed (29) hide show
  1. package/README.md +4 -4
  2. package/bin/npm-agent-installation.mjs +1 -1
  3. package/bin/npm-installer-dsh.mjs +92 -4
  4. package/package.json +3 -2
  5. package/payload/desktop-preparation/materials.json +4 -4
  6. package/payload/desktop-preparation/qwenwork-template/authoring/studio-creators/material.json +1 -1
  7. package/payload/desktop-preparation/qwenwork-template/authoring/studio-creators/source/docs/system-design-baseline.md +5 -0
  8. package/payload/desktop-preparation/studio-authoring-template/authoring/studio-creators/material.json +1 -1
  9. package/payload/desktop-preparation/studio-authoring-template/authoring/studio-creators/source/docs/system-design-baseline.md +5 -0
  10. package/payload/overlays/claude-code/.claude-plugin/plugin.json +1 -1
  11. package/payload/overlays/claude-code/authoring/studio-creators/material.json +1 -1
  12. package/payload/overlays/claude-code/authoring/studio-creators/source/docs/system-design-baseline.md +5 -0
  13. package/payload/overlays/codex/.codex-plugin/plugin.json +1 -1
  14. package/payload/overlays/codex/authoring/studio-creators/material.json +1 -1
  15. package/payload/overlays/codex/authoring/studio-creators/source/docs/system-design-baseline.md +5 -0
  16. package/payload/overlays/qoder/.qoder-plugin/plugin.json +1 -1
  17. package/payload/overlays/qoder/authoring/studio-creators/material.json +1 -1
  18. package/payload/overlays/qoder/authoring/studio-creators/source/docs/system-design-baseline.md +5 -0
  19. package/payload/shared/authoring/studio-creators/material.json +1 -1
  20. package/payload/shared/authoring/studio-creators/source/docs/system-design-baseline.md +5 -0
  21. package/payload/shared/knowledge/runtime-manifest.json +2 -1
  22. package/payload/shared/scripts/design.mjs +1 -1
  23. package/payload/shared/scripts/{server-BBHB9EQr.mjs → server-BnEtfptI.mjs} +1 -1
  24. package/payload/shared/scripts/{studio-CS5TyoYn.mjs → studio-CFUWk0vJ.mjs} +1 -1
  25. package/payload/shared/scripts/{studio-instances-D-Y1WNya.mjs → studio-instances-gQFR9yqL.mjs} +65 -2
  26. package/payload/shared/scripts/workbuddy-panel-service.mjs +1 -1
  27. package/payload/shared/web/client.js +127 -86
  28. package/release-hosts.json +1 -1
  29. package/release-manifest.json +32 -31
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Yugoo Design
2
2
 
3
- Package: `yugoo-design@0.2.0`.
3
+ Package: `yugoo-design@0.2.2`.
4
4
 
5
5
  Yugoo Design (语构设计系统) is an interactive design plugin for native Agent Hosts.
6
6
  It combines domain methods, Design Projects, versioned Design Files and shared
@@ -55,7 +55,7 @@ from another operating system requires an explicit Windows path and reports that
55
55
  locator as unverified; it does not establish target runtime acceptance.
56
56
 
57
57
  ```sh
58
- ONNXRUNTIME_NODE_INSTALL_CUDA=skip npm install --ignore-scripts=false --save-exact yugoo-design@0.2.0 --registry=https://registry.npmjs.org
58
+ ONNXRUNTIME_NODE_INSTALL_CUDA=skip npm install --ignore-scripts=false --save-exact yugoo-design@0.2.2 --registry=https://registry.npmjs.org
59
59
  npx --no-install yugoo-design --help
60
60
  ```
61
61
 
@@ -72,7 +72,7 @@ allowBuilds:
72
72
  ```
73
73
 
74
74
  ```sh
75
- ONNXRUNTIME_NODE_INSTALL_CUDA=skip pnpm add --save-exact yugoo-design@0.2.0 --registry=https://registry.npmjs.org
75
+ ONNXRUNTIME_NODE_INSTALL_CUDA=skip pnpm add --save-exact yugoo-design@0.2.2 --registry=https://registry.npmjs.org
76
76
  pnpm exec yugoo-design --help
77
77
  ```
78
78
 
@@ -121,7 +121,7 @@ process value:
121
121
  $previousOrtCuda = [Environment]::GetEnvironmentVariable('ONNXRUNTIME_NODE_INSTALL_CUDA', 'Process')
122
122
  try {
123
123
  $env:ONNXRUNTIME_NODE_INSTALL_CUDA = 'skip'
124
- npm install --ignore-scripts=false --save-exact yugoo-design@0.2.0 --registry=https://registry.npmjs.org
124
+ npm install --ignore-scripts=false --save-exact yugoo-design@0.2.2 --registry=https://registry.npmjs.org
125
125
  } finally {
126
126
  [Environment]::SetEnvironmentVariable('ONNXRUNTIME_NODE_INSTALL_CUDA', $previousOrtCuda, 'Process')
127
127
  }
@@ -73,7 +73,7 @@ export function installationResult(host, result, packageIdentity, { disableEmbed
73
73
  activation: failed ? 'not-performed' : 'required', usability: 'unverified',
74
74
  embedding: { status: disableEmbedding ? 'disabled' : 'unverified', blocksBasicDesign: false },
75
75
  nextActions: failed ? [{ action: 'inspect-retained-state', automatic: false, path: result.receiptFile,
76
- message: 'Inspect the owning receipt and retained DSH state before another operation. No automatic rollback or retry was attempted.' }]
76
+ message: result.failure?.recovery ?? 'Inspect the owning receipt and retained DSH state before another operation. No automatic rollback or retry was attempted.' }]
77
77
  : activationActions(host, result, disableEmbedding) } }
78
78
  }
79
79
 
@@ -6,7 +6,8 @@ import { createHash, randomUUID } from 'node:crypto'
6
6
  import { lstat, readFile, realpath, writeFile } from 'node:fs/promises'
7
7
  import { dirname, isAbsolute, join, resolve } from 'node:path'
8
8
  import { pathToFileURL } from 'node:url'
9
- import { promisify } from 'node:util'
9
+ import { isDeepStrictEqual, promisify } from 'node:util'
10
+ import { createRequire } from 'node:module'
10
11
 
11
12
  const exec = promisify(execFile)
12
13
  const admitted = new WeakMap()
@@ -15,6 +16,7 @@ const canonical = value => Array.isArray(value) ? value.map(canonical) : value &
15
16
  ? Object.fromEntries(Object.keys(value).sort().map(key => [key, canonical(value[key])])) : value
16
17
  const digest = value => sha(JSON.stringify(canonical(value)))
17
18
  const beneath = isPathWithin
19
+ const exactVersion = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/u
18
20
  export const DSH_INSTALL_MAX_OUTPUT_BYTES = 1024 * 1024
19
21
 
20
22
  /** Install duration belongs to the native package manager, not a probe timer. */
@@ -181,7 +183,7 @@ async function readOwnedReceipt(path, state, profile, currentProduct) {
181
183
  assert.match(receipt.id ?? '', /^[0-9a-f-]{36}$/u)
182
184
  assert.equal(receipt.receiptPath, path)
183
185
  assert.equal(join(dirname(path), receipt.id + '.dsh-result.json'), path)
184
- assert.equal(receipt.status, 'registered-config-parsed', 'Successful owned installation required')
186
+ assert.equal(receipt.status, 'registered-config-parsed', 'Successful owned installation required; inspect failed DSH state in the official host plugin manager instead of reapplying its plan or receipt')
185
187
  assert.equal(receipt.ownershipEstablished, true, 'Previous installation ownership was not established')
186
188
  assert.equal(receipt.exitCode, 0); assert.equal(receipt.partialStateRetained, false)
187
189
  assert.equal(receipt.userConfigurationPreserved, true)
@@ -448,6 +450,72 @@ export async function inspectDshInstallation(options) {
448
450
  runtimeMounted: false, bundleCycleVerified: false, releaseValidated: false }
449
451
  }
450
452
 
453
+ async function workspaceSettings(bytes) {
454
+ if (bytes === null) return null
455
+ const { parseDocument } = await import('yaml')
456
+ const document = parseDocument(bytes.toString('utf8'), { uniqueKeys: true })
457
+ if (document.errors.length || document.warnings.length) return null
458
+ const value = document.toJS({ maxAliasCount: 100 })
459
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return null
460
+ const { minimumReleaseAgeExclude = [], ...settings } = value
461
+ if (!Array.isArray(minimumReleaseAgeExclude) || !minimumReleaseAgeExclude.every(item => typeof item === 'string')) return null
462
+ return { settings, exclusions: minimumReleaseAgeExclude }
463
+ }
464
+
465
+ // Follow only exact runtime declarations in the selected installed aggregate.
466
+ // Reading package metadata must not execute code or depend on package.json exports.
467
+ async function installedExactSelectors(installed) {
468
+ const selectors = new Set(), visited = new Set()
469
+ async function visit(path, name, version) {
470
+ path = await realpath(path)
471
+ if (visited.has(path)) return
472
+ visited.add(path)
473
+ const bytes = await boundedFile(path), manifest = JSON.parse(bytes)
474
+ if (manifest.name !== name || manifest.version !== version) return
475
+ selectors.add(`${name}@${version}`)
476
+ const require = createRequire(path)
477
+ for (const [dependency, pin] of Object.entries({ ...manifest.dependencies, ...manifest.optionalDependencies })) {
478
+ if (!/^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/u.test(dependency) || !exactVersion.test(pin)) continue
479
+ for (const search of require.resolve.paths(dependency) ?? []) {
480
+ const candidate = join(search, dependency, 'package.json')
481
+ if (await regular(candidate, true) === null) continue
482
+ await visit(candidate, dependency, pin)
483
+ break
484
+ }
485
+ }
486
+ }
487
+ const path = join(installed.realPackageDir, 'package.json')
488
+ assert.equal(sha(await regular(path)), installed.manifestSha256, 'Installed aggregate metadata changed')
489
+ await visit(path, installed.name, installed.version)
490
+ return selectors
491
+ }
492
+
493
+ async function preservedConfigPins(before, after, workspaceBefore) {
494
+ const changedFiles = [...new Set([...Object.keys(before.configPins), ...Object.keys(after.configPins)])]
495
+ .filter(path => before.configPins[path] !== after.configPins[path])
496
+ const result = { preserved: changedFiles.length === 0, changedFiles, releaseAgeExclusionsAdded: [],
497
+ reason: changedFiles.length === 0 ? 'unchanged' : 'configuration-file-changed' }
498
+ const workspace = join(before.dir, 'pnpm-workspace.yaml')
499
+ if (changedFiles.length !== 1 || changedFiles[0] !== workspace || !after.installed) return result
500
+ try {
501
+ const bytes = await regular(workspace, true)
502
+ if (bytes === null || sha(bytes) !== after.configPins[workspace]) return result
503
+ const old = await workspaceSettings(workspaceBefore), current = await workspaceSettings(bytes)
504
+ if (!old || !current) return { ...result, reason: 'workspace-policy-unverified' }
505
+ if (!isDeepStrictEqual(old.settings, current.settings)) return { ...result, reason: 'workspace-settings-changed' }
506
+ if (!isDeepStrictEqual(old.exclusions, current.exclusions.slice(0, old.exclusions.length)))
507
+ return { ...result, reason: 'existing-release-age-exclusions-changed' }
508
+ const added = current.exclusions.slice(old.exclusions.length)
509
+ if (!added.length || new Set(added).size !== added.length || added.some(value => old.exclusions.includes(value))) return result
510
+ const exact = await installedExactSelectors(after.installed)
511
+ if (added.some(value => !exact.has(value))) return { ...result, reason: 'release-age-exclusion-outside-exact-dependencies' }
512
+ return { ...result, preserved: true, releaseAgeExclusionsAdded: added, reason: 'exact-dependency-release-age-exclusions-added' }
513
+ } catch {
514
+ // Unreadable or unsupported policy/metadata cannot justify a changed pin.
515
+ return { ...result, reason: 'workspace-policy-unverified' }
516
+ }
517
+ }
518
+
451
519
  /** Runs only the pinned public CLI; retains partial state on failure, never rolls back. */
452
520
  export async function applyDshInstallation(plan, { adapter, signal, timeoutMs = 0, logDirectory } = {}) {
453
521
  plan = structuredClone(plan)
@@ -456,6 +524,9 @@ export async function applyDshInstallation(plan, { adapter, signal, timeoutMs =
456
524
  const state = await protocol(adapter)
457
525
  const fresh = await planDshInstallation({ ...plan, adapter })
458
526
  assert.equal(fresh.planSha256, plan.planSha256, 'Plan or profile changed; replan before execution')
527
+ const workspace = join(fresh.before.dir, 'pnpm-workspace.yaml')
528
+ const workspaceBefore = await regular(workspace, true)
529
+ assert.equal(workspaceBefore === null ? null : sha(workspaceBefore), fresh.before.configPins[workspace], 'Workspace changed; replan before execution')
459
530
  if (logDirectory !== undefined) {
460
531
  await safeDirectory(logDirectory)
461
532
  for (const root of [state.dshHome, plan.product?.npmRoot, plan.previous?.product.npmRoot,
@@ -475,20 +546,37 @@ export async function applyDshInstallation(plan, { adapter, signal, timeoutMs =
475
546
  catch (error) { diagnosticError = String(error.code ?? error.name) }
476
547
  }
477
548
  let readback = null, readbackError = null, userConfigurationPreserved = false
549
+ let configurationChanges = { preserved: false, changedFiles: [], releaseAgeExclusionsAdded: [], reason: 'readback-unverified' }
478
550
  try {
479
551
  readback = await inspectDshInstallation({ ...plan, adapter })
552
+ configurationChanges = await preservedConfigPins(plan.before, readback, workspaceBefore)
480
553
  userConfigurationPreserved = readback.foreignSha256 === plan.before.foreignSha256
481
- && digest(readback.patches) === digest(plan.before.patches) && digest(readback.configPins) === digest(plan.before.configPins)
554
+ && digest(readback.patches) === digest(plan.before.patches) && configurationChanges.preserved
482
555
  && (plan.action !== 'update' || digest(readback.bundles) === digest(plan.before.bundles))
483
556
  } catch (error) { readbackError = error.message }
484
557
  const succeeded = exitCode === 0 && diagnosticError === null && userConfigurationPreserved && readback?.configurationParsed === true
558
+ const reasons = []
559
+ if (exitCode !== 0) reasons.push('native-command-' + execution.state)
560
+ if (diagnosticError !== null) reasons.push('command-log-unavailable')
561
+ if (readback === null) reasons.push('configuration-readback-failed')
562
+ else {
563
+ if (!userConfigurationPreserved) reasons.push('user-configuration-changed')
564
+ if (!readback.packageInstalled) reasons.push('package-not-installed')
565
+ if (!readback.bundleRegistered) reasons.push('bundle-not-registered')
566
+ if (!readback.configurationParsed) reasons.push('configuration-not-parsed')
567
+ }
568
+ const failure = succeeded ? null : { reasons, automaticRetry: false,
569
+ recovery: 'Inspect this receipt, its command logs and the retained profile in the official DSH Plugins interface. '
570
+ + 'Use the existing host plugin manager to inspect or repair package/bundle state after reviewing the cause. '
571
+ + 'Do not reapply this saved plan or use a failed receipt as previous ownership. DSH has no installer recover/adopt route; '
572
+ + 'a restart or an already-registered observation cannot repair failed transaction ownership. Keep existing projects and configuration.' }
485
573
  const ownershipEstablished = Boolean(succeeded && plan.product?.releaseSelection && (plan.previous
486
574
  || plan.action === 'install' && !plan.before.installed && !plan.before.registered && execution.state === 'completed'))
487
575
  return { schemaVersion: 2, kind: 'dsh-installation', host: 'dsh', route: 'official-dsh-bundle',
488
576
  product: plan.product, planSnapshot: plan, planSha256: plan.planSha256, operation: plan.action,
489
577
  ownershipEstablished, source: { expected: expectedSource(plan), observed: readback === null ? null : ownedState(readback) },
490
578
  registryAcquisitionVerified: false, scope: adapter.scope, status: succeeded ? 'registered-config-parsed' : 'failed-partial-state-retained',
491
- exitCode, executionError, execution, diagnosticError, readbackError, readback, userConfigurationPreserved,
579
+ exitCode, executionError, execution, diagnosticError, readbackError, readback, userConfigurationPreserved, configurationChanges, failure,
492
580
  userConfigurationStatus: readback === null ? 'unverified' : userConfigurationPreserved ? 'observed-matching' : 'changed',
493
581
  rollbackAttempted: false, rollbackScope: 'adapter-only; official CLI may perform limited compatibility restoration', partialStateRetained: !succeeded,
494
582
  runtimeMounted: false, bundleCycleVerified: false, releaseValidated: false }
package/package.json CHANGED
@@ -49,7 +49,8 @@
49
49
  "@huggingface/transformers": "3.8.1",
50
50
  "onnxruntime-common": "1.21.0",
51
51
  "undici": "8.10.2",
52
- "trash": "10.1.1"
52
+ "trash": "10.1.1",
53
+ "yaml": "2.9.1"
53
54
  },
54
55
  "x-design-release-review": {
55
56
  "fixture": false,
@@ -78,5 +79,5 @@
78
79
  }
79
80
  },
80
81
  "name": "yugoo-design",
81
- "version": "0.2.0"
82
+ "version": "0.2.2"
82
83
  }
@@ -14,7 +14,7 @@
14
14
  "qwenwork-template/NOTICE": "6b4eec391144fcbd96ec7b45a28764ab1932722a96325248377c3e28aac2c62d",
15
15
  "qwenwork-template/THIRD_PARTY_NOTICES.md": "bfcab921c6c15ccc47f9b1a6cc5941675c95962de5ea5b0edc50fbfa2aef136a",
16
16
  "qwenwork-template/authoring/studio-creators/index.md": "01eb453e4bcbd7cd104bdd9032a1c1d09c3a4de5b69982eaf18ae528c6a7ea37",
17
- "qwenwork-template/authoring/studio-creators/material.json": "2a8c1ebe8b6fed2cea583f162ddbe5ec17350ed3a981d97d0cb395cbc5673466",
17
+ "qwenwork-template/authoring/studio-creators/material.json": "c2fdb30666942a942157c7f1e1a9ecfe542b87bf35b30412a6a541e584fac216",
18
18
  "qwenwork-template/authoring/studio-creators/source/.agents/skills/design-bundle-creator/SKILL.md": "99c0ddca35a9a65ca9b097ee9072994a1ca2a4848ef6fe3ca07f5f29956806ed",
19
19
  "qwenwork-template/authoring/studio-creators/source/.agents/skills/design-bundle-creator/agents/openai.yaml": "60da07d566f3c27a4f9d373d14473db1bbae82fa36f1ada035c6f9128d74bb00",
20
20
  "qwenwork-template/authoring/studio-creators/source/.agents/skills/design-bundle-creator/assets/skill.template.yaml": "d7a6c63460403c981a7a107f9a4a715919b8653ce5aa268ce6aecf100b925b59",
@@ -38,7 +38,7 @@
38
38
  "qwenwork-template/authoring/studio-creators/source/docs/bundle-contract.md": "aa4da3d9be862de30f70f5539061c7018144047e8bef9bcc37e54ca119a1767f",
39
39
  "qwenwork-template/authoring/studio-creators/source/docs/dsl-spec.md": "9d2897f48ff470d1a51d93af0b1d90b8173052f1a6e0380ba4629470dfdcfc5e",
40
40
  "qwenwork-template/authoring/studio-creators/source/docs/panel-uiux-standard.md": "37d3f5095fd4e7b62fb46a13375bc5b265e5ca4798f5016a0cba42ba9129c9b8",
41
- "qwenwork-template/authoring/studio-creators/source/docs/system-design-baseline.md": "cb34d1c68576ada8d8626a653c46ac875e651e365f2db39e0ca305b6275f4e9a",
41
+ "qwenwork-template/authoring/studio-creators/source/docs/system-design-baseline.md": "eecd569936892c90d32d7822547972913d373ef42af2970ffdac9d38abb2cbe7",
42
42
  "qwenwork-template/authoring/studio-creators/source/docs/wiki/extending.md": "2774e855d86104dcf49559cbcf868b1083da0d39c669cec4d914c56b82852b3d",
43
43
  "qwenwork-template/authoring/studio-creators/source/docs/wiki/terminology.md": "e17ac6fd530861295dbf8f6fd7bc742f93fb32707cc19f377632c2352f9385a0",
44
44
  "qwenwork-template/authoring/studio-creators/source/examples/community-workshop-delivery/mindset.md": "647002e93e0ca4700ad167f08990a7360da148a46c0830b862769840c0dc93d8",
@@ -127,7 +127,7 @@
127
127
  "src/workbuddy-relay-service.mjs": "44d60d6956250417507fb76c71c3030a01bc38e565e4572a761b46f255f8e669",
128
128
  "src/workbuddy-ui-probes.mjs": "a91d4651248125769254755bdf66a44bbc9e5a793dad0a137c35acbb10a89a88",
129
129
  "studio-authoring-template/authoring/studio-creators/index.md": "01eb453e4bcbd7cd104bdd9032a1c1d09c3a4de5b69982eaf18ae528c6a7ea37",
130
- "studio-authoring-template/authoring/studio-creators/material.json": "2a8c1ebe8b6fed2cea583f162ddbe5ec17350ed3a981d97d0cb395cbc5673466",
130
+ "studio-authoring-template/authoring/studio-creators/material.json": "c2fdb30666942a942157c7f1e1a9ecfe542b87bf35b30412a6a541e584fac216",
131
131
  "studio-authoring-template/authoring/studio-creators/source/.agents/skills/design-bundle-creator/SKILL.md": "99c0ddca35a9a65ca9b097ee9072994a1ca2a4848ef6fe3ca07f5f29956806ed",
132
132
  "studio-authoring-template/authoring/studio-creators/source/.agents/skills/design-bundle-creator/agents/openai.yaml": "60da07d566f3c27a4f9d373d14473db1bbae82fa36f1ada035c6f9128d74bb00",
133
133
  "studio-authoring-template/authoring/studio-creators/source/.agents/skills/design-bundle-creator/assets/skill.template.yaml": "d7a6c63460403c981a7a107f9a4a715919b8653ce5aa268ce6aecf100b925b59",
@@ -151,7 +151,7 @@
151
151
  "studio-authoring-template/authoring/studio-creators/source/docs/bundle-contract.md": "aa4da3d9be862de30f70f5539061c7018144047e8bef9bcc37e54ca119a1767f",
152
152
  "studio-authoring-template/authoring/studio-creators/source/docs/dsl-spec.md": "9d2897f48ff470d1a51d93af0b1d90b8173052f1a6e0380ba4629470dfdcfc5e",
153
153
  "studio-authoring-template/authoring/studio-creators/source/docs/panel-uiux-standard.md": "37d3f5095fd4e7b62fb46a13375bc5b265e5ca4798f5016a0cba42ba9129c9b8",
154
- "studio-authoring-template/authoring/studio-creators/source/docs/system-design-baseline.md": "cb34d1c68576ada8d8626a653c46ac875e651e365f2db39e0ca305b6275f4e9a",
154
+ "studio-authoring-template/authoring/studio-creators/source/docs/system-design-baseline.md": "eecd569936892c90d32d7822547972913d373ef42af2970ffdac9d38abb2cbe7",
155
155
  "studio-authoring-template/authoring/studio-creators/source/docs/wiki/extending.md": "2774e855d86104dcf49559cbcf868b1083da0d39c669cec4d914c56b82852b3d",
156
156
  "studio-authoring-template/authoring/studio-creators/source/docs/wiki/terminology.md": "e17ac6fd530861295dbf8f6fd7bc742f93fb32707cc19f377632c2352f9385a0",
157
157
  "studio-authoring-template/authoring/studio-creators/source/examples/community-workshop-delivery/mindset.md": "647002e93e0ca4700ad167f08990a7360da148a46c0830b862769840c0dc93d8",