nx-kv 0.15.0 → 0.16.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.
Files changed (165) hide show
  1. package/CHANGELOG.md +205 -76
  2. package/README.md +16 -3
  3. package/assets/groups.json +16 -20
  4. package/assets/kv-get/SKILL.md +100 -0
  5. package/assets/{kv-localget/SKILL.md → kv-get/references/localget.md} +21 -4
  6. package/assets/{kv-timegoal/references/workflow.md → kv-get/references/timegoal-workflow.md} +1 -1
  7. package/assets/{kv-timegoal/SKILL.md → kv-get/references/timegoal.md} +14 -1
  8. package/assets/{kv-waittask/references/kv-waittask-workflow.md → kv-get/references/wait-workflow.md} +11 -2
  9. package/assets/{kv-waittask/SKILL.md → kv-get/references/waitloop.md} +10 -1
  10. package/assets/kv-repo/SKILL.md +29 -2
  11. package/assets/kv-submit/SKILL.md +20 -6
  12. package/assets/nx-kv/references/repo-registry.md +5 -58
  13. package/package.json +2 -1
  14. package/src/core/command-table.js +22 -0
  15. package/src/core/instruction-template.js +109 -0
  16. package/src/core/keys.js +32 -0
  17. package/src/core/zip.js +69 -5
  18. package/src/modules/bundled/index.js +0 -1
  19. package/src/modules/docs/docref.js +77 -0
  20. package/src/modules/docs/index.js +354 -0
  21. package/src/modules/docs/knowledge.js +347 -0
  22. package/src/modules/docs/links.js +43 -0
  23. package/src/modules/docs/paths.js +102 -0
  24. package/src/modules/docs/refs.js +201 -0
  25. package/src/modules/docs/repos-bridge.js +11 -0
  26. package/src/modules/docs/seed.js +147 -0
  27. package/src/modules/docs/store.js +213 -0
  28. package/src/modules/file/index.js +0 -1
  29. package/src/modules/localtask/board-target.js +161 -0
  30. package/src/modules/localtask/index.js +285 -27
  31. package/src/modules/localtask/service.js +318 -359
  32. package/src/modules/repos/boards.js +278 -22
  33. package/src/modules/repos/index.js +193 -79
  34. package/src/modules/repos/keys.js +1 -6
  35. package/src/modules/repos/remote.js +10 -111
  36. package/src/modules/repos/service.js +137 -177
  37. package/src/modules/repos/transfer.js +203 -42
  38. package/src/modules/setting/index.js +0 -1
  39. package/src/modules/system/index.js +8 -70
  40. package/src/modules/system/routes.js +71 -0
  41. package/src/modules/tasktool/add.js +113 -0
  42. package/src/modules/tasktool/attach.js +182 -0
  43. package/src/modules/tasktool/get.js +58 -0
  44. package/src/modules/tasktool/getloop.js +84 -0
  45. package/src/modules/tasktool/groupctx.js +85 -0
  46. package/src/modules/{timegoal → tasktool}/index.js +28 -11
  47. package/src/modules/tasktool/taskgoal.js +100 -0
  48. package/src/modules/{timegoal/service.js → tasktool/timegoal.js} +141 -16
  49. package/src/modules/tasktool/wait.js +510 -0
  50. package/src/modules/templates/index.js +97 -0
  51. package/src/modules/templates/service.js +182 -0
  52. package/src/modules/todo/index.js +0 -1
  53. package/src/modules/todo/service.js +1 -1
  54. package/src/runtime/cli.js +37 -17
  55. package/src/runtime/registry.js +21 -6
  56. package/src/runtime/spec.js +14 -0
  57. package/src/shared/frontmatter.js +80 -0
  58. package/src/shared/wikilink.js +64 -0
  59. package/src/web/frontend/App.jsx +377 -177
  60. package/src/web/frontend/app-context.jsx +13 -0
  61. package/src/web/frontend/components/Introduction/index.jsx +76 -0
  62. package/src/web/frontend/components/Introduction/rail.jsx +141 -0
  63. package/src/web/frontend/components/Introduction/style.css +43 -0
  64. package/src/web/frontend/components/Introduction/use-intro.js +153 -0
  65. package/src/web/frontend/components/board/member-picker.jsx +257 -0
  66. package/src/{modules/todo → web/frontend/components/cloud}/editor.jsx +2 -2
  67. package/src/{modules/todo → web/frontend/components/cloud}/group-popup.jsx +3 -3
  68. package/src/{modules/todo → web/frontend/components/cloud}/markdown.jsx +1 -1
  69. package/src/{modules/todo → web/frontend/components/cloud}/row-menu.jsx +1 -1
  70. package/src/{modules/todo → web/frontend/components/cloud}/upload.js +1 -1
  71. package/src/web/frontend/components/icons.jsx +10 -2
  72. package/src/web/frontend/{modules/md-workspace → components/md}/attach-bar.jsx +1 -1
  73. package/src/web/frontend/components/md/attachments.js +104 -0
  74. package/src/web/frontend/components/md/doc-outline-rail.jsx +2 -0
  75. package/src/web/frontend/{modules/md-workspace → components/md}/md-panes.jsx +17 -71
  76. package/src/web/frontend/components/md/sel-menu.jsx +157 -0
  77. package/src/web/frontend/components/md/template-editor.jsx +120 -0
  78. package/src/web/frontend/{modules/md-workspace → components/md}/tool-bar.jsx +7 -10
  79. package/src/web/frontend/components/migrate/use-move.js +1 -1
  80. package/src/web/frontend/components/pager.jsx +71 -0
  81. package/src/{modules → web/frontend/components}/repos/transfer-panel.jsx +2 -2
  82. package/src/web/frontend/components/sidebar/drag.js +34 -73
  83. package/src/web/frontend/components/sidebar/index.jsx +144 -142
  84. package/src/web/frontend/components/sidebar/model.js +92 -151
  85. package/src/web/frontend/components/sidebar/panel.jsx +193 -0
  86. package/src/web/frontend/components/sidebar/queue-nav.js +40 -0
  87. package/src/web/frontend/components/sidebar/rescue-fab.jsx +78 -0
  88. package/src/web/frontend/components/sidebar/row-menu.jsx +25 -135
  89. package/src/web/frontend/components/sidebar/side-state.js +48 -0
  90. package/src/web/frontend/components/sidebar/task-children.jsx +36 -7
  91. package/src/web/frontend/main.jsx +1 -0
  92. package/src/{modules/localtask/board.js → web/frontend/modules/board/board-view.js} +35 -4
  93. package/src/web/frontend/modules/board/reopen-text.js +67 -0
  94. package/src/web/frontend/modules/md/doc-store.js +78 -0
  95. package/src/web/frontend/modules/md/md-parse.js +435 -0
  96. package/src/web/frontend/modules/{md-workspace → md}/style.css +519 -59
  97. package/src/web/frontend/modules/md/use-templates.js +74 -0
  98. package/src/{modules/todo/view.jsx → web/frontend/page/cloud/index.jsx} +8 -10
  99. package/src/web/frontend/page/dir/index.jsx +249 -0
  100. package/src/web/frontend/page/dir/landing.jsx +184 -0
  101. package/src/web/frontend/page/dir/task.jsx +796 -0
  102. package/src/web/frontend/page/doc/index.jsx +410 -0
  103. package/src/web/frontend/page/group/index.jsx +208 -0
  104. package/src/web/frontend/page/overview/index.jsx +368 -0
  105. package/src/web/frontend/page/progress/index.jsx +223 -0
  106. package/src/{modules/repos/view.jsx → web/frontend/page/repos/index.jsx} +315 -144
  107. package/src/web/frontend/page/settings/index.jsx +604 -0
  108. package/src/web/frontend/page/settings/style.css +182 -0
  109. package/src/web/frontend/page/templates/index.jsx +224 -0
  110. package/src/web/frontend/panels.jsx +219 -0
  111. package/src/web/frontend/prefs.js +17 -81
  112. package/src/web/frontend/registry.js +16 -12
  113. package/src/web/frontend/style-v2.css +457 -213
  114. package/src/web/frontend/style.css +105 -38
  115. package/src/web/frontend/workspace.js +568 -0
  116. package/src/web/public/assets/Introduction-DdUm5Il3.js +1 -0
  117. package/src/web/public/assets/Introduction-Q36q9sjA.css +1 -0
  118. package/src/web/public/assets/cloud-CRC00qO-.js +3 -0
  119. package/src/web/public/assets/dir-CrUiP4aQ.js +3 -0
  120. package/src/web/public/assets/group-CYVEZpI9.js +1 -0
  121. package/src/web/public/assets/index-Did6XKz0.js +50 -0
  122. package/src/web/public/assets/index-pgxfM8xe.css +1 -0
  123. package/src/web/public/assets/jsx-runtime-D3jfb0Ew.js +1 -0
  124. package/src/web/public/assets/md-edit-ops-Bl0Zx0aJ.js +22 -0
  125. package/src/web/public/assets/md-history-rfsLK89W.js +4 -0
  126. package/src/web/public/assets/member-picker-BGUlAVgA.js +1 -0
  127. package/src/web/public/assets/overview-BFoqWgXk.js +1 -0
  128. package/src/web/public/assets/progress-Df-DZ6uP.js +3 -0
  129. package/src/web/public/assets/reopen-text-DSB76_rF.js +5 -0
  130. package/src/web/public/assets/repos-Bvg8dLSB.js +11 -0
  131. package/src/web/public/assets/settings-DM779jcF.css +1 -0
  132. package/src/web/public/assets/settings-DtmMN_KG.js +1 -0
  133. package/src/web/public/assets/task-D5YReySK.js +2 -0
  134. package/src/web/public/assets/templates-BLGE6arn.js +2 -0
  135. package/src/web/public/assets/upload-DLBQnUn4.js +1 -0
  136. package/src/web/public/index.html +3 -3
  137. package/src/modules/localtask/use-cloud-dir.js +0 -74
  138. package/src/modules/localtask/view-overview.jsx +0 -96
  139. package/src/modules/repos/detail.jsx +0 -289
  140. package/src/modules/repos/remote-panel.jsx +0 -218
  141. package/src/web/frontend/components/CliHints.jsx +0 -25
  142. package/src/web/frontend/modules/md-workspace/attachments.js +0 -60
  143. package/src/web/frontend/modules/md-workspace/landing.jsx +0 -30
  144. package/src/web/frontend/modules/md-workspace/md-parse.js +0 -222
  145. package/src/web/frontend/modules/md-workspace/progress-panel.jsx +0 -135
  146. package/src/web/frontend/modules/md-workspace/sel-menu.jsx +0 -65
  147. package/src/web/frontend/modules/md-workspace/tabs-store.js +0 -130
  148. package/src/web/frontend/modules/md-workspace/view.jsx +0 -557
  149. package/src/web/public/assets/CliHints-ClCH9hMc.js +0 -1
  150. package/src/web/public/assets/board-BBYw95q0.js +0 -1
  151. package/src/web/public/assets/detail-DLLVTDvq.js +0 -2
  152. package/src/web/public/assets/index-DAAwgr0O.js +0 -11
  153. package/src/web/public/assets/index-DUWdqYzy.css +0 -1
  154. package/src/web/public/assets/jsx-runtime-DLNB9Qsn.js +0 -1
  155. package/src/web/public/assets/md-parse-BAglkG0y.js +0 -18
  156. package/src/web/public/assets/view-BI8jWJma.js +0 -10
  157. package/src/web/public/assets/view-BVRdFSDe.js +0 -26
  158. package/src/web/public/assets/view-Bd2rRJ3_.js +0 -3
  159. package/src/web/public/assets/view-CD0wpGx_.css +0 -1
  160. package/src/web/public/assets/view-overview-BzsxIsw5.js +0 -1
  161. /package/assets/{kv-repo-mmx-gitrepo/SKILL.md → kv-repo/references/mmx-gitclone.md} +0 -0
  162. /package/src/{modules/todo → shared}/attach.js +0 -0
  163. /package/src/web/frontend/{modules/md-workspace → components/md}/shortcut-sheet.jsx +0 -0
  164. /package/src/web/frontend/modules/{md-workspace → md}/md-edit-ops.js +0 -0
  165. /package/src/web/frontend/modules/{md-workspace → md}/md-history.js +0 -0
