@rowansenne/workflow-run 0.20.0 → 0.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -1
- package/README.md +16 -17
- package/bin/lib/doctor.mjs +13 -11
- package/bin/lib/install.mjs +1 -1
- package/bin/seed-templates.mjs +4 -4
- package/bin/workflow-run.mjs +2 -2
- package/create-release-md-doc/SKILL.md.tpl +3 -2
- package/create-tech-md-doc/SKILL.md.tpl +3 -2
- package/package.json +1 -1
- package/workflow/SKILL.md.tpl +2 -2
- package/workflow/references/status.md +2 -2
- package/workflow/references/templates.md +18 -14
- package/workflow/scripts/docnexus.mjs +1 -1
- package/workflow/scripts/resolve.mjs +18 -12
- package/workflow/scripts/template.mjs +20 -29
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.21.1] - 2026-10-18
|
|
8
|
+
|
|
9
|
+
### 修复
|
|
10
|
+
- 提示里的命令改成完整的 `npx @rowansenne/workflow-run <子命令>`(如 `seed-templates --update`、`upgrade`):之前写的是 `workflow-run ...`,用 npx 安装、没有全局安装时会报命令找不到。
|
|
11
|
+
|
|
12
|
+
## [0.21.0] - 2026-10-18
|
|
13
|
+
|
|
14
|
+
### 变更(破坏性)
|
|
15
|
+
- **默认模板只读,定制模板只放 DocNexus**:skills 自带的模板不能改;修改或新建模板一律写进 DocNexus 知识库,便于团队共享(每次变更有 timeline)。`workflow-run/templates/` 下的项目模板不再生效,`resolve.mjs` 输出 `stale_project_file`,`doctor` 提示导入知识库后删除;接入 DocNexus 后缺模板时仍把它作为 `import_from` 提议导入。
|
|
16
|
+
- 未接入 DocNexus 时:只用默认模板;`template.mjs draft` / `save` 退出码 2、输出 `need_docnexus: true`,提示先 `--with-docnexus` 接入。技术方案、上线方案没有默认模板,`resolve.mjs template` 同样返回 `need_docnexus`,要先接入 DocNexus 才能创建模板和生成文档;`resolve.mjs status` 新增 `templates_need_docnexus`。
|
|
17
|
+
- `template.mjs save` 不再写项目文件、不再备份到 `workflow-run/tmp/template-backup/`,只给出写入知识库的 capture 指引;撤销按 DocNexus 的 timeline 恢复。
|
|
18
|
+
|
|
7
19
|
## [0.20.0] - 2026-10-18
|
|
8
20
|
|
|
9
21
|
### 变更
|
|
@@ -260,7 +272,8 @@
|
|
|
260
272
|
- 安装器改为单一 Node 实现,`init-skills.sh` / `init-skills.ps1` 只是薄封装。
|
|
261
273
|
- `code-review` 改名为 `project-review`,升级时自动清理旧名。
|
|
262
274
|
|
|
263
|
-
[Unreleased]: https://github.com/guilianerde/skills-init/compare/v0.
|
|
275
|
+
[Unreleased]: https://github.com/guilianerde/skills-init/compare/v0.21.0...HEAD
|
|
276
|
+
[0.21.0]: https://github.com/guilianerde/skills-init/compare/v0.20.0...v0.21.0
|
|
264
277
|
[0.20.0]: https://github.com/guilianerde/skills-init/compare/v0.19.0...v0.20.0
|
|
265
278
|
[0.19.0]: https://github.com/guilianerde/skills-init/compare/v0.18.0...v0.19.0
|
|
266
279
|
[0.18.0]: https://github.com/guilianerde/skills-init/compare/v0.17.0...v0.18.0
|
package/README.md
CHANGED
|
@@ -122,7 +122,7 @@ npx @rowansenne/workflow-run docs-repo git@git.example.com:team/team-docs.git
|
|
|
122
122
|
/workflow report # 本地效果报告(也可以直接运行 npx @rowansenne/workflow-run report)
|
|
123
123
|
```
|
|
124
124
|
|
|
125
|
-
**效果报告**(`/workflow report` 或 `workflow-run report [--since YYYY-MM-DD] [--all-branches] [--json]`)只读统计 `workflow-run/docs/requirements/` 下已落盘的产物,不上报、不另存记录,用来回答「用了以后有没有更好」。默认只看工作区;产物随特性分支提交、还没合并时加 `--all-branches`,用 git 只读扫描所有本地分支(同一路径以工作区为准)。统计内容:
|
|
125
|
+
**效果报告**(`/workflow report` 或 `npx @rowansenne/workflow-run report [--since YYYY-MM-DD] [--all-branches] [--json]`)只读统计 `workflow-run/docs/requirements/` 下已落盘的产物,不上报、不另存记录,用来回答「用了以后有没有更好」。默认只看工作区;产物随特性分支提交、还没合并时加 `--all-branches`,用 git 只读扫描所有本地分支(同一路径以工作区为准)。统计内容:
|
|
126
126
|
|
|
127
127
|
* 审查:各级别发现条数、严重问题复核通过率、复审时上次问题的修复率;
|
|
128
128
|
* 交付:功能 / 缺陷、S / M / L、开工前经需求澄清确认的决定条数、带「未验证项」的交付;
|
|
@@ -276,7 +276,7 @@ dev、project-review、技术方案、上线方案都在对应环节调用它:
|
|
|
276
276
|
|
|
277
277
|
## 重跑与升级
|
|
278
278
|
|
|
279
|
-
可以放心重复执行 init 来升级模板;只想按原来的环境升级时用 `workflow-run upgrade`,不用再选一遍:
|
|
279
|
+
可以放心重复执行 init 来升级模板;只想按原来的环境升级时用 `npx @rowansenne/workflow-run upgrade`,不用再选一遍:
|
|
280
280
|
|
|
281
281
|
* `SKILL.md`、`references/checklist.md`、`template.md`、脚本等**模板文件会被更新**;但被你**手动改过**的模板文件不会被静默覆盖(见下方「安装清单」);
|
|
282
282
|
* 新版本模板里已删除的文件会被清理;你改过的不删,保留并在结尾提示;
|
|
@@ -315,7 +315,7 @@ mv .agents/skills/.skills-init.json .agents/skills/.workflow-run.json
|
|
|
315
315
|
| 清单里有、新版里已没有 | 没改过直接删除;改过的备份后删除 |
|
|
316
316
|
|
|
317
317
|
* 这样 `SKILL.md`、`skill.json`、脚本始终是同一个版本,不会出现「新 SKILL.md 配旧 skill.json」的混搭。
|
|
318
|
-
* 项目自己的定制不要改 skills 目录里的文件,放到不会被覆盖的地方:项目事实和约定写 `workflow/profile.json`(约定写 `notes
|
|
318
|
+
* 项目自己的定制不要改 skills 目录里的文件,放到不会被覆盖的地方:项目事实和约定写 `workflow/profile.json`(约定写 `notes`),文档模板只能在 DocNexus 里定制(skills 自带的默认模板只读),通用规则写 `CLAUDE.md` / `AGENTS.md`。
|
|
319
319
|
* 需要找回手改内容时到备份目录里取。
|
|
320
320
|
|
|
321
321
|
### 卸载
|
|
@@ -390,11 +390,11 @@ npx @rowansenne/workflow-run uninstall
|
|
|
390
390
|
| `workflow/scripts/resolve.mjs infer-profile` | 按固定规则从构建文件、Makefile、依赖与配置文件、git 推断项目画像草稿,每个字段附依据;不写文件 |
|
|
391
391
|
| `workflow/scripts/lint-doc.mjs <文档> --skill <skill> [--facts]` | 对照当前生效的模板检查生成的文档:必填章节、残留 `{{...}}` 占位符、元信息行为错误;缺普通章节、顺序不一致为警告;列出待填写位置。`--facts` 再核对正文里的类名、文件、接口、表名:在对比分支的 diff 和代码里都找不到的记为警告(防编造) |
|
|
392
392
|
| `workflow/scripts/requirement.mjs which / bind / path / sync / pending / list / config` | 产物按需求归档(`workflow-run/docs/requirements/<需求>/`,独立文档仓库模式再分 `<项目>/`):查当前分支绑定的需求(没绑定时给出按分支名生成的建议名)、绑定需求名、给出本次落盘路径(不覆盖,带上一版的 wiki 记录)、重建 `meta.json`、列出所有需求;`config` 设置产物位置(文档仓库、项目名、提交提示),`pending` 看文档仓库里还没提交的产物 |
|
|
393
|
-
| `workflow/scripts/view.mjs [--out f] [--open]` | 项目文档视图(`/workflow view`、`workflow-run view`):读需求目录里的产物,生成单个 HTML,按需求列出各阶段、审查记录(各级别数量、复核、与上次对比)、交付记录、沉淀到的知识文档,正文直接渲染;顶部「知识文档」列出每篇知识文档来自哪个需求、哪份产物;数据内嵌,只读、不联网,默认写到 `workflow-run/tmp/view/index.html` |
|
|
393
|
+
| `workflow/scripts/view.mjs [--out f] [--open]` | 项目文档视图(`/workflow view`、`npx @rowansenne/workflow-run view`):读需求目录里的产物,生成单个 HTML,按需求列出各阶段、审查记录(各级别数量、复核、与上次对比)、交付记录、沉淀到的知识文档,正文直接渲染;顶部「知识文档」列出每篇知识文档来自哪个需求、哪份产物;数据内嵌,只读、不联网,默认写到 `workflow-run/tmp/view/index.html` |
|
|
394
394
|
| `workflow/scripts/artifacts.mjs [--branch b \| --all]` | 按分支汇总 `workflow-run/docs/requirements/` 下的开发方案、交付说明、审查报告、技术方案、上线方案及其 wiki 发布记录,给出下一步建议;分支取自文档元信息行,不另存记录。上线方案没传 `--tech` 时据此自动引用同分支的技术方案;project-review 据此对照本分支方案、识别复审 |
|
|
395
|
-
| `workflow/scripts/report.mjs [--since d] [--all-branches] [--json]` | 本地效果报告(`/workflow report`、`workflow-run report`):审查发现与修复率、复核率、需求澄清、沉淀率、知识引用、各分支链路 |
|
|
395
|
+
| `workflow/scripts/report.mjs [--since d] [--all-branches] [--json]` | 本地效果报告(`/workflow report`、`npx @rowansenne/workflow-run report`):审查发现与修复率、复核率、需求澄清、沉淀率、知识引用、各分支链路 |
|
|
396
396
|
| `workflow/scripts/tables.mjs [--diff b...h \| --base b \| --files a,b]` | 找出改动涉及哪些表:实体注解(`@TableName` / `@Table`,没写表名时按类名推断)、Mapper XML 与代码里的 SQL、DDL 脚本;标出 DDL、是否在 `schema.md` 里,并给出拉表结构的命令。dev 调研 / 自检与 project-review 审 SQL / DDL 时使用 |
|
|
397
|
-
| `workflow/scripts/template.mjs list / draft / check / save <模板>` | 修改 / 创建模板(`/workflow template`):把当前模板复制成草稿(或 `--from <样例>` 抽骨架),`check` 校验格式、列出章节变化、拿最近几份已生成文档试跑 lint 看影响,`save`
|
|
397
|
+
| `workflow/scripts/template.mjs list / draft / check / save <模板>` | 修改 / 创建模板(`/workflow template`):把当前模板复制成草稿(或 `--from <样例>` 抽骨架),`check` 校验格式、列出章节变化、拿最近几份已生成文档试跑 lint 看影响,`save` 给出写入 DocNexus 知识库的 capture 指引,不直接写知识库;未接入 DocNexus 时 `draft` / `save` 提示先接入(默认模板只读) |
|
|
398
398
|
| `workflow/scripts/pr-desc.mjs [--branch b] [--base m] [--out f]` | 按本分支产物生成 PR / MR 描述;没有交付说明时退回用 git 记录 |
|
|
399
399
|
| `database-query/scripts/query.mjs` | 执行 SQL:选连接、取密码(只通过环境变量传给客户端)、会话层只读、拦截写语句和多语句、自动补 LIMIT、超时、脱敏敏感列;支持 mysql / psql 客户端,其他 driver 退回 JDBC |
|
|
400
400
|
| `database-query/scripts/query.mjs --schema [--tables a,b] [--write]` | 按只读会话导出表结构为 Markdown;`--write` 写入 `references/schema.md` 的 `schema:begin` / `schema:end` 之间,标记外的补充说明保留;指定的表在库里不存在时标出 |
|
|
@@ -500,7 +500,7 @@ npx @rowansenne/workflow-run docs-repo <团队文档仓库地址> [--project <
|
|
|
500
500
|
* 其他服务的需求要先在 `workflow-run/` 里拉下来(`git -C workflow-run pull`),绑定时才看得到。
|
|
501
501
|
* `/workflow view` 在这个模式下显示文档仓库里所有项目的需求。
|
|
502
502
|
|
|
503
|
-
**浏览**:`/workflow view` 或 `workflow-run view --open` 生成一个本地页面(`workflow-run/tmp/view/index.html`)。左边是需求列表,可按名称或分支搜索;右边是这个需求的各阶段、审查记录(每轮的级别数量、复核、与上次对比的修复情况)、交付记录,以及各份文档的渲染正文。页面是生成那一刻的快照,产物有更新时重新生成。
|
|
503
|
+
**浏览**:`/workflow view` 或 `npx @rowansenne/workflow-run view --open` 生成一个本地页面(`workflow-run/tmp/view/index.html`)。左边是需求列表,可按名称或分支搜索;右边是这个需求的各阶段、审查记录(每轮的级别数量、复核、与上次对比的修复情况)、交付记录,以及各份文档的渲染正文。页面是生成那一刻的快照,产物有更新时重新生成。
|
|
504
504
|
|
|
505
505
|
其他产物:
|
|
506
506
|
|
|
@@ -508,11 +508,10 @@ npx @rowansenne/workflow-run docs-repo <团队文档仓库地址> [--project <
|
|
|
508
508
|
| --- | --- | --- |
|
|
509
509
|
| database-query | 查询结果 | 默认对话输出;导出时 `workflow-run/tmp/database-query/result-<时间戳>.csv` |
|
|
510
510
|
| md-to-wiki | 转换临时 XHTML | `workflow-run/tmp/md-to-wiki/_wiki_upload_<时间戳>.html`(上传后可删) |
|
|
511
|
-
| 各文档类 skill | 项目模板 | `workflow-run/templates/<skill>/`(见下文「模板」) |
|
|
512
511
|
|
|
513
512
|
规则:
|
|
514
513
|
|
|
515
|
-
* 本工具的产出都在 `workflow-run/`:`docs/requirements/`(需求产物)、`docnexus/`(DocNexus
|
|
514
|
+
* 本工具的产出都在 `workflow-run/`:`docs/requirements/`(需求产物)、`docnexus/`(DocNexus 工作区,含定制的文档模板)是**持久产物**,随代码提交或在独立文档仓库里提交,团队共享。
|
|
516
515
|
* `workflow-run/tmp/` 是**临时产物**目录,安装时自动把 `/workflow-run/tmp/` 加入 `.gitignore`,不入库。
|
|
517
516
|
|
|
518
517
|
## 自定义模板
|
|
@@ -593,8 +592,9 @@ workflow-run(安装器仓库)/
|
|
|
593
592
|
|
|
594
593
|
文档类 skill 的模板来源取决于项目是否接入了 DocNexus,生成的文档开头会注明「模板来源」:
|
|
595
594
|
|
|
596
|
-
* **已接入 DocNexus:只用知识库里的模板** `workflow-run/docnexus/library/templates/<skill>/<文件名>`(分类 `doc-template`)。不再使用 skill
|
|
597
|
-
* **未接入 DocNexus
|
|
595
|
+
* **已接入 DocNexus:只用知识库里的模板** `workflow-run/docnexus/library/templates/<skill>/<文件名>`(分类 `doc-template`)。不再使用 skill 自带的默认模板。库里缺模板时 skill 会停下来,提示你导入后再继续,不会悄悄回退到默认模板。
|
|
596
|
+
* **未接入 DocNexus**:只用 skill 自带的默认模板。
|
|
597
|
+
* **默认模板只读,定制只走 DocNexus**:要改模板或新建模板,都写进 DocNexus 知识库,团队共享同一份、每次变更有 timeline。不要直接改 skills 目录里的模板(升级会覆盖);`workflow-run/templates/` 下的项目模板已不再生效,`doctor` 会提示你导入知识库后删除。
|
|
598
598
|
|
|
599
599
|
| skill | 文件名 | 用途 | 默认模板 |
|
|
600
600
|
| --- | --- | --- | --- |
|
|
@@ -605,18 +605,17 @@ workflow-run(安装器仓库)/
|
|
|
605
605
|
| project-review | `checklist.md` | 审查清单 | 有 |
|
|
606
606
|
| project-review | `report.md` | 审查报告模板 | 有 |
|
|
607
607
|
|
|
608
|
-
**技术方案、上线方案的模板按团队自己的格式创建**:各团队发到 wiki 的文档格式不同,skills 不再自带固定格式。第一次生成时 skill 会停下来,请你给一份团队现有的同类文档(本地 Markdown,或 wiki 的 pageId / URL)作样例,用 `workflow/scripts/make-template.mjs`
|
|
608
|
+
**技术方案、上线方案的模板按团队自己的格式创建**:各团队发到 wiki 的文档格式不同,skills 不再自带固定格式。第一次生成时 skill 会停下来,请你给一份团队现有的同类文档(本地 Markdown,或 wiki 的 pageId / URL)作样例,用 `workflow/scripts/make-template.mjs` 抽出章节和表格结构,把正文换成填写说明,你确认后经你授权写入 DocNexus。因此这两类文档**需要先接入 DocNexus**(`--with-docnexus`),未接入时 skill 会停下来提示。之后想换格式,直接说「重新生成技术方案模板」。
|
|
609
609
|
|
|
610
610
|
**修改模板**:说「改技术方案模板,加一节回滚方案」或 `/workflow template release 去掉灰度那节`,agent 会一路走完:
|
|
611
611
|
|
|
612
612
|
1. 把当前生效的模板复制成草稿 `workflow-run/tmp/template-draft/<skill>/<文件名>`,只改草稿;
|
|
613
613
|
2. `template.mjs check` 校验格式(必填 ` *`、可选「(如有)」、占位符),列出新增 / 删除的章节、必填变化,并拿最近几份已生成的文档试跑,告诉你新模板下它们会多出哪些错误;
|
|
614
|
-
3.
|
|
614
|
+
3. 你确认后经你授权按 capture 流程写入 DocNexus 知识库,再确认生效;要撤销按 DocNexus 的 timeline 恢复旧版本。
|
|
615
615
|
|
|
616
|
-
模板别名:`tech`、`release`、`plan`、`delivery`、`review`、`checklist
|
|
616
|
+
模板别名:`tech`、`release`、`plan`、`delivery`、`review`、`checklist`。改带默认版本的模板(开发方案、交付说明、审查报告、审查清单)也走这条路,知识库里的版本取代默认版本,升级不会覆盖。未接入 DocNexus 时不能修改模板,agent 会提示你先接入。
|
|
617
617
|
|
|
618
|
-
*
|
|
619
|
-
* `doctor` 和 `/workflow status` 会列出还没创建的模板。
|
|
618
|
+
* `doctor` 和 `/workflow status` 会列出还没创建的模板,以及要先接入 DocNexus 才能创建的模板。
|
|
620
619
|
|
|
621
620
|
**模板导入 DocNexus**:
|
|
622
621
|
|
|
@@ -630,7 +629,7 @@ npx @rowansenne/workflow-run seed-templates --diff # 团队改过
|
|
|
630
629
|
* 只导入 DocNexus 里还没有的、有默认版本的模板(技术方案、上线方案不在内),已有的不覆盖;项目已接入但缺模板时,安装结束会列出缺哪几份。
|
|
631
630
|
* 之后模板随知识库更新:直接编辑 `workflow-run/docnexus/library/templates/...` 后在 `workflow-run/` 下执行 `./docnexus/node_modules/.bin/docnexus document sync --id <id>` 采纳;或者在生成文档后,skill 发现你做了结构性调整时会提议同步回模板(你确认后才写入)。每次变更都记录在 DocNexus 的 timeline 里,可追溯。
|
|
632
631
|
* 模板里的 `{{...}}` 是给 agent 的填写提示,DocNexus 原样保存;不要写成单独一行的 `{{fact:...}}`(那是 DocNexus 的事实引用语法)。
|
|
633
|
-
*
|
|
632
|
+
* 以前放在 `workflow-run/templates/` 下的项目模板:接入 DocNexus 后,缺模板时 skill 会把它作为 `import_from` 提议导入知识库;导入后删除这些文件。
|
|
634
633
|
|
|
635
634
|
## 触发准确度评估
|
|
636
635
|
|
package/bin/lib/doctor.mjs
CHANGED
|
@@ -36,7 +36,7 @@ export function doctor(root, offline) {
|
|
|
36
36
|
if (!found.length) { bad('未找到安装清单:本项目还没用 workflow-run 安装过'); return 1; }
|
|
37
37
|
const m = found[0].m;
|
|
38
38
|
const c = cmpVersion(m.version ?? '0', PKG.version);
|
|
39
|
-
if (c < 0) meh(`已安装 ${m.version},当前包是 ${PKG.version}:运行 workflow-run upgrade 升级`);
|
|
39
|
+
if (c < 0) meh(`已安装 ${m.version},当前包是 ${PKG.version}:运行 npx @rowansenne/workflow-run upgrade 升级`);
|
|
40
40
|
else if (c > 0) meh(`已安装 ${m.version},比当前包 ${PKG.version} 新(当前包版本过旧)`);
|
|
41
41
|
else ok(`已安装版本 ${m.version}(环境 ${(m.envs ?? []).join(',')},模式 ${m.mode})`);
|
|
42
42
|
|
|
@@ -45,12 +45,12 @@ export function doctor(root, offline) {
|
|
|
45
45
|
let modified = 0, missing = 0;
|
|
46
46
|
for (const [skill, entry] of Object.entries(man.skills)) {
|
|
47
47
|
const dir = path.join(base, skill);
|
|
48
|
-
if (!fs.existsSync(dir)) { bad(`${toPosix(path.join(rel, skill))} 不存在:运行 workflow-run upgrade 恢复`); continue; }
|
|
48
|
+
if (!fs.existsSync(dir)) { bad(`${toPosix(path.join(rel, skill))} 不存在:运行 npx @rowansenne/workflow-run upgrade 恢复`); continue; }
|
|
49
49
|
for (const [f, h] of Object.entries(entry.files ?? {})) {
|
|
50
50
|
const file = path.join(dir, f);
|
|
51
51
|
const label = toPosix(path.join(rel, skill, f));
|
|
52
|
-
if (!fs.existsSync(file)) { missing++; meh(`缺少 ${label}:运行 workflow-run upgrade 恢复`); }
|
|
53
|
-
else if (fileHash(file) !== h) { modified++; meh(`${label} 被手动修改过(升级时会被新版覆盖,原文件备份到 workflow-run/tmp/upgrade-backup/;项目定制请放到 profile.json
|
|
52
|
+
if (!fs.existsSync(file)) { missing++; meh(`缺少 ${label}:运行 npx @rowansenne/workflow-run upgrade 恢复`); }
|
|
53
|
+
else if (fileHash(file) !== h) { modified++; meh(`${label} 被手动修改过(升级时会被新版覆盖,原文件备份到 workflow-run/tmp/upgrade-backup/;项目定制请放到 profile.json 或 DocNexus,模板只能在 DocNexus 里定制)`); }
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
if (!modified && !missing) ok(`${toPosix(rel)}:${Object.keys(man.skills).length} 个 skill 的模板文件与安装时一致`);
|
|
@@ -67,7 +67,7 @@ export function doctor(root, offline) {
|
|
|
67
67
|
for (const skill of Object.keys(canon.m.skills)) {
|
|
68
68
|
const link = path.join(dir, skill);
|
|
69
69
|
const st = lstat(link);
|
|
70
|
-
if (!st) bad(`${d}/${skill} 不存在:运行 workflow-run upgrade 重建`);
|
|
70
|
+
if (!st) bad(`${d}/${skill} 不存在:运行 npx @rowansenne/workflow-run upgrade 重建`);
|
|
71
71
|
else if (!st.isSymbolicLink()) { if (!readManifest(dir)) meh(`${d}/${skill} 是普通目录而非软链接(可能是建链接失败后的独立拷贝)`); else good++; }
|
|
72
72
|
else if (!fs.existsSync(link)) bad(`${d}/${skill} 是断开的软链接`);
|
|
73
73
|
else good++;
|
|
@@ -84,7 +84,7 @@ export function doctor(root, offline) {
|
|
|
84
84
|
if (fs.existsSync(resolveJs)) {
|
|
85
85
|
const r = spawnSync(process.execPath, [resolveJs, '--root', root, 'status'], { encoding: 'utf8' });
|
|
86
86
|
try { st = JSON.parse(r.stdout); } catch { bad(`resolve.mjs status 执行失败:${(r.stderr || '').trim().split('\n')[0]}`); }
|
|
87
|
-
} else bad('缺少 workflow/scripts/resolve.mjs:运行 workflow-run upgrade');
|
|
87
|
+
} else bad('缺少 workflow/scripts/resolve.mjs:运行 npx @rowansenne/workflow-run upgrade');
|
|
88
88
|
if (st) {
|
|
89
89
|
if (st.profile.ok) ok('项目画像已填写'); else meh(`项目画像未完成(空字段:${st.profile.empty.join('、')}):运行 /workflow profile`);
|
|
90
90
|
if (st.wiki.ok) ok('wiki 已配置'); else console.log(' -- wiki 未配置(可选;也可能通过 wiki MCP 提供)');
|
|
@@ -93,7 +93,7 @@ export function doctor(root, offline) {
|
|
|
93
93
|
const linked = INSTALL_BASES.some((b) => lstat(path.join(root, b, 'docnexus-recall'))?.isSymbolicLink());
|
|
94
94
|
const ctx = ['CLAUDE.md', 'AGENTS.md'].some((f) => { try { return fs.readFileSync(path.join(root, f), 'utf8').includes('workflow-run:docnexus:start'); } catch { return false; } });
|
|
95
95
|
if (linked && ctx) ok(`DocNexus 在 ${HOME}/docnexus/,本项目已链接它的 skills 并写入段落`);
|
|
96
|
-
else meh(`DocNexus 在 ${HOME}/docnexus/,但本项目${linked ? '' : '缺少 docnexus skill 链接'}${!linked && !ctx ? '、' : ''}${ctx ? '' : '缺少 CLAUDE.md / AGENTS.md 里的 DocNexus 段落'}:运行 workflow-run upgrade`);
|
|
96
|
+
else meh(`DocNexus 在 ${HOME}/docnexus/,但本项目${linked ? '' : '缺少 docnexus skill 链接'}${!linked && !ctx ? '、' : ''}${ctx ? '' : '缺少 CLAUDE.md / AGENTS.md 里的 DocNexus 段落'}:运行 npx @rowansenne/workflow-run upgrade`);
|
|
97
97
|
}
|
|
98
98
|
// 产出目录:都在 workflow-run/
|
|
99
99
|
const mode = st.artifacts?.mode === 'repo' ? `独立文档仓库(${HOME}/ 自己是 git 仓库)` : '随项目提交';
|
|
@@ -101,15 +101,17 @@ export function doctor(root, offline) {
|
|
|
101
101
|
else ok(`产出目录 ${HOME}/:${mode}`);
|
|
102
102
|
if (st.docnexus.ok) {
|
|
103
103
|
if (!reportTemplateStatus(root, meh)) ok('DocNexus 已接入,文档模板齐全且与默认模板同步(或为团队定制版)');
|
|
104
|
-
for (const f of st.docnexus.stale_project_templates) meh(`${f} 在接入 DocNexus 后已不再生效,建议删除`);
|
|
105
104
|
if (docnexusSupportsCategory(root) === false) meh(`已装的 DocNexus 不支持 draft seal --category:各 skill 的分类只能经 metadata.category 写入,不记为调用方指定。升级:${docnexusUpgradeCmd()}`);
|
|
106
105
|
else ok('DocNexus 支持调用方显式分类(draft seal --category)');
|
|
107
106
|
if (docnexusSupportsRecallCategory(root) === false) meh(`已装的 DocNexus 不支持 recall --category:knowledge.mjs --query 只列文档,skill 改用不带分类的 recall。升级:${docnexusUpgradeCmd()}`);
|
|
108
107
|
else ok('DocNexus 支持按分类检索(recall --category)');
|
|
109
|
-
} else console.log(' -- DocNexus
|
|
108
|
+
} else console.log(' -- DocNexus 未接入(可选;未接入时只能用 skills 自带的默认模板,不能修改)');
|
|
109
|
+
// workflow-run/templates/ 已不再生效:模板定制只放 DocNexus
|
|
110
|
+
for (const f of st.docnexus.stale_project_templates ?? []) meh(st.docnexus.ok ? `${f} 已不再生效:确认已导入 DocNexus 知识库后删除` : `${f} 已不再生效(模板定制只放 DocNexus):重跑 npx @rowansenne/workflow-run 并加 --with-docnexus 接入后导入知识库,再删除`);
|
|
111
|
+
for (const t of st.templates_need_docnexus ?? []) console.log(` -- ${t.skill} 的模板 ${t.id} 不随 skills 提供,要先接入 DocNexus 才能创建(重跑 npx @rowansenne/workflow-run 并加 --with-docnexus)`);
|
|
110
112
|
for (const t of st.templates_to_create ?? []) console.log(` -- ${t.skill} 的模板 ${t.id} 还没有创建(不随 skills 提供):第一次生成文档时会请你给一份样例文档来创建,保存到 ${t.expected}`);
|
|
111
113
|
if (st.codegraph?.ok) ok(`CodeGraph 已接入(codegraph ${codegraphVersion(root)},索引在 .codegraph/)`);
|
|
112
|
-
else if (st.codegraph?.indexed) meh('有 .codegraph/ 索引但找不到 codegraph 命令:npm i -g @colbymchenry/codegraph,或重跑 workflow-run 并加 --with-codegraph');
|
|
114
|
+
else if (st.codegraph?.indexed) meh('有 .codegraph/ 索引但找不到 codegraph 命令:npm i -g @colbymchenry/codegraph,或重跑 npx @rowansenne/workflow-run 并加 --with-codegraph');
|
|
113
115
|
else if (st.codegraph?.cli) console.log(' -- 已装 codegraph,但本项目没有建索引(可选:在项目根运行 codegraph init)');
|
|
114
116
|
else console.log(' -- CodeGraph 未接入(可选)');
|
|
115
117
|
if (!st.database.ok) console.log(' -- 数据库未配置(可选)');
|
|
@@ -133,7 +135,7 @@ export function doctor(root, offline) {
|
|
|
133
135
|
const lines = fs.existsSync(gi) ? fs.readFileSync(gi, 'utf8').split(/\r?\n/).map((l) => l.trim()) : [];
|
|
134
136
|
const need = ['**/database-query/config.json', '**/wiki-config.json'];
|
|
135
137
|
const lack = need.filter((r) => !lines.includes(r));
|
|
136
|
-
if (lack.length) bad(`.gitignore 缺少 ${lack.join(' ')}:凭据可能被提交,重跑 workflow-run upgrade 补齐`); else ok('凭据文件已被忽略');
|
|
138
|
+
if (lack.length) bad(`.gitignore 缺少 ${lack.join(' ')}:凭据可能被提交,重跑 npx @rowansenne/workflow-run upgrade 补齐`); else ok('凭据文件已被忽略');
|
|
137
139
|
|
|
138
140
|
console.log(`\n${errors.length} 个错误,${warns.length} 个警告`);
|
|
139
141
|
return errors.length ? 1 : 0;
|
package/bin/lib/install.mjs
CHANGED
|
@@ -12,7 +12,7 @@ import { detectEnv } from '../../workflow/scripts/resolve.mjs';
|
|
|
12
12
|
export const report = { overwritten: [], removed: [], unlisted: [], unlistedDirs: [], backupDir: null };
|
|
13
13
|
|
|
14
14
|
// skills 目录里的文件一律以安装包为准:手改过的先备份到 <项目根>/workflow-run/tmp/upgrade-backup/<时间>/(同一次运行共用一个目录),
|
|
15
|
-
// 再覆盖或删除。项目自己的定制应放在不会被升级覆盖的地方:workflow/profile.json、
|
|
15
|
+
// 再覆盖或删除。项目自己的定制应放在不会被升级覆盖的地方:workflow/profile.json、DocNexus(文档模板只能在这里定制)、CLAUDE.md / AGENTS.md
|
|
16
16
|
let stamp = null;
|
|
17
17
|
function backup(root, file) {
|
|
18
18
|
stamp ??= timestamp();
|
package/bin/seed-templates.mjs
CHANGED
|
@@ -140,9 +140,9 @@ export function updateTemplates(root, tplDir, records = {}, { ok = console.log,
|
|
|
140
140
|
|
|
141
141
|
export const STATUS_TEXT = {
|
|
142
142
|
current: '与默认模板一致',
|
|
143
|
-
outdated: '默认模板有新版,库中模板未改动:运行 workflow-run seed-templates --update 更新',
|
|
144
|
-
customized: '团队改过,默认模板也有新版:运行 workflow-run seed-templates --diff 查看差异后手动合并',
|
|
143
|
+
outdated: '默认模板有新版,库中模板未改动:运行 npx @rowansenne/workflow-run seed-templates --update 更新',
|
|
144
|
+
customized: '团队改过,默认模板也有新版:运行 npx @rowansenne/workflow-run seed-templates --diff 查看差异后手动合并',
|
|
145
145
|
edited: '团队改过(默认模板无变化)',
|
|
146
|
-
untracked: '没有导入记录,内容与默认模板不同:如需采用新默认模板,运行 workflow-run seed-templates --diff 对比',
|
|
147
|
-
missing: '知识库中缺失:运行 workflow-run seed-templates 导入(upgrade 时会自动导入)',
|
|
146
|
+
untracked: '没有导入记录,内容与默认模板不同:如需采用新默认模板,运行 npx @rowansenne/workflow-run seed-templates --diff 对比',
|
|
147
|
+
missing: '知识库中缺失:运行 npx @rowansenne/workflow-run seed-templates 导入(upgrade 时会自动导入)',
|
|
148
148
|
};
|
package/bin/workflow-run.mjs
CHANGED
|
@@ -244,7 +244,7 @@ async function main() {
|
|
|
244
244
|
// upgrade 顺带的导入是尽力而为:失败只提示,不让升级本身算失败
|
|
245
245
|
const explicit = o.seedTemplates || o.withDocNexus;
|
|
246
246
|
seedFailed = explicit && r.failed.length > 0;
|
|
247
|
-
if (!explicit && r.failed.length) warn('新增模板导入失败(skills 已升级):修复后运行 workflow-run seed-templates 重试');
|
|
247
|
+
if (!explicit && r.failed.length) warn('新增模板导入失败(skills 已升级):修复后运行 npx @rowansenne/workflow-run seed-templates 重试');
|
|
248
248
|
if (upgradeSeed && !r.seeded.length && !r.failed.length) ok('知识库里的文档模板齐全,无需导入');
|
|
249
249
|
} catch (e) { warn(e.message); seedFailed = o.seedTemplates || o.withDocNexus; }
|
|
250
250
|
}
|
|
@@ -265,7 +265,7 @@ async function main() {
|
|
|
265
265
|
if (docnexusConnected(o.root)) reportTemplateStatus(o.root);
|
|
266
266
|
if (docnexus === 'failed') warn('注意:DocNexus 接入失败(见上方输出),其他 skills 不受影响;修复后可重跑(加 --with-docnexus)。');
|
|
267
267
|
if (codegraph === 'failed') warn('注意:CodeGraph 接入失败(见上方输出),其他 skills 不受影响;skills 会退回 grep / 读文件;修复后可重跑(加 --with-codegraph)。');
|
|
268
|
-
const keep = '(skills 目录里的文件以安装包为准;项目定制请放到 workflow/profile.json、
|
|
268
|
+
const keep = '(skills 目录里的文件以安装包为准;项目定制请放到 workflow/profile.json、DocNexus(文档模板只能在这里定制)或 CLAUDE.md / AGENTS.md)';
|
|
269
269
|
if (report.overwritten.length || report.removed.length) {
|
|
270
270
|
warn(`以下文件被手动修改过,已按新版${report.removed.length ? '覆盖或删除' : '覆盖'},原文件备份在 ${report.backupDir}/${keep}:`);
|
|
271
271
|
for (const f of report.overwritten) warn(` ${f}`);
|
|
@@ -39,8 +39,9 @@ description: "Generate a Markdown release/deployment plan (上线方案) from th
|
|
|
39
39
|
|
|
40
40
|
- 模板:在项目根运行 `node <skills>/workflow/scripts/resolve.mjs template create-release-md-doc template.md`(`<skills>` 是本 skill 所在的 skills 目录,如 `.agents/skills`),读输出的 `path`,并把 `source` 写进元数据行。上线方案模板**不随 skills 提供**,由各团队按自己 wiki 上的格式创建:
|
|
41
41
|
- 退出码 2 且 `on_demand: true` → 还没有创建模板:**停下这一步**,按 `<skills>/workflow/references/templates.md`「创建模板」请用户给一份团队现有的上线方案作样例,生成模板、用户确认后保存到输出的 `expected`,再继续。不要自己编一份通用模板凑数。
|
|
42
|
-
- 退出码 2
|
|
43
|
-
-
|
|
42
|
+
- 退出码 2 且 `need_docnexus: true` → 未接入 DocNexus:上线方案模板只保存在 DocNexus 里,**停下这一步**告诉用户先重跑 workflow-run 并加 `--with-docnexus` 接入,再按「创建模板」创建。不要另存到别处。
|
|
43
|
+
- 退出码 2 的其他情况 → 按输出的 `hint` 处理。
|
|
44
|
+
- 用户要修改、重新生成或换一份上线方案模板时,按 `<skills>/workflow/references/templates.md`「修改模板」用 `template.mjs` 处理(模板别名 `release`;按样例重做用 `draft release --from <样例>`),保存写入 DocNexus 知识库。
|
|
44
45
|
- 填充:模板的章节和编号因团队而异,**按章节含义**放事实,不按编号。下表是事实的来源,放进模板里含义对应的章节;模板里没有对应章节的事实不擅自加章节,在交付摘要里列出「模板中没有位置的事实」;模板有、但 diff 和 PRD 都给不出内容的章节写「待补充」。
|
|
45
46
|
|
|
46
47
|
| 事实 | 来源 |
|
|
@@ -38,8 +38,9 @@ description: "Generate a Markdown technical design doc (技术方案) from the d
|
|
|
38
38
|
|
|
39
39
|
- 模板:在项目根运行 `node <skills>/workflow/scripts/resolve.mjs template create-tech-md-doc template.md`(`<skills>` 是本 skill 所在的 skills 目录,如 `.agents/skills`),读输出的 `path`,并把 `source` 写进元数据行。技术方案模板**不随 skills 提供**,由各团队按自己 wiki 上的格式创建:
|
|
40
40
|
- 退出码 2 且 `on_demand: true` → 还没有创建模板:**停下这一步**,按 `<skills>/workflow/references/templates.md`「创建模板」请用户给一份团队现有的技术方案作样例,生成模板、用户确认后保存到输出的 `expected`,再继续。不要自己编一份通用模板凑数。
|
|
41
|
-
- 退出码 2
|
|
42
|
-
-
|
|
41
|
+
- 退出码 2 且 `need_docnexus: true` → 未接入 DocNexus:技术方案模板只保存在 DocNexus 里,**停下这一步**告诉用户先重跑 workflow-run 并加 `--with-docnexus` 接入,再按「创建模板」创建。不要另存到别处。
|
|
42
|
+
- 退出码 2 的其他情况 → 按输出的 `hint` 处理。
|
|
43
|
+
- 用户要修改、重新生成或换一份技术方案模板时,按 `<skills>/workflow/references/templates.md`「修改模板」用 `template.mjs` 处理(模板别名 `tech`;按样例重做用 `draft tech --from <样例>`),保存写入 DocNexus 知识库。
|
|
43
44
|
- 填充:模板的章节和编号因团队而异,**按章节含义**放事实,不按编号。下表是事实的来源,放进模板里含义对应的章节;模板里没有对应章节的事实不擅自加章节,在交付摘要里列出「模板中没有位置的事实」;模板有、但 diff 和 PRD 都给不出内容的章节写「待补充」。
|
|
44
45
|
|
|
45
46
|
| 事实 | 来源 |
|
package/package.json
CHANGED
package/workflow/SKILL.md.tpl
CHANGED
|
@@ -33,10 +33,10 @@ description: "Entry point for this project's dev workflow skills: routes a reque
|
|
|
33
33
|
| 写 PR / MR 描述、提 PR | `workflow/scripts/pr-desc.mjs` | 汇总本分支交付说明、审查报告、技术 / 上线方案;创建 PR 需用户同意 |
|
|
34
34
|
| 这套工作流效果怎么样、用得怎么样 | `/workflow report` | 只读统计 `workflow-run/docs/requirements/` 下的产物 |
|
|
35
35
|
| 看看项目文档、某个需求留下了哪些文档、审查记录 | `/workflow view` | 生成本地静态页面,按需求浏览 |
|
|
36
|
-
| 改技术方案 / 上线方案 / 交付说明 / 审查报告的模板,按样例建模板 | `/workflow template` | 草稿 → 校验与影响 →
|
|
36
|
+
| 改技术方案 / 上线方案 / 交付说明 / 审查报告的模板,按样例建模板 | `/workflow template` | 草稿 → 校验与影响 → 用户确认后写入 DocNexus(默认模板只读,未接入 DocNexus 时不能改) |
|
|
37
37
|
| 记住 / 查找项目决策与约定 | DocNexus(入口 skill `docnexus`) | 需已接入;写入必须用户授权 |
|
|
38
38
|
|
|
39
|
-
意图明确时直接按对应 skill 执行,不必先输出这张表。目标 skill 没有安装(`resolve.mjs status` 输出的 `skills` 里没有它,安装时用了 `--skills` 子集)→ 告诉用户可以运行 `workflow-run --skills <名称>` 补装,不要假装执行。意图横跨多个阶段时按下面的「完整链路」逐段推进,每段结束告诉用户下一段是什么,由用户决定是否继续。走到哪一步不靠记忆:运行 `node <skills>/workflow/scripts/artifacts.mjs [--branch <分支>]`,它扫描 `workflow-run/docs/requirements/` 下的产物,按元信息行里的分支归组,输出每类最新的一份、wiki 发布记录和 `next`(下一步建议)。
|
|
39
|
+
意图明确时直接按对应 skill 执行,不必先输出这张表。目标 skill 没有安装(`resolve.mjs status` 输出的 `skills` 里没有它,安装时用了 `--skills` 子集)→ 告诉用户可以运行 `npx @rowansenne/workflow-run --skills <名称>` 补装,不要假装执行。意图横跨多个阶段时按下面的「完整链路」逐段推进,每段结束告诉用户下一段是什么,由用户决定是否继续。走到哪一步不靠记忆:运行 `node <skills>/workflow/scripts/artifacts.mjs [--branch <分支>]`,它扫描 `workflow-run/docs/requirements/` 下的产物,按元信息行里的分支归组,输出每类最新的一份、wiki 发布记录和 `next`(下一步建议)。
|
|
40
40
|
|
|
41
41
|
### 完整链路(从需求到上线)
|
|
42
42
|
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
|---|---|---|
|
|
10
10
|
| 项目画像 | ✅ / ⚠️ 部分字段为空 | <空字段>;运行 /workflow profile |
|
|
11
11
|
| wiki | ✅ / ❌ | 填写 md-to-wiki/wiki-config.json 或接入 wiki MCP |
|
|
12
|
-
| DocNexus | ✅ / ❌ | 重跑 workflow-run 并加 --with-docnexus;已接入但缺模板时列出缺的模板并提示 `workflow-run seed-templates` |
|
|
12
|
+
| DocNexus | ✅ / ❌ | 重跑 npx @rowansenne/workflow-run 并加 --with-docnexus;已接入但缺模板时列出缺的模板并提示 `npx @rowansenne/workflow-run seed-templates`;未接入时说明默认模板只读、不能定制,技术方案 / 上线方案要先接入(`templates_need_docnexus`);`stale_project_templates` 非空时提示这些项目模板已不再生效 |
|
|
13
13
|
| 数据库 | ✅ / ❌ | 重跑 `npx @rowansenne/workflow-run` 补配 |
|
|
14
|
-
| 代码图谱 | ✅ / ⚠️ 已装未建索引 / ❌ | 重跑 workflow-run 并加 --with-codegraph;已装 codegraph 但没有 .codegraph/ 时提示用户自己运行 codegraph init |
|
|
14
|
+
| 代码图谱 | ✅ / ⚠️ 已装未建索引 / ❌ | 重跑 npx @rowansenne/workflow-run 并加 --with-codegraph;已装 codegraph 但没有 .codegraph/ 时提示用户自己运行 codegraph init |
|
|
15
15
|
|
|
16
16
|
## 当前分支 <分支>
|
|
17
17
|
| 环节 | 产物 | wiki |
|
|
@@ -6,19 +6,25 @@
|
|
|
6
6
|
node <skills>/workflow/scripts/resolve.mjs template <skill> <文件名>
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
`<skills>` 是本 skill 所在的 skills 目录(如 `.agents/skills`),在项目根执行。输出 JSON:`path` 是要读的模板,`source` 是 `docnexus` / `
|
|
9
|
+
`<skills>` 是本 skill 所在的 skills 目录(如 `.agents/skills`),在项目根执行。输出 JSON:`path` 是要读的模板,`source` 是 `docnexus` / `default`,写进产出的「模板来源」。
|
|
10
|
+
|
|
11
|
+
**skills 自带的默认模板只读**:不要直接编辑 skills 目录里的模板文件(升级时会被覆盖),也不要在 `workflow-run/templates/` 放项目模板(已不再生效)。要改模板只有一条路:写进 DocNexus 知识库,团队通过知识库共享同一份。
|
|
12
|
+
|
|
13
|
+
判定规则(实现在脚本里,这里只是说明):
|
|
10
14
|
|
|
11
15
|
- **已接入 DocNexus**:只用 `workflow-run/docnexus/library/templates/<skill>/<文件名>`(分类 `doc-template`,普通 Markdown,手工改动立即生效)。不使用 skill 默认模板,也不使用 `workflow-run/templates/`——知识库是唯一来源,避免几份模板各自演化。
|
|
12
|
-
- 缺模板时退出码 2,输出 `expected`(应在的位置)、`import_from`(可导入的来源)和 `hint`。**停下这一步**,告诉用户缺哪份模板,给两个选择:在项目根运行 `workflow-run seed-templates`(或重跑安装加 `--seed-templates`);或者由你在用户确认后按 DocNexus 的 capture 流程把 `import_from` 写入 `expected`,以显式分类封存(`draft seal ... --category doc-template`,metadata.category 也写 `doc-template`)。导入后再继续。
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
- **技术方案、上线方案没有默认模板**(`create-tech-md-doc`、`create-release-md-doc` 的 `template.md`):各团队发到 wiki 的格式不同,skills
|
|
16
|
+
- 缺模板时退出码 2,输出 `expected`(应在的位置)、`import_from`(可导入的来源)和 `hint`。**停下这一步**,告诉用户缺哪份模板,给两个选择:在项目根运行 `npx @rowansenne/workflow-run seed-templates`(或重跑安装加 `--seed-templates`);或者由你在用户确认后按 DocNexus 的 capture 流程把 `import_from` 写入 `expected`,以显式分类封存(`draft seal ... --category doc-template`,metadata.category 也写 `doc-template`)。导入后再继续。
|
|
17
|
+
- **未接入 DocNexus**:只用 skill 默认模板,不能修改或新建模板。
|
|
18
|
+
- 输出里 `stale_project_file` 非空:`workflow-run/templates/` 下的这份已不再生效,提醒用户导入 DocNexus 后删除(未接入时先接入)。
|
|
19
|
+
- **技术方案、上线方案没有默认模板**(`create-tech-md-doc`、`create-release-md-doc` 的 `template.md`):各团队发到 wiki 的格式不同,skills 不自带固定格式,第一次使用时按样例创建到知识库。
|
|
20
|
+
- 已接入 DocNexus、还没创建:退出码 2,输出 `on_demand: true`、`expected`(知识库里的位置)和 `hint`,按下面「创建模板」处理。
|
|
21
|
+
- 未接入 DocNexus:退出码 2,输出 `need_docnexus: true` 和 `hint`。**停下这一步**,告诉用户这两类文档的模板只保存在 DocNexus 里,要先重跑 npx @rowansenne/workflow-run 并加 `--with-docnexus` 接入,再创建模板。不要自己编一份模板凑数。
|
|
16
22
|
|
|
17
|
-
`resolve.mjs templates` 列出所有登记模板的来源;登记表在各 skill 的 `skill.json`(`templates` 字段)。`--with-docnexus` 接入时会自动导入默认模板,之后可运行 `workflow-run seed-templates` 补导入(已存在的不覆盖)。
|
|
23
|
+
`resolve.mjs templates` 列出所有登记模板的来源;登记表在各 skill 的 `skill.json`(`templates` 字段)。`--with-docnexus` 接入时会自动导入默认模板,之后可运行 `npx @rowansenne/workflow-run seed-templates` 补导入(已存在的不覆盖)。
|
|
18
24
|
|
|
19
25
|
## 修改模板(/workflow template)
|
|
20
26
|
|
|
21
|
-
用户要改某份模板(「技术方案模板加一节回滚」「上线方案去掉灰度那节」「审查报告的严重问题表加一列」),或要新建、按样例重做模板时,用 `template.mjs`
|
|
27
|
+
用户要改某份模板(「技术方案模板加一节回滚」「上线方案去掉灰度那节」「审查报告的严重问题表加一列」),或要新建、按样例重做模板时,用 `template.mjs` 一路走完,不要直接编辑生效中的模板文件。未接入 DocNexus 时 `draft` / `save` 退出码 2、输出 `need_docnexus: true`:告诉用户默认模板不能改,要先接入 DocNexus(重跑 npx @rowansenne/workflow-run 并加 `--with-docnexus`),不要另找地方保存。`<模板>` 写别名 `tech` / `release` / `plan` / `delivery` / `review` / `checklist`,或 `<skill>/<文件名>`;没说哪份时先 `template.mjs list` 列出来问。
|
|
22
28
|
|
|
23
29
|
1. **起草稿**:`node <skills>/workflow/scripts/template.mjs draft <模板>`,把当前生效的模板复制到 `workflow-run/tmp/template-draft/<skill>/<文件名>`(输出的 `draft`)。草稿已存在会沿用(上次没改完);要从当前模板重来加 `--force`。
|
|
24
30
|
- 退出码 2、`need_sample: true`:还没有这份模板,按下面「创建模板」第 1 步向用户要样例,再运行 `draft <模板> --from <样例文件>`(从 stdin 读用 `--from -`)。用户要「按这份文档重做模板」时同样用 `--from`。
|
|
@@ -28,14 +34,12 @@ node <skills>/workflow/scripts/resolve.mjs template <skill> <文件名>
|
|
|
28
34
|
- `impact`:最近几份已生成的文档按新模板会多出哪些错误(例如新的必填章节它们没有)。只影响以后生成和 lint,已有文档不会被改;
|
|
29
35
|
- `warnings`:例如没有任何必填章节;
|
|
30
36
|
- 附上草稿全文(或改动的部分)。
|
|
31
|
-
4. **用户确认后保存**:`node <skills>/workflow/scripts/template.mjs save
|
|
32
|
-
|
|
33
|
-
- 已接入 DocNexus:退出码 2,按输出的 `hint` 走 capture 流程把草稿写入知识库(写入要用户授权),完成后运行 `resolve.mjs template <skill> <文件名>` 确认 `path` 指向知识库里的那份,再删除草稿。
|
|
34
|
-
5. 用户想撤销:把 `backup` 复制回 `saved` 的位置(未接入 DocNexus);DocNexus 里的模板按 timeline 恢复旧版本。
|
|
37
|
+
4. **用户确认后保存**:`node <skills>/workflow/scripts/template.mjs save <模板>`。它不直接写知识库,退出码 2:按输出的 `hint` 走 capture 流程把草稿写入知识库(写入要用户授权),完成后运行 `resolve.mjs template <skill> <文件名>` 确认 `path` 指向知识库里的那份,再删除草稿。改的是带默认版本的模板(plan / delivery / review / checklist)时,知识库里的版本取代默认版本,以后升级 skills 也不会覆盖它。
|
|
38
|
+
5. 用户想撤销:DocNexus 里的模板按 timeline 恢复旧版本。
|
|
35
39
|
|
|
36
40
|
## 创建模板
|
|
37
41
|
|
|
38
|
-
|
|
42
|
+
需要已接入 DocNexus。技术方案、上线方案第一次生成时没有模板,由用户给一份**团队现有的同类文档**作样例来创建。用户也可以随时主动要求「创建 / 重新生成技术方案(上线方案)模板」,流程相同。
|
|
39
43
|
|
|
40
44
|
1. **要样例**:停下来告诉用户还没有这份模板,请用户给一份团队现有的同类文档:本地 Markdown 路径,或 wiki 页面的 pageId / URL。
|
|
41
45
|
- wiki 页面:运行 `node <skills>/md-to-wiki/scripts/upload.mjs get <pageId> --text`,取输出的 `text` 作样例(需要 wiki 已配置,见 `<skills>/workflow/SKILL.md`「增强能力探测」;没配置就请用户导出成 Markdown 或直接贴出内容)。
|
|
@@ -45,8 +49,8 @@ node <skills>/workflow/scripts/resolve.mjs template <skill> <文件名>
|
|
|
45
49
|
- 把每节的 `{{...}}` 改成具体的填写说明(这一节写什么、从哪类事实来,例如「受影响的接口、模块,带文件路径」),不要把样例里的具体业务内容留在模板里;
|
|
46
50
|
- 必填章节在标题末尾加 ` *`,可选章节在标题里加「(如有)」:`lint-doc.mjs` 靠这两个标记检查生成的文档;
|
|
47
51
|
- 对照这份 skill 会采集的事实(`references/diff-collection.md`),diff 能提供、但样例里没有对应章节的(例如配置、SQL、定时任务、回滚),列给用户问要不要加章节,不要擅自加。
|
|
48
|
-
4. **确认后保存**:`template.mjs check` 通过后把完整模板给用户看,用户确认后运行 `template.mjs save <模板>`(同「修改模板」第 4
|
|
52
|
+
4. **确认后保存**:`template.mjs check` 通过后把完整模板给用户看,用户确认后运行 `template.mjs save <模板>`(同「修改模板」第 4 步),按输出的 `hint` 走 capture 流程写入知识库(写入需要用户授权),以显式分类 `--category doc-template` 封存,metadata.category 也写 `doc-template`。
|
|
49
53
|
5. 保存后确认生效(`save` 输出 `effective: true`,或 DocNexus 写入后重新运行 `resolve.mjs template <skill> template.md`),再继续原来的生成步骤。
|
|
50
54
|
|
|
51
|
-
- **模板随知识库更新**:用户在生成的文档里做了结构性调整(新增 / 删除 /
|
|
55
|
+
- **模板随知识库更新**:用户在生成的文档里做了结构性调整(新增 / 删除 / 重排章节、改表格列、改必填项)时,交付后列出这些调整,**询问**是否同步回模板;同意后按 DocNexus 的 capture 流程更新同一路径(先 `document get --include document,metadata,timeline` 取 `record_version`,以 `--base-version <record_version> --category doc-template` 封存,用户确认后 `document add --draft <id> --replace`),DocNexus 会在 timeline 中记录每次变更。只改结构,不把某次需求的具体内容写进模板。用户也可以说「改模板」走上面的「修改模板」,或直接编辑库里的模板文件,再用 `<docnexus.bin> document sync --id <id>` 采纳(`<docnexus.bin>` 取 `resolve.mjs status` 的输出)。
|
|
52
56
|
- 模板里的 `{{...}}` 是给 agent 看的填写提示,不是模板引擎语法;不要写成单独一行的 `{{fact:...}}`(那是 DocNexus 的事实引用语法)。
|
|
@@ -39,7 +39,7 @@ export function run(root, args, opts = {}) {
|
|
|
39
39
|
const entry = cliEntry(root);
|
|
40
40
|
if (entry) return spawnSync(process.execPath, [entry, ...args], o);
|
|
41
41
|
const bin = docnexusBin(root);
|
|
42
|
-
if (!bin) return { status: 1, error: 'DocNexus 没装:重跑 workflow-run 并加 --with-docnexus' };
|
|
42
|
+
if (!bin) return { status: 1, error: 'DocNexus 没装:重跑 npx @rowansenne/workflow-run 并加 --with-docnexus' };
|
|
43
43
|
return spawnSync(path.resolve(root, bin), args, { ...o, shell: process.platform === 'win32' });
|
|
44
44
|
}
|
|
45
45
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
// node .agents/skills/workflow/scripts/resolve.mjs category <skill> # 该 skill 写入 DocNexus 时的显式分类
|
|
11
11
|
// node .agents/skills/workflow/scripts/resolve.mjs status # 能力探测(/workflow status)
|
|
12
12
|
// node .agents/skills/workflow/scripts/resolve.mjs env # 本机系统与终端(安装时记录),写终端命令按它来
|
|
13
|
-
// 输出 JSON。退出码:0 正常;2
|
|
13
|
+
// 输出 JSON。退出码:0 正常;2 缺该模板(知识库里没有,或未接入 DocNexus 而该模板没有默认版本;按输出的 hint 处理);1 参数错误 / 该 skill 没有声明分类
|
|
14
14
|
|
|
15
15
|
import fs from 'node:fs';
|
|
16
16
|
import path from 'node:path';
|
|
@@ -58,7 +58,7 @@ export function codegraphStatus(root) {
|
|
|
58
58
|
const cli = r.status === 0;
|
|
59
59
|
return {
|
|
60
60
|
ok: indexed && cli, cli, indexed,
|
|
61
|
-
how: cli && indexed ? null : !cli ? '重跑 workflow-run 并加 --with-codegraph(或 npm i -g @colbymchenry/codegraph)' : '在项目根运行 codegraph init 建索引(由用户决定)',
|
|
61
|
+
how: cli && indexed ? null : !cli ? '重跑 npx @rowansenne/workflow-run 并加 --with-codegraph(或 npm i -g @colbymchenry/codegraph)' : '在项目根运行 codegraph init 建索引(由用户决定)',
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
64
|
|
|
@@ -75,8 +75,10 @@ export function resolveTemplate(root, skill, id) {
|
|
|
75
75
|
// 没有 src 的模板(技术方案、上线方案)不随 skills 提供,缺失时按「创建模板」由用户给样例生成
|
|
76
76
|
const builtin = t.src ? path.join(SKILLS_DIR, skill, t.src.replace(/\.tpl$/, '')) : null;
|
|
77
77
|
const CREATE = '按 <skills>/workflow/references/templates.md「创建模板」处理:请用户给一份团队现有的同类文档作样例(本地 md 或 wiki pageId / URL),用 workflow/scripts/make-template.mjs 抽骨架,和用户确认后保存到 expected';
|
|
78
|
+
// workflow-run/templates/ 下的项目模板已不再生效(定制模板只放 DocNexus,便于共享),留着的只用来提示导入
|
|
79
|
+
const stale = fs.existsSync(project) ? rel(root, project) : null;
|
|
78
80
|
if (docnexusConnected(root)) {
|
|
79
|
-
const res = { skill, id, docnexus: true, stale_project_file:
|
|
81
|
+
const res = { skill, id, docnexus: true, stale_project_file: stale };
|
|
80
82
|
if (fs.existsSync(lib)) return { ok: true, ...res, source: 'docnexus', path: rel(root, lib) };
|
|
81
83
|
if (!builtin) {
|
|
82
84
|
return {
|
|
@@ -88,17 +90,18 @@ export function resolveTemplate(root, skill, id) {
|
|
|
88
90
|
return {
|
|
89
91
|
ok: false, ...res, error: 'missing', expected: rel(root, lib),
|
|
90
92
|
import_from: fs.existsSync(project) ? rel(root, project) : rel(root, builtin),
|
|
91
|
-
hint: '已接入 DocNexus,只使用知识库中的模板。停下这一步告诉用户缺这份模板:可在项目根运行 workflow-run seed-templates(或重跑安装加 --seed-templates),或经用户确认后把 import_from 按 capture 流程写入 expected(以显式分类 --category doc-template 封存)。',
|
|
93
|
+
hint: '已接入 DocNexus,只使用知识库中的模板。停下这一步告诉用户缺这份模板:可在项目根运行 npx @rowansenne/workflow-run seed-templates(或重跑安装加 --seed-templates),或经用户确认后把 import_from 按 capture 流程写入 expected(以显式分类 --category doc-template 封存)。',
|
|
92
94
|
};
|
|
93
95
|
}
|
|
94
|
-
|
|
96
|
+
// 未接入 DocNexus:只用 skill 自带的默认模板(只读,不能改);没有默认版本的(技术方案、上线方案)要先接入 DocNexus 才能创建
|
|
97
|
+
const res = { skill, id, docnexus: false, stale_project_file: stale };
|
|
95
98
|
if (!builtin) {
|
|
96
99
|
return {
|
|
97
|
-
ok: false,
|
|
98
|
-
hint: `这份模板不随 skills
|
|
100
|
+
ok: false, ...res, error: 'missing', need_docnexus: true, expected: rel(root, lib),
|
|
101
|
+
hint: `这份模板不随 skills 提供,自定义模板只保存在 DocNexus 知识库里(便于团队共享),本项目还没有接入 DocNexus。停下这一步告诉用户:先重跑 npx @rowansenne/workflow-run 并加 --with-docnexus 接入${stale ? `(项目里的 ${stale} 已不再生效,接入后可导入知识库)` : ''},再${CREATE}。`,
|
|
99
102
|
};
|
|
100
103
|
}
|
|
101
|
-
return { ok: true,
|
|
104
|
+
return { ok: true, ...res, source: 'default', path: rel(root, builtin) };
|
|
102
105
|
}
|
|
103
106
|
|
|
104
107
|
// DocNexus 对显式分类名的约束:1–80 字符,无首尾空白与控制字符(与 bin/skills.mjs 一致)
|
|
@@ -186,10 +189,11 @@ export function status(root) {
|
|
|
186
189
|
// 运行 DocNexus 命令的写法(在项目根执行,任何终端都一样):后面接原命令的参数;node 脚本前加 --node
|
|
187
190
|
run: `node ${(rel(root, path.join(SKILLS_DIR, 'workflow', 'scripts', 'docnexus.mjs')))}`,
|
|
188
191
|
missing_templates: dn ? templates.filter((t) => !t.ok && !t.on_demand).map((t) => t.expected) : [],
|
|
189
|
-
|
|
192
|
+
// workflow-run/templates/ 下已不生效的项目模板:接入 DocNexus 后导入知识库再删除
|
|
193
|
+
stale_project_templates: templates.map((t) => t.stale_project_file).filter(Boolean),
|
|
190
194
|
// 各 skill 写入时使用的显式分类(没声明的 skill 不列出)
|
|
191
195
|
categories: Object.fromEntries(skillMetas().map((m) => [m.name, resolveCategory(root, m.name)]).filter(([, c]) => c.ok).map(([n, c]) => [n, c.category])),
|
|
192
|
-
how: dn ? '缺模板时运行 workflow-run seed-templates' : '重跑 workflow-run 并加 --with-docnexus',
|
|
196
|
+
how: dn ? '缺模板时运行 npx @rowansenne/workflow-run seed-templates' : '重跑 npx @rowansenne/workflow-run 并加 --with-docnexus',
|
|
193
197
|
},
|
|
194
198
|
// 产物位置:项目里(默认)或独立文档仓库(workflow/references/requirements.md)
|
|
195
199
|
artifacts: (() => { const L = layout(root); return { mode: L.mode, ok: L.ok, ...(L.mode === 'repo' ? { repo: L.repo_rel, project: L.project, commit_prompt: L.commit_prompt } : { dir: 'workflow-run/docs/requirements' }), how: L.ok ? null : L.hint }; })(),
|
|
@@ -199,11 +203,13 @@ export function status(root) {
|
|
|
199
203
|
ok: !!db?.connections && Object.keys(db.connections).length > 0,
|
|
200
204
|
default: db?.default_connection ?? (db?.connections?.default ? 'default' : null),
|
|
201
205
|
connections: Object.fromEntries(Object.entries(db?.connections ?? {}).map(([k, c]) => [k, { driver: c.driver ?? 'mysql', readonly: c.readonly !== false }])),
|
|
202
|
-
how: '重跑 workflow-run 补配数据库',
|
|
206
|
+
how: '重跑 npx @rowansenne/workflow-run 补配数据库',
|
|
203
207
|
},
|
|
204
|
-
templates: templates.map(({ skill, id, source, path: p2, ok, on_demand, expected }) => ({ skill, id, ok, source: source ?? 'missing', path: p2 ?? null, ...(on_demand ? { on_demand: true, expected } : {}) })),
|
|
208
|
+
templates: templates.map(({ skill, id, source, path: p2, ok, on_demand, need_docnexus, expected }) => ({ skill, id, ok, source: source ?? 'missing', path: p2 ?? null, ...(on_demand ? { on_demand: true, expected } : {}), ...(need_docnexus ? { need_docnexus: true } : {}) })),
|
|
205
209
|
// 不随 skills 提供、还没创建的模板(技术方案、上线方案):第一次生成文档时按「创建模板」引导用户创建
|
|
206
210
|
templates_to_create: templates.filter((t) => t.on_demand).map((t) => ({ skill: t.skill, id: t.id, expected: t.expected })),
|
|
211
|
+
// 没有默认版本、要先接入 DocNexus 才能创建的模板(未接入时)
|
|
212
|
+
templates_need_docnexus: templates.filter((t) => t.need_docnexus).map((t) => ({ skill: t.skill, id: t.id })),
|
|
207
213
|
};
|
|
208
214
|
}
|
|
209
215
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// 修改 / 创建文档模板(/workflow template)的确定性步骤:起草稿 → 校验并与当前模板、已生成文档比对 → 确认后保存。
|
|
3
|
-
// 来源判定沿用 resolve.mjs template;改动只落在草稿 workflow-run/tmp/template-draft/<skill
|
|
4
|
-
//
|
|
3
|
+
// 来源判定沿用 resolve.mjs template;改动只落在草稿 workflow-run/tmp/template-draft/<skill>/<模板>。
|
|
4
|
+
// skill 自带的默认模板只读:定制模板只保存在 DocNexus 知识库里(便于团队共享),未接入 DocNexus 时 draft / save 退出码 2 提示先接入;
|
|
5
|
+
// save 也不直接写知识库(写入需按 capture 流程、经用户授权),退出码 2 并给出指引。
|
|
5
6
|
// 流程说明见 workflow/references/templates.md「修改模板」。
|
|
6
7
|
//
|
|
7
8
|
// 用法(在项目根执行;--root 可指定项目根):
|
|
@@ -12,8 +13,8 @@
|
|
|
12
13
|
// <模板>:tech | release | plan | delivery | review | checklist,或 <skill>[/<模板文件名>](如 create-tech-md-doc/template.md)
|
|
13
14
|
// draft:把当前生效的模板复制成草稿;还没有模板(或 --from)时按样例抽骨架(make-template.mjs)。草稿已存在时不覆盖,--force 重来
|
|
14
15
|
// check:草稿本身的格式问题、与当前模板相比的章节变化、拿最近几份已生成文档按新旧模板各跑一次 lint-doc 看影响
|
|
15
|
-
// save:check
|
|
16
|
-
// 输出 JSON。退出码:0 正常;1 参数错误 / 草稿有错误;2 需要按输出的 hint
|
|
16
|
+
// save:check 无错误后给出写入知识库的 capture 指引(写入后重新运行 resolve.mjs template 确认生效)
|
|
17
|
+
// 输出 JSON。退出码:0 正常;1 参数错误 / 草稿有错误;2 需要按输出的 hint 处理(缺样例、未接入 DocNexus、需 capture 写入)
|
|
17
18
|
|
|
18
19
|
import fs from 'node:fs';
|
|
19
20
|
import path from 'node:path';
|
|
@@ -37,7 +38,6 @@ const SAMPLE_DOCS = 5;
|
|
|
37
38
|
|
|
38
39
|
const rel = (root, p) => path.relative(root, p).split(path.sep).join('/');
|
|
39
40
|
const read = (f) => { try { return fs.readFileSync(f, 'utf8'); } catch { return null; } };
|
|
40
|
-
const stamp = () => new Date().toISOString().replace(/[-:]/g, '').replace(/\..*$/, '').replace('T', '-');
|
|
41
41
|
|
|
42
42
|
// <模板> → { skill, id };未知返回 null
|
|
43
43
|
export function target(name) {
|
|
@@ -50,6 +50,10 @@ export function target(name) {
|
|
|
50
50
|
return t ? { skill, id: t.id } : null;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
// 未接入 DocNexus:默认模板只读,不能改也不能新建
|
|
54
|
+
const NEED_DOCNEXUS = '默认模板随 skills 提供、只读不能改;自定义模板只保存在 DocNexus 知识库里,便于团队共享。告诉用户先重跑 npx @rowansenne/workflow-run 并加 --with-docnexus 接入,再修改或创建模板。';
|
|
55
|
+
const needDocNexus = (t, r) => ({ code: 2, out: { ok: false, skill: t.skill, id: t.id, docnexus: false, need_docnexus: true, current: r.ok ? r.path : null, hint: NEED_DOCNEXUS } });
|
|
56
|
+
|
|
53
57
|
const draftPath = (root, { skill, id }) => path.join(root, 'workflow-run', 'tmp', 'template-draft', skill, id);
|
|
54
58
|
|
|
55
59
|
// 草稿本身的格式检查:错误挡住保存,警告给用户看
|
|
@@ -118,8 +122,9 @@ function current(root, t) {
|
|
|
118
122
|
export function draft(root, t, { from = null, force = false, stdin = () => fs.readFileSync(0, 'utf8') } = {}) {
|
|
119
123
|
const file = draftPath(root, t);
|
|
120
124
|
const { r, text } = current(root, t);
|
|
121
|
-
|
|
122
|
-
if (r.
|
|
125
|
+
if (r.error === 'unknown') return { code: 1, out: { ok: false, skill: t.skill, id: t.id, message: r.message } };
|
|
126
|
+
if (!r.docnexus) return needDocNexus(t, r);
|
|
127
|
+
const base = { skill: t.skill, id: t.id, draft: rel(root, file), source: r.ok ? r.source : null, current: r.ok ? r.path : null, docnexus: true, expected: r.ok ? r.path : r.expected };
|
|
123
128
|
if (fs.existsSync(file) && !force && !from) return { code: 0, out: { ok: true, ...base, created: false, note: '草稿已存在,沿用上次的草稿;要从当前模板重来加 --force' } };
|
|
124
129
|
let content;
|
|
125
130
|
let origin;
|
|
@@ -164,28 +169,14 @@ export function save(root, t, file = null) {
|
|
|
164
169
|
if (c.code) return c;
|
|
165
170
|
if (c.out.unchanged) return { code: 0, out: { ok: true, skill: t.skill, id: t.id, saved: null, note: '草稿与当前模板相同,没有写入' } };
|
|
166
171
|
const r = resolveTemplate(root, t.skill, t.id);
|
|
167
|
-
if (r.docnexus)
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
const dst = path.join(root, 'workflow-run', 'templates', t.skill, t.id);
|
|
176
|
-
let backup = null;
|
|
177
|
-
if (fs.existsSync(dst)) {
|
|
178
|
-
backup = path.join(root, 'workflow-run', 'tmp', 'template-backup', stamp(), t.skill, t.id);
|
|
179
|
-
fs.mkdirSync(path.dirname(backup), { recursive: true });
|
|
180
|
-
fs.copyFileSync(dst, backup);
|
|
181
|
-
}
|
|
182
|
-
const src = path.resolve(root, c.out.draft);
|
|
183
|
-
fs.mkdirSync(path.dirname(dst), { recursive: true });
|
|
184
|
-
fs.writeFileSync(dst, fs.readFileSync(src, 'utf8'));
|
|
185
|
-
const after = resolveTemplate(root, t.skill, t.id);
|
|
186
|
-
const effective = after.ok && after.path === rel(root, dst);
|
|
187
|
-
if (effective && src === draftPath(root, t)) fs.rmSync(src);
|
|
188
|
-
return { code: effective ? 0 : 1, out: { ok: effective, skill: t.skill, id: t.id, saved: rel(root, dst), backup: backup && rel(root, backup), effective, source: after.source ?? null, warnings: c.out.warnings, changes: c.out.changes } };
|
|
172
|
+
if (!r.docnexus) return needDocNexus(t, r);
|
|
173
|
+
return {
|
|
174
|
+
code: 2, out: {
|
|
175
|
+
ok: false, skill: t.skill, id: t.id, docnexus: true, draft: c.out.draft, expected: r.ok ? r.path : r.expected,
|
|
176
|
+
hint: '模板只认知识库里的那份,写入要按 capture 流程并经用户授权:已有模板时先 document get --include document,metadata,timeline 取 record_version,以草稿内容 --base-version <record_version> --category doc-template 封存,用户确认后 document add --draft <id> --replace;还没有时以 --category doc-template 新建。完成后重新运行 resolve.mjs template 确认,再删除草稿。',
|
|
177
|
+
warnings: c.out.warnings, changes: c.out.changes,
|
|
178
|
+
},
|
|
179
|
+
};
|
|
189
180
|
}
|
|
190
181
|
|
|
191
182
|
export function list(root) {
|