@hongmaple0820/scale-engine 0.49.0 → 0.50.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 (183) hide show
  1. package/README.en.md +2 -2
  2. package/README.md +2 -2
  3. package/dist/api/DashboardHttpConfig.d.ts +28 -0
  4. package/dist/api/DashboardHttpConfig.js +110 -0
  5. package/dist/api/DashboardHttpConfig.js.map +1 -0
  6. package/dist/api/cli.js +102 -11
  7. package/dist/api/cli.js.map +1 -1
  8. package/dist/api/http.d.ts +1 -0
  9. package/dist/api/http.js +52 -0
  10. package/dist/api/http.js.map +1 -0
  11. package/dist/artifact/types.d.ts +5 -0
  12. package/dist/artifact/types.js.map +1 -1
  13. package/dist/bootstrap/DependencyBootstrap.d.ts +1 -0
  14. package/dist/bootstrap/DependencyBootstrap.js +14 -3
  15. package/dist/bootstrap/DependencyBootstrap.js.map +1 -1
  16. package/dist/cli/cortexApplyCommand.d.ts +26 -0
  17. package/dist/cli/cortexApplyCommand.js +74 -0
  18. package/dist/cli/cortexApplyCommand.js.map +1 -0
  19. package/dist/cli/cortexCandidateCommands.d.ts +42 -0
  20. package/dist/cli/cortexCandidateCommands.js +119 -0
  21. package/dist/cli/cortexCandidateCommands.js.map +1 -0
  22. package/dist/cli/cortexCommands.d.ts +31 -0
  23. package/dist/cli/cortexCommands.js +102 -17
  24. package/dist/cli/cortexCommands.js.map +1 -1
  25. package/dist/cli/engineBootstrap.d.ts +1 -1
  26. package/dist/cli/engineBootstrap.js +2 -0
  27. package/dist/cli/engineBootstrap.js.map +1 -1
  28. package/dist/cli/evalCommands.js +1 -0
  29. package/dist/cli/evalCommands.js.map +1 -1
  30. package/dist/cli/phaseCommands.d.ts +28 -0
  31. package/dist/cli/phaseCommands.js +148 -9
  32. package/dist/cli/phaseCommands.js.map +1 -1
  33. package/dist/cli/runtimeSkillCommands.js +12 -2
  34. package/dist/cli/runtimeSkillCommands.js.map +1 -1
  35. package/dist/cli/shieldCommands.d.ts +1 -0
  36. package/dist/cli/shieldCommands.js +20 -7
  37. package/dist/cli/shieldCommands.js.map +1 -1
  38. package/dist/cli/workflowEvidenceCommands.d.ts +120 -0
  39. package/dist/cli/workflowEvidenceCommands.js +228 -2
  40. package/dist/cli/workflowEvidenceCommands.js.map +1 -1
  41. package/dist/cortex/AutoFixEventObservations.d.ts +11 -0
  42. package/dist/cortex/AutoFixEventObservations.js +72 -0
  43. package/dist/cortex/AutoFixEventObservations.js.map +1 -0
  44. package/dist/cortex/GateEvidenceObservations.d.ts +22 -0
  45. package/dist/cortex/GateEvidenceObservations.js +179 -0
  46. package/dist/cortex/GateEvidenceObservations.js.map +1 -0
  47. package/dist/cortex/GovernanceMetrics.d.ts +2 -0
  48. package/dist/cortex/GovernanceMetrics.js +112 -22
  49. package/dist/cortex/GovernanceMetrics.js.map +1 -1
  50. package/dist/cortex/InstinctApplicationRecorder.d.ts +28 -0
  51. package/dist/cortex/InstinctApplicationRecorder.js +145 -0
  52. package/dist/cortex/InstinctApplicationRecorder.js.map +1 -0
  53. package/dist/cortex/InstinctCandidateAudit.d.ts +3 -0
  54. package/dist/cortex/InstinctCandidateAudit.js +39 -0
  55. package/dist/cortex/InstinctCandidateAudit.js.map +1 -0
  56. package/dist/cortex/InstinctCandidateReview.d.ts +32 -0
  57. package/dist/cortex/InstinctCandidateReview.js +125 -0
  58. package/dist/cortex/InstinctCandidateReview.js.map +1 -0
  59. package/dist/cortex/InstinctExtractor.d.ts +1 -0
  60. package/dist/cortex/InstinctExtractor.js +24 -17
  61. package/dist/cortex/InstinctExtractor.js.map +1 -1
  62. package/dist/cortex/InstinctRuntimeEvidence.d.ts +14 -0
  63. package/dist/cortex/InstinctRuntimeEvidence.js +120 -0
  64. package/dist/cortex/InstinctRuntimeEvidence.js.map +1 -0
  65. package/dist/cortex/InstinctStore.d.ts +31 -4
  66. package/dist/cortex/InstinctStore.js +120 -20
  67. package/dist/cortex/InstinctStore.js.map +1 -1
  68. package/dist/cortex/SessionInjector.d.ts +1 -0
  69. package/dist/cortex/SessionInjector.js +54 -4
  70. package/dist/cortex/SessionInjector.js.map +1 -1
  71. package/dist/dashboard/DashboardServer.d.ts +237 -0
  72. package/dist/dashboard/DashboardServer.js +1083 -19
  73. package/dist/dashboard/DashboardServer.js.map +1 -1
  74. package/dist/dashboard/spa/assets/index-VYBCLBje.js +11 -0
  75. package/dist/dashboard/spa/assets/index-VhwY_ac1.css +1 -0
  76. package/dist/dashboard/spa/assets/naive-ui-BQy2AJkt.js +3340 -0
  77. package/dist/dashboard/spa/assets/vendor-BPU6aOYA.js +3 -0
  78. package/dist/dashboard/spa/assets/vue-CQQMb5Wi.js +17 -0
  79. package/dist/dashboard/spa/index.html +16 -0
  80. package/dist/env/EnvironmentDoctor.js +12 -7
  81. package/dist/env/EnvironmentDoctor.js.map +1 -1
  82. package/dist/eval/WorkflowEval.d.ts +9 -0
  83. package/dist/eval/WorkflowEval.js +348 -2
  84. package/dist/eval/WorkflowEval.js.map +1 -1
  85. package/dist/memory/MemoryBrain.d.ts +13 -0
  86. package/dist/memory/MemoryBrain.js +47 -0
  87. package/dist/memory/MemoryBrain.js.map +1 -1
  88. package/dist/memory/MemoryFabric.d.ts +14 -1
  89. package/dist/memory/MemoryFabric.js +72 -8
  90. package/dist/memory/MemoryFabric.js.map +1 -1
  91. package/dist/memory/MemoryLearning.d.ts +1 -0
  92. package/dist/memory/MemoryLearning.js +6 -3
  93. package/dist/memory/MemoryLearning.js.map +1 -1
  94. package/dist/memory/MemoryProviders.d.ts +8 -1
  95. package/dist/memory/MemoryProviders.js +143 -29
  96. package/dist/memory/MemoryProviders.js.map +1 -1
  97. package/dist/runtime/AiOsRuntime.d.ts +14 -1
  98. package/dist/runtime/AiOsRuntime.js +59 -3
  99. package/dist/runtime/AiOsRuntime.js.map +1 -1
  100. package/dist/runtime/RuntimeDoctor.js +3 -1
  101. package/dist/runtime/RuntimeDoctor.js.map +1 -1
  102. package/dist/runtime/RuntimeEvidenceLedger.d.ts +6 -0
  103. package/dist/runtime/RuntimeEvidenceLedger.js +52 -1
  104. package/dist/runtime/RuntimeEvidenceLedger.js.map +1 -1
  105. package/dist/runtime/SessionLedger.d.ts +2 -0
  106. package/dist/runtime/SessionLedger.js +4 -0
  107. package/dist/runtime/SessionLedger.js.map +1 -1
  108. package/dist/setup/SetupVerification.js +53 -5
  109. package/dist/setup/SetupVerification.js.map +1 -1
  110. package/dist/shield/PolicyCompiler.js +73 -12
  111. package/dist/shield/PolicyCompiler.js.map +1 -1
  112. package/dist/shield/ProtectedPaths.js +4 -2
  113. package/dist/shield/ProtectedPaths.js.map +1 -1
  114. package/dist/skills/SkillCatalog.d.ts +2 -0
  115. package/dist/skills/SkillCatalog.js +8 -0
  116. package/dist/skills/SkillCatalog.js.map +1 -1
  117. package/dist/skills/SkillDoctor.d.ts +19 -2
  118. package/dist/skills/SkillDoctor.js +163 -13
  119. package/dist/skills/SkillDoctor.js.map +1 -1
  120. package/dist/tools/SafeCommandRunner.d.ts +1 -0
  121. package/dist/tools/SafeCommandRunner.js +1 -0
  122. package/dist/tools/SafeCommandRunner.js.map +1 -1
  123. package/dist/tools/ToolCapabilityRegistry.js +25 -3
  124. package/dist/tools/ToolCapabilityRegistry.js.map +1 -1
  125. package/dist/tools/ToolOrchestrator.js +21 -0
  126. package/dist/tools/ToolOrchestrator.js.map +1 -1
  127. package/dist/version.d.ts +1 -1
  128. package/dist/version.js +1 -1
  129. package/dist/workflow/AgentLoopReadiness.d.ts +103 -0
  130. package/dist/workflow/AgentLoopReadiness.js +371 -0
  131. package/dist/workflow/AgentLoopReadiness.js.map +1 -0
  132. package/dist/workflow/EcosystemReadinessGate.d.ts +46 -0
  133. package/dist/workflow/EcosystemReadinessGate.js +126 -0
  134. package/dist/workflow/EcosystemReadinessGate.js.map +1 -0
  135. package/dist/workflow/EngineeringStandards.js +48 -3
  136. package/dist/workflow/EngineeringStandards.js.map +1 -1
  137. package/dist/workflow/GateCatalog.js +9 -0
  138. package/dist/workflow/GateCatalog.js.map +1 -1
  139. package/dist/workflow/GovernanceTemplatePacks.js +2 -26
  140. package/dist/workflow/GovernanceTemplatePacks.js.map +1 -1
  141. package/dist/workflow/GovernanceTemplates.js +8 -1
  142. package/dist/workflow/GovernanceTemplates.js.map +1 -1
  143. package/dist/workflow/ReleaseDeploymentLedger.d.ts +63 -0
  144. package/dist/workflow/ReleaseDeploymentLedger.js +154 -0
  145. package/dist/workflow/ReleaseDeploymentLedger.js.map +1 -0
  146. package/dist/workflow/ReviewAnalyzer.js +50 -3
  147. package/dist/workflow/ReviewAnalyzer.js.map +1 -1
  148. package/dist/workflow/SessionPreamble.d.ts +7 -0
  149. package/dist/workflow/SessionPreamble.js +48 -9
  150. package/dist/workflow/SessionPreamble.js.map +1 -1
  151. package/dist/workflow/VerificationCommands.d.ts +1 -0
  152. package/dist/workflow/VerificationCommands.js.map +1 -1
  153. package/dist/workflow/VerificationProfile.d.ts +5 -0
  154. package/dist/workflow/VerificationProfile.js +26 -0
  155. package/dist/workflow/VerificationProfile.js.map +1 -1
  156. package/dist/workflow/VerificationSchema.d.ts +3 -0
  157. package/dist/workflow/VerificationSchema.js +6 -0
  158. package/dist/workflow/VerificationSchema.js.map +1 -1
  159. package/dist/workflow/WorkflowEffectiveness.d.ts +97 -0
  160. package/dist/workflow/WorkflowEffectiveness.js +302 -0
  161. package/dist/workflow/WorkflowEffectiveness.js.map +1 -0
  162. package/dist/workflow/WorkflowEffectivenessRenderer.d.ts +2 -0
  163. package/dist/workflow/WorkflowEffectivenessRenderer.js +67 -0
  164. package/dist/workflow/WorkflowEffectivenessRenderer.js.map +1 -0
  165. package/dist/workflow/WorkflowEffectivenessScoring.d.ts +6 -0
  166. package/dist/workflow/WorkflowEffectivenessScoring.js +243 -0
  167. package/dist/workflow/WorkflowEffectivenessScoring.js.map +1 -0
  168. package/dist/workflow/gates/GateSystem.d.ts +16 -0
  169. package/dist/workflow/gates/GateSystem.js +208 -41
  170. package/dist/workflow/gates/GateSystem.js.map +1 -1
  171. package/dist/workflow/gates/MetaGovernanceGates.js +269 -8
  172. package/dist/workflow/gates/MetaGovernanceGates.js.map +1 -1
  173. package/docs/reference/cli.md +2 -1
  174. package/docs/start/agent-governance-demo.md +1 -1
  175. package/docs/workflow/ASSESSMENT_INDEX.md +326 -0
  176. package/docs/workflow/COMPARATIVE_ANALYSIS.md +422 -0
  177. package/docs/workflow/EXECUTIVE_SUMMARY.md +310 -0
  178. package/docs/workflow/IMPROVEMENT_CHECKLIST.md +518 -0
  179. package/docs/workflow/IMPROVEMENT_ROADMAP.md +707 -0
  180. package/docs/workflow/README.md +9 -1
  181. package/docs/workflow/templates/github-actions-scale-preflight.yml +4 -1
  182. package/package.json +10 -3
  183. package/scripts/workflow/run-vitest.mjs +123 -0