package/CHANGELOG.md CHANGED
@@ -2,104 +2,233 @@
2
2
 
3
3
  本文件记录对外可见的变更。格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/)。
4
4
 
5
- ## [0.15.0] - 2026-10-31 仓库详情页 + desc 升级成 md 列表
5
+ ## [0.16.0] - 2026-11-04 占位成员可救可清 + 仓库页可读性 + 前后端分层解耦
6
6
 
7
7
  ### Added
8
8
 
9
- - **仓库详情页 `#/repo/<key>`**:一个仓库的信息(key / 远程 / 路径 / 备注 / 项目组)、
10
- **md 描述文档**(按份渲染,可切 tab)、**相关任务**(本机队列按 cwd 匹配到它,
11
- 待领取 / 已领取分列,可一键跳工作台)。侧边栏点项目、列表点 md chip 都落这一页。
12
- - **`docs` 字段:仓库内 md 的相对路径列表**。desc 从此只是摘要,详细说明写 md:
13
- `repo add/update --docs README.md,docs/arch.md`、`repo doc <id> --path …` 读正文。
14
- 只收仓库内相对路径(绝对路径 / `..` / 非 md 拒收),读正文有越界、不存在、
15
- 512KB 上限三类显式错误;导出布局不带 md 正文。
16
- - 仓库列表行的 desc 下面多一排 `md` chip(点一下直达详情页那一份)。
9
+ - **`board rekey <from> --to <仓库>`**:把组里的**占位 key** 重绑到本机仓库——
10
+ 改的是**关系**(`repoKeys`),仓库登记与 key 不动;组内描述(`repoNotes`)与
11
+ 组内文档绑定(`repoDocs`)跟着 key 搬。不给 `--board` = 全组一起重绑
12
+ (假 key 是身份问题,只修一个组会留下另一半残局)。目标已在组里则合并。
13
+ - **`board prune [--board] [--all] [--apply]`**:清理占位成员。默认只清**无来源**的
14
+ (没有远程地址 → 克隆不回来 → 永远转不了正),带 remote 的加 `--all` 才清;
15
+ 默认预览,`--apply` 落盘。
16
+ - **占位成员带线索**:导入布局时把对方的 `name / remote / desc / type` 记进
17
+ `board.repoHints`,占位从此能显示名字、能「克隆到本地」;`board export` 也不再
18
+ 丢掉占位(以前导出的看板比屏幕上少人)。
17
19
 
18
20
  ### Changed
19
21
 
