@namewta/speculo 1.0.13 → 1.0.15

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 (41) hide show
  1. package/README.md +3 -1
  2. package/package.json +1 -1
  3. package/template/canonical/canonical-specdev-goal-plan.md +9 -5
  4. package/template/canonical/canonical-specdev-grill-with-docs.md +6 -4
  5. package/template/canonical/canonical-specdev-spec.md +8 -4
  6. package/template/canonical/canonical-specdev-tickets.md +20 -4
  7. package/template/commands/handoff.md +1 -1
  8. package/template/commands/status.md +1 -1
  9. package/template/workflows/specdev/A-archive-and-consolidate/A-archive-and-consolidate.md +3 -3
  10. package/template/workflows/specdev/I-implement/references/implementation-procedure.md +1 -1
  11. package/template/workflows/specdev/I-init-setup/tracking-template.md +1 -1
  12. package/template/workflows/specdev/INDEX.md +1 -1
  13. package/template/workflows/specdev/README.md +4 -4
  14. package/template/workflows/specdev/T-tickets/ticket-template.md +1 -0
  15. package/template/workflows/specdev/T-triage/T-triage.md +80 -15
  16. package/template/workflows/specdev/T-triage/capture-protocol.md +89 -0
  17. package/template/workflows/specdev/T-triage/capture-template.md +42 -0
  18. package/template/workflows/specdev/T-triage/close-comment-template.md +42 -0
  19. package/template/workflows/specdev/T-triage/intake-protocol.md +8 -2
  20. package/template/workflows/specdev/T-triage/issue-body-template.md +34 -0
  21. package/template/workflows/specdev/T-triage/issue-record-template.md +27 -0
  22. package/template/workflows/specdev/T-triage/publish-protocol.md +92 -0
  23. package/template/workflows/specdev/T-triage/publish-template.md +49 -0
  24. package/template/workflows/specdev/T-triage/reconcile-protocol.md +3 -3
  25. package/template/workflows/specdev/T-triage/references/classification-map.md +54 -0
  26. package/template/workflows/specdev/T-triage/references/public-projection.md +89 -0
  27. package/template/workflows/specdev/T-triage/tools/capture-status.mjs +125 -0
  28. package/template/workflows/specdev/T-triage/tools/publish-status.mjs +148 -0
  29. package/template/workflows/specdev/T-triage/triage-template.md +12 -1
  30. package/template/workflows/specdev/common/README.md +2 -0
  31. package/template/workflows/specdev/common/rules/artifact-contract.md +6 -4
  32. package/template/workflows/specdev/common/rules/change-completion.md +1 -1
  33. package/template/workflows/specdev/common/rules/evidence-and-verification.md +2 -0
  34. package/template/workflows/specdev/common/rules/workflow-routing.md +3 -1
  35. package/template/workflows/specdev/common/rules/workflow-state-and-lifecycle.md +1 -0
  36. package/template/workflows/specdev/common/schemas/capture.schema.json +15 -0
  37. package/template/workflows/specdev/common/schemas/publish.schema.json +21 -0
  38. package/template/workflows/specdev/common/schemas/ticket.schema.json +11 -0
  39. package/template/workflows/specdev/common/schemas/triage.schema.json +3 -1
  40. package/template/workflows/specdev/common/tools/README.md +7 -0
  41. package/template/workflows/specdev/common/tools/validate-specdev.mjs +304 -6
