harveyz-skill 0.34.0 → 0.35.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 -0
- package/README.md +31 -2
- package/bin/cli.js +49 -20
- package/lib/bundles.js +12 -4
- package/lib/mcp-server.js +2 -2
- package/package.json +8 -3
- package/skills/agent-canvas/agent-canvas-control/SKILL.md +3 -2
- package/skills/agent-canvas/capture-requirement/SKILL.md +3 -2
- package/skills/agent-canvas/close-node/SKILL.md +3 -2
- package/skills/agent-canvas/describe-node/SKILL.md +11 -6
- package/skills/agent-canvas/relate-node/SKILL.md +4 -3
- package/skills/agent-canvas/relation-review/SKILL.md +3 -3
- package/skills/coding/analyze-claudemd/SKILL.md +114 -0
- package/skills/coding/analyze-claudemd/references/criteria.md +142 -0
- package/skills/coding/capture-vocab/SKILL.md +20 -74
- package/skills/coding/capture-vocab/references/manage.md +115 -0
- package/skills/coding/capture-vocab/references/project-setup.md +31 -0
- package/skills/coding/capture-vocab/scripts/__pycache__/vocab.cpython-314.pyc +0 -0
- package/skills/coding/capture-vocab/scripts/vocab.py +207 -0
- package/skills/coding/capture-vocab/tests/__pycache__/test_vocab.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/coding/capture-vocab/tests/fixtures/.hskill/capture-vocab/vocab.md +245 -0
- package/skills/coding/capture-vocab/tests/test_vocab.py +159 -0
- package/skills/coding/init-project/SKILL.md +157 -0
- package/skills/coding/init-project/assets/skeleton/CLAUDE.md +17 -0
- package/skills/coding/init-project/assets/skeleton/README.md +12 -0
- package/skills/coding/init-project/assets/skeleton/TODO.md +9 -0
- package/skills/coding/init-project/assets/skeleton/gitignore-code +19 -0
- package/skills/coding/init-project/assets/templates/code.yml +37 -0
- package/skills/coding/init-project/references/check-report.md +55 -0
- package/skills/coding/init-project/references/template-schema.md +63 -0
- package/skills/feed/manage-creators/SKILL.md +10 -2
- package/skills/feed/sync-website/scripts/__pycache__/store_config.cpython-314.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-xtimeline/scripts/__pycache__/store_config.cpython-314.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-ytchannel/scripts/__pycache__/store_config.cpython-314.pyc +0 -0
- package/skills/feed/sync-ytchannel/tests/__pycache__/test_store_config.cpython-314-pytest-9.1.1.pyc +0 -0
- package/skills/research/clip-url/scripts/__pycache__/store_config.cpython-314.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/learn-video/SKILL.md +14 -7
- package/skills/research/learn-video/scripts/__pycache__/archive.cpython-314.pyc +0 -0
- package/skills/research/learn-video/scripts/__pycache__/build_creator_index.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 +21 -57
- package/skills/research/learn-video/scripts/build_creator_index.py +136 -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_build_creator_index.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 +61 -108
- package/skills/research/learn-video/tests/test_build_creator_index.py +192 -0
- package/skills-index.json +37 -13
- package/tools/roster/roster/__init__.py +1 -1
- package/tools/roster/roster/__main__.py +33 -3
- 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__/migrate_schema.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/migrate_schema.py +52 -0
- package/tools/roster/roster/registry.py +7 -3
- package/tools/roster/roster/urls.py +5 -1
- package/tools/roster/tests/__pycache__/test_cli.cpython-314-pytest-9.1.1.pyc +0 -0
- package/tools/roster/tests/__pycache__/test_config.cpython-314-pytest-9.1.1.pyc +0 -0
- package/tools/roster/tests/__pycache__/test_migrate_schema.cpython-314-pytest-9.1.1.pyc +0 -0
- package/tools/roster/tests/__pycache__/test_registry.cpython-314-pytest-9.1.1.pyc +0 -0
- package/tools/roster/tests/__pycache__/test_registry_merge.cpython-314-pytest-9.1.1.pyc +0 -0
- package/tools/roster/tests/__pycache__/test_state.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 +28 -1
- package/tools/roster/tests/test_config.py +2 -2
- package/tools/roster/tests/test_migrate_schema.py +157 -0
- package/tools/roster/tests/test_registry.py +33 -2
- package/tools/roster/tests/test_registry_merge.py +11 -0
- package/tools/roster/tests/test_state.py +26 -0
- package/tools/roster/tests/test_urls.py +15 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.35.0] - 2026-09-21
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- `learn-video`:新增 `build_creator_index.py`(`build`/`check` 两个子命令)。扫描 vdl 写出的全部 `meta.json`,按归一化后的 YouTube handle(去 `@`、转小写)分组,产出 `<knowledgeRoot>/videos/creators.json`。不读、不写 `registry.json`——"是不是在关注这个人"是判断,判断不落盘在事实旁边,完全交给下游(scholia)现查决定,索引本身永远不含 `watched`/`creator_id`。原子写(临时文件 + rename),构建失败旧索引原样保留;单个 `meta.json` 损坏时归入 `unresolved` 而不是从统计里静默消失;`work` 目录不存在(vdl 的 `WORK_ROOT` 漂了)时报错退出,不会把一个正常的索引悄悄替换成空索引
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- **破坏性变更** `learn-video`:`archive.py` 从"写 `meta.json`"降级为"校验 `meta.json`"。vdl(Video-Learner 仓库)现在自己把 `uploader_id`/`channel_id`/`uploader_url` 三个新字段与统一存储契约的三个必填字段(`source_url`/`title`/`fetched_at`)全部写好,`archive.py` 只剩读一遍 `meta.json` 核对必填字段是否齐全,不再从 vdl 的 sqlite 捞取任何展示字段,也不再写文件。CLI 入参从 `TASK_ID`/`SOURCE_URL`/`TITLE`/`FETCHED_AT` 四个环境变量精简到只剩 `TASK_ID`。version 1.8.2 → 1.9.0
|
|
17
|
+
- **升级路径**:这是 vdl 那一侧先落地的改动的下游收尾。若本机 vdl 版本落后(写出的 `meta.json` 还没有新增字段/契约字段),归档步骤会直接报错停下并列出缺的字段名,不会再像过去那样悄悄补一份缺字段的 `meta.json`。看到这个报错,先确认 Video-Learner 是否需要升级
|
|
18
|
+
|
|
10
19
|
## [0.34.0] - 2026-09-16
|
|
11
20
|
|
|
12
21
|
### Added
|
package/README.md
CHANGED
|
@@ -96,14 +96,43 @@ hskill install --bundle dev # 安装整个 bundle
|
|
|
96
96
|
hskill install --skill git-workflow-init # 安装单个 skill
|
|
97
97
|
hskill install --tool hub # 安装 shell 工具
|
|
98
98
|
hskill list # 查看可用 skill
|
|
99
|
-
hskill update #
|
|
99
|
+
hskill update # 更新 hskill 自身(沿用当前来源)
|
|
100
|
+
hskill version # 查看版本与安装来源
|
|
100
101
|
hskill --help # 查看帮助
|
|
101
102
|
```
|
|
102
103
|
|
|
103
104
|
Skills 安装到 `~/.claude/skills/`,shell 工具安装到 `~/.local/bin/`。
|
|
104
105
|
|
|
106
|
+
**从本地仓库安装 hskill 自身**
|
|
107
|
+
|
|
108
|
+
发版前想先用一阵子工作树里的改动,可以把 hskill 装成本地来源:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
hskill update --local ~/Projects/harveyz-skill # 从本地仓库打包安装
|
|
112
|
+
hskill update # 之后裸跑就一直走本地,不会跳回 npm
|
|
113
|
+
hskill update --npm # 显式切回 npm registry
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
`--local` 走的是 `npm pack` + 安装 tarball,**不是软链**——产出独立快照,并且真实执行 `prepack` 与 `package.json` 的 `files[]` 白名单,等于在发 npm 之前预演一次真实发布,能提前暴露打包问题。
|
|
117
|
+
|
|
118
|
+
两种来源共存于同一个命令,`update` 是**粘性**的:本地装的就从原仓库重新打包,npm 装的就走 registry,**裸 `update` 永远不跨来源**。跨来源只能由 `--local` / `--npm` 显式触发,触发时会打印完整迁移行。
|
|
119
|
+
|
|
120
|
+
安装来源记在全局安装目录里(`.hskill-source.json` + 版本号后缀 `+local`)。因为任何一次 `npm install -g` 都会清空重建该目录,绕过 hskill 手工安装也会自动抹掉痕迹,所以记录的来源不会与实际情况脱节:
|
|
121
|
+
|
|
122
|
+
```console
|
|
123
|
+
$ hskill version
|
|
124
|
+
0.34.0+local
|
|
125
|
+
|
|
126
|
+
source: local /Users/you/Projects/harveyz-skill
|
|
127
|
+
branch: staging commit: 3d4192a
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
本地来源下 `hskill version --check` 比对的是**记录的 commit 与仓库 HEAD**,不是版本号——开发分支上版本号常常几十个提交不动,能动的只有 commit。
|
|
131
|
+
|
|
105
132
|
**本地源码开发**
|
|
106
133
|
|
|
134
|
+
不安装、直接从仓库跑 CLI 来装 skill:
|
|
135
|
+
|
|
107
136
|
```bash
|
|
108
137
|
node bin/cli.js install --skill mermaid-diagram --target claude
|
|
109
138
|
node bin/cli.js install --bundle dev --target claude
|
|
@@ -149,7 +178,7 @@ hskill hooks uninstall check-similar-branch --scope project # 从当前项目
|
|
|
149
178
|
| **hskill_install** | 安装一个 bundle、指定 skill 或 shell 工具 |
|
|
150
179
|
| **hskill_uninstall** | 卸载指定的 skill 或 shell 工具 |
|
|
151
180
|
| **hskill_hooks** | 查看、安装或卸载 hskill git hooks |
|
|
152
|
-
| **hskill_update** |
|
|
181
|
+
| **hskill_update** | 更新 hskill 自身,沿用当前安装来源(npm 或本地仓库);切换来源需用 CLI 的 `--npm` / `--local` |
|
|
153
182
|
|
|
154
183
|
在 MCP host 的配置中注册(假设已通过 `npm install -g harveyz-skill` 全局安装):
|
|
155
184
|
|
package/bin/cli.js
CHANGED
|
@@ -9,7 +9,7 @@ import path from 'path'
|
|
|
9
9
|
import { fileURLToPath } from 'url'
|
|
10
10
|
import {
|
|
11
11
|
getAllSkillItems, getAllToolItems, getAllHookItems, checkHookInstalled,
|
|
12
|
-
checkInstalled, checkToolInstalled, scopeSummary,
|
|
12
|
+
checkInstalled, checkToolInstalled, scopeSummary, toSkillItems,
|
|
13
13
|
resolveSkills, resolveSkillsByName, resolveTools, resolveToolsByName,
|
|
14
14
|
TOOL_BUNDLE_CHOICES,
|
|
15
15
|
} from '../lib/bundles.js'
|
|
@@ -375,13 +375,32 @@ if (subcommand === 'update') {
|
|
|
375
375
|
await updateToNpm(priorSource)
|
|
376
376
|
}
|
|
377
377
|
|
|
378
|
+
// Re-require fresh: the self-update above just replaced this install
|
|
379
|
+
// directory's skills-index.json on disk, but bin/cli.js's own top-level
|
|
380
|
+
// import of lib/bundles.js already cached the *old* skillDefs at process
|
|
381
|
+
// start. A plain require() here is the first hit for this path in this
|
|
382
|
+
// process, so it reads what's actually on disk now.
|
|
383
|
+
const { renames = [], skills: freshSkillDefs = [] } = require('../skills-index.json')
|
|
384
|
+
const skillsRoot = path.join(__dirname, '..', 'skills')
|
|
385
|
+
|
|
386
|
+
// Auto-upgrade skills opted into `autoUpdate: true` (skills-index.json),
|
|
387
|
+
// scoped to `user` to match `hskill upgrade`'s default scope.
|
|
388
|
+
const autoUpdateRows = buildSkillRows(null, toSkillItems(freshSkillDefs, skillsRoot))
|
|
389
|
+
.filter(r => r.autoUpdate)
|
|
390
|
+
if (autoUpdateRows.length > 0) {
|
|
391
|
+
const autoTargets = resolveTargets(['all'], 'user')
|
|
392
|
+
const autoSummary = await upgradeOutdatedSkills(autoUpdateRows, autoTargets, 'userDetail')
|
|
393
|
+
const upgraded = [...new Set(Object.values(autoSummary).flatMap(s => s.installed ?? []))]
|
|
394
|
+
const failed = [...new Set(Object.values(autoSummary).flatMap(s => (s.failed ?? []).map(f => f.name)))]
|
|
395
|
+
if (upgraded.length > 0) console.log(chalk.green(` ✔ Auto-updated ${upgraded.length} skill(s): ${upgraded.join(', ')}`))
|
|
396
|
+
if (failed.length > 0) console.log(chalk.yellow(` ⚠ Auto-update failed for: ${failed.join(', ')}`))
|
|
397
|
+
}
|
|
398
|
+
|
|
378
399
|
// Run skill rename migrations
|
|
379
|
-
const { renames = [], skills: skillDefs = [] } = require('../skills-index.json')
|
|
380
400
|
if (renames.length > 0) {
|
|
381
401
|
console.log(chalk.dim(' · Migrating renamed skills…'))
|
|
382
402
|
const targets = SKILL_TARGETS.map(name => ({ name, dir: userSkillDir(name) }))
|
|
383
|
-
const
|
|
384
|
-
const migrationSummary = await migrateRenamedSkills(renames, targets, skillsRoot, skillDefs)
|
|
403
|
+
const migrationSummary = await migrateRenamedSkills(renames, targets, skillsRoot, freshSkillDefs)
|
|
385
404
|
const totalMigrated = Object.values(migrationSummary).reduce((n, s) => n + s.migrated.length, 0)
|
|
386
405
|
const totalFailed = Object.values(migrationSummary).reduce((n, s) => n + s.failed.length, 0)
|
|
387
406
|
if (totalMigrated > 0) console.log(chalk.green(` ✔ Migrated ${totalMigrated} skill(s)`))
|
|
@@ -453,10 +472,11 @@ function resolveHookDisplayVersion(inst, sourceVersion) {
|
|
|
453
472
|
}
|
|
454
473
|
|
|
455
474
|
// ── Shared skill scan ─────────────────────────────────────────────────────────
|
|
456
|
-
function buildSkillRows(nameFilter = null) {
|
|
475
|
+
function buildSkillRows(nameFilter = null, sourceItems = null) {
|
|
476
|
+
const allItems = sourceItems ?? getAllSkillItems()
|
|
457
477
|
const items = nameFilter
|
|
458
|
-
?
|
|
459
|
-
:
|
|
478
|
+
? allItems.filter(s => s.skillName === nameFilter)
|
|
479
|
+
: allItems
|
|
460
480
|
return items.map(s => {
|
|
461
481
|
const inst = checkInstalled(s.skillName, s.version ?? '—')
|
|
462
482
|
return {
|
|
@@ -464,6 +484,7 @@ function buildSkillRows(nameFilter = null) {
|
|
|
464
484
|
bundle: s.bundle ?? '—',
|
|
465
485
|
version: s.version ?? '—',
|
|
466
486
|
installScope: s.installScope ?? null,
|
|
487
|
+
autoUpdate: s.autoUpdate ?? false,
|
|
467
488
|
srcPath: s.srcPath,
|
|
468
489
|
userStatus: scopeSummary(inst.user),
|
|
469
490
|
projectStatus: scopeSummary(inst.project),
|
|
@@ -473,6 +494,26 @@ function buildSkillRows(nameFilter = null) {
|
|
|
473
494
|
})
|
|
474
495
|
}
|
|
475
496
|
|
|
497
|
+
// Shared by `upgrade` and the post-`update` auto-upgrade step: for each
|
|
498
|
+
// target, install whichever rows are outdated (status === 'update') on that
|
|
499
|
+
// target's scope. Rows not carrying the given scope's detail are left alone.
|
|
500
|
+
async function upgradeOutdatedSkills(rows, targetList, scopeKey) {
|
|
501
|
+
const summary = {}
|
|
502
|
+
for (const { name: targetName, dir } of targetList) {
|
|
503
|
+
const upgradeList = rows
|
|
504
|
+
.filter(r => r[scopeKey]?.[targetName]?.status === 'update')
|
|
505
|
+
.map(r => ({ skillName: r.name, srcPath: r.srcPath, version: r.version }))
|
|
506
|
+
|
|
507
|
+
if (!upgradeList.length) continue
|
|
508
|
+
|
|
509
|
+
console.log('')
|
|
510
|
+
const result = await installSkills(upgradeList, [{ name: targetName, dir }], true)
|
|
511
|
+
Object.assign(summary, result)
|
|
512
|
+
console.log('')
|
|
513
|
+
}
|
|
514
|
+
return summary
|
|
515
|
+
}
|
|
516
|
+
|
|
476
517
|
// ── Status / Outdated ─────────────────────────────────────────────────────────
|
|
477
518
|
if (subcommand === 'status' || subcommand === 'outdated') {
|
|
478
519
|
const outdatedOnly = subcommand === 'outdated'
|
|
@@ -924,19 +965,7 @@ if (subcommand === 'upgrade') {
|
|
|
924
965
|
const targetList = resolveTargets(upgradeTargetArg ? [upgradeTargetArg] : ['all'], upgradeScopeArg)
|
|
925
966
|
const scopeKey = upgradeScopeArg + 'Detail' // 'userDetail' or 'projectDetail'
|
|
926
967
|
|
|
927
|
-
const summary =
|
|
928
|
-
for (const { name: targetName, dir } of targetList) {
|
|
929
|
-
const upgradeList = rows
|
|
930
|
-
.filter(r => r[scopeKey]?.[targetName]?.status === 'update')
|
|
931
|
-
.map(r => ({ skillName: r.name, srcPath: r.srcPath, version: r.version }))
|
|
932
|
-
|
|
933
|
-
if (!upgradeList.length) continue
|
|
934
|
-
|
|
935
|
-
console.log('')
|
|
936
|
-
const result = await installSkills(upgradeList, [{ name: targetName, dir }], true)
|
|
937
|
-
Object.assign(summary, result)
|
|
938
|
-
console.log('')
|
|
939
|
-
}
|
|
968
|
+
const summary = await upgradeOutdatedSkills(rows, targetList, scopeKey)
|
|
940
969
|
|
|
941
970
|
const nothingUpgraded = Object.keys(summary).length === 0
|
|
942
971
|
if (jsonFlag) {
|
package/lib/bundles.js
CHANGED
|
@@ -101,21 +101,29 @@ export function buildAllChoices() {
|
|
|
101
101
|
return choices
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
//
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
104
|
+
// 把一组原始 skill 定义(来自 skills-index.json 的 skills[])展开为运行时条目。
|
|
105
|
+
// 抽出来是因为 `hskill update` 在自更新落盘后,需要绕开本模块顶部那次一次性
|
|
106
|
+
// require() 缓存的旧 skillDefs,直接用刚写到磁盘的新 skills-index.json 重新展开。
|
|
107
|
+
export function toSkillItems(defs, root) {
|
|
108
|
+
return defs.map(skill => {
|
|
109
|
+
const srcPath = path.join(root, skill.path)
|
|
108
110
|
return {
|
|
109
111
|
kind: 'skill',
|
|
110
112
|
skillName: skill.path.split('/').pop(),
|
|
111
113
|
bundle: skill.bundle,
|
|
112
114
|
installScope: skill.installScope ?? null,
|
|
115
|
+
autoUpdate: skill.autoUpdate ?? false,
|
|
113
116
|
srcPath,
|
|
114
117
|
version: readVersion(srcPath),
|
|
115
118
|
}
|
|
116
119
|
})
|
|
117
120
|
}
|
|
118
121
|
|
|
122
|
+
// 所有 skill 展开为 { kind:'skill', skillName, bundle, srcPath } 列表(对应 all 选项)
|
|
123
|
+
export function getAllSkillItems() {
|
|
124
|
+
return toSkillItems(skillDefs, skillsRoot)
|
|
125
|
+
}
|
|
126
|
+
|
|
119
127
|
// 所有 tool 展开为 { kind:'tool', toolName, srcPath, version } 列表
|
|
120
128
|
export function getAllToolItems() {
|
|
121
129
|
return toolDefs.map(tool => {
|
package/lib/mcp-server.js
CHANGED
|
@@ -152,12 +152,12 @@ export function createServer() {
|
|
|
152
152
|
})
|
|
153
153
|
|
|
154
154
|
server.registerTool('hskill_update', {
|
|
155
|
-
description: 'Update hskill itself
|
|
155
|
+
description: 'Update hskill itself from whichever source the current install came from: the npm registry (the default) or, if it was installed from a local repo, that same repo re-packed. Never switches between the two — use the CLI (`hskill update --npm` / `--local <path>`) to change source. This replaces the globally installed hskill binary and is irreversible except by manually reinstalling a specific version.',
|
|
156
156
|
inputSchema: {},
|
|
157
157
|
}, async () => {
|
|
158
158
|
const { code, stdout, stderr } = await runCli(['update'])
|
|
159
159
|
if (code === 0) {
|
|
160
|
-
return { content: [{ type: 'text', text: 'hskill updated
|
|
160
|
+
return { content: [{ type: 'text', text: stdout.trim() || 'hskill updated.' }] }
|
|
161
161
|
}
|
|
162
162
|
const message = stderr.trim() || stdout.trim() || `update failed with exit code ${code}`
|
|
163
163
|
return { content: [{ type: 'text', text: message }], isError: true }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "harveyz-skill",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.35.0",
|
|
4
4
|
"description": "Skill manager for Claude Code, Cursor, Codex, OpenClaw, Hermes, OpenCode, and Pi",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
11
|
"prepack": "node scripts/generate-npmignore.js",
|
|
12
|
-
"test": "bats tests/ && bash scripts/run-skill-tests.sh && node --test tests/mcp.test.mjs tests/harness/*.test.mjs"
|
|
12
|
+
"test": "bats tests/ && bash scripts/run-skill-tests.sh && node --test tests/mcp.test.mjs tests/templates.test.mjs tests/harness/*.test.mjs"
|
|
13
13
|
},
|
|
14
14
|
"files": [
|
|
15
15
|
"bin/",
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"skills/coding/capture-vocab/",
|
|
41
41
|
"skills/coding/rephrase/",
|
|
42
42
|
"skills/coding/explain-pm/",
|
|
43
|
+
"skills/coding/init-project/",
|
|
43
44
|
"skills/writing/forge-doc/",
|
|
44
45
|
"skills/writing/draw-diagram/",
|
|
45
46
|
"skills/writing/manage-dir/",
|
|
@@ -68,6 +69,7 @@
|
|
|
68
69
|
"skills/agent-canvas/capture-requirement/",
|
|
69
70
|
"skills/agent-canvas/relation-review/",
|
|
70
71
|
"skills/agent-canvas/close-node/",
|
|
72
|
+
"skills/coding/analyze-claudemd/",
|
|
71
73
|
"tools/hub/",
|
|
72
74
|
"tools/sync-agent/",
|
|
73
75
|
"tools/browser-fetch/",
|
|
@@ -89,5 +91,8 @@
|
|
|
89
91
|
"type": "git",
|
|
90
92
|
"url": "git+https://github.com/harveyzhang814/harveyz-skill.git"
|
|
91
93
|
},
|
|
92
|
-
"license": "MIT"
|
|
94
|
+
"license": "MIT",
|
|
95
|
+
"devDependencies": {
|
|
96
|
+
"js-yaml": "^5.4.2"
|
|
97
|
+
}
|
|
93
98
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: agent-canvas-control
|
|
3
|
-
description:
|
|
4
|
-
|
|
3
|
+
description: Control Agent Canvas node entities and layout from claude-code/codex/pi nodes — create, query, update, delete nodes, and put or hide them on the canvas; also usable from shell/hermes-tui nodes or terminals outside the canvas via `--canvas`/`resolve-canvas`/`resolve`.
|
|
4
|
+
user_invocable: true
|
|
5
|
+
version: "1.0.1"
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
# 操控节点与画布(agent-canvas-control)
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: capture-requirement
|
|
3
|
-
description:
|
|
4
|
-
|
|
3
|
+
description: File the requirement the current session is implementing as a standalone requirement node and link an implements relation to it — call once after Gate 2 is finalized; only usable inside an Agent Canvas node.
|
|
4
|
+
user_invocable: true
|
|
5
|
+
version: "1.0.1"
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
# 需求立项(capture-requirement)
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: close-node
|
|
3
|
-
description:
|
|
3
|
+
description: Wrap up the current canvas node when a round of work is done — advance requirement status, verify handoff closure, merge the branch, stop the process, and hide the node from the canvas; only usable inside an Agent Canvas node.
|
|
4
4
|
disable-model-invocation: true
|
|
5
|
-
|
|
5
|
+
user_invocable: true
|
|
6
|
+
version: "1.0.1"
|
|
6
7
|
---
|
|
7
8
|
|
|
8
9
|
# 节点收尾(close-node)
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: describe-node
|
|
3
|
-
description:
|
|
4
|
-
|
|
3
|
+
description: Auto-generate a title and description for the Agent Canvas node you are running in — use it to summarize what the session is doing, name the node, or update its title/description; only usable inside an Agent Canvas node.
|
|
4
|
+
user_invocable: true
|
|
5
|
+
version: "1.0.2"
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
# 为当前节点生成标题与描述(describe-node)
|
|
@@ -12,14 +13,18 @@ version: "1.0.0"
|
|
|
12
13
|
## 怎么调
|
|
13
14
|
|
|
14
15
|
```
|
|
15
|
-
agent-canvas-ctl summarize-self [--spec
|
|
16
|
+
agent-canvas-ctl summarize-self [--spec <规格文档绝对路径>]
|
|
16
17
|
```
|
|
17
18
|
|
|
18
19
|
**不需要传节点 id**——它按祖先进程链反查你所在的节点,"谁调用就摘要谁"。
|
|
19
20
|
|
|
20
|
-
- `--spec`
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
- `--spec` 指定据以撰写的规格文档,**必须是绝对路径**。相对路径不报错、退出码照样是
|
|
22
|
+
0,只是读不到文件,`specUsed` 静默返回 null——和"没找到"长得一模一样。它是在主进程
|
|
23
|
+
里按主进程的 cwd 解析的,不是你会话的当前目录,所以"从我这儿看是对的"不作数。
|
|
24
|
+
- 不传 `--spec` 时会从本会话记录里自动发现你写过或读过的 `docs/superpowers/specs/*.md`,
|
|
25
|
+
按 Write > Edit > Read 取最后一次;**只有 Read 命中、且读过不止一份不同的 spec 时,
|
|
26
|
+
自动发现会直接放弃**(归属不明,它不猜)。会话里读过别人的 spec 就属于这种情况。
|
|
27
|
+
`specUsed` 为 null 就表示没用上,知道该用哪份就补传 `--spec`。
|
|
23
28
|
- 成功时 stdout 返回 `{nodeId, title, description, taskType?, specUsed}`,退出码 0;
|
|
24
29
|
失败时错误写 stderr、退出码非 0。
|
|
25
30
|
- 要跑一次模型调用,通常 5–15 秒,属正常。
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: relate-node
|
|
3
|
-
description:
|
|
4
|
-
|
|
3
|
+
description: Work out the current node's semantic relations to other Agent Canvas nodes (depends-on/hands-off-to/implements/produces or references docs) — use after Gate 2 is finalized and before the closing report, when deciding whether to link an existing node; only usable inside an Agent Canvas node.
|
|
4
|
+
user_invocable: true
|
|
5
|
+
version: "1.0.2"
|
|
5
6
|
---
|
|
6
7
|
|
|
7
8
|
# 梳理节点关系(relate-node)
|
|
@@ -35,7 +36,7 @@ version: "1.0.0"
|
|
|
35
36
|
|
|
36
37
|
## 两次调用(对齐 describe-node 的两个时机,可紧挨着调)
|
|
37
38
|
|
|
38
|
-
- **第一次(闸门 2
|
|
39
|
+
- **第一次(闸门 2 通过后、开工实现前)**:核对 `phase.start` 列出的 type——
|
|
39
40
|
`implements`(需求此刻最显眼,收尾时早被压缩出上下文)、`depends-on`(已知的阻塞)、
|
|
40
41
|
`hands-off-to`(**只核对,不在这里新建**——接手方要补走 `/handoff` verify,见下方归属规则)。
|
|
41
42
|
- **第二次(收尾、汇报验收前)**:核对 `phase.finish` 列出的 type——
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: relation-review
|
|
3
|
-
description:
|
|
4
|
-
|
|
5
|
-
version: "1.0.
|
|
3
|
+
description: Global-Pilot-only relation-type governance loop — scans the pending queue and runs proposed types through four gates before promotion; invoked on a cron schedule, must not be manually called from a project canvas node.
|
|
4
|
+
user_invocable: false
|
|
5
|
+
version: "1.0.1"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Relation 类型治理循环(relation-review)
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: analyze-claudemd
|
|
3
|
+
description: "Audit a project's CLAUDE.md against 17 falsifiable criteria — ownership overlap with the skills and scripts it names, structural coherence around the main flow, and whether every instruction is actually executable by an agent. Reports blocking findings and suggestions with sources, then applies deletions only after explicit approval. Triggers: 'review CLAUDE.md', 'audit CLAUDE.md', 'slim down CLAUDE.md', 'is my CLAUDE.md bloated', 'what should I delete from CLAUDE.md', 'does CLAUDE.md duplicate my skills'."
|
|
4
|
+
user_invocable: true
|
|
5
|
+
version: "1.0.0"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# 评审 CLAUDE.md
|
|
9
|
+
|
|
10
|
+
拿 17 条可证伪的判据过一遍项目的 `CLAUDE.md`,指出哪些内容不该由它承担、哪些结构判断不出归属、哪些指令 agent 其实执行不了。
|
|
11
|
+
|
|
12
|
+
**这个 skill 的核心不是"精简",是"归属"。** 长不是问题,一条知识同时活在两个地方才是问题——改了一处,另一处就在和它对着打架。所以本 skill 绝大部分时间花在读被点名的 skill 和脚本的**源文件**上,而不是读 `CLAUDE.md` 本身。
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 触发条件
|
|
17
|
+
|
|
18
|
+
触发本 skill:
|
|
19
|
+
|
|
20
|
+
- "评审 / 优化 / 精简 CLAUDE.md"、"CLAUDE.md 该删什么"
|
|
21
|
+
- "review CLAUDE.md"、"audit CLAUDE.md"、"is my CLAUDE.md bloated"
|
|
22
|
+
- 新接手一个项目,想知道它的 `CLAUDE.md` 有没有和现有 skill 打架
|
|
23
|
+
|
|
24
|
+
不触发(其他 skill 负责):
|
|
25
|
+
|
|
26
|
+
- 评审 **skill 自身**的设计规范 → 用 `init-skill` 的 `references/skill-standard.md`
|
|
27
|
+
- 初始化分支保护与 git hooks → `init-workflow`
|
|
28
|
+
- 润色文风、改写措辞质量 → 本 skill 只判归属与结构,不做文字润色
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 判据表
|
|
33
|
+
|
|
34
|
+
17 条判据在 `references/criteria.md`(C1–C17,分五组)。Step 3 加载它逐条过,**不要凭记忆复述判据**——判据本身会演进。
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 执行步骤
|
|
39
|
+
|
|
40
|
+
### Step 0 — 定位评审对象
|
|
41
|
+
|
|
42
|
+
三级 fallback,命中即停:
|
|
43
|
+
|
|
44
|
+
1. 用户在调用时给了路径 → 用它(`~` 显式展开)
|
|
45
|
+
2. 项目根的 `CLAUDE.md` → 用它
|
|
46
|
+
3. 都没有 → 列出仓库里的候选(`CLAUDE.md` / `AGENTS.md` / `.claude/CLAUDE.md`)让用户选
|
|
47
|
+
|
|
48
|
+
用户已经指明对象时不要再问。确认不了就停下问一句,**不要默认挑一个开始读**。
|
|
49
|
+
|
|
50
|
+
### Step 1 — 执行前置检查
|
|
51
|
+
|
|
52
|
+
任一失败立即中止并报原因,不要带病往下走:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
git rev-parse --show-toplevel # 不在 git 仓库 → 中止(Step 2 要按仓库定位权威源)
|
|
56
|
+
test -f <目标文件> # 不存在 → 中止
|
|
57
|
+
git status --short # 非空 → 只做只读评审,Step 5 需用户先处理
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Step 2 — 建执行体清单
|
|
61
|
+
|
|
62
|
+
**这一步决定整次评审的成色,不能省。**
|
|
63
|
+
|
|
64
|
+
1. 从目标文件里抽出所有被点名的可执行体:skill 名、脚本路径、CLI 命令、hook、settings 开关。用 grep 抽,**不要在本 skill 里硬编码任何 skill 名单**——每个项目点名的东西都不一样。
|
|
65
|
+
2. 逐个定位它的**权威源**,按这个顺序找:项目内的源文件 → 该 skill 的源仓库 → 最后才是装机副本(`~/.claude/skills/`)。找到装机副本时必须再往上找一层:副本会落后,拿它当权威会同时造出两类误判——把"源里已修"读成"还没修",把"源里缺了"读成"重复了"。核对版本号能对上再采信。
|
|
66
|
+
3. 逐个读完再进 Step 3。**禁止边读边下结论**:一条 `CLAUDE.md` 的约束常常同时被两三个执行体覆盖,只读第一个就判"重复"会删错东西。
|
|
67
|
+
4. 读不到源的执行体(外部工具、闭源 CLI)单独列出来,它们相关的判据一律降级成 `[需核实]`,不出阻塞结论。
|
|
68
|
+
|
|
69
|
+
### Step 3 — 逐条比对判据
|
|
70
|
+
|
|
71
|
+
读 `references/criteria.md`,C1–C17 逐条过。三件事必须做到:
|
|
72
|
+
|
|
73
|
+
- **先判文档形态**:C11–C14 那组结构判据只适用于"流程主导型"文档(大部分内容围绕一条主流程展开)。不是流程主导的文档,这四条整组跳过并说明,不要硬套 Step N。
|
|
74
|
+
- **每条结论挂证据**:证据形如 `<执行体源文件>:<行号>`,写明它在那儿说了什么。
|
|
75
|
+
- **推断与读到分开**:读到的写读到的,推出来的标 `[Agent 推断]`,没查的标 `[需核实]`。
|
|
76
|
+
|
|
77
|
+
### Step 4 — 输出评审报告
|
|
78
|
+
|
|
79
|
+
按判据分组,不按发现顺序混排。分三档:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
━━━ 归属(C3–C8)━━━
|
|
83
|
+
❌ CLAUDE.md:217 simulate-user 的"非 jsdom"理由是它自己 description 的中译
|
|
84
|
+
证据:skills/.../simulate-user/SKILL.md:3
|
|
85
|
+
⚠️ CLAUDE.md:265 --spec 绝对路径要求,skill 源里确实没有(C7:该改上游)
|
|
86
|
+
证据:skills/.../describe-node/SKILL.md:16-18 无此约束
|
|
87
|
+
|
|
88
|
+
━━━ 结构(C11–C14)━━━
|
|
89
|
+
✓ 流程主导型,Step N 编章完整
|
|
90
|
+
|
|
91
|
+
阻塞 1 / 建议 1 / 通过 15
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
- **阻塞**:两处都写、改一处会打架的(C3/C4/C5),以及 agent 执行不了的指令(C2)。
|
|
95
|
+
- **建议**:结构类(C11–C14)、措辞类(C16),不改也能用。
|
|
96
|
+
- 报告末尾给下一步:确认哪几条要删。
|
|
97
|
+
|
|
98
|
+
### Step 5 — 应用确认过的修改
|
|
99
|
+
|
|
100
|
+
**默认不改任何文件。** 用户明确点头之后才进这一步:
|
|
101
|
+
|
|
102
|
+
1. 列出将删/将改的**具体条目**(文件:行号 + 删后留什么),等 y/n。
|
|
103
|
+
2. 按项目自己的分支规范落盘。不在受保护分支(`main` / `master` / `staging`)上直接改;项目有合并脚本就用脚本,没有就交回用户手动合并。
|
|
104
|
+
3. **不 push、不发布。**
|
|
105
|
+
4. C7 命中的条目(该改上游 skill 的)**这一步不动**:上游改完到下游生效之间有窗口期,窗口期内删掉,这条知识在真实环境里会有一段时间完全不存在。把它单独列出来交给用户决定先后。
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## 不在范围内
|
|
110
|
+
|
|
111
|
+
- **润色文风与措辞质量**——只判归属与结构。
|
|
112
|
+
- **修上游 skill**——C7 只负责指出"这条该由 skill 承担",改不改、什么时候改由用户定。
|
|
113
|
+
- **评审 skill 自身的设计**——那归 `init-skill` 的 `skill-standard.md`。
|
|
114
|
+
- **批量评审多个仓库**——一次一个 `CLAUDE.md`。
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# CLAUDE.md 评审判据(C1–C17)
|
|
2
|
+
|
|
3
|
+
每条给**判据**(怎样算命中)、**怎么查**(具体动作)、必要时给**代价**(遵守它要付出什么)。
|
|
4
|
+
标 `[阻塞]` 的命中后不修就会真的出错;标 `[建议]` 的是累积成本,不致命。
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 一、读者
|
|
9
|
+
|
|
10
|
+
### C1 读者是 agent,不是人 [建议]
|
|
11
|
+
|
|
12
|
+
表达形式按"agent 能不能稳定解析"取舍,不按"人看着直不直观"。ASCII 流程图、艺术字对齐、
|
|
13
|
+
需要视觉扫描才成立的排版,换成章节编号层级或表格——编号本身就是层级,不必在视觉上重建一次。
|
|
14
|
+
|
|
15
|
+
**怎么查**:文档里每处图形化表达,问"换成编号/表格会丢信息吗"。不丢就换。
|
|
16
|
+
|
|
17
|
+
**代价**:人快速扫读时不如图直观。这是有意识付出的代价,不是疏忽。
|
|
18
|
+
|
|
19
|
+
### C2 写进去的指令必须 agent 真能执行 [阻塞]
|
|
20
|
+
|
|
21
|
+
凡是"调用 X"的句子,先查 X 的可调用性。人工触发的东西只写"它归谁触发、agent 不代跑",
|
|
22
|
+
**绝不把它的步骤抄进来**——抄了就是给 agent 一条它执行不了的指令:它要么照着手跑(绕过了
|
|
23
|
+
那个机制存在的理由),要么在那里卡住。
|
|
24
|
+
|
|
25
|
+
**怎么查**:grep 文档里所有被点名的可执行体,逐个读它的声明。skill 看 frontmatter 的
|
|
26
|
+
`disable-model-invocation` / `user_invocable`;CLI 看它在不在 PATH、要不要交互式输入;
|
|
27
|
+
工具看当前 harness 给没给。
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 二、内容归属(占评审工作量的一半以上)
|
|
32
|
+
|
|
33
|
+
### C3 只写流程,不写执行体怎么执行 [阻塞]
|
|
34
|
+
|
|
35
|
+
文档只承担三样:**每一步什么时候发生、判据是什么、要落什么产物**。被调用的 skill/脚本
|
|
36
|
+
自己怎么执行、有哪些边界和坑,去读那个执行体。
|
|
37
|
+
|
|
38
|
+
**怎么查**:逐条问"这句如果删掉,是不是还有另一个地方写着同一件事"。两处都写,改了一处
|
|
39
|
+
就会对着打架——**这是删除的唯一理由,不是"太长了"**。
|
|
40
|
+
|
|
41
|
+
### C4 脚本已经自动处理的,不写 [阻塞]
|
|
42
|
+
|
|
43
|
+
默认优先靠脚本修复,不靠文档叮嘱人绕开。机制加了自动处理之后,当初的"注意……"就变成了
|
|
44
|
+
死约束,而它读起来像经验。
|
|
45
|
+
|
|
46
|
+
**怎么查**:读脚本源码确认它真的处理了,不凭记忆、不凭 README。
|
|
47
|
+
|
|
48
|
+
### C5 不越过执行体规定手法 [阻塞]
|
|
49
|
+
|
|
50
|
+
**怎么查**:句子里出现具体命令、文件路径、匹配方式,而这个动作有现成的 skill/脚本——就是
|
|
51
|
+
越界。改成"调那个 skill",把手法交回去。
|
|
52
|
+
|
|
53
|
+
典型形态:文档写"先 grep `<某个数据文件>` 查该词条(不要把整篇读进上下文)",而那个 skill
|
|
54
|
+
的 query 操作本来就规定了匹配方式和只读命中段落——文档该写的只有"优先调它查"。
|
|
55
|
+
|
|
56
|
+
### C6 对照读权威源,不读拷贝 [阻塞]
|
|
57
|
+
|
|
58
|
+
装机副本、vendored 拷贝、镜像目录都会落后于源仓库。
|
|
59
|
+
|
|
60
|
+
**怎么查**:对照前确认读的是源(skill 看它的源仓库,不是 `~/.claude/skills/`),版本号能
|
|
61
|
+
对上再开始。拿落后的副本做对照会同时造出两类误判:把"源里已修"读成"还没修",把"源里还缺"
|
|
62
|
+
读成"重复了"。
|
|
63
|
+
|
|
64
|
+
### C7 执行体自己缺了该有的约定 → 改上游 [建议]
|
|
65
|
+
|
|
66
|
+
不要在下游文档里替它补。
|
|
67
|
+
|
|
68
|
+
**代价**:上游改完到下游生效之间有窗口期。**窗口期内下游那段不能删**——删早了,这条知识
|
|
69
|
+
在真实环境里会有一段时间完全不存在,而那段时间恰好是最容易踩坑的时候。
|
|
70
|
+
|
|
71
|
+
### C8 决定保留时,要说得出"唯一载体" [建议]
|
|
72
|
+
|
|
73
|
+
保留的理由只能是"这条知识在别处没有",不能是"写着也没坏处"。
|
|
74
|
+
|
|
75
|
+
**怎么查**:对每条打算保留的,写一句"它在 X 里没有、在 Y 里也没有"。写不出来就是该删。
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 三、规定到哪里为止
|
|
80
|
+
|
|
81
|
+
### C9 只规定优先级和时机,不规定未定情况下的应对 [建议]
|
|
82
|
+
|
|
83
|
+
"优先查 X"是约束;"查不到就去做 Y"通常不是——那是当场才知道的判断,写死会把多种情况压成
|
|
84
|
+
一种(有的词本来就自明,有的该去翻代码,有的该反问用户)。
|
|
85
|
+
|
|
86
|
+
**怎么查**:找"如果……就……"的兜底分支,问分支里装的是硬约束还是判断。是判断就删。
|
|
87
|
+
|
|
88
|
+
### C10 不写已经不存在的约束 [阻塞]
|
|
89
|
+
|
|
90
|
+
机制变了、警告还留着,比没有警告更糟——它看起来像是经验,agent 会绕开一个并不存在的坑。
|
|
91
|
+
|
|
92
|
+
**怎么查**:每条"注意/警告/不要",去执行体里找它现在还成不成立。
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 四、组织结构
|
|
97
|
+
|
|
98
|
+
> C11–C14 只适用于**流程主导型**文档(大部分内容围绕一条主流程展开)。
|
|
99
|
+
> 不是这种形态的,整组跳过并说明,不要硬套。
|
|
100
|
+
|
|
101
|
+
### C11 围绕主流程组织全文 [建议]
|
|
102
|
+
|
|
103
|
+
与流程无关的内容另起章节、集中在前面。理由:大部分内容本来就是围着流程长出来的,不按主
|
|
104
|
+
流程排,约束就会散落到判断不出归属的地方。
|
|
105
|
+
|
|
106
|
+
### C12 流程简述 + `Step N` 编章 [建议]
|
|
107
|
+
|
|
108
|
+
开头一段流程简述(N 步一览),之后严格按 `Step N` 编章,一步一章。
|
|
109
|
+
|
|
110
|
+
### C13 每一步的标准和执行细则写在它自己那一章 [阻塞]
|
|
111
|
+
|
|
112
|
+
**怎么查**:随便挑一条约束,问"它属于哪一步"。答不上来,就是散的。散落的约束会被同时当成
|
|
113
|
+
"到处都要遵守"和"哪儿都不归我管"。
|
|
114
|
+
|
|
115
|
+
### C14 章内统一槽位,缺的整节省略 [建议]
|
|
116
|
+
|
|
117
|
+
每章内部用固定槽位、编号与顺序不变,说明是说明、标准是标准、执行细则是执行细则,
|
|
118
|
+
Special Case 单独成节、不混进正文。本步没有的那一节**整节省略**,不留空标题。
|
|
119
|
+
|
|
120
|
+
**代价**:有的步骤会只剩一两个槽位、显得空。但槽位缺席本身是信息——它说明这一步没有判据
|
|
121
|
+
或没有特例,比塞点东西填满诚实。
|
|
122
|
+
|
|
123
|
+
### C15 分类由内容决定,不是固定几类 [建议]
|
|
124
|
+
|
|
125
|
+
"流程 / 执行细则 / 标准"是**分离原则的例子**,不是章节清单。原则是"同类内容归一处、不同类
|
|
126
|
+
不混写",具体分几类由这份文档实际装了什么决定。
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 五、精简方式
|
|
131
|
+
|
|
132
|
+
### C16 压措辞,不外迁内容 [建议]
|
|
133
|
+
|
|
134
|
+
主文件仍是唯一入口。外迁的代价是多一跳,而且被移走的那份很容易失联——**除非**那个目标文件
|
|
135
|
+
本来就是该内容的权威载体(那属于 C3 的归属问题,不属于精简)。
|
|
136
|
+
|
|
137
|
+
### C17 规则落仓库文件,不落 agent 的私有 memory [阻塞]
|
|
138
|
+
|
|
139
|
+
memory 只有写它的那个 agent 读得到、会陈旧、接手方访问不到。一条给所有人的规则,唯一载体
|
|
140
|
+
不能是一个只有一个人能看见的文件。
|
|
141
|
+
|
|
142
|
+
**怎么查**:评审中发现的每条该留的规则,确认它落在仓库里的具体文件,而不是"我记住了"。
|