20
- - **侧边栏的项目行点击 = 进仓库详情页**。以前是「展开任务子行」,于是**没有队列的
21
- 仓库点了没反应**(它唯一去处是工作台,而空队列没有 topicKey)。现在行点击一律有去处,
22
- 展开任务子行改点左边的箭头(有队列才画箭头);详情页里也能看到任务并跳工作台。
23
- - 侧边栏行的 tooltip 会列出该仓库的 md 文档。
24
-
25
- ### 证据
26
-
27
- `tests/unit/repos-docs.test.mjs`(7 条:路径清洗、增改查口径、三类读错误、导出不带正文)。
28
- 全量:lint 干净 / build 通过 / unit 303 / smoke 158。CLI 与面板都实测(无头 Chrome
29
- 点侧边栏 → `#/repo/…`,md 渲染、任务列表、md chip 均正常)。
30
-
31
- ## [0.14.0] - 2026-10-31 仓库身份只有两个来源:远程地址 / 自定义 key;都没有就冻结
22
+ - **修掉「用本机仓库接管」的方向错误**:它原先把**本机仓库的 key** 改成占位 key
23
+ (`local/xxx`),真实身份被降级并随导出传播。现在改为重绑组里的 key,登记不动。
24
+ - **仓库页可读性**:正文字号整体提一档(表格 13.5px、描述两行、路径 12px 等宽),
25
+ 待初始化区改成「一条占位一张卡」:名字 / 来源组 / key 分层,三个出口
26
+ (绑定到候选仓库 / 克隆 / 移除)+ 批量清理。
27
+
28
+ ### Changed(架构:前后端彻底解耦)
29
+
30
+ - **模块声明里不再有 `view`**。`src/modules/<x>/index.js` 曾经写着
31
+ `view: () => import('../../web/frontend/page/x/index.jsx')`——后端声明里出现前端文件
32
+ 路径,前端换个目录就要改后端代码;而 `localtask` 那条 `import('./view.jsx')` 指向的
33
+ 文件**早就不存在**(没人读它,所以坏了也没报错)。视图现在只在前端
34
+ `web/frontend/registry.js` 登记,后端对自己的面板一无所知。
35
+ - **新增同构层 `src/shared/`**:`attach.js`(附件语法)、`wikilink.js`(双链)、
36
+ `frontmatter.js`(任务头)以前长在后端模块里,却被前端直接 import(12 处)——
37
+ 等于浏览器包依赖后端的目录结构。现在只有这一层能同时被两端加载,且**零依赖**
38
+ (不许 `node:`、不许第三方包)。
39
+ - **两个纯前端文件归位**:`localtask/board.js`(显示序 / 队列拆分,7 处前端引用)、
40
+ `localtask/reopen-text.js`(重开正文拼装)没有任何后端消费方,移到
41
+ `web/frontend/modules/board/`;顺手删掉同目录里没人引用的 `use-cloud-dir.js`。
42
+ - **`routes` 改成平台命令**:它描述的是 `ALL_COMMANDS` 本身,只有 runtime 拿得到。
43
+ 以前 system 模块为它 `await import('../../runtime/cli.js')`(分层倒置),现在逻辑
44
+ 留在 `modules/system/routes.js`(纯函数,表由调用方传入),命令挂在 `cli.js` 的
45
+ BUILTINS 上;`bootstrap` 下发的命令表改读 `core/command-table.js` 的快照。
46
+ - **边界写成机器检查**:`eslint.config.js` 新增 modules→web / modules→runtime /
47
+ shared 零依赖 / 模块内禁 react 四类规则;新增 `tests/unit/layering.test.mjs`,
48
+ 解析真实 import 路径比对层次(`web` 只能看到 `web + shared`),并断言后端目录里
49
+ 没有 `.jsx`、模块不再声明 `view`。
50
+
51
+ ## [0.15.0] - 2026-11-04 工作组两级口径(任务带归属)+ 划线评论与完成验收闭环 + 任务附件 + 队列显示序与分页
32
52
 
33
53
  ### Added
34
54
 
35
- - **编辑仓库弹窗可自定义 key**(原来只有 CLI 能设)。留空 = 跟随远程地址,填了 =
36
- 自定义身份。表单里实时说明当前这条的身份来自哪儿。
37
- - **冻结**:既没有远程地址、也没有自定义 key 的仓库被明确标成「无 key · 冻结」
38
- (仓库表格徽标 + `repo list` / `repo add` 的 CLI 输出)。它照常能在本机用
39
- (侧边栏、本地任务、绑定、进项目组),但**不参与导出导入**:导出时仓库本体被跳过,
40
- 项目组里的冻结成员也从导出的成员表里剔除,并如实告警——因为没有 key,
41
- 映射到「另一台机器上的同一个仓库」这件事本身就无意义。
42
- - CLI:`repo key refresh` 对没有远程地址的仓库不再建议 `local/<名称>` 兜底,
43
- 改为说明「无法派生 key:用 repo key set 自定义或补 remote,否则冻结」。
55
+ - **任务带工作组归属(--board / --project)**:`localtask add --project <项目>` 让任务
56
+ 挂到某个项目上(落点目录由归属项目的登记路径推导,任务正文自动写 frontmatter:
57
+ `board` / `project` + 双方介绍**引用式**字段);`--board <项目组>` 要求归属项目必须是
58
+ 该组成员。改文案(`update --text` / `reopen`)不丢 frontmatter;正文自带 frontmatter
59
+ 时同样认归属(fail-open:补介绍引用,落点跟到项目队列;显式给了 `--cwd` 就不挪窝)。
60
+ - 领到组内任务时,交付 `instruction` 封装**项目组上下文**:组定位、组介绍、本项目
61
+ 位置、兄弟成员角色、组绑定参考文件的可读路径(`task.text` 保持原文)。
62
+ - CLI、HTTP、面板提交、远程清单导入同走一条 `submitTask`(tasktool/add.js)——
63
+ 落点判定只此一份实现。
64
+
65
+ - **任务附件**:`localtask attach` 给任务追加附件(--path 上传本机文件,或 --fileId
66
+ 追加已上传附件,以 markdown 嵌入正文末尾,与云端 todo 同构);`localtask attachments`
67
+ 列出某条任务引用的附件与本地是否已有。`get` / `wait` / `show` 的交付自带附件清单与
68
+ 本地绝对路径(自动下载跟随本机设置;标注/同步 fail-open,零附件时载荷不变)。
69
+ 面板编辑器贴图即嵌附件(图床优先,图床不可达时退回本地旧路)。
70
+
71
+ - **划线评论 → 直接提交成任务**:MD 工作台划选正文 → 「评论」→ 提问**直接提交**成
72
+ 新任务(不再先开编辑页),并**整块继承原任务的 frontmatter**——原任务属于某工作组,
73
+ 评论出的新任务也归该组,组面板「本组任务」里能看见。
74
+
75
+ - **完成任务的验收闭环**:任务完成后给出 agent 的完成总结(ack)+ 验收条——
76
+ **通行**(验收通过)/ **重做**(评论模式下带反馈重开,反馈加粗进正文)/
77
+ **提详细问题**(划线评论生成新任务)。重开时正文自动追加**上一轮完成总结**与
78
+ **验收反馈**两段(`modules/localtask/reopen-text.js` 唯一实现:任务页评论框与
79
+ 列表页行内重做共用;同一份总结不追加两遍)。
80
+
81
+ - **队列显示序与分页**:显示序改「**未完成(待领取)优先**」——队列数组是追加序,
82
+ 新任务会被历史埋底;显示序与队列序分开(`sortTasksForDisplay`,桶内待领取仍按
83
+ 队列原序)。侧栏任务子行不再硬截断 12 条(静默丢弃第 13 条起),改**分页**
84
+ (12 条/页);目录任务表同样分页(20 条/页)+「N 待领取 · M 个任务」计数。
85
+
86
+ - **项目组「添加成员」就地选择器**:组面板里就地弹窗——搜索框 + 「项目组」「项目」
87
+ 两段列表;项目行加入/移出本组(行尾标出它还在哪些组),项目组行「并入 N」把该组
88
+ 成员一并纳入(归属是复制不是移动);不再跳仓库管理页,去掉说明性段落。
89
+ 仓库页「成员管理 / 导入仓库」复用同一组件。
90
+
91
+ - **dev-nxkv 项目级 skill**(`.claude/skills/dev-nxkv/`):改本仓库代码的施工单——
92
+ 分层边界、模块骨架、action 字段全表、CRUD 契约、注册三步、常见坑与验收命令。
44
93
 
