@surething/cockpit 1.0.247 → 1.0.248

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/.next-prod/BUILD_ID +1 -1
  2. package/.next-prod/app-path-routes-manifest.json +2 -2
  3. package/.next-prod/build-manifest.json +2 -2
  4. package/.next-prod/prerender-manifest.json +3 -3
  5. package/.next-prod/server/app/_global-error/page_client-reference-manifest.js +1 -1
  6. package/.next-prod/server/app/_global-error.html +1 -1
  7. package/.next-prod/server/app/_global-error.rsc +1 -1
  8. package/.next-prod/server/app/_global-error.segments/_full.segment.rsc +1 -1
  9. package/.next-prod/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  10. package/.next-prod/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  11. package/.next-prod/server/app/_global-error.segments/_head.segment.rsc +1 -1
  12. package/.next-prod/server/app/_global-error.segments/_index.segment.rsc +1 -1
  13. package/.next-prod/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  14. package/.next-prod/server/app/_not-found/page_client-reference-manifest.js +1 -1
  15. package/.next-prod/server/app/_not-found.html +2 -2
  16. package/.next-prod/server/app/_not-found.rsc +2 -2
  17. package/.next-prod/server/app/_not-found.segments/_full.segment.rsc +2 -2
  18. package/.next-prod/server/app/_not-found.segments/_head.segment.rsc +1 -1
  19. package/.next-prod/server/app/_not-found.segments/_index.segment.rsc +2 -2
  20. package/.next-prod/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  21. package/.next-prod/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  22. package/.next-prod/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  23. package/.next-prod/server/app/m/page_client-reference-manifest.js +1 -1
  24. package/.next-prod/server/app/page_client-reference-manifest.js +1 -1
  25. package/.next-prod/server/app/project/page_client-reference-manifest.js +1 -1
  26. package/.next-prod/server/app/review/[id]/page_client-reference-manifest.js +1 -1
  27. package/.next-prod/server/app-paths-manifest.json +2 -2
  28. package/.next-prod/server/chunks/4848.js +68 -13
  29. package/.next-prod/server/chunks/6038.js +1 -1
  30. package/.next-prod/server/chunks/9658.js +3 -3
  31. package/.next-prod/server/middleware-build-manifest.js +1 -1
  32. package/.next-prod/server/pages/404.html +2 -2
  33. package/.next-prod/server/pages/500.html +1 -1
  34. package/.next-prod/server/server-reference-manifest.json +1 -1
  35. package/.next-prod/static/chunks/{6784-59c6418d36cf5a13.js → 6784-4a7131705a94a485.js} +0 -0
  36. package/.next-prod/static/chunks/{8010-75928e3e1e85c88e.js → 8010-feeef81a0401286a.js} +1 -1
  37. package/.next-prod/trace +14 -14
  38. package/.next-prod/trace-build +1 -1
  39. package/dist/scheduledTasks.mjs +70 -37
  40. package/package.json +1 -1
  41. /package/.next-prod/static/{CQYkjM0s2vhvvRjWjJ865 → 16e9CEOqCbMBCySF862ss}/_buildManifest.js +0 -0
  42. /package/.next-prod/static/{CQYkjM0s2vhvvRjWjJ865 → 16e9CEOqCbMBCySF862ss}/_ssgManifest.js +0 -0
@@ -405,12 +405,27 @@ argument-hint: "描述你想要的小应用"
405
405
  # 生成 Cockpit 小应用
406
406
 