@@ -0,0 +1,89 @@
1
+ # Capture Protocol
2
+
3
+ 仅在 Triage `mode=capture` 时加载。目标是把尚未成 Change 的记事项写成仍 open 的 GitHub Issue,并留下 workspace 级 `<Path>{roots.state}/specdev/capture.md</Path>`。
4
+
5
+ GitHub 是 inbox 和计数器,不是 tracker,也不是开发权威。capture 不创建、不选择、不改写任何 change。票级完成后投影走 publish,源 Issue 关闭走 reconcile,外部输入冻结走 intake;四者互不覆盖。
6
+
7
+ ## 1. 触发与对象
8
+
9
+ 用户必须给出至少一条记事项(标题、现在时摘要、分类)。禁止扫整个 workspace 自动发。允许一次授权批量多条;默认 **1 条记录 = 1 次未来 intake / 1 个未来 Change**。v1 不写 `related_locators`,不把 N 条 locator 塞进同一个未来 source。
10
+
11
+ 相关但目标不清 → 先 capture 为多条 inbox,以后走 `<Path>{roots.workflows}/specdev/W-wayfinder/W-wayfinder.md</Path>` 或逐条 intake,不在本协议合并。
12
+
13
+ 可选开关:排除 id 列表。目标 repo 默认从 `git remote` 推断,必须展示确认。
14
+
15
+ capture **不得**:
16
+
17
+ - 创建 change 目录或 `<Path>{roots.state}/specdev/changes/{change}/</Path>` 下任何工件;
18
+ - 写 `<Path>{roots.state}/specdev/changes/{change}/triage.md</Path>` / `<Path>{roots.state}/specdev/changes/{change}/source.md</Path>` / `<Path>{roots.state}/specdev/changes/{change}/publish.md</Path>`;
19
+ - 设置任何 change 的 `current_work`;
20
+ - 加载 `<Path>{roots.workflows}/specdev/common/rules/change-completion.md</Path>`;
21
+ - 调用 `issue-comment-close` 或关闭刚创建的 Issue;
22
+ - 在本地复制 inbox 正文副本;
23
+ - 打 `specdev:published`、`specdev:change`、`needs-triage`、`needs-info`、`ready-for-agent`、`ready-for-human`。
24
+
25
+ 只写 `<Path>{roots.state}/specdev/capture.md</Path>` 和经授权的远程 inbox Issue。缺失该账本合法,首次 capture 才创建。
26
+
27
+ ## 2. 硬门
28
+
29
+ 失败即停,零远程写入。已有账本行保持原 state。
30
+
31
+ 1. 每条纳入记录有 id(`YYYY-MM-DD-<kebab>`)、现在时摘要、且 `kind` 为 bug、feature、refactor、investigation、operations、documentation 或 review。禁止 `mixed`。
32
+ 2. 调用 `<Path>{roots.skills}/github-npm-ops/SKILL.md</Path>` 能读目标 repo、能 dry-run `issue-create`。本协议只用 `issue-search` / `issue-create`。
33
+ 3. 分类映射见 `<Path>{roots.workflows}/specdev/T-triage/references/classification-map.md</Path>`。缺 type 标签时 dry-run 表列出将创建的标签,授权后才 `gh label create`。
34
+ 4. 用户看见完整 dry-run 表(id、标题、标签、正文、reason)并给出 **本次** 明确确认。
35
+
36
+ origin 固定 `local`。marker:`specdev:capture:<id>`。
37
+
38
+ ## 3. 准备记录
39
+
40
+ 按 `<Path>{roots.workflows}/specdev/T-triage/references/public-projection.md</Path>` 脱敏。现在时,不是完成后的过去时,也不是派工祈使句。
41
+
42
+ Issue 正文:`<Path>{roots.workflows}/specdev/T-triage/issue-record-template.md</Path>`。
43
+
44
+ 用 `<Path>{roots.workflows}/specdev/T-triage/capture-template.md</Path>` 写或更新 `<Path>{roots.state}/specdev/capture.md</Path>`。先把纳入行标 `planned`,用户排除的标 `skipped:duplicate` 以外的跳过由执行期判定。
45
+
46
+ ## 4. 幂等执行
47
+
48
+ 对每条纳入记录:
49
+
50
+ 1. `issue-search` 查 marker 或精确标题 + `specdev:captured`。
51
+ 2. 已存在且 marker 在且仍 open → 账本 `open`,跳过创建。
52
+ 3. 已存在且 marker 在但已 closed → 停止该行,展示冲突,不重开、不覆盖。intake 已消耗的行应为 `intaken`,由 intake 协议回写,不由本协议改 closed。
53
+ 4. 已存在但无 marker → 停止该行,展示冲突,不覆盖别人的 Issue。
54
+ 5. 不存在 → dry-run `issue-create` → 授权后 `--apply` → 保持 **open**。marker 写在正文 Provenance。不评论、不关闭。
55
+ 6. 任一步失败:该行 `failed`,记录已完成步骤和下一重试动作;已成功的记录不回滚。
56
+
57
+ `--apply` 只表示调用方完成本次确认,不替代授权。远程失败不补建本地 Change。
58
+
59
+ 全部纳入记录到达 `open` 或合法 `skipped:duplicate`,且无 `failed` 时结束。用户明确放弃未发出的行:`waived`。重跑是恢复,不是重发。`intaken` 只由后续 intake 写入。
60
+
61
+ ## 5. 校验与计数
62
+
63
+ 账本存在时:
64
+
65
+ ```bash
66
+ node <Path>{roots.workflows}/specdev/common/tools/validate-specdev.mjs</Path> \
67
+ --capture <Path>{roots.state}/specdev/capture.md</Path>
68
+ ```
69
+
70
+ 缺失该文件时不要为了校验去创建它。
71
+
72
+ workspace inbox 计数:
73
+
74
+ ```bash
75
+ node <Path>{roots.workflows}/specdev/T-triage/tools/capture-status.mjs</Path> \
76
+ --state-root <Path>{roots.state}/specdev</Path>
77
+ ```
78
+
79
+ 数字只来自 `<Path>{roots.state}/specdev/capture.md</Path>`,不把 GitHub 搜索当权威,也不计入 `published_issues`。
80
+
81
+ ## 完成标准
82
+
83
+ - 用户指定的记事项均有对应仍 open 的 GitHub Issue,或账本有合法 skip / waived;
84
+ - 每条已捕获 Issue 带且仅带一个 type 标签,以及 `specdev:captured` 与 `origin:local`;
85
+ - 正文是现在时 inbox 记录,不是派工单,也不是完成后投影;
86
+ - marker 使重跑不重复建贴;
87
+ - 未创建 Change,未写 `current_work`,未调用关闭;
88
+ - `<Path>{roots.state}/specdev/capture.md</Path>` 与远程重读一致,失败行可恢复;
89
+ - 未授权时远程写入为零。
@@ -0,0 +1,42 @@
1
+ ---
2
+ schema_version: 1
3
+ artifact: capture-index
4
+ mode: capture
5
+ repo: owner/repo
6
+ updated_at: <ISO-8601>
7
+ ---
8
+
9
+ # Capture
10
+
11
+ ## 捕获计划
12
+
13
+ - **目标 repo:** `owner/repo`
14
+ - **origin:** local
15
+ - **排除 id:** 无 / `<YYYY-MM-DD-slug>`
16
+ - **确认记录:** 无 / 本次授权时间与操作员
17
+
18
+ capture 不创建 Change,不写 `current_work`,不关闭 Issue。GitHub 是 inbox,不是开发权威。
19
+
20
+ ## 账本
21
+
22
+ | id | kind | title | labels | number | url | marker | sha256 | state |
23
+ |---|---|---|---|---|---|---|---|---|
24
+ | 2026-09-17-login-timeout | bug | bug: login timeout on empty session | bug, specdev:captured, origin:local | — | — | specdev:capture:2026-09-17-login-timeout | — | planned |
25
+
26
+ `state`:`planned | open | skipped:duplicate | intaken | waived | failed`。
27
+
28
+ `sha256` 覆盖实际发出的 Issue 正文。漂移只警告,不自动重发。
29
+
30
+ ## 计数
31
+
32
+ - **inbox_open:** 0
33
+ - **inbox_intaken:** 0
34
+ - **inbox_waived:** 0
35
+ - **skipped:** 0
36
+ - **failed:** 0
37
+
38
+ 计数权威是本文件,不是 GitHub 搜索。`inbox_open` 不计 `published_issues`。
39
+
40
+ ## 重试
41
+
42
+ 无 / 失败行的已完成步骤和下一步。已成功的记录不回滚。
@@ -0,0 +1,42 @@
1
+ # Evidence 关闭评论模板
2
+
3
+ publish 调用 `issue-comment-close` 时使用。先套 `<Path>{roots.workflows}/specdev/T-triage/references/public-projection.md</Path>`。
4
+
5
+ done 票 `--reason completed`:
6
+
7
+ ```markdown
8
+ > *This was generated by AI during SpecDev T-triage publish.*
9
+
10
+ ## Completion
11
+
12
+ **Result:** delivered and verified.
13
+
14
+ **Public commit / PR:** <url or sha or 无公开 commit/PR>
15
+
16
+ **Verification:**
17
+ - Directed: passed | not-run (<reason>)
18
+ - Regression: passed | not-run (<reason>)
19
+ - E2E: passed | not-run (<reason>)
20
+
21
+ **Residual risk:** <可公开残余风险或「无」。>
22
+
23
+ Marker: `specdev:<change>:T-01:published`
24
+ ```
25
+
26
+ 纳入的 cancelled 票 `--reason not_planned`:
27
+
28
+ ```markdown
29
+ > *This was generated by AI during SpecDev T-triage publish.*
30
+
31
+ ## Cancelled
32
+
33
+ **Reason:** cancelled-already-implemented | cancelled-out-of-scope
34
+
35
+ **Notes:** <指到已有公开位置或 ADR / 用户决定;不贴内部路径。>
36
+
37
+ **Public commit / PR:** <url or sha or 无公开 commit/PR>
38
+
39
+ Marker: `specdev:<change>:T-01:published`
40
+ ```
41
+
42
+ 父索引关闭评论 marker 为 `specdev:<change>:publish-index`,正文列出已关闭的子 Issue 编号与计数。
@@ -1,6 +1,6 @@
1
1
  # Intake Protocol