45
94
  ### Changed
46
95
 
47
- - **`local/<名称>` 不再是身份**:它退化为纯内部锚点(本机关系要有落点),
48
- 不再冒充 key 参与导出、也不再参与导入匹配。
49
- - **改 key = 换身份,关系跟着搬**:项目组成员、组内描述、参考绑定会在 key 变化时
50
- 一起重映射。以前改 key(自定义或换 remote 派生)会把关系断在旧 key 上,
51
- 表现为「仓库莫名从项目组里掉了」。
52
- - 冻结的仓库不参与 key 唯一性检查:两份同名副本(如两个 `nx-kv` 目录)可以各自登记。
53
- - **仓库页去掉「扫描」按钮**(连同它的弹窗与结果卡片):登记入口统一走「添加仓库」。
54
- CLI 的 `nx-kv repo scan` 仍然保留(`--dry-run` 只发现不登记),需要时用命令跑。
96
+ - **进程界面时间起点改为领取时刻**(原为任务创建时刻)。
97
+ - 面板组任务提交走与 CLI 同一条严格口径(组 → 严格 board+project,成员校验一致)。
98
+ - MD 工作台修正:能打出空格(块↔正文往返不再吃掉尾随空白);标题不再与正文融合进
99
+ 同一块;frontmatter 渲染成属性卡;划选不误触编辑。
100
+ - cloud 清单页移除「CLI 等价」提示块。
55
101
 
56
- ### 证据
102
+ ### Fixed
57
103
 
58
- `tests/unit/repos-frozen-key.test.mjs`(11 条)钉住身份判定、冻结的导出行为、
59
- 自定义 key 往返、改 key 搬关系、同名不冲突。全量:lint 干净 / build 通过 /
60
- unit 296 / smoke 158。
104
+ - 项目组「添加成员」的 UI/UX(见上:就地选择器 + 搜索 + 归属继承)。
61
105
 
62
- ## [0.13.0] - 2026-10-30 项目 / 项目组是资产,收纳组只是显示;remote 批量对齐
106
+ ## [0.14.0] - 2026-11-03 wait 收尾指令模板化 + 回调提示词/持续 get 可配多条 + timegoal 面板入口 + 前缀归组改一次性命令 + 删全局默认时长
63
107
 
64
108
  ### Changed
65
109
 
66
- - **侧边栏的层级错了,改正:项目组(看板)不是仓库的父目录。**
67
- 项目(仓库)与项目组(看板)是**并列的资产**——两者都能被编排、都能挂参考,
68
- 项目组内部装的是「开发仓库 + 参考仓库」(那是数据),但侧边栏不再把它画成
69
- 装仓库的文件夹:一条仓库属于某个项目组,仍然在顶层自己出现。
70
- 以前 board 行里嵌 repo 行,读起来就是「仓库属于它、移动就改归属」。
71
- - **左侧的「组」回到侧边栏,但只是显示层(收纳组)**:把项目/项目组摆在一起的
72
- 格子(类似压缩包),存在 `prefs.groups`(浏览器本地),不写 store、不进导出。
73
- 一条资产最多在一个盒子里;解散盒子只拆格子,资产一个都不少。
74
- 与项目组的分工写死在菜单措辞里:**「归入项目组 X」= 数据**(store 里的成员表,
75
- 会导出、跨机可见),**「放进收纳组 X」= 显示**(只影响我怎么看)。
76
- - **「对齐 remote」从一个仓库一个按钮改成一次扫全部**:判断该换哪条 remote 的依据
77
- 全在数据里(`git remote -v` + 登记采纳值 + key 派生),所以仓库页右上给一个
78
- 「对齐 remote」按钮:一屏列出 remote 现状(可替换 / 无 remote / 登记悬空 / 目录不可用),
79
- 带建议与「全部按建议对齐」。行内的 remote 按钮已去掉。
80
- **清单只含开发仓库**:参考仓库的 remote 就是它 clone 的来源兼 key,没有「换一条」的
81
- 余地,列进来只是几十行噪音(它们的健康度看 `repo ref check`)。要看参考仓库得
82
- 显式 `--type ref`,两类一起是 `--type all`。
83
- - 侧边栏点项目组 = 去仓库页筛选到这一组(`#/repos?board=<id>`)——项目组没有独立
84
- 页面,它的成员、组级参考仓库、组内描述都长在仓库页上。
110
+ - **回调提示词可配多条**:`localtask config` 的收尾指令从单条升级为**列表**
111
+ (`settings.taskSuffix` 存 `string[]`,上限 10 条、单条 ≤2000 字)。设置面板
112
+ 「模板与任务工具」改为按条编辑(每条一个文本框 + 删除,「添加一条…」追加,
113
+ 一次保存整体生效);CLI 新增 `--suffix-add "<指令>"` 追加一条、
114
+ `--suffix-remove <序号>` 按序号删一条(与 `--suffix` / `--no-suffix` / `--reset-suffix`
115
+ 互斥)。交付语义不变:多条按空行拼接后统一分流——任一条含 `{{` 整体渲染进
116
+ `instruction` 字段,纯文本仍追加正文末尾;删光 = 关闭。
117
+ - 兼容:旧单条 store(string)读入时整体迁为一列、不拆段;`--suffix "<文本>"`
118
+ 仍是「整体替换为这一条」;设置视图同时暴露 `taskSuffix`(多条拼接串,旧消费者
119
+ 无感)与 `taskSuffixList`(canonical 列表,UI/CLI 按条编辑用)。
120
+ - **项目级「持续 get」模板同步支持多条**(`getLoop.template` 存 `string[]`,同上限
121
+ 规则):设置面板「项目级设置」的持续 get 区块同款按条编辑;交付时多条按空行
122
+ 拼接后统一渲染,全部留空 = 用默认模板;`getLoopForCwd` 暴露 `template`(拼接串)
123
+ 与 `templateList`(列表)。CLI `--get-loop-template` 仍是「整体替换为这一条」。
124
+
125
+ - **timegoal 时长删除全局默认,只在发布任务时设置**:任务时间目标的时长只在
126
+ `localtask add --duration` 显式给出(发布时校验写法),不再有「发布没给时长就按
127
+ 全局默认计时」的兜底。设置面板「模板与任务工具」的「任务时间目标默认时长」输入框
128
+ 与 CLI `localtask config --default-duration / --clear-default-duration` 一并移除。
129
+ - ⚠️ 升级注意:存量 store 里的 `settings.defaultDuration` 残留值被忽略(下次落盘
130
+ 丢弃);此前靠默认时长隐式带时间目标的任务,现在发布时需显式 `--duration`。
131
+
132
+ - **timegoal 面板入口补齐(发布 + 编辑都可设)**:此前带时长的任务只能 CLI 发布——
133
+ 面板任务编辑页没有时间目标入口。现在编辑页标题栏下新增「⏱ 时间目标」行(时长 +
134
+ 可选附加要求):草稿提交即带声明(POST `/api/localtasks` 的 `duration`/`goalPrompt`
135
+ 字段本来就已支持);**未领取**的任务在编辑页可改/清声明(`localtask update` 新增
136
+ `--duration` / `--goal-prompt` / `--clear-goal`,`--text` 在只改时间目标时可省);
137
+ 已领取计时中的任务声明冻结(要调先 reopen 重开)。目录任务表任务标题旁显示
138
+ `⏱ <时长>` 徽标(悬停看附加要求)。
139
+ - 语义约束:`--clear-goal` 与 `--duration` 互斥;只带附加要求不带时长在发布端报错;
140
+ 改时长不带 `--goal-prompt` 则保留原附加要求。
141
+
142
+ - **按前缀归组改为一次性命令,废除常驻规则**:原「仓库名以某前缀开头 → 自动算成员」
143
+ 的前缀分组规则(`board prefix list/add/remove`、仓库页「按前缀分组」区块)整块移除,
144
+ 改为一条一次性命令 `nx-kv board prefix <prefix> [--board <看板>]`——跑一次就把名字
145
+ 以 `<prefix>` 开头(大小写不敏感)的已登记仓库**固化成目标看板的显式成员**(与手工
146
+ 挂的完全同权);`--board` 省略 = 按前缀名自动建同名看板。成员关系从此只有显式成员
147
+ 一个来源;之后新登记的仓库要再跑一次命令。组详情页随之去掉「归属(手动/按前缀)」列。
148
+ - ⚠️ 升级注意:存量 `prefixGroups` 规则不再生效、下次落盘时被丢弃;原来由规则
149
+ 动态归组的仓库会回到未分组——需要的话对每个前缀各跑一次 `board prefix` 补回。
150
+
151
+ - **wait 收尾指令模板化(task / waittask / timegoal 融合)**:`localtask config --suffix`
152
+ 从「固定追加语」升级为**占位符模板**。含 `{{` 的值在 wait 返回时由服务端渲染成融合
153
+ 指令,放进返回载荷的新字段 `instruction`;默认模板 = 该目录 timegoal 状态
154
+ (`〔时间目标「目录名」剩余 X〕`,到点显示「已到点(已超时 X)」)+ 原收尾要求。
155
+ **模板模式下 `task.text` 保持库存原文、不再追加指令**(正文与指令分区打印)。
156
+ - 兼容:纯文本(无 `{{`)维持 v0.x 的 task.text 追加行为(旧 skill 副本不失效);
157
+ `''` 仍 = 关闭;显式存过旧默认文本的 store 需 `localtask config --reset-suffix`
158
+ 才拿到新默认模板。
159
+ - 占位符:`{{goal.name}} {{goal.remainingHuman}} {{goal.deadline}} {{goal.prompt}}
160
+ {{task.id}} {{task.text}} {{source}} {{summary}} {{cwd}} {{name}}`;段落
161
+ `{{#goal}}…{{/goal}}`、`{{#task}}…{{/task}}` 上下文缺失时整段消失。渲染是服务端
162
+ **单遍确定性替换**——goal.prompt / task.text 里的 `{{...}}` 逐字保留、绝不二次
163
+ 展开(防漂移契约延伸到字符串层)。
164
+ - 新核心模块 `src/core/instruction-template.js`(纯函数、零依赖);模板长度上限
165
+ 500 → 2000(渲染产物不设限)。渲染走 `showTimegoal` 只读路径,不写盘、不影响
166
+ `timegoal check` 契约与到点自动收尾(goal_expired)行为。
167
+ - ⚠️ 降级注意:旧版 nx-kv 打开存了新默认模板的 store 会把原始 `{{...}}` 当纯文本
168
+ 追加进 task.text(自定义模板超过旧版 500 上限的还会被截断)——请整版升级,
169
+ 不要混跑新旧二进制。
170
+
171
+ ## [0.13.0] - 2026-10-31 任务模板可配置 + 完成任务可删除 + 无队列仓库可从侧边栏新建任务 + 仓库前缀分组
85
172
 
