zdashboard 2.2.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +309 -211
- package/dist/cli.js.map +1 -1
- package/dist/web/assets/{web-BnZ_68eg.js → CodeViewer-D8YqzmwB.js} +8 -23
- package/dist/web/assets/FilterPills-A_fz1nby.js +1 -0
- package/dist/web/assets/{katex.min-D_D1u30F.js → MdViewer-P4wmRzy_.js} +24 -24
- package/dist/web/assets/ProgressBar-B4U41etC.js +1 -0
- package/dist/web/assets/Workspace-nm0YyxF7.js +1 -0
- package/dist/web/assets/badge-C92Y2FRG.js +1 -0
- package/dist/web/assets/file-text-BHzQwEJK.js +6 -0
- package/dist/web/assets/index-ByI0Pghw.css +1 -0
- package/dist/web/assets/index-CNPKNdvp.js +111 -0
- package/dist/web/assets/{index-6FGn10zY.js → index-C_wTjWH0.js} +1 -1
- package/dist/web/assets/web-5tq6UJuk.js +2 -0
- package/dist/web/assets/web-DgYHvMu9.js +16 -0
- package/dist/web/assets/web-DhyfyLB-.js +11 -0
- package/dist/web/assets/web-JxMZZReP.js +2 -0
- package/dist/web/assets/web-ZQ0eDR1y.js +31 -0
- package/dist/web/assets/web-vTYFh6Bo.js +25 -0
- package/dist/web/assets/web-vbs6AnjC.js +26 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/dist/web/assets/MdViewer-qvXbO8IA.js +0 -1
- package/dist/web/assets/Workspace-D96dCoOA.js +0 -1
- package/dist/web/assets/git-branch-DJLd5kDE.js +0 -11
- package/dist/web/assets/index-15cLfCw4.js +0 -90
- package/dist/web/assets/index-CYqm3unP.css +0 -1
- package/dist/web/assets/web-BUNysAkV.js +0 -7
- package/dist/web/assets/web-BeuJXCg2.js +0 -26
- package/dist/web/assets/web-C-O8qmKu.js +0 -31
- package/dist/web/assets/web-CJq1r_vk.js +0 -11
- package/dist/web/assets/web-DP_CBpB2.js +0 -2
- package/dist/web/assets/web-Xpqif6fn.js +0 -32
- /package/dist/web/assets/{katex-BTcE7LSd.css → MdViewer-BTcE7LSd.css} +0 -0
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/server/detect.ts","../src/server/bugs.ts","../src/server/api/fetch.ts","../src/server/errors.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/core/tree.ts","../src/core/worktrees.ts","../src/core/manifest.ts","../src/server/just-runner.ts","../src/plugins/just/index.ts","../src/plugins/bugs/index.ts","../src/server/review-store.ts","../src/plugins/review/index.ts","../src/plugins/apply/scan.ts","../src/plugins/apply/index.ts","../src/server/design-assets.ts","../src/plugins/design/index.ts","../src/plugins/view/index.ts","../src/plugins/stats/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 { 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} 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';\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 opts: Record<string, string | boolean> = {};\n let portExplicit = false;\n for (let i = 0; i < args.length; i++) {\n const a = args[i];\n if (a.startsWith('--')) {\n const key = a.slice(2);\n const next = args[i + 1];\n if (next && !next.startsWith('--')) {\n opts[key] = next;\n i++;\n } else {\n opts[key] = true;\n }\n if (key === 'port') portExplicit = true;\n }\n }\n return {\n dir: typeof opts.dir === 'string' ? opts.dir : process.cwd(),\n port: typeof opts.port === 'string' ? Number(opts.port) : DEFAULT_PORT,\n portExplicit,\n open: !!opts.open,\n page: typeof opts.page === 'string' ? opts.page : null,\n restart: !!opts.restart,\n plugins: typeof opts.plugins === 'string' ? opts.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 // 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 // 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: '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';\nimport { BUGS_CONFIG_CANDIDATES } from './bugs.js';\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', '--unsorted'], { cwd, timeout: 5000 }, (err) => {\n resolve(!err);\n });\n if (child.killed) resolve(false);\n });\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 = BUGS_CONFIG_CANDIDATES.some((rel) => fs.existsSync(path.join(root, rel)));\n return { hasOpenspec, hasDocs, hasJust, hasBugs };\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fetchJson } from './api/fetch.js';\n\n/** .zdev/config.yaml(优先)或 .zgoal/config.yaml(回退):禅道凭据配置,扁平 key: value */\nexport const BUGS_CONFIG_CANDIDATES = ['.zdev/config.yaml', '.zgoal/config.yaml'] as const;\n\nexport interface ZgoalConfig {\n url: string;\n account: string;\n password?: string;\n token?: string;\n product: number;\n}\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\n/** 极简扁平 yaml 解析(仅 key: value 行,够 .zdev/.zgoal/config.yaml 用) */\nfunction loadConfig(root: string): ZgoalConfig | null {\n for (const rel of BUGS_CONFIG_CANDIDATES) {\n const file = path.join(root, rel);\n if (!fs.existsSync(file)) continue;\n const kv: Record<string, string> = {};\n for (const line of fs.readFileSync(file, 'utf8').split('\\n')) {\n const m = line.match(/^\\s*([A-Za-z_]\\w*)\\s*:\\s*(.+?)\\s*$/);\n if (m && !m[2].startsWith('#')) kv[m[1]] = m[2].replace(/^[\"']|[\"']$/g, '');\n }\n const product = Number(kv.product);\n if (!kv.url || !product) return null;\n return {\n url: kv.url.replace(/\\/+$/, ''),\n account: kv.account ?? '',\n password: kv.password,\n token: kv.token,\n product,\n };\n }\n return null;\n}\n\nlet tokenCache: { key: string; token: string; at: number } | null = null;\n\nasync function getToken(cfg: ZgoalConfig): Promise<string> {\n if (cfg.token) return cfg.token;\n const key = `${cfg.url}|${cfg.account}|${cfg.password ?? ''}`;\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: cfg.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\n/** 只读拉取禅道 bug 列表(GET,绝不写)。失败返回 ok:false,不抛。 */\nexport async function fetchBugs(root: string): Promise<BugsResult> {\n const cfg = loadConfig(root);\n if (!cfg) {\n const anyExists = BUGS_CONFIG_CANDIDATES.some((rel) => fs.existsSync(path.join(root, rel)));\n return {\n ok: false,\n error: anyExists\n ? '配置存在但无效(缺 url 或 product 字段)——检查 .zdev/config.yaml'\n : '.zdev/config.yaml 缺失(由 zgoal skill 创建;存量 .zgoal/config.yaml 亦可)',\n };\n }\n try {\n const token = await getToken(cfg);\n const json = await fetchJson(\n `${cfg.url}/api.php/v1/products/${cfg.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: cfg.url, total: Number(json.total ?? raw.length), bugs: raw.map((b) => normBug(b, cfg.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 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 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 { Service } from 'cordis';\nimport { clearRecord } from './instance.js';\nimport { openUrl } from './open-url.js';\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 '.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 '.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('reload',function(){location.reload();});es.onerror=function(){es.close();};}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.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 }));\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\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 serveFile(filePath: string, res: http.ServerResponse, injectHtml: boolean) {\n fs.readFile(filePath, (err, data) => {\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 let body = 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, 'Cache-Control': 'no-cache' });\n res.end(body);\n });\n }\n\n private servePrefix(url: string, 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); return res.end('Forbidden'); }\n this.serveFile(fp, 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, 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, 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, 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 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.2.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 \"@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 \"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}\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 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 } 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 exec(`${cmd} ${url}`);\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 = 150;\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 }, () => {\n if (this.timer) clearTimeout(this.timer);\n this.timer = setTimeout(() => {\n this.broadcast('reload');\n this.broadcast('files');\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';\n\nexport type NodeKind = 'file' | 'dir' | 'log';\nexport interface TreeNode {\n name: string;\n kind: NodeKind;\n path?: string; // file: 相对 root 的路径(点击预览用)\n defaultCollapsed?: boolean;\n children?: TreeNode[];\n}\n\nfunction walkFiles(absDir: string, relDir: string, depth = 0): TreeNode[] {\n if (depth > 4) return [];\n let ents: fs.Dirent[];\n try { ents = fs.readdirSync(absDir, { withFileTypes: true }); } catch { return []; }\n const nodes: TreeNode[] = [];\n for (const ent of ents) {\n if (ent.name.startsWith('.') || ent.name === 'node_modules') continue;\n const rel = relDir ? `${relDir}/${ent.name}` : ent.name;\n if (ent.isDirectory()) {\n nodes.push({ name: ent.name, kind: 'dir', children: walkFiles(path.join(absDir, ent.name), rel, depth + 1) });\n } else {\n nodes.push({ name: ent.name, kind: 'file', path: rel });\n }\n }\n nodes.sort((a, b) => (a.kind === b.kind ? a.name.localeCompare(b.name) : a.kind === 'dir' ? -1 : 1));\n return nodes;\n}\n\n/** 方案模式树形扫描:openspec 感知 + docs 聚合 + 其他兜底 */\nexport function scanTree(root: string, hasOpenspec: boolean, hasDocs: boolean): TreeNode[] {\n const tree: TreeNode[] = [];\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 active.push({ name: ent.name, kind: 'dir', children: walkFiles(path.join(changesDir, ent.name), `openspec/changes/${ent.name}`) });\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 archived.push({ name: ent.name, kind: 'dir', children: walkFiles(path.join(archiveDir, ent.name), `openspec/changes/archive/${ent.name}`) });\n }\n archived.sort((a, b) => b.name.localeCompare(a.name)); // 日期前缀倒序\n }\n if (active.length) tree.push({ name: `进行中 (${active.length})`, kind: 'dir', children: active });\n if (archived.length) tree.push({ name: 'archive', kind: 'dir', defaultCollapsed: true, children: archived });\n const specsDir = path.join(root, 'openspec', 'specs');\n if (fs.existsSync(specsDir)) {\n const specs = walkFiles(specsDir, 'openspec/specs');\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 docs = walkFiles(path.join(root, 'docs'), 'docs');\n if (docs.length) tree.push({ name: 'docs', kind: 'dir', children: docs });\n }\n const skip = new Set(['openspec', 'docs', 'node_modules', '.git', 'dist', 'test-server']); // .zworktree 以 . 开头已被点前缀过滤\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 (ent.name.startsWith('.') || 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: `其他 (${etc.length})`, kind: 'dir', children: etc });\n return tree;\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'] 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 tree = scanTree(config.root, d.hasOpenspec, d.hasDocs);\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';\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}\n\nexport class DashboardService extends Service {\n static inject = ['server'];\n private plugins = new Map<string, PluginManifest>();\n\n constructor(ctx: Context) {\n super(ctx, 'dashboard');\n this.ctx.effect(() => () => this.plugins.clear());\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\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","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';\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') => {\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\nasync function readBody(req: http.IncomingMessage): Promise<string> {\n return new Promise((resolve) => {\n let data = '';\n req.on('data', (c: string | Buffer) => { data += c; });\n req.on('end', () => resolve(data));\n req.on('error', () => resolve('')); // 客户端中断时兜底 settle,避免悬挂\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({ mode: 'bugs', label: '禅道 Bugs', icon: '🎯', description: '只读 bug 列表' });\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 result = await fetchBugs(root);\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';\n\nexport interface ReviewItem {\n id: string;\n doc?: string;\n category?: string;\n severity?: 'high' | 'medium' | 'low';\n state: ItemState;\n question: string;\n answer?: string;\n}\n\nexport interface ReviewData {\n status: ReviewStatus;\n items: ReviewItem[];\n}\n\nconst REVIEW_CANDIDATES = ['.zdev/review.yaml', 'review.yaml'] as const;\n\nexport class ReviewStore {\n private root: string;\n private file: string;\n private onChange?: () => void;\n\n constructor(root: string, onChange?: () => void) {\n this.root = root;\n this.onChange = onChange;\n // 优先 .zdev/review.yaml,回退根目录 review.yaml;都不存在则用 .zdev 路径(新建跟着新协议走)\n const existing = REVIEW_CANDIDATES.find((rel) => fs.existsSync(path.join(root, rel)));\n this.file = path.join(root, existing ?? REVIEW_CANDIDATES[0]);\n }\n\n exists(): boolean { return fs.existsSync(this.file); }\n\n read(): ReviewData {\n try {\n const parsed = YAML.parse(fs.readFileSync(this.file, 'utf8')) as ReviewData;\n if (!parsed || !Array.isArray(parsed.items)) return { status: 'draft', items: [] };\n return parsed;\n } catch {\n return { status: 'draft', items: [] };\n }\n }\n\n private write(data: ReviewData) {\n fs.mkdirSync(path.dirname(this.file), { recursive: true });\n fs.writeFileSync(this.file, YAML.stringify(data), 'utf8');\n this.onChange?.();\n }\n\n updateItem(id: string, patch: { answer?: string; state?: ItemState }): ReviewData {\n const data = this.read();\n const item = data.items.find((i) => i.id === 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.state === 'answered' && !patch.answer && !item.answer) item.answer = '';\n this.write(data);\n return data;\n }\n\n setStatus(status: ReviewStatus): ReviewData {\n const data = this.read();\n if (status === 'passed' && data.items.some((i) => i.state === 'open')) {\n throw new Error('存在未处理的评审项(open),不能通过');\n }\n data.status = status;\n this.write(data);\n return data;\n }\n\n docs(): string[] {\n try {\n const zdevDir = path.join(this.root, '.zdev');\n if (!fs.existsSync(zdevDir) || !fs.statSync(zdevDir).isDirectory()) return [];\n return fs.readdirSync(zdevDir)\n .filter((f) => /\\.(md|markdown)$/i.test(f) && fs.statSync(path.join(zdevDir, f)).isFile())\n .sort();\n } catch { return []; }\n }\n}\n","import type { Context } from 'cordis';\nimport http from 'node:http';\nimport { ReviewStore, type ItemState, type ReviewStatus } from '../../server/review-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({ mode: 'review', label: '文档评审', icon: '✅', description: 'review.yaml 逐项对齐' });\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, { answer: body.answer, state: body.state as ItemState | undefined });\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.docs()));\n });\n });\n },\n};\n\nasync function readBody(req: http.IncomingMessage): Promise<string> {\n return new Promise((resolve) => {\n let data = '';\n req.on('data', (c: string | Buffer) => { data += c; });\n req.on('end', () => resolve(data));\n });\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\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 countTasks(md: string): { total: number; done: number } {\n const all = (md.match(/^\\s*-\\s*\\[[ xX]\\]\\s*/gm) || []).length;\n const done = (md.match(/^\\s*-\\s*\\[[xX]\\]\\s*/gm) || []).length;\n return { total: all, done };\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","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 fs from 'node:fs';\nimport path from 'node:path';\n\nexport type AssetType = 'page' | 'component' | 'icon' | 'token' | 'md' | 'video' | 'audio' | 'pdf' | 'font' | 'other';\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', '.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 'other';\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): ScanResult {\n const out: ScanResult = {} as ScanResult;\n const keys: AssetType[] = ['page','component','icon','token','md','video','audio','pdf','font','other'];\n for (const k of keys) out[k] = [];\n const SKIP = new Set(['node_modules', '.git', 'dist', 'build', 'coverage', '.next', '.cache']);\n function walk(dir: string, rel: string) {\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('.') || SKIP.has(ent.name)) continue;\n const r = rel ? `${rel}/${ent.name}` : ent.name;\n if (ent.isDirectory()) { walk(path.join(dir, ent.name), r); continue; }\n const ext = path.extname(ent.name).toLowerCase();\n const t = categorize(r, ext);\n if (t) out[t].push({ path: r, name: ent.name, ext, type: t });\n }\n }\n walk(root, '');\n return out;\n}\n","import type { Context } from 'cordis';\nimport { scanAssets } from '../../server/design-assets.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: 'design', label: '设计资产', icon: '🎨', description: '页面/组件/图标/Token 分类预览' });\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 res.end(JSON.stringify(scanAssets(root)));\n });\n });\n },\n};\n","import type { Context } from 'cordis';\n\nexport const apply = {\n inject: ['dashboard'] as const,\n apply(ctx: Context) {\n ctx.dashboard.register({ mode: 'view', label: '项目浏览', icon: '👁️', description: 'openspec / docs / 文档预览' });\n },\n};\n","import type { Context } from 'cordis';\nimport fs from 'node:fs';\nimport path from 'node:path';\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 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('.') || SKIP_DIRS.has(ent.name)) continue;\n const abs = path.join(dir, ent.name);\n if (ent.isDirectory()) { stats.dirs++; walk(abs); continue; }\n stats.files++;\n try { stats.totalSize += fs.statSync(abs).size; } catch {}\n const ext = path.extname(ent.name).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"],"mappings":"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","names":["path","fs","fileURLToPath","fs","path","fs","path","fs","path","fs","path","path","fs","fp","fs","Service","fs","path","execFile","apply","Service","execFile","apply","apply","fs","path","apply","readBody","fs","path","apply","fs","path","apply","apply","fs","path","apply","__dirname","path","fileURLToPath","fs","apply"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/server/detect.ts","../src/server/bugs.ts","../src/server/api/fetch.ts","../src/server/errors.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/server/just-runner.ts","../src/core/read-body.ts","../src/plugins/just/index.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/server/design-assets.ts","../src/plugins/design/index.ts","../src/plugins/view/index.ts","../src/plugins/stats/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} 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';\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 // 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 // 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: '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';\nimport { BUGS_CONFIG_CANDIDATES } from './bugs.js';\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', '--unsorted'], { cwd, timeout: 5000 }, (err) => {\n resolve(!err);\n });\n if (child.killed) resolve(false);\n });\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 = BUGS_CONFIG_CANDIDATES.some((rel) => fs.existsSync(path.join(root, rel)));\n return { hasOpenspec, hasDocs, hasJust, hasBugs };\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport YAML from 'yaml';\nimport { fetchJson } from './api/fetch.js';\n\n/** .zdev/config.yaml(优先)或 .zgoal/config.yaml(回退):禅道凭据配置,扁平 key: value */\nexport const BUGS_CONFIG_CANDIDATES = ['.zdev/config.yaml', '.zgoal/config.yaml'] as const;\n\nexport interface ZgoalConfig {\n url: string;\n account: string;\n password?: string;\n token?: string;\n product: number;\n}\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\nfunction loadConfig(root: string): ZgoalConfig | null {\n for (const rel of BUGS_CONFIG_CANDIDATES) {\n const file = path.join(root, rel);\n if (!fs.existsSync(file)) continue;\n try {\n const kv = YAML.parse(fs.readFileSync(file, 'utf8'));\n if (!kv || typeof kv !== 'object') return null;\n const record = kv as Record<string, unknown>;\n const product = Number(record.product);\n if (!record.url || !product) return null;\n return {\n url: String(record.url).replace(/\\/+$/, ''),\n account: record.account ?? '',\n password: record.password,\n token: record.token,\n product,\n };\n } catch {\n return null;\n }\n }\n return null;\n}\n\nlet tokenCache: { key: string; token: string; at: number } | null = null;\n\nasync function getToken(cfg: ZgoalConfig): Promise<string> {\n if (cfg.token) return cfg.token;\n const key = `${cfg.url}|${cfg.account}|${cfg.password ?? ''}`;\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: cfg.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\n/** 只读拉取禅道 bug 列表(GET,绝不写)。失败返回 ok:false,不抛。 */\nexport async function fetchBugs(root: string): Promise<BugsResult> {\n const cfg = loadConfig(root);\n if (!cfg) {\n const anyExists = BUGS_CONFIG_CANDIDATES.some((rel) => fs.existsSync(path.join(root, rel)));\n return {\n ok: false,\n error: anyExists\n ? '配置存在但无效(缺 url 或 product 字段)——检查 .zdev/config.yaml'\n : '.zdev/config.yaml 缺失(由 zgoal skill 创建;存量 .zgoal/config.yaml 亦可)',\n };\n }\n try {\n const token = await getToken(cfg);\n const json = await fetchJson(\n `${cfg.url}/api.php/v1/products/${cfg.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: cfg.url, total: Number(json.total ?? raw.length), bugs: raw.map((b) => normBug(b, cfg.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 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 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 { Service } from 'cordis';\nimport { clearRecord } from './instance.js';\nimport { openUrl } from './open-url.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('reload',function(){location.reload();});es.onerror=function(){es.close();};}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\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 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); return res.end('Forbidden'); }\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.3.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 \"@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 \"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}\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 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 = 150;\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 }, () => {\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 }, 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[]): 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\n if (!map.has(current)) {\n const node: TreeNode = {\n name: part,\n kind: isLast ? 'file' : 'dir',\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\n/** 方案模式树形扫描:openspec 感知 + docs 聚合 + 其他兜底 */\nexport function scanTree(root: string, hasOpenspec: boolean, hasDocs: boolean): TreeNode[] {\n const tree: TreeNode[] = [];\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, onFile: (_, rel) => paths.push(rel ? `${relBase}/${rel}` : relBase) });\n const children = buildTree(paths).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, onFile: (_, rel) => paths.push(rel ? `${relBase}/${rel}` : relBase) });\n const children = buildTree(paths).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, onFile: (_, rel) => paths.push(`openspec/specs/${rel}`) });\n const specs = buildTree(paths).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, onFile: (_, rel) => paths.push(`docs/${rel}`) });\n const docs = buildTree(paths).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', 'test-server']); // .zworktree 以 . 开头已被点前缀过滤\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 (ent.name.startsWith('.') || 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 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('.') || 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'] 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 tree = scanTree(config.root, d.hasOpenspec, d.hasDocs);\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';\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}\n\nexport class DashboardService extends Service {\n static inject = ['server'];\n private plugins = new Map<string, PluginManifest>();\n\n constructor(ctx: Context) {\n super(ctx, 'dashboard');\n this.ctx.effect(() => () => this.plugins.clear());\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\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","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 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 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') => {\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 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({ mode: 'bugs', label: '禅道 Bugs', icon: '🎯', description: '只读 bug 列表' });\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 result = await fetchBugs(root);\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';\n\nexport interface ReviewItem {\n id: string;\n doc?: string;\n category?: string;\n severity?: 'high' | 'medium' | 'low';\n state: ItemState;\n question: string;\n answer?: string;\n}\n\nexport interface ReviewData {\n status: ReviewStatus;\n items: ReviewItem[];\n}\n\nconst REVIEW_CANDIDATES = ['.zdev/review.yaml', 'review.yaml'] as const;\n\nexport class ReviewStore {\n private root: string;\n private file: string;\n private onChange?: () => void;\n\n constructor(root: string, onChange?: () => void) {\n this.root = root;\n this.onChange = onChange;\n // 优先 .zdev/review.yaml,回退根目录 review.yaml;都不存在则用 .zdev 路径(新建跟着新协议走)\n const existing = REVIEW_CANDIDATES.find((rel) => fs.existsSync(path.join(root, rel)));\n this.file = path.join(root, existing ?? REVIEW_CANDIDATES[0]);\n }\n\n exists(): boolean { return fs.existsSync(this.file); }\n\n read(): ReviewData {\n try {\n const parsed = YAML.parse(fs.readFileSync(this.file, 'utf8')) as ReviewData;\n if (!parsed || !Array.isArray(parsed.items)) return { status: 'draft', items: [] };\n return parsed;\n } catch {\n return { status: 'draft', items: [] };\n }\n }\n\n private write(data: ReviewData) {\n fs.mkdirSync(path.dirname(this.file), { recursive: true });\n fs.writeFileSync(this.file, YAML.stringify(data), 'utf8');\n this.onChange?.();\n }\n\n updateItem(id: string, patch: { answer?: string; state?: ItemState }): ReviewData {\n const data = this.read();\n const item = data.items.find((i) => i.id === 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.state === 'answered' && !patch.answer && !item.answer) item.answer = '';\n this.write(data);\n return data;\n }\n\n setStatus(status: ReviewStatus): ReviewData {\n const data = this.read();\n if (status === 'passed' && data.items.some((i) => i.state === 'open')) {\n throw new Error('存在未处理的评审项(open),不能通过');\n }\n data.status = status;\n this.write(data);\n return data;\n }\n\n docs(): string[] {\n try {\n const zdevDir = path.join(this.root, '.zdev');\n if (!fs.existsSync(zdevDir) || !fs.statSync(zdevDir).isDirectory()) return [];\n return fs.readdirSync(zdevDir)\n .filter((f) => /\\.(md|markdown)$/i.test(f) && fs.statSync(path.join(zdevDir, f)).isFile())\n .sort();\n } catch { return []; }\n }\n}\n","import type { Context } from 'cordis';\nimport http from 'node:http';\nimport { ReviewStore, type ItemState, type ReviewStatus } 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: 'review.yaml 逐项对齐' });\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, { answer: body.answer, state: body.state as ItemState | undefined });\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.docs()));\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 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' | 'other';\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 'other';\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): ScanResult {\n const out: ScanResult = {} as ScanResult;\n const keys: AssetType[] = ['page','component','icon','token','md','video','audio','pdf','font','other'];\n for (const k of keys) out[k] = [];\n const SKIP = new Set(['node_modules', '.git', 'dist', 'build', 'coverage', '.next', '.cache']);\n walkDir(root, { 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';\nimport { scanAssets } from '../../server/design-assets.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: 'design', label: '设计资产', icon: '🎨', description: '页面/组件/图标/Token 分类预览' });\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 res.end(JSON.stringify(scanAssets(root)));\n });\n });\n },\n};\n","import type { Context } from 'cordis';\n\nexport const apply = {\n inject: ['dashboard'] as const,\n apply(ctx: Context) {\n ctx.dashboard.register({ mode: 'view', label: '项目浏览', icon: '👁️', description: 'openspec / docs / 文档预览' });\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"],"mappings":"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","names":["path","fs","fileURLToPath","fs","path","fs","path","fs","path","fs","path","execFile","execFile","path","fs","err","fp","fs","Service","fs","path","fs","path","fs","path","execFile","apply","Service","execFile","apply","apply","fs","path","YAML","apply","fs","path","fs","path","apply","path","path","apply","apply","fs","path","path","fs","apply","__dirname","path","fileURLToPath","fs","apply"]}
|