2
2
 
3
- 仅在 Triage `mode=intake` 时加载。本协议把外部输入转换为不可静默覆盖的本地来源快照。
3
+ 仅在 Triage `mode=intake` 时加载。本协议把外部输入转换为不可静默覆盖的本地来源快照。v1 不回写源 Issue 标签。
4
4
 
5
5
  ## 1. 解析来源
6
6
 
@@ -16,6 +16,10 @@
16
16
  - locator 相同但 hash 不同:展示漂移,不覆盖原快照;只有用户确认后才创建新 change,并在新 source 中记录 `supersedes_source`;
17
17
  - 没有稳定 locator:按用户指定 change 或新 change 继续。
18
18
 
19
+ 若 `<Path>{roots.state}/specdev/capture.md</Path>` 存在,且某行 `url` 或 marker 对应当前 `canonical_locator`:将该行标为 `intaken`。不得把多条 capture 行合并进同一个 source。默认一条 capture 记录对应一次未来 intake / 一个 Change。相关但目标不清时先走 `<Path>{roots.workflows}/specdev/W-wayfinder/W-wayfinder.md</Path>`。缺失捕获账本不影响 intake。
20
+
21
+ 同时只读扫描永久 ADR、archive 中已关闭的同类请求和当前 active change 标题。发现概念相似项时向用户展示路径与一句话理由,询问是否仍要继续。不自动 wontfix,不新建 `.out-of-scope/` 目录。
22
+
19
23
  ## 3. 冻结内容