86
- ### Fixed
173
+ ### Added
87
174
 
88
- - **侧边栏拖拽在稀疏排序下「拖了没反应」**:`prefs.order` 只存用户动过的条目,
89
- 拖到一个从没排过序的目标上时 `order.indexOf(target)` 是 -1,旧实现直接放弃。
90
- 现在以「当前渲染序」为落点基准,结果写回完整序列,顺序完全确定。
91
- - 拖进收纳组会自动展开盒子(否则拖完像是东西消失了)。
175
+ - **点项目组/项目目录 = 看表格**:
176
+ - 新增**项目组详情**(`#/group/<看板 id>`):组里的**子目录**以表格呈现 ——
177
+ 目录 / 路径 / 说明 / 待领取 / 归属(手动 vs 按前缀)。点组行进这里,点表行进该目录。
178
+ - 目录工作台的落地页改成**子任务表**(表格):编号 / 任务 / 状态 / 创建 / 领取 /
179
+ 删除。列表把「什么时候建、什么时候被领走」压成一行就丢了,表格才看得到。
180
+ - 侧栏点击语义分开:**点行 = 去看内容**(组 → 组表,目录 → 子任务表),
181
+ **点 chevron = 在树里展开/收起**。以前两者抢同一个点击,展开就没法兼得。
182
+ - **仓库按前缀分组**:「仓库名以 nx 开头 → 归成一类」这类规则现在有了。
183
+ - 规则只改**成员关系**,看板仍是唯一分组载体 —— 侧边栏分组、仓库页看板筛选、
184
+ 成员管理全都自动跟着生效,不用各改一遍。
185
+ - 规则存服务端(仓库 store 的 `prefixGroups`),换浏览器/换机一致;
186
+ 规则同时记看板 id 与 key(改名不失效、导入换机有兜底)。
187
+ - CLI:`board prefix list` / `board prefix add <前缀> [--board <看板>]` /
188
+ `board prefix remove <前缀>`;HTTP 同构:
189
+ `GET/POST /api/boards/prefix-groups`、`DELETE /api/boards/prefix-groups/:prefix`。
190
+ 目标看板留空 = 按前缀名**自动建同名看板**(如 `board prefix add nx`)。
191
+ - 面板:仓库管理页「看板」区新增「按前缀分组」区块(规则 chip + 前缀/看板输入 + 添加)。
192
+ - 删规则时,**规则建的空看板**一并清掉;看板里有手动成员则只删规则、不动看板。
193
+ - **侧边栏分组读成组**:看板的成员行原本混在全局名称序里(组标题与成员不相邻,
194
+ 「nx 一类」看着只是一堆缩进行)。现在成员紧跟在自己的看板行下面,未归组的仓库
195
+ 排在所有组之后。
196
+ - **任务模板(`template` 命令族 + 面板管理)**:MD 工作台「新建页」的起始正文不再写死。
197
+ - 存 `~/.nx-kv/templates.json`(`NX_KV_TEMPLATES_STORE` 可覆盖);内置一条默认模板
198
+ (不可删),删掉自定义默认后默认回落到内置。
199
+ - 面板:管理入口在**侧边栏设置**(齿轮 → 「任务模板…」弹窗:新增 / 编辑 / 删除 /
200
+ 设为默认)。弹窗头部写明新建页默认用哪个模板;每行给正文前几行的等宽预览;
201
+ 正文用 **MD 编辑器**(源码 + 实时预览 + 格式工具条 B/I/代码/链接/列表/待办/引用/
202
+ H2/H3,Ctrl/⌘+B/I/E/K,视图可切并排/源码/预览)——模板本身就是 Markdown,
203
+ 配置它不该是一个裸 textarea;编辑是行内表单(Ctrl/⌘+Enter 保存);删除带确认。
204
+ 落地页「模板 ▾」菜单按模板直接开新页(✓ 标默认)。「新建页」「新任务」一律取
205
+ 默认模板正文,API 不可达时退回内置骨架(与旧版行为一致)。设置与工作台共享
206
+ 同一份模板数据,改完即时生效。
207
+ - CLI:`template list` / `template add <name> [--body <md> | --body-file <文件> | --body -]`
208
+ `[--setDefault]` / `template update <id> [--name] [--body|--body-file]` /
209
+ `template remove <id>` / `template default <id>`;HTTP 同构:
210
+ `GET/POST /api/templates`、`PATCH /api/templates/:id`、
211
+ `DELETE /api/templates/:id`、`PATCH /api/templates/default`。
212
+ 多行 Markdown 正文在 cmd.exe 里塞不进参数,所以给了 `--body-file`(读文件)与
213
+ `--body -`(读标准输入)——这两条**只在 CLI 生效**,HTTP 不暴露读本机文件。
214
+ - **设置齿轮图标画错**:原来的 `gear` 是「圆心 + 八向光线」的日芒/亮度形状,不像设置。
215
+ 重画为标准齿轮(中心圆 + 齿圈)。
216
+ - **旧版 serve 进程配新版面板资产时,模板弹窗只说「加载失败」**:路由在进程启动时加载、
217
+ 静态资产从磁盘现读——跑着旧进程时新 UI 会拿到 `/api/templates` 404。现在识别出
218
+ 「接口不存在」这种版本偏差,弹窗明说「本机面板服务较旧,重启面板后重试」并隐藏
219
+ 必然失败的表单,只留「重试」;普通瞬时失败同样给「重试」。
92
220
 
