@wwkit/harness 1.0.9 → 1.0.11

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 (125) hide show
  1. package/agents/extract.md +2 -14
  2. package/agents/lint.md +368 -0
  3. package/agents/pyit.md +361 -0
  4. package/agents/pyut.md +347 -0
  5. package/agents/query.md +2 -14
  6. package/agents/revise.md +2 -14
  7. package/agents/work.md +631 -0
  8. package/commands/fix.md +77 -0
  9. package/commands/git-sync.md +218 -0
  10. package/commands/net-port.md +364 -0
  11. package/commands/pyit.md +6 -0
  12. package/commands/pyut.md +6 -0
  13. package/commands/resume.md +104 -0
  14. package/package.json +4 -2
  15. package/plugins/work-bootstrap.js +77 -0
  16. package/scripts/work-review-package +50 -0
  17. package/scripts/work-task-brief +27 -0
  18. package/scripts/work-workspace +31 -0
  19. package/skills/better-skill/SKILL.md +124 -0
  20. package/skills/blame-skill/SKILL.md +201 -0
  21. package/skills/lint-ai-fix/SKILL.md +141 -0
  22. package/skills/lint-config-setup/SKILL.md +106 -0
  23. package/skills/lint-config-setup/references/languages/js.md +110 -0
  24. package/skills/lint-config-setup/references/languages/py.md +89 -0
  25. package/skills/lint-env-ensure/SKILL.md +92 -0
  26. package/skills/lint-env-ensure/references/config.md +65 -0
  27. package/skills/lint-language-detect/SKILL.md +79 -0
  28. package/skills/lint-language-detect/references/detect-language.js +65 -0
  29. package/skills/lint-rules-analyze/SKILL.md +129 -0
  30. package/skills/lint-suitability-check/SKILL.md +84 -0
  31. package/skills/lint-tool-fix/SKILL.md +94 -0
  32. package/skills/new-skill/SKILL.md +227 -0
  33. package/skills/new-skill/references/template.md +53 -0
  34. package/skills/new-skill/references/workflow-patterns.md +104 -0
  35. package/skills/pytest-case-create/SKILL.md +327 -0
  36. package/skills/pytest-case-create/references/test-standards.md +244 -0
  37. package/skills/pytest-case-fix/SKILL.md +274 -0
  38. package/skills/pytest-coverage-analyze/SKILL.md +226 -0
  39. package/skills/pytest-coverage-analyze/references/scoring-rules.md +57 -0
  40. package/skills/pytest-env-ensure/SKILL.md +198 -0
  41. package/skills/pytest-env-ensure/references/config.md +145 -0
  42. package/skills/pytest-execute/SKILL.md +155 -0
  43. package/skills/pytest-sample/SKILL.md +164 -0
  44. package/skills/pytest-sample/references/src/pytest-sample/Calculator.py +67 -0
  45. package/skills/pytest-sample/references/src/pytest-sample/ConfigManager.py +68 -0
  46. package/skills/pytest-sample/references/src/pytest-sample/FileProcessor.py +53 -0
  47. package/skills/pytest-sample/references/src/pytest-sample/OrderService.py +82 -0
  48. package/skills/pytest-sample/references/src/pytest-sample/TokenGenerator.py +50 -0
  49. package/skills/pytest-sample/references/src/pytest-sample/UserService.py +45 -0
  50. package/skills/pytest-sample/references/src/pytest-sample/__init__.py +0 -0
  51. package/skills/pytest-suitability-check/SKILL.md +224 -0
  52. package/skills/read-docs/SKILL.md +134 -0
  53. package/skills/read-docs/references/opencode/agents/cases.md +206 -0
  54. package/skills/read-docs/references/opencode/agents/design-pattern.md +47 -0
  55. package/skills/read-docs/references/opencode/agents/detail.md +191 -0
  56. package/skills/read-docs/references/opencode/agents/examples.md +100 -0
  57. package/skills/read-docs/references/opencode/agents/index.md +309 -0
  58. package/skills/read-docs/references/opencode/agents/parallel-dispatch.md +149 -0
  59. package/skills/read-docs/references/opencode/agents/subagent-internals.md +217 -0
  60. package/skills/read-docs/references/opencode/agents/workflow.md +161 -0
  61. package/skills/read-docs/references/opencode/cli/commands/acp.md +32 -0
  62. package/skills/read-docs/references/opencode/cli/commands/agent.md +16 -0
  63. package/skills/read-docs/references/opencode/cli/commands/attach.md +20 -0
  64. package/skills/read-docs/references/opencode/cli/commands/mcp.md +37 -0
  65. package/skills/read-docs/references/opencode/cli/commands/others.md +49 -0
  66. package/skills/read-docs/references/opencode/cli/commands/plugin.md +13 -0
  67. package/skills/read-docs/references/opencode/cli/commands/provider.md +44 -0
  68. package/skills/read-docs/references/opencode/cli/commands/run.md +81 -0
  69. package/skills/read-docs/references/opencode/cli/commands/serve.md +84 -0
  70. package/skills/read-docs/references/opencode/cli/commands/session.md +38 -0
  71. package/skills/read-docs/references/opencode/cli/commands/web.md +15 -0
  72. package/skills/read-docs/references/opencode/cli/env.md +39 -0
  73. package/skills/read-docs/references/opencode/cli/index.md +19 -0
  74. package/skills/read-docs/references/opencode/cli/tui.md +35 -0
  75. package/skills/read-docs/references/opencode/commands/examples.md +42 -0
  76. package/skills/read-docs/references/opencode/commands/index.md +185 -0
  77. package/skills/read-docs/references/opencode/config/provider.md +152 -0
  78. package/skills/read-docs/references/opencode/formatter/index.md +71 -0
  79. package/skills/read-docs/references/opencode/guide/config.md +419 -0
  80. package/skills/read-docs/references/opencode/guide/formatters.md +70 -0
  81. package/skills/read-docs/references/opencode/guide/index.md +37 -0
  82. package/skills/read-docs/references/opencode/guide/providers.md +31 -0
  83. package/skills/read-docs/references/opencode/guide/rules.md +63 -0
  84. package/skills/read-docs/references/opencode/plugins/examples.md +75 -0
  85. package/skills/read-docs/references/opencode/plugins/index.md +188 -0
  86. package/skills/read-docs/references/opencode/reference/index.md +119 -0
  87. package/skills/read-docs/references/opencode/rule/index.md +78 -0
  88. package/skills/read-docs/references/opencode/skills/detail.md +113 -0
  89. package/skills/read-docs/references/opencode/skills/examples.md +141 -0
  90. package/skills/read-docs/references/opencode/skills/index.md +126 -0
  91. package/skills/read-docs/references/opencode/skills/workflow.md +146 -0
  92. package/skills/read-docs/references/opencode/tests/agent.md +10 -0
  93. package/skills/read-docs/references/opencode/tests/config.md +60 -0
  94. package/skills/read-docs/references/opencode/tests/file.md +12 -0
  95. package/skills/read-docs/references/opencode/tests/serve.md +18 -0
  96. package/skills/read-docs/references/opencode/tests/session.md +31 -0
  97. package/skills/read-docs/references/opencode/tests/web.md +17 -0
  98. package/skills/read-docs/references/opencode/tools/arguments.md +305 -0
  99. package/skills/read-docs/references/opencode/tools/context.md +18 -0
  100. package/skills/read-docs/references/opencode/tools/custom.md +111 -0
  101. package/skills/read-docs/references/opencode/tools/detail.md +104 -0
  102. package/skills/read-docs/references/opencode/tools/examples.md +71 -0
  103. package/skills/read-docs/references/opencode/tools/index.md +56 -0
  104. package/skills/read-docs/references/opencode/tools/lsp.md +26 -0
  105. package/skills/read-docs/references/opencode/tools/mcp.md +132 -0
  106. package/skills/read-docs/references/opencode/train/README.md +135 -0
  107. package/skills/read-docs/references/opencode/train/agent-basic.md +772 -0
  108. package/skills/read-docs/references/opencode/train/command-basic.md +668 -0
  109. package/skills/read-docs/references/opencode/train/config-basic.md +509 -0
  110. package/skills/read-docs/references/opencode/train/index.md +164 -0
  111. package/skills/read-docs/references/opencode/train/practice.md +873 -0
  112. package/skills/read-docs/references/opencode/train/skill-basic.md +608 -0
  113. package/skills/read-docs/references/opencode/tui/commands/config.md +32 -0
  114. package/skills/read-docs/references/opencode/tui/commands/editor.md +47 -0
  115. package/skills/read-docs/references/opencode/tui/commands/index.md +125 -0
  116. package/skills/read-docs/references/opencode/tui/commands/init.md +5 -0
  117. package/skills/read-docs/references/opencode/tui/index.md +26 -0
  118. package/skills/read-docs/references/superpowers/bootstrap.md +107 -0
  119. package/skills/read-docs/references/superpowers/comparison.md +77 -0
  120. package/skills/read-docs/references/superpowers/context.md +71 -0
  121. package/skills/read-docs/references/superpowers/index.md +58 -0
  122. package/skills/read-docs/references/superpowers/parallel.md +49 -0
  123. package/skills/read-docs/references/superpowers/sdd.md +183 -0
  124. package/skills/read-docs/references/superpowers/skills.md +68 -0
  125. package/skills/read-docs/references/superpowers/workflow.md +83 -0