20
24
 
21
25
  GitHub 来源保存 title、body、author、state、labels、created/updated 和截至捕获时可见的全部评论。普通 URL 保存可读正文和元数据;项目文件保存内容及项目相对 Path;粘贴或对话保存用户原文。
@@ -29,4 +33,6 @@ GitHub 来源保存 title、body、author、state、labels、created/updated 和
29
33
  - 来源类型、locator、捕获时间、hash 和关闭能力已确定;
30
34
  - 完整可持久化正文与评论已冻结;
31
35
  - 重复和漂移分支有唯一结果;
32
- - 失败没有生成伪造或不完整的 Ready source。
36
+ - 相似归档/ADR 项已展示或明确无匹配;
37
+ - 失败没有生成伪造或不完整的 Ready source;
38
+ - 源 Issue 标签未被本协议修改。
@@ -0,0 +1,34 @@
1
+ # Published Ticket 正文模板
2
+
3
+ publish 创建 GitHub Issue 时使用。先套 `<Path>{roots.workflows}/specdev/T-triage/references/public-projection.md</Path>` 脱敏,再填本模板。占位符不得把 state Path 带出去。
4
+
5
+ ```markdown
6
+ > *This was generated by AI during SpecDev T-triage publish.*
7
+
8
+ ## Published Ticket
9
+
10
+ **Category:** <bug | feature | refactor | investigation | operations | documentation | review>
11
+ **Change:** <change-name>
12
+ **Ticket:** T-01
13
+ **Origin:** local | intake
14
+ **Parent:** Part of #<n> / none
15
+
16
+ **Summary:** <一句话,已经发生的事实。>
17
+
18
+ **Delivered behavior:**
19
+ <完成后系统对外可见的行为。写「现在会怎样」,不写「去改哪个文件」。>
20
+
21
+ **Acceptance:**
22
+ - [x] AC-001:<可公开验收,状态按 Evidence 勾选>
23
+
24
+ **Blocked by:**
25
+ - #<n> <title>
26
+ - None
27
+
28
+ **Out of scope:**
29
+ <票里 OUT 列的可公开项;没有则写「无」。>
30
+
31
+ **Provenance:**
32
+ - Public commit / PR: <url or sha or 无>
33
+ - Marker: `specdev:<change>:T-01:published`
34
+ ```
@@ -0,0 +1,27 @@
1
+ # Captured Record 正文模板
2
+
3
+ capture 创建仍 open 的 GitHub Issue 时使用。先套 `<Path>{roots.workflows}/specdev/T-triage/references/public-projection.md</Path>` 脱敏,再填本模板。占位符不得把 state Path 带出去。现在时;不写「请去实现」。
4
+
5
+ ```markdown
6
+ > *This was generated by AI during SpecDev T-triage capture.*
7
+
8
+ ## Captured Record
9
+
10
+ **Category:** <bug | feature | refactor | investigation | operations | documentation | review>
11
+ **Origin:** local
12
+ **Status:** inbox, open; not a development ticket
13
+
14
+ **Summary:** <一句话,现在要记下的事实或意图。>
15
+
16
+ **Observed / intended:**
17
+ <现在观察到什么、想记下什么。写「现在怎样 / 想记下什么」,不写「去改哪个文件」,不写派工祈使句。>
18
+
19
+ **Why parked:**
20
+ <为什么先记到 GitHub、还不进 Change。>
21
+
22
+ **Out of scope for this record:**
23
+ <本条不决定的事项;没有则写「无」。本条默认对应一次未来 intake / 一个未来 Change。>
24
+
25
+ **Provenance:**
26
+ - Marker: `specdev:capture:<YYYY-MM-DD-slug>`
27
+ ```
@@ -0,0 +1,92 @@
1
+ # Publish Protocol
2
+
3
+ 仅在 Triage `mode=publish` 时加载。目标是把已完成 Change 的计划内 Ticket 投影为带分类标签的 GitHub Issue,用脱敏 Evidence 关闭它们,并留下 `<Path>{roots.state}/specdev/changes/{change}/publish.md</Path>`。
4
+
5
+ GitHub 是投影和计数器,不是开发权威。源 Issue 的关闭仍走 reconcile,与本协议互不覆盖。
6
+
7
+ ## 1. 触发与对象
8
+
9
+ 用户必须指定一个已存在的 change(active 或尚未归档的 completed)。禁止扫整个 workspace 自动发。
10
+
11
+ 可选开关:`include-cancelled`、`force-parent` / `no-parent`、排除票号列表。目标 repo 默认从 `git remote` 推断,必须展示确认。
12
+
13
+ 没有先前 intake 时允许补写:
14
+
15
+ - `<Path>{roots.state}/specdev/changes/{change}/triage.md</Path>`,`mode: publish`,`publish_action: pending`;
16
+ - 轻量 `<Path>{roots.state}/specdev/changes/{change}/source.md</Path>`:`source_type` 为 `conversation | pasted | local-file`,`canonical_locator: null`,`close_capability: not-applicable`。禁止虚构 GitHub locator。
17
+
18
+ publish **不得**改 Ticket / Spec / Evidence / Goal / change completed 事实。只写 `<Path>{roots.state}/specdev/changes/{change}/publish.md</Path>`、`<Path>{roots.state}/specdev/changes/{change}/triage.md</Path>` 的 publish 字段,以及经授权的远程投影。
19
+
20
+ ## 2. 硬门
21
+
22
+ 失败即停,零远程写入。`publish_action` 保持 `not-requested`(尚未开始)或变为 `publish-failed`(已开始后失败)。
23
+
24
+ 1. 按 `<Path>{roots.workflows}/specdev/common/rules/change-completion.md</Path>` 重验本地完成。
25
+ 2. 至少一张可发布票:status `done`,或用户选择纳入的 `cancelled`。没有 Ticket 文件(纯 Direct Spec)时停止;v1 不发 Change 级单 Issue。
26
+ 3. 调用 `<Path>{roots.skills}/github-npm-ops/SKILL.md</Path>` 能读目标 repo、能 dry-run `issue-create`。
27
+ 4. 分类映射见 `<Path>{roots.workflows}/specdev/T-triage/references/classification-map.md</Path>`。缺 type 标签时 dry-run 表列出将创建的标签,授权后才 `gh label create`。
28
+ 5. Change `classification` 为 `mixed` 时,确认表上每张纳入票都有 `kind`。
29
+ 6. 用户看见完整 dry-run 表(标题、标签、正文、关闭评论、reason)并给出 **本次** 明确确认。
30
+
31
+ cancelled 默认跳过,账本记 `skipped:cancelled`。只有 `include-cancelled` 或确认表勾选才建 Issue,并以 `not_planned` 关闭。
32
+
33
+ 父 Change Issue:纳入票数 ≥ 2 时默认创建;1 票时票 Issue 本身就是记录。`force-parent` / `no-parent` 覆盖默认。v1 只用正文 `Part of #<n>` / `Blocked by #<n>`,不上 native sub-issue API。
34
+
35
+ ## 3. 准备投影
36
+
37
+ 对每张纳入票读取 Ticket 与对应 Evidence,按 `<Path>{roots.workflows}/specdev/T-triage/references/public-projection.md</Path>` 脱敏。
38
+
39
+ - Issue 正文:`<Path>{roots.workflows}/specdev/T-triage/issue-body-template.md</Path>`(过去时)。
40
+ - 关闭评论:`<Path>{roots.workflows}/specdev/T-triage/close-comment-template.md</Path>`。
41
+ - `kind` 缺省继承 Change 分类;写回票 frontmatter 可选,账本该行必须有 `kind`。
42
+ - origin:源 `close_capability` 为 supported 或 locator 是 GitHub Issue/PR 则为 `intake`,否则 `local`。
43
+ - marker:`specdev:<change>:<ticket-id>:published`。
44
+
45
+ 用 `<Path>{roots.workflows}/specdev/T-triage/publish-template.md</Path>` 写或更新 `<Path>{roots.state}/specdev/changes/{change}/publish.md</Path>`。先把纳入行标 `planned`,跳过行标 `skipped:cancelled` 或 `skipped:excluded`,`publish_action: pending`。
46
+
47
+ ## 4. 幂等执行
48
+
49
+ 顺序:先父(若有)→ 按 `blocked_by` 拓扑建子 → 回写父正文真实编号 → 关子 → 关父。
50
+
51
+ 对每张票:
52
+
53
+ 1. `issue-search` 查 marker 或精确标题 + `specdev:published`。
54
+ 2. 已存在且 marker 在且已关闭 → 账本 `closed`,跳过。
55
+ 3. 已存在且 marker 在但仍 open → 只补 `issue-comment-close`。
56
+ 4. 已存在但无 marker → 停止该行,展示冲突,不覆盖别人的 Issue。
57
+ 5. 不存在 → dry-run `issue-create` → 授权后 `--apply` → 立刻 `issue-comment-close`,marker 双写(正文 Provenance + 关闭评论)。
58
+ 6. 任一步失败:该行 `failed`,记录已完成步骤和下一重试动作;已成功的票不回滚。
59
+
60
+ `--apply` 只表示调用方完成本次确认,不替代授权。远程失败不回滚本地完成事实。
61
+
62
+ 全部纳入票到达 `closed` 或合法 `skipped:*`,且无 `failed` 时:`publish_action: published`,填写 `published_at`。用户明确放弃:`waived`。重跑是恢复,不是重发。
63
+
64
+ 摄入源 Change:本协议只建票 Issue。原来的源 Issue 仍由 reconcile 关闭;源 Issue ≠ 票 Issue。reconcile 评论可以链接已发布编号。
65
+
66
+ ## 5. 校验与计数
67
+
68
+ ```bash
69
+ node <Path>{roots.workflows}/specdev/common/tools/validate-specdev.mjs</Path> \
70
+ --stage triage \
71
+ <Path>{roots.state}/specdev/changes/{change}</Path>
72
+ ```
73
+
74
+ workspace 计数:
75
+
76
+ ```bash
77
+ node <Path>{roots.workflows}/specdev/T-triage/tools/publish-status.mjs</Path> \
78
+ --state-root <Path>{roots.state}/specdev</Path>
79
+ ```
80
+
81
+ 数字只来自 active + archive 的 `<Path>{roots.state}/specdev/changes/{change}/publish.md</Path>`,不把 GitHub 搜索当权威。
82
+
83
+ ## 完成标准
84
+
85
+ - 指定 completed Change 的 done 票均有对应 GitHub Issue,或账本有合法 skip;
86
+ - 每条已发布 Issue 带且仅带一个 type 标签,以及 `specdev:published` 与 `origin:*`;
87
+ - 关闭评论是 Evidence 脱敏投影;
88
+ - marker 使重跑不重复建贴;
89
+ - 本地源计入 `published_issues`;
90
+ - `<Path>{roots.state}/specdev/changes/{change}/publish.md</Path>` 与远程重读一致,失败行可恢复;
91
+ - Ticket / Spec / Evidence / completed 事实未被改写;
92
+ - 未授权时远程写入为零。
@@ -0,0 +1,49 @@
1
+ ---
2
+ schema_version: 1
3
+ artifact: publish
4
+ change: <YYYY-MM-DD-topic>
5
+ mode: publish
6
+ repo: owner/repo
7
+ publish_action: pending
8
+ include_cancelled: false
9
+ parent_issue: null
10
+ origin: local
11
+ published_at: null
12
+ updated_at: <ISO-8601>
13
+ ---
14
+
15
+ # Publish: <change>
16
+
17
+ ## 发布计划
18
+
19
+ - **目标 repo:** `owner/repo`
20
+ - **origin:** local / intake
21
+ - **含 cancelled:** false
22
+ - **父 Issue:** 默认(纳入票 ≥ 2 时创建)/ 强制开 / 强制关
23
+ - **排除票:** 无 / T-0N
24
+ - **确认记录:** 无 / 本次授权时间与操作员
25
+
26
+ publish 不改写 Ticket、Spec、Evidence、Goal 或 change completed 事实。
27
+
28
+ ## 账本
29
+
30
+ | ticket | kind | labels | number | url | marker | sha256 | state |
31
+ |---|---|---|---|---|---|---|---|
32
+ | T-01 | bug | bug, specdev:published, origin:local | — | — | specdev:<change>:T-01:published | — | planned |
33
+
34
+ `state`:`planned | created | commented | closed | skipped:cancelled | skipped:excluded | failed`。
35
+
36
+ `sha256` 覆盖实际发出的 Issue 正文 + 关闭评论。漂移只警告,不自动重发。
37
+
38
+ ## 计数
39
+
40
+ - **published_closed:** 0
41
+ - **published_open:** 0
42
+ - **skipped:** 0
43
+ - **failed:** 0
44
+
45
+ 计数权威是本文件,不是 GitHub 搜索。`published_issues` = closed + created(仍 open 的失败中途行)。
46
+
47
+ ## 重试
48
+
49
+ 无 / 失败行的已完成步骤和下一步。已成功的票不回滚。
@@ -1,6 +1,6 @@
1
1
  # Reconcile Protocol