93
- ### Added
221
+ ### Fixed
94
222
 
95
- - `repo remote scan [--type dev|ref]`(HTTP `GET /api/repos/remote/scan`):
96
- 批量扫描全部仓库的 remote 现状并给建议。**只读本地 git 配置、不发网络请求**,
97
- 所以够快;远端存在性仍是按需的 `repo remote check`。
98
- - `repo remote align`(HTTP `POST /api/repos/remote/align`,body `items`):
99
- 整批落盘(自定义 key 只改 remote,不覆盖 key)。
100
- - 测试:`tests/unit/sidebar-model.test.mjs`(15 条,钉住「资产 vs 收纳组」与拖拽落点)、
101
- `tests/unit/repos-remote-scan.test.mjs`(10 条,钉住 scan 的判定与批量对齐)。
102
- 全量:lint 干净、build 通过、unit 285、smoke 158。
223
+ - **绑定的仓库没有任务队列时,侧边栏展不开也建不了任务**:仓库行的展开键在无队列时
224
+ 是空串,渲染判断永远为 false——「+ 新建页」子行根本不出现;直接跳工作台又会因
225
+ 找不到队列主题落「目录不存在」。现在点无队列仓库能正常展开,点「新建页」/行菜单
226
+ 「打开详情」/收起态 rail 图标会先自动登记该目录为任务队列(幂等、防 prune),再进
227
+ 工作台。
228
+ - **本地任务完成后没有任何删除入口**:完成(consumed)的任务此前只能留存在列表里。
229
+ 现在两处都可删:落地页列表行悬停出「✕」;打开的页面在工具栏「更多」里有「删除」。
230
+ 删除是**软删除**(`deletedAt` 标记,CLI `localtask task restore` 可恢复),已打开的
231
+ 页签会随手关闭。
103
232
 
104
233
  ## [0.12.1] - 2026-10-30 key 归一化修复 + remote 对齐反馈
105
234
 
package/README.md CHANGED
@@ -268,9 +268,10 @@ nx-kv todo get --ref "旧记录" --topic fr # 或按主题收窄
268
268
 
269
269
  ```
270
270
  src/core/ 零业务语义:kvapi / fileapi(后端客户端) / attachstore(附件本地镜像) / config / errors / fstree
271
+ src/shared/ 同构纯函数:附件语法 / 双链 / frontmatter——Node 与浏览器加载同一份,零依赖
271
272
  src/modules/ 功能域:system / setting / auth / group / localtask / timegoal / todo / file / bundled
272
273
  src/runtime/ 装配层:registry / spec / cli / api / server
273
- src/web/frontend/ React 壳
274
+ src/web/frontend/ React 壳(视图全在这里,后端不知道它们的路径)
274
275
  assets/nx-kv/ 内置 skill:KV 清单操作手册(远程)
275
276
  assets/kv-waittask/ 内置 skill:对话内本地任务接力(等待侧)
276
277
  assets/kv-submit/ 内置 skill:需求提炼与委托提交(提交侧)
@@ -278,8 +279,20 @@ assets/kv-localget/ 内置 skill:领取本目录本地任务(领取
278
279
  assets/kv-timegoal/ 内置 skill:持续 N 小时任务的时间目标与提示词回显
279
280
  ```
280
281
 
281
- 分层由 `eslint.config.js` 的 `no-restricted-imports` 强制;
282
- `tests/unit/registry.test.mjs` 断言模块目录 ↔ 后端注册表 ↔ 前端视图注册表三方对齐。
282
+ 分层由 `eslint.config.js` 的 `no-restricted-imports` 与 `tests/unit/layering.test.mjs` 双重强制:
283
+
284
+ ```
285
+ core ← 谁都不依赖 shared ← 零依赖(不许 node: / 第三方包)
286
+ modules ← core + shared runtime ← 装配全部 web ← 只有 shared
287
+ ```
288
+
289
+ **前端够不着 modules / runtime / core**——它消费后端的唯一方式就是 HTTP `/api`。
290
+ `tests/unit/registry.test.mjs` 断言模块目录 ↔ 后端注册表 ↔ 前端视图注册表三方对齐,
291
+ 并检查面板里出现的每个 `/api` 路径都真实存在。
292
+
293
+ > **改本仓库代码时**:先看项目级 skill `.claude/skills/dev-nxkv/`——它是一份施工单
294
+ > (分层地图、模块骨架、action 字段全表、CRUD 契约、注册三步、常见坑与验收命令)。
295
+ > 在本仓库里开工的 agent 会自动带上它。
283
296
 
284
297
  ## 给 agent 用
285
298
 
@@ -3,32 +3,28 @@
3
3
  "$comment": "group 名 → skill 名列表的别名表。当前 group 名 ≡ skill 名(一对一);skills 是数组,为「一个 group 含多个 skill」预留。路径恒由 assets/<skills[i]>/ 推导——本文件只做聚合,不是第二条事实源。",