@@ -0,0 +1,104 @@
1
+ ---
2
+ description: 基于导出的历史会话文件(ses_*.json/txt 等)确认任务状态并继续对话;路径支持 @workdir 简写
3
+ ---
4
+
5
+ 你是**会话续接助手**。用户因 TUI 崩溃/异常退出了历史会话,只能把会话导出成文件(JSON 或文本)并在新对话中继续。你的任务是:确认旧任务的**最终状态**(只读文件**结尾**),输出精炼简报,然后接着旧任务继续对话。
6
+
7
+ ## 铁律(违反即失败)
8
+
9
+ 1. **绝不读取会话文件全文**。导出文件可能极大(几十万~上百万行),整读会耗尽上下文甚至卡死会话。只允许**自底向上**读取:从**末尾**开始,向上扩展,**一旦识别到有效任务状态信息立即停止**,不再多读。
10
+ 2. **绝不把文件原始内容成段倒入上下文**。所有内容必须先提炼成 ≤几行的结论再输出。
11
+ 3. 文件可能不是 JSON(.txt、.log 或其他文本格式),按 Step 2 的格式判定处理,不要假定格式。
12
+ 4. **有效任务状态信息**(命中即停的信号)定义为:`status=done|partial|failed|blocked|escalate`、`## 结果摘要`、JSON 消息的 `finish` 字段(`stop`/`error`/`tool-calls` 等)、或明显的总结性结论句(含 完成/成功/失败/阻塞/错误/退出 等关键字)。
13
+
14
+ ## Step 1:解析路径参数
15
+
16
+ 输入为 `$ARGUMENTS`:**1..n 个路径**(空格分隔,可能是多个历史文件)。若为空,自动在 workdir 下找最新的 `ses_*` 文件(`ls -t ses_*` 取第一个),找不到则报告后停止。
17
+
18
+ 对每个路径按下表解析(**支持 @ 开头**——这是 opencode 对 workdir 的简写,参数可能已被 opencode 解析成绝对路径,也可能原样传入):
19
+
20
+ | 形式 | 处理 |
21
+ |------|------|
22
+ | `@foo.json`(@ 开头) | 去掉 `@`,视为相对 **workdir**(工程根目录 root_dir)→ `<root_dir>/foo.json` |
23
+ | `/abs/path` 或 `~/...` | 原样使用(先展开 `~`) |
24
+ | `rel/path`(相对) | 先相对当前 workdir 解析;不存在则相对 root_dir 再试 |
25
+
26
+ 校验存在性用 `ls -la <path>`;不存在时用 glob 找相近文件(如 `**/ses_*.json`、`**/ses_*`)并告知用户候选。**所有路径均无效** → 报告并停止。
27
+
28
+ ## Step 2:只读结尾(核心,每个文件)
29
+
30
+ **统一原则:自底向上 + 命中即停。** 从文件**末尾**开始读取,向上扩展;一旦识别到"有效任务状态信息"(见铁律 4)**立即停止**,不再向上扩展。避免固定行数导致的漏读/多读。
31
+
32
+ ### 2a. JSON 会话文件(扩展名 .json,或内容以 `{` 开头)
33
+
34
+ 用 node 解析,**自底向上收集,命中即停**(内存解析整文件没问题,关键是控制打印量):
35
+
36
+ ```bash
37
+ node -e '
38
+ const fs = require("fs");
39
+ const p = process.argv[1];
40
+ let d;
41
+ try { d = JSON.parse(fs.readFileSync(p, "utf8")); }
42
+ catch (e) { console.log("NOT_JSON"); process.exit(0); }
43
+ const i = d.info || {};
44
+ const msgs = Array.isArray(d.messages) ? d.messages : [];
45
+ const text = (m) => (m.parts || []).filter(x => x.type === "text").map(x => x.text).join("\n");
46
+ const lastTool = (m) => { const t = (m.parts || []).filter(x => x.type === "tool"); const g = t.pop(); return g ? { tool: g.tool, status: (g.state || {}).status } : null; };
47
+ const HIT = /status=(done|partial|failed|blocked|escalate)|## 结果摘要|(完成|成功|失败|阻塞|错误|退出)/;
48
+ // 从底部向上遍历,命中有效状态即停;兜底最多 3 条
49
+ const collected = [];
50
+ let hit = false, stop = false;
51
+ for (let k = msgs.length - 1; k >= 0 && collected.length < 3 && !stop; k--) {
52
+ const m = msgs[k];
53
+ const t = text(m);
54
+ const finish = (m.info || {}).finish;
55
+ collected.unshift({ role: (m.info || {}).role, finish, lastTool: lastTool(m), textTail: t.slice(-1500) });
56
+ if (finish === "stop" || finish === "error" || finish === "tool-calls" || HIT.test(t)) { hit = true; stop = true; }
57
+ }
58
+ const out = {
59
+ title: i.title || null, agent: i.agent || null,
60
+ model: (i.model || {}).id || null, fileSummary: i.summary || null,
61
+ updated: i.time && i.time.updated ? new Date(i.time.updated).toISOString() : null,
62
+ msgCount: msgs.length,
63
+ readMode: hit ? "命中有效状态,停止" : "兜底:已达最大收集数(3)",
64
+ tail: collected
65
+ };
66
+ console.log(JSON.stringify(out, null, 2));
67
+ ' "$path"
68
+ ```
69
+
70
+ > 行为:从最后一条消息**向上**逐条收集,遇到第一条 `finish=stop/error/tool-calls` 或文本含状态摘要/结论关键字的 assistant 消息即停(正常结束只读 1 条 `stop`;崩溃点即最后一条 `finish=tool-calls`,命中后停并报告"中断在执行中";最后是 user 待回复会向前多读 1 条到上次 `stop`)。兜底上限 3 条、每条文本尾部 1500 字符。**不要**用 read 工具读这个文件,**不要**打印 `msgs` 数组。
71
+
72
+ ### 2b. 其他文本文件(.txt/.log 等)
73
+
74
+ **自底向上阶梯式读取,命中即停**:
75
+
76
+ 1. 先 `wc -l <path>` 看总行数;总行数 ≤ 300 可直接整读(小文件安全)。
77
+ 2. 否则从尾部开始,按阶梯向上扩展(100 → 300 → 700 → 1500 → **上限 3000 行**):
78
+ - 第 1 步:`tail -n 100 "$path"`,检查是否命中"有效状态信息";
79
+ - 未命中:`tail -n 300`、`tail -n 700`、`tail -n 1500` 逐级扩大窗口再检查;
80
+ - **命中立即停止**,不再扩展。
81
+ 3. 命中判定同铁律 4(`status=`/`## 结果摘要`/完成/成功/失败/阻塞/错误/退出 等关键字,或末尾本身就是总结性结论句)。
82
+ 4. 到达上限 3000 行仍未命中:停止,报告"未在尾部 3000 行内找到明确状态,建议人工查看中段"。
83
+
84
+ ## Step 3:判定任务状态(对每个文件)
85
+
86
+ 依据 2a/2b 拿到的**尾部信息**判定,并给出结论:
87
+
88
+ | 观测 | 判定 |
89
+ |------|------|
90
+ | 最后一条是 assistant 且 `finish: "stop"` | 会话**正常结束**;再查其文本是否含结果摘要(`## 结果摘要` / `status=done|partial|failed|blocked|escalate`),有则直接采用 |
91
+ | 最后一条是 assistant 且 `finish: "tool-calls"` | 会话**中断在执行中**(很可能就是崩溃点):最后一步是某工具调用(见 `lastTool`),任务未完成 |
92
+ | 最后一条是 user | 上次停在**等待 agent 回复**,任务未完成 |
93
+ | 文本文件 | 从尾部提取退出/状态关键字(如 完成/成功/失败/阻塞/错误/status=…),结合最后输出的结论句判断 |
94
+ | 无任何可读内容 / 格式无法识别 | 报告 `无法解析`,跳过该文件继续处理其余文件 |
95
+
96
+ 对每个文件产出 ≤5 行的状态卡片:`文件路径 | 标题 | 消息数 | 最终状态 | 最后消息要点 | 未完成事项`。
97
+
98
+ ## Step 4:输出续聊简报并继续
99
+
100
+ 1. **简报**:先汇总所有文件的状态卡片(多文件时逐个列出,再综合)。总输出保持精炼。
101
+ 2. **续接方案**:基于状态给出下一步——
102
+ - 任务未完成且最后步骤明确 → 列出"从哪继续"的具体续接计划(参照最后工具调用/最后文本)。
103
+ - 任务已完成 → 简述结论与变更,提示如需继续新需求可直接提出。
104
+ 3. **征询后继续**:用一句话向用户确认续接方向(例如"按上述计划从 X 继续?"),**不要**未经确认就擅自执行重活(大规模改动/长流程)。用户确认后即按原任务上下文继续推进(沿用原任务的目标与验收标准)。
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "@wwkit/harness",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "author": "bluesliu <langcai163@163.com>",
5
5
  "description": "WebWork abilities for opencode",