@@ -21,8 +21,12 @@ make verify PROFILE=default
21
21
  scale gates status --json
22
22
  scale score task --changed --json
23
23
  scale prompt optimize --input "raw coding request" --json
24
+ scale vibe-index
25
+ npm run serve
24
26
  ```
25
27
 
28
+ `npm run build` now builds the TypeScript CLI/runtime and builds the Vue 3 dashboard as the default UI. `npm run serve` prints the concrete dashboard URL, normally `http://localhost:3210/`. If the port is already occupied, either stop the stale process or set `SCALE_DASHBOARD_PORT=auto`.
29
+
26
30
  ### SCALE 2.0 引擎命令
27
31
 
28
32
  ```bash
@@ -38,7 +42,7 @@ scale orch status # 查看状态 + workspace 列表
38
42
  # Scale Cortex — 持续进化
39
43
  scale cortex evolve # 完整进化周期
40
44
  scale cortex extract # 提取 Instincts
41
- scale cortex inject --minimal # 预览 SessionStart 注入
45
+ scale cortex inject --minimal # 预览 runtime/AI OS 会消费的 SessionStart 注入
42
46
  scale cortex metrics --days 30 # 治理 ROI 报告
43
47
  ```
44
48
 
@@ -52,6 +56,10 @@ See [GATES_AND_SCORE.md](GATES_AND_SCORE.md) for gate catalog visibility, archit
52
56
 