4
4
  "groups": {
5
5
  "nx-kv": {
6
- "skills": ["nx-kv"],
6
+ "skills": [
7
+ "nx-kv"
8
+ ],
7
9
  "summary": "KV 清单管理中枢主 skill(默认 install 装的就是这个):todo / group / 工作空间(远程,需登录)"
8
10
  },
9
- "kv-waittask": {
10
- "skills": ["kv-waittask"],
11
- "summary": "对话内实时人机接力(等待侧)——agent 阻塞 wait,用户在网页回填"
11
+ "kv-get": {
12
+ "skills": [
13
+ "kv-get"
14
+ ],
15
+ "summary": "领取与完成本机任务:get 领活 / wait 等人回填 / 时间目标 check 门禁 / done 完成 / reopen 按反馈重开"
12
16
  },
13
17
  "kv-submit": {
14
- "skills": ["kv-submit"],
15
- "summary": "总结上下文、提炼用户需求,提交到别的目录队列委托其它 agent(提交侧)"
16
- },
17
- "kv-localget": {
18
- "skills": ["kv-localget"],
19
- "summary": "领取排给本目录的本地任务 + 队列管理(领取侧)"
20
- },
21
- "kv-timegoal": {
22
- "skills": ["kv-timegoal"],
23
- "summary": "把「持续运行 N 小时」任务固化到 nx-kv:每轮回显原文提示词防偏移 + 时间到点自动停手"
18
+ "skills": [
19
+ "kv-submit"
20
+ ],
21
+ "summary": "总结上下文、提炼用户需求,提交到别的目录队列委托其它 agent(提交侧);可带 --duration 时间目标"
24
22
  },
25
23
  "kv-repo": {
26
- "skills": ["kv-repo"],
27
- "summary": "仓库组识别与关系报告——/kv-repo <组名> 一步加载看板相关项目;board/repo 查询、读并维护领域描述(中心/终端、关键路径、搜索关键词)"
28
- },
29
- "kv-repo-mmx-gitrepo": {
30
- "skills": ["kv-repo-mmx-gitrepo"],
31
- "summary": "mmx 深度搜索并克隆参考仓库——repo ref clone 统一落 gitRepoRoot、remote 为 key 登记绑定,替代散装的 git clone + git.remote 清单流程"
24
+ "skills": [
25
+ "kv-repo"
26
+ ],
27
+ "summary": "仓库组识别与关系报告;克隆外源参考仓库并强制读(读参考实现不许只凭搜索摘要)"
32
28
  }
33
29
  }
34
30
  }
@@ -0,0 +1,100 @@
1
+ ---
2
+ name: kv-get
3
+ description: 领取与完成排给本工作目录的本地任务(别人通过 kv-submit 委托的、用户在面板/弹窗排队的,都落在「目录名即主题」的队列里)——用 localtask get 取活(默认直接领;项目开启「持续 get」后自动阻塞等人回填)、localtask wait 挂着等人接力、localtask done 标记完成(带时间目标的任务未到点会被拒绝,提示派 sub agent 重提需求)、localtask reopen 把用户的修改反馈送回队列重新执行。触发词:领取本地任务、看看有没有排给我的任务、本地队列、领取委托任务、拿任务、本目录的任务、排队任务、localtask get、localtask wait、标记完成、任务完成、修改反馈、重新执行、kv-get。凡「主动获取排给本目录的任务」以及「把任务标记完成/按反馈重开」的场景都走本 skill。反例:把需求提交/委托给别的目录用 kv-submit;查本机仓库分组与参考仓库用 kv-repo;操作远程 KV 清单(todo)用 nx-kv。
4
+ ---
5
+
6
+ # kv-get — 领取、执行、完成(领取侧)
7
+
8
+ 一个 skill 覆盖本机任务的**完整生命周期**:领 → 干 → 标完成 → 按反馈重开。
9
+ 细节拆在 references 里,按需读:
10
+
11
+ - [[localget]] — 领取侧:队列管理、单条查看/编辑/删除/调序
12
+ - [[waitloop]] — 等待侧契约:wait 是本轮最后一步,唯一合法出口是 timeout
13
+ - [[timegoal]] — 时间目标:目录级与**任务级**(领取即计时)的 check 门禁
14
+ - [[wait-workflow]] / [[timegoal-workflow]] — 两套循环的细则
15
+
16
+ ## 三个动作,三种语义(别混用)
17
+
18
+ | 动作 | 命令 | 语义 |
19
+ | --- | --- | --- |
20
+ | **领活** | `nx-kv localtask get --summary "<现状>" --json` | 队列有任务**立即领走**;没有就**立即返回 timeout**(不阻塞、不开窗)——「暂时没活」是正常业务结果 |
21
+ | **等人** | `nx-kv localtask wait --summary "<现状>" --timeout 30 --json` | 阻塞等人回填;**本轮最后一步**,唯一合法出口是 timeout |
22
+ | **挂着领** | 同上,但项目开启了「持续 get」 | `get` 升级为 waitgoal:无任务自动唤起(打开目录页面 + 项目配置的分钟数),期间用户回填就直接领到;领到的交付文本自带「继续 get 直到超时」的项目模板 |
23
+
24
+ 「持续 get」是**项目级**开关(设置面板 → 项目级设置,或 `repo update --get-loop on`),
25
+ 默认关闭——默认就是「直接 get」。
26
+
27
+ ## 领取到的东西必须读全
28
+
29
+ ```bash
30
+ nx-kv localtask get --summary "<本轮现状>" --json
31
+ # → { status:"ok", task:{id,text,...}, instruction:"…" }
32
+ ```
33
+
34
+ - `task.text` = 任务正文(Markdown),**永远读它**;
35
+ - `instruction` = 服务端渲染的指令段,**有则必读**(与 task.text 一起构成这一轮的根指令):
36
+ - **项目组上下文**(领的是组内仓库时):组定位、组介绍、本项目在组里的位置、兄弟成员的角色、组绑定参考文件的**可读路径**——这些路径是磁盘上的真实文件,需要细节就直接读;
37
+ - **收尾指令**(可配置,默认「本轮最后再 wait 一次」);
38
+ - **任务级时间目标的 check 指令**(见下)。
39
+
40
+ ## 时间目标:领取即计时,未到点不许标完成
41
+
42
+ 发布方可以给单条任务带时长(`localtask add … --duration 2h`)。这种任务被领取时
43
+ **自动起表**,交付文本里带一条固定指令:
44
+
45
+ ```bash
46
+ nx-kv timegoal check --task task:<topicKey>:<taskId> --summary "<本轮现状>" --progress "<进展/下一步>"
47
+ ```
48
+
49
+ 每轮推进先跑一次 check(它会原文回显时间目标提示词,防长对话漂移)。
50
+ **时间未到不能标完成**——`localtask done` 会返回业务结果(不是错误):
51
+
52
+ ```json
53
+ { "status": "blocked", "reason": "goal_not_reached", "remainingSec": 1830,
54
+ "hint": "时间未到,不能标记完成——请派出 sub agent 重新提出新的需求;到点后…再来标完成" }
55
+ ```
56
+
57
+ 此时**不要**硬标完成、也不要自己改时间:按提示**派 sub agent 重新提出新的需求**,
58
+ 再继续推进;到点(check 返回 `reached:true`)后再 `done`:
59
+
60
+ ```bash
61
+ nx-kv localtask done --id <n> --summary "<完成总结>" --json
62
+ ```
63
+
64
+ 没有时间目标的任务直接 done 即可。目录级 timegoal(`timegoal set --cwd …`)是另一回事:
65
+ 它是「这个目录整体要跑多久」的预算,见 [[timegoal]]。
66
+
67
+ ## 完成与反馈:闭环的两端
68
+
69
+ ```bash
70
+ # 标记完成(完成总结必填——它就是下一轮 agent 能看到的「上轮做了什么」)
71
+ nx-kv localtask done --id <n> --summary "<完成总结>" [--progress "<完成度/下一步>"]
72
+
73
+ # 用户看了结果提修改意见 → 任务回到待领取,agent 可再次领取(执行循环继续)
74
+ nx-kv localtask reopen --id <n> [--text "<改后的正文(Markdown)>"] --json
75
+ ```
76
+
77
+ `reopen` 会作废领取时间(新一轮从**再次领取**开始重新计时)、清掉完成标记,
78
+ 但**保留上一轮的完成总结**——下一轮接手时 agent 能看到自己上轮做到哪。
79
+
80
+ ## 硬规则
81
+
82
+ 1. **同一个目录同一时刻只挂一个 wait**(waiters 是进程内注册表,一个 key 只能有一个)。
83
+ 2. **timeout 是业务结果,不是错误**(exit 0):按「暂时没活」收尾,**不要**当失败重试。
84
+ 3. **wait 是本轮最后一步**:拿到任务或超时之前,不要提前结束本轮。
85
+ 4. **instruction 有则必读**:里面的组上下文/时间目标/收尾要求都是硬约束。
86
+ 5. **带时间目标的任务不许提前标完成**——被拒绝就按提示派 sub agent 重提需求。
87
+ 6. **同一时刻只挂一个 wait**;`get` 与 `wait` 不要并发跑(都在同一队列上抢任务)。
88
+
89
+ ## 队列管理(需要时)
90
+
91
+ ```bash
92
+ nx-kv localtask list --json # 全部主题:目录、现状、等待中、待领取数
93
+ nx-kv localtask show --id <n> --json # 查看单条(get 已是「领取」动词)
94
+ nx-kv localtask update --id <n> --text "<新内容>" --json # 改正文;--duration 2h 设时间目标、--clear-goal 清除(仅未领取时可改)
95
+ nx-kv localtask remove --id <n> --json # 软删除(CLI restore 可恢复)
96
+ nx-kv localtask reorder --id <n> --before-id <m> --json
97
+ nx-kv localtask topic remove --cwd "<目录>" # 删整个主题(等待中需 --force)
98
+ ```
99
+
100
+ 以上都不传 `--cwd` 时按进程当前目录定位。
@@ -16,24 +16,41 @@ description: 领取排给本工作目录的本地任务——别人通过 kv-sub
16
16
  nx-kv localtask list --json