407
407
  一个能取/改数据的小应用:预览时注入了全局 \`window.cockpit\` SDK —— 本质就是 Bash
408
- 工具暴露给页面,页面按钮能 \`curl\`、读写文件、跑脚本。用 \`Write\` 生成文件。
408
+ 工具暴露给页面,页面按钮能 \`curl\`、读写文件、跑脚本。
409
409
 
410
410
  **默认用 React 写**(下面的本地零构建栈,productized、AI 最熟,适合有状态 / 多视图 /
411
411
  表单);只有**极简单的单视图、或纯静态一次性页**才退回单文件内联 HTML。两种模式共用下面
412
412
  这套契约。
413
413
 
414
+ ## 流程:先对齐,确认后再写(重要)
415
+
416
+ **别一上来就写文件**,分三步:
417
+
418
+ 1. **对齐需求** —— 先复述你对这个小应用的理解(做什么、用 React 还是单文件、数据从哪来、
419
+ 关键功能与交互)。仅当需求有歧义或存在多种合理解读时才回问;已经清楚就直接给一段简短
420
+ 的理解摘要,不必逐条追问。
421
+ 2. **告知存放目录** —— 按下面「存放位置」规则定出 \`<目录>/<name>/\`,明确告诉用户准备存哪、
422
+ 叫什么名;用户可否决或改目录 / 改名。
423
+ 3. **确认后才写** —— 等用户明确同意(确认 / 开始 / 写吧 / go 等任意肯定表示)再 \`Write\`
424
+ 落盘。确认之前只讨论、不写文件。
425
+
426
+ 即便用户在 \`/html\` 后已经把需求和目录都写清楚了,也要先停一轮,给出「理解 + 目录 + 一句
427
+ 『确认就开始写?』」等待确认——但这一轮要**轻量**,别反复追问。
428
+
414
429
  ## 契约:window.cockpit(两模式共用,只此一处)
415
430
 
416
431
  页面加载时 SDK 已就绪,无需引入任何库:
@@ -536,7 +551,17 @@ function App() {
536
551
  </script>
537
552
  \`\`\`
538
553
 
539
- 生成后用 \`Write\` 写成 \`.html\`,用户点击即可预览并交互。`,en:`---
554
+ ## 存放位置
555
+
556
+ 一个 app 的所有文件(\`index.html\` + \`app.jsx\` + \`api.mjs\` …)放进同一个 \`<name>/\`
557
+ 子目录。\`<name>\` **一律由你按需求起名**(短横线小写,与 \`cockpit-name\` 一致),用户只
558
+ 描述需求、不负责起名。目标目录按下面规则确定:
559
+
560
+ - 用户在需求里给了目录 → 存到 \`<用户给的目录>/<name>/\`
561
+ - 用户没给 → 存到**当前聊天工作目录**(本次会话的 cwd)下的 \`<name>/\`
562
+
563
+ 别把文件散落到别处或自造 \`.cockpit-apps\` 之类目录。这个目录就是上面「流程」第 2 步要告知用户的;**用户确认后**再用 \`Write\` 写出,用户点击
564
+ 即可预览并交互。`,en:`---
540
565
  name: html
541
566
  description: "Generate an interactive small app with the built-in cockpit bash SDK to fetch/update data"
542
567
  argument-hint: "describe the small app you want"
@@ -546,13 +571,32 @@ argument-hint: "describe the small app you want"
546
571
 
547
572
  A small app that can fetch/update data: the preview injects a global
548
573
  \`window.cockpit\` SDK — essentially the Bash tool exposed to the page, so buttons can
549
- \`curl\`, read/write files, and run scripts. Use \`Write\` to create the file.
574
+ \`curl\`, read/write files, and run scripts.
550
575
 
551
576
  **Default to React** (the local zero-build stack below — productized, most AI-familiar,
552
577
  ideal for stateful / multi-view / form apps); fall back to single-file inline HTML only
553
578
  for a **trivial single view or a purely static one-off**. Both modes share the one
554
579
  contract below.
555
580
 
581
+ ## Flow: align first, write only after confirmation (important)
582
+
583
+ **Don't write files up front.** Three steps:
584
+
585
+ 1. **Align on the requirement** — restate your understanding of the app (what it does,
586
+ React vs single-file, where data comes from, key features/interactions). Ask back only
587
+ when the requirement is ambiguous or has several reasonable readings; if it's already
588
+ clear, just give a short understanding summary — don't interrogate.
589
+ 2. **Tell the storage directory** — resolve \`<dir>/<name>/\` per the "Where to store" rules
590
+ below and tell the user exactly where it'll go and what it's named; the user may reject
591
+ or change the directory / name.
592
+ 3. **Write only after confirmation** — \`Write\` the files only once the user clearly agrees
593
+ (confirm / start / go / "write it" — any affirmative). Until then, only discuss — write
594
+ nothing to disk.
595
+
596
+ Even if the user already spelled out the requirement and directory in the \`/html\` call,
597
+ still stop once to present "understanding + directory + a 'shall I start writing?'" and
598
+ wait — but keep this round **lightweight**, don't re-interrogate.
599
+
556
600
  ## Contract: window.cockpit (shared by both modes, stated once)
557
601
 
558
602
  The SDK is ready on load — no library to import:
@@ -684,7 +728,18 @@ Background (live log):
684
728
  </script>
685
729
  \`\`\`
686
730
 
687
- Write the result to a \`.html\` file with \`Write\`; the user clicks it to preview and interact.`},cg:{zh:`---
731
+ ## Where to store it
732
+
733
+ Put all of an app's files (\`index.html\` + \`app.jsx\` + \`api.mjs\` …) in a single
734
+ \`<name>/\` subdirectory. **You always pick \`<name>\`** from the request (lowercase
735
+ kebab-case, matching \`cockpit-name\`) — the user only describes the app, they don't
736
+ name it. Resolve the target directory as follows:
737
+
738
+ - The user gave a directory in the request → store under \`<the given directory>/<name>/\`.
739
+ - The user gave none → store under the **current chat working directory** (this session's cwd), i.e. \`<cwd>/<name>/\`.
740
+
741
+ Don't scatter files elsewhere or invent a directory like \`.cockpit-apps\`. This directory is what step 2 of the flow above tells the user; **after the user confirms**,
742
+ \`Write\` the files; the user clicks to preview and interact.`},cg:{zh:`---
688
743
  name: cg
689
744
  description: "进入项目图谱(CodeGraph)探索模式:用预建的符号 + 调用图 + git 协同视图(search/callers/callees/impact/file/coedit + context/related/risk/affected)追代码、评估影响范围,返回坐标而非源码。"
690
745
  ---
@@ -854,7 +909,7 @@ curl -fsS "{{BASE_URL}}/api/projectGraph/affected?cwd=$PWD&files=<a.ts,b.ts>&dep
854
909
  - \`degraded: true\` means results are still usable but lower precision; \`degradedReason\` gives the cause (\`analytics-warming\` = backing index warming up; \`coedit-unavailable\` = git history signal unavailable, fall back to manually picking tests)
855
910
  - **risk / related responses already include a \`coedit\` field** (target file's coedit history) — DO NOT issue a separate /coedit request for the same file
856
911
  - If related returns \`ambiguousIn\`, the same qname exists in multiple files — retry with \`&filePath=<rel>\`
857
- - These three endpoints also return coordinates only; fetch source with Read`,labelZh:"探索问题:",labelEn:"Exploration: "},cc:{zh:'---\nname: cc\ndescription: "进入 Cockpit CLI(cock/cockpit 子命令)操作模式:通过瘦客户端驱动本机 server 的 terminal/browser 气泡与 codegraph 等子命令。"\n---\n\n进入 Cockpit CLI 操作模式\n\nCockpit CLI 是本机 Cockpit server 的瘦客户端:每个调用都把请求转发到正在跑的 server,复用其索引、缓存、git 视图等。\n\nCLI 入口选择(**默认 = prod**):\n\n- 默认用 **`cockpit`**(prod,端口 3457)—— 没有明确信号就用这个\n- 仅在用户**明确给出 dev 信号**时才换成 `cockpit-dev`(dev,端口 3456),两种信号:\n 1. 任务文本里直接写了 `cockpit-dev ...`\n 2. `/cc` 后第一个词是 `dev`(例:`/cc dev terminal bmfb 看错误`)\n- `cock` 是 `cockpit` 的 prod 短别名,行为一致;dev 无对应短别名\n\n下文统一写 `cockpit`,仅在上述 dev 信号触发时替换为 `cockpit-dev`。\n\n## 子命令\n\n| 子命令 | 用途 |\n|---|---|\n| (无) / `<path>` | 启动 server,打开项目 |\n| `browser <id> <action>` | 控制浏览器气泡 |\n| `terminal <id> [<action>]` | 只读观察终端 ring buffer |\n| `codegraph <subcmd>` | 项目代码图(search/callers/callees/impact/file/coedit/context/related/risk/affected) |\n| `update` | 升级到最新 npm 版本 |\n\n## 典型用法模式\n\nUI 上的 terminal / browser 气泡带一个 4 字符短 id(如 `bmfb` / `mpcw`)。用户输入 `/cc` 后通常跟一段 `cockpit <subcmd> <id> <要做的事>` 描述,例如:\n\n```\n/cc cockpit terminal bmfb 看一下最近的错误日志 ← 默认 prod (cockpit)\n/cc cockpit browser mpcw 截图当前页面 ← 默认 prod (cockpit)\n/cc cockpit codegraph risk searchIndex 评估改这个的影响 ← 默认 prod (cockpit)\n/cc dev terminal aqou 看一下错误 ← dev 信号 #2 → 用 cockpit-dev\n/cc cockpit-dev codegraph file packages/... ← dev 信号 #1 → 用 cockpit-dev\n```\n\n收到这类输入时:\n1. 把 `<id>` 当作具体的气泡标识传给对应子命令\n2. 先跑 `cockpit <subcmd> <id>`(或 `<subcmd> --help`)看支持的 action\n3. 选合适的 action 执行用户任务\n\n## 先看气泡清单(不知道用哪个 id 时)\n\n当用户用 "alloydb 那个 terminal" / "看一下后台" 这种**语义指代**而非具体 id 时,先用 `connection list` 拿到当前项目所有气泡 + 用户起的 title:\n\n```bash\ncockpit connection list --cwd $PWD\n```\n\n输出每行:`<type> <shortId> <title> <projectCwd> <command-or-url>`(TAB 分隔)。按 title 匹配用户的语义指代挑出 `<shortId>`,再走「典型用法模式」。title 没设的气泡显示为 `(none)`,此时可结合 `<command>` 字段(terminal 的命令字符串 / browser 的 URL)区分。\n\n## 获取详细用法\n\n每个子命令的 `--help` 是 canonical reference,**包含 usage / flags / 输出格式 / exit code / 示例**。先看 help 再用:\n\n```bash\ncockpit --help\ncockpit <subcommand> --help\ncockpit codegraph <subsubcmd> --help\n```',en:"---\nname: cc\ndescription: \"Enter Cockpit CLI (cock/cockpit subcommands) operation mode: drive the running server's terminal/browser bubbles and codegraph subcommands through the thin local client.\"\n---\n\nEnter Cockpit CLI operation mode.\n\nThe Cockpit CLI is a thin local client over the running Cockpit server: each invocation forwards to the server and reuses its CodeIndex / caches / git views.\n\nCLI entry point selection (**default = prod**):\n\n- Default: **`cockpit`** (prod, port 3457) — use this when no explicit dev signal is given.\n- Switch to `cockpit-dev` (dev, port 3456) ONLY when the user explicitly signals dev mode, via one of:\n 1. They write `cockpit-dev ...` directly in the task text.\n 2. The first word after `/cc` is `dev` (e.g. `/cc dev terminal bmfb check the errors`).\n- `cock` is the prod-only short alias of `cockpit`; behaviour is identical. There is no short alias for dev.\n\nExamples below use `cockpit`; only swap in `cockpit-dev` when one of the two dev signals above is present.\n\n## Subcommands\n\n| Subcommand | Purpose |\n|---|---|\n| (none) / `<path>` | Start server, open project |\n| `browser <id> <action>` | Drive browser bubbles |\n| `terminal <id> [<action>]` | Read-only observation of a terminal ring buffer |\n| `codegraph <subcmd>` | Project code graph (search/callers/callees/impact/file/coedit/context/related/risk/affected) |\n| `update` | Upgrade to latest npm version |\n\n## Typical usage pattern\n\nTerminal / browser bubbles in the UI carry a 4-char short id (e.g. `bmfb` / `mpcw`). After `/cc` users typically follow with `cockpit <subcmd> <id> <what to do>`, e.g.:\n\n```\n/cc cockpit terminal bmfb look at the recent error logs ← default prod (cockpit)\n/cc cockpit browser mpcw take a screenshot of the current page ← default prod (cockpit)\n/cc cockpit codegraph risk searchIndex assess the impact ← default prod (cockpit)\n/cc dev terminal aqou check the errors ← dev signal #2 → use cockpit-dev\n/cc cockpit-dev codegraph file packages/... ← dev signal #1 → use cockpit-dev\n```\n\nWhen you receive such input:\n1. Treat `<id>` as the concrete bubble identifier and pass it to the subcommand\n2. Run `cockpit <subcmd> <id>` (or `<subcmd> --help`) first to see supported actions\n3. Pick the right action to fulfil the user's task\n\n## When you don't know which id to use — list bubbles first\n\nIf the user refers to a bubble semantically (\"the alloydb proxy terminal\" / \"the admin page\") rather than by id, list every bubble in the current project — each one carries any user-set title:\n\n```bash\ncockpit connection list --cwd $PWD\n```\n\nOutput rows are TAB-separated: `<type> <shortId> <title> <projectCwd> <command-or-url>`. Match the user's reference against the title, take the `<shortId>`, then proceed with the typical usage pattern. Unnamed bubbles show `(none)` for title — fall back to the `<command>` column (terminal's command string / browser's URL) to disambiguate.\n\n## Getting detailed usage\n\nEvery subcommand's `--help` is the canonical reference — **it includes usage, flags, output format, exit codes, and examples.** Read it first:\n\n```bash\ncockpit --help\ncockpit <subcommand> --help\ncockpit codegraph <subsubcmd> --help\n```",labelZh:"任务:",labelEn:"Task: "},cr:{zh:`---
912
+ - These three endpoints also return coordinates only; fetch source with Read`},cc:{zh:'---\nname: cc\ndescription: "进入 Cockpit CLI(cock/cockpit 子命令)操作模式:通过瘦客户端驱动本机 server 的 terminal/browser 气泡与 codegraph 等子命令。"\n---\n\n进入 Cockpit CLI 操作模式\n\nCockpit CLI 是本机 Cockpit server 的瘦客户端:每个调用都把请求转发到正在跑的 server,复用其索引、缓存、git 视图等。\n\nCLI 入口选择(**默认 = prod**):\n\n- 默认用 **`cockpit`**(prod,端口 3457)—— 没有明确信号就用这个\n- 仅在用户**明确给出 dev 信号**时才换成 `cockpit-dev`(dev,端口 3456),两种信号:\n 1. 任务文本里直接写了 `cockpit-dev ...`\n 2. `/cc` 后第一个词是 `dev`(例:`/cc dev terminal bmfb 看错误`)\n- `cock` 是 `cockpit` 的 prod 短别名,行为一致;dev 无对应短别名\n\n下文统一写 `cockpit`,仅在上述 dev 信号触发时替换为 `cockpit-dev`。\n\n## 子命令\n\n| 子命令 | 用途 |\n|---|---|\n| (无) / `<path>` | 启动 server,打开项目 |\n| `browser <id> <action>` | 控制浏览器气泡 |\n| `terminal <id> [<action>]` | 只读观察终端 ring buffer |\n| `codegraph <subcmd>` | 项目代码图(search/callers/callees/impact/file/coedit/context/related/risk/affected) |\n| `update` | 升级到最新 npm 版本 |\n\n## 典型用法模式\n\nUI 上的 terminal / browser 气泡带一个 4 字符短 id(如 `bmfb` / `mpcw`)。用户输入 `/cc` 后通常跟一段 `cockpit <subcmd> <id> <要做的事>` 描述,例如:\n\n```\n/cc cockpit terminal bmfb 看一下最近的错误日志 ← 默认 prod (cockpit)\n/cc cockpit browser mpcw 截图当前页面 ← 默认 prod (cockpit)\n/cc cockpit codegraph risk searchIndex 评估改这个的影响 ← 默认 prod (cockpit)\n/cc dev terminal aqou 看一下错误 ← dev 信号 #2 → 用 cockpit-dev\n/cc cockpit-dev codegraph file packages/... ← dev 信号 #1 → 用 cockpit-dev\n```\n\n收到这类输入时:\n1. 把 `<id>` 当作具体的气泡标识传给对应子命令\n2. 先跑 `cockpit <subcmd> <id>`(或 `<subcmd> --help`)看支持的 action\n3. 选合适的 action 执行用户任务\n\n## 先看气泡清单(不知道用哪个 id 时)\n\n当用户用 "alloydb 那个 terminal" / "看一下后台" 这种**语义指代**而非具体 id 时,先用 `connection list` 拿到当前项目所有气泡 + 用户起的 title:\n\n```bash\ncockpit connection list --cwd $PWD\n```\n\n输出每行:`<type> <shortId> <title> <projectCwd> <command-or-url>`(TAB 分隔)。按 title 匹配用户的语义指代挑出 `<shortId>`,再走「典型用法模式」。title 没设的气泡显示为 `(none)`,此时可结合 `<command>` 字段(terminal 的命令字符串 / browser 的 URL)区分。\n\n## 获取详细用法\n\n每个子命令的 `--help` 是 canonical reference,**包含 usage / flags / 输出格式 / exit code / 示例**。先看 help 再用:\n\n```bash\ncockpit --help\ncockpit <subcommand> --help\ncockpit codegraph <subsubcmd> --help\n```',en:"---\nname: cc\ndescription: \"Enter Cockpit CLI (cock/cockpit subcommands) operation mode: drive the running server's terminal/browser bubbles and codegraph subcommands through the thin local client.\"\n---\n\nEnter Cockpit CLI operation mode.\n\nThe Cockpit CLI is a thin local client over the running Cockpit server: each invocation forwards to the server and reuses its CodeIndex / caches / git views.\n\nCLI entry point selection (**default = prod**):\n\n- Default: **`cockpit`** (prod, port 3457) — use this when no explicit dev signal is given.\n- Switch to `cockpit-dev` (dev, port 3456) ONLY when the user explicitly signals dev mode, via one of:\n 1. They write `cockpit-dev ...` directly in the task text.\n 2. The first word after `/cc` is `dev` (e.g. `/cc dev terminal bmfb check the errors`).\n- `cock` is the prod-only short alias of `cockpit`; behaviour is identical. There is no short alias for dev.\n\nExamples below use `cockpit`; only swap in `cockpit-dev` when one of the two dev signals above is present.\n\n## Subcommands\n\n| Subcommand | Purpose |\n|---|---|\n| (none) / `<path>` | Start server, open project |\n| `browser <id> <action>` | Drive browser bubbles |\n| `terminal <id> [<action>]` | Read-only observation of a terminal ring buffer |\n| `codegraph <subcmd>` | Project code graph (search/callers/callees/impact/file/coedit/context/related/risk/affected) |\n| `update` | Upgrade to latest npm version |\n\n## Typical usage pattern\n\nTerminal / browser bubbles in the UI carry a 4-char short id (e.g. `bmfb` / `mpcw`). After `/cc` users typically follow with `cockpit <subcmd> <id> <what to do>`, e.g.:\n\n```\n/cc cockpit terminal bmfb look at the recent error logs ← default prod (cockpit)\n/cc cockpit browser mpcw take a screenshot of the current page ← default prod (cockpit)\n/cc cockpit codegraph risk searchIndex assess the impact ← default prod (cockpit)\n/cc dev terminal aqou check the errors ← dev signal #2 → use cockpit-dev\n/cc cockpit-dev codegraph file packages/... ← dev signal #1 → use cockpit-dev\n```\n\nWhen you receive such input:\n1. Treat `<id>` as the concrete bubble identifier and pass it to the subcommand\n2. Run `cockpit <subcmd> <id>` (or `<subcmd> --help`) first to see supported actions\n3. Pick the right action to fulfil the user's task\n\n## When you don't know which id to use — list bubbles first\n\nIf the user refers to a bubble semantically (\"the alloydb proxy terminal\" / \"the admin page\") rather than by id, list every bubble in the current project — each one carries any user-set title:\n\n```bash\ncockpit connection list --cwd $PWD\n```\n\nOutput rows are TAB-separated: `<type> <shortId> <title> <projectCwd> <command-or-url>`. Match the user's reference against the title, take the `<shortId>`, then proceed with the typical usage pattern. Unnamed bubbles show `(none)` for title — fall back to the `<command>` column (terminal's command string / browser's URL) to disambiguate.\n\n## Getting detailed usage\n\nEvery subcommand's `--help` is the canonical reference — **it includes usage, flags, output format, exit codes, and examples.** Read it first:\n\n```bash\ncockpit --help\ncockpit <subcommand> --help\ncockpit codegraph <subsubcmd> --help\n```"},cr:{zh:`---
858
913
  name: cr
859
914
  description: "完整代码审查:静态 + 动态一遍做完。静态三角校验(拿改动和 意图 / 输入域 / 周遭 三个参照交叉定位)广扫全部改动;碰状态 / 时序 / 并发的切片再走动态推演管线(状态图 + 时间线 → 6 类动态风险)。自包含。"
860
915
  ---
@@ -1271,7 +1326,7 @@ Output confirmation: branch name, current HEAD commit, and sync status against o
1271
1326
 
1272
1327
  - **Start from the latest**: always base on \`origin/main\`, never on a possibly stale local main.
1273
1328
  - **Never lose changes**: confirm before any operation that could lose the user's work.
1274
- - **Verify right after cutting**: use rev-list to confirm actual sync; never assume.`,labelZh:"需求:",labelEn:"Intent: "},skillify:{zh:`---
1329
+ - **Verify right after cutting**: use rev-list to confirm actual sync; never assume.`},skillify:{zh:`---
1275
1330
  name: skillify
1276
1331
  description: "把一次成功的处理流程 / 调研方式 / 工具组合 / 习惯,沉淀成一个可复用的 Skill。先分析历史会话有没有值得提取的知识,再提炼,最后按指定目录保存。"
1277
1332
  argument-hint: "[放置目录] [要 skillify 的对象]"
@@ -1290,7 +1345,7 @@ argument-hint: "[放置目录] [要 skillify 的对象]"
1290
1345
 
1291
1346
  ## 参数(都可选,保存时才用)
1292
1347
 
1293
- - **尾随文本**(\`目标:\`后面那段)= 想 skillify 的对象 / 线索;不给就从最近上下文里自动提炼。
1348
+ - **尾随文本**(\`/skillify\` 后面那段)= 想 skillify 的对象 / 线索;不给就从最近上下文里自动提炼。
1294
1349
  - **放置目录 \`<skills-dir>\`** = skill 落盘位置,canonical source 写到 \`<skills-dir>/<slug>/SKILL.md\`。**到"保存"那一步才需要**;用户没给再问,不要在分析前就先问。
1295
1350
 
1296
1351
  ## 第 1 步:分析 —— 有没有值得沉淀的知识(扫描 → 闸门)
@@ -1475,7 +1530,7 @@ Core goal: **turn a one-time success into a stable procedure, not copy a transie
1475
1530
 
1476
1531
  ## Arguments (all optional; used only at save time)
1477
1532
 
1478
- - **Trailing text** (after \`Target: \`) = the object / lead to skillify; if omitted, distil from recent context.
1533
+ - **Trailing text** (after \`/skillify\`) = the object / lead to skillify; if omitted, distil from recent context.
1479
1534
  - **Placement directory \`<skills-dir>\`** = where the skill lands; the canonical source goes to \`<skills-dir>/<slug>/SKILL.md\`. **Only needed at the "save" step**; ask only if the user hasn't provided it — never ask before analysis.
1480
1535
 
1481
1536
  ## Step 1: Analyze — is there knowledge worth capturing (scan → gate)
@@ -1641,11 +1696,11 @@ When done, briefly report: skill slug, source path (\`<skills-dir>/<slug>/SKILL.
1641
1696
  - The user wants a **captured capability**, not a copied conversation.
1642
1697
  - **Analysis first**: decide whether there's knowledge worth capturing; if not, stop — don't force it, and don't ask for a directory early.
1643
1698
  - The canonical source always lives in \`<skills-dir>/<slug>/\`; even a single-file skill gets its own subdirectory.
1644
- - Distinguish fact / hypothesis / to-be-confirmed; don't hardcode a solution too early.`,labelZh:"目标:",labelEn:"Target: "}},h=(0,e.join)(f.Kv,"skills"),i=/^\s*([/@])([a-zA-Z][a-zA-Z0-9-]*)(?:\s+|$)/;function j(a,b="en",c){let l,m=b.startsWith("zh")?"zh":"en",n=function(){try{let a=JSON.parse((0,d.readFileSync)(f.GB,"utf-8")),b=[];for(let c of a.skills??[]){let a=function(a){try{let b=(0,d.readFileSync)(a,"utf-8"),c=b.match(/^---\r?\n([\s\S]*?)\r?\n---/),e=(c?c[1]:b).match(/^name:\s*["']?([^"'\n]+?)["']?\s*$/m);return e?e[1].trim():null}catch{return null}}(c.path);a&&b.push({name:a,path:c.path})}return b}catch{return[]}}(),o=a.split("\n"),p=[];if(o.forEach((a,b)=>{let c,d=a.match(i);d&&(g[c=d[2]]||n.some(a=>a.name===c))&&p.push({i:b,marker:d[1],cmd:d[2],rest:a.slice(d[0].length)})}),0===p.length)return a;let q=o.slice(0,p[0].i).join("\n").trim(),r=p.map((a,b)=>{let c=b+1<p.length?p[b+1].i:o.length,d=[a.rest,...o.slice(a.i+1,c)].join("\n").trim();return{marker:a.marker,cmd:a.cmd,body:d}}),s=(l=process.env.COCKPIT_PORT||process.env.PORT||"3457",`http://localhost:${l}`),t=r.map(a=>(function(a,b,c,f){var i,j;let l,m=f.find(b=>b.name===a.cmd);if(m)return{marker:a.marker,body:a.body,label:"",pointer:k(m.path,b)};let n=g[a.cmd],o=n[b].replaceAll("{{BASE_URL}}",c),p=function(a,b){try{let c=(0,e.join)(h,a);(0,d.mkdirSync)(c,{recursive:!0});let f=(0,e.join)(c,"SKILL.md");return(0,d.writeFileSync)(f,b.endsWith("\n")?b:`${b}
1645
- `,"utf-8"),f}catch{return null}}(a.cmd,o),q=p?k(p,b):o;return{marker:a.marker,body:a.body,label:(i=n,(l="zh"===(j=b)?i.labelZh:i.labelEn)||("zh"===j?"问题:":"Question: ")),pointer:q}})(a,m,s,n));if(1===t.length&&"/"===t[0].marker&&!q){let a=t[0];return a.body?`${a.pointer}
1699
+ - Distinguish fact / hypothesis / to-be-confirmed; don't hardcode a solution too early.`}},h=(0,e.join)(f.Kv,"skills"),i=/^\s*([/@])([a-zA-Z][a-zA-Z0-9-]*)(?:\s+|$)/;function j(a,b="en",c){let l,m=b.startsWith("zh")?"zh":"en",n=function(){try{let a=JSON.parse((0,d.readFileSync)(f.GB,"utf-8")),b=[];for(let c of a.skills??[]){let a=function(a){try{let b=(0,d.readFileSync)(a,"utf-8"),c=b.match(/^---\r?\n([\s\S]*?)\r?\n---/),e=(c?c[1]:b).match(/^name:\s*["']?([^"'\n]+?)["']?\s*$/m);return e?e[1].trim():null}catch{return null}}(c.path);a&&b.push({name:a,path:c.path})}return b}catch{return[]}}(),o=a.split("\n"),p=[];if(o.forEach((a,b)=>{let c,d=a.match(i);d&&(g[c=d[2]]||n.some(a=>a.name===c))&&p.push({i:b,marker:d[1],cmd:d[2],rest:a.slice(d[0].length)})}),0===p.length)return a;let q=o.slice(0,p[0].i).join("\n").trim(),r=p.map((a,b)=>{let c=b+1<p.length?p[b+1].i:o.length,d=[a.rest,...o.slice(a.i+1,c)].join("\n").trim();return{marker:a.marker,cmd:a.cmd,body:d}}),s=(l=process.env.COCKPIT_PORT||process.env.PORT||"3457",`http://localhost:${l}`),t=r.map(a=>(function(a,b,c,f){let i=f.find(b=>b.name===a.cmd);if(i)return{marker:a.marker,body:a.body,pointer:k(i.path,b)};let j=g[a.cmd][b].replaceAll("{{BASE_URL}}",c),l=function(a,b){try{let c=(0,e.join)(h,a);(0,d.mkdirSync)(c,{recursive:!0});let f=(0,e.join)(c,"SKILL.md");return(0,d.writeFileSync)(f,b.endsWith("\n")?b:`${b}
1700
+ `,"utf-8"),f}catch{return null}}(a.cmd,j),m=l?k(l,b):j;return{marker:a.marker,body:a.body,pointer:m}})(a,m,s,n)),u="zh"===m?"然后:":"Then: ";if(1===t.length&&"/"===t[0].marker&&!q){let a=t[0];return a.body?`${a.pointer}
1646
1701
 
1647
- ${a.label}${a.body}`:a.pointer}let u=t.map((a,b)=>{var c,d;let e=(c=b+1,d=a.marker,"zh"===m?"@"===d?`步骤 ${c}(用 subagent 执行):`:`步骤 ${c}(主会话执行):`:"@"===d?`Step ${c} (run in a subagent): `:`Step ${c} (run in the main session): `),f=a.body?`
1648
- ${a.label}${a.body}`:"";return`${e}
1649
- ${a.pointer}${f}`}),v=[];return q&&v.push(q),v.push("zh"===m?"请按以下步骤依次完成:":"Complete the following steps in order:",u.join("\n\n")),v.join("\n\n")}function k(a,b){return"zh"===b?`请读取这个 skill 文件:
1702
+ ${u}${a.body}`:a.pointer}let v=t.map((a,b)=>{var c,d;let e=(c=b+1,d=a.marker,"zh"===m?"@"===d?`步骤 ${c}(用 subagent 执行):`:`步骤 ${c}(主会话执行):`:"@"===d?`Step ${c} (run in a subagent): `:`Step ${c} (run in the main session): `),f=a.body?`
1703
+ ${u}${a.body}`:"";return`${e}
1704
+ ${a.pointer}${f}`}),w=[];return q&&w.push(q),w.push("zh"===m?"请按以下步骤依次完成:":"Complete the following steps in order:",v.join("\n\n")),w.join("\n\n")}function k(a,b){return"zh"===b?`请读取这个 skill 文件:
1650
1705
  ${a}`:`Please read this skill file:
1651
1706
  ${a}`}},38561:(a,b,c)=>{c.d(b,{W:()=>d});let d=new Set(["Read","Grep","Glob","LS","WebSearch","WebFetch","NotebookRead","TodoRead","AskUserQuestion","ExitPlanMode","TodoWrite","Skill"])},72891:(a,b,c)=>{c.a(a,async(a,d)=>{try{c.d(b,{OZ:()=>o,RL:()=>n,k9:()=>p,ok:()=>l});var e=c(37625),f=c(52693),g=c(18412),h=c(89705),i=c(94506),j=c(770),k=a([i]);i=(k.then?(await k)():k)[0];let l=(a,b=200)=>new Response(JSON.stringify(a),{status:b,headers:{"content-type":"application/json"}}),m=a=>{let b=e.od(a);if(f.Ru(b)){let a=b.value,c=(0,j.Sh)(a);return new Response(JSON.stringify({error:(a=>{let b=a.message;if("string"==typeof b&&b.length>0)return b;let c=a.cause;if(c instanceof Error&&c.message.length>0)return c.message;switch(a._tag){case"ValidationError":return`Invalid ${a.field}: ${a.reason}`;case"NotFoundError":return`${a.resource} not found: ${a.id}`;case"PermissionError":return`Permission denied: ${a.action} on ${a.resource}`;case"DBError":return`${a.db} ${a.op} failed`;case"FSError":return`${a.op} ${a.path} failed`;case"WSError":return`${a.proto} ${a.kind} failed`;case"AgentError":return`${a.provider} ${a.kind} failed`;default:return a._tag}})(a),tag:a._tag}),{status:c,headers:{"content-type":"application/json"}})}return console.error("[handler] uncaught defect:\n"+e.j9(a)),new Response(JSON.stringify({error:"Internal Server Error",tag:"InternalError"}),{status:500,headers:{"content-type":"application/json"}})},n=a=>async b=>{let c=await i.s9.runPromiseExit(a(b));return g.YW(c,{onFailure:a=>m(a),onSuccess:a=>a})},o=a=>async(b,c)=>{let d=await c.params,e=await i.s9.runPromiseExit(a(b,d));return g.YW(e,{onFailure:a=>m(a),onSuccess:a=>a})},p=a=>h.$mh({try:()=>a.json(),catch:()=>new j.yI({field:"body",reason:"invalid JSON"})});d()}catch(a){d(a)}})},82940:(a,b,c)=>{c.d(b,{AD:()=>j,GS:()=>l,HS:()=>m,Si:()=>n,Y6:()=>r,ah:()=>k,e5:()=>q,j$:()=>p,yQ:()=>o});let d=globalThis,e=d.__cockpitRunRegistry??(d.__cockpitRunRegistry=new Map),f=d.__cockpitRunListeners??(d.__cockpitRunListeners=new Map),g=d.__cockpitRunSeqByKey??(d.__cockpitRunSeqByKey=new Map);function h(a){for(let b of(a.seq+=1,a.keys))g.set(b,a.seq);return a.seq}function i(a,b){for(let c of a.keys){let a=f.get(c);if(a)for(let c of a)try{c(b)}catch{}}}function j(a,b,c,d){let f=e.get(a);if(f?.status==="running")return!1;let h=f?.seq??g.get(a)??0;if(f)for(let a of(f.evictTimer&&clearTimeout(f.evictTimer),f.keys))e.delete(a);let i=Date.now();return e.set(a,{keys:new Set([a]),cwd:b,status:"running",seq:h,events:[],startedAt:i,updatedAt:i}),c&&k(a,{type:"user",_human:!0,...d?{_turnId:d}:{},_ts:i,message:{role:"user",content:c}}),!0}function k(a,b){let c=e.get(a);c&&"running"===c.status&&(h(c),c.events.push(b),c.updatedAt=Date.now(),i(c,{seq:c.seq,message:b}))}function l(a,b){let c=e.get(a);c&&(c.sessionId=b,a!==b&&(c.keys.add(b),e.set(b,c)))}function m(a,b="idle"){let c=e.get(a);if(c){if("running"!==c.status){"idle"===c.status&&"error"===b&&(c.status="error");return}c.status=b,c.updatedAt=Date.now(),h(c),i(c,{seq:c.seq,message:{type:"run-ended",status:b}}),c.evictTimer&&clearTimeout(c.evictTimer),c.evictTimer=setTimeout(()=>{for(let a of c.keys)e.delete(a)},6e4)}}function n(a){let b=e.get(a);return b?{status:b.status,seq:b.seq,events:b.events.slice(),startedAt:b.startedAt}:null}function o(a){return e.get(a)?.status==="running"}function p(a){return e.get(a)?.sessionId??null}function q(a,b){let c=e.get(a);c&&(c.abort=b)}function r(a){let b=e.get(a);if(!b)return!1;try{b.abort?.()}catch{}return k(a,{type:"result",subtype:"stopped"}),m(a,"idle"),!0}}};