6
6
  "type": "module",
7
7
  "main": "plugin.js",
8
8
  "files": [
9
9
  "plugin.js",
10
+ "plugins",
11
+ "scripts",
10
12
  "skills",
11
13
  "agents",
12
14
  "commands",
@@ -38,7 +40,7 @@
38
40
  "access": "public"
39
41
  },
40
42
  "dependencies": {
41
- "@opencode-ai/plugin": "1.18.27",
43
+ "@opencode-ai/plugin": "1.18.30",
42
44
  "ajv": "^8.17.0",
43
45
  "cheerio": "^1.0.0",
44
46
  "json5": "^2.2.3"
@@ -0,0 +1,77 @@
1
+ import { randomUUID } from 'crypto'
2
+
3
+ const BOOTSTRAP_MARKER = '__wwkit_work_bootstrap__'
4
+
5
+ const BOOTSTRAP_TEXT = `[${BOOTSTRAP_MARKER}]
6
+
7
+ 你是 work(任务调度指挥官)。以下强约束优先级高于你的其他指令,必须遵守:
8
+
9
+ ## Red Flags(禁止行为)
10
+
11
+ 1. **禁止亲自逐行实现**:你的职责是拆解→派发→汇总,不是写代码。除非是单步 trivial 任务(≤1 文件、≤5 行),否则必须派发 subagent。
12
+ 2. **禁止先动手后规划**:多步骤任务必须先 todowrite 落单,再派发。
13
+ 3. **禁止上下文倾倒**:subagent prompt 必须自包含精炼上下文,不要把整个对话历史贴进去。
14
+ 4. **禁止串行派发**:独立任务必须在一条消息里并行发出多个 task 调用(≤5)。
15
+ 5. **禁止无限重试**:单个 worker failed/blocked 只记录不中断;全部失败才重规划;重规划 ≤3 轮。
16
+
17
+ ## 强制优先级
18
+
19
+ - 能 single 绝不 parallel(先路由判断)。
20
+ - 但如果任务涉及 ≥2 个独立子问题或 ≥3 个文件,必须 parallel。
21
+ - subagent 类型:只读调研用 explore,可写改动用 general。
22
+ - 每轮派发前必须确认 writable 白名单不重叠(文件所有权分区)。`
23
+
24
+ export const WorkBootstrapPlugin = async () => {
25
+ return {
26
+ 'experimental.chat.messages.transform': async (input, output) => {
27
+ const messages = output.messages
28
+ if (!Array.isArray(messages) || messages.length === 0) return
29
+
30
+ const users = messages.filter((m) => m?.info?.role === 'user')
31
+ const lastUser = users[users.length - 1]
32
+ if (!lastUser) return
33
+
34
+ const agent = lastUser.info?.agent
35
+ if (agent !== 'work') return
36
+
37
+ const alreadyInjected = messages.some((m) => {
38
+ const parts = m?.parts
39
+ if (!Array.isArray(parts)) return false
40
+ return parts.some(
41
+ (p) => p?.type === 'text' && typeof p.text === 'string' && p.text.includes(BOOTSTRAP_MARKER)
42
+ )
43
+ })
44
+ if (alreadyInjected) return
45
+
46
+ const sessionId = lastUser.info?.sessionID || lastUser.info?.id || ''
47
+ const messageId = lastUser.info?.id || ''
48
+
49
+ const bootstrapPart = {
50
+ id: `prt_${randomUUID()}`,
51
+ sessionID: sessionId,
52
+ messageID: messageId,
53
+ type: 'text',
54
+ text: BOOTSTRAP_TEXT,
55
+ synthetic: true,
56
+ time: { start: Date.now() }
57
+ }
58
+
59
+ messages.unshift({
60
+ info: {
61
+ id: `msg_${randomUUID()}`,
62
+ sessionID: sessionId,
63
+ role: 'assistant',
64
+ time: { created: Date.now() },
65
+ parentID: '',
66
+ modelID: '',
67
+ providerID: '',
68
+ mode: 'primary',
69
+ path: { cwd: '', root: '' },
70
+ cost: 0,
71
+ tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } }
72
+ },
73
+ parts: [bootstrapPart]
74
+ })
75
+ }
76
+ }
77
+ }
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env bash
2
+ # Generate a review package: commit list, stat summary, and the net
3
+ # diff with extended context, written to a file the reviewer reads in one
4
+ # call. Using the recorded per-task BASE (not HEAD~1) keeps multi-commit
5
+ # tasks intact.
6
+ #
7
+ # Usage: work-review-package WORKSPACE_DIR TASK_NUMBER BASE HEAD [SUFFIX]
8
+ # Writes to: <WORKSPACE_DIR>/task-<N>-review-<base7>..<head7>.diff
9
+ # If SUFFIX is "final", writes to: <WORKSPACE_DIR>/final-review-<base7>..<head7>.diff
10
+ set -euo pipefail
11
+
12
+ if [ $# -lt 4 ] || [ $# -gt 5 ]; then
13
+ echo "usage: work-review-package WORKSPACE_DIR TASK_NUMBER BASE HEAD [SUFFIX]" >&2
14
+ exit 2
15
+ fi
16
+
17
+ ws="$1"
18
+ n="$2"
19
+ base="$3"
20
+ head="$4"
21
+ suffix="${5:-}"
22
+ [ -d "$ws" ] || { echo "no such workspace directory: $ws" >&2; exit 2; }
23
+
24
+ git rev-parse --verify --quiet "$base" >/dev/null || { echo "bad BASE: $base" >&2; exit 2; }
25
+ git rev-parse --verify --quiet "$head" >/dev/null || { echo "bad HEAD: $head" >&2; exit 2; }
26
+
27
+ base7=$(git rev-parse --short "$base")
28
+ head7=$(git rev-parse --short "$head")
29
+
30
+ if [ "$suffix" = "final" ]; then
31
+ out="$ws/final-review-${base7}..${head7}.diff"
32
+ else
33
+ out="$ws/task-${n}-review-${base7}..${head7}.diff"
34
+ fi
35
+
36
+ {
37
+ echo "# Review package: ${base}..${head}"
38
+ echo
39
+ echo "## Commits"
40
+ git log --oneline "${base}..${head}"
41
+ echo
42
+ echo "## Files changed"
43
+ git diff --stat "${base}..${head}"
44
+ echo
45
+ echo "## Diff"
46
+ git diff -U10 "${base}..${head}"
47
+ } > "$out"
48
+
49
+ commits=$(git rev-list --count "${base}..${head}")
50
+ echo "wrote ${out}: ${commits} commit(s), $(wc -c < "$out" | tr -d ' ') bytes"
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env bash
2
+ # Write a task brief file from stdin, so the implementer reads its task
3
+ # text in one call instead of receiving it through the controller's context.
4
+ #
5
+ # Usage: work-task-brief WORKSPACE_DIR TASK_NUMBER
6
+ # Reads task text from stdin, writes to <WORKSPACE_DIR>/task-<N>-brief.md
7
+ set -euo pipefail
8
+
9
+ if [ $# -ne 2 ]; then
10
+ echo "usage: work-task-brief WORKSPACE_DIR TASK_NUMBER" >&2
11
+ echo " Reads task text from stdin." >&2
12
+ exit 2
13
+ fi
14
+
15
+ ws="$1"
16
+ n="$2"
17
+ [ -d "$ws" ] || { echo "no such workspace directory: $ws" >&2; exit 2; }
18
+
19
+ out="$ws/task-${n}-brief.md"
20
+ cat > "$out"
21
+
22
+ if [ ! -s "$out" ]; then
23
+ echo "task brief is empty (stdin had no content)" >&2
24
+ exit 3
25
+ fi
26
+
27
+ echo "wrote ${out}: $(wc -l < "$out" | tr -d ' ') lines"
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env bash
2
+ # Resolve and ensure the working-tree directory for one work session's
3
+ # short-lived artifacts: plan, task briefs, implementer reports, review
4
+ # packages, and the progress ledger.
5
+ #
6
+ # Directory: <root_dir>/webwork/harness/work/<session-id>/
7
+ # One directory per session so concurrent sessions never collide.
8
+ #
9
+ # Usage: work-workspace ROOT_DIR [SESSION_ID]
10
+ # Prints the session directory's absolute path.
11
+ set -euo pipefail
12
+
13
+ if [ $# -lt 1 ] || [ $# -gt 2 ]; then
14
+ echo "usage: work-workspace ROOT_DIR [SESSION_ID]" >&2
15
+ exit 2
16
+ fi
17
+
18
+ root="$1"
19
+ [ -d "$root" ] || { echo "no such directory: $root" >&2; exit 2; }
20
+
21
+ if [ $# -eq 2 ]; then
22
+ sid="$2"
23
+ else
24
+ sid="$(date +%s)"
25
+ fi
26
+
27
+ base="$root/webwork/harness/work"
28
+ dir="$base/$sid"
29
+ mkdir -p "$dir"
30
+ printf '*\n' > "$base/.gitignore"
31
+ cd "$dir" && pwd
@@ -0,0 +1,124 @@
1
+ ---
2
+ name: better-skill
3
+ description: |
4
+ 基于 blame-skill 审计评分,自动迭代优化 Skill 定义文件直到达到优秀等级。
5
+ 提供:迭代优化流程、自动改进策略、评分达标验证。
6
+ 适用:新建 Skill 后自动优化、已有 Skill 质量提升、批量 Skill 质量治理。
7
+ 不适用:非 SKILL.md 文件优化、Agent 定义优化、无需评分的简单修改。
8
+ license: MIT
9
+ ---
10
+
11
+ # Skill 自动优化器
12
+
13
+ ## 工作流模式
14
+
15
+ 本 Skill 采用 **迭代优化** 工作流:
16
+
17
+ 1. **评估**:调用 blame-skill 对目标 Skill 进行审计评分
18
+ 2. **判断**:检查分数是否 >= 90(A 级)或已达最大迭代次数
19
+ 3. **改进**:根据审计报告的改进建议,修改目标 SKILL.md
20
+ 4. **重评**:再次调用 blame-skill 重新评估
21
+ 5. **循环**:重复步骤 2-4 直到达标或累计迭代 5 次
22
+
23
+ ## 输入要求
24
+
25
+ 用户必须提供要优化的 **skill 名称**(如 `git-feat`、`clean-code`)。
26
+
27
+ ## 迭代流程
28
+
29
+ ### 第 1 步:初始评估
30
+
31
+ 调用 blame-skill 对目标 Skill 进行审计评分,使用 `--format=json` 结构化模式获取结果:
32
+
33
+ - 读取 blame-skill 的评分规则
34
+ - 按路径顺序查找目标 SKILL.md
35
+ - 逐项评分并生成结构化审计报告
36
+
37
+ ### 第 2 步:达标判断
38
+
39
+ 从审计结果中提取 `total_score`:
40
+
41
+ | 条件 | 动作 |
42
+ |------|------|
43
+ | `total_score >= 90` | 输出最终报告,流程结束 |
44
+ | `total_score < 90` 且迭代次数 < 5 | 进入第 3 步改进 |
45
+ | `total_score < 90` 且迭代次数 >= 5 | 输出最终报告(含未达标说明),流程结束 |
46
+
47
+ ### 第 3 步:改进 Skill
48
+
49
+ 根据审计报告中的 `issues` 和 `improvement_priority`,对目标 SKILL.md 进行修改:
50
+
51
+ 1. 按 `improvement_priority` 顺序逐项处理
52
+ 2. 对每个 issue,将 `suggestion` 转化为具体的文件修改操作
53
+ 3. 修改时遵循以下原则:
54
+ - **Frontmatter**:补充/修正 name、description 字段,确保 description 在 50-300 字符且包含具体能力、适用场景、不适用场景、提供资源
55
+ - **工作流声明**:在正文开头添加明确的工作流模式声明
56
+ - **失败处理**:补充失败处理机制(回滚、重试、降级、人工介入)
57
+ - **正文结构**:使用标题、列表、表格等结构化格式,补充代码示例和边界说明
58
+ - **渐进式加载**:当内容超过 200 行时,将详细数据拆分到 references/ 目录
59
+ - **Name 规范**:如 name 不符合 `^[a-z0-9]+(-[a-z0-9]+)*$` 格式,提示用户确认是否重命名
60
+
61
+ ### 第 4 步:重新评估
62
+
63
+ 修改完成后,再次调用 blame-skill 进行审计评分,回到第 2 步。
64
+
65
+ ## 迭代控制
66
+
67
+ | 参数 | 值 | 说明 |
68
+ |------|-----|------|
69
+ | 目标分数 | 90 | A 级(优秀) |
70
+ | 最大迭代次数 | 5 | 防止无限循环 |
71
+ | 迭代计数起点 | 1 | 首次评估计为第 1 次 |
72
+
73
+ ## 输出格式
74
+
75
+ 迭代结束后,输出最终报告:
76
+
77
+ ```
78
+ ## Skill 优化报告:[skill-name]
79
+
80
+ ### 最终得分:XX / 100(等级:X)
81
+ ### 迭代次数:X / 5
82
+
83
+ ### 各轮得分变化
84
+
85
+ | 轮次 | 得分 | 等级 | 主要改进项 |
86
+ |------|------|------|-----------|
87
+ | 1 | XX | X | 初始评估 |
88
+ | 2 | XX | X | [改进项1], [改进项2] |
89
+ | ... | ... | ... | ... |
90
+
91
+ ### 改进摘要
92
+
93
+ - [改进项1]:[修改前] → [修改后]
94
+ - [改进项2]:[修改前] → [修改后]
95
+
96
+ ### 未解决项(如有)
97
+
98
+ - [ ] **[项目名]**:[原因说明]
99
+ ```
100
+
101
+ ## 一定要做
102
+
103
+ 1. 每次迭代前必须调用 blame-skill 获取最新评分
104
+ 2. 按改进优先级从高到低处理 issue
105
+ 3. 修改 SKILL.md 后立即重新评估
106
+ 4. 记录每轮迭代的得分变化
107
+ 5. 迭代结束时输出完整的优化报告
108
+
109
+ ## 一定不要做
110
+
111
+ 1. 不要跳过 blame-skill 评估直接修改
112
+ 2. 不要在一次迭代中修改后不重新评估就继续修改
113
+ 3. 不要修改 blame-skill 的评分规则
114
+ 4. 不要在未达到 90 分时提前终止(除非已达 5 次上限)
115
+ 5. 不要修改目标 Skill 的核心功能语义(只优化结构,不改意图)
116
+
117
+ ## 失败处理
118
+
119
+ | 场景 | 处理方式 |
120
+ |------|---------|
121
+ | 目标 Skill 不存在 | 提示用户检查名称,终止流程 |
122
+ | blame-skill 评估失败 | 终止流程,输出已完成的迭代结果 |
123
+ | 5 次迭代仍未达标 | 输出当前最高分和未解决项,建议人工介入 |
124
+ | 修改导致分数下降 | 回滚本次修改,跳过该项,继续下一优先级 |
@@ -0,0 +1,201 @@
1
+ ---
2
+ name: blame-skill
3
+ description: |
4
+ 审计和评分 OpenCode Skill 定义文件(SKILL.md),基于工作流模式和最佳实践规则进行量化评估。
5
+ 提供:评分规则(满分100分)、工作流匹配分析、改进建议生成。
6
+ 适用:审查已有 Skill 质量、改进 Skill 定义、新建 Skill 前参考评分标准。
7
+ 不适用:审查 Agent 定义、审查 Command 定义、通用代码审查。
8
+ ---
9
+
10
+ # Skill 审计评分器
11
+
12
+ ## 工作流模式
13
+
14
+ 本 Skill 采用 **迭代优化** 工作流:
15
+ 1. **读取**:加载目标 SKILL.md 及 references/ 目录
16
+ 2. **评分**:按评分规则逐项打分
17
+ 3. **诊断**:列出未满足项及改进建议
18
+ 4. **输出**:生成结构化审计报告
19
+
20
+ ## 评分规则(满分 100 分)
21
+
22
+ ### 一、工作流匹配(20 分)
23
+
24
+ Skill 是否符合某种明确的工作流模式,是评分的第一标准。
25
+
26
+ | 项目 | 分值 | 评分标准 |
27
+ |------|------|---------|
28
+ | 工作流识别 | 8 分 | 能明确识别属于以下模式之一:顺序工作流、多 MCP 协调、迭代优化、上下文感知、领域智能。无法识别得 0 分 |
29
+ | 工作流完整性 | 5 分 | 工作流步骤完整,有清晰的阶段划分或步骤编号。步骤模糊或不完整扣 3-5 分 |
30
+ | 指令可执行 | 3 分 | 每个步骤的指令具体、可操作,非泛泛而谈。模糊指令扣 2-3 分 |
31
+ | 失败处理 | 4 分 | 包含失败处理机制(回滚、重试、降级、人工介入)。无任何失败处理扣 4 分 |
32
+
33
+ ### 二、Description 质量(20 分)
34
+
35
+ Description 是唯一决定 Skill 是否被触发的因素。
36
+
37
+ | 项目 | 分值 | 评分标准 |
38
+ |------|------|---------|
39
+ | 具体能力 | 5 分 | 一句话说明核心能力,模糊不得分 |
40
+ | 适用场景 | 5 分 | 明确列出触发场景,缺失扣 5 分 |
41
+ | 不适用场景 | 5 分 | 明确列出边界限制,缺失扣 5 分 |
42
+ | 提供资源 | 5 分 | 说明 Skill 包含的资源(表结构、公式、模板等),缺失扣 5 分 |
43
+
44
+ ### 三、Name 规范(10 分)
45
+
46
+ | 项目 | 分值 | 评分标准 |
47
+ |------|------|---------|
48
+ | 命名规范 | 5 分 | 符合 `^[a-z0-9]+(-[a-z0-9]+)*$` 格式。不符合得 0 分 |
49
+ | 语义清晰 | 5 分 | 名称反映核心功能,无法从名称推断用途扣 3-5 分 |
50
+
51
+ ### 四、正文质量(25 分)
52
+
53
+ | 项目 | 分值 | 评分标准 |
54
+ |------|------|---------|
55
+ | Markdown 结构 | 5 分 | 使用标题、列表、表格等结构化格式。纯文本无结构扣 5 分 |
56
+ | 具体示例 | 5 分 | 包含代码块或使用示例。无示例扣 5 分 |
57
+ | 边界说明 | 5 分 | 明确说明不能做什么或限制条件。缺失扣 5 分 |
58
+ | 输入输出规范 | 5 分 | 明确定义 Skill 的输入要求和输出格式。若 Skill 无需输入输出(如纯执行类),自动得 5 分;需要但缺失扣 5 分,定义不完整扣 2-3 分 |
59
+ | 渐进式加载 | 5 分 | 主文件精简,详细数据放 references/。主文件过长(>200 行)且无 references 扣 5 分 |
60
+
61
+ ### 五、Frontmatter 规范(15 分)
62
+
63
+ | 项目 | 分值 | 评分标准 |
64
+ |------|------|---------|
65
+ | name 字段 | 3 分 | 存在且与目录名一致。缺失或不一致扣 3 分 |
66
+ | description 字段 | 5 分 | 存在且 1-1024 字符。缺失扣 5 分 |
67
+ | description 长度 | 4 分 | 描述充分但不冗长(建议 50-300 字符)。过短(<30 字符)扣 2 分,过长(>500 字符)扣 2 分 |
68
+ | 可选字段 | 3 分 | 合理使用 license / compatibility / metadata 等可选字段。无可选字段不扣分,有则检查合理性 |
69
+
70
+ ### 六、目录结构(10 分)
71
+
72
+ | 项目 | 分值 | 评分标准 |
73
+ |------|------|---------|
74
+ | SKILL.md 存在 | 5 分 | 文件名必须为 SKILL.md(大写)。不存在得 0 分 |
75
+ | references/ 使用 | 5 分 | 当内容较多时使用 references/ 目录存放详细文档。内容多但未拆分扣 5 分,内容少不需要则不扣分 |
76
+
77
+ ## 评分等级
78
+
79
+ | 分数 | 等级 | 说明 |
80
+ |------|------|------|
81
+ | 90-100 | A 优秀 | 完全符合最佳实践 |
82
+ | 75-89 | B 良好 | 基本符合,有少量改进空间 |
83
+ | 60-74 | C 合格 | 可用但需要改进 |
84
+ | 40-59 | D 不足 | 存在明显问题 |
85
+ | <40 | E 较差 | 需要重写 |
86
+
87
+ ## 输入要求
88
+
89
+ 用户必须提供要审计的 **skill 名称**(如 `git-feat`、`clean-code`)。
90
+
91
+ ## Skill 加载路径
92
+
93
+ 按以下顺序查找目标 Skill 的 SKILL.md 文件,找到即停止:
94
+
95
+ 1. **项目级**:`.opencode/skills/<name>/SKILL.md`(从当前目录向上遍历至 git worktree)
96
+ 2. **OPENCODE_CONFIG_DIR**:`$OPENCODE_CONFIG_DIR/skills/<name>/SKILL.md`
97
+ 3. **全局**:`~/.config/opencode/skills/<name>/SKILL.md`
98
+
99
+ 如果目录下存在 `references/` 子目录,也一并读取用于评估渐进式加载。
100
+
101
+ ## 审计流程
102
+
103
+ ### 步骤 1:定位并读取目标 Skill
104
+
105
+ 根据用户提供的 skill 名称,按上述路径顺序查找 SKILL.md。未找到则提示用户检查名称或路径。
106
+
107
+ ### 步骤 2:逐项评分
108
+
109
+ 按上述六大类评分规则,逐项评估并记录得分和扣分原因。
110
+
111
+ ### 步骤 3:生成审计报告
112
+
113
+ 按以下格式输出:
114
+
115
+ ```
116
+ ## Skill 审计报告:[skill-name]
117
+
118
+ ### 总分:XX / 100(等级:X)
119
+
120
+ ### 分项得分
121
+
122
+ | 类别 | 得分 | 满分 |
123
+ |------|------|------|
124
+ | 工作流匹配 | XX | 20 |
125
+ | Description 质量 | XX | 20 |
126
+ | Name 规范 | XX | 10 |
127
+ | 正文质量 | XX | 25 |
128
+ | Frontmatter 规范 | XX | 15 |
129
+ | 目录结构 | XX | 10 |
130
+
131
+ ### 未满足项及改进建议
132
+
133
+ - [ ] **[项目名]** (扣 X 分)
134
+ - 现状:[当前情况]
135
+ - 建议:[具体改进方案]
136
+
137
+ ### 改进优先级
138
+
139
+ 1. [最应优先改进的项]
140
+ 2. [次优先改进的项]
141
+ 3. ...
142
+ ```
143
+
144
+ ### 步骤 4:输出格式
145
+
146
+ 支持两种输出模式,根据调用方式自动选择:
147
+
148
+ #### 模式 A:人类阅读模式(默认)
149
+
150
+ 用户直接调用 blame-skill 时使用,输出完整的 Markdown 审计报告。
151
+
152
+ #### 模式 B:结构化模式(程序化调用)
153
+
154
+ 当调用参数包含 `--format=json` 或由其他 Skill 程序化调用时,输出 JSON 结构化结果,便于自动化解析:
155
+
156
+ ```json
157
+ {
158
+ "skill_name": "git-clear",
159
+ "total_score": 76,
160
+ "grade": "B",
161
+ "scores": {
162
+ "workflow_match": 14,
163
+ "description_quality": 9,
164
+ "name_convention": 9,
165
+ "content_quality": 21,
166
+ "frontmatter": 13,
167
+ "directory_structure": 10
168
+ },
169
+ "score_details": {
170
+ "workflow_match": {
171
+ "workflow_identification": 8,
172
+ "workflow_completeness": 5,
173
+ "instruction_executable": 3,
174
+ "failure_handling": 0
175
+ },
176
+ "content_quality": {
177
+ "markdown_structure": 5,
178
+ "concrete_examples": 5,
179
+ "boundary_description": 5,
180
+ "input_output_spec": 0,
181
+ "progressive_loading": 5
182
+ }
183
+ },
184
+ "issues": [
185
+ {
186
+ "item": "工作流识别",
187
+ "deduction": 2,
188
+ "current": "工作流隐含在步骤中,未显式声明工作流模式",
189
+ "suggestion": "在正文开头明确声明工作流模式(如'本 Skill 采用顺序工作流')"
190
+ }
191
+ ],
192
+ "improvement_priority": [
193
+ "Description 补充不适用场景和提供资源",
194
+ "Description 长度扩展"
195
+ ]
196
+ }
197
+ ```
198
+
199
+ ### 步骤 5:如果用户需要,提供改进后的 SKILL.md
200
+
201
+ 根据审计结果,重写一份符合最佳实践的 SKILL.md 供用户参考。