2
2
 
3
- 仅在 Triage `mode=reconcile` 时加载。目标是把本地完成结果最小化投影到来源 Issue,并关闭它。
3
+ 仅在 Triage `mode=reconcile` 时加载。目标是把本地完成结果最小化投影到来源 Issue,并关闭它。票级发布走 publish,不走本协议。
4
4
 
5
5
  ## 1. 本地完成硬门
6
6
 
@@ -10,7 +10,7 @@
10
10
 
11
11
  ## 2. 准备关闭计划
12
12
 
13
- 从本地 Evidence 生成简短评论:完成结果、关键验证、可公开的 commit/PR URL、残余风险或后续工作。不得发布 state Path、机器路径、秘密、内部日志或未核对声明。
13
+ 从本地 Evidence 生成简短评论:完成结果、关键验证、可公开的 commit/PR URL、残余风险或后续工作。遵守 `<Path>{roots.workflows}/specdev/T-triage/references/public-projection.md</Path>`。若同一 change 已 publish,评论可以链接票 Issue 编号;源 Issue 仍不是那些票 Issue。
14
14
 
15
15
  向用户展示准确 repo、Issue 编号、评论全文、close reason 和将执行的动作。只有本次明确确认后才继续;拒绝或暂不执行时零远程写入。用户明确放弃关闭可将状态置为 `waived`。