53
57
  See [PROMPT_OPTIMIZATION.md](PROMPT_OPTIMIZATION.md) for the deterministic prompt rewrite layer used by `scale prompt optimize` and `scale define`.
54
58
 
59
+ See [../VIBE-TEMPLATES.md](../VIBE-TEMPLATES.md) for built-in vibe coding templates. The default live dashboard is the Vue 3 + Naive UI app at the server root `/`. The Vue dashboard includes Overview, Workflow, Topology, Monitoring, Token/Cost, Documents, Knowledge, and Prompt Studio pages. Prompt Studio covers templates, packs, custom prompts, copy/download/export, and the deterministic optimizer. The Knowledge page separates repo knowledge base, gbrain memory, and graph visualization instead of treating memory as the whole knowledge system.
60
+
61
+ The dashboard reads `GET /api/dashboard/capabilities` before rendering capability claims. Empty panels should have an explicit source and reason: missing model usage means no `.scale/model-usage/usage.jsonl`; missing knowledge base means no knowledge docs, `.scale/knowledge.db`, or `graphify-out/graph.json`; missing gbrain memory means no `.scale/memory/brain.sqlite` nodes; partial realtime/workflow transitions mean the HTTP serve path has not been started with EventBus/FSM/store injection.
62
+
55
63
  ## 模板与示例