17
17
  # → {topics:[{key,cwd,name,summary,waiting,pending,total,tasks:[...]}], waiting, settings}
18
18
 
19
- # 2. 有待领取 → 取走最早的一条(队列非空时 wait 立即返回,不开窗不阻塞)
20
- nx-kv localtask wait --summary "<本轮现状,如:空闲,领取新任务>" --timeout 30 --json
19
+ # 2. 有待领取 → 取走最早的一条(默认「直接 get」:队列非空立即返回,不开窗不阻塞)
20
+ nx-kv localtask get --summary "<本轮现状,如:空闲,领取新任务>" --json
21
21
  # → {status:"ok", queued:true, task:{id,text,...}}
22
22
 
23
+ # 2b. 想挂着等活(阻塞等人回填)→ 用 wait(kv-waittask 的循环契约)
24
+ nx-kv localtask wait --summary "<本轮现状>" --timeout 30 --json
25
+
23
26
  # 3. 执行 task.text(内容永远读 task.text,id 只是编号),产出落在本目录
27
+
28
+ # 4. 干完标记完成(带时间目标的任务:未到点会被拒绝)
29
+ nx-kv localtask done --id <n> --summary "<完成总结>" --json
24
30
  ```
25
31
 
26
32
  - `queued:true` = 从队列取到任务,直接执行。
33
+ - 返回可能带 `instruction` 字段(收尾指令模板的渲染结果,默认含该目录 timegoal 的
34
+ 剩余预算 +「计划最后再 wait 一次」)——有则必读,与 `task.text` 一起构成这一轮的
35
+ 根指令;字段缺席 = 已关闭或本轮没有可渲染内容(如模板只有 goal 段而该目录无目标)。
27
36
  - `{status:"timeout"}`(exit 0,不是错误)= 时限内没有新任务:想继续等就再
28
37
  wait(挂起等待,期间别人提交的会立刻送达),不想等就收工。
38
+ - **get 的两种形态**:默认「直接 get」(没任务立即返回 timeout,不阻塞);项目在设置
39
+ 面板里开启「持续 get(waitgoal)」后,get 变成**阻塞唤起**——自动打开对应目录页面、
40
+ 等项目配置的分钟数,期间用户回填就直接领到;领到的交付文本自带「继续 get 直到
41
+ 超时」的项目模板(不用自己记循环)。
42
+ - **带时间目标的任务**(发布时 `--duration 2h`):领取即计时,交付的 instruction 里
43
+ 带 `timegoal check --task …` 指令;**时间未到不许标记完成**——`localtask done`
44
+ 会返回 `{status:"blocked", reason:"goal_not_reached"}`,此时应派出 sub agent
45
+ 重新提出新的需求再继续,而不是硬标完成。
29
46
  - `--timeout <秒>`:阻塞上限(缺省用页面配置 180 秒,最大 600);「查完就走」
30
47
  用短超时,「挂着等活」用长超时。
31
48
 
32
49
  ## 队列管理(需要时)
33
50
 
34
51
  ```bash
35
- nx-kv localtask get --id <n> # 查看单条
36
- nx-kv localtask update --id <n> --text "<新内容>" # 改写任务内容
52
+ nx-kv localtask show --id <n> # 查看单条(get 已改为领取动作)
53
+ nx-kv localtask update --id <n> --text "<新内容>" # 改写任务内容;--duration/--clear-goal 改时间目标(仅未领取时)
37
54
  nx-kv localtask remove --id <n> # 删除单条
38
55
  nx-kv localtask reorder --id <n> --before-id <m> # 调整领取顺序(或 --after-id)
39
56
  nx-kv localtask topic remove --cwd "<目录>" # 删除整个主题(等待中需 --force)
@@ -1,6 +1,6 @@
1
1
  # kv-timegoal · 时序与完整示例
2
2
 
3
- 按需加载:只是想看命令的话回到 [[kv-timegoal|SKILL.md]],不必读这份。
3
+ 按需加载:只是想看命令的话回到 [[timegoal]],不必读这份。
4
4
  下面给一份能复刻的"3 小时调研 Redis 差距并自迭代实现生产级数据库"任务
5
5
  完整时序,含可直接抄走的 prompt 模板。
6
6
 
@@ -171,10 +171,23 @@ nx-kv timegoal log --cwd <dir> # 回看每
171
171
 
172
172
  **没有依赖关系。** timegoal 只做两件事:算时间、回显提示词原文。
173
173
 
174
- - 不调用 `localtask wait`:等不到任务是别的事,与是否到点无关
174
+ - 不调用 `localtask wait`:等不到任务是别的事,与是否到点有关
175
+ - **两种 timegoal**:目录级(`--cwd`,与目录一对一)与**任务级**(`--task
176
+ task:<topicKey>:<taskId>`,发布时 `localtask add --duration 2h` 随任务携带,
177
+ **领取即计时**)。任务级的 goal key 会随任务交付的 instruction 一起给你,
178
+ 直接照抄执行即可;`timegoal check --task <key> --summary … --progress …` 记日志,
179
+ 未到点 `localtask done` 会拒绝标记完成。
175
180
  - 不阻塞任何东西:可以同时跑人机接力、派任务给别的 agent、外部 cron
176
181
  - 不需要登录 KV 后端:纯本机
177
182
 
183
+ **与 wait 的融合(只读,单向)**:这个目录挂着 timegoal 时,`localtask wait`
184
+ 返回的 `instruction` 字段会带上目标状态(默认模板:`〔时间目标「目录名」剩余 X〕`;
185
+ 到点后显示「已到点」)——kv-waittask 循环里的 agent 不调 check 也能看到预算。
186
+ 融合是**渲染时只读**(`showTimegoal` 只读路径,不写盘、不写 check 日志、不影响
187
+ 计时与到点判定),timegoal 自身的命令族与契约完全不变;`check` 的 prompt 原文
188
+ 回显仍是防漂移的唯一正式通道。要到 wait 的 instruction 里携带 prompt 原文,
189
+ 用 `localtask config --suffix` 自定义模板并写入 `{{goal.prompt}}`。
190
+
178
191
  你可以把它当成一个独立计时器 + 便签本:`set` 把便签写进文件,`check` 读出来
179
192
  顺便告诉你还剩多少时间。
180
193