16
16
 
@@ -23,7 +23,7 @@
23
23
  - marker 不存在:评论成功后再 close;
24
24
  - 任一步失败:记录已完成步骤、错误和下一重试动作,状态为 `close-failed`。
25
25
 
26
- 成功后重读远程状态,只有观察到 closed 才写 `external_action: closed`。
26
+ 成功后重读远程状态,只有观察到 closed 才写 `external_action: closed`。不改写 `publish_action`。
27
27
 
28
28
  ## 完成标准
29
29
 
@@ -0,0 +1,54 @@
1
+ # Classification Map
2
+
3
+ T-triage 本地分类与 GitHub type 标签的对照。publish 与 capture 只打本表允许的标签;intake 仍把 8 值写在 `<Path>{roots.state}/specdev/changes/{change}/triage.md</Path>`,v1 不回写源 Issue。
4
+
5
+ ## SpecDev 分类
6
+
7
+ Change 级 `classification`:`bug | feature | refactor | investigation | operations | documentation | review | mixed`。
8
+
9
+ 票级 `kind` 与上相同,去掉 `mixed`。缺省合法:publish 时继承 Change 分类;Change 为 `mixed` 时确认表必须给出每张纳入票的 `kind`。capture 每条记录必须自带 `kind`,禁止 `mixed`。
10
+
11
+ ## GitHub type 标签
12
+
13
+ 优先使用目标仓库已有标签。确认表展示实际将打的字符串。
14
+
15
+ | SpecDev | GitHub type(优先) | 降级 | 标题前缀 |
16
+ |---|---|---|---|
17
+ | `bug` | `bug` | — | `bug:` |
18
+ | `feature` | `feature-request` | `enhancement` | `feature:` |
19
+ | `refactor` | `enhancement`,若仓库已有 `refactor` 则额外打 `refactor` | — | `refactor:` |
20
+ | `investigation` | `question` | `enhancement` | `investigate:` |
21
+ | `operations` | `operations` | `enhancement` | `ops:` |
22
+ | `documentation` | `documentation` | — | `docs:` |
23
+ | `review` | `enhancement` | — | `review:` |
24
+ | `mixed` | 禁止直接发布 | 拆到票级 `kind` | — |
25
+
26
+ 每个已发布 Issue 恰好一个 type 标签(`refactor` 的额外 `refactor` 不算第二 type)。capture 的 inbox Issue 同样恰好一个 type 标签。
27
+
28
+ ## 固定附加标签
29
+
30
+ - `specdev:published`:publish 计数与去重。不得打到 capture 的 inbox Issue。
31
+ - `specdev:captured`:capture inbox 计数与去重。不得打到 publish 的票 Issue 或父索引。与 `specdev:published` 互斥。
32
+ - `origin:local` 或 `origin:intake`:来源。本地对话/粘贴/项目文件为 `local`;冻结自 GitHub Issue/PR 为 `intake`。capture 固定 `origin:local`。
33
+ - 父 Change 索引 Issue 另打 `specdev:change`。`mixed` 的父 Issue 不打 type。capture 不得打 `specdev:change`。
34
+
35
+ ## 可选标签
36
+
37
+ - `area:*`:仅当 tickets-map / `expected_changes` 能唯一推断顶层目录时才打;不确定则不问不打。
38
+ - `priority:*`:由 triage `risk` 映射:`critical→priority:critical`,`high→priority:high`,`medium→priority:medium`,`low→priority:low`。确认表可改。
39
+
40
+ ## 禁止标签
41
+
42
+ 不得打到自发布 Issue、父索引或 capture inbox Issue 上:
43
+
44
+ `needs-triage`、`needs-info`、`ready-for-agent`、`ready-for-human`、`wontfix`、`duplicate`、`invalid`、`stale`。
45
+
46
+ cancelled 票若被纳入 publish,使用 close reason `not_planned`,不打 `wontfix`。
47
+
48
+ ## 标题
49
+
50
+ ```text
51
+ <前缀> <ticket.title>
52
+ ```
53
+
54
+ 不把内部 id `T-01` 写入标题。内部 id 只出现在正文 Provenance 和 `<Path>{roots.state}/specdev/changes/{change}/publish.md</Path>`。capture 标题同样不加内部 id;capture id 只出现在正文 Provenance 和 `<Path>{roots.state}/specdev/capture.md</Path>`。
@@ -0,0 +1,89 @@
1
+ # Public Projection
2
+
3
+ T-triage 远程正文的脱敏与耐久规则。intake 不写远程。reconcile 关闭评论、publish 的 Issue 正文 / 关闭评论、以及 capture 的 inbox Issue 正文都遵守本文件。
4
+
5
+ ## Disclaimer
6
+
7
+ 每条远程 Issue 正文和评论必须以这一行开头。publish:
8
+
9
+ ```markdown
10
+ > *This was generated by AI during SpecDev T-triage publish.*
11
+ ```
12
+
13
+ reconcile 关闭评论把 `publish` 换成 `reconcile`:
14
+
15
+ ```markdown
16
+ > *This was generated by AI during SpecDev T-triage reconcile.*
17
+ ```
18
+
19
+ capture inbox 正文把 `publish` 换成 `capture`:
20
+
21
+ ```markdown
22
+ > *This was generated by AI during SpecDev T-triage capture.*
23
+ ```
24
+
25
+ ## 允许写入远程的字段
26
+
27
+ publish / reconcile(过去时):
28
+
29
+ - 已发生的行为与验收(过去时)
30
+ - 可公开 commit / PR URL
31
+ - 验证结论:定向 / 回归 / E2E 是否跑过、是否通过;未跑时一句原因
32
+ - 残余风险(可公开)
33
+ - 分类、origin、Change 名、Ticket id、marker
34
+ - `Part of #<n>` / `Blocked by #<n>`
35
+ - cancelled 原因:`cancelled-already-implemented`(指到已有公开位置)或 `cancelled-out-of-scope`(指到 ADR / 用户决定)
36
+
37
+ capture(现在时):
38
+
39
+ - 现在观察到的现象或想记下的意图(现在时)
40
+ - 分类、`origin:local`、capture id、marker
41
+ - 为什么先停在 inbox、还不进 Change
42
+ - 本条明确不决定的事项
43
+
44
+ 项目相对路径只在描述公开模块边界时允许,并注明「当时路径,可能已变」。
45
+
46
+ ## 禁止写入远程
47
+
48
+ - 状态根、工作流根、技能根别名与任何 Path 标签
49
+ - 机器绝对路径、worktree 路径、state 文件路径
50
+ - token、Cookie、密钥、私人日志、未核对声明
51
+ - skill JSON、workspace 策略原文、candidate 内部字段、内部 SHA 链(除非该 SHA 已是将推送的公开 commit)
52
+ - 「请 agent 去实现」的祈使句
53
+ - 文件行号
54
+
55
+ 关闭评论是 Evidence 的公共投影,不是副本。不得把 Evidence 原文贴出去。capture 没有关闭评论。
56
+
57
+ ## 最低关闭评论
58
+
59
+ 即使脱敏后也必须保留(仅 reconcile / publish):
60
+
61
+ 1. 结果一句话(通过 / 取消原因)
62
+ 2. 公开 commit 或 PR URL;没有则写「无公开 commit/PR」
63
+ 3. 验证结论四字级摘要(通过 / 未跑 + 原因)
64
+
65
+ ## Marker
66
+
67
+ 票 Issue:
68
+
69
+ ```text
70
+ specdev:<change>:<ticket-id>:published
71
+ ```
72
+
73
+ 同时写入 Issue 正文 Provenance 和关闭评论,供 `issue-search` 去重。
74
+
75
+ 父索引:
76
+
77
+ ```text
78
+ specdev:<change>:publish-index
79
+ ```
80
+
81
+ reconcile 源 Issue 仍用 `specdev:<change>:completion`,与 publish marker 互不替代。
82
+
83
+ capture inbox:
84
+
85
+ ```text
86
+ specdev:capture:<YYYY-MM-DD-slug>
87
+ ```
88
+
89
+ 只写入 Issue 正文 Provenance。Issue 保持 open。与 `specdev:published` / `specdev:<change>:completion` 互不替代。