56
64
 
57
65
  - 不知道一个任务该用哪些模板、模板和哪个门禁挂钩,先读 [TEMPLATE_GUIDE.md](TEMPLATE_GUIDE.md)(按等级 + 按改动类型的选择矩阵,含模板↔门禁映射)。
@@ -7,6 +7,9 @@ on:
7
7
  - main
8
8
  - master
9
9
 
10
+ permissions:
11
+ contents: read
12
+
10
13
  jobs:
11
14
  preflight:
12
15
  runs-on: ubuntu-latest
@@ -29,4 +32,4 @@ jobs:
29
32
  fi
30
33
 
31
34
  - name: Run SCALE preflight
32
- run: npx @hongmaple0820/scale-engine@latest preflight --service all --preflight-profile ci
35
+ run: npx @hongmaple0820/scale-engine@latest preflight --service all --profile ci --preflight-profile ci
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hongmaple0820/scale-engine",
3
- "version": "0.49.0",
3
+ "version": "0.50.2",
4
4
  "description": "Executable AI agent governance with workflow gates, evidence, skill/tool orchestration, and traceable HTML artifacts",
5
5
  "repository": {
6
6
  "type": "git",
@@ -33,6 +33,7 @@
33
33
  "docs/workflow",
34
34
  "examples/demo-projects/agent-governance-demo",
35
35
  "scripts/workflow/lib",
36
+ "scripts/workflow/run-vitest.mjs",
36
37
  "scripts/workflow/setup-smoke.mjs",
37
38
  "scripts/workflow/provider-rehearsal.mjs"
38
39
  ],
