zdashboard 2.7.0 → 2.8.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.
Files changed (47) hide show
  1. package/README.md +1 -0
  2. package/dist/cli.js +571 -1018
  3. package/dist/cli.js.map +1 -1
  4. package/dist/web/assets/BatchView-BcYVTq5m.js +2 -0
  5. package/dist/web/assets/{CheckpointViewer-DBmTkC_E.js → CheckpointViewer-aVIaKKvz.js} +1 -1
  6. package/dist/web/assets/{FileIcon-tDB2mYGC.js → CodeViewer-DFzMfmdB.js} +31 -31
  7. package/dist/web/assets/DependencyGraph-NqqCB6Vt.js +1 -0
  8. package/dist/web/assets/FileIcon-Bk6QVgj6.js +1 -0
  9. package/dist/web/assets/{FilterPills-CvO0pz85.js → FilterPills-CiDfp_8h.js} +1 -1
  10. package/dist/web/assets/{ProgressBar-DIoIeYBA.js → ProgressBar-DIVNOeTV.js} +1 -1
  11. package/dist/web/assets/Sidebar-DbPvTOr4.js +1 -0
  12. package/dist/web/assets/Sidebar-prXqMrLa.js +1 -0
  13. package/dist/web/assets/SingleChangeView-e7LU1eVP.js +1 -0
  14. package/dist/web/assets/ViewHeader-1hW25T7x.js +1 -0
  15. package/dist/web/assets/Workspace-BgZLrrMa.js +1 -0
  16. package/dist/web/assets/Workspace-BjE2HRuu.js +1 -0
  17. package/dist/web/assets/Workspace-CCD9dE4r.js +2 -0
  18. package/dist/web/assets/Workspace-CthIPSy_.js +1 -0
  19. package/dist/web/assets/Workspace-DHQUpHN1.js +5 -0
  20. package/dist/web/assets/client-Cw4K1Nx3.js +1 -0
  21. package/dist/web/assets/{index-yx7txO50.js → index-Cq5UOBJN.js} +509 -509
  22. package/dist/web/assets/index-DcspTMh9.css +1 -0
  23. package/dist/web/assets/{index-CtlFZEcM.js → index-PcP6ebRP.js} +2 -2
  24. package/dist/web/assets/usePluginData-Cpm5C7LU.js +1 -0
  25. package/dist/web/assets/web-BnL7vuwB.js +2 -0
  26. package/dist/web/assets/web-CdCGfZIi.js +2 -0
  27. package/dist/web/assets/web-Ch8IK7pu.js +2 -0
  28. package/dist/web/assets/web-CjjS2dbX.js +2 -0
  29. package/dist/web/assets/web-Jaf9aZCx.js +2 -0
  30. package/dist/web/index.html +3 -3
  31. package/package.json +6 -1
  32. package/dist/web/assets/ApprovalPanel-CXQRioSw.js +0 -1
  33. package/dist/web/assets/BatchDashboard-BigPUG8g.js +0 -2
  34. package/dist/web/assets/ConfigField-BqjVlteZ.js +0 -1
  35. package/dist/web/assets/DependencyGraph-DPVneSQh.js +0 -1
  36. package/dist/web/assets/Workspace-B2nKQnQf.js +0 -1
  37. package/dist/web/assets/badge-CmIMTBDj.js +0 -1
  38. package/dist/web/assets/index-BHL7sr_b.css +0 -1
  39. package/dist/web/assets/web-BBv8hkwo.js +0 -1
  40. package/dist/web/assets/web-BNjs9lCy.js +0 -139
  41. package/dist/web/assets/web-BX2cajm6.js +0 -5
  42. package/dist/web/assets/web-BpBEbcYZ.js +0 -1
  43. package/dist/web/assets/web-CGbbhItO.js +0 -2
  44. package/dist/web/assets/web-CcDed_yx.js +0 -1
  45. package/dist/web/assets/web-DsIjKVnn.js +0 -2
  46. package/dist/web/assets/web-Eo4S0U_k.js +0 -2
  47. /package/dist/web/assets/{FileIcon-BTcE7LSd.css → CodeViewer-BTcE7LSd.css} +0 -0
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/server/detect.ts","../src/core/server.ts","../package.json","../src/core/instance.ts","../src/core/open-url.ts","../src/core/reload.ts","../src/server/spec-scan.ts","../src/server/walk.ts","../src/core/tree.ts","../src/core/worktrees.ts","../src/core/manifest.ts","../src/core/read-body.ts","../src/server/just-runner.ts","../src/plugins/just/index.ts","../src/server/api/fetch.ts","../src/server/errors.ts","../src/server/bugs.ts","../src/plugins/bugs/index.ts","../src/server/review-store.ts","../src/plugins/review/index.ts","../src/plugins/apply/scan.ts","../src/plugins/apply/parse-tasks.ts","../src/plugins/apply/index.ts","../src/plugins/design/index.ts","../src/server/design-assets.ts","../src/plugins/view/index.ts","../src/plugins/stats/index.ts","../src/server/apply-batch-store.ts","../src/plugins/apply-batch/index.ts"],"sourcesContent":["import path from 'node:path';\nimport fs from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport { access, readdir } from 'node:fs/promises';\nimport { exec } from 'node:child_process';\nimport { parseArgs as utilParseArgs } from 'node:util';\nimport { detect } from './server/detect.js';\nimport type { DetectResult } from './server/detect.js';\nimport { Context, Service } from 'cordis';\nimport { ServerService, PLUGIN_STATIC_PREFIX } from './core/server.js';\nimport { ReloadService } from './core/reload.js';\nimport { apply as treeApply } from './core/tree.js';\nimport { apply as worktreesApply } from './core/worktrees.js';\nimport { DashboardService } from './core/manifest.js';\nimport {\n findReusable,\n stopInstance,\n writeRecord,\n clearRecord,\n readPluginsConfig,\n writePluginsConfig,\n} from './core/instance.js';\nimport { openUrl } from './core/open-url.js';\nimport { apply as justApply } from './plugins/just/index.js';\nimport { apply as bugsApply } from './plugins/bugs/index.js';\nimport { apply as reviewApply } from './plugins/review/index.js';\nimport { apply as applyApply } from './plugins/apply/index.js';\nimport { apply as designApply } from './plugins/design/index.js';\nimport { apply as viewApply } from './plugins/view/index.js';\nimport { apply as statsApply } from './plugins/stats/index.js';\nimport { apply as applyBatchApply } from './plugins/apply-batch/index.js';\nimport YAML from 'yaml';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nconst DEFAULT_PORT = 4190;\n\nfunction parseArgs() {\n const args = process.argv.slice(2);\n const { values } = utilParseArgs({\n options: {\n dir: { type: 'string' },\n port: { type: 'string' },\n open: { type: 'boolean', default: false },\n page: { type: 'string' },\n restart: { type: 'boolean', default: false },\n plugins: { type: 'string' },\n },\n args,\n strict: false,\n allowPositionals: false,\n });\n return {\n dir: typeof values.dir === 'string' ? values.dir : process.cwd(),\n port: typeof values.port === 'string' ? Number(values.port) : DEFAULT_PORT,\n portExplicit: args.some(a => a === '--port' || a.startsWith('--port=')),\n open: !!values.open,\n page: typeof values.page === 'string' ? values.page : null,\n restart: !!values.restart,\n plugins: typeof values.plugins === 'string' ? values.plugins : null,\n };\n}\n\nasync function pathExists(p: string): Promise<boolean> {\n try { await access(p); return true; } catch { return false; }\n}\n\nfunction migrateLegacyBugsConfig(root: string): void {\n const zgoalConfigYaml = path.join(root, '.zgoal', 'config.yaml');\n const zdevConfigYaml = path.join(root, '.zdev', 'config.yaml');\n\n if (fs.existsSync(zgoalConfigYaml)) {\n try { fs.unlinkSync(zgoalConfigYaml); } catch { /* ignore */ }\n }\n\n if (!fs.existsSync(zdevConfigYaml)) return;\n\n const pluginsConfig = readPluginsConfig(root);\n if ('bugs' in pluginsConfig) {\n try { fs.unlinkSync(zdevConfigYaml); } catch { /* ignore */ }\n return;\n }\n\n let yamlContent: string;\n try {\n yamlContent = fs.readFileSync(zdevConfigYaml, 'utf8');\n } catch {\n return;\n }\n\n let parsed: Record<string, unknown>;\n try {\n parsed = YAML.parse(yamlContent) as Record<string, unknown>;\n } catch {\n console.warn('[zdashboard] 无效的 .zdev/config.yaml,已忽略并删除');\n try { fs.unlinkSync(zdevConfigYaml); } catch { /* ignore */ }\n return;\n }\n\n if (!parsed || typeof parsed !== 'object' || !parsed.url || !parsed.product) {\n console.warn('[zdashboard] .zdev/config.yaml 缺少必要字段,已忽略并删除');\n try { fs.unlinkSync(zdevConfigYaml); } catch { /* ignore */ }\n return;\n }\n\n const bugsConfig: Record<string, unknown> = {\n url: String(parsed.url).replace(/\\/+$/, ''),\n account: typeof parsed.account === 'string' ? parsed.account : '',\n token: typeof parsed.token === 'string' ? parsed.token : (typeof parsed.password === 'string' ? parsed.password : ''),\n product: Number(parsed.product),\n };\n\n pluginsConfig.bugs = bugsConfig;\n writePluginsConfig(root, pluginsConfig);\n\n try { fs.unlinkSync(zdevConfigYaml); } catch { /* ignore */ }\n}\n\nasync function loadExternal(ctx: Context, dir: string, root: string) {\n if (!dir) return;\n let tsxLoaded = false;\n try {\n const { register } = await import('tsx/esm/api');\n register();\n tsxLoaded = true;\n } catch {\n // tsx not available\n }\n\n try {\n const entries = await pathExists(dir) ? await readdir(dir, { withFileTypes: true }) : [];\n for (const ent of entries) {\n if (!ent.isDirectory()) continue;\n const candidates = tsxLoaded ? ['index.ts', 'index.js', 'index.mjs'] : ['index.js', 'index.mjs'];\n for (const name of candidates) {\n const p = path.join(dir, ent.name, name);\n if (await pathExists(p)) {\n try {\n const mod = await import(p);\n const plugin = mod.default ?? mod;\n if (plugin?.apply) {\n try {\n await ctx.plugin(plugin, { root });\n } catch (e) {\n console.error(`[zdashboard] failed to apply plugin ${ent.name}:`, e);\n break;\n }\n // 自动接线约定:mode === 目录名时补 external 标记与 viewerUrl\n const m = ctx.dashboard.get(ent.name);\n if (m && m.mode === ent.name) {\n const patch: Record<string, unknown> = { external: true };\n const webDir = path.join(dir, ent.name, 'web');\n if (await pathExists(path.join(webDir, 'index.html'))) {\n ctx.server.static(`${PLUGIN_STATIC_PREFIX}${ent.name}/`, webDir);\n if (!m.viewerUrl) patch.viewerUrl = `${PLUGIN_STATIC_PREFIX}${ent.name}/`;\n }\n ctx.dashboard.register({ ...m, ...patch });\n }\n }\n } catch (e) {\n console.error(`[zdashboard] failed to load plugin ${ent.name}:`, e);\n }\n break;\n }\n }\n }\n } catch {\n // ignore\n }\n}\n\nasync function main() {\n const args = parseArgs();\n const root = path.resolve(args.dir);\n\n // --- instance reuse (before creating Context) ---\n const existing = await findReusable(root);\n if (existing && !args.restart) {\n const u = `http://localhost:${existing.port}` + (args.page ? `#${args.page}` : '');\n if (args.open) openUrl(u);\n console.log(`[zdashboard] 已复用实例 ${u}(--restart 可强制重开)`);\n // 管道场景下 stdout 是异步写,显式等 flush 再 exit,避免日志被截断\n await new Promise<void>((resolve) => process.stdout.write('', () => resolve()));\n process.exit(0);\n }\n // 记录旧端口(--restart 时用于端口继承;stopInstance 会清 record)\n const oldRecord = existing && args.restart ? existing : null;\n if (oldRecord) {\n console.log(`[zdashboard] --restart:停止旧实例 pid=${oldRecord.pid}`);\n await stopInstance(oldRecord);\n }\n\n const appDir = path.resolve(__dirname, 'web');\n\n // P2: restart 且有旧记录时,起始端口用 record.port(用户显式 --port 则尊重)\n const startPort = oldRecord && !args.portExplicit ? oldRecord.port : args.port;\n\n // P0: 数据目录检测(.zdev/ 存在则优先)\n const zdevDir = path.join(root, '.zdev');\n const dataDir = fs.existsSync(zdevDir) ? '.zdev/' : '';\n\n const det = await detect(root);\n\n migrateLegacyBugsConfig(root);\n\n const ctx = new Context();\n\n // core services\n ctx.plugin(ServerService, {\n root,\n appDir,\n port: startPort,\n open: args.open,\n detect: det,\n page: args.page,\n dataDir: dataDir || undefined,\n onListen: (port: number) => writeRecord(root, port),\n });\n ctx.plugin(ReloadService, { root });\n ctx.plugin(treeApply, { root });\n ctx.plugin(worktreesApply, { root });\n ctx.plugin(DashboardService);\n\n // built-in plugins\n const plugins = [\n { name: 'stats', apply: statsApply },\n { name: 'just', apply: justApply },\n { name: 'bugs', apply: bugsApply },\n { name: 'review', apply: reviewApply },\n { name: 'apply', apply: applyApply },\n { name: 'apply-batch', apply: applyBatchApply },\n { name: 'design', apply: designApply },\n { name: 'view', apply: viewApply },\n ];\n for (const p of plugins) {\n try {\n ctx.plugin(p.apply, { root });\n } catch (e) {\n console.error(`[zdashboard] plugin ${p.name} failed:`, e);\n }\n }\n\n // external plugins\n if (args.plugins) {\n await loadExternal(ctx, path.resolve(args.plugins), root);\n }\n\n // graceful shutdown: clear .zdev record on SIGTERM / SIGINT\n const shutdown = () => {\n try { clearRecord(root); } catch {}\n process.exit(0);\n };\n process.on('SIGTERM', shutdown);\n process.on('SIGINT', shutdown);\n\n return ctx;\n}\n\nawait main().catch((e) => {\n console.error(e);\n process.exit(1);\n});\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { execFile } from 'node:child_process';\n\nexport interface DetectResult {\n hasOpenspec: boolean;\n hasDocs: boolean;\n hasJust: boolean;\n hasBugs: boolean;\n}\n\nfunction justAvailable(cwd: string): Promise<boolean> {\n return new Promise((resolve) => {\n const child = execFile('just', ['--list', '--unsupported'], { cwd, timeout: 5000 }, (err) => {\n resolve(!err);\n });\n if (child.killed) resolve(false);\n });\n}\n\nfunction hasBugsConfig(root: string): boolean {\n const dashboardPath = path.join(root, '.zdev', 'dashboard.json');\n if (!fs.existsSync(dashboardPath)) return false;\n try {\n const raw = fs.readFileSync(dashboardPath, 'utf-8');\n const rec = JSON.parse(raw) as { plugins?: { bugs?: Record<string, unknown> } };\n const bugs = rec.plugins?.bugs;\n if (bugs && typeof bugs === 'object' && bugs.url && bugs.product) return true;\n } catch { /* ignore */ }\n return false;\n}\n\nexport async function detect(root: string): Promise<DetectResult> {\n const hasOpenspec = fs.existsSync(path.join(root, 'openspec'));\n const hasDocs = fs.existsSync(path.join(root, 'docs'));\n const hasJust = await justAvailable(root);\n const hasBugs = hasBugsConfig(root);\n return { hasOpenspec, hasDocs, hasJust, hasBugs };\n}\n","import http from 'node:http';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport crypto from 'node:crypto';\nimport { fileURLToPath } from 'node:url';\nimport pkg from '../../package.json' with { type: 'json' };\nimport type { Context } from 'cordis';\nimport type { DetectResult } from '../server/detect.js';\nimport type { PluginManifest, ConfigField } from '../core/manifest.js';\nimport { Service } from 'cordis';\nimport { clearRecord, readPluginsConfig, writePluginsConfig } from './instance.js';\nimport { openUrl } from './open-url.js';\nimport { readBody } from './read-body.js';\nimport { execFile } from 'node:child_process';\n\nconst VERSION = pkg.version;\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface ServerOptions {\n root: string;\n appDir: string;\n port: number;\n open: boolean;\n page: string | null;\n detect: DetectResult;\n dataDir?: string;\n onListen?: (port: number) => void;\n}\n\ndeclare module 'cordis' {\n interface Context {\n server: ServerService;\n }\n}\n\nconst MIME: Record<string, string> = {\n '.html': 'text/html; charset=utf-8', '.htm': 'text/html; charset=utf-8',\n '.css': 'text/css; charset=utf-8', '.js': 'application/javascript; charset=utf-8',\n '.mjs': 'application/javascript; charset=utf-8', '.json': 'application/json; charset=utf-8',\n '.svg': 'image/svg+xml', '.png': 'image/png', '.ico': 'image/x-icon',\n '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.gif': 'image/gif', '.webp': 'image/webp',\n '.avif': 'image/avif',\n '.md': 'text/markdown; charset=utf-8', '.txt': 'text/plain; charset=utf-8',\n '.sql': 'text/plain; charset=utf-8', '.csv': 'text/plain; charset=utf-8',\n '.tsv': 'text/plain; charset=utf-8', '.yaml': 'text/yaml; charset=utf-8',\n '.yml': 'text/yaml; charset=utf-8', '.xml': 'application/xml; charset=utf-8',\n '.py': 'text/plain; charset=utf-8', '.ts': 'text/plain; charset=utf-8',\n '.java': 'text/plain; charset=utf-8', '.go': 'text/plain; charset=utf-8',\n '.rs': 'text/plain; charset=utf-8', '.rb': 'text/plain; charset=utf-8',\n '.php': 'text/plain; charset=utf-8', '.c': 'text/plain; charset=utf-8',\n '.cpp': 'text/plain; charset=utf-8', '.h': 'text/plain; charset=utf-8',\n '.cs': 'text/plain; charset=utf-8', '.swift': 'text/plain; charset=utf-8',\n '.kt': 'text/plain; charset=utf-8', '.scala': 'text/plain; charset=utf-8',\n '.sh': 'text/plain; charset=utf-8', '.bash': 'text/plain; charset=utf-8',\n '.zsh': 'text/plain; charset=utf-8', '.fish': 'text/plain; charset=utf-8',\n '.env': 'text/plain; charset=utf-8', '.gitignore': 'text/plain; charset=utf-8',\n '.dockerfile': 'text/plain; charset=utf-8',\n '.mp4': 'video/mp4', '.webm': 'video/webm', '.mov': 'video/quicktime',\n '.m4a': 'audio/mp4', '.aac': 'audio/aac',\n '.woff': 'font/woff', '.woff2': 'font/woff2', '.ttf': 'font/woff',\n '.map': 'application/json; charset=utf-8',\n};\n\nconst INJECT = `<script>(function(){try{var es=new EventSource('/__reload');es.addEventListener('files',function(){/* plugin 局部刷新由 useSSE 消费,此处不再整页 reload */});es.onerror=function(){/* EventSource 原生重连,静默处理 */};}catch(e){}document.addEventListener('click',function(e){var t=e.target;if(t&&t.closest){var a=t.closest('a[target]');if(a&&a.target!=='_self'){a.target='_self';}}},true);})();</script>`;\n\nexport const PLUGIN_STATIC_PREFIX = '/__plugin/';\n\nexport class ServerService extends Service {\n stopToken: string;\n private root: string;\n private appDir: string;\n private open: boolean;\n private page: string | null;\n private det: DetectResult;\n private dataDir?: string;\n private routes = new Map<string, (req: http.IncomingMessage, res: http.ServerResponse) => void>();\n private sses = new Map<string, (res: http.ServerResponse) => (() => void) | void>();\n private prefixStatic = new Map<string, string>();\n private server?: http.Server;\n private onListen?: (port: number) => void;\n\n constructor(ctx: Context, config: ServerOptions) {\n super(ctx, 'server');\n this.stopToken = crypto.randomBytes(12).toString('hex');\n this.root = config.root;\n this.appDir = config.appDir;\n this.open = config.open;\n this.page = config.page;\n this.det = config.detect;\n this.dataDir = config.dataDir;\n this.onListen = config.onListen;\n ctx.effect(() => () => this.dispose());\n\n this.refreshGitInfo();\n this.route('/__config', (_req, res) => {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify({ stopToken: this.stopToken, version: VERSION, root: this.root, ...this.gitInfo }));\n });\n\n this.route('/__stop', async (req, res) => {\n if (req.headers['x-stop-token'] !== this.stopToken) {\n res.writeHead(403);\n res.end('forbidden');\n return;\n }\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end('{\"ok\":true}');\n this.stop();\n });\n\n this.start(config.port);\n }\n\n route(path: string, handler: (req: http.IncomingMessage, res: http.ServerResponse) => void) {\n this.routes.set(path, handler);\n this.ctx.effect(() => () => this.routes.delete(path));\n }\n\n sse(path: string, onConnect: (res: http.ServerResponse) => (() => void) | void) {\n this.sses.set(path, onConnect);\n this.ctx.effect(() => () => this.sses.delete(path));\n }\n\n static(prefix: string, dir: string) {\n this.prefixStatic.set(prefix, dir);\n this.ctx.effect(() => () => this.prefixStatic.delete(prefix));\n }\n\n private pluginsConfig: Record<string, Record<string, unknown>> = {};\n\n getPluginConfig(mode: string): Record<string, unknown> {\n return this.pluginsConfig[mode] ?? {};\n }\n\n refreshPluginsConfig() {\n this.pluginsConfig = readPluginsConfig(this.root);\n }\n\n savePluginConfig(merged: Record<string, Record<string, unknown>>) {\n this.pluginsConfig = merged;\n writePluginsConfig(this.root, merged);\n }\n\n private serveFile(filePath: string, req: http.IncomingMessage, res: http.ServerResponse, injectHtml: boolean) {\n fs.stat(filePath, (err, stat) => {\n if (err) { res.writeHead(404); return res.end('Not found'); }\n const ext = path.extname(filePath).toLowerCase();\n const ct = MIME[ext] ?? 'application/octet-stream';\n\n // ---- HTTP Range support ----\n const rangeHeader = (req.headers['range'] as string | undefined);\n let range: { start: number; end: number } | null = null;\n if (rangeHeader) {\n const m = rangeHeader.match(/^bytes=(\\d+)-(\\d*)$/);\n if (m) {\n const start = Number(m[1]);\n const end = m[2] !== '' ? Number(m[2]) : stat.size - 1;\n if (!Number.isNaN(start) && !Number.isNaN(end) && start <= end && start < stat.size) {\n range = { start, end: Math.min(end, stat.size - 1) };\n }\n // malformed range → fall through to 200 full response\n }\n // unparseable range header → fall through to 200 full response\n }\n\n if (range) {\n const { start, end } = range;\n const chunkSize = end - start + 1;\n res.writeHead(206, {\n 'Content-Type': ct,\n 'Content-Length': String(chunkSize),\n 'Content-Range': `bytes ${start}-${end}/${stat.size}`,\n 'Accept-Ranges': 'bytes',\n 'Cache-Control': 'no-cache',\n });\n // stat 成功后文件仍可能在 open 前被删/换(高频增删的工作区),流错误无人接会崩进程\n const stream = fs.createReadStream(filePath, { start, end });\n stream.on('error', () => { try { res.destroy(); } catch { /* 已断 */ } });\n stream.pipe(res);\n return;\n }\n\n // Full response\n fs.readFile(filePath, (err, data) => {\n if (err) { res.writeHead(404); return res.end('Not found'); }\n let body: string | Buffer = data;\n if (injectHtml && ext === '.html') {\n const s = data.toString('utf8');\n body = Buffer.from(s.indexOf('</body>') >= 0 ? s.replace('</body>', INJECT + '</body>') : s + INJECT);\n }\n res.writeHead(200, { 'Content-Type': ct, 'Accept-Ranges': 'bytes', 'Cache-Control': 'no-cache' });\n res.end(body);\n });\n });\n }\n\n private servePrefix(url: string, req: http.IncomingMessage, res: http.ServerResponse): boolean {\n for (const [prefix, dir] of this.prefixStatic) {\n if (url.indexOf(prefix) === 0) {\n let rel = this.safeDecode(url.slice(prefix.length));\n if (!rel || rel === '/' || !path.extname(rel)) rel = path.join(rel || '', 'index.html');\n const fp = path.join(dir, rel);\n if (fp.indexOf(dir + path.sep) !== 0) { res.writeHead(403); res.end('Forbidden'); return false; }\n this.serveFile(fp, req, res, true);\n return true;\n }\n }\n return false;\n }\n\n private safeDecode(raw: string): string {\n try { return decodeURIComponent(raw); } catch { return raw; }\n }\n\n private handler = (req: http.IncomingMessage, res: http.ServerResponse) => {\n try {\n const rawUrl = req.url || '/';\n const url = rawUrl.split('?')[0];\n\n const rh = this.routes.get(url);\n if (rh) { rh(req, res); return; }\n const sh = this.sses.get(url);\n if (sh) {\n res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', Connection: 'keep-alive' });\n res.write(': connected\\n\\n');\n const cleanup = sh(res);\n req.on('close', () => { cleanup?.(); });\n return;\n }\n\n if (this.servePrefix(url, req, res)) return;\n\n if (url === '/' || url.indexOf('/__app/') === 0 || url.indexOf('/assets/') === 0) {\n let fp = this.appDir;\n if (url !== '/') fp = path.join(this.appDir, this.safeDecode(url));\n if (url.indexOf('/__app/') === 0) fp = path.join(this.appDir, url.slice(7));\n if (fp !== this.appDir && fp.indexOf(this.appDir + path.sep) !== 0) { res.writeHead(403); return res.end('Forbidden'); }\n if (url === '/') fp = path.join(this.appDir, 'index.html');\n return this.serveFile(fp, req, res, false);\n }\n\n const fp = path.join(this.root, this.safeDecode(url));\n if (fp !== this.root && fp.indexOf(this.root + path.sep) !== 0) { res.writeHead(403); return res.end('Forbidden'); }\n return this.serveFile(fp, req, res, true);\n } catch (e) {\n try { res.writeHead(400); res.end('bad request'); } catch {}\n console.error('[zdashboard] handler error', e);\n }\n };\n\n start(port: number) {\n this.server = http.createServer(this.handler);\n // 浏览器复用空闲 keep-alive 连接时若已被服务端关闭,请求会石沉大海(点击无响应)。\n // 拉长 keep-alive 使其远大于浏览器侧空闲窗口\n this.server.keepAliveTimeout = 65_000;\n this.server.headersTimeout = 66_000;\n this.server.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n console.log(`[zdashboard] port ${port} busy, trying ${port + 1}`);\n this.start(port + 1);\n } else throw err;\n });\n this.server.listen(port, '127.0.0.1', () => {\n const u = `http://localhost:${port}`;\n const target = this.page ? `${u}#${this.page}` : u;\n console.log(`[zdashboard] v${VERSION} dashboard -> ${u}`);\n console.log(`[zdashboard] project -> ${this.root}`);\n console.log(`[zdashboard] detect -> openspec:${this.det.hasOpenspec} docs:${this.det.hasDocs} just:${this.det.hasJust} bugs:${this.det.hasBugs}`);\n if (this.dataDir) console.log(`[zdashboard] data -> ${this.dataDir}`);\n if (this.open) openUrl(target);\n this.onListen?.(port);\n });\n }\n\n /** 项目 git 信息(分支/脏文件数),启动探测一次,文件变更时刷新 */\n private gitInfo: { branch?: string; dirty?: number } = {};\n\n refreshGitInfo() {\n const run = (args: string[]) => new Promise<string>((resolve) => {\n execFile('git', args, { cwd: this.root, timeout: 3000 }, (err, stdout) => resolve(err ? '' : stdout));\n });\n void (async () => {\n const [branch, status] = await Promise.all([\n run(['rev-parse', '--abbrev-ref', 'HEAD']),\n run(['status', '--porcelain']),\n ]);\n const b = branch.trim();\n this.gitInfo = b ? { branch: b, dirty: status ? status.split('\\n').filter(Boolean).length : 0 } : {};\n })();\n }\n\n stop() {\n if (this.server) { try { this.server.close(); } catch {} }\n try { clearRecord(this.root); } catch {}\n setTimeout(() => {\n try { this.ctx.root.fiber.dispose(); } catch {}\n process.exit(0);\n }, 50);\n }\n\n dispose() {\n if (this.server) { try { this.server.close(); } catch {} }\n try { clearRecord(this.root); } catch {}\n }\n}\n","{\n \"name\": \"zdashboard\",\n \"version\": \"2.7.0\",\n \"description\": \"ZCode skill dashboard platform — pluggable viewers for zdesign/zview/zreview/zgoal\",\n \"type\": \"module\",\n \"bin\": {\n \"zdashboard\": \"./dist/cli.js\"\n },\n \"files\": [\n \"dist\"\n ],\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"dev\": \"vite\",\n \"build\": \"tsup && vite build\",\n \"build:web\": \"vite build\",\n \"build:node\": \"tsup\",\n \"start\": \"node dist/cli.js\",\n \"preview\": \"vite preview\"\n },\n \"dependencies\": {\n \"@fontsource/vt323\": \"^5.3.0\",\n \"@phosphor-icons/react\": \"^2.1.10\",\n \"@radix-ui/react-dropdown-menu\": \"^2.1.24\",\n \"@radix-ui/react-scroll-area\": \"^1.2.0\",\n \"@radix-ui/react-separator\": \"^1.1.0\",\n \"@radix-ui/react-slot\": \"^1.1.0\",\n \"@radix-ui/react-tooltip\": \"^1.1.2\",\n \"@uidotdev/usehooks\": \"^2.4.0\",\n \"ansi-to-react\": \"^6.1.6\",\n \"class-variance-authority\": \"^0.7.0\",\n \"clsx\": \"^2.1.1\",\n \"cordis\": \"4.0.0-rc.8\",\n \"cosmokit\": \"^1.8.1\",\n \"date-fns\": \"^3.6.0\",\n \"filesize\": \"^11.0.0\",\n \"highlight.js\": \"^11.11.1\",\n \"katex\": \"^0.16.11\",\n \"ky\": \"^1.7.0\",\n \"lodash-es\": \"^4.17.21\",\n \"lucide-react\": \"^0.460.0\",\n \"pixelarticons\": \"^2.4.1\",\n \"react\": \"^18.3.1\",\n \"react-dom\": \"^18.3.1\",\n \"react-error-boundary\": \"^5.0.0\",\n \"react-markdown\": \"^9.0.1\",\n \"rehype-autolink-headings\": \"^7.1.0\",\n \"rehype-highlight\": \"^7.0.1\",\n \"rehype-katex\": \"^7.0.1\",\n \"rehype-raw\": \"^7.0.0\",\n \"rehype-slug\": \"^6.0.0\",\n \"remark-frontmatter\": \"^5.0.0\",\n \"remark-gfm\": \"^4.0.0\",\n \"remark-math\": \"^6.0.0\",\n \"sonner\": \"^1.5.0\",\n \"tailwind-merge\": \"^2.5.4\",\n \"tsx\": \"^4.7.0\",\n \"use-debounce\": \"^10.0.0\",\n \"yaml\": \"^2.9.0\"\n },\n \"devDependencies\": {\n \"@tailwindcss/typography\": \"^0.5.20\",\n \"@testing-library/jest-dom\": \"^7.0.1\",\n \"@testing-library/react\": \"^16.3.2\",\n \"@types/lodash-es\": \"^4.17.12\",\n \"@types/node\": \"^22.9.0\",\n \"@types/react\": \"^18.3.12\",\n \"@types/react-dom\": \"^18.3.1\",\n \"@vitejs/plugin-react\": \"^4.7.0\",\n \"autoprefixer\": \"^10.4.20\",\n \"jsdom\": \"^30.0.1\",\n \"postcss\": \"^8.4.49\",\n \"tailwindcss\": \"^3.4.14\",\n \"tailwindcss-animate\": \"^1.0.7\",\n \"tsup\": \"^8.3.5\",\n \"typescript\": \"^5.6.3\",\n \"vite\": \"^5.4.10\",\n \"vitest\": \"^1.6.0\"\n },\n \"pnpm\": {\n \"onlyBuiltDependencies\": [\n \"esbuild\"\n ]\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nexport interface InstanceRecord {\n pid: number;\n port: number;\n root: string;\n startedAt: string;\n plugins?: Record<string, Record<string, unknown>>;\n}\n\nexport const RECORD_FILE = '.zdev/dashboard.json';\nexport const VERIFY_TIMEOUT_MS = 1500;\nexport const STOP_POLL_MS = 2000;\nexport const STOP_POLL_INTERVAL_MS = 100;\nexport const STOP_FINAL_WAIT_MS = 100;\n\nfunction recordPath(root: string): string {\n return path.join(root, RECORD_FILE);\n}\n\nexport function readRecord(root: string): InstanceRecord | null {\n try {\n const fp = recordPath(root);\n const raw = fs.readFileSync(fp, 'utf-8');\n const rec = JSON.parse(raw) as Partial<InstanceRecord>;\n if (\n typeof rec.pid === 'number' &&\n typeof rec.port === 'number' &&\n typeof rec.root === 'string' &&\n typeof rec.startedAt === 'string'\n ) {\n return rec as InstanceRecord;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nexport function writeRecord(root: string, port: number): void {\n fs.mkdirSync(path.dirname(recordPath(root)), { recursive: true });\n const rec: InstanceRecord = {\n pid: process.pid,\n port,\n root,\n startedAt: new Date().toISOString(),\n };\n fs.writeFileSync(recordPath(root), JSON.stringify(rec, null, 2) + '\\n');\n}\n\nexport function readPluginsConfig(root: string): Record<string, Record<string, unknown>> {\n try {\n const rec = readRecord(root);\n if (rec?.plugins && typeof rec.plugins === 'object') {\n return rec.plugins as Record<string, Record<string, unknown>>;\n }\n } catch { /* ignore */ }\n return {};\n}\n\nexport function writePluginsConfig(root: string, plugins: Record<string, Record<string, unknown>>): void {\n const fp = recordPath(root);\n let rec: InstanceRecord;\n try {\n const raw = fs.readFileSync(fp, 'utf-8');\n rec = JSON.parse(raw) as InstanceRecord;\n } catch {\n rec = { pid: process.pid, port: 0, root, startedAt: new Date().toISOString() };\n }\n rec.plugins = plugins;\n const tmp = fp + '.tmp';\n fs.writeFileSync(tmp, JSON.stringify(rec, null, 2) + '\\n');\n fs.renameSync(tmp, fp);\n}\n\nexport function clearRecord(root: string): void {\n try {\n // 属主校验:记录若已指向别的实例(并发双启落败者),不得误删胜者记录\n const rec = readRecord(root);\n if (rec && rec.pid !== process.pid) return;\n fs.unlinkSync(recordPath(root));\n } catch {\n // best-effort\n }\n}\n\nexport function isAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code === 'ESRCH') return false;\n // EPERM or other → process exists, we just can't signal it\n return true;\n }\n}\n\nasync function fetchWithTimeout(url: string): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), VERIFY_TIMEOUT_MS);\n try {\n return await fetch(url, { signal: controller.signal });\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function verifyRoot(port: number, root: string): Promise<boolean> {\n try {\n const res = await fetchWithTimeout(`http://127.0.0.1:${port}/__config`);\n if (res.status !== 200) return false;\n const body = await res.json();\n if (typeof body.root !== 'string') return false;\n return body.root === root;\n } catch {\n return false;\n }\n}\n\nexport async function findReusable(root: string): Promise<InstanceRecord | null> {\n const rec = readRecord(root);\n if (!rec) return null;\n if (!isAlive(rec.pid)) return null;\n if (!(await verifyRoot(rec.port, root))) return null;\n return rec;\n}\n\nexport async function stopInstance(record: InstanceRecord): Promise<void> {\n try {\n process.kill(record.pid, 'SIGTERM');\n } catch {\n return;\n }\n\n const deadline = Date.now() + STOP_POLL_MS;\n while (Date.now() < deadline) {\n if (!isAlive(record.pid)) return;\n await new Promise((r) => setTimeout(r, STOP_POLL_INTERVAL_MS));\n }\n\n // still alive → SIGKILL\n try {\n process.kill(record.pid, 'SIGKILL');\n } catch {\n // ignore\n }\n await new Promise((r) => setTimeout(r, STOP_FINAL_WAIT_MS));\n}\n","import { exec, execFile } from 'node:child_process';\n\n/** 跨平台打开浏览器(macOS open / Windows start / Linux xdg-open) */\nexport function openUrl(url: string): void {\n const cmd =\n process.platform === 'darwin' ? 'open' :\n process.platform === 'win32' ? 'start' :\n 'xdg-open';\n // win32 `start` 是 shell 内建命令,只能走 shell;其他平台直接用 execFile\n if (process.platform === 'win32') {\n exec(`start \"\" \"${url}\"`);\n } else {\n execFile(cmd, [url]);\n }\n}\n","import fs from 'node:fs';\nimport http from 'node:http';\nimport { Service } from 'cordis';\nimport type { Context } from 'cordis';\n\ndeclare module 'cordis' {\n interface Context {\n reload: ReloadService;\n }\n}\n\nconst WATCH_DEBOUNCE_MS = 300;\n\nexport class ReloadService extends Service {\n static inject = ['server'];\n private clients = new Set<http.ServerResponse>();\n private watcher?: fs.FSWatcher;\n private timer?: NodeJS.Timeout;\n\n constructor(ctx: Context, config: { root: string }) {\n super(ctx, 'reload');\n this.ctx.effect(() => () => this.dispose());\n\n this.ctx.server.sse('/__reload', (res) => {\n this.clients.add(res);\n return () => this.clients.delete(res);\n });\n\n try {\n this.watcher = fs.watch(config.root, { recursive: true }, (eventType, filename) => {\n if (filename && /^(?:\\.git|node_modules|dist|\\.pnpm)(?:[/\\\\]|$)/.test(filename)) return;\n if (filename && /\\.(?:swp|tmp)$|~$|^\\.DS_Store$|^Thumbs\\.db$/i.test(filename)) return;\n if (this.timer) clearTimeout(this.timer);\n this.timer = setTimeout(() => {\n this.ctx.server.refreshGitInfo();\n this.broadcast('reload');\n this.broadcast('files');\n this.timer = undefined;\n }, WATCH_DEBOUNCE_MS);\n });\n } catch {\n // watch unavailable - static only\n }\n }\n\n broadcast(ev: string, data: unknown = '') {\n const payload = `event: ${ev}\\ndata: ${JSON.stringify(data == null ? '' : data)}\\n\\n`;\n for (const c of this.clients) {\n try { c.write(payload); } catch {}\n }\n }\n\n dispose() {\n if (this.watcher) { try { this.watcher.close(); } catch {} }\n if (this.timer) { clearTimeout(this.timer); }\n for (const c of this.clients) { try { c.end(); } catch {} }\n this.clients.clear();\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { walkDir } from './walk.js';\n\nexport type NodeKind = 'file' | 'dir' | 'log';\nexport interface TreeNode {\n name: string;\n kind: NodeKind;\n path?: string;\n defaultCollapsed?: boolean;\n children?: TreeNode[];\n}\n\nfunction buildTree(paths: string[], defaultExpandDepth = 2): TreeNode[] {\n const root: TreeNode[] = [];\n const map = new Map<string, TreeNode>();\n\n for (const p of paths) {\n const parts = p.split('/');\n let current = '';\n let parent = root;\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n current = current ? `${current}/${part}` : part;\n const isLast = i === parts.length - 1;\n const depth = i;\n\n if (!map.has(current)) {\n const isDir = !isLast;\n const collapsed = isDir && typeof defaultExpandDepth === 'number' && depth > defaultExpandDepth;\n const node: TreeNode = {\n name: part,\n kind: isLast ? 'file' : 'dir',\n ...(collapsed ? { defaultCollapsed: true } : {}),\n ...(isLast ? { path: p } : { children: [] }),\n };\n map.set(current, node);\n parent.push(node);\n }\n\n if (!isLast) {\n parent = map.get(current)!.children!;\n }\n }\n }\n\n const sortNodes = (nodes: TreeNode[]) => {\n nodes.sort((a, b) => (a.kind === b.kind ? a.name.localeCompare(b.name) : a.kind === 'dir' ? -1 : 1));\n for (const n of nodes) {\n if (n.children) sortNodes(n.children);\n }\n };\n\n sortNodes(root);\n return root;\n}\n\nexport interface ScanTreeOptions {\n hiddenDirs?: string[];\n showHidden?: boolean;\n defaultExpandDepth?: number;\n}\n\n/** 方案模式树形扫描:openspec 感知 + docs 聚合 + 其他兜底 */\nexport function scanTree(root: string, hasOpenspec: boolean, hasDocs: boolean, opts?: ScanTreeOptions): TreeNode[] {\n const tree: TreeNode[] = [];\n const defaultExpandDepth = typeof opts?.defaultExpandDepth === 'number' ? opts.defaultExpandDepth : 2;\n if (hasOpenspec && fs.existsSync(path.join(root, 'openspec', 'changes'))) {\n const changesDir = path.join(root, 'openspec', 'changes');\n const active: TreeNode[] = [];\n const archived: TreeNode[] = [];\n for (const ent of fs.readdirSync(changesDir, { withFileTypes: true })) {\n if (!ent.isDirectory() || ent.name.startsWith('.') || ent.name === 'archive') continue;\n const relBase = `openspec/changes/${ent.name}`;\n const paths: string[] = [];\n walkDir(path.join(changesDir, ent.name), { maxDepth: 4, showHidden: opts?.showHidden, onFile: (_, rel) => paths.push(rel ? `${relBase}/${rel}` : relBase) });\n const children = buildTree(paths, defaultExpandDepth).map((n) => ({ ...n, path: n.path ? `${relBase}/${n.path}` : undefined }));\n active.push({ name: ent.name, kind: 'dir', children });\n }\n active.sort((a, b) => a.name.localeCompare(b.name));\n const archiveDir = path.join(changesDir, 'archive');\n if (fs.existsSync(archiveDir)) {\n for (const ent of fs.readdirSync(archiveDir, { withFileTypes: true })) {\n if (!ent.isDirectory() || ent.name.startsWith('.')) continue;\n const relBase = `openspec/changes/archive/${ent.name}`;\n const paths: string[] = [];\n walkDir(path.join(archiveDir, ent.name), { maxDepth: 4, showHidden: opts?.showHidden, onFile: (_, rel) => paths.push(rel ? `${relBase}/${rel}` : relBase) });\n const children = buildTree(paths, defaultExpandDepth).map((n) => ({ ...n, path: n.path ? `${relBase}/${n.path}` : undefined }));\n archived.push({ name: ent.name, kind: 'dir', children });\n }\n archived.sort((a, b) => b.name.localeCompare(a.name)); // 日期前缀倒序\n }\n if (active.length) tree.push({ name: `changes (${active.length})`, kind: 'dir', children: active });\n if (archived.length) tree.push({ name: `archive (${archived.length})`, kind: 'dir', defaultCollapsed: true, children: archived });\n const specsDir = path.join(root, 'openspec', 'specs');\n if (fs.existsSync(specsDir)) {\n const paths: string[] = [];\n walkDir(specsDir, { maxDepth: 4, showHidden: opts?.showHidden, onFile: (_, rel) => paths.push(`openspec/specs/${rel}`) });\n const specs = buildTree(paths, defaultExpandDepth).map((n) => ({ ...n, path: n.path ? `openspec/specs/${n.path}` : undefined }));\n if (specs.length) tree.push({ name: 'specs', kind: 'dir', children: specs });\n }\n }\n if (hasDocs && fs.existsSync(path.join(root, 'docs'))) {\n const paths: string[] = [];\n walkDir(path.join(root, 'docs'), { maxDepth: 4, showHidden: opts?.showHidden, onFile: (_, rel) => paths.push(`docs/${rel}`) });\n const docs = buildTree(paths, defaultExpandDepth).map((n) => ({ ...n, path: n.path ? `docs/${n.path}` : undefined }));\n if (docs.length) tree.push({ name: 'docs', kind: 'dir', children: docs });\n }\n const skip = new Set(['openspec', 'docs', 'node_modules', '.git', 'dist', 'playground', '.zreview']);\n if (Array.isArray(opts?.hiddenDirs)) {\n for (const d of opts.hiddenDirs) skip.add(d);\n }\n // \"其他\"只收根目录的 md 文档(README/CLAUDE 等);构建配置(pom.xml/justfile 等)不收——对\"方案+日志\"定位是噪音\n const etc: TreeNode[] = [];\n try {\n for (const ent of fs.readdirSync(root, { withFileTypes: true })) {\n if (!opts?.showHidden && ent.name.startsWith('.')) continue;\n if (skip.has(ent.name)) continue;\n const ext = path.extname(ent.name).toLowerCase();\n if (ent.isFile() && (ext === '.md' || ext === '.markdown')) etc.push({ name: ent.name, kind: 'file', path: ent.name });\n }\n } catch (e) { console.error('[zdashboard] scan root etc failed:', e); }\n etc.sort((a, b) => a.name.localeCompare(b.name));\n if (etc.length) tree.push({ name: `other (${etc.length})`, kind: 'dir', children: etc });\n return tree;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nexport interface WalkOptions {\n skip?: Set<string>;\n maxDepth?: number;\n showHidden?: boolean;\n onFile?: (abs: string, rel: string) => void;\n onDir?: (abs: string, rel: string) => void;\n}\n\nexport function walkDir(root: string, opts: WalkOptions = {}): void {\n const { skip = new Set(), maxDepth, showHidden, onFile, onDir } = opts;\n\n function walk(dir: string, rel: string, depth: number) {\n if (typeof maxDepth === 'number' && depth > maxDepth) return;\n let ents: fs.Dirent[];\n try { ents = fs.readdirSync(dir, { withFileTypes: true }); } catch { return; }\n for (const ent of ents) {\n if (!showHidden && ent.name.startsWith('.')) continue;\n if (skip.has(ent.name)) continue;\n const abs = path.join(dir, ent.name);\n const r = rel ? `${rel}/${ent.name}` : ent.name;\n if (ent.isDirectory()) {\n onDir?.(abs, r);\n walk(abs, r, depth + 1);\n } else if (onFile) {\n onFile(abs, r);\n }\n }\n }\n\n walk(root, '', 0);\n}\n","import type { Context } from 'cordis';\nimport { scanTree } from '../server/spec-scan.js';\nimport { detect } from '../server/detect.js';\nimport type { DetectResult } from '../server/detect.js';\n\nexport const apply = {\n inject: ['server', 'dashboard'] as const,\n apply(ctx: Context, config: { root: string }) {\n let cached: { p: Promise<DetectResult>; v?: DetectResult } | null = null;\n const getDet = async (): Promise<DetectResult> => {\n if (cached?.v) return cached.v;\n if (!cached) cached = { p: detect(config.root).catch(() => ({ hasOpenspec: false, hasDocs: false, hasJust: false, hasBugs: false } as DetectResult)) };\n const d = await cached.p;\n cached.v = d;\n return d;\n };\n\n const server = ctx.server;\n if (server?.route) {\n server.route('/__files', async (_req, res) => {\n try {\n const d = await getDet();\n const viewCfg = ctx.dashboard.getConfig('view') as { hiddenDirs?: string[]; defaultExpandDepth?: number; showHidden?: boolean } | undefined;\n const tree = scanTree(config.root, d.hasOpenspec, d.hasDocs, {\n hiddenDirs: Array.isArray(viewCfg?.hiddenDirs) ? viewCfg.hiddenDirs : undefined,\n defaultExpandDepth: typeof viewCfg?.defaultExpandDepth === 'number' ? viewCfg.defaultExpandDepth : undefined,\n showHidden: typeof viewCfg?.showHidden === 'boolean' ? viewCfg.showHidden : undefined,\n });\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify({ tree, ...d }));\n } catch {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify({ tree: [], hasOpenspec: false, hasDocs: false, hasJust: false, hasBugs: false }));\n }\n });\n }\n },\n};\n","import { execFile } from 'node:child_process';\nimport type { Context } from 'cordis';\n\nexport interface WorktreeInfo {\n path: string;\n name: string;\n branch: string;\n head: string;\n dirty: boolean;\n}\n\nconst GIT_TIMEOUT_MS = 5_000;\nconst ZWORKTREE_SEGMENT = '.zworktree/';\n\nfunction runGit(args: string[], cwd: string): Promise<string> {\n return new Promise((resolve) => {\n execFile('git', args, { cwd, timeout: GIT_TIMEOUT_MS }, (err, stdout) => {\n if (err) return resolve('');\n resolve(stdout);\n });\n });\n}\n\nexport async function listWorktrees(root: string): Promise<WorktreeInfo[]> {\n const raw = await runGit(['worktree', 'list', '--porcelain'], root);\n if (!raw) return [];\n\n const entries: WorktreeInfo[] = [];\n const lines = raw.split('\\n');\n let current: Partial<WorktreeInfo> = {};\n\n for (const line of lines) {\n const m = line.match(/^(worktree|HEAD|branch|detached)\\s+(.+)$/);\n if (!m) continue;\n const [, key, val] = m;\n if (key === 'worktree') {\n if (current.path && current.path.includes(ZWORKTREE_SEGMENT)) {\n entries.push({\n path: current.path,\n name: current.path.split(ZWORKTREE_SEGMENT).pop() ?? '',\n branch: current.branch ?? '',\n head: current.head ?? '',\n dirty: false,\n });\n }\n current = { path: val, head: '', branch: '' };\n } else if (key === 'HEAD') {\n current.head = val;\n } else if (key === 'branch') {\n current.branch = val.replace(/^refs\\/heads\\//, '');\n }\n }\n\n // flush last entry\n if (current.path && current.path.includes(ZWORKTREE_SEGMENT)) {\n entries.push({\n path: current.path,\n name: current.path.split(ZWORKTREE_SEGMENT).pop() ?? '',\n branch: current.branch ?? '',\n head: current.head ?? '',\n dirty: false,\n });\n }\n\n // dirty detection: git status --porcelain 非空即 dirty(失败默认 false)\n await Promise.all(\n entries.map(async (entry) => {\n try {\n const statusOut = await runGit(['status', '--porcelain'], entry.path);\n entry.dirty = statusOut.trim().length > 0;\n } catch {\n entry.dirty = false;\n }\n })\n );\n\n return entries;\n}\n\nexport const apply = {\n inject: ['server'] as const,\n apply(ctx: Context, config: { root: string }) {\n const server = ctx.server;\n if (!server?.route) return;\n\n server.route('/__worktrees', async (_req, res) => {\n try {\n const entries = await listWorktrees(config.root);\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(entries));\n } catch {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify([]));\n }\n });\n },\n};\n","import { Service } from 'cordis';\nimport type { Context } from 'cordis';\nimport { readBody } from './read-body.js';\n\ndeclare module 'cordis' {\n interface Context {\n dashboard: DashboardService;\n }\n}\n\nexport interface PluginManifest {\n mode: string;\n label: string;\n icon: string;\n description?: string;\n viewerUrl?: string; // 同源 URL,前端 iframe 渲染\n external?: boolean;\n config?: Record<string, ConfigField>;\n}\n\nexport interface ConfigField {\n type: 'string' | 'text' | 'number' | 'boolean' | 'string[]' | 'select' | 'multiselect';\n label: string;\n default?: unknown;\n placeholder?: string;\n options?: { value: string; label: string }[];\n min?: number;\n max?: number;\n}\n\nexport class DashboardService extends Service {\n static inject = ['server', 'reload'];\n private plugins = new Map<string, PluginManifest>();\n private reloadRef: any;\n\n constructor(ctx: Context) {\n super(ctx, 'dashboard');\n this.ctx.effect(() => () => this.plugins.clear());\n this.reloadRef = ctx.reload;\n\n this.ctx.server.route('/__plugins', (_req, res) => {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify({ plugins: Array.from(this.plugins.values()) }));\n });\n\n this.ctx.server.route('/__plugins/config', async (req, res) => {\n const out: Record<string, Record<string, unknown>> = {};\n if (req.method === 'GET') {\n for (const m of this.plugins.values()) {\n const stored = this.ctx.server.getPluginConfig(m.mode);\n const schema = m.config ?? {};\n const merged: Record<string, unknown> = {};\n for (const [key, field] of Object.entries(schema)) {\n merged[key] = key in stored ? stored[key] : (field as ConfigField).default ?? '';\n }\n if (Object.keys(merged).length) out[m.mode] = merged;\n }\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(out));\n return;\n }\n if (req.method === 'POST') {\n if (req.headers['x-stop-token'] !== this.ctx.server.stopToken) {\n res.writeHead(403);\n res.end('forbidden');\n return;\n }\n try {\n const body = JSON.parse(await readBody(req));\n const merged = {};\n for (const mode of Object.keys(body)) {\n merged[mode] = body[mode] ?? {};\n }\n this.ctx.server.savePluginConfig(merged);\n for (const mode of Object.keys(body)) {\n try { this.reloadRef.broadcast('config', { plugin: mode }); } catch { /* ignore */ }\n }\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end('{\"ok\":true}');\n } catch (e) {\n console.error('[config] POST error', e);\n res.writeHead(400);\n res.end('{\"error\":\"bad request\"}');\n }\n return;\n }\n res.writeHead(405);\n res.end('{\"error\":\"method not allowed\"}');\n });\n }\n\n register(manifest: PluginManifest) {\n this.plugins.set(manifest.mode, manifest);\n this.ctx.effect(() => () => this.plugins.delete(manifest.mode));\n }\n\n list() {\n return Array.from(this.plugins.values());\n }\n\n get(mode: string): PluginManifest | undefined {\n return this.plugins.get(mode);\n }\n\n getConfig(mode: string): Record<string, unknown> {\n return this.ctx.server.getPluginConfig(mode);\n }\n}\n","import http from 'node:http';\n\n/**\n * Read the full body of an IncomingMessage.\n * Listens for 'error' to prevent a hanging promise when the client aborts mid-stream.\n */\nexport async function readBody(req: http.IncomingMessage): Promise<string> {\n return new Promise((resolve) => {\n let data = '';\n req.on('data', (chunk: string | Buffer) => { data += chunk; });\n req.on('end', () => resolve(data));\n req.on('error', () => resolve('')); // client abort → settle with empty string\n });\n}\n","import { spawn, execFile, type ChildProcess } from 'node:child_process';\n\nexport interface Recipe { name: string; description: string; }\nexport type TaskStatus = 'running' | 'exited';\nexport interface TaskInfo { recipe: string; state: TaskStatus; code: number | null; startedAt: number; signal?: string }\n\nexport type JustEvent =\n | { type: 'log'; recipe: string; text: string }\n | { type: 'clear'; recipe: string }\n | { type: 'state'; recipe: string; state: TaskStatus; code: number | null; startedAt?: number; signal?: string };\n\ninterface Task {\n recipe: string;\n child: ChildProcess | null;\n state: TaskStatus;\n code: number | null;\n signal?: string;\n startedAt: number;\n buffer: string[];\n pending: string; // 行缓冲:块缓冲输出会在行中间断开,攒到 \\n 才切行\n}\n\nconst MAX_BUFFER = 1000;\n\n/** 多任务并发 runner:每个 recipe 独立进程/日志/状态,同名 start 即重启,互不影响 */\nexport class JustRunner {\n private cwd: string;\n private tasks = new Map<string, Task>();\n private clients = new Set<(ev: JustEvent) => void>();\n private recipesCache: Recipe[] | null = null;\n\n constructor(cwd: string) { this.cwd = cwd; }\n\n recipes(): Promise<Recipe[]> {\n if (this.recipesCache) return Promise.resolve(this.recipesCache);\n return new Promise((resolve) => {\n execFile('just', ['--list', '--unsorted'], { cwd: this.cwd, maxBuffer: 1 << 20, timeout: 8000 }, (err, stdout) => {\n if (err) { resolve([]); return; }\n const out: Recipe[] = [];\n const seen = new Set<string>();\n for (const line of stdout.split(/\\r?\\n/).slice(1)) { // 跳过 \"Available recipes:\"\n const trimmed = line.trim();\n if (!trimmed) continue;\n const hashIdx = trimmed.indexOf('#');\n const sig = (hashIdx >= 0 ? trimmed.slice(0, hashIdx) : trimmed).trim();\n if (!sig) continue;\n const name = sig.split(/\\s+/)[0]; // \"hello msg=...\" -> \"hello\"\n if (seen.has(name)) continue;\n seen.add(name);\n out.push({ name, description: hashIdx >= 0 ? trimmed.slice(hashIdx + 1).trim() : '' });\n }\n this.recipesCache = out;\n resolve(out);\n });\n });\n }\n\n subscribe(fn: (ev: JustEvent) => void): () => void {\n this.clients.add(fn);\n // 连上即重放:全部任务的日志与状态\n for (const t of this.tasks.values()) {\n for (const text of t.buffer) fn({ type: 'log', recipe: t.recipe, text });\n fn({ type: 'state', recipe: t.recipe, state: t.state, code: t.code, startedAt: t.startedAt });\n }\n return () => this.clients.delete(fn);\n }\n\n private emit(ev: JustEvent) { for (const fn of this.clients) fn(ev); }\n\n list(): TaskInfo[] {\n return Array.from(this.tasks.values(), (t) => ({ recipe: t.recipe, state: t.state, code: t.code, startedAt: t.startedAt }));\n }\n\n /** 启动 recipe:同名先停旧进程(重启语义),不影响其他任务;调用方须先用 recipes() 校验名字 */\n start(recipe: string) {\n this.killOne(recipe);\n const task: Task = { recipe, child: null, state: 'running', code: null, startedAt: Date.now(), buffer: [], pending: '' };\n this.tasks.set(recipe, task);\n this.emit({ type: 'clear', recipe }); // 广播清屏:同步清掉该任务上一轮残留日志\n this.emit({ type: 'state', recipe, state: 'running', code: null, startedAt: task.startedAt });\n const child = spawn('just', [recipe], {\n cwd: this.cwd,\n shell: true,\n env: {\n ...process.env,\n FORCE_COLOR: '1', // node 生态(chalk 等)\n // maven 检测非 tty 会关颜色;经 MAVEN_OPTS 强制开(保留用户已有值)\n MAVEN_OPTS: `${process.env.MAVEN_OPTS ?? ''} -Dstyle.color=always`.trim(),\n CI: '',\n },\n });\n task.child = child;\n // 身份守卫:同名重启后旧进程的迟到输出/退出不得污染新任务(闭包 task 是旧对象时静默丢弃)\n const isStale = () => this.tasks.get(recipe) !== task;\n const push = (d: Buffer) => {\n if (isStale()) return;\n task.pending += d.toString();\n let idx: number;\n while ((idx = task.pending.indexOf('\\n')) >= 0) {\n const line = task.pending.slice(0, idx + 1);\n task.pending = task.pending.slice(idx + 1);\n this.pushLine(task, line);\n }\n // 无 \\n 的尾巴留在 pending,等下个 chunk(块缓冲输出会在行中断开,不能当独立行)\n };\n child.stdout?.on('data', push);\n child.stderr?.on('data', push);\n child.on('error', (err) => { this.pushLine(task, `[zdashboard] spawn error: ${err.message}\\n`); });\n child.on('exit', (code, signal) => {\n if (task.pending && !isStale()) { this.pushLine(task, task.pending + '\\n'); } // flush 末尾无换行的残留\n task.pending = '';\n task.child = null;\n task.state = 'exited';\n task.code = code ?? 0;\n task.signal = signal ?? undefined; // 用户主动 stop 时 code=null+SIGTERM,与成功退出区分\n if (isStale()) return; // 迟到的旧进程退出,不打扰新任务状态\n this.emit({ type: 'state', recipe, state: 'exited', code: task.code, startedAt: task.startedAt, signal: task.signal });\n });\n }\n\n private pushLine(task: Task, line: string) {\n task.buffer.push(line);\n if (task.buffer.length > MAX_BUFFER) task.buffer.shift();\n this.emit({ type: 'log', recipe: task.recipe, text: line });\n }\n\n /** 停单个任务;不传 recipe 停全部 */\n stop(recipe?: string) {\n if (recipe === undefined) { for (const t of this.tasks.values()) this.killOne(t.recipe); }\n else this.killOne(recipe);\n }\n\n restart(recipe: string) {\n if (this.tasks.has(recipe)) this.start(recipe);\n }\n\n /** 清空某任务的日志缓冲并广播(真源清除,重连重放不会复活) */\n clear(recipe: string) {\n const task = this.tasks.get(recipe);\n if (!task) return;\n task.buffer = [];\n task.pending = '';\n this.emit({ type: 'clear', recipe });\n }\n\n private killOne(recipe: string) {\n const task = this.tasks.get(recipe);\n const child = task?.child;\n if (child?.pid) {\n try {\n if (process.platform === 'win32') spawn('taskkill', ['/PID', String(child.pid), '/T', '/F']);\n else child.kill('SIGTERM');\n } catch { /* 已退出 */ }\n }\n if (task) { task.child = null; }\n }\n}\n","import type { Context } from 'cordis';\nimport http from 'node:http';\nimport { JustRunner } from '../../server/just-runner.js';\nimport { readBody } from '../../core/read-body.js';\n\nexport const apply = {\n inject: ['server', 'dashboard'] as const,\n apply(ctx: Context, config: { root: string }) {\n const root = config.root;\n\n ctx.inject(['server'], () => {\n if (!ctx.server?.route) return;\n\n const runner = new JustRunner(root);\n ctx.effect(() => () => runner.stop());\n\n ctx.dashboard.register({ mode: 'just', label: 'Just Runner', icon: '📜', description: 'Just 多任务并发执行与日志' });\n\n ctx.server.route('/__just/recipes', async (_req, res) => {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n try {\n const recipes = await runner.recipes();\n res.end(JSON.stringify(recipes));\n } catch {\n res.end(JSON.stringify([]));\n }\n });\n\n ctx.server.sse('/__just/logs', (res) => {\n const unsub = runner.subscribe((ev) => {\n res.write(`data: ${JSON.stringify(ev)}\\n\\n`);\n });\n return unsub;\n });\n\n /** start/restart 须带合法 recipe(同名 start 即重启,不影响其他任务);stop 可带单个 recipe 或省略(停全部) */\n const handleAction = async (req: http.IncomingMessage, res: http.ServerResponse, act: 'start' | 'stop' | 'restart' | 'clear') => {\n if (req.headers['x-stop-token'] !== ctx.server.stopToken) { res.writeHead(403); res.end('forbidden'); return; }\n const body = await readBody(req);\n let recipe: string | undefined;\n try { recipe = JSON.parse(body || '{}').recipe; } catch { /* ignore */ }\n if (act === 'clear') {\n if (recipe) runner.clear(recipe);\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end('{\"ok\":true}');\n return;\n }\n if (act !== 'stop') {\n if (!recipe) { res.writeHead(400); res.end('{\"error\":\"no recipe\"}'); return; }\n const recipes = await runner.recipes();\n if (!recipes.some((r) => r.name === recipe)) { res.writeHead(403); res.end('{\"error\":\"unknown recipe\"}'); return; }\n runner.start(recipe);\n } else {\n runner.stop(recipe || undefined);\n }\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify(runner.list()));\n };\n\n const routeAction = (name: 'start' | 'stop' | 'restart' | 'clear') => {\n ctx.server.route(`/__just/${name}`, (req, res) => {\n handleAction(req, res, name).catch(() => {\n if (!res.headersSent) { res.writeHead(500); res.end('{\"error\":\"internal\"}'); }\n });\n });\n };\n routeAction('start');\n routeAction('stop');\n routeAction('restart');\n routeAction('clear');\n });\n },\n};\n\n","import ky from 'ky';\nimport { HttpError, NetworkError } from '../errors.js';\n\nexport async function fetchJson(url: string, init?: RequestInit): Promise<Record<string, unknown>> {\n try {\n const res = await ky(url, { ...init, timeout: 8000, retry: 2 });\n return await res.json() as Record<string, unknown>;\n } catch (e) {\n if (e instanceof HttpError) throw e;\n if (e instanceof Error && e.name === 'TimeoutError') {\n throw new NetworkError(`请求超时: ${url}`);\n }\n if (e instanceof Error && e.name === 'HTTPError') {\n throw new HttpError((e as Error & { status?: number }).status ?? 500, e.message);\n }\n throw new NetworkError(`请求失败: ${url}`, e);\n }\n}\n","export class HttpError extends Error {\n constructor(\n public status: number,\n message: string,\n public body?: unknown,\n ) {\n super(message);\n this.name = 'HttpError';\n }\n}\n\nexport class NetworkError extends Error {\n constructor(message: string, public cause?: unknown) {\n super(message);\n this.name = 'NetworkError';\n }\n}\n\nexport function isHttpError(e: unknown): e is HttpError {\n return e instanceof HttpError;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fetchJson } from './api/fetch.js';\n\nexport interface ZenBug {\n id: number;\n title: string;\n severity: number | string;\n pri: number | string;\n status: string;\n assignedTo: string;\n openedBy?: string;\n /** 指派给 config.account 的本人 */\n mine: boolean;\n}\n\nexport type BugsResult =\n | { ok: true; url: string; total: number; bugs: ZenBug[] }\n | { ok: false; error: string };\n\nlet tokenCache: { key: string; token: string; at: number } | null = null;\n\nasync function getToken(cfg: { url: string; account: string; token?: string }): Promise<string> {\n if (cfg.token) return cfg.token;\n const key = `${cfg.url}|${cfg.account}`;\n if (tokenCache && tokenCache.key === key && Date.now() - tokenCache.at < 10 * 60_000) return tokenCache.token;\n const json = await fetchJson(`${cfg.url}/api.php/v1/tokens`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ account: cfg.account, password: '' }),\n });\n const token = typeof json.token === 'string' ? json.token : '';\n if (!token) throw new Error('token 获取失败:检查 account / password');\n tokenCache = { key, token, at: Date.now() };\n return token;\n}\n\nfunction normBug(b: Record<string, unknown>, account: string): ZenBug {\n const assigned = b.assignedTo;\n const assignedTo =\n typeof assigned === 'string'\n ? assigned\n : assigned && typeof assigned === 'object' && 'realname' in (assigned as Record<string, unknown>)\n ? String((assigned as Record<string, unknown>).realname ?? '')\n : '';\n const assignedAccount =\n typeof assigned === 'string'\n ? assigned\n : assigned && typeof assigned === 'object'\n ? String((assigned as Record<string, unknown>).account ?? '')\n : '';\n const mine = !!account && (assignedAccount === account || assignedTo === account);\n return {\n id: Number(b.id),\n title: String(b.title ?? ''),\n severity: (b.severity as number | string) ?? 4,\n pri: (b.pri as number | string) ?? 3,\n status: String(b.status ?? ''),\n assignedTo,\n openedBy: typeof b.openedBy === 'string' ? b.openedBy : undefined,\n mine,\n };\n}\n\nexport async function fetchBugs(config: { url: string; account: string; token: string; product: number }): Promise<BugsResult> {\n if (!config.url || !config.product) {\n return { ok: false, error: '配置无效:请设置服务器 URL 和产品 ID' };\n }\n try {\n const token = await getToken(config);\n const json = await fetchJson(\n `${config.url}/api.php/v1/products/${config.product}/bugs?page=1&limit=100`,\n { headers: { Token: token } },\n );\n const raw = Array.isArray(json.bugs) ? (json.bugs as Record<string, unknown>[]) : [];\n return { ok: true, url: config.url, total: Number(json.total ?? raw.length), bugs: raw.map((b) => normBug(b, config.account)) };\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return { ok: false, error: `禅道请求失败(${msg})——检查 url / 凭据 / 是否开启 RESTful API v1` };\n }\n}\n","import type { Context } from 'cordis';\nimport { fetchBugs } from '../../server/bugs.js';\n\nexport const apply = {\n inject: ['server', 'dashboard'] as const,\n apply(ctx: Context, config: { root: string }) {\n const root = config.root;\n\n ctx.inject(['server'], () => {\n if (!ctx.server?.route) return;\n\n ctx.dashboard.register({\n mode: 'bugs',\n label: '禅道 Bugs',\n icon: '🎯',\n description: '只读 bug 列表',\n config: {\n url: { type: 'string', label: '服务器 URL', default: '' },\n account: { type: 'string', label: '账号', default: '' },\n token: { type: 'string', label: 'Token', default: '' },\n product: { type: 'number', label: '产品 ID', default: 0 },\n },\n });\n\n ctx.server.route('/__bugs', async (_req, res) => {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n try {\n const bugConfig = ctx.dashboard.getConfig('bugs') as { url?: string; account?: string; token?: string; product?: number } | undefined;\n const result = await fetchBugs({\n url: String(bugConfig?.url ?? ''),\n account: String(bugConfig?.account ?? ''),\n token: String(bugConfig?.token ?? ''),\n product: Number(bugConfig?.product ?? 0),\n });\n res.end(JSON.stringify(result));\n } catch (e) {\n res.end(JSON.stringify({ ok: false, error: e instanceof Error ? e.message : 'unknown error' }));\n }\n });\n\n });\n },\n};\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport YAML from 'yaml';\n\nexport type ItemState = 'open' | 'answered' | 'accepted' | 'dismissed';\nexport type ReviewStatus = 'draft' | 'reviewing' | 'passed' | 'rejected';\nexport type ItemType = 'question' | 'conflict' | 'gap' | 'ambiguity' | 'decomposition';\nexport type Priority = 'high' | 'medium' | 'low';\nexport type Severity = 'high' | 'medium' | 'low';\n\nexport interface ReviewItem {\n id: string;\n type: ItemType;\n severity?: Severity;\n state: ItemState;\n title: string;\n question?: string;\n answer?: string;\n doc?: string;\n context?: string;\n sources?: Array<{ doc: string; quote: string }>;\n priority?: Priority;\n children?: ReviewItem[];\n}\n\nexport interface ReviewDocument {\n id: string;\n path: string;\n title: string;\n type: string;\n parsedAt: string;\n}\n\nexport interface ReviewCodebase {\n id: string;\n path: string;\n title: string;\n type: string;\n summary: string;\n}\n\nexport interface ReviewDiagram {\n path: string;\n title: string;\n type: string;\n}\n\nexport interface ReviewData {\n status: ReviewStatus;\n summary: string;\n documents: ReviewDocument[];\n codebases: ReviewCodebase[];\n diagrams: ReviewDiagram[];\n items: ReviewItem[];\n}\n\nconst REVIEW_DIR = '.zreview';\nconst REVIEW_FILE = path.join(REVIEW_DIR, 'review.yaml');\nconst DOCS_DIR = path.join(REVIEW_DIR, 'docs');\nconst DIAGRAMS_DIR = path.join(REVIEW_DIR, 'diagrams');\n\nexport class ReviewStore {\n private root: string;\n private onChange?: () => void;\n\n constructor(root: string, onChange?: () => void) {\n this.root = root;\n this.onChange = onChange;\n }\n\n exists(): boolean { return fs.existsSync(path.join(this.root, REVIEW_FILE)); }\n\n read(): ReviewData {\n const fullPath = path.join(this.root, REVIEW_FILE);\n if (!fs.existsSync(fullPath)) {\n return { status: 'draft', summary: '', documents: [], codebases: [], diagrams: [], items: [] };\n }\n try {\n const parsed = YAML.parse(fs.readFileSync(fullPath, 'utf8')) as ReviewData;\n if (!parsed || !Array.isArray(parsed.items)) {\n return { status: 'draft', summary: parsed?.summary ?? '', documents: parsed?.documents ?? [], codebases: parsed?.codebases ?? [], diagrams: parsed?.diagrams ?? [], items: [] };\n }\n return {\n status: parsed.status ?? 'draft',\n summary: parsed.summary ?? '',\n documents: parsed.documents ?? [],\n codebases: parsed.codebases ?? [],\n diagrams: parsed.diagrams ?? [],\n items: parsed.items,\n };\n } catch {\n return { status: 'draft', summary: '', documents: [], codebases: [], diagrams: [], items: [] };\n }\n }\n\n private write(data: ReviewData) {\n fs.mkdirSync(path.join(this.root, REVIEW_DIR), { recursive: true });\n fs.writeFileSync(path.join(this.root, REVIEW_FILE), YAML.stringify(data), 'utf8');\n this.onChange?.();\n }\n\n updateItem(id: string, patch: { answer?: string; state?: ItemState; priority?: Priority; title?: string }): ReviewData {\n const data = this.read();\n const item = this.findItem(data.items, id);\n if (!item) throw new Error(`item ${id} not found`);\n if (patch.answer !== undefined) item.answer = patch.answer;\n if (patch.state !== undefined) item.state = patch.state;\n if (patch.priority !== undefined) item.priority = patch.priority;\n if (patch.title !== undefined) item.title = patch.title;\n if (patch.state === 'answered' && !patch.answer && !item.answer) item.answer = '';\n this.write(data);\n return data;\n }\n\n addChild(parentId: string, title: string, priority: Priority = 'medium'): ReviewData {\n const data = this.read();\n const parent = this.findItem(data.items, parentId);\n if (!parent) throw new Error(`parent ${parentId} not found`);\n if (!parent.children) parent.children = [];\n const newId = `${parentId}-${parent.children.length + 1}`;\n parent.children.push({\n id: newId,\n type: 'decomposition',\n state: 'open',\n title,\n priority,\n });\n this.write(data);\n return data;\n }\n\n removeItem(id: string): ReviewData {\n const data = this.read();\n const removed = this.removeItemFromList(data.items, id);\n if (!removed) throw new Error(`item ${id} not found`);\n this.write(data);\n return data;\n }\n\n setStatus(status: ReviewStatus): ReviewData {\n const data = this.read();\n if (status === 'passed' && this.hasOpenItems(data.items)) {\n throw new Error('存在未处理的评审项(open),不能通过');\n }\n data.status = status;\n this.write(data);\n return data;\n }\n\n listDocs(): string[] {\n const docsDir = path.join(this.root, DOCS_DIR);\n if (!fs.existsSync(docsDir)) return [];\n try {\n return fs.readdirSync(docsDir)\n .filter((f) => /\\.(md|markdown|txt)$/i.test(f))\n .sort();\n } catch { return []; }\n }\n\n readDoc(name: string): string {\n const fullPath = path.join(this.root, DOCS_DIR, name);\n if (!fs.existsSync(fullPath)) throw new Error(`doc ${name} not found`);\n return fs.readFileSync(fullPath, 'utf8');\n }\n\n listDiagrams(): string[] {\n const dir = path.join(this.root, DIAGRAMS_DIR);\n if (!fs.existsSync(dir)) return [];\n try {\n return fs.readdirSync(dir)\n .filter((f) => /\\.html$/i.test(f))\n .sort();\n } catch { return []; }\n }\n\n readDiagram(name: string): string {\n const fullPath = path.join(this.root, DIAGRAMS_DIR, name);\n if (!fs.existsSync(fullPath)) throw new Error(`diagram ${name} not found`);\n return fs.readFileSync(fullPath, 'utf8');\n }\n\n private findItem(items: ReviewItem[], id: string): ReviewItem | null {\n for (const item of items) {\n if (item.id === id) return item;\n if (item.children) {\n const found = this.findItem(item.children, id);\n if (found) return found;\n }\n }\n return null;\n }\n\n private removeItemFromList(items: ReviewItem[], id: string): boolean {\n for (let i = 0; i < items.length; i++) {\n if (items[i].id === id) {\n items.splice(i, 1);\n return true;\n }\n if (items[i].children && this.removeItemFromList(items[i].children!, id)) {\n return true;\n }\n }\n return false;\n }\n\n private hasOpenItems(items: ReviewItem[]): boolean {\n for (const item of items) {\n if (item.state === 'open') return true;\n if (item.children && this.hasOpenItems(item.children)) return true;\n }\n return false;\n }\n}\n","import type { Context } from 'cordis';\nimport { ReviewStore, type ItemState, type ReviewStatus, type Priority } from '../../server/review-store.js';\nimport { readBody } from '../../core/read-body.js';\n\nexport const apply = {\n inject: ['server', 'dashboard', 'reload'] as const,\n apply(ctx: Context, config: { root: string }) {\n const root = config.root;\n\n ctx.inject(['server'], () => {\n if (!ctx.server?.route) return;\n\n ctx.dashboard.register({ mode: 'review', label: '文档评审', icon: '✅', description: '多文档需求评审与拆解 · zreview' });\n\n const reviewStore = new ReviewStore(root, () => {\n ctx.reload.broadcast('files');\n });\n\n ctx.server.route('/__review', async (_req, res) => {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(reviewStore.read()));\n });\n\n ctx.server.route('/__review/item', async (req, res) => {\n if (req.headers['x-stop-token'] !== ctx.server.stopToken) { res.writeHead(403); res.end('forbidden'); return; }\n try {\n const body = JSON.parse(await readBody(req) || '{}');\n const data = reviewStore.updateItem(body.id, {\n answer: body.answer,\n state: body.state as ItemState | undefined,\n priority: body.priority as Priority | undefined,\n title: body.title,\n });\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(data));\n } catch (e) {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: e instanceof Error ? e.message : 'unknown error' }));\n }\n });\n\n ctx.server.route('/__review/item/add-child', async (req, res) => {\n if (req.headers['x-stop-token'] !== ctx.server.stopToken) { res.writeHead(403); res.end('forbidden'); return; }\n try {\n const body = JSON.parse(await readBody(req) || '{}');\n const data = reviewStore.addChild(body.parentId, body.title, body.priority);\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(data));\n } catch (e) {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: e instanceof Error ? e.message : 'unknown error' }));\n }\n });\n\n ctx.server.route('/__review/item/remove', async (req, res) => {\n if (req.headers['x-stop-token'] !== ctx.server.stopToken) { res.writeHead(403); res.end('forbidden'); return; }\n try {\n const body = JSON.parse(await readBody(req) || '{}');\n const data = reviewStore.removeItem(body.id);\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(data));\n } catch (e) {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: e instanceof Error ? e.message : 'unknown error' }));\n }\n });\n\n ctx.server.route('/__review/status', async (req, res) => {\n if (req.headers['x-stop-token'] !== ctx.server.stopToken) { res.writeHead(403); res.end('forbidden'); return; }\n try {\n const body = JSON.parse(await readBody(req) || '{}');\n const data = reviewStore.setStatus(body.status as ReviewStatus);\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(data));\n } catch (e) {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: e instanceof Error ? e.message : 'unknown error' }));\n }\n });\n\n ctx.server.route('/__docs', async (_req, res) => {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(reviewStore.listDocs()));\n });\n\n ctx.server.route('/__docs/:name', async (req, res) => {\n try {\n const name = (req as any).params?.name;\n if (!name) throw new Error('missing doc name');\n const content = reviewStore.readDoc(name);\n res.writeHead(200, { 'Content-Type': 'text/markdown; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(content);\n } catch (e) {\n res.writeHead(404, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: e instanceof Error ? e.message : 'not found' }));\n }\n });\n });\n },\n};\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { countTasks } from './parse-tasks.js';\n\nexport interface ChangeSummary {\n name: string;\n path: string;\n total: number;\n done: number;\n hasProposal: boolean;\n hasDesign: boolean;\n inWorktree: boolean;\n}\n\nexport interface ChangeDetail extends ChangeSummary {\n proposal?: string;\n design?: string;\n tasks: string;\n dependsOn: string[];\n hasTestStrategy: boolean;\n}\n\nfunction readText(p: string): string {\n try { return fs.readFileSync(p, 'utf8'); } catch { return ''; }\n}\n\nfunction worktreeDir(root: string, name: string): string {\n return path.join(root, '.zworktree', name);\n}\n\nfunction changeDir(root: string, name: string): string {\n return path.join(root, 'openspec', 'changes', name);\n}\n\nfunction parseDependsOn(proposal: string): string[] {\n const deps: string[] = [];\n // 提取 \"## 依赖\" 节:紧跟该标题的列表行\n const m = proposal.match(/^##\\s+依赖\\s*\\n([\\s\\S]*?)(?:\\n#{1,6}\\s|\\n---\\s*\\n|$)/i);\n if (!m) return deps;\n for (const line of m[1].split('\\n')) {\n // 仅收集零缩进的一级条目(/^-/),子级列表(缩进 -)不算依赖名\n if (!/^-\\s+/.test(line)) continue;\n const name = line.replace(/^-\\s+/, '').trim();\n if (name) deps.push(name);\n }\n return deps;\n}\n\nexport function scanApplyChanges(root: string): ChangeSummary[] {\n const changesDir = path.join(root, 'openspec', 'changes');\n if (!fs.existsSync(changesDir)) return [];\n const out: ChangeSummary[] = [];\n for (const ent of fs.readdirSync(changesDir, { withFileTypes: true })) {\n if (!ent.isDirectory() || ent.name.startsWith('.') || ent.name === 'archive') continue;\n const wt = worktreeDir(root, ent.name);\n const tasks = readText(path.join(wt, 'openspec', 'changes', ent.name, 'tasks.md'));\n if (!tasks) {\n const fallback = readText(path.join(changesDir, ent.name, 'tasks.md'));\n if (fallback) {\n const { total, done } = countTasks(fallback);\n const wtChange = path.join(wt, 'openspec', 'changes', ent.name);\n const mainChange = path.join(changesDir, ent.name);\n out.push({\n name: ent.name,\n path: `openspec/changes/${ent.name}`,\n total,\n done,\n hasProposal: fs.existsSync(path.join(wtChange, 'proposal.md')) || fs.existsSync(path.join(mainChange, 'proposal.md')),\n hasDesign: fs.existsSync(path.join(wtChange, 'design.md')) || fs.existsSync(path.join(mainChange, 'design.md')),\n // worktree 目录存在即算执行中(tasks.md 可能尚未落盘)\n inWorktree: fs.existsSync(wtChange),\n });\n }\n } else {\n const { total, done } = countTasks(tasks);\n const wtChange = path.join(wt, 'openspec', 'changes', ent.name);\n const mainChange = path.join(changesDir, ent.name);\n out.push({\n name: ent.name,\n path: `openspec/changes/${ent.name}`,\n total,\n done,\n // 任一侧存在即算(详情读取是 worktree 优先、主目录兜底,列表标记保持一致)\n hasProposal: fs.existsSync(path.join(wtChange, 'proposal.md')) || fs.existsSync(path.join(mainChange, 'proposal.md')),\n hasDesign: fs.existsSync(path.join(wtChange, 'design.md')) || fs.existsSync(path.join(mainChange, 'design.md')),\n inWorktree: true,\n });\n }\n }\n out.sort((a, b) => a.name.localeCompare(b.name));\n return out;\n}\n\nexport function readApplyChange(root: string, name: string): ChangeDetail {\n const wt = worktreeDir(root, name);\n const mainChangeDir = changeDir(root, name);\n\n // 优先 worktree 内;回退主目录\n const proposalFrom = fs.existsSync(path.join(wt, 'openspec', 'changes', name, 'proposal.md'))\n ? path.join(wt, 'openspec', 'changes', name, 'proposal.md')\n : path.join(mainChangeDir, 'proposal.md');\n const designFrom = fs.existsSync(path.join(wt, 'openspec', 'changes', name, 'design.md'))\n ? path.join(wt, 'openspec', 'changes', name, 'design.md')\n : path.join(mainChangeDir, 'design.md');\n const tasksFrom = fs.existsSync(path.join(wt, 'openspec', 'changes', name, 'tasks.md'))\n ? path.join(wt, 'openspec', 'changes', name, 'tasks.md')\n : path.join(mainChangeDir, 'tasks.md');\n\n const proposal = readText(proposalFrom);\n const design = readText(designFrom);\n const tasks = readText(tasksFrom);\n const { total, done } = countTasks(tasks);\n const inWorktree = fs.existsSync(path.join(wt, 'openspec', 'changes', name));\n const dependsOn = parseDependsOn(proposal);\n const hasTestStrategy = /^##\\s+测试策略\\s*$/m.test(design);\n\n return {\n name,\n path: `openspec/changes/${name}`,\n total,\n done,\n hasProposal: !!proposal,\n hasDesign: !!design,\n inWorktree,\n proposal,\n design,\n tasks,\n dependsOn,\n hasTestStrategy,\n };\n}\n","const TASK_RE = /^\\s*-\\s*\\[([ xX])\\]\\s*(.*)$/;\n\nexport interface ParsedTask {\n text: string\n checked: boolean\n}\n\nexport function parseTasks(md: string): ParsedTask[] {\n return md\n .split('\\n')\n .filter((l) => TASK_RE.test(l))\n .map((l) => {\n const m = l.match(TASK_RE);\n return { text: (m?.[2] ?? l).trim(), checked: m?.[1] !== ' ' };\n });\n}\n\nexport function countTasks(md: string): { total: number; done: number } {\n const tasks = parseTasks(md);\n return { total: tasks.length, done: tasks.filter((t) => t.checked).length };\n}\n","import type { Context } from 'cordis';\nimport { scanApplyChanges, readApplyChange } from './scan.js';\n\nexport const apply = {\n inject: ['server', 'dashboard'] as const,\n apply(ctx: Context, config: { root: string }) {\n const root = config.root;\n\n ctx.inject(['server'], () => {\n if (!ctx.server?.route) return;\n\n ctx.dashboard.register({ mode: 'apply', label: '执行进度', icon: '⚙️', description: 'OpenSpec change 任务进度' });\n\n ctx.server.route('/__apply', async (_req, res) => {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(scanApplyChanges(root)));\n });\n\n ctx.server.route('/__apply/change', async (req, res) => {\n const url = new URL(req.url || '', 'http://x');\n const name = url.searchParams.get('name');\n if (!name) {\n res.writeHead(400);\n res.end(JSON.stringify({ error: 'missing name' }));\n return;\n }\n if (name.includes('..') || name.includes('/') || name.includes('\\\\')) {\n res.writeHead(400);\n res.end(JSON.stringify({ error: 'invalid name' }));\n return;\n }\n try {\n const data = readApplyChange(root, name);\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(data));\n } catch (e) {\n res.writeHead(400);\n res.end(JSON.stringify({ error: e instanceof Error ? e.message : 'unknown error' }));\n }\n });\n });\n },\n};\n","import type { Context } from 'cordis';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport { scanAssets, type ScanResult, type AssetType } from '../../server/design-assets.js';\n\nconst ASSET_KEYS: AssetType[] = ['page','component','icon','token','md','video','audio','pdf','font'];\n\nfunction mergeScanResults(a: ScanResult, b: ScanResult): ScanResult {\n const out: ScanResult = {} as ScanResult;\n for (const k of ASSET_KEYS) {\n out[k] = [...a[k], ...b[k]];\n }\n return out;\n}\n\nexport const apply = {\n inject: ['server', 'dashboard'] as const,\n apply(ctx: Context, config: { root: string }) {\n const root = config.root;\n\n ctx.inject(['server'], () => {\n if (!ctx.server?.route) return;\n\n ctx.dashboard.register({\n mode: 'design',\n label: '设计资产',\n icon: '🎨',\n description: '页面/组件/图标/Token 分类预览',\n config: {\n folders: { type: 'string[]', label: '扫描文件夹', default: [] },\n },\n });\n\n ctx.server.route('/__design/assets', async (_req, res) => {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n const designConfig = ctx.dashboard.getConfig('design') as { folders?: string[] } | undefined;\n const folders = Array.isArray(designConfig?.folders) ? designConfig.folders : [];\n\n if (folders.length === 0) {\n res.end(JSON.stringify(scanAssets(root)));\n return;\n }\n\n let merged: ScanResult = {} as ScanResult;\n for (const k of ASSET_KEYS) merged[k] = [];\n\n for (const folder of folders) {\n const folderPath = path.resolve(root, folder);\n if (fs.existsSync(folderPath) && fs.statSync(folderPath).isDirectory()) {\n const result = scanAssets(folderPath);\n merged = mergeScanResults(merged, result);\n }\n }\n\n res.end(JSON.stringify(merged));\n });\n });\n },\n};\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { walkDir } from './walk.js';\n\nexport type AssetType = 'page' | 'component' | 'icon' | 'token' | 'md' | 'video' | 'audio' | 'pdf' | 'font';\n\nconst PAGE_EXTS = ['.html', '.htm'];\nconst ICON_EXTS = ['.svg', '.png', '.ico', '.jpg', '.jpeg', '.gif', '.webp'];\nconst VIDEO_EXTS = ['.mp4', '.webm', '.mov', '.ogg', '.ogv'];\nconst AUDIO_EXTS = ['.mp3', '.wav', '.flac', '.aac', '.m4a'];\nconst CODE_EXTS = ['.js', '.mjs', '.cjs', '.mts', '.cts', '.ts', '.tsx', '.jsx', '.css', '.json', '.txt', '.xml', '.yml', '.yaml', '.sh', '.md'];\nconst FONT_EXTS = ['.woff', '.woff2', '.ttf', '.otf'];\nconst TOKEN_RE = /token|theme|design|color|palette|typograph/i;\n\nexport function categorize(rel: string, ext: string): AssetType | null {\n if (rel.indexOf('components/') === 0) return 'component';\n if (VIDEO_EXTS.includes(ext)) return 'video';\n if (AUDIO_EXTS.includes(ext)) return 'audio';\n if (ext === '.pdf') return 'pdf';\n if (ext === '.md') return 'md';\n if (FONT_EXTS.includes(ext)) return 'font';\n if (ICON_EXTS.includes(ext)) return 'icon';\n if (PAGE_EXTS.includes(ext)) return 'page';\n if (CODE_EXTS.includes(ext)) {\n if (TOKEN_RE.test(rel) && (ext === '.css' || ext === '.json')) return 'token';\n return null;\n }\n return null;\n}\n\nexport interface AssetFile { path: string; name: string; ext: string; type: AssetType; }\nexport type ScanResult = Record<AssetType, AssetFile[]>;\n\nexport function scanAssets(root: string, subDir = ''): ScanResult {\n const out: ScanResult = {} as ScanResult;\n const keys: AssetType[] = ['page','component','icon','token','md','video','audio','pdf','font'];\n for (const k of keys) out[k] = [];\n const SKIP = new Set(['node_modules', '.git', 'dist', 'build', 'coverage', '.next', '.cache']);\n const scanRoot = subDir ? path.join(root, subDir) : root;\n walkDir(scanRoot, { skip: SKIP, onFile: (abs, rel) => {\n const ext = path.extname(abs).toLowerCase();\n const t = categorize(rel, ext);\n if (t) out[t].push({ path: rel, name: path.basename(abs), ext, type: t });\n }});\n return out;\n}\n","import type { Context } from 'cordis';\n\nexport const apply = {\n inject: ['dashboard'] as const,\n apply(ctx: Context) {\n ctx.dashboard.register({\n mode: 'view',\n label: '项目浏览',\n icon: '👁️',\n description: 'openspec / docs / 文档预览',\n config: {\n hiddenDirs: { type: 'string[]', label: '隐藏目录', default: ['.git', 'node_modules', 'dist', 'build'] },\n defaultExpandDepth: { type: 'number', label: '默认展开深度', default: 2 },\n showHidden: { type: 'boolean', label: '显示隐藏文件', default: false },\n },\n });\n },\n};\n","import type { Context } from 'cordis';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { walkDir } from '../../server/walk.js';\n\ninterface Stats {\n root: string;\n files: number;\n dirs: number;\n totalSize: number;\n byExt: { ext: string; count: number }[];\n markdown: number;\n openspec: { active: number; archived: number };\n hasJust: boolean;\n}\n\nconst SKIP_DIRS = new Set(['node_modules', '.git', 'dist', 'build', '.next', '.cache']);\n\nfunction scan(root: string): Stats {\n const stats: Stats = {\n root: path.basename(root),\n files: 0,\n dirs: 0,\n totalSize: 0,\n byExt: [],\n markdown: 0,\n openspec: { active: 0, archived: 0 },\n hasJust: fs.existsSync(path.join(root, 'justfile')),\n };\n const extMap = new Map<string, number>();\n\n const walk = (dir: string) => {\n walkDir(dir, { skip: SKIP_DIRS, onDir: () => { stats.dirs++; }, onFile: (abs) => {\n stats.files++;\n try { stats.totalSize += fs.statSync(abs).size; } catch {}\n const ext = path.extname(abs).toLowerCase() || '(无扩展名)';\n extMap.set(ext, (extMap.get(ext) ?? 0) + 1);\n if (ext === '.md' || ext === '.markdown') stats.markdown++;\n }});\n };\n walk(root);\n\n const changesDir = path.join(root, 'openspec', 'changes');\n if (fs.existsSync(changesDir)) {\n for (const ent of fs.readdirSync(changesDir, { withFileTypes: true })) {\n if (!ent.isDirectory() || ent.name.startsWith('.')) continue;\n if (ent.name === 'archive') {\n try {\n stats.openspec.archived = fs.readdirSync(path.join(changesDir, 'archive'), { withFileTypes: true })\n .filter(e => e.isDirectory() && !e.name.startsWith('.')).length;\n } catch { /* ignore */ }\n } else stats.openspec.active++;\n }\n }\n\n stats.byExt = Array.from(extMap.entries())\n .map(([ext, count]) => ({ ext, count }))\n .sort((a, b) => b.count - a.count)\n .slice(0, 10);\n return stats;\n}\n\nexport const apply = {\n inject: ['server', 'dashboard'] as const,\n apply(ctx: Context, config: { root: string }) {\n ctx.inject(['server', 'dashboard'], () => {\n const server = (ctx as any).server;\n const dashboard = (ctx as any).dashboard;\n if (!server?.route || !dashboard?.register) return;\n\n dashboard.register({\n mode: 'stats',\n label: '项目统计',\n icon: '📊',\n description: '项目文件统计 · 扫描生成',\n });\n\n server.route('/__stats/data', (_req: unknown, res: import('node:http').ServerResponse) => {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(scan(config.root)));\n });\n });\n },\n};\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nexport interface BatchChange {\n name: string;\n path: string;\n status: 'pending' | 'running' | 'completed' | 'failed' | 'parked' | 'skipped';\n priority: number;\n risk: 'low' | 'medium' | 'high' | 'unknown';\n dependencies: string[];\n estimatedDuration: number;\n batchIndex: number;\n checkpoint?: {\n currentTaskIndex: number;\n totalTasks: number;\n completedTasks: number;\n currentTask: string;\n };\n error?: string;\n retryCount: number;\n startedAt?: string;\n completedAt?: string;\n}\n\nexport interface BatchLog {\n timestamp: string;\n level: 'info' | 'warn' | 'error' | 'success';\n message: string;\n changeName?: string;\n}\n\nexport interface BatchConflict {\n changeA: string;\n changeB: string;\n files: string[];\n resolution: 'serialize' | 'merge' | 'ignore';\n}\n\nexport interface BatchState {\n version: string;\n status: 'idle' | 'analyzing' | 'pending-approval' | 'running' | 'paused' | 'completed' | 'failed';\n changes: BatchChange[];\n batches: {\n index: number;\n changeNames: string[];\n status: 'pending' | 'running' | 'completed' | 'failed';\n startedAt?: string;\n completedAt?: string;\n }[];\n currentBatchIndex: number;\n parallelism: number;\n logs: BatchLog[];\n conflicts: BatchConflict[];\n createdAt: string;\n updatedAt: string;\n}\n\nconst DEFAULT_STATE: Omit<BatchState, 'createdAt' | 'updatedAt'> = {\n version: '1',\n status: 'idle',\n changes: [],\n batches: [],\n currentBatchIndex: -1,\n parallelism: 2,\n logs: [],\n conflicts: [],\n};\n\nexport class ApplyBatchStore {\n private root: string;\n private statePath: string;\n private state: BatchState;\n private listeners: Set<() => void> = new Set();\n\n constructor(root: string, onBroadcast?: () => void) {\n this.root = root;\n this.statePath = path.join(root, '.zapply', 'batch-state.json');\n this.state = this.load();\n }\n\n private load(): BatchState {\n try {\n if (fs.existsSync(this.statePath)) {\n return JSON.parse(fs.readFileSync(this.statePath, 'utf8'));\n }\n } catch { /* ignore */ }\n return { ...DEFAULT_STATE, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString() };\n }\n\n private save(): void {\n this.state.updatedAt = new Date().toISOString();\n fs.mkdirSync(path.dirname(this.statePath), { recursive: true });\n fs.writeFileSync(this.statePath, JSON.stringify(this.state, null, 2));\n this.listeners.forEach(fn => fn());\n }\n\n subscribe(fn: () => void) {\n this.listeners.add(fn);\n return () => this.listeners.delete(fn);\n }\n\n read(): BatchState {\n return this.state;\n }\n\n updateStatus(status: BatchState['status']) {\n this.state.status = status;\n this.save();\n }\n\n updateChanges(changes: BatchChange[]) {\n this.state.changes = changes;\n this.save();\n }\n\n updateBatches(batches: BatchState['batches']) {\n this.state.batches = batches;\n this.save();\n }\n\n updateParallelism(parallelism: number) {\n this.state.parallelism = Math.max(1, Math.min(8, parallelism));\n this.save();\n }\n\n addLog(log: BatchLog) {\n this.state.logs.push(log);\n // Keep only last 1000 logs\n if (this.state.logs.length > 1000) {\n this.state.logs = this.state.logs.slice(-1000);\n }\n this.save();\n }\n\n updateConflicts(conflicts: BatchConflict[]) {\n this.state.conflicts = conflicts;\n this.save();\n }\n\n updateChange(name: string, patch: Partial<BatchChange>) {\n const idx = this.state.changes.findIndex(c => c.name === name);\n if (idx !== -1) {\n this.state.changes[idx] = { ...this.state.changes[idx], ...patch };\n this.save();\n }\n }\n\n updateCheckpoint(name: string, checkpoint: BatchChange['checkpoint']) {\n const idx = this.state.changes.findIndex(c => c.name === name);\n if (idx !== -1) {\n this.state.changes[idx].checkpoint = checkpoint;\n this.save();\n }\n }\n\n reset() {\n this.state = { ...DEFAULT_STATE, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString() };\n this.save();\n }\n}\n","import type { Context } from 'cordis';\nimport { ApplyBatchStore } from '../../server/apply-batch-store.js';\n\nexport const apply = {\n inject: ['server', 'dashboard', 'reload'] as const,\n apply(ctx: Context, config: { root: string }) {\n const root = config.root;\n\n ctx.inject(['server'], () => {\n if (!ctx.server?.route) return;\n\n ctx.dashboard.register({\n mode: 'apply-batch',\n label: '批量执行',\n icon: '⚡',\n description: 'zapply 批量并行执行驾驶舱',\n });\n\n const store = new ApplyBatchStore(root, () => {\n try { ctx.reload.broadcast('files'); } catch { /* ignore */ }\n });\n\n ctx.server.route('/__apply-batch', async (_req, res) => {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(store.read()));\n });\n\n ctx.server.route('/__apply-batch/status', async (req, res) => {\n try {\n const body = JSON.parse(await readBody(req) || '{}');\n store.updateStatus(body.status);\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(store.read()));\n } catch (e) {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: e instanceof Error ? e.message : 'unknown error' }));\n }\n });\n\n ctx.server.route('/__apply-batch/changes', async (_req, res) => {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(store.read().changes));\n });\n\n ctx.server.route('/__apply-batch/graph', async (_req, res) => {\n const state = store.read();\n const graph = {\n changes: state.changes.map(c => ({\n name: c.name,\n status: c.status,\n dependencies: c.dependencies,\n batchIndex: c.batchIndex,\n })),\n batches: state.batches,\n conflicts: state.conflicts,\n };\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(graph));\n });\n\n ctx.server.route('/__apply-batch/logs', async (_req, res) => {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(store.read().logs.slice(-100)));\n });\n\n ctx.server.route('/__apply-batch/approve', async (req, res) => {\n try {\n const body = JSON.parse(await readBody(req) || '{}');\n store.updateStatus('running');\n store.updateParallelism(body.parallelism ?? 2);\n if (body.skipChanges?.length) {\n for (const name of body.skipChanges) {\n store.updateChange(name, { status: 'skipped' });\n }\n }\n store.addLog({\n timestamp: new Date().toISOString(),\n level: 'info',\n message: `用户确认执行计划,并行度=${body.parallelism ?? 2}`,\n });\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(store.read()));\n } catch (e) {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: e instanceof Error ? e.message : 'unknown error' }));\n }\n });\n\n ctx.server.route('/__apply-batch/adjust', async (req, res) => {\n try {\n const body = JSON.parse(await readBody(req) || '{}');\n if (body.parallelism) store.updateParallelism(body.parallelism);\n if (body.skipChanges?.length) {\n for (const name of body.skipChanges) {\n store.updateChange(name, { status: 'skipped' });\n }\n }\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(store.read()));\n } catch (e) {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: e instanceof Error ? e.message : 'unknown error' }));\n }\n });\n\n ctx.server.route('/__apply-batch/retry', async (req, res) => {\n try {\n const body = JSON.parse(await readBody(req) || '{}');\n const name = body.name;\n if (!name) throw new Error('missing name');\n const change = store.read().changes.find(c => c.name === name);\n if (!change) throw new Error('change not found');\n store.updateChange(name, {\n status: 'pending',\n error: undefined,\n retryCount: (change.retryCount ?? 0) + 1,\n });\n store.addLog({\n timestamp: new Date().toISOString(),\n level: 'info',\n message: `重试 change: ${name}`,\n changeName: name,\n });\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(store.read()));\n } catch (e) {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: e instanceof Error ? e.message : 'unknown error' }));\n }\n });\n\n ctx.server.route('/__apply-batch/pause', async (req, res) => {\n store.updateStatus('paused');\n store.addLog({\n timestamp: new Date().toISOString(),\n level: 'warn',\n message: '用户暂停批量执行',\n });\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(store.read()));\n });\n\n ctx.server.route('/__apply-batch/resume', async (req, res) => {\n store.updateStatus('running');\n store.addLog({\n timestamp: new Date().toISOString(),\n level: 'info',\n message: '用户恢复批量执行',\n });\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(store.read()));\n });\n\n ctx.server.route('/__apply-batch/reset', async (req, res) => {\n store.reset();\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(store.read()));\n });\n });\n },\n};\n"],"mappings":"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","names":["path","fs","fileURLToPath","fs","path","fs","path","execFile","execFile","path","fs","err","fp","fs","Service","fs","path","fs","path","fs","path","execFile","apply","Service","readBody","Service","readBody","execFile","apply","readBody","apply","fs","path","apply","readBody","fs","path","fs","path","apply","path","fs","path","path","apply","path","fs","apply","fs","path","path","fs","apply","fs","path","apply","YAML","__dirname","path","fileURLToPath","fs","apply"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/server/detect.ts","../src/core/server.ts","../package.json","../src/core/instance.ts","../src/core/open-url.ts","../src/core/reload.ts","../src/server/spec-scan.ts","../src/server/walk.ts","../src/core/tree.ts","../src/core/worktrees.ts","../src/core/manifest.ts","../src/core/read-body.ts","../src/server/just-runner.ts","../src/sdk/server.ts","../src/plugins/builtin.ts","../src/plugins/just/manifest.ts","../src/plugins/just/index.ts","../src/plugins/apply/scan.ts","../src/plugins/apply/parse-tasks.ts","../src/plugins/apply/batch.ts","../src/plugins/apply/manifest.ts","../src/plugins/apply/index.ts","../src/plugins/design/index.ts","../src/server/design-assets.ts","../src/plugins/design/manifest.ts","../src/plugins/view/manifest.ts","../src/plugins/view/index.ts","../src/plugins/stats/index.ts","../src/plugins/stats/manifest.ts"],"sourcesContent":["import path from 'node:path';\nimport fs from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport { access, readdir } from 'node:fs/promises';\nimport { exec } from 'node:child_process';\nimport { parseArgs as utilParseArgs } from 'node:util';\nimport { detect } from './server/detect.js';\nimport type { DetectResult } from './server/detect.js';\nimport { Context, Service } from 'cordis';\nimport { ServerService, PLUGIN_STATIC_PREFIX } from './core/server.js';\nimport { ReloadService } from './core/reload.js';\nimport { apply as treeApply } from './core/tree.js';\nimport { apply as worktreesApply } from './core/worktrees.js';\nimport { DashboardService } from './core/manifest.js';\nimport {\n findReusable,\n stopInstance,\n writeRecord,\n clearRecord,\n stripDeadPluginConfig,\n} from './core/instance.js';\nimport { openUrl } from './core/open-url.js';\nimport { apply as justApply } from './plugins/just/index.js';\nimport { apply as applyApply } from './plugins/apply/index.js';\nimport { apply as designApply } from './plugins/design/index.js';\nimport { apply as viewApply } from './plugins/view/index.js';\nimport { apply as statsApply } from './plugins/stats/index.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nconst DEFAULT_PORT = 4190;\n\nfunction parseArgs() {\n const args = process.argv.slice(2);\n const { values } = utilParseArgs({\n options: {\n dir: { type: 'string' },\n port: { type: 'string' },\n open: { type: 'boolean', default: false },\n page: { type: 'string' },\n restart: { type: 'boolean', default: false },\n plugins: { type: 'string' },\n },\n args,\n strict: false,\n allowPositionals: false,\n });\n return {\n dir: typeof values.dir === 'string' ? values.dir : process.cwd(),\n port: typeof values.port === 'string' ? Number(values.port) : DEFAULT_PORT,\n portExplicit: args.some(a => a === '--port' || a.startsWith('--port=')),\n open: !!values.open,\n page: typeof values.page === 'string' ? values.page : null,\n restart: !!values.restart,\n plugins: typeof values.plugins === 'string' ? values.plugins : null,\n };\n}\n\nasync function pathExists(p: string): Promise<boolean> {\n try { await access(p); return true; } catch { return false; }\n}\n\nasync function loadExternal(ctx: Context, dir: string, root: string) {\n if (!dir) return;\n let tsxLoaded = false;\n try {\n const { register } = await import('tsx/esm/api');\n register();\n tsxLoaded = true;\n } catch {\n // tsx not available\n }\n\n try {\n const entries = await pathExists(dir) ? await readdir(dir, { withFileTypes: true }) : [];\n for (const ent of entries) {\n if (!ent.isDirectory()) continue;\n const candidates = tsxLoaded ? ['index.ts', 'index.js', 'index.mjs'] : ['index.js', 'index.mjs'];\n for (const name of candidates) {\n const p = path.join(dir, ent.name, name);\n if (await pathExists(p)) {\n try {\n const mod = await import(p);\n const plugin = mod.default ?? mod;\n if (plugin?.apply) {\n try {\n await ctx.plugin(plugin, { root });\n } catch (e) {\n console.error(`[zdashboard] failed to apply plugin ${ent.name}:`, e);\n break;\n }\n // 自动接线约定:mode === 目录名时补 external 标记与 viewerUrl\n const m = ctx.dashboard.get(ent.name);\n if (m && m.mode === ent.name) {\n const patch: Record<string, unknown> = { external: true };\n const webDir = path.join(dir, ent.name, 'web');\n if (await pathExists(path.join(webDir, 'index.html'))) {\n ctx.server.static(`${PLUGIN_STATIC_PREFIX}${ent.name}/`, webDir);\n if (!m.viewerUrl) patch.viewerUrl = `${PLUGIN_STATIC_PREFIX}${ent.name}/`;\n }\n ctx.dashboard.register({ ...m, ...patch });\n }\n }\n } catch (e) {\n console.error(`[zdashboard] failed to load plugin ${ent.name}:`, e);\n }\n break;\n }\n }\n }\n } catch {\n // ignore\n }\n}\n\nasync function main() {\n const args = parseArgs();\n const root = path.resolve(args.dir);\n\n // --- instance reuse (before creating Context) ---\n const existing = await findReusable(root);\n if (existing && !args.restart) {\n const u = `http://localhost:${existing.port}` + (args.page ? `#${args.page}` : '');\n if (args.open) openUrl(u);\n console.log(`[zdashboard] 已复用实例 ${u}(--restart 可强制重开)`);\n // 管道场景下 stdout 是异步写,显式等 flush 再 exit,避免日志被截断\n await new Promise<void>((resolve) => process.stdout.write('', () => resolve()));\n process.exit(0);\n }\n // 记录旧端口(--restart 时用于端口继承;stopInstance 会清 record)\n const oldRecord = existing && args.restart ? existing : null;\n if (oldRecord) {\n console.log(`[zdashboard] --restart:停止旧实例 pid=${oldRecord.pid}`);\n await stopInstance(oldRecord);\n }\n\n const appDir = path.resolve(__dirname, 'web');\n\n // built-in plugins:统一数组注册(未来迁移为 definePlugin 产出后无需改动此处)\n // apply-batch 已并入 apply(mode apply,view=batch Tab 只读驾驶舱),见 2026-08-28-apply-merge-progress\n const BUILTIN_PLUGINS = [statsApply, justApply, applyApply, designApply, viewApply];\n\n // 约定化扫描:启动一次性剥离 dashboard.json 里内置插件的死配置键(未声明 config 即清,external/未知保留)\n if (stripDeadPluginConfig(root, BUILTIN_PLUGINS.map((p) => p.manifest))) {\n console.log('[zdashboard] 已清理 dashboard.json 中内置插件的过时配置键');\n }\n\n // P2: restart 且有旧记录时,起始端口用 record.port(用户显式 --port 则尊重)\n const startPort = oldRecord && !args.portExplicit ? oldRecord.port : args.port;\n\n // P0: 数据目录检测(.zdev/ 存在则优先)\n const zdevDir = path.join(root, '.zdev');\n const dataDir = fs.existsSync(zdevDir) ? '.zdev/' : '';\n\n const det = await detect(root);\n\n const ctx = new Context();\n\n // core services\n ctx.plugin(ServerService, {\n root,\n appDir,\n port: startPort,\n open: args.open,\n detect: det,\n page: args.page,\n dataDir: dataDir || undefined,\n onListen: (port: number) => writeRecord(root, port),\n });\n ctx.plugin(ReloadService, { root });\n ctx.plugin(treeApply, { root });\n ctx.plugin(worktreesApply, { root });\n ctx.plugin(DashboardService);\n\n for (const apply of BUILTIN_PLUGINS) {\n try {\n ctx.plugin(apply, { root });\n } catch (e) {\n console.error('[zdashboard] builtin plugin failed:', e);\n }\n }\n\n // external plugins\n if (args.plugins) {\n await loadExternal(ctx, path.resolve(args.plugins), root);\n }\n\n // graceful shutdown: clear .zdev record on SIGTERM / SIGINT\n const shutdown = () => {\n try { clearRecord(root); } catch {}\n process.exit(0);\n };\n process.on('SIGTERM', shutdown);\n process.on('SIGINT', shutdown);\n\n return ctx;\n}\n\nawait main().catch((e) => {\n console.error(e);\n process.exit(1);\n});\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { execFile } from 'node:child_process';\n\nexport interface DetectResult {\n hasOpenspec: boolean;\n hasDocs: boolean;\n hasJust: boolean;\n}\n\n/** --list 主探测超时(与迁移前一致) */\nconst JUST_PROBE_TIMEOUT_MS = 5000;\n/** --version 兜底探测超时(快失败:二进制存在性检查无需长等) */\nconst JUST_FALLBACK_TIMEOUT_MS = 3000;\n\nfunction justAvailable(cwd: string): Promise<boolean> {\n /** 探测一次:进程正常退出即视为可用 */\n const probe = (args: string[], timeout: number) => new Promise<boolean>((resolve) => {\n const child = execFile('just', args, { cwd, timeout }, (err) => resolve(!err));\n if (child.killed) resolve(false);\n });\n // 旧版以 --list --unsupported 判定;新版 just 移除该旗标会报错(hasJust 恒 false),\n // 回退 --version 探测二进制本身可用\n return probe(['--list', '--unsupported'], JUST_PROBE_TIMEOUT_MS)\n .then((ok) => (ok ? true : probe(['--version'], JUST_FALLBACK_TIMEOUT_MS)));\n}\n\nexport async function detect(root: string): Promise<DetectResult> {\n const hasOpenspec = fs.existsSync(path.join(root, 'openspec'));\n const hasDocs = fs.existsSync(path.join(root, 'docs'));\n const hasJust = await justAvailable(root);\n return { hasOpenspec, hasDocs, hasJust };\n}\n\n/** /__detect 的响应形状:与 DetectResult 同形(bugs 期兼容字段已随清理 change 摘除) */\nexport type DetectResponse = DetectResult;\n\n/** 现场探测(每次请求重新跑),供 /__detect 独立路由使用 */\nexport async function detectLiveShape(root: string): Promise<DetectResponse> {\n return detect(root);\n}\n","import http from 'node:http';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport crypto from 'node:crypto';\nimport { fileURLToPath } from 'node:url';\nimport pkg from '../../package.json' with { type: 'json' };\nimport type { Context } from 'cordis';\nimport type { DetectResult, DetectResponse } from '../server/detect.js';\nimport { detectLiveShape } from '../server/detect.js';\nimport type { PluginManifest, ConfigField } from '../core/manifest.js';\nimport { Service } from 'cordis';\nimport { clearRecord, readPluginsConfig, writePluginsConfig } from './instance.js';\nimport { openUrl } from './open-url.js';\nimport { readBody } from './read-body.js';\nimport { execFile } from 'node:child_process';\n\nconst VERSION = pkg.version;\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface ServerOptions {\n root: string;\n appDir: string;\n port: number;\n open: boolean;\n page: string | null;\n detect: DetectResult;\n dataDir?: string;\n onListen?: (port: number) => void;\n}\n\ndeclare module 'cordis' {\n interface Context {\n server: ServerService;\n }\n}\n\n/** 扩展名 → Content-Type 表(SDK 插件路由等复用,勿在他处复制) */\nexport const MIME: Record<string, string> = {\n '.html': 'text/html; charset=utf-8', '.htm': 'text/html; charset=utf-8',\n '.css': 'text/css; charset=utf-8', '.js': 'application/javascript; charset=utf-8',\n '.mjs': 'application/javascript; charset=utf-8', '.json': 'application/json; charset=utf-8',\n '.svg': 'image/svg+xml', '.png': 'image/png', '.ico': 'image/x-icon',\n '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.gif': 'image/gif', '.webp': 'image/webp',\n '.avif': 'image/avif',\n '.md': 'text/markdown; charset=utf-8', '.txt': 'text/plain; charset=utf-8',\n '.sql': 'text/plain; charset=utf-8', '.csv': 'text/plain; charset=utf-8',\n '.tsv': 'text/plain; charset=utf-8', '.yaml': 'text/yaml; charset=utf-8',\n '.yml': 'text/yaml; charset=utf-8', '.xml': 'application/xml; charset=utf-8',\n '.py': 'text/plain; charset=utf-8', '.ts': 'text/plain; charset=utf-8',\n '.java': 'text/plain; charset=utf-8', '.go': 'text/plain; charset=utf-8',\n '.rs': 'text/plain; charset=utf-8', '.rb': 'text/plain; charset=utf-8',\n '.php': 'text/plain; charset=utf-8', '.c': 'text/plain; charset=utf-8',\n '.cpp': 'text/plain; charset=utf-8', '.h': 'text/plain; charset=utf-8',\n '.cs': 'text/plain; charset=utf-8', '.swift': 'text/plain; charset=utf-8',\n '.kt': 'text/plain; charset=utf-8', '.scala': 'text/plain; charset=utf-8',\n '.sh': 'text/plain; charset=utf-8', '.bash': 'text/plain; charset=utf-8',\n '.zsh': 'text/plain; charset=utf-8', '.fish': 'text/plain; charset=utf-8',\n '.env': 'text/plain; charset=utf-8', '.gitignore': 'text/plain; charset=utf-8',\n '.dockerfile': 'text/plain; charset=utf-8',\n '.mp4': 'video/mp4', '.webm': 'video/webm', '.mov': 'video/quicktime',\n '.m4a': 'audio/mp4', '.aac': 'audio/aac',\n '.woff': 'font/woff', '.woff2': 'font/woff2', '.ttf': 'font/woff',\n '.map': 'application/json; charset=utf-8',\n};\n\n// 静态 HTML 注入脚本:仅保留 _self 链接补丁(文件预览页内跳转留在当前窗口)。\n// 旧 EventSource('/__reload') 注入已随沙箱收紧移除——sandbox=allow-scripts 下 iframe\n// 为不透明源,/__reload 属跨域请求,只会制造 console error 且其处理器本已为空。\nconst INJECT = `<script>(function(){document.addEventListener('click',function(e){var t=e.target;if(t&&t.closest){var a=t.closest('a[target]');if(a&&a.target!=='_self'){a.target='_self';}}},true);})();</script>`;\n\nexport const PLUGIN_STATIC_PREFIX = '/__plugin/';\n\n/** json 响应助手:统一 Content-Type/缓存头与序列化,消灭 writeHead 样板 */\nexport function json(res: http.ServerResponse, data: unknown, status = 200): void {\n res.writeHead(status, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(data));\n}\n\n/** x-stop-token 鉴权助手:通过返回 true;未通过时已写 403 响应并返回 false */\nexport function guarded(req: http.IncomingMessage, res: http.ServerResponse, token: string): boolean {\n if (req.headers['x-stop-token'] !== token) {\n res.writeHead(403);\n res.end('forbidden');\n return false;\n }\n return true;\n}\n\nexport class ServerService extends Service {\n stopToken: string;\n private root: string;\n private appDir: string;\n private open: boolean;\n private page: string | null;\n private det: DetectResult;\n private dataDir?: string;\n private routes = new Map<string, (req: http.IncomingMessage, res: http.ServerResponse) => void>();\n private sses = new Map<string, (res: http.ServerResponse) => (() => void) | void>();\n private prefixStatic = new Map<string, string>();\n private server?: http.Server;\n private onListen?: (port: number) => void;\n\n constructor(ctx: Context, config: ServerOptions) {\n super(ctx, 'server');\n this.stopToken = crypto.randomBytes(12).toString('hex');\n this.root = config.root;\n this.appDir = config.appDir;\n this.open = config.open;\n this.page = config.page;\n this.det = config.detect;\n this.dataDir = config.dataDir;\n this.onListen = config.onListen;\n ctx.effect(() => () => this.dispose());\n\n this.refreshGitInfo();\n this.route('/__config', (_req, res) => {\n json(res, { stopToken: this.stopToken, version: VERSION, root: this.root, ...this.gitInfo });\n });\n\n // 独立探测接口(轻量,替代 HomeGrid 借道 /__files 全量树)\n this.route('/__detect', async (_req, res) => {\n const shape: DetectResponse = await detectLiveShape(this.root);\n json(res, shape);\n });\n\n // 应用级静态文件(index.html 引用但不在 /assets/ 下),避免落到项目目录 404\n this.route('/favicon.svg', (req, res) => {\n this.serveFile(path.join(this.appDir, 'favicon.svg'), req, res, false);\n });\n\n this.route('/__file-content', async (req, res) => {\n const url = new URL(req.url || '/', 'http://localhost');\n const rawPath = url.pathname.replace(/^\\/__file-content\\/?/, '');\n if (!rawPath || rawPath === '/') {\n res.writeHead(400);\n res.end('missing path');\n return;\n }\n const filePath = path.join(this.root, decodeURIComponent(rawPath));\n if (!filePath.startsWith(this.root + path.sep) && filePath !== this.root) {\n res.writeHead(403);\n res.end('Forbidden');\n return;\n }\n fs.stat(filePath, (err) => {\n if (err) { res.writeHead(404); return res.end('Not found'); }\n const ext = path.extname(filePath).toLowerCase();\n const ct = MIME[ext] ?? 'application/octet-stream';\n res.writeHead(200, { 'Content-Type': ct, 'Cache-Control': 'no-cache' });\n fs.createReadStream(filePath).pipe(res);\n });\n });\n\n this.route('/__stop', async (req, res) => {\n if (!guarded(req, res, this.stopToken)) return;\n json(res, { ok: true });\n this.stop();\n });\n\n this.start(config.port);\n }\n\n route(path: string, handler: (req: http.IncomingMessage, res: http.ServerResponse) => void) {\n this.routes.set(path, handler);\n this.ctx.effect(() => () => this.routes.delete(path));\n }\n\n sse(path: string, onConnect: (res: http.ServerResponse) => (() => void) | void) {\n this.sses.set(path, onConnect);\n this.ctx.effect(() => () => this.sses.delete(path));\n }\n\n static(prefix: string, dir: string) {\n this.prefixStatic.set(prefix, dir);\n this.ctx.effect(() => () => this.prefixStatic.delete(prefix));\n }\n\n private pluginsConfig: Record<string, Record<string, unknown>> = {};\n\n getPluginConfig(mode: string): Record<string, unknown> {\n return this.pluginsConfig[mode] ?? {};\n }\n\n refreshPluginsConfig() {\n this.pluginsConfig = readPluginsConfig(this.root);\n }\n\n savePluginConfig(merged: Record<string, Record<string, unknown>>) {\n this.pluginsConfig = merged;\n writePluginsConfig(this.root, merged);\n }\n\n private serveFile(filePath: string, req: http.IncomingMessage, res: http.ServerResponse, injectHtml: boolean) {\n fs.stat(filePath, (err, stat) => {\n if (err) { res.writeHead(404); return res.end('Not found'); }\n const ext = path.extname(filePath).toLowerCase();\n const ct = MIME[ext] ?? 'application/octet-stream';\n\n // ---- HTTP Range support ----\n const rangeHeader = (req.headers['range'] as string | undefined);\n let range: { start: number; end: number } | null = null;\n if (rangeHeader) {\n const m = rangeHeader.match(/^bytes=(\\d+)-(\\d*)$/);\n if (m) {\n const start = Number(m[1]);\n const end = m[2] !== '' ? Number(m[2]) : stat.size - 1;\n if (!Number.isNaN(start) && !Number.isNaN(end) && start <= end && start < stat.size) {\n range = { start, end: Math.min(end, stat.size - 1) };\n }\n // malformed range → fall through to 200 full response\n }\n // unparseable range header → fall through to 200 full response\n }\n\n if (range) {\n const { start, end } = range;\n const chunkSize = end - start + 1;\n res.writeHead(206, {\n 'Content-Type': ct,\n 'Content-Length': String(chunkSize),\n 'Content-Range': `bytes ${start}-${end}/${stat.size}`,\n 'Accept-Ranges': 'bytes',\n 'Cache-Control': 'no-cache',\n });\n // stat 成功后文件仍可能在 open 前被删/换(高频增删的工作区),流错误无人接会崩进程\n const stream = fs.createReadStream(filePath, { start, end });\n stream.on('error', () => { try { res.destroy(); } catch { /* 已断 */ } });\n stream.pipe(res);\n return;\n }\n\n // Full response\n fs.readFile(filePath, (err, data) => {\n if (err) { res.writeHead(404); return res.end('Not found'); }\n let body: string | Buffer = data;\n if (injectHtml && ext === '.html') {\n const s = data.toString('utf8');\n body = Buffer.from(s.indexOf('</body>') >= 0 ? s.replace('</body>', INJECT + '</body>') : s + INJECT);\n }\n res.writeHead(200, { 'Content-Type': ct, 'Accept-Ranges': 'bytes', 'Cache-Control': 'no-cache' });\n res.end(body);\n });\n });\n }\n\n private servePrefix(url: string, req: http.IncomingMessage, res: http.ServerResponse): boolean {\n for (const [prefix, dir] of this.prefixStatic) {\n if (url.indexOf(prefix) === 0) {\n let rel = this.safeDecode(url.slice(prefix.length));\n if (!rel || rel === '/' || !path.extname(rel)) rel = path.join(rel || '', 'index.html');\n const fp = path.join(dir, rel);\n if (fp.indexOf(dir + path.sep) !== 0) { res.writeHead(403); res.end('Forbidden'); return false; }\n this.serveFile(fp, req, res, true);\n return true;\n }\n }\n return false;\n }\n\n private safeDecode(raw: string): string {\n try { return decodeURIComponent(raw); } catch { return raw; }\n }\n\n private handler = (req: http.IncomingMessage, res: http.ServerResponse) => {\n try {\n const rawUrl = req.url || '/';\n const url = rawUrl.split('?')[0];\n\n const rh = this.routes.get(url);\n if (rh) { rh(req, res); return; }\n for (const [rp, rh2] of this.routes) {\n if (url.startsWith(rp + '/')) { rh2(req, res); return; }\n }\n const sh = this.sses.get(url);\n if (sh) {\n res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', Connection: 'keep-alive' });\n res.write(': connected\\n\\n');\n const cleanup = sh(res);\n req.on('close', () => { cleanup?.(); });\n return;\n }\n\n if (this.servePrefix(url, req, res)) return;\n\n if (url === '/' || url.indexOf('/__app/') === 0 || url.indexOf('/assets/') === 0) {\n let fp = this.appDir;\n if (url !== '/') fp = path.join(this.appDir, this.safeDecode(url));\n if (url.indexOf('/__app/') === 0) fp = path.join(this.appDir, url.slice(7));\n if (fp !== this.appDir && fp.indexOf(this.appDir + path.sep) !== 0) { res.writeHead(403); return res.end('Forbidden'); }\n if (url === '/') fp = path.join(this.appDir, 'index.html');\n return this.serveFile(fp, req, res, false);\n }\n\n const fp = path.join(this.root, this.safeDecode(url));\n if (fp !== this.root && fp.indexOf(this.root + path.sep) !== 0) { res.writeHead(403); return res.end('Forbidden'); }\n return this.serveFile(fp, req, res, true);\n } catch (e) {\n try { res.writeHead(400); res.end('bad request'); } catch {}\n console.error('[zdashboard] handler error', e);\n }\n };\n\n start(port: number) {\n this.server = http.createServer(this.handler);\n // 浏览器复用空闲 keep-alive 连接时若已被服务端关闭,请求会石沉大海(点击无响应)。\n // 拉长 keep-alive 使其远大于浏览器侧空闲窗口\n this.server.keepAliveTimeout = 65_000;\n this.server.headersTimeout = 66_000;\n this.server.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n console.log(`[zdashboard] port ${port} busy, trying ${port + 1}`);\n this.start(port + 1);\n } else throw err;\n });\n this.server.listen(port, '127.0.0.1', () => {\n // port=0(测试/随机端口)时上报实际绑定端口\n const addr = this.server?.address();\n const bound = typeof addr === 'object' && addr ? addr.port : port;\n const u = `http://localhost:${bound}`;\n const target = this.page ? `${u}#${this.page}` : u;\n console.log(`[zdashboard] v${VERSION} dashboard -> ${u}`);\n console.log(`[zdashboard] project -> ${this.root}`);\n console.log(`[zdashboard] detect -> openspec:${this.det.hasOpenspec} docs:${this.det.hasDocs} just:${this.det.hasJust}`);\n if (this.dataDir) console.log(`[zdashboard] data -> ${this.dataDir}`);\n if (this.open) openUrl(target);\n this.onListen?.(bound);\n });\n }\n\n /** 项目 git 信息(分支/脏文件数),启动探测一次,文件变更时刷新 */\n private gitInfo: { branch?: string; dirty?: number } = {};\n\n refreshGitInfo() {\n const run = (args: string[]) => new Promise<string>((resolve) => {\n execFile('git', args, { cwd: this.root, timeout: 3000 }, (err, stdout) => resolve(err ? '' : stdout));\n });\n void (async () => {\n const [branch, status] = await Promise.all([\n run(['rev-parse', '--abbrev-ref', 'HEAD']),\n run(['status', '--porcelain']),\n ]);\n const b = branch.trim();\n this.gitInfo = b ? { branch: b, dirty: status ? status.split('\\n').filter(Boolean).length : 0 } : {};\n })();\n }\n\n stop() {\n if (this.server) { try { this.server.close(); } catch {} }\n try { clearRecord(this.root); } catch {}\n setTimeout(() => {\n try { this.ctx.root.fiber.dispose(); } catch {}\n process.exit(0);\n }, 50);\n }\n\n dispose() {\n if (this.server) { try { this.server.close(); } catch {} }\n try { clearRecord(this.root); } catch {}\n }\n}\n","{\n \"name\": \"zdashboard\",\n \"version\": \"2.8.1\",\n \"description\": \"ZCode skill dashboard platform — pluggable viewers for zdesign/zview/zreview/zgoal\",\n \"type\": \"module\",\n \"bin\": {\n \"zdashboard\": \"./dist/cli.js\"\n },\n \"files\": [\n \"dist\"\n ],\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"scripts\": {\n \"dev\": \"vite\",\n \"build\": \"tsup && vite build\",\n \"build:web\": \"vite build\",\n \"build:node\": \"tsup\",\n \"start\": \"node dist/cli.js\",\n \"test\": \"vitest run\",\n \"typecheck\": \"tsc --noEmit\",\n \"test:coverage\": \"vitest run --coverage\",\n \"preview\": \"vite preview\"\n },\n \"dependencies\": {\n \"@fontsource/vt323\": \"^5.3.0\",\n \"@phosphor-icons/react\": \"^2.1.10\",\n \"@radix-ui/react-dropdown-menu\": \"^2.1.24\",\n \"@radix-ui/react-scroll-area\": \"^1.2.0\",\n \"@radix-ui/react-separator\": \"^1.1.0\",\n \"@radix-ui/react-slot\": \"^1.1.0\",\n \"@radix-ui/react-tooltip\": \"^1.1.2\",\n \"@uidotdev/usehooks\": \"^2.4.0\",\n \"ansi-to-react\": \"^6.1.6\",\n \"class-variance-authority\": \"^0.7.0\",\n \"clsx\": \"^2.1.1\",\n \"cordis\": \"4.0.0-rc.8\",\n \"cosmokit\": \"^1.8.1\",\n \"date-fns\": \"^3.6.0\",\n \"filesize\": \"^11.0.0\",\n \"highlight.js\": \"^11.11.1\",\n \"iconv-lite\": \"0.7.3\",\n \"katex\": \"^0.16.11\",\n \"ky\": \"^1.7.0\",\n \"lodash-es\": \"^4.17.21\",\n \"lucide-react\": \"^0.460.0\",\n \"pixelarticons\": \"^2.4.1\",\n \"react\": \"^18.3.1\",\n \"react-dom\": \"^18.3.1\",\n \"react-error-boundary\": \"^5.0.0\",\n \"react-markdown\": \"^9.0.1\",\n \"rehype-autolink-headings\": \"^7.1.0\",\n \"rehype-highlight\": \"^7.0.1\",\n \"rehype-katex\": \"^7.0.1\",\n \"rehype-raw\": \"^7.0.0\",\n \"rehype-slug\": \"^6.0.0\",\n \"remark-frontmatter\": \"^5.0.0\",\n \"remark-gfm\": \"^4.0.0\",\n \"remark-math\": \"^6.0.0\",\n \"sonner\": \"^1.5.0\",\n \"tailwind-merge\": \"^2.5.4\",\n \"tsx\": \"^4.7.0\",\n \"use-debounce\": \"^10.0.0\",\n \"yaml\": \"^2.9.0\"\n },\n \"devDependencies\": {\n \"@tailwindcss/typography\": \"^0.5.20\",\n \"@testing-library/jest-dom\": \"^7.0.1\",\n \"@testing-library/react\": \"^16.3.2\",\n \"@types/lodash-es\": \"^4.17.12\",\n \"@types/node\": \"^22.9.0\",\n \"@types/react\": \"^18.3.12\",\n \"@types/react-dom\": \"^18.3.1\",\n \"@vitejs/plugin-react\": \"^4.7.0\",\n \"@vitest/coverage-v8\": \"1.6.0\",\n \"autoprefixer\": \"^10.4.20\",\n \"jsdom\": \"^30.0.1\",\n \"postcss\": \"^8.4.49\",\n \"tailwindcss\": \"^3.4.14\",\n \"tailwindcss-animate\": \"^1.0.7\",\n \"tsup\": \"^8.3.5\",\n \"typescript\": \"^5.6.3\",\n \"vite\": \"^5.4.10\",\n \"vitest\": \"^1.6.0\"\n },\n \"pnpm\": {\n \"onlyBuiltDependencies\": [\n \"esbuild\"\n ]\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nexport interface InstanceRecord {\n pid: number;\n port: number;\n root: string;\n startedAt: string;\n plugins?: Record<string, Record<string, unknown>>;\n}\n\nexport const RECORD_FILE = '.zdev/dashboard.json';\nexport const VERIFY_TIMEOUT_MS = 1500;\nexport const STOP_POLL_MS = 2000;\nexport const STOP_POLL_INTERVAL_MS = 100;\nexport const STOP_FINAL_WAIT_MS = 100;\n\nfunction recordPath(root: string): string {\n return path.join(root, RECORD_FILE);\n}\n\nexport function readRecord(root: string): InstanceRecord | null {\n try {\n const fp = recordPath(root);\n const raw = fs.readFileSync(fp, 'utf-8');\n const rec = JSON.parse(raw) as Partial<InstanceRecord>;\n if (\n typeof rec.pid === 'number' &&\n typeof rec.port === 'number' &&\n typeof rec.root === 'string' &&\n typeof rec.startedAt === 'string'\n ) {\n return rec as InstanceRecord;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nexport function writeRecord(root: string, port: number): void {\n const fp = recordPath(root);\n fs.mkdirSync(path.dirname(fp), { recursive: true });\n // 读改写:onListen 每次启动都会调 writeRecord,需沿用旧记录的 plugins 段,\n // 只更新运行字段(pid/port/root/startedAt),否则插件配置跨重启清零。\n const old = readRecord(root); // 记录缺失/损坏 → null,兜底最小记录\n const rec: InstanceRecord = {\n pid: process.pid,\n port,\n root,\n startedAt: new Date().toISOString(),\n };\n if (old?.plugins && typeof old.plugins === 'object') {\n rec.plugins = old.plugins;\n }\n // tmp+rename 原子写(对齐 writePluginsConfig),避免半写状态被读到\n const tmp = fp + '.tmp';\n fs.writeFileSync(tmp, JSON.stringify(rec, null, 2) + '\\n');\n fs.renameSync(tmp, fp);\n}\n\nexport function readPluginsConfig(root: string): Record<string, Record<string, unknown>> {\n try {\n const rec = readRecord(root);\n if (rec?.plugins && typeof rec.plugins === 'object') {\n return rec.plugins as Record<string, Record<string, unknown>>;\n }\n } catch { /* ignore */ }\n return {};\n}\n\nexport function writePluginsConfig(root: string, plugins: Record<string, Record<string, unknown>>): void {\n const fp = recordPath(root);\n let rec: InstanceRecord;\n try {\n const raw = fs.readFileSync(fp, 'utf-8');\n rec = JSON.parse(raw) as InstanceRecord;\n } catch {\n rec = { pid: process.pid, port: 0, root, startedAt: new Date().toISOString() };\n }\n rec.plugins = plugins;\n const tmp = fp + '.tmp';\n fs.writeFileSync(tmp, JSON.stringify(rec, null, 2) + '\\n');\n fs.renameSync(tmp, fp);\n}\n\n/** 死键剥离判定所需的最小 manifest 投影(PluginManifest 结构兼容) */\nexport interface ConfigSchemaInfo {\n mode: string;\n external?: boolean;\n /** manifest.config 声明:缺省或空对象表示该内置插件无配置面 */\n config?: Record<string, unknown>;\n}\n\n/**\n * 启动一次性:剥离 dashboard.json 里内置插件的死配置键(通用规则,收敛自 view/design 约定化扫描)。\n * - 内置(非 external)未声明 config → 整段死键,清除;\n * - 内置已声明 config → 仅保留声明键(键级收敛);\n * - external 插件键保留;存储中无 manifest 声明的键(未知/未加载插件)保守保留。\n * 无变更/无记录时不写盘。返回是否发生了剥离。记录缺失/损坏跳过清理,不阻塞启动。\n */\nexport function stripDeadPluginConfig(root: string, manifests: readonly ConfigSchemaInfo[]): boolean {\n try {\n const rec = readRecord(root);\n if (!rec?.plugins || typeof rec.plugins !== 'object') return false;\n const byMode = new Map(manifests.map((m) => [m.mode, m]));\n const stored = rec.plugins as Record<string, unknown>;\n const plugins: Record<string, unknown> = { ...stored };\n let changed = false;\n for (const mode of Object.keys(plugins)) {\n const m = byMode.get(mode);\n // 无声明(未注册,可能是外部插件或已卸载)→ 保守不清;external → 保留\n if (!m || m.external) continue;\n const section = plugins[mode];\n if (section === null || typeof section !== 'object') continue;\n const keys = Object.keys(section as Record<string, unknown>);\n if (!m.config || Object.keys(m.config).length === 0) {\n // 内置且未声明 config → 整段死键\n if (keys.length > 0) {\n delete plugins[mode];\n changed = true;\n }\n continue;\n }\n // 键级收敛:仅保留 manifest.config 声明的键\n const kept: Record<string, unknown> = {};\n for (const key of Object.keys(m.config)) {\n if (key in (section as Record<string, unknown>)) kept[key] = (section as Record<string, unknown>)[key];\n }\n if (Object.keys(kept).length !== keys.length) {\n if (Object.keys(kept).length === 0) delete plugins[mode];\n else plugins[mode] = kept;\n changed = true;\n }\n }\n if (!changed) return false;\n writePluginsConfig(root, plugins as Record<string, Record<string, unknown>>); // tmp+rename 原子写\n return true;\n } catch {\n return false; // 记录缺失/损坏:跳过清理,不阻塞启动\n }\n}\n\nexport function clearRecord(root: string): void {\n try {\n // 属主校验:记录若已指向别的实例(并发双启落败者),不得误删胜者记录\n const rec = readRecord(root);\n if (rec && rec.pid !== process.pid) return;\n fs.unlinkSync(recordPath(root));\n } catch {\n // best-effort\n }\n}\n\nexport function isAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (e) {\n if ((e as NodeJS.ErrnoException).code === 'ESRCH') return false;\n // EPERM or other → process exists, we just can't signal it\n return true;\n }\n}\n\nasync function fetchWithTimeout(url: string): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), VERIFY_TIMEOUT_MS);\n try {\n return await fetch(url, { signal: controller.signal });\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function verifyRoot(port: number, root: string): Promise<boolean> {\n try {\n const res = await fetchWithTimeout(`http://127.0.0.1:${port}/__config`);\n if (res.status !== 200) return false;\n const body = await res.json();\n if (typeof body.root !== 'string') return false;\n return body.root === root;\n } catch {\n return false;\n }\n}\n\nexport async function findReusable(root: string): Promise<InstanceRecord | null> {\n const rec = readRecord(root);\n if (!rec) return null;\n if (!isAlive(rec.pid)) return null;\n if (!(await verifyRoot(rec.port, root))) return null;\n return rec;\n}\n\nexport async function stopInstance(record: InstanceRecord): Promise<void> {\n try {\n process.kill(record.pid, 'SIGTERM');\n } catch {\n return;\n }\n\n const deadline = Date.now() + STOP_POLL_MS;\n while (Date.now() < deadline) {\n if (!isAlive(record.pid)) return;\n await new Promise((r) => setTimeout(r, STOP_POLL_INTERVAL_MS));\n }\n\n // still alive → SIGKILL\n try {\n process.kill(record.pid, 'SIGKILL');\n } catch {\n // ignore\n }\n await new Promise((r) => setTimeout(r, STOP_FINAL_WAIT_MS));\n}\n","import { exec, execFile } from 'node:child_process';\n\n/** 跨平台打开浏览器(macOS open / Windows start / Linux xdg-open) */\nexport function openUrl(url: string): void {\n const cmd =\n process.platform === 'darwin' ? 'open' :\n process.platform === 'win32' ? 'start' :\n 'xdg-open';\n // win32 `start` 是 shell 内建命令,只能走 shell;其他平台直接用 execFile\n if (process.platform === 'win32') {\n exec(`start \"\" \"${url}\"`);\n } else {\n execFile(cmd, [url]);\n }\n}\n","import fs from 'node:fs';\nimport http from 'node:http';\nimport { Service } from 'cordis';\nimport type { Context } from 'cordis';\n\ndeclare module 'cordis' {\n interface Context {\n reload: ReloadService;\n }\n}\n\nconst WATCH_DEBOUNCE_MS = 300;\n\n/** 忽略目录(recursive watch 相对路径前缀)与编辑器/系统/日志噪音文件 */\nconst IGNORED_DIR_RE = /^(?:\\.git|node_modules|dist|\\.pnpm)(?:[/\\\\]|$)/;\nconst IGNORED_FILE_RE = /\\.(?:swp|tmp|log)$|~$|^\\.DS_Store$|^Thumbs\\.db$/i;\n\n/** filename 是否应被 watcher 忽略;null(平台未提供文件名)放行,行为不变 */\nexport function isIgnoredPath(filename: string | null): boolean {\n if (!filename) return false;\n return IGNORED_DIR_RE.test(filename) || IGNORED_FILE_RE.test(filename);\n}\n\nexport class ReloadService extends Service {\n static inject = ['server'];\n private clients = new Set<http.ServerResponse>();\n private watcher?: fs.FSWatcher;\n private timer?: NodeJS.Timeout;\n\n constructor(ctx: Context, config: { root: string }) {\n super(ctx, 'reload');\n this.ctx.effect(() => () => this.dispose());\n\n this.ctx.server.sse('/__reload', (res) => {\n this.clients.add(res);\n return () => this.clients.delete(res);\n });\n\n try {\n this.watcher = fs.watch(config.root, { recursive: true }, (eventType, filename) => {\n if (isIgnoredPath(filename)) return;\n if (this.timer) clearTimeout(this.timer);\n this.timer = setTimeout(() => {\n this.ctx.server.refreshGitInfo();\n this.broadcast('reload');\n this.broadcast('files');\n this.timer = undefined;\n }, WATCH_DEBOUNCE_MS);\n });\n } catch {\n // watch unavailable - static only\n }\n }\n\n broadcast(ev: string, data: unknown = '') {\n const payload = `event: ${ev}\\ndata: ${JSON.stringify(data == null ? '' : data)}\\n\\n`;\n for (const c of this.clients) {\n try { c.write(payload); } catch {}\n }\n }\n\n /** 插件专用频道:plugin:<mode>:<event>,客户端 usePluginData subscribe 消费 */\n broadcastPlugin(mode: string, event: string, data: unknown = '') {\n this.broadcast(`plugin:${mode}:${event}`, data);\n }\n\n dispose() {\n if (this.watcher) { try { this.watcher.close(); } catch {} }\n if (this.timer) { clearTimeout(this.timer); }\n for (const c of this.clients) { try { c.end(); } catch {} }\n this.clients.clear();\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { walkDir } from './walk.js';\n\nexport type NodeKind = 'file' | 'dir' | 'log';\nexport interface TreeNode {\n name: string;\n kind: NodeKind;\n path?: string;\n defaultCollapsed?: boolean;\n children?: TreeNode[];\n}\n\nfunction buildTree(paths: string[], defaultExpandDepth = 2): TreeNode[] {\n const root: TreeNode[] = [];\n const map = new Map<string, TreeNode>();\n\n for (const p of paths) {\n const parts = p.split('/');\n let current = '';\n let parent = root;\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n current = current ? `${current}/${part}` : part;\n const isLast = i === parts.length - 1;\n const depth = i;\n\n if (!map.has(current)) {\n const isDir = !isLast;\n const collapsed = isDir && typeof defaultExpandDepth === 'number' && depth > defaultExpandDepth;\n const node: TreeNode = {\n name: part,\n kind: isLast ? 'file' : 'dir',\n ...(collapsed ? { defaultCollapsed: true } : {}),\n ...(isLast ? { path: p } : { children: [] }),\n };\n map.set(current, node);\n parent.push(node);\n }\n\n if (!isLast) {\n parent = map.get(current)!.children!;\n }\n }\n }\n\n const sortNodes = (nodes: TreeNode[]) => {\n nodes.sort((a, b) => (a.kind === b.kind ? a.name.localeCompare(b.name) : a.kind === 'dir' ? -1 : 1));\n for (const n of nodes) {\n if (n.children) sortNodes(n.children);\n }\n };\n\n sortNodes(root);\n return root;\n}\n\nexport interface ScanTreeOptions {\n defaultExpandDepth?: number;\n}\n\nfunction prefixPaths(nodes: TreeNode[], prefix: string): TreeNode[] {\n return nodes.map((n) => {\n if (n.kind === 'file' && n.path) {\n return { ...n, path: `${prefix}/${n.path}` };\n }\n if (n.children) {\n return { ...n, children: prefixPaths(n.children, prefix) };\n }\n return n;\n });\n}\n\n/** 方案模式树形扫描:按 scanDirs 白名单扫描 */\nexport function scanTree(root: string, scanDirs: string[], opts?: ScanTreeOptions): TreeNode[] {\n const tree: TreeNode[] = [];\n const defaultExpandDepth = typeof opts?.defaultExpandDepth === 'number' ? opts.defaultExpandDepth : 2;\n const dirs = Array.isArray(scanDirs) ? scanDirs.filter((d) => typeof d === 'string' && d) : [];\n for (const dir of dirs) {\n const dirPath = path.join(root, dir);\n if (!fs.existsSync(dirPath)) continue;\n const paths: string[] = [];\n walkDir(dirPath, { maxDepth: 4, onFile: (_, rel) => paths.push(rel) });\n const prefix = dir;\n const children = prefixPaths(buildTree(paths, defaultExpandDepth), prefix);\n if (children.length) {\n tree.push({ name: `${dir} (${children.length})`, kind: 'dir', children });\n }\n }\n return tree;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nexport interface WalkOptions {\n skip?: Set<string>;\n maxDepth?: number;\n onFile?: (abs: string, rel: string) => void;\n onDir?: (abs: string, rel: string) => void;\n}\n\nexport function walkDir(root: string, opts: WalkOptions = {}): void {\n const { skip = new Set(), maxDepth, onFile, onDir } = opts;\n\n function walk(dir: string, rel: string, depth: number) {\n if (typeof maxDepth === 'number' && depth > maxDepth) return;\n let ents: fs.Dirent[];\n try { ents = fs.readdirSync(dir, { withFileTypes: true }); } catch { return; }\n for (const ent of ents) {\n if (ent.name.startsWith('.')) continue;\n if (skip.has(ent.name)) continue;\n const abs = path.join(dir, ent.name);\n const r = rel ? `${rel}/${ent.name}` : ent.name;\n if (ent.isDirectory()) {\n onDir?.(abs, r);\n walk(abs, r, depth + 1);\n } else if (onFile) {\n onFile(abs, r);\n }\n }\n }\n\n walk(root, '', 0);\n}\n","import type { Context } from 'cordis';\nimport { scanTree } from '../server/spec-scan.js';\n\n/** 生态约定:项目根/worktree 根下的固定扫描目录,非用户可配 */\nconst CONVENTION_SCAN_DIRS = ['openspec', 'docs'] as const;\n\nexport const apply = {\n inject: ['server'] as const,\n apply(ctx: Context, config: { root: string }) {\n const server = ctx.server;\n if (server?.route) {\n // /__files 仅返回目录树;探测位已由独立轻量接口 /__detect 承担,不再搭车\n server.route('/__files', async (req, res) => {\n try {\n const url = new URL(req.url || '/', 'http://localhost');\n const wt = url.searchParams.get('wt');\n const scanRoot = wt ? decodeURIComponent(wt) : config.root;\n const tree = scanTree(scanRoot, [...CONVENTION_SCAN_DIRS]);\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify({ tree }));\n } catch {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify({ tree: [] }));\n }\n });\n }\n },\n};\n","import { execFile } from 'node:child_process';\nimport type { Context } from 'cordis';\n\nexport interface WorktreeInfo {\n path: string;\n name: string;\n branch: string;\n head: string;\n dirty: boolean;\n}\n\nconst GIT_TIMEOUT_MS = 5_000;\nconst ZWORKTREE_SEGMENT = '.zworktree/';\n\nfunction runGit(args: string[], cwd: string): Promise<string> {\n return new Promise((resolve) => {\n execFile('git', args, { cwd, timeout: GIT_TIMEOUT_MS }, (err, stdout) => {\n if (err) return resolve('');\n resolve(stdout);\n });\n });\n}\n\nexport async function listWorktrees(root: string): Promise<WorktreeInfo[]> {\n const raw = await runGit(['worktree', 'list', '--porcelain'], root);\n if (!raw) return [];\n\n const entries: WorktreeInfo[] = [];\n const lines = raw.split('\\n');\n let current: Partial<WorktreeInfo> = {};\n\n for (const line of lines) {\n const m = line.match(/^(worktree|HEAD|branch|detached)\\s+(.+)$/);\n if (!m) continue;\n const [, key, val] = m;\n if (key === 'worktree') {\n if (current.path && current.path.includes(ZWORKTREE_SEGMENT)) {\n entries.push({\n path: current.path,\n name: current.path.split(ZWORKTREE_SEGMENT).pop() ?? '',\n branch: current.branch ?? '',\n head: current.head ?? '',\n dirty: false,\n });\n }\n current = { path: val, head: '', branch: '' };\n } else if (key === 'HEAD') {\n current.head = val;\n } else if (key === 'branch') {\n current.branch = val.replace(/^refs\\/heads\\//, '');\n }\n }\n\n // flush last entry\n if (current.path && current.path.includes(ZWORKTREE_SEGMENT)) {\n entries.push({\n path: current.path,\n name: current.path.split(ZWORKTREE_SEGMENT).pop() ?? '',\n branch: current.branch ?? '',\n head: current.head ?? '',\n dirty: false,\n });\n }\n\n // dirty detection: git status --porcelain 非空即 dirty(失败默认 false)\n await Promise.all(\n entries.map(async (entry) => {\n try {\n const statusOut = await runGit(['status', '--porcelain'], entry.path);\n entry.dirty = statusOut.trim().length > 0;\n } catch {\n entry.dirty = false;\n }\n })\n );\n\n return entries;\n}\n\nexport const apply = {\n inject: ['server'] as const,\n apply(ctx: Context, config: { root: string }) {\n const server = ctx.server;\n if (!server?.route) return;\n\n server.route('/__worktrees', async (_req, res) => {\n try {\n const entries = await listWorktrees(config.root);\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(entries));\n } catch {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify([]));\n }\n });\n },\n};\n","import { Service } from 'cordis';\nimport type { Context } from 'cordis';\nimport { readBody } from './read-body.js';\n\ndeclare module 'cordis' {\n interface Context {\n dashboard: DashboardService;\n }\n}\n\nexport interface PluginManifest {\n mode: string;\n label: string;\n icon: string;\n description?: string;\n viewerUrl?: string; // 同源 URL,前端 iframe 渲染\n external?: boolean;\n order?: number; // 排序权重(小在前);缺省按字母序\n config?: Record<string, ConfigField>;\n}\n\nexport interface ConfigField {\n type: 'string' | 'text' | 'number' | 'boolean' | 'string[]' | 'select' | 'multiselect';\n label: string;\n default?: unknown;\n placeholder?: string;\n options?: { value: string; label: string }[];\n min?: number;\n max?: number;\n}\n\nexport class DashboardService extends Service {\n static inject = ['server', 'reload'];\n private plugins = new Map<string, PluginManifest>();\n private reloadRef: any;\n\n constructor(ctx: Context) {\n super(ctx, 'dashboard');\n this.ctx.effect(() => () => this.plugins.clear());\n this.reloadRef = ctx.reload;\n\n this.ctx.server.route('/__plugins', (_req, res) => {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify({ plugins: Array.from(this.plugins.values()) }));\n });\n\n this.ctx.server.route('/__plugins/config', async (req, res) => {\n const out: Record<string, Record<string, unknown>> = {};\n if (req.method === 'GET') {\n for (const m of this.plugins.values()) {\n const stored = this.ctx.server.getPluginConfig(m.mode);\n const schema = m.config ?? {};\n const merged: Record<string, unknown> = {};\n for (const [key, field] of Object.entries(schema)) {\n merged[key] = key in stored ? stored[key] : (field as ConfigField).default ?? '';\n }\n if (Object.keys(merged).length) out[m.mode] = merged;\n }\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-cache' });\n res.end(JSON.stringify(out));\n return;\n }\n if (req.method === 'POST') {\n if (req.headers['x-stop-token'] !== this.ctx.server.stopToken) {\n res.writeHead(403);\n res.end('forbidden');\n return;\n }\n try {\n const body = JSON.parse(await readBody(req));\n const merged: Record<string, Record<string, unknown>> = {};\n for (const mode of Object.keys(body)) {\n merged[mode] = body[mode] ?? {};\n }\n this.ctx.server.savePluginConfig(merged);\n for (const mode of Object.keys(body)) {\n try { this.reloadRef.broadcast('config', { plugin: mode }); } catch { /* ignore */ }\n }\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end('{\"ok\":true}');\n } catch (e) {\n console.error('[config] POST error', e);\n res.writeHead(400);\n res.end('{\"error\":\"bad request\"}');\n }\n return;\n }\n res.writeHead(405);\n res.end('{\"error\":\"method not allowed\"}');\n });\n }\n\n register(manifest: PluginManifest) {\n this.plugins.set(manifest.mode, manifest);\n this.ctx.effect(() => () => this.plugins.delete(manifest.mode));\n }\n\n list() {\n return Array.from(this.plugins.values());\n }\n\n get(mode: string): PluginManifest | undefined {\n return this.plugins.get(mode);\n }\n\n getConfig(mode: string): Record<string, unknown> {\n return this.ctx.server.getPluginConfig(mode);\n }\n}\n","import http from 'node:http';\n\n/**\n * Read the full body of an IncomingMessage.\n * Listens for 'error' to prevent a hanging promise when the client aborts mid-stream.\n */\nexport async function readBody(req: http.IncomingMessage): Promise<string> {\n return new Promise((resolve) => {\n let data = '';\n req.on('data', (chunk: string | Buffer) => { data += chunk; });\n req.on('end', () => resolve(data));\n req.on('error', () => resolve('')); // client abort → settle with empty string\n });\n}\n","import { spawn, execFile, type ChildProcess } from 'node:child_process';\nimport iconv from 'iconv-lite';\n\nexport interface Recipe { name: string; description: string; }\nexport type TaskStatus = 'running' | 'exited';\nexport interface TaskInfo { recipe: string; state: TaskStatus; code: number | null; startedAt: number; signal?: string }\n\nexport type JustEvent =\n | { type: 'log'; recipe: string; text: string }\n | { type: 'clear'; recipe: string }\n | { type: 'state'; recipe: string; state: TaskStatus; code: number | null; startedAt?: number; signal?: string };\n\ninterface Task {\n recipe: string;\n child: ChildProcess | null;\n state: TaskStatus;\n code: number | null;\n signal?: string;\n startedAt: number;\n buffer: string[];\n pending: Buffer; // 字节级行缓冲:块缓冲输出会在行中间断开,攒到 \\n(0x0A)才切行——多字节字符不会跨行界,解码只发生在完整行上\n}\n\nconst MAX_BUFFER = 1000;\n\nconst utf8Strict = new TextDecoder('utf-8', { fatal: true });\n\n/**\n * 逐行解码:先 UTF-8 严格解码,失败回退 GBK(Windows 码页输出)。\n * 行界按 0x0A 字节切分是安全的:UTF-8 续字节 ≥ 0x80、GBK 尾字节 0x40–0xFE,均不含 0x0A。\n */\nfunction decodeLine(buf: Buffer): string {\n try {\n return utf8Strict.decode(buf);\n } catch {\n return iconv.decode(buf, 'gbk');\n }\n}\n\n/** 多任务并发 runner:每个 recipe 独立进程/日志/状态,同名 start 即重启,互不影响 */\nexport class JustRunner {\n private cwd: string;\n private tasks = new Map<string, Task>();\n private clients = new Set<(ev: JustEvent) => void>();\n private recipesCache: Recipe[] | null = null;\n\n constructor(cwd: string) { this.cwd = cwd; }\n\n recipes(): Promise<Recipe[]> {\n if (this.recipesCache) return Promise.resolve(this.recipesCache);\n return new Promise((resolve) => {\n execFile('just', ['--list', '--unsorted'], { cwd: this.cwd, maxBuffer: 1 << 20, timeout: 8000 }, (err, stdout) => {\n if (err) { resolve([]); return; }\n const out: Recipe[] = [];\n const seen = new Set<string>();\n for (const line of stdout.split(/\\r?\\n/).slice(1)) { // 跳过 \"Available recipes:\"\n const trimmed = line.trim();\n if (!trimmed) continue;\n const hashIdx = trimmed.indexOf('#');\n const sig = (hashIdx >= 0 ? trimmed.slice(0, hashIdx) : trimmed).trim();\n if (!sig) continue;\n const name = sig.split(/\\s+/)[0]; // \"hello msg=...\" -> \"hello\"\n if (seen.has(name)) continue;\n seen.add(name);\n out.push({ name, description: hashIdx >= 0 ? trimmed.slice(hashIdx + 1).trim() : '' });\n }\n this.recipesCache = out;\n resolve(out);\n });\n });\n }\n\n subscribe(fn: (ev: JustEvent) => void): () => void {\n this.clients.add(fn);\n // 连上即重放:全部任务的日志与状态\n for (const t of this.tasks.values()) {\n for (const text of t.buffer) fn({ type: 'log', recipe: t.recipe, text });\n fn({ type: 'state', recipe: t.recipe, state: t.state, code: t.code, startedAt: t.startedAt });\n }\n return () => this.clients.delete(fn);\n }\n\n private emit(ev: JustEvent) { for (const fn of this.clients) fn(ev); }\n\n list(): TaskInfo[] {\n return Array.from(this.tasks.values(), (t) => ({ recipe: t.recipe, state: t.state, code: t.code, startedAt: t.startedAt }));\n }\n\n /** 启动 recipe:同名先停旧进程(重启语义),不影响其他任务;调用方须先用 recipes() 校验名字 */\n start(recipe: string) {\n this.killOne(recipe);\n const task: Task = { recipe, child: null, state: 'running', code: null, startedAt: Date.now(), buffer: [], pending: Buffer.alloc(0) };\n this.tasks.set(recipe, task);\n this.emit({ type: 'clear', recipe }); // 广播清屏:同步清掉该任务上一轮残留日志\n this.emit({ type: 'state', recipe, state: 'running', code: null, startedAt: task.startedAt });\n const child = spawn('just', [recipe], {\n cwd: this.cwd,\n shell: true,\n env: {\n ...process.env,\n FORCE_COLOR: '1', // node 生态(chalk 等)\n // maven 检测非 tty 会关颜色;经 MAVEN_OPTS 强制开(保留用户已有值)\n MAVEN_OPTS: `${process.env.MAVEN_OPTS ?? ''} -Dstyle.color=always`.trim(),\n CI: '',\n },\n });\n task.child = child;\n // 身份守卫:同名重启后旧进程的迟到输出/退出不得污染新任务(闭包 task 是旧对象时静默丢弃)\n const isStale = () => this.tasks.get(recipe) !== task;\n const push = (d: Buffer) => {\n if (isStale()) return;\n task.pending = Buffer.concat([task.pending, d]);\n let idx: number;\n while ((idx = task.pending.indexOf(0x0a)) >= 0) { // 字节级切行:行界 0x0A 不会落在多字节字符内部\n const line = task.pending.subarray(0, idx + 1);\n task.pending = task.pending.subarray(idx + 1);\n this.pushLine(task, decodeLine(line));\n }\n // 无 \\n 的尾巴留在字节缓冲,等下个 chunk(块缓冲输出会在行中断开,不能当独立行;半个多字节字符也在此安全等待)\n };\n child.stdout?.on('data', push);\n child.stderr?.on('data', push);\n child.on('error', (err) => { this.pushLine(task, `[zdashboard] spawn error: ${err.message}\\n`); });\n child.on('exit', (code, signal) => {\n if (task.pending.length > 0 && !isStale()) { this.pushLine(task, decodeLine(task.pending) + '\\n'); } // flush 末尾无换行的残留(空 Buffer 为 truthy,须按 length 判)\n task.pending = Buffer.alloc(0);\n task.child = null;\n task.state = 'exited';\n task.code = code ?? 0;\n task.signal = signal ?? undefined; // 用户主动 stop 时 code=null+SIGTERM,与成功退出区分\n if (isStale()) return; // 迟到的旧进程退出,不打扰新任务状态\n this.emit({ type: 'state', recipe, state: 'exited', code: task.code, startedAt: task.startedAt, signal: task.signal });\n });\n }\n\n private pushLine(task: Task, line: string) {\n task.buffer.push(line);\n if (task.buffer.length > MAX_BUFFER) task.buffer.shift();\n this.emit({ type: 'log', recipe: task.recipe, text: line });\n }\n\n /** 停单个任务;不传 recipe 停全部 */\n stop(recipe?: string) {\n if (recipe === undefined) { for (const t of this.tasks.values()) this.killOne(t.recipe); }\n else this.killOne(recipe);\n }\n\n restart(recipe: string) {\n if (this.tasks.has(recipe)) this.start(recipe);\n }\n\n /** 清空某任务的日志缓冲并广播(真源清除,重连重放不会复活) */\n clear(recipe: string) {\n const task = this.tasks.get(recipe);\n if (!task) return;\n task.buffer = [];\n task.pending = Buffer.alloc(0);\n this.emit({ type: 'clear', recipe });\n }\n\n private killOne(recipe: string) {\n const task = this.tasks.get(recipe);\n const child = task?.child;\n if (child?.pid) {\n try {\n if (process.platform === 'win32') spawn('taskkill', ['/PID', String(child.pid), '/T', '/F']);\n else child.kill('SIGTERM');\n } catch { /* 已退出 */ }\n }\n if (task) { task.child = null; }\n }\n}\n","/**\n * 插件 SDK(server 侧):definePlugin 是插件接入宿主的唯一姿势。\n *\n * 内部自动完成 dashboard.register(manifest) 与 effect 清理注册,\n * 插件作者只面对 PluginContext 的七个通道;四种 cordis 手写姿势由此消亡。\n */\nimport type http from 'node:http';\nimport { json, guarded } from '../core/server.js';\nimport type { Context } from 'cordis';\nimport type { PluginManifest } from '../core/manifest.js';\n\n/** handler 返回非 undefined 值时由 SDK 包装为 json 响应;自行写响应则返回 undefined */\nexport type RouteHandler = (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n) => unknown | Promise<unknown>;\n\nexport type SseHandler = (res: http.ServerResponse) => (() => void) | void;\n\nexport interface PluginContext {\n /** manifest.mode 的只读镜像 */\n readonly mode: string;\n /** manifest.config 默认值合并 .zdev/dashboard.json 存储值(存储优先) */\n config<T extends Record<string, unknown> = Record<string, unknown>>(): T;\n /** 注册路由;handler 返回值自动 json 包装(200 + application/json) */\n route(path: string, handler: RouteHandler): void;\n /** 校验 x-stop-token 后执行 route 语义;缺/错 token 直接 403 */\n guardedRoute(path: string, handler: RouteHandler): void;\n sse(path: string, handler: SseHandler): void;\n static(prefix: string, dir: string): void;\n /** 广播到 SSE 频道 plugin:<mode>:<event>,客户端 usePluginData subscribe 消费 */\n broadcast(event: string, data?: unknown): void;\n onDispose(fn: () => void): void;\n}\n\ninterface CordisPluginApply {\n inject?: readonly string[];\n apply(ctx: Context, config: unknown): unknown;\n}\n\n/**\n * 定义内置/外部插件的 server 侧入口。\n * @param def.manifest 与 client defineWebPlugin 共享的同一份常量(SSOT)\n * @param def.setup 在 server/dashboard 服务就绪的上下文中执行\n */\nexport function definePlugin(def: {\n manifest: PluginManifest;\n setup(ctx: PluginContext): void;\n}): CordisPluginApply & { inject: readonly string[] } {\n const { manifest, setup } = def;\n\n return {\n inject: ['server', 'dashboard', 'reload'] as const,\n apply(this: void, ctx: Context) {\n const disposers: Array<() => void> = [];\n ctx.effect(() => () => {\n for (const fn of disposers.splice(0)) {\n try { fn(); } catch (e) {\n console.error(`[zdashboard] plugin ${manifest.mode} dispose error:`, e);\n }\n }\n });\n\n ctx.dashboard.register(manifest);\n\n /** json 包装语义与错误兜底;guardedRoute 不经此重注册路径 */\n const respondWith = (handler: RouteHandler) => async (req: http.IncomingMessage, res: http.ServerResponse) => {\n if (res.headersSent) return;\n try {\n const data = await handler(req, res);\n if (data !== undefined && !res.writableEnded) json(res, data);\n } catch (e) {\n console.error(`[zdashboard] plugin ${manifest.mode} route error:`, e);\n if (!res.headersSent) json(res, { error: 'internal' }, 500);\n }\n };\n\n const pctx: PluginContext = {\n mode: manifest.mode,\n config<T extends Record<string, unknown> = Record<string, unknown>>(): T {\n const schema = manifest.config ?? {};\n const stored = ctx.server.getPluginConfig(manifest.mode) ?? {};\n const defaults = Object.fromEntries(\n Object.entries(schema).map(([key, field]) => [key, field.default]),\n );\n return { ...defaults, ...stored } as T;\n },\n route(path: string, handler: RouteHandler): void {\n ctx.server.route(path, respondWith(handler));\n },\n guardedRoute(path: string, handler: RouteHandler): void {\n const token = () => ctx.server.stopToken;\n ctx.server.route(path, (req, res) => {\n if (!guarded(req, res, token())) return;\n void respondWith(handler)(req, res);\n });\n },\n sse(path: string, handler: SseHandler): void {\n ctx.server.sse(path, handler);\n },\n static(prefix: string, dir: string): void {\n ctx.server.static(prefix, dir);\n },\n broadcast(event: string, data?: unknown): void {\n ctx.reload?.broadcast(`plugin:${manifest.mode}:${event}`, data ?? '');\n },\n onDispose(fn: () => void): void {\n disposers.push(fn);\n },\n };\n\n setup(pctx);\n },\n };\n}\n","/**\n * 内置插件 root 注入壳(插件侧适配,不动 SDK 公共契约):\n *\n * SDK definePlugin 的 apply(ctx) 不向 setup 转发 cordis 插件 config,\n * 而六个内置插件都需要 cli 注入的 { root }。此壳在插件层捕获 config.root\n * 再调用 SDK 产出的 apply,setup 以第二参拿到 root。\n * 若 SDK 未来转发 config,此文件可整体删除。\n */\nimport type { Context } from 'cordis';\nimport { definePlugin, type PluginContext } from '../sdk/server.js';\nimport type { PluginManifest } from '../core/manifest.js';\n\nexport function defineBuiltin(def: {\n manifest: PluginManifest;\n setup(ctx: PluginContext, root: string): void;\n}) {\n let currentRoot = '';\n const inner = definePlugin({\n manifest: def.manifest,\n setup(pctx) { def.setup(pctx, currentRoot); },\n });\n\n return {\n inject: inner.inject,\n manifest: def.manifest, // cli 启动期死键剥离按 manifest 判定(config 声明/external)\n apply(ctx: Context, config: { root?: string }) {\n currentRoot = config?.root ?? '';\n inner.apply(ctx, config);\n },\n };\n}\n","/** just 插件单源:server definePlugin 与 web defineWebPlugin 共享 */\nimport type { PluginManifest } from '../../core/manifest.js';\nimport type { ParamSchema } from '../../sdk/shared.js';\n\nexport const manifest: PluginManifest = {\n mode: 'just',\n label: 'Just Runner',\n icon: '📜',\n description: 'Just 任务日志与执行',\n order: 50,\n};\n\n/** recipe:选中 recipe;task:活跃任务 id(与 recipe 同名空间) */\nexport const params: ParamSchema = [\n { name: 'recipe', label: 'Recipe', type: 'string', description: '选中的 recipe 名' },\n { name: 'task', label: '任务', type: 'string', description: '活跃任务 id' },\n];\n","/**\n * just server 侧:definePlugin 接入(manifest 单源)。\n *\n * JustRunner 并发核实结论(T5):src/server/just-runner.ts 已是多任务并发 runner ——\n * tasks Map 每 recipe 独立子进程/日志缓冲/状态,事件载荷自带 recipe(=taskId),\n * 无需 runner 池改造。plugin:just:log 等频道广播按事件原样携带 taskId。\n *\n * start/restart/stop/clear 走 guardedRoute(x-stop-token);\n * /__just/tasks 为任务列表提供只读路由。\n */\nimport type http from 'node:http';\nimport { JustRunner } from '../../server/just-runner.js';\nimport { readBody } from '../../core/read-body.js';\nimport { defineBuiltin } from '../builtin.js';\nimport { manifest } from './manifest.js';\nimport type { RouteHandler } from '../../sdk/server.js';\n\nexport const apply = defineBuiltin({\n manifest,\n setup(ctx, root) {\n const runner = new JustRunner(root);\n ctx.onDispose(() => runner.stop());\n\n ctx.route('/__just/recipes', async () => {\n try {\n return await runner.recipes();\n } catch {\n return [];\n }\n });\n\n ctx.route('/__just/tasks', async () => runner.list());\n\n ctx.sse('/__just/logs', (res) => {\n const unsub = runner.subscribe((ev) => {\n // 插件频道镜像:type 即事件名(log/clear/state),载荷携带 taskId(recipe)\n try { ctx.broadcast(ev.type, ev); } catch { /* reload 未就绪 */ }\n res.write(`data: ${JSON.stringify(ev)}\\n\\n`);\n });\n return unsub;\n });\n\n /** start/restart 须带合法 recipe(同名 start 即重启);stop 可带单个 recipe 或省略(停全部);clear 清日志 */\n const handleAction = async (req: http.IncomingMessage, res: http.ServerResponse, act: 'start' | 'stop' | 'restart' | 'clear') => {\n const body = await readBody(req);\n let recipe: string | undefined;\n try { recipe = JSON.parse(body || '{}').recipe; } catch { /* ignore */ }\n if (act === 'clear') {\n if (recipe) runner.clear(recipe);\n return { ok: true };\n }\n if (act !== 'stop') {\n if (!recipe) {\n res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end('{\"error\":\"no recipe\"}');\n return undefined;\n }\n const recipes = await runner.recipes();\n if (!recipes.some((r) => r.name === recipe)) {\n res.writeHead(403, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end('{\"error\":\"unknown recipe\"}');\n return undefined;\n }\n runner.start(recipe);\n } else {\n runner.stop(recipe || undefined);\n }\n return runner.list();\n };\n\n const routeAction = (name: 'start' | 'stop' | 'restart' | 'clear') => {\n ctx.guardedRoute(`/__just/${name}`, ((req, res) => handleAction(req, res, name)) satisfies RouteHandler);\n };\n routeAction('start');\n routeAction('stop');\n routeAction('restart');\n routeAction('clear');\n },\n});\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { countTasks } from './parse-tasks.js';\n\nexport interface ChangeSummary {\n name: string;\n path: string;\n total: number;\n done: number;\n hasProposal: boolean;\n hasDesign: boolean;\n inWorktree: boolean;\n}\n\nexport interface ChangeDetail extends ChangeSummary {\n proposal?: string;\n design?: string;\n tasks: string;\n dependsOn: string[];\n hasTestStrategy: boolean;\n}\n\nfunction readText(p: string): string {\n try { return fs.readFileSync(p, 'utf8'); } catch { return ''; }\n}\n\nfunction worktreeDir(root: string, name: string): string {\n return path.join(root, '.zworktree', name);\n}\n\nfunction changeDir(root: string, name: string): string {\n return path.join(root, 'openspec', 'changes', name);\n}\n\nfunction parseDependsOn(proposal: string): string[] {\n const deps: string[] = [];\n // 提取 \"## 依赖\" 节:紧跟该标题的列表行\n const m = proposal.match(/^##\\s+依赖\\s*\\n([\\s\\S]*?)(?:\\n#{1,6}\\s|\\n---\\s*\\n|$)/i);\n if (!m) return deps;\n for (const line of m[1].split('\\n')) {\n // 仅收集零缩进的一级条目(/^-/),子级列表(缩进 -)不算依赖名\n if (!/^-\\s+/.test(line)) continue;\n const name = line.replace(/^-\\s+/, '').trim();\n if (name) deps.push(name);\n }\n return deps;\n}\n\nexport function scanApplyChanges(root: string): ChangeSummary[] {\n const changesDir = path.join(root, 'openspec', 'changes');\n if (!fs.existsSync(changesDir)) return [];\n const out: ChangeSummary[] = [];\n for (const ent of fs.readdirSync(changesDir, { withFileTypes: true })) {\n if (!ent.isDirectory() || ent.name.startsWith('.') || ent.name === 'archive') continue;\n const wt = worktreeDir(root, ent.name);\n const tasks = readText(path.join(wt, 'openspec', 'changes', ent.name, 'tasks.md'));\n if (!tasks) {\n const fallback = readText(path.join(changesDir, ent.name, 'tasks.md'));\n if (fallback) {\n const { total, done } = countTasks(fallback);\n const wtChange = path.join(wt, 'openspec', 'changes', ent.name);\n const mainChange = path.join(changesDir, ent.name);\n out.push({\n name: ent.name,\n path: `openspec/changes/${ent.name}`,\n total,\n done,\n hasProposal: fs.existsSync(path.join(wtChange, 'proposal.md')) || fs.existsSync(path.join(mainChange, 'proposal.md')),\n hasDesign: fs.existsSync(path.join(wtChange, 'design.md')) || fs.existsSync(path.join(mainChange, 'design.md')),\n // worktree 目录存在即算执行中(tasks.md 可能尚未落盘)\n inWorktree: fs.existsSync(wtChange),\n });\n }\n } else {\n const { total, done } = countTasks(tasks);\n const wtChange = path.join(wt, 'openspec', 'changes', ent.name);\n const mainChange = path.join(changesDir, ent.name);\n out.push({\n name: ent.name,\n path: `openspec/changes/${ent.name}`,\n total,\n done,\n // 任一侧存在即算(详情读取是 worktree 优先、主目录兜底,列表标记保持一致)\n hasProposal: fs.existsSync(path.join(wtChange, 'proposal.md')) || fs.existsSync(path.join(mainChange, 'proposal.md')),\n hasDesign: fs.existsSync(path.join(wtChange, 'design.md')) || fs.existsSync(path.join(mainChange, 'design.md')),\n inWorktree: true,\n });\n }\n }\n out.sort((a, b) => a.name.localeCompare(b.name));\n return out;\n}\n\nexport function readApplyChange(root: string, name: string): ChangeDetail {\n const wt = worktreeDir(root, name);\n const mainChangeDir = changeDir(root, name);\n\n // 优先 worktree 内;回退主目录\n const proposalFrom = fs.existsSync(path.join(wt, 'openspec', 'changes', name, 'proposal.md'))\n ? path.join(wt, 'openspec', 'changes', name, 'proposal.md')\n : path.join(mainChangeDir, 'proposal.md');\n const designFrom = fs.existsSync(path.join(wt, 'openspec', 'changes', name, 'design.md'))\n ? path.join(wt, 'openspec', 'changes', name, 'design.md')\n : path.join(mainChangeDir, 'design.md');\n const tasksFrom = fs.existsSync(path.join(wt, 'openspec', 'changes', name, 'tasks.md'))\n ? path.join(wt, 'openspec', 'changes', name, 'tasks.md')\n : path.join(mainChangeDir, 'tasks.md');\n\n const proposal = readText(proposalFrom);\n const design = readText(designFrom);\n const tasks = readText(tasksFrom);\n const { total, done } = countTasks(tasks);\n const inWorktree = fs.existsSync(path.join(wt, 'openspec', 'changes', name));\n const dependsOn = parseDependsOn(proposal);\n const hasTestStrategy = /^##\\s+测试策略\\s*$/m.test(design);\n\n return {\n name,\n path: `openspec/changes/${name}`,\n total,\n done,\n hasProposal: !!proposal,\n hasDesign: !!design,\n inWorktree,\n proposal,\n design,\n tasks,\n dependsOn,\n hasTestStrategy,\n };\n}\n","const TASK_RE = /^\\s*-\\s*\\[([ xX])\\]\\s*(.*)$/;\n\n/** zskills/zapply 约定:任务行首的 🔧[人工] 前缀标记(人工项不计完成度) */\nconst MANUAL_PREFIX = '🔧[人工]';\n\nexport interface ParsedTask {\n text: string\n checked: boolean\n /** 行首 🔧[人工] 标记的人工条目 */\n manual?: boolean\n}\n\nexport function parseTasks(md: string): ParsedTask[] {\n // 按可选 \\r 拆行:CRLF 文件(\\r 是正则行终止符,$ 无法锚定其前)否则全量失配\n return md\n .split(/\\r?\\n/)\n .filter((l) => TASK_RE.test(l))\n .map((l) => {\n const m = l.match(TASK_RE);\n const text = (m?.[2] ?? l).trim();\n return { text, checked: m?.[1] !== ' ', manual: text.startsWith(MANUAL_PREFIX) };\n });\n}\n\nexport function countTasks(md: string): { total: number; done: number; manual: number } {\n const tasks = parseTasks(md);\n const normal = tasks.filter((t) => !t.manual);\n return {\n total: normal.length,\n done: normal.filter((t) => t.checked).length,\n manual: tasks.length - normal.length,\n };\n}\n","/**\n * 批量执行只读读取器(zapply 新约定):读 `.zdev/apply/CURRENT` 指针 →\n * `.zdev/apply/runs/<runId>/state.json` 快照。无状态投影,不持缓存——\n * state.json 由 zapply skill 外部写入,文件小、读廉价,缓存失效复杂度不值得。\n *\n * 空态语义(design.md 契约):无 CURRENT / runId 非法 → { run: null, state: null };\n * CURRENT 有效但 state.json 缺失或 JSON 损坏 → { run: { id }, state: null },前端空态引导。\n * BatchState 接口形状与旧 ApplyBatchStore(.zapply/batch-state.json 时代)完全一致。\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nexport interface BatchChange {\n name: string;\n path: string;\n status: 'pending' | 'running' | 'completed' | 'failed' | 'parked' | 'skipped';\n priority: number;\n risk: 'low' | 'medium' | 'high' | 'unknown';\n dependencies: string[];\n estimatedDuration: number;\n batchIndex: number;\n checkpoint?: {\n currentTaskIndex: number;\n totalTasks: number;\n completedTasks: number;\n currentTask: string;\n };\n error?: string;\n retryCount: number;\n startedAt?: string;\n completedAt?: string;\n}\n\nexport interface BatchLog {\n timestamp: string;\n level: 'info' | 'warn' | 'error' | 'success';\n message: string;\n changeName?: string;\n}\n\nexport interface BatchConflict {\n changeA: string;\n changeB: string;\n files: string[];\n resolution: 'serialize' | 'merge' | 'ignore';\n}\n\nexport interface BatchState {\n version: string;\n status: 'idle' | 'analyzing' | 'pending-approval' | 'running' | 'paused' | 'completed' | 'failed';\n changes: BatchChange[];\n batches: {\n index: number;\n changeNames: string[];\n status: 'pending' | 'running' | 'completed' | 'failed';\n startedAt?: string;\n completedAt?: string;\n }[];\n currentBatchIndex: number;\n parallelism: number;\n logs: BatchLog[];\n conflicts: BatchConflict[];\n createdAt: string;\n updatedAt: string;\n}\n\n/** 活动 run 指针(只读快照引用) */\nexport interface BatchRunRef {\n id: string;\n}\n\n/** GET /__apply/batch 响应形状 */\nexport interface BatchSnapshot {\n run: BatchRunRef | null;\n state: BatchState | null;\n}\n\n/** GET /__apply/batch/graph 响应形状(与旧 /__apply-batch/graph 一致) */\nexport interface BatchGraph {\n changes: Array<Pick<BatchChange, 'name' | 'status' | 'dependencies' | 'batchIndex'>>;\n batches: BatchState['batches'];\n conflicts: BatchConflict[];\n}\n\n/** runId 仅允许字母/数字/连字符(同时阻断路径穿越);与 zapply 生成约定一致 */\nconst RUN_ID_PATTERN = /^[A-Za-z0-9-]+$/;\n\n/** BatchState 必须是普通对象:数组/原始值放行会让投影层 state.changes.map 抛 TypeError */\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\nfunction readText(p: string): string | null {\n try {\n return fs.readFileSync(p, 'utf8');\n } catch {\n return null;\n }\n}\n\n/** 读活动 run 指针与状态快照;任何缺失/非法分支均降级为空态而非抛错 */\nexport function readBatchState(root: string): BatchSnapshot {\n const applyDir = path.join(root, '.zdev', 'apply');\n const raw = readText(path.join(applyDir, 'CURRENT'));\n const runId = raw?.trim() ?? '';\n if (!runId || !RUN_ID_PATTERN.test(runId)) {\n return { run: null, state: null };\n }\n const parsed: unknown = (() => {\n const text = readText(path.join(applyDir, 'runs', runId, 'state.json'));\n if (text == null) return null;\n try {\n return JSON.parse(text);\n } catch {\n return null;\n }\n })();\n if (!isPlainObject(parsed)) {\n return { run: { id: runId }, state: null };\n }\n // 形状守卫已确认普通对象;字段级结构由消费方容忍(外部写入,无 schema 校验层)\n return { run: { id: runId }, state: parsed as unknown as BatchState };\n}\n\n/** batch state → 依赖图投影;state 缺失时给三数组空投影(前端空态直接消费) */\nexport function projectGraph(state: BatchState | null): BatchGraph {\n if (!state) {\n return { changes: [], batches: [], conflicts: [] };\n }\n return {\n changes: state.changes.map((c) => ({\n name: c.name,\n status: c.status,\n dependencies: c.dependencies,\n batchIndex: c.batchIndex,\n })),\n batches: state.batches,\n conflicts: state.conflicts,\n };\n}\n\n/** 日志尾窗口:GET /__apply/batch/logs 只回最近 N 条(与旧行为一致) */\nexport const BATCH_LOGS_TAIL = 100;\n\nexport function tailLogs(state: BatchState | null): BatchLog[] {\n return (state?.logs ?? []).slice(-BATCH_LOGS_TAIL);\n}\n\n/** 读活动 run 的 plan.md 文本;缺失返回 null(路由层转 404,前端空态承接) */\nexport function readBatchPlan(root: string, runId: string): string | null {\n return readText(path.join(root, '.zdev', 'apply', 'runs', runId, 'plan.md'));\n}\n","/** apply 插件单源:server definePlugin 与 web defineWebPlugin 共享 */\nimport type { PluginManifest } from '../../core/manifest.js';\nimport type { ParamSchema } from '../../sdk/shared.js';\n\nexport const manifest: PluginManifest = {\n mode: 'apply',\n label: '执行进度',\n icon: '⚙️',\n description: 'OpenSpec 执行进度 · zapply 单 change 与批量',\n order: 40,\n};\n\n/** change:单 change 视图选中的 change 名;view:single/batch Tab;sel:批量视图选中 change 名 */\nexport const params: ParamSchema = [\n { name: 'change', label: 'Change', type: 'string', description: 'openspec change 名' },\n { name: 'view', label: '视图', type: 'string', description: 'single/batch(缺省 single)' },\n { name: 'sel', label: '选中 change', type: 'string', description: '批量驾驶舱选中的 change 名' },\n];\n","/**\n * apply server 侧:definePlugin 接入(manifest 单源)。\n * 单 change 读路由(/__apply、/__apply/change)与批量只读路由(/__apply/batch*)。\n * 批量只读:状态文件由 zapply skill 写入,dashboard 不提供任何写路由(避免双写冲突)。\n * 响应形状:错误手写 400/404 + {error},不经 SDK 500 兜底(与既有契约一致)。\n */\nimport type http from 'node:http';\nimport { scanApplyChanges, readApplyChange } from './scan.js';\nimport { readBatchState, projectGraph, tailLogs, readBatchPlan } from './batch.js';\nimport { defineBuiltin } from '../builtin.js';\nimport { manifest } from './manifest.js';\n\n/** 错误响应:写状态码 + {error: 具体信息},返回 undefined 短路 SDK json 包装 */\nfunction errorResponse(res: http.ServerResponse, status: number, msg: string): undefined {\n res.writeHead(status, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ error: msg }));\n return undefined;\n}\n\nexport const apply = defineBuiltin({\n manifest,\n setup(ctx, root) {\n ctx.route('/__apply', async () => scanApplyChanges(root));\n\n ctx.route('/__apply/change', async (req, res) => {\n const url = new URL(req.url || '', 'http://x');\n const name = url.searchParams.get('name');\n const bad = (msg: string) => errorResponse(res, 400, msg);\n if (!name) return bad('missing name');\n if (name.includes('..') || name.includes('/') || name.includes('\\\\')) return bad('invalid name');\n try {\n return readApplyChange(root, name);\n } catch (e) {\n return bad(e instanceof Error ? e.message : 'unknown error');\n }\n });\n\n // ── 批量驾驶舱只读路由(数据源 .zdev/apply/runs/<runId>/) ──\n ctx.route('/__apply/batch', async () => readBatchState(root));\n\n ctx.route('/__apply/batch/graph', async () => projectGraph(readBatchState(root).state));\n\n ctx.route('/__apply/batch/logs', async () => tailLogs(readBatchState(root).state));\n\n ctx.route('/__apply/batch/plan', async (_req, res) => {\n const snap = readBatchState(root);\n const plan = snap.run ? readBatchPlan(root, snap.run.id) : null;\n if (plan == null) return errorResponse(res, 404, 'plan not found');\n return { plan };\n });\n },\n});\n","/**\n * design server 侧:definePlugin 接入(约定化扫描)。\n * 恒扫 <root>/.zdev/design(zdesign 等 skill 统一产出目录,walkDir 跳过点目录扫根看不见);\n * 目录缺失 → emptyScan() 九组空数组。/__design/assets 响应形状(ScanResult)保持不变。\n * 另供只读代理 /__design/asset?path=<rel-to-.zdev/design>,viewers 由此加载资产(直取根路径必 404)。\n */\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport { MIME } from '../../core/server.js';\nimport { scanAssets, type ScanResult, type AssetType } from '../../server/design-assets.js';\nimport { defineBuiltin } from '../builtin.js';\nimport { manifest } from './manifest.js';\n\nconst ASSET_KEYS: AssetType[] = ['page', 'component', 'icon', 'token', 'md', 'video', 'audio', 'pdf', 'font'];\n\nfunction emptyScan(): ScanResult {\n const out = {} as ScanResult;\n for (const k of ASSET_KEYS) out[k] = [];\n return out;\n}\n\nexport const apply = defineBuiltin({\n manifest,\n setup(ctx, root) {\n ctx.route('/__design/assets', async () => {\n const designRoot = path.join(root, '.zdev', 'design');\n return fs.existsSync(designRoot) ? scanAssets(designRoot) : emptyScan();\n });\n\n // 只读资产代理:三重防御钉死任意读(字符拒绝 → join 归一化 → 前缀校验),先例 /__file-content\n ctx.route('/__design/asset', async (req, res) => {\n const rel = new URL(req.url || '/', 'http://localhost').searchParams.get('path') ?? '';\n if (!rel || rel.includes('..') || rel.includes('\\\\') || path.isAbsolute(rel)) {\n res.writeHead(400);\n res.end('bad path');\n return;\n }\n const designRoot = path.join(root, '.zdev', 'design');\n const filePath = path.join(designRoot, rel);\n if (!filePath.startsWith(designRoot + path.sep)) {\n res.writeHead(400);\n res.end('bad path');\n return;\n }\n fs.stat(filePath, (err) => {\n if (err) { res.writeHead(404); return res.end('Not found'); }\n const ct = MIME[path.extname(filePath).toLowerCase()] ?? 'application/octet-stream';\n res.writeHead(200, { 'Content-Type': ct, 'Cache-Control': 'no-cache' });\n // stat 通过后文件仍可能被删,流错误无人接会崩进程(与 core/server serveFile 同款兜底)\n const stream = fs.createReadStream(filePath);\n stream.on('error', () => { try { res.destroy(); } catch { /* 已断 */ } });\n stream.pipe(res);\n });\n });\n },\n});\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { walkDir } from './walk.js';\n\nexport type AssetType = 'page' | 'component' | 'icon' | 'token' | 'md' | 'video' | 'audio' | 'pdf' | 'font';\n\nconst PAGE_EXTS = ['.html', '.htm'];\nconst ICON_EXTS = ['.svg', '.png', '.ico', '.jpg', '.jpeg', '.gif', '.webp'];\nconst VIDEO_EXTS = ['.mp4', '.webm', '.mov', '.ogg', '.ogv'];\nconst AUDIO_EXTS = ['.mp3', '.wav', '.flac', '.aac', '.m4a'];\nconst CODE_EXTS = ['.js', '.mjs', '.cjs', '.mts', '.cts', '.ts', '.tsx', '.jsx', '.css', '.json', '.txt', '.xml', '.yml', '.yaml', '.sh', '.md'];\nconst FONT_EXTS = ['.woff', '.woff2', '.ttf', '.otf'];\nconst TOKEN_RE = /token|theme|design|color|palette|typograph/i;\n\nexport function categorize(rel: string, ext: string): AssetType | null {\n if (rel.indexOf('components/') === 0) return 'component';\n if (VIDEO_EXTS.includes(ext)) return 'video';\n if (AUDIO_EXTS.includes(ext)) return 'audio';\n if (ext === '.pdf') return 'pdf';\n if (ext === '.md') return 'md';\n if (FONT_EXTS.includes(ext)) return 'font';\n if (ICON_EXTS.includes(ext)) return 'icon';\n if (PAGE_EXTS.includes(ext)) return 'page';\n if (CODE_EXTS.includes(ext)) {\n if (TOKEN_RE.test(rel) && (ext === '.css' || ext === '.json')) return 'token';\n return null;\n }\n return null;\n}\n\nexport interface AssetFile { path: string; name: string; ext: string; type: AssetType; }\nexport type ScanResult = Record<AssetType, AssetFile[]>;\n\nexport function scanAssets(root: string, subDir = ''): ScanResult {\n const out: ScanResult = {} as ScanResult;\n const keys: AssetType[] = ['page','component','icon','token','md','video','audio','pdf','font'];\n for (const k of keys) out[k] = [];\n const SKIP = new Set(['node_modules', '.git', 'dist', 'build', 'coverage', '.next', '.cache']);\n const scanRoot = subDir ? path.join(root, subDir) : root;\n walkDir(scanRoot, { skip: SKIP, onFile: (abs, rel) => {\n const ext = path.extname(abs).toLowerCase();\n const t = categorize(rel, ext);\n if (t) out[t].push({ path: rel, name: path.basename(abs), ext, type: t });\n }});\n return out;\n}\n","/** design 插件单源:server definePlugin 与 web defineWebPlugin 共享 */\nimport type { PluginManifest } from '../../core/manifest.js';\nimport type { ParamSchema } from '../../sdk/shared.js';\n\nexport const manifest: PluginManifest = {\n mode: 'design',\n label: '设计资产',\n icon: '🎨',\n description: '设计资产分类浏览 · zdesign',\n order: 30,\n};\n\n/** type:资产类型;asset:选中资产路径;folder:资产路径过滤展示 */\nexport const params: ParamSchema = [\n { name: 'type', label: '资产类型', type: 'string', description: 'page/component/icon/token/md/video/audio/pdf/font' },\n { name: 'asset', label: '选中资产', type: 'string', description: '资产相对路径' },\n { name: 'folder', label: '当前文件夹', type: 'string', description: '限定展示的资产路径前缀' },\n];\n","/** view 插件单源:server definePlugin 与 web defineWebPlugin 共享 */\nimport type { PluginManifest } from '../../core/manifest.js';\nimport type { ParamSchema } from '../../sdk/shared.js';\n\nexport const manifest: PluginManifest = {\n mode: 'view',\n label: '项目浏览',\n icon: '👁️',\n description: 'openspec / docs / 文档预览',\n order: 20,\n};\n\n/** wt:worktree 绝对路径;file:文件相对路径;filter:树过滤词 */\nexport const params: ParamSchema = [\n { name: 'wt', label: 'Worktree 路径', type: 'string', description: 'worktree 绝对路径' },\n { name: 'file', label: '文件路径', type: 'string', description: '预览文件相对路径' },\n { name: 'filter', label: '过滤词', type: 'string', description: '文件树过滤词' },\n];\n","/**\n * view server 侧:definePlugin 接入(manifest 单源)。\n * 文件树路由 /__files 由 core/tree.ts 宿主服务提供(约定目录 ['openspec','docs'],非配置),此处仅注册 manifest。\n */\nimport { defineBuiltin } from '../builtin.js';\nimport { manifest } from './manifest.js';\n\nexport const apply = defineBuiltin({\n manifest,\n setup() { /* 路由由 core/tree.ts 承载 */ },\n});\n","/**\n * stats server 侧:definePlugin 接入(manifest 单源)。\n * /__stats/data 响应形状与迁移前保持一致。\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { execFile } from 'node:child_process';\nimport { walkDir } from '../../server/walk.js';\nimport { listWorktrees } from '../../core/worktrees.js';\nimport { defineBuiltin } from '../builtin.js';\nimport { manifest } from './manifest.js';\n\ninterface Stats {\n root: string;\n files: number;\n dirs: number;\n totalSize: number;\n byExt: { ext: string; count: number }[];\n markdown: number;\n openspec: { active: number; archived: number };\n hasJust: boolean;\n worktrees: number;\n branch?: string;\n dirty?: number;\n}\n\nconst SKIP_DIRS = new Set(['node_modules', '.git', 'dist', 'build', '.next', '.cache']);\n\nfunction execFilePromise(file: string, args: string[], opts: { cwd: string }): Promise<string> {\n return new Promise((resolve) => {\n execFile(file, args, opts, (err, stdout) => resolve(err ? '' : stdout));\n });\n}\n\nfunction scan(root: string): Stats {\n const stats: Stats = {\n root: path.basename(root),\n files: 0,\n dirs: 0,\n totalSize: 0,\n byExt: [],\n markdown: 0,\n openspec: { active: 0, archived: 0 },\n hasJust: fs.existsSync(path.join(root, 'justfile')),\n worktrees: 0,\n };\n const extMap = new Map<string, number>();\n\n const walk = (dir: string) => {\n walkDir(dir, { skip: SKIP_DIRS, onDir: () => { stats.dirs++; }, onFile: (abs) => {\n stats.files++;\n try { stats.totalSize += fs.statSync(abs).size; } catch {}\n const ext = path.extname(abs).toLowerCase() || '(无扩展名)';\n extMap.set(ext, (extMap.get(ext) ?? 0) + 1);\n if (ext === '.md' || ext === '.markdown') stats.markdown++;\n }});\n };\n walk(root);\n\n const changesDir = path.join(root, 'openspec', 'changes');\n if (fs.existsSync(changesDir)) {\n for (const ent of fs.readdirSync(changesDir, { withFileTypes: true })) {\n if (!ent.isDirectory() || ent.name.startsWith('.')) continue;\n if (ent.name === 'archive') {\n try {\n stats.openspec.archived = fs.readdirSync(path.join(changesDir, 'archive'), { withFileTypes: true })\n .filter(e => e.isDirectory() && !e.name.startsWith('.')).length;\n } catch { /* ignore */ }\n } else stats.openspec.active++;\n }\n }\n\n stats.byExt = Array.from(extMap.entries())\n .map(([ext, count]) => ({ ext, count }))\n .sort((a, b) => b.count - a.count)\n .slice(0, 10);\n return stats;\n}\n\nexport const apply = defineBuiltin({\n manifest,\n setup(ctx, root) {\n ctx.route('/__stats/data', async () => {\n const stats = scan(root);\n try {\n const wts = await listWorktrees(root);\n stats.worktrees = wts.length;\n } catch {\n stats.worktrees = 0;\n }\n try {\n const branchOut = await execFilePromise('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { cwd: root });\n stats.branch = branchOut.trim() || undefined;\n } catch { /* ignore */ }\n try {\n const statusOut = await execFilePromise('git', ['status', '--porcelain'], { cwd: root });\n stats.dirty = statusOut.trim() ? statusOut.trim().split('\\n').length : 0;\n } catch { /* ignore */ }\n return stats;\n });\n },\n});\n","/** stats 插件单源:server definePlugin 与 web defineWebPlugin 共享 */\nimport type { PluginManifest } from '../../core/manifest.js';\nimport type { ParamSchema } from '../../sdk/shared.js';\n\nexport const manifest: PluginManifest = {\n mode: 'stats',\n label: '项目统计',\n icon: '📊',\n description: '项目文件统计 · 扫描生成',\n order: 10,\n};\n\n/** card:钻取来源(worktree/dirty),view 侧读取后高亮 */\nexport const params: ParamSchema = [\n { name: 'card', label: '钻取来源', type: 'string', description: '钻取来源(worktree/dirty),view 侧读取后高亮' },\n];\n"],"mappings":"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","names":["path","fs","fileURLToPath","fs","path","fs","path","execFile","execFile","path","fs","err","fp","fs","Service","fs","path","fs","path","path","fs","execFile","apply","Service","Service","manifest","execFile","manifest","path","apply","fs","path","fs","path","fs","path","readText","manifest","apply","manifest","path","fs","path","path","manifest","apply","manifest","path","fs","manifest","apply","manifest","fs","path","execFile","manifest","execFile","path","fs","apply","manifest","__dirname","path","fileURLToPath","apply","fs"]}