harveyz-skill 0.31.0 → 0.33.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 +27 -0
- package/package.json +2 -1
- package/skills/coding/handoff/SKILL.md +223 -18
- package/skills/coding/handoff/assets/handoff-template.md +26 -7
- package/skills/coding/handoff/evals/evals.json +134 -38
- package/skills/coding/handoff/evals/fixtures/accept/{handoff-slugify.md → 2026-08-02-slugify-handoff.md} +7 -3
- package/skills/coding/handoff/evals/fixtures/accept-worktree/setup.sh +119 -0
- package/skills/coding/handoff/scripts/validate-handoff.sh +186 -0
- package/skills/coding/handoff/tests/validate-handoff.bats +352 -0
- package/skills/feed/manage-creators/SKILL.md +2 -2
- package/skills/feed/manage-creators/scripts/__pycache__/roster_locate.cpython-314.pyc +0 -0
- package/skills/feed/manage-creators/tests/__pycache__/test_roster_locate.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/feed/sync-website/SKILL.md +203 -0
- package/skills/feed/sync-website/platforms/SKILL.claude.md +19 -0
- package/skills/feed/sync-website/platforms/SKILL.codex.md +22 -0
- package/skills/feed/sync-website/platforms/SKILL.hermes.md +22 -0
- package/skills/feed/sync-website/platforms/SKILL.pi.md +18 -0
- package/skills/feed/sync-website/scripts/__pycache__/archive_articles.cpython-314.pyc +0 -0
- package/skills/feed/sync-website/scripts/__pycache__/articles_client.cpython-314.pyc +0 -0
- package/skills/feed/sync-website/scripts/__pycache__/browser_fetch_cli.cpython-314.pyc +0 -0
- package/skills/feed/sync-website/scripts/__pycache__/browser_fetch_locate.cpython-314.pyc +0 -0
- package/skills/feed/sync-website/scripts/__pycache__/calibration_gate.cpython-314.pyc +0 -0
- package/skills/feed/sync-website/scripts/__pycache__/config.cpython-314.pyc +0 -0
- package/skills/feed/sync-website/scripts/__pycache__/cursor.cpython-314.pyc +0 -0
- package/skills/feed/sync-website/scripts/__pycache__/digest.cpython-314.pyc +0 -0
- package/skills/feed/sync-website/scripts/__pycache__/fetch_new_articles.cpython-314.pyc +0 -0
- package/skills/feed/sync-website/scripts/__pycache__/roster_client.cpython-314.pyc +0 -0
- package/skills/feed/sync-website/scripts/__pycache__/roster_locate.cpython-314.pyc +0 -0
- package/skills/feed/sync-website/scripts/__pycache__/store_config.cpython-314.pyc +0 -0
- package/skills/feed/sync-website/scripts/archive_articles.py +53 -0
- package/skills/feed/sync-website/scripts/articles_client.py +90 -0
- package/skills/feed/sync-website/scripts/browser_fetch_cli.py +23 -0
- package/skills/feed/sync-website/scripts/browser_fetch_locate.py +50 -0
- package/skills/feed/sync-website/scripts/calibration_gate.py +50 -0
- package/skills/feed/sync-website/scripts/config.py +13 -0
- package/skills/feed/sync-website/scripts/cursor.py +29 -0
- package/skills/feed/sync-website/scripts/digest.py +90 -0
- package/skills/feed/sync-website/scripts/fetch_new_articles.py +124 -0
- package/skills/feed/sync-website/scripts/roster_client.py +44 -0
- package/skills/feed/sync-website/scripts/roster_locate.py +46 -0
- package/skills/feed/sync-website/scripts/store_config.py +143 -0
- package/skills/feed/sync-website/tests/__pycache__/conftest.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/feed/sync-website/tests/__pycache__/test_archive_articles.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/feed/sync-website/tests/__pycache__/test_articles_client.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/feed/sync-website/tests/__pycache__/test_browser_fetch_locate.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/feed/sync-website/tests/__pycache__/test_calibration_gate.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/feed/sync-website/tests/__pycache__/test_cursor.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/feed/sync-website/tests/__pycache__/test_digest.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/feed/sync-website/tests/__pycache__/test_fetch_new_articles.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/feed/sync-website/tests/__pycache__/test_roster_client.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/feed/sync-website/tests/__pycache__/test_store_config.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/feed/sync-website/tests/conftest.py +27 -0
- package/skills/feed/sync-website/tests/test_archive_articles.py +91 -0
- package/skills/feed/sync-website/tests/test_articles_client.py +93 -0
- package/skills/feed/sync-website/tests/test_browser_fetch_locate.py +69 -0
- package/skills/feed/sync-website/tests/test_calibration_gate.py +77 -0
- package/skills/feed/sync-website/tests/test_cursor.py +47 -0
- package/skills/feed/sync-website/tests/test_digest.py +158 -0
- package/skills/feed/sync-website/tests/test_fetch_new_articles.py +185 -0
- package/skills/feed/sync-website/tests/test_roster_client.py +83 -0
- package/skills/feed/sync-website/tests/test_store_config.py +199 -0
- package/skills/feed/sync-xtimeline/SKILL.md +7 -3
- package/skills/feed/sync-xtimeline/scripts/__pycache__/archive_tweets.cpython-314.pyc +0 -0
- package/skills/feed/sync-xtimeline/scripts/__pycache__/config.cpython-314.pyc +0 -0
- package/skills/feed/sync-xtimeline/scripts/__pycache__/fetch_new_tweets.cpython-314.pyc +0 -0
- package/skills/feed/sync-xtimeline/scripts/__pycache__/render_digest.cpython-314.pyc +0 -0
- package/skills/feed/sync-xtimeline/scripts/__pycache__/roster_client.cpython-314.pyc +0 -0
- package/skills/feed/sync-xtimeline/scripts/__pycache__/store_config.cpython-314.pyc +0 -0
- package/skills/feed/sync-xtimeline/scripts/store_config.py +84 -2
- package/skills/feed/sync-xtimeline/tests/__pycache__/conftest.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/feed/sync-xtimeline/tests/__pycache__/test_archive_tweets.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/feed/sync-xtimeline/tests/__pycache__/test_fetch_new_tweets.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/feed/sync-xtimeline/tests/__pycache__/test_render_digest.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/feed/sync-xtimeline/tests/__pycache__/test_store_config.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/feed/sync-xtimeline/tests/test_store_config.py +101 -0
- package/skills/feed/sync-ytchannel/SKILL.md +7 -3
- package/skills/feed/sync-ytchannel/scripts/__pycache__/archive_videos.cpython-314.pyc +0 -0
- package/skills/feed/sync-ytchannel/scripts/__pycache__/config.cpython-314.pyc +0 -0
- package/skills/feed/sync-ytchannel/scripts/__pycache__/digest.cpython-314.pyc +0 -0
- package/skills/feed/sync-ytchannel/scripts/__pycache__/fetch_new_videos.cpython-314.pyc +0 -0
- package/skills/feed/sync-ytchannel/scripts/__pycache__/roster_client.cpython-314.pyc +0 -0
- package/skills/feed/sync-ytchannel/scripts/__pycache__/store_config.cpython-314.pyc +0 -0
- package/skills/feed/sync-ytchannel/scripts/store_config.py +84 -2
- package/skills/feed/sync-ytchannel/tests/__pycache__/conftest.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/feed/sync-ytchannel/tests/__pycache__/test_archive_videos.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/feed/sync-ytchannel/tests/__pycache__/test_digest.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/feed/sync-ytchannel/tests/__pycache__/test_fetch_new_videos.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/feed/sync-ytchannel/tests/__pycache__/test_store_config.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/feed/sync-ytchannel/tests/test_store_config.py +101 -0
- package/skills/mint/init-skill/SKILL.md +1 -1
- package/skills/mint/learn-skill/SKILL.md +1 -1
- package/skills/research/clip-url/SKILL.md +10 -3
- package/skills/research/clip-url/scripts/__pycache__/store_config.cpython-314.pyc +0 -0
- package/skills/research/clip-url/scripts/__pycache__/vault_config.cpython-314.pyc +0 -0
- package/skills/research/clip-url/scripts/store_config.py +84 -2
- package/skills/research/clip-url/tests/__pycache__/conftest.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/research/clip-url/tests/__pycache__/test_dedup_check.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/research/clip-url/tests/__pycache__/test_mcp_fetch_client.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/research/clip-url/tests/__pycache__/test_store_config.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/research/clip-url/tests/__pycache__/test_vault_config.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/research/clip-url/tests/__pycache__/test_write_meta_and_separate.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/research/clip-url/tests/test_store_config.py +101 -0
- package/skills/research/learn-video/SKILL.md +8 -6
- package/skills/research/learn-video/scripts/__pycache__/archive.cpython-314.pyc +0 -0
- package/skills/research/learn-video/scripts/__pycache__/store_config.cpython-314.pyc +0 -0
- package/skills/research/learn-video/scripts/archive.py +31 -0
- package/skills/research/learn-video/scripts/store_config.py +84 -2
- package/skills/research/learn-video/tests/__pycache__/conftest.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/research/learn-video/tests/__pycache__/test_archive.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/research/learn-video/tests/__pycache__/test_store_config.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/research/learn-video/tests/test_archive.py +64 -0
- package/skills/research/learn-video/tests/test_store_config.py +101 -0
- package/skills/research/survey-skillrepo/SKILL.md +1 -1
- package/skills-index.json +26 -19
- package/tools/browser-fetch/browser_fetch/__pycache__/cli.cpython-314.pyc +0 -0
- package/tools/browser-fetch/browser_fetch/__pycache__/core.cpython-314.pyc +0 -0
- package/tools/browser-fetch/browser_fetch/__pycache__/extractors.cpython-314.pyc +0 -0
- package/tools/browser-fetch/browser_fetch/__pycache__/normalize.cpython-314.pyc +0 -0
- package/tools/browser-fetch/browser_fetch/__pycache__/site_rules.cpython-314.pyc +0 -0
- package/tools/browser-fetch/browser_fetch/cli.py +43 -0
- package/tools/browser-fetch/browser_fetch/core.py +155 -1
- package/tools/browser-fetch/browser_fetch/extractors.py +38 -0
- package/tools/browser-fetch/browser_fetch/normalize.py +42 -0
- package/tools/browser-fetch/browser_fetch/site_rules.py +186 -0
- package/tools/browser-fetch/pyproject.toml +1 -1
- package/tools/browser-fetch/tests/__pycache__/conftest.cpython-314-pytest-9.1.1.pyc +0 -0
- package/tools/browser-fetch/tests/__pycache__/test_cli_articles.cpython-314-pytest-9.1.1.pyc +0 -0
- package/tools/browser-fetch/tests/__pycache__/test_cli_articles_rule.cpython-314-pytest-9.1.1.pyc +0 -0
- package/tools/browser-fetch/tests/__pycache__/test_cli_articles_transform.cpython-314-pytest-9.1.1.pyc +0 -0
- package/tools/browser-fetch/tests/__pycache__/test_extractors_articles.cpython-314-pytest-9.1.1.pyc +0 -0
- package/tools/browser-fetch/tests/__pycache__/test_normalize.cpython-314-pytest-9.1.1.pyc +0 -0
- package/tools/browser-fetch/tests/__pycache__/test_site_rules.cpython-314-pytest-9.1.1.pyc +0 -0
- package/tools/browser-fetch/tests/__pycache__/test_site_rules_dirs.cpython-314-pytest-9.1.1.pyc +0 -0
- package/tools/browser-fetch/tests/conftest.py +30 -0
- package/tools/browser-fetch/tests/test_cli_articles.py +90 -0
- package/tools/browser-fetch/tests/test_cli_articles_rule.py +63 -0
- package/tools/browser-fetch/tests/test_cli_articles_transform.py +169 -0
- package/tools/browser-fetch/tests/test_extractors_articles.py +29 -0
- package/tools/browser-fetch/tests/test_normalize.py +55 -0
- package/tools/browser-fetch/tests/test_site_rules.py +86 -0
- package/tools/browser-fetch/tests/test_site_rules_dirs.py +235 -0
- package/tools/browser-fetch/tool.json +1 -1
- package/tools/roster/roster/__pycache__/__init__.cpython-314.pyc +0 -0
- package/tools/roster/roster/__pycache__/__main__.cpython-314.pyc +0 -0
- package/tools/roster/roster/__pycache__/registry.cpython-314.pyc +0 -0
- package/tools/roster/roster/__pycache__/urls.cpython-314.pyc +0 -0
- package/tools/roster/roster/urls.py +30 -0
- package/tools/roster/tests/__pycache__/test_cli.cpython-314-pytest-9.1.1.pyc +0 -0
- package/tools/roster/tests/__pycache__/test_urls.cpython-314-pytest-9.1.1.pyc +0 -0
- package/tools/roster/tests/test_cli.py +1 -1
- package/tools/roster/tests/test_urls.py +11 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.33.0] - 2026-09-15
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- `store_config.py`(`learn-video`/`clip-url`/`sync-xtimeline`/`sync-ytchannel`/`sync-website` 共用):新增 `check-downstream`,核对统一存储根的产物与 vdl / scholia 两个下游读取方是否同步,五份 SKILL.md 的前置检查步骤接入该核对
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- `handoff`(1.8.0 → 1.11.0):新增 Phase 2.5 接手方自测闸门 + 打回复修回路(此前「接手方完工 → 待验收」这个状态转移毫无前置条件);建工作区改为显式给基线分支并 `EnterWorktree(path:)` 进去,三方指令统一,修复了两次因裸 git 命令落到主工作树而夹带他人未合并提交的翻车;关闭 `using-git-worktrees` 前置调用(它会另起一个 `.worktrees/` 下的第二工作区,与 handoff 自己的工作区约定冲突);平台专属指令(`EnterWorktree` 等 Claude Code harness 特性)拆进独立「平台适配」章节,避免 pi/hermes/Codex 上的接手方读到卡住
|
|
17
|
+
- `publish-skill` 审计:`init-skill`(1.2.0→1.2.1)、`learn-skill`(2.0.0→2.0.1)、`research/survey-skillrepo`(2.0.1→2.0.2)——内容已变但 version 未 bump,属于 F8 硬性检查项,现已按 patch 补齐;另有 6 个 skill(`handoff`/`sync-website`/`sync-xtimeline`/`sync-ytchannel`/`clip-url`/`learn-video`)此前 version 已 bump 但 `skills-index.json` 里的 `contentHash` 记录没跟上,已同步
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
- `learn-video` / `clip-url` / `sync-xtimeline` / `sync-ytchannel` / `sync-website` 共用的 `knowledgeRoot` 默认建议路径从 `~/Documents/knowledge` 改为 `~/knowledge`:前者在无 Full Disk Access 的 agent 执行环境下写入会静默失败,且此前没有护栏阻止 agent 擅自把配置改到别的路径绕过,导致产物在用户不知情的情况下分裂到两个根目录;五份 SKILL.md 加"写入失败必须如实报告并停下问用户"的护栏指令
|
|
21
|
+
- `tests/install.bats` / `tests/interactive.bats`:`survey-skillrepo` 测试夹具的硬编码版本号随上面的 F8 审计一并更新为 `2.0.2`,此前的 bump 一度导致 3 个断言失败
|
|
22
|
+
|
|
23
|
+
## [0.32.0] - 2026-09-07
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
- `sync-website`:新增追更网站文章列表页的第三种渠道类型,与 sync-xtimeline / sync-ytchannel 并列。browser-fetch 新增 per-domain selector 规则存储与 calibrate/run 流水线,roster 支持网站 URL 兜底解析。13 任务计划通过 subagent-driven-development 执行,逐任务 review + 全分支收尾 review(4 处修复:roster URL 守卫缺口、digest 里看不见的自愈、published_at 文档订正、路径穿越与 prompt-injection 加固),并对 simonwillison.net 做了真实 E2E 验证
|
|
27
|
+
- `browser-fetch`:site_rules 新增二档 selector+transform 抽取(`about:blank` 隔离上下文求值),归一化管线三档共用;transform 报错改为触发自愈而非永久失败,超出自愈上限才报错
|
|
28
|
+
- `scripts/rebuild-orphan-articles.py`:一次性重建脚本,把统一存储根迁移后遗留在 `_orphans/` 里、但 frontmatter 带 `source_url`/`origin_title`/`fetch_date` 的孤儿文章重新收进索引;只在无歧义(`hash8` 未被占用且只有一个来源文件对应)时重建,多源冲突留给人工判断
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
- `handoff`(1.3.0 → 1.8.0):一次性完成多轮迭代——工作区改由 author 建并留到验收通过(接手方与验收方都不再新建 worktree/分支)、抬头字段搬进 frontmatter 并加 `validate-handoff.sh` 机器校验、author 登记交接源节点与画布 `hands-off-to` 关系、交付时新增可粘贴的接手/验收指令(只放寻址信息不复述文档内容,避免摘要和文档变成两个真相源)。工作区约定同步写进 `CLAUDE.md` 与 `.hskill/handoff/config.md`
|
|
32
|
+
- `feed/manage-creators` / `sync-xtimeline` / `sync-ytchannel`:patch 版本刷新(`skill-publish` F8 contentHash 校验触发的措辞级 drift 修正,无行为变化)
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
- `scripts/migrate-store.sh`(v0.31.0 引入的统一存储根一次性迁移脚本):在真实数据上跑 dry-run 后暴露并修复 7 处问题——旧版 `sync-xtimeline` 产物路径未读取 `config.json` 的 `DATA_DIR`、`--verify` 对旧布局的校验有两处假绿(路径解析未跟进迁移、并入语义被误判成覆盖语义)、`--verify` 未区分"目标被追加变大"(正常)与"被截断变小"(真失败)、vault 顶层孤儿译文未被搬迁、视频回填从无条件覆盖改为按字段并入以保留 vdl 自身写入的 50 份 meta.json / 483 个字段、scholia 视频卡片缺失展示字段(url/uploader/upload_date/duration 等)、`_orphans/` 未移出 `articles/` 导致孤儿被当正式文章重复列出
|
|
36
|
+
|
|
10
37
|
## [0.31.0] - 2026-09-02
|
|
11
38
|
|
|
12
39
|
### Added
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "harveyz-skill",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.0",
|
|
4
4
|
"description": "Skill manager for Claude Code, Cursor, Codex, OpenClaw, Hermes, OpenCode, and Pi",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"skills/research/clip-url/",
|
|
31
31
|
"skills/feed/sync-xtimeline/",
|
|
32
32
|
"skills/feed/sync-ytchannel/",
|
|
33
|
+
"skills/feed/sync-website/",
|
|
33
34
|
"skills/creative/capture-todo/",
|
|
34
35
|
"skills/creative/capture-insight/",
|
|
35
36
|
"skills/coding/init-workflow/",
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: handoff
|
|
3
|
-
description: Use when handing a task across sessions — writing a self-contained handoff doc for a fresh session to pick up (author), sanity-checking an inbound handoff before starting (verify), or accepting completed work against the criteria agreed at handoff time (accept). Triggers on phrases like "write a handoff", "hand this off", "pick up this task", "sign off on this work". Generic skill — project-specific conventions are read from .hskill/handoff/config.md.
|
|
4
|
-
version: "1.
|
|
3
|
+
description: Use when handing a task across sessions — writing a self-contained handoff doc for a fresh session to pick up (author), sanity-checking an inbound handoff before starting (verify), self-testing against the agreed criteria before reporting the work done or re-submitting after a rejection (self-test), or accepting completed work against the criteria agreed at handoff time (accept). Triggers on phrases like "write a handoff", "hand this off", "pick up this task", "sign off on this work". Generic skill — project-specific conventions are read from .hskill/handoff/config.md.
|
|
4
|
+
version: "1.11.0"
|
|
5
5
|
user_invocable: true
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# 跨 session 任务交接(handoff)
|
|
9
9
|
|
|
10
|
-
产出并驱动一份自包含交接文档:接手 session 只读这一份文件即可续做,完成后由原 session
|
|
10
|
+
产出并驱动一份自包含交接文档:接手 session 只读这一份文件即可续做,完成后由原 session 按约定判据验收。交付时另给一段**可粘贴的接手指令**,它只负责寻址(工作区路径、分支、文档路径),**不复述文档内容**——一旦指令里塞进摘要,接手方就会读指令不读文档,摘要与文档立刻变成两个真相源。文档内容跟着这次交接的实际目的走——不是无论目的是什么都写一份详实清单,缺了会让接手方出问题的信息才写,其余不写。
|
|
11
11
|
|
|
12
12
|
## Phase 触发判定(先做这一步)
|
|
13
13
|
|
|
@@ -15,6 +15,10 @@ user_invocable: true
|
|
|
15
15
|
2. 文本未指明 → 看上下文:刚做完规划 → author;拿到别人的交接文档准备开工 → verify;接手方回报完成、要核收 → accept。
|
|
16
16
|
3. 仍不确定 → **问用户,不猜**。
|
|
17
17
|
|
|
18
|
+
**Phase 2.5(自测)没有对应的斜杠命令**,因为它不是谁"调"出来的:接手方干完活、准备把
|
|
19
|
+
`status` 推到「待验收」的那一刻就该执行它,被打回后复修完再执行一遍。它写在 Phase 2 与
|
|
20
|
+
Phase 3 之间。
|
|
21
|
+
|
|
18
22
|
判定后跳到对应 phase 段执行。
|
|
19
23
|
|
|
20
24
|
## Phase 1 — author(写交接)
|
|
@@ -26,47 +30,248 @@ user_invocable: true
|
|
|
26
30
|
- 无 → 用通用默认(`output_dir=docs/commute/`),以后不再问。
|
|
27
31
|
2. **判断目的**:从当前对话判断这次交接是为了什么——不套预设分类,一句自然语言判断即可(例如"接手方续做同一个实现任务"或"把讨论结论作为背景传给接手方去开展新话题")。这句话会写进文档开头的"交接目的",且始终存在,不可省略。
|
|
28
32
|
3. **汇集上下文**:以**当前对话**为真相源。涉及代码时读 `git status` / `git diff` 核对现状、排查受影响文件(若这两类内容按第 4 步判定为必要),并作为门禁的现实校验(纯规划交接可跳过);spec/plan 作为权威指针。**不把 memory 写进文档**——memory 可能陈旧、且接手方访问不到你的 memory 目录;若某条 memory 是承载性背景,把**核实过的事实**内联进去,别留 `[[memory]]` 死链。现状一律以 git/仓库为准,不以 memory 为准。
|
|
29
|
-
4.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
4. **备好交接工作区**(接手方会在**另一条分支**上开工时才做;就地同分支续做则整步跳过):
|
|
34
|
+
分支和 worktree 都由**你**建好,不留给接手方建。这是整条交接链能闭环的关键——工作区是你建的,
|
|
35
|
+
你就一直知道它在哪;验收时直接回到这里读那份被接手方改过的文档,不必去别处找、更不必扫描。
|
|
36
|
+
- 已经在一条 feature worktree 里干活 → 就用它,别新建。
|
|
37
|
+
- 否则 `git worktree add <路径> -b <分支名> <基线分支>`;路径按 `.hskill/handoff/config.md`
|
|
38
|
+
的 workflow 段给的习惯,没给就用 `.claude/worktrees/<分支名把 / 换成 +>`。
|
|
39
|
+
**基线分支必须显式写出来**(通常是 `staging`)。不写就从主工作树当前 HEAD 拉分支,而主
|
|
40
|
+
工作树未必停在集成分支上——它可能正停在**别的 session 的分支**上。那样你的新分支会静默
|
|
41
|
+
夹带别人未合并的提交,合并时等于替对方把没写完的东西发布出去。这种错不会有任何报错,
|
|
42
|
+
merge 会干净利落地成功。
|
|
43
|
+
- **建完立刻进去**(怎么进见文末「平台适配」)。不进去的话,你后面每一条不带限定的
|
|
44
|
+
git 命令都作用在**主工作树**上而不是这个工作区。进不去的平台上,就把「限定到工作区」
|
|
45
|
+
当成每条命令的硬要求,别靠记性。
|
|
46
|
+
- **建完不要 `git worktree remove`。** 接手方要进来干活,你验收时还要再进来一次。这个工作区
|
|
47
|
+
在整条交接链上一直活着,直到验收通过。
|
|
48
|
+
- 把分支名填进 frontmatter 的 `branch`、工作区**绝对路径**填进 `worktree`。
|
|
49
|
+
- **同一时刻只有一方在这个工作区里动手**:你写完交接就停手,接手方做完停手,再轮到你验收。
|
|
50
|
+
两个 session 同时在一个工作区里跑 git 会互踩暂存区。
|
|
51
|
+
5. **起草**:读 `assets/handoff-template.md`,按其中的候选内容清单逐类过必要性测试——"不写这条信息,接手方会不会出问题",答案是"会"才写出对应章节,答案是"不会"整节跳过,不留空标题。**交接目的**和**最小验收锚点**这两项任何情况下都必须写。指针式引用权威依据,只内联接手方开工必需的硬核,不重抄 spec 全文。写到**第 4 步那个工作区**里的 `<output_dir>/YYYY-MM-DD-<topic>-handoff.md`,按模板填 frontmatter(`status: 待执行`、`date` 与文件名日期段一致、`acceptance` 按最小验收锚点是硬判据还是软判据填 `hard`/`soft`;`branch`/`worktree` 第 4 步已填)。
|
|
52
|
+
6. **画布节点登记**(仅当 `agent-canvas-ctl` 命令存在时做;不在 Agent Canvas 画布节点里就整步跳过,不报错):
|
|
53
|
+
- 跑 `agent-canvas-ctl whoami` 取自己的节点 id,填进 frontmatter 的 `source_node`。
|
|
54
|
+
这个字段是接手方**唯一**能找回你这个节点的线索——文档路径和分支名都指认不到画布上的
|
|
55
|
+
节点实体。不在画布节点里就整个字段删掉,别留空值。
|
|
56
|
+
- 若这次交接**你已经能指认接手节点**(例如接手用的 PTY 节点是你亲手创建的)→ 当场建关系
|
|
57
|
+
`agent-canvas-ctl link-nodes --from <自己的 nodeId> --to <接手节点 nodeId> --type hands-off-to`,
|
|
58
|
+
并把接手节点 id 填进 `target_node`,接手方只核对、不重复建。
|
|
59
|
+
- 指认不到接手节点(常态:接手方是还不存在的下一个 session)→ 只填 `source_node`,`target_node`
|
|
60
|
+
留空给接手方在 verify 阶段回填。归属规则是**谁先能同时指认两端谁建**,另一方只核对。
|
|
61
|
+
7. **跑完整性门禁**(见下),不过不放行。
|
|
62
|
+
8. **落库**:把交接文档 commit 进这条分支——未提交的文档接手方根本看不到,等于没交出去。
|
|
63
|
+
**不要 `git worktree remove`**(见第 4 步):这个工作区既是接手方的落脚点,也是你验收时要回来
|
|
64
|
+
的地方。接手方就在同一目录同一分支续做、或文档整份贴给对方时,此步可省。
|
|
65
|
+
9. **交付**:输出一段**可粘贴的接手指令**给用户,让它成为路径信息的载体——你这个 session
|
|
66
|
+
的上下文迟早会没,工作区路径不能只活在你的记忆里。指令里**只放寻址信息,不放任何文档内容
|
|
67
|
+
的摘要**(理由见本文开头)。形如:
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
接手任务。工作区已建好,不要自己建:
|
|
71
|
+
<worktree 绝对路径>
|
|
72
|
+
按你所在平台的方式进入它(Claude Code 用 EnterWorktree(path: "<路径>");
|
|
73
|
+
没有这类能力就每条命令都限定到这个路径,别靠裸 cd)。
|
|
74
|
+
分支 <branch>,已被这个工作区 checkout(git worktree add 会失败,属正常)。
|
|
75
|
+
<若 config.md 的 workflow 段有开工前置命令,原样列在这里>
|
|
76
|
+
交接文档:<相对于工作区的文档路径>
|
|
77
|
+
先 /handoff verify <文档路径> 核对,无缺口再开工。
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**同一段指令换个动词就是验收指令**(`/handoff accept <文档路径>`)——一并给用户,
|
|
81
|
+
将来验收若换了新 session,它靠这段就能回到正确的工作区。用户把这段弄丢了也不致命:
|
|
82
|
+
`git worktree list` 能查回分支与工作区的对应关系,只是要多问一步。
|
|
33
83
|
|
|
34
84
|
## 完整性门禁(author 收尾硬动作)
|
|
35
85
|
|
|
36
|
-
|
|
86
|
+
**第一道,机器校验**:`bash <skill 目录>/scripts/validate-handoff.sh <文档路径>`。
|
|
87
|
+
它查 frontmatter 字段齐不齐/枚举值合不合法、`date` 与文件名对不对得上、`branch` 在本仓库
|
|
88
|
+
存不存在、`source_node`/`target_node` 是不是合法 uuid、正文有没有「交接目的」与
|
|
89
|
+
「最小验收锚点」,并对指不到文件的引用路径给 WARN。**exit 非 0 不放行**;WARN 逐条判断
|
|
90
|
+
是笔误还是指向本次待创建的产物。
|
|
91
|
+
|
|
92
|
+
它查的是**在不在、合不合法**,查不了**够不够、对不对**——那是下面这道。
|
|
37
93
|
|
|
38
|
-
|
|
94
|
+
**第二道,冷读测试**:假装自己是零上下文的接手方,只有这份文档,逐项自问——
|
|
95
|
+
|
|
96
|
+
- **交接目的**和**最小验收锚点**(脚本已确认它们在)**内容够用吗**?目的这一句说得清这次交接
|
|
97
|
+
是为了什么吗?
|
|
39
98
|
- 文档里**实际出现**的每个章节是否自洽:
|
|
40
|
-
- 出现了「相关文档索引」→ 每个引用路径**真实存在**吗?(实际 `ls`/读一下核对,不靠记忆)
|
|
41
99
|
- 出现了「关键决定」→ 够不够让接手方**不用回问**原 session?
|
|
42
100
|
- 出现了「范围铁律」→ in/out 是否都点名,没有模糊地带?
|
|
43
101
|
- 出现了「受影响文件/落点」→ 与「相关文档索引」描述是否自洽?
|
|
44
102
|
- 最小验收锚点若是硬判据 → **可证伪**吗?(有明确对/错判定,不是"让它工作"这种软标准)
|
|
103
|
+
并与 frontmatter 的 `acceptance` 对得上吗?(硬判据填 `hard`,软判据填 `soft`——accept
|
|
104
|
+
阶段按这个字段分叉,填反了验收方式就跑偏)
|
|
105
|
+
- 接手方要在**另一条分支**上开工 → `branch` 与 `worktree` 都填了吗?(脚本只能校验填了的值
|
|
106
|
+
合不合法,判断不了"你本该填而没填"。这两个字段漏了,接手方不知道去哪开工,而你验收时也
|
|
107
|
+
找不回它改过的那份文档——整条交接链就断在这里)
|
|
108
|
+
- 你**在画布节点里**(`agent-canvas-ctl` 存在)→ frontmatter 的 `source_node` 填了吗?(脚本
|
|
109
|
+
只能校验填了的值合不合法,判断不了"你本该填而没填";缺了接手方就建不出 `hands-off-to`,
|
|
110
|
+
交接关系在画布上永远不成立)
|
|
45
111
|
- **反向检查**:有没有哪类内容被必要性测试判定为"不需要",但其实接手方会因此卡住、走错方向、或推翻已定方案?(防止必要性判断本身错判)
|
|
46
112
|
|
|
47
113
|
任一项答不上 → 补文档、重跑门禁。核对结论可选择性附在文档末尾。
|
|
48
114
|
|
|
49
115
|
## Phase 2 — verify(接手方开工前,可选)
|
|
50
116
|
|
|
117
|
+
- **先跑机器校验**:`bash <skill 目录>/scripts/validate-handoff.sh <文档路径>`。exit 非 0
|
|
118
|
+
说明这份文档本身不合规(字段缺失/枚举非法/`branch` 在本仓库不存在),直接打回原 session,
|
|
119
|
+
不要自己猜着补。WARN(引用路径指不到文件)不阻断,但要当作可疑点带进下面的怀疑视角核对。
|
|
51
120
|
- 读交接文档,以**怀疑视角**核对可执行性,逐项列出缺口/断链/歧义(复用上面的冷读测试项,只核对文档里实际出现的章节)。
|
|
52
121
|
- 有缺口 → 打回原 session 补,别硬开工。
|
|
53
|
-
-
|
|
122
|
+
- **建 `hands-off-to` 关系**(仅当 `agent-canvas-ctl` 存在、且 frontmatter 有 `source_node` 时做;
|
|
123
|
+
任一条件不满足就整步跳过,不报错):
|
|
124
|
+
1. `agent-canvas-ctl whoami` 取自己的节点 id。
|
|
125
|
+
2. `agent-canvas-ctl node-relations <自己的 nodeId> --direction in --type hands-off-to` 核对——
|
|
126
|
+
已经有一条来自交接源节点的边(author 那边建过)就跳过,不重复主张。
|
|
127
|
+
3. 没有 → `agent-canvas-ctl link-nodes --from <source_node> --to <自己的 nodeId> --type hands-off-to`。
|
|
128
|
+
4. 把自己的节点 id 填进 frontmatter 的 `target_node`——两端都填齐,这次交接在画布上才是闭环的,
|
|
129
|
+
accept 时一眼看得出关系建没建。
|
|
130
|
+
|
|
131
|
+
**只建这一条边。**不要顺带把自己挂到交接源节点实现的需求上(不建 `implements`),也不要调
|
|
132
|
+
`capture-requirement` 另立需求——需求已经挂在交接源节点上,接手节点该不该关联需求是另一个
|
|
133
|
+
问题,不在这次交接的范围内。
|
|
134
|
+
- **进 author 备好的工作区开工**(frontmatter 有 `worktree` 时):按文末「平台适配」进去,
|
|
135
|
+
然后核对 `git rev-parse --abbrev-ref HEAD` 与 `branch` 一致,就在这里干活。
|
|
136
|
+
- **绝不要销毁这个工作区**(`git worktree remove`,或平台的"退出并删除")——验收还要用。
|
|
137
|
+
- **不要自己 `git worktree add`。** 那条分支已经被这个工作区 checkout 了,再建会直接失败;
|
|
138
|
+
而且你另建一个,原 session 验收时会回到它自己建的那个,看不到你的改动。
|
|
139
|
+
- **不要 `git worktree remove`**,验收还要用。
|
|
140
|
+
- 路径不存在(被误删了)→ 打回原 session 重建,别自己找地方开工——你选的位置它不知道。
|
|
141
|
+
- `branch` 与实际不符 → 以**文档**为准打回确认,不要自己改字段:字段是 author 立的约,
|
|
142
|
+
改它等于单方面改约。
|
|
143
|
+
- 无缺口 → `status` 置 `执行中`,若文档有「工作流约定」章节按其开工,没有就直接开工。
|
|
144
|
+
|
|
145
|
+
## Phase 2.5 — 自测(接手方推 `status` 到「待验收」之前的硬闸门)
|
|
146
|
+
|
|
147
|
+
**「待验收」不是「我改完了」,是「我自己已经按锚点跑过一遍、拿得出结果」。** 这两件事之间
|
|
148
|
+
隔着一整轮 accept:没自测就推上来,红的那条要等 accept 方耗掉整轮才发现,而它本来可以由你
|
|
149
|
+
自己在几分钟内跑掉。
|
|
150
|
+
|
|
151
|
+
推 `status` 之前做完这四件事,缺一件就别推:
|
|
152
|
+
|
|
153
|
+
1. **逐条实跑「最小验收锚点」全集**——不是只跑你改动相关的那几条。`acceptance: hard`
|
|
154
|
+
逐条判对错;`soft` 按其描述做定性判断。文档若还点名了「必须复跑的既有资产」,一并跑。
|
|
155
|
+
项目自己的验证约定(跑什么测、要不要真产物 E2E)见 `.hskill/handoff/config.md` 的
|
|
156
|
+
`verification` 段。
|
|
157
|
+
2. **判成败的命令不接管道。** `cmd | tail` 的退出码是 `tail` 的,它恒为 0;输出还被截断,
|
|
158
|
+
连哪些用例根本没被发现都看不出来——两个信息一起丢。
|
|
159
|
+
3. **结果写成独立小节**,标题形如 `## 接手方自测记录(<日期>)`——**标题里必须有「自测」
|
|
160
|
+
二字**,`validate-handoff.sh` 按这个词认这一节。逐条列 pass/fail,附实际跑的命令。
|
|
161
|
+
写进你自己这一节,别混进原 session 的验收记录。
|
|
162
|
+
4. **有红就不许推 `status`。** 两条出路,没有第三条:
|
|
163
|
+
- 修到绿;
|
|
164
|
+
- 或者认为那条红不构成未达成(例如它在你动手之前就红),**在自测记录里那一条旁边写出
|
|
165
|
+
归因证据**(比如在分叉点上跑同一条命令的结果),并显式声明「带着这条红送验」。
|
|
166
|
+
**沉默地推上来不行**——accept 方一定会跑到它,届时你既丢了一轮,也丢了信用。
|
|
167
|
+
|
|
168
|
+
自测**不替代** accept:accept 方一律不采信接手方结论、逐条自己重跑(Phase 3)。自测的作用
|
|
169
|
+
是让「送验」这个动作有成本、有记录,不是让 accept 省事。
|
|
170
|
+
|
|
171
|
+
### 复修轮(被打回之后)
|
|
172
|
+
|
|
173
|
+
打回不是「改那一条就完事」。范围小、心态是「就改一行」,恰恰是二次打回最常见的来源。
|
|
174
|
+
|
|
175
|
+
- 复修完**重新走一遍本 phase**,`status` 才能再置回「待验收」。
|
|
176
|
+
- **自测范围默认是锚点全集,不是被打回的那几条。** 要缩小,必须在复修自测记录里给出两样
|
|
177
|
+
东西:改动范围证据(`git diff --name-only <打回点提交>..HEAD`)+「为什么其余条目不可能
|
|
178
|
+
被这些改动波及」的论证。给不出就跑全集。
|
|
179
|
+
- 记录**另起一节**,标题形如 `## 接手方复修自测记录(第 N 轮)`,同样必须含「自测」二字。
|
|
180
|
+
不覆盖、不合并前几轮——几轮并排放着,后来人才看得出哪条判据反复红过。
|
|
181
|
+
- 打回记录点名了修法就照做;**不认同要在复修记录里写出理由退回讨论,不要静默换一种改法**。
|
|
182
|
+
尤其不要把一条刚开始真的会红的断言改回恒真——那不是修复,是把判据废掉。
|
|
54
183
|
|
|
55
184
|
## Phase 3 — accept(原 session 验收)
|
|
56
185
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
186
|
+
**先到位,再验收。** 验收在**被验代码所在的工作区**跑——不在主工作树、不在核心分支
|
|
187
|
+
(staging / main / master)上跑。主工作树通常停在集成分支,那里根本没有接手方的改动:
|
|
188
|
+
在那里跑出来的绿是**别的代码的绿**,比不跑更有害,因为它看起来像验过了。
|
|
189
|
+
|
|
190
|
+
1. **回到交接工作区**:按文末「平台适配」进 author 阶段第 4 步建的那个 worktree。
|
|
191
|
+
路径有三个可能来源,
|
|
192
|
+
哪个在手用哪个——你自己的上下文(你就是 author 时)、用户粘贴的验收指令(author 第 9 步
|
|
193
|
+
输出的那段)、或文档 frontmatter 的 `worktree`(文档已在手时)。三个都没有 → 用
|
|
194
|
+
`git worktree list` 按分支名查回来。确认这次交接根本不涉及独立工作区(同目录同分支续做)
|
|
195
|
+
才跳过本步。
|
|
196
|
+
- **在那里重读一遍交接文档。** 你手上这份可能是 author 时写的旧版;接手方的自测记录、
|
|
197
|
+
`status`、以及被修正过的字段,全都只存在于那个工作区里的那一份。读错版本不会报错,
|
|
198
|
+
只会让你对着过时的内容验收。
|
|
199
|
+
- 后面**每一条**验收命令都在这个工作区里跑。
|
|
200
|
+
- 路径不在了(被谁 remove 了)→ `git worktree list` 看这条分支现在挂在哪;都没有就用
|
|
201
|
+
`git worktree add --detach <临时路径> <branch>` 重建,验完 remove。**必须带 `--detach`**——
|
|
202
|
+
一条分支不能被两个 worktree 同时 checkout。
|
|
203
|
+
- 跑第一条验收命令之前确认到位:`git -C <验收目录> rev-parse --abbrev-ref HEAD` 落在
|
|
204
|
+
staging/main/master 上,说明你还在主工作树,停下来查,别接着跑。
|
|
205
|
+
2. **先跑一次机器校验**:`bash <skill 目录>/scripts/validate-handoff.sh <文档路径>`。
|
|
206
|
+
`status` 是「待验收」却没有含「自测」的小节 → 脚本直接 exit 1。**这种情况按未达成处理,
|
|
207
|
+
当场置「打回」退回去,不必开始逐条重跑**:接手方连自己那一遍都没跑,你这一轮多半是在
|
|
208
|
+
替它跑第一遍。
|
|
209
|
+
|
|
210
|
+
3. 找文档里的**最小验收锚点**——这是唯一固定依据。**接手方自填的结论一律不采信,逐条自己跑**:验证产物"存在"不等于"跑得过",点得出脚本名不等于那个脚本此刻是绿的。frontmatter 的 `acceptance` 指明是哪一档:`hard`(逐条对/错)→ 按锚点描述**逐条实跑**(单测/E2E/核验);`soft`(定性描述)→ 按其描述做定性判断。字段与锚点正文不符时**以正文为准**并把字段改对——字段是索引,正文才是判据。
|
|
211
|
+
4. 把验收结果(每条 pass/fail,或整体达成/未达成)追加记录到最小验收锚点所在章节末尾。**接手方若已自填过验收记录,另起小节并列,不覆盖也不合并**——两份并排放着,后来人才看得出哪些结论被第二方复核过。其中若有与实跑不符的陈述,**显式写出更正**,不要静默改掉:静默改掉等于把同一个错误留给下一次。
|
|
212
|
+
5. 达成 → `status` 置 `已验收`;未达成 → `status` 置 `打回`。打回记录必须写清三件事,
|
|
213
|
+
缺了接手方只能猜:**哪几条未达成**、**为什么**(判据原文 vs 实跑结果)、以及
|
|
214
|
+
**复修后要重跑的范围**(默认全集;认为可以只跑子集就在这里点名)。退回接手方后,
|
|
215
|
+
它重新走 Phase 2.5 才能再置回「待验收」。
|
|
216
|
+
6. **达成才算真正完成**(硬判据要求逐条全绿;软判据按其描述定性判断是否达成)。
|
|
61
217
|
|
|
62
218
|
## 状态生命周期
|
|
63
219
|
|
|
64
|
-
`待执行`(author 写完)→ `执行中`(verify 通过 / 接手方开工)→
|
|
220
|
+
`待执行`(author 写完)→ `执行中`(verify 通过 / 接手方开工)→ `待验收`(接手方**自测通过后**
|
|
221
|
+
回报完成,见 Phase 2.5)→ `已验收`(accept 判定达成)/ `打回`(accept 判定未达成,退回执行中)。
|
|
222
|
+
|
|
223
|
+
`打回` 之后的回路是闭合的:**接手方复修 → 重新走一遍 Phase 2.5 → 才能再置回 `待验收`**。
|
|
224
|
+
直接从复修跳回「待验收」不算数。
|
|
225
|
+
|
|
226
|
+
`status` 是各 phase 间唯一协调锚点,无需外部状态存储。
|
|
227
|
+
|
|
228
|
+
要扫「哪些交接还没验收」,**别在当前工作树里 grep**——在途交接的文档都在各自的交接工作区里,
|
|
229
|
+
主工作树上那份(如果有)是合并后的历史归档,状态是旧的。正确做法是先 `git worktree list`
|
|
230
|
+
列出所有工作区,再到每个工作区的 `<output_dir>` 里 grep `status`。
|
|
65
231
|
|
|
66
|
-
|
|
232
|
+
**写入权按 phase 分:接手方最多只能把 `status` 推到「待验收」,且推之前必须过 Phase 2.5。`已验收` / `打回` 只能由原 session 在 accept 之后写。**
|
|
67
233
|
|
|
68
|
-
|
|
234
|
+
校验脚本查不了「谁写的」——它看不出某个值出自哪一方。这是约定,靠 accept 方兜底(见本节末)。
|
|
235
|
+
它查得了的是「有没有自测记录」:`status` 为「待验收」而正文没有含「自测」的小节,脚本 exit 1。
|
|
236
|
+
这一条堵的是「改完就推」,堵不住「自测跑了但结论是编的」——后者仍然只能靠 accept 方逐条重跑。
|
|
69
237
|
|
|
70
238
|
这条不是流程洁癖。「已验收」的全部信息量就是**做事的人之外的另一方查过**;做事的人一旦能自己写它,它就退化成「做事的人说做完了」——而这个信息「待验收」里已经有了,两个状态变成同义词,字段失效。风险还会反向放大:一份自填的「已验收」通常附着一张全 PASS 的表,比没有记录更难被怀疑。
|
|
71
239
|
|
|
72
240
|
接手方若跳档自填,accept 方**按未验收处理**,照常逐条重跑。
|
|
241
|
+
|
|
242
|
+
## 平台适配(怎么进出交接工作区)
|
|
243
|
+
|
|
244
|
+
author 之后的每个 phase 都要求"到被验代码所在的工作区里去"。**这个要求是平台无关的,实现手段不是**——
|
|
245
|
+
所以正文只说"进去",具体动作查本节。你所在的平台不在下表里,按「通用兜底」办。
|
|
246
|
+
|
|
247
|
+
判据只有一条:**后续命令的工作目录是不是那个工作区**。谁能做到都行。
|
|
248
|
+
|
|
249
|
+
### Claude Code
|
|
250
|
+
|
|
251
|
+
| 动作 | 手段 |
|
|
252
|
+
|---|---|
|
|
253
|
+
| 进入 | `EnterWorktree(path: "<工作区绝对路径>")` |
|
|
254
|
+
| 离开 | `ExitWorktree(action: "keep")` |
|
|
255
|
+
|
|
256
|
+
- **只用 `path` 模式,绝不用 `name`。** `name` 会**自己建**工作区和分支:分支名形如
|
|
257
|
+
`worktree-<name 把 / 换成 +>`(过不了多数仓库的分支命名 hook),基线由 `worktree.baseRef`
|
|
258
|
+
决定、默认 `fresh` 取 `origin/<默认分支>`——仓库若不常推远程,那可能落后几百个提交。
|
|
259
|
+
交接要的分支名和基线都得由 author 自己定,所以只能**先 `git worktree add` 建、再 `path` 进**。
|
|
260
|
+
- `path` 只认**当前仓库**(或嵌套在其中的仓库)注册过的工作区,跨仓库直接拒绝。
|
|
261
|
+
交接双方在同一仓库时不是问题;跨仓库按「通用兜底」办。
|
|
262
|
+
- 必须由当前会话**直接调**,不能交给 fork/subagent 代调。
|
|
263
|
+
- 离开一律 `action: "keep"`。以 `path` 进入的工作区它本来就不会删,但显式 `keep` 更稳;
|
|
264
|
+
**`remove` 在交接期间绝对不能用**——验收方还要回来。
|
|
265
|
+
|
|
266
|
+
### 通用兜底(无此类能力,或跨仓库)
|
|
267
|
+
|
|
268
|
+
每条命令自带限定,**不要靠裸 `cd`**:多数 agent harness 里 `cd` 只在单条命令内有效,
|
|
269
|
+
下一条又回到原目录,你会以为自己在工作区里、其实命令全打在主工作树上。
|
|
270
|
+
|
|
271
|
+
- git:`git -C <工作区> <命令>`
|
|
272
|
+
- 其他 shell 命令:`cd <工作区> && <命令>` 写在**同一条**命令里
|
|
273
|
+
- **读写文件一律用绝对路径。** 这条最容易漏:`git -C` 只管得住 git,管不住
|
|
274
|
+
Read / Edit / Write / Grep / Glob——那些按**会话当前目录**解析相对路径。会话在主工作树、
|
|
275
|
+
你以为在工作区里改文件,一个相对路径就改到了另一份同名文件上,**而且会成功**。
|
|
276
|
+
|
|
277
|
+
人类接手时同理:`cd <工作区>` 之后不要再切回去。
|
|
@@ -2,19 +2,37 @@
|
|
|
2
2
|
|
|
3
3
|
不是待填空的固定骨架。每次起草前,先确定这次交接的目的,再对下表逐类内容过一遍必要性测试——测试答案是"会"就写出对应章节,答案是"不会"就跳过,不留空标题、不留占位。
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 固定骨架:frontmatter + 两个锚点
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
frontmatter 的字段是给机器读的(`status` 驱动各 phase,`source_node`/`target_node` 驱动画布关系,`branch` 与 `worktree` 由 author 建好工作区后填,接手方照它进去开工、accept 方照它回来验收),由 `scripts/validate-handoff.sh` 校验;「交接目的」和「最小验收锚点」是给人读的,任何情况下不能省。文档必须包含以下开头结构和「最小验收锚点」一节:
|
|
8
8
|
|
|
9
9
|
```
|
|
10
|
+
---
|
|
11
|
+
status: 待执行 # 待执行|执行中|待验收|已验收|打回
|
|
12
|
+
date: <YYYY-MM-DD> # 须与文件名的日期段一致
|
|
13
|
+
author_model: <model>
|
|
14
|
+
acceptance: hard # hard|soft,决定 accept 阶段逐条实跑还是定性判断
|
|
15
|
+
branch: <分支名> # 可选:接手方要在另一条分支上开工时,由 author 建好后填
|
|
16
|
+
worktree: <绝对路径> # 与 branch 成对:author 建好的交接工作区,接手方与 accept 方都进这里
|
|
17
|
+
source_node: <uuid> # 可选:author 在 Agent Canvas 画布节点里时才写
|
|
18
|
+
target_node: # 留空,接手方在 verify 建完 hands-off-to 后回填
|
|
19
|
+
---
|
|
20
|
+
|
|
10
21
|
# 交接:<任务一句话>
|
|
11
22
|
|
|
12
|
-
**日期**:<YYYY-MM-DD>
|
|
13
|
-
**author 模型**:<model>
|
|
14
|
-
**状态**:待执行 <!-- 待执行 → 执行中 → 待验收 → 已验收 / 打回 -->
|
|
15
23
|
**交接目的**:<一句话,自由描述这次交接是为了什么,不受预设分类约束>
|
|
16
24
|
|
|
17
|
-
>
|
|
25
|
+
> **接手方须知**:你正在接手一个任务。本文档是完整交接与唯一权威入口:从头读到尾,若文档里有「工作流约定」章节按其开工,没有就直接开工。
|
|
26
|
+
>
|
|
27
|
+
> **完成后不是直接推状态,先自测**(skill 的 Phase 2.5):逐条实跑「最小验收锚点」**全集**(不是只跑你改动相关的那几条),外加文档点名要复跑的既有资产;判成败的命令不接管道(`| tail` 的退出码是 `tail` 的,恒为 0)。把结果写成**独立小节**,标题里必须有「自测」二字(如「接手方自测记录(日期)」),逐条列 pass/fail 并附实际命令——写你自己这一节,别混进原 session 的验收记录。**有红就别推状态**:要么修到绿,要么在那一条旁边写出归因证据并显式声明「带着这条红送验」,不许沉默推上来。`validate-handoff.sh` 会拦:`status` 是「待验收」而正文没有含「自测」的小节直接 exit 1。
|
|
28
|
+
>
|
|
29
|
+
> 自测过了,才把 frontmatter 的 `status` 置为「待验收」并**停在这里**——`已验收` / `打回` 由原 session 按「最小验收锚点」判定后写,不要代填。
|
|
30
|
+
>
|
|
31
|
+
> **被打回之后同理,而且默认跑全集**:打回轮范围小、容易觉得「就改一行」,恰恰是二次打回最常见的来源。复修完重新走一遍自测才能再置回「待验收」;要只跑子集,必须在记录里附改动范围证据(`git diff --name-only <打回点提交>..HEAD`)和「其余条目不可能被波及」的论证。复修记录另起一节(如「接手方复修自测记录(第 N 轮)」,同样含「自测」二字),不覆盖前几轮。
|
|
32
|
+
>
|
|
33
|
+
> **开工前**:若 frontmatter 有 `source_node`、且你也在 Agent Canvas 画布节点里,先建一条 `hands-off-to` 关系(`agent-canvas-ctl whoami` 取自己的 id,核对 `node-relations` 里没有后 `link-nodes --from <source_node> --to <自己> --type hands-off-to`),建完把自己的 id 填进 `target_node`。**只建这一条**——别建 `implements`、别另立需求节点。
|
|
34
|
+
>
|
|
35
|
+
> **在哪开工**:frontmatter 有 `worktree` 时,进那个工作区干活,核对当前分支与 `branch` 一致。**怎么进按你所在平台来**(Claude Code 用 `EnterWorktree(path: <worktree>)` 的 `path` 模式;没有这类能力就每条命令自带限定 `git -C <worktree>`,读写文件用绝对路径,别靠裸 `cd`——它只在单条命令内有效)。判据只有一条:后续命令的工作目录确实是那个工作区。**不要自己 `git worktree add`**(那条分支已被这个工作区占用,再建会失败,而且原 session 验收时回的是它自己建的那个,看不到你的改动),**也绝不要销毁它**(`git worktree remove`,或平台的"退出并删除")——验收还要用。路径不存在就打回原 session 重建,别自己挑地方。
|
|
18
36
|
|
|
19
37
|
---
|
|
20
38
|
|
|
@@ -42,4 +60,5 @@
|
|
|
42
60
|
2. 逐类过必要性测试表,决定要写哪些章节。
|
|
43
61
|
3. 按选中的章节撰写:背景 → 关键决定 → 范围铁律 → 相关文档索引 → 受影响文件/落点 → 工作流约定 → 验证步骤(只写选中的,跳过未选中的)。指针式引用权威依据,只内联接手方开工必需的硬核。
|
|
44
62
|
4. 写最小验收锚点(必写,任何情况下不能省)。
|
|
45
|
-
5.
|
|
63
|
+
5. 若在 Agent Canvas 画布节点里,按 `SKILL.md` author 第 6 步填 `source_node`(并在已能指认接手节点时当场建 `hands-off-to`)。
|
|
64
|
+
6. 跑 `SKILL.md` 里的完整性门禁(先跑 `scripts/validate-handoff.sh`,再做冷读测试)。
|