@@ -40,10 +41,11 @@
40
41
  "access": "public"
41
42
  },
42
43
  "scripts": {
43
- "build": "tsc",
44
+ "build": "tsc && node scripts/workflow/cleanup-dashboard-legacy.mjs && vite build --config vite.dashboard.config.ts",
44
45
  "dev": "bun --watch src/api/cli.ts",
45
- "test": "vitest run --reporter dot --pool=forks --maxWorkers=4 --minWorkers=1",
46
+ "test": "node scripts/workflow/run-vitest.mjs --timeout-ms 900000 --testTimeout=120000",
46
47
  "test:serial": "vitest run --reporter dot --pool=forks --poolOptions.forks.maxForks=1 --poolOptions.forks.minForks=1",
48
+ "coverage": "node scripts/workflow/run-vitest.mjs --timeout-ms 300000 tests/workflow/gateCatalog.test.ts tests/workflow/verificationProfile.test.ts --coverage --coverage.provider=v8 --coverage.reporter=text --coverage.include=src/workflow/GateCatalog.ts --coverage.include=src/workflow/VerificationProfile.ts --testTimeout=120000",
47
49
  "typecheck": "tsc --noEmit",
48
50
  "lint": "eslint src/**/*.ts",
49
51
  "smoke:setup": "node scripts/workflow/setup-smoke.mjs",
@@ -66,9 +68,11 @@
66
68
  "execa": "^9.3.0",
67
69
  "hono": "^4.5.0",
68
70
  "js-yaml": "^4.1.0",
71
+ "naive-ui": "^2.44.1",
69
72
  "pino": "^9.3.0",
70
73
  "pino-pretty": "^11.2.0",
71
74
  "type-is": "2.0.1",
75
+ "vue": "^3.5.38",
72
76
  "zod": "^3.23.0"
73
77
  },
74
78
  "overrides": {
@@ -85,9 +89,12 @@
85
89
  "@types/node": "^20.14.0",
86
90
  "@typescript-eslint/eslint-plugin": "^8.60.1",
87
91
  "@typescript-eslint/parser": "^8.59.3",
92
+ "@vitejs/plugin-vue": "^5.2.4",
93
+ "@vitest/coverage-v8": "2.1.9",
88
94
  "eslint": "^9.0.0",
89
95
  "tsx": "^4.21.0",
90
96
  "typescript": "^5.9.3",
97
+ "vite": "^5.4.21",
91
98
  "vitest": "^2.0.0"
92
99
  },
