@rowansenne/workflow-run 0.20.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -1
- package/README.md +11 -12
- package/bin/lib/doctor.mjs +5 -3
- package/bin/lib/install.mjs +1 -1
- package/bin/workflow-run.mjs +1 -1
- 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 +1 -1
- package/workflow/references/status.md +1 -1
- package/workflow/references/templates.md +16 -12
- package/workflow/scripts/resolve.mjs +14 -8
- package/workflow/scripts/template.mjs +20 -29
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.21.0] - 2026-10-18
|
|
8
|
+
|
|
9
|
+
### 变更(破坏性)
|
|
10
|
+
- **默认模板只读,定制模板只放 DocNexus**:skills 自带的模板不能改;修改或新建模板一律写进 DocNexus 知识库,便于团队共享(每次变更有 timeline)。`workflow-run/templates/` 下的项目模板不再生效,`resolve.mjs` 输出 `stale_project_file`,`doctor` 提示导入知识库后删除;接入 DocNexus 后缺模板时仍把它作为 `import_from` 提议导入。
|
|
11
|
+
- 未接入 DocNexus 时:只用默认模板;`template.mjs draft` / `save` 退出码 2、输出 `need_docnexus: true`,提示先 `--with-docnexus` 接入。技术方案、上线方案没有默认模板,`resolve.mjs template` 同样返回 `need_docnexus`,要先接入 DocNexus 才能创建模板和生成文档;`resolve.mjs status` 新增 `templates_need_docnexus`。
|
|
12
|
+
- `template.mjs save` 不再写项目文件、不再备份到 `workflow-run/tmp/template-backup/`,只给出写入知识库的 capture 指引;撤销按 DocNexus 的 timeline 恢复。
|
|
13
|
+
|
|
7
14
|
## [0.20.0] - 2026-10-18
|
|
8
15
|
|
|
9
16
|
### 变更
|
|
@@ -260,7 +267,8 @@
|
|
|
260
267
|
- 安装器改为单一 Node 实现,`init-skills.sh` / `init-skills.ps1` 只是薄封装。
|
|
261
268
|
- `code-review` 改名为 `project-review`,升级时自动清理旧名。
|
|
262
269
|
|
|
263
|
-
[Unreleased]: https://github.com/guilianerde/skills-init/compare/v0.
|
|
270
|
+
[Unreleased]: https://github.com/guilianerde/skills-init/compare/v0.21.0...HEAD
|
|
271
|
+
[0.21.0]: https://github.com/guilianerde/skills-init/compare/v0.20.0...v0.21.0
|
|
264
272
|
[0.20.0]: https://github.com/guilianerde/skills-init/compare/v0.19.0...v0.20.0
|
|
265
273
|
[0.19.0]: https://github.com/guilianerde/skills-init/compare/v0.18.0...v0.19.0
|
|
266
274
|
[0.18.0]: https://github.com/guilianerde/skills-init/compare/v0.17.0...v0.18.0
|
package/README.md
CHANGED
|
@@ -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
|
### 卸载
|
|
@@ -394,7 +394,7 @@ npx @rowansenne/workflow-run uninstall
|
|
|
394
394
|
| `workflow/scripts/artifacts.mjs [--branch b \| --all]` | 按分支汇总 `workflow-run/docs/requirements/` 下的开发方案、交付说明、审查报告、技术方案、上线方案及其 wiki 发布记录,给出下一步建议;分支取自文档元信息行,不另存记录。上线方案没传 `--tech` 时据此自动引用同分支的技术方案;project-review 据此对照本分支方案、识别复审 |
|
|
395
395
|
| `workflow/scripts/report.mjs [--since d] [--all-branches] [--json]` | 本地效果报告(`/workflow report`、`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` 之间,标记外的补充说明保留;指定的表在库里不存在时标出 |
|
|
@@ -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
|
@@ -50,7 +50,7 @@ export function doctor(root, offline) {
|
|
|
50
50
|
const file = path.join(dir, f);
|
|
51
51
|
const label = toPosix(path.join(rel, skill, f));
|
|
52
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
|
|
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 的模板文件与安装时一致`);
|
|
@@ -101,12 +101,14 @@ 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):重跑 workflow-run 并加 --with-docnexus 接入后导入知识库,再删除`);
|
|
111
|
+
for (const t of st.templates_need_docnexus ?? []) console.log(` -- ${t.skill} 的模板 ${t.id} 不随 skills 提供,要先接入 DocNexus 才能创建(重跑 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
114
|
else if (st.codegraph?.indexed) meh('有 .codegraph/ 索引但找不到 codegraph 命令:npm i -g @colbymchenry/codegraph,或重跑 workflow-run 并加 --with-codegraph');
|
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/workflow-run.mjs
CHANGED
|
@@ -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,7 +33,7 @@ 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
39
|
意图明确时直接按对应 skill 执行,不必先输出这张表。目标 skill 没有安装(`resolve.mjs status` 输出的 `skills` 里没有它,安装时用了 `--skills` 子集)→ 告诉用户可以运行 `workflow-run --skills <名称>` 补装,不要假装执行。意图横跨多个阶段时按下面的「完整链路」逐段推进,每段结束告诉用户下一段是什么,由用户决定是否继续。走到哪一步不靠记忆:运行 `node <skills>/workflow/scripts/artifacts.mjs [--branch <分支>]`,它扫描 `workflow-run/docs/requirements/` 下的产物,按元信息行里的分支归组,输出每类最新的一份、wiki 发布记录和 `next`(下一步建议)。
|
|
@@ -9,7 +9,7 @@
|
|
|
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 | ✅ / ❌ | 重跑 workflow-run 并加 --with-docnexus;已接入但缺模板时列出缺的模板并提示 `workflow-run seed-templates`;未接入时说明默认模板只读、不能定制,技术方案 / 上线方案要先接入(`templates_need_docnexus`);`stale_project_templates` 非空时提示这些项目模板已不再生效 |
|
|
13
13
|
| 数据库 | ✅ / ❌ | 重跑 `npx @rowansenne/workflow-run` 补配 |
|
|
14
14
|
| 代码图谱 | ✅ / ⚠️ 已装未建索引 / ❌ | 重跑 workflow-run 并加 --with-codegraph;已装 codegraph 但没有 .codegraph/ 时提示用户自己运行 codegraph init |
|
|
15
15
|
|
|
@@ -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
16
|
- 缺模板时退出码 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
|
|
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 里,要先重跑 workflow-run 并加 `--with-docnexus` 接入,再创建模板。不要自己编一份模板凑数。
|
|
16
22
|
|
|
17
23
|
`resolve.mjs templates` 列出所有登记模板的来源;登记表在各 skill 的 `skill.json`(`templates` 字段)。`--with-docnexus` 接入时会自动导入默认模板,之后可运行 `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(重跑 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 的事实引用语法)。
|
|
@@ -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';
|
|
@@ -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 {
|
|
@@ -91,14 +93,15 @@ export function resolveTemplate(root, skill, id) {
|
|
|
91
93
|
hint: '已接入 DocNexus,只使用知识库中的模板。停下这一步告诉用户缺这份模板:可在项目根运行 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。停下这一步告诉用户:先重跑 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,7 +189,8 @@ 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
196
|
how: dn ? '缺模板时运行 workflow-run seed-templates' : '重跑 workflow-run 并加 --with-docnexus',
|
|
@@ -201,9 +205,11 @@ export function status(root) {
|
|
|
201
205
|
connections: Object.fromEntries(Object.entries(db?.connections ?? {}).map(([k, c]) => [k, { driver: c.driver ?? 'mysql', readonly: c.readonly !== false }])),
|
|
202
206
|
how: '重跑 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 知识库里,便于团队共享。告诉用户先重跑 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) {
|