93
100
  "engines": {
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env node
2
+ import { spawn } from 'node:child_process'
3
+
4
+ const DEFAULT_TIMEOUT_MS = 600_000
5
+ const DEFAULT_ARGS = [
6
+ 'vitest',
7
+ 'run',
8
+ '--reporter',
9
+ 'dot',
10
+ '--pool=forks',
11
+ '--maxWorkers=4',
12
+ '--minWorkers=1',
13
+ ]
14
+
15
+ const options = parseArgs(process.argv.slice(2))
16
+ const commandArgs = [...DEFAULT_ARGS, ...options.vitestArgs]
17
+ const invocation = buildInvocation(commandArgs)
18
+ let timedOut = false
19
+ let child
20
+
21
+ child = spawn(invocation.command, invocation.args, {
22
+ cwd: process.cwd(),
23
+ env: process.env,
24
+ stdio: 'inherit',
25
+ detached: process.platform !== 'win32',
26
+ windowsHide: true,
27
+ })
28
+
29
+ const timer = setTimeout(() => {
30
+ timedOut = true
31
+ process.stderr.write(`\n[scale-engine] vitest timed out after ${options.timeoutMs}ms; terminating process tree.\n`)
32
+ terminateProcessTree(child.pid)
33
+ }, options.timeoutMs)
34
+
35
+ child.on('exit', (code, signal) => {
36
+ clearTimeout(timer)
37
+ if (timedOut) {
38
+ process.exitCode = 124
39
+ return
40
+ }
41
+ if (typeof code === 'number') {
42
+ process.exitCode = code
43
+ return
44
+ }
45
+ process.stderr.write(`[scale-engine] vitest exited via signal ${signal ?? 'unknown'}.\n`)
46
+ process.exitCode = 1
47
+ })
48
+
49
+ child.on('error', error => {
50
+ clearTimeout(timer)
51
+ process.stderr.write(`[scale-engine] failed to start vitest: ${error.message}\n`)
52
+ process.exitCode = 1
53
+ })
54
+
55
+ for (const signal of ['SIGINT', 'SIGTERM']) {
56
+ process.on(signal, () => {
57
+ clearTimeout(timer)
58
+ terminateProcessTree(child?.pid)
59
+ process.exit(130)
60
+ })
61
+ }
62
+
63
+ function parseArgs(args) {
64
+ const parsed = {
65
+ timeoutMs: Number.parseInt(process.env.SCALE_TEST_TIMEOUT_MS ?? '', 10),
66
+ vitestArgs: [],
67
+ }
68
+ for (let index = 0; index < args.length; index += 1) {
69
+ const arg = args[index]
70
+ if (arg === '--timeout-ms') {
71
+ parsed.timeoutMs = Number.parseInt(args[++index] ?? '', 10)
72
+ continue
73
+ }
74
+ if (arg.startsWith('--timeout-ms=')) {
75
+ parsed.timeoutMs = Number.parseInt(arg.slice('--timeout-ms='.length), 10)
76
+ continue
77
+ }
78
+ parsed.vitestArgs.push(arg)
79
+ }
80
+ if (!Number.isFinite(parsed.timeoutMs) || parsed.timeoutMs <= 0) {
81
+ parsed.timeoutMs = DEFAULT_TIMEOUT_MS
82
+ }
83
+ return parsed
84
+ }
85
+
86
+ function terminateProcessTree(pid) {
87
+ if (!pid) return
88
+ if (process.platform === 'win32') {
89
+ const killer = spawn('taskkill', ['/pid', String(pid), '/T', '/F'], {
90
+ stdio: 'ignore',
91
+ windowsHide: true,
92
+ })
93
+ killer.on('error', () => {
94
+ try { process.kill(pid, 'SIGKILL') } catch (error) { ignoreExitedProcess(error) }
95
+ })
96
+ return
97
+ }
98
+ try { process.kill(-pid, 'SIGTERM') } catch { try { process.kill(pid, 'SIGTERM') } catch (error) { ignoreExitedProcess(error) } }
99
+ setTimeout(() => {
100
+ try { process.kill(-pid, 'SIGKILL') } catch { try { process.kill(pid, 'SIGKILL') } catch (error) { ignoreExitedProcess(error) } }
101
+ }, 2000).unref()
102
+ }
103
+
104
+ function ignoreExitedProcess(error) {
105
+ if (process.env.SCALE_TEST_DEBUG) {
106
+ process.stderr.write(`[scale-engine] process tree cleanup notice: ${error instanceof Error ? error.message : String(error)}\n`)
107
+ }
108
+ }
109
+
110
+ function buildInvocation(args) {
111
+ const configured = process.env.SCALE_VITEST_RUNNER
112
+ if (configured) return { command: configured, args }
113
+ if (process.platform !== 'win32') return { command: 'npx', args }
114
+ return {
115
+ command: 'cmd.exe',
116
+ args: ['/d', '/s', '/c', ['npx', ...args].map(windowsQuote).join(' ')],
117
+ }
118
+ }
119
+
120
+ function windowsQuote(value) {
121
+ if (/^[A-Za-z0-9_./:=@-]+$/.test(value)) return value
122
+ return `"${value.replace(/"/g, '\\"')}"`
123
+ }