@heihei0299/matt-skills 2.0.2 → 2.1.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/.agents/skills/ci-guard/SKILL.md +6 -2
- package/.agents/skills/commit-check/scripts/scan-sensitive.sh +14 -6
- package/.agents/skills/diagnose-fix/SKILL.md +16 -15
- package/.agents/skills/diagnose-fix/references/anti-patterns.md +5 -4
- package/.agents/skills/grill-to-spec/SKILL.md +4 -0
- package/.agents/skills/grill-to-spec/references/rules.md +19 -24
- package/.agents/skills/scaffold-functional-test/SKILL.md +9 -6
- package/.agents/skills/scaffold-functional-test/references/schema.md +56 -11
- package/.agents/skills/tdd-implement/SKILL.md +14 -9
- package/.agents/skills/tdd-implement/references/contract.md +21 -0
- package/.agents/skills/tdd-implement/references/deliver.md +33 -0
- package/.agents/skills/tdd-implement/references/orchestration.md +9 -6
- package/.agents/skills/tdd-implement/references/red-green.md +25 -0
- package/.agents/skills/tdd-implement/references/stages.md +11 -9
- package/.agents/skills/tdd-implement/references/verify.md +24 -0
- package/.agents/skills/tdd-implement/scripts/scan-sensitive.sh +37 -0
- package/README.md +48 -27
- package/bin/cli.js +85 -24
- package/bin/skill-boundaries.js +61 -0
- package/config/proprietary.json +28 -9
- package/package.json +1 -1
- package/scripts/sync-upstream.js +4 -8
- package/template/.agents/skills/diagnose-fix/SKILL.md +16 -15
- package/template/.agents/skills/diagnose-fix/references/anti-patterns.md +5 -4
- package/template/.agents/skills/grill-to-spec/SKILL.md +4 -0
- package/template/.agents/skills/grill-to-spec/references/rules.md +19 -24
- package/template/.agents/skills/scaffold-functional-test/SKILL.md +9 -6
- package/template/.agents/skills/scaffold-functional-test/references/schema.md +56 -11
- package/template/.agents/skills/tdd-implement/SKILL.md +14 -9
- package/template/.agents/skills/tdd-implement/references/contract.md +21 -0
- package/template/.agents/skills/tdd-implement/references/deliver.md +33 -0
- package/template/.agents/skills/tdd-implement/references/orchestration.md +9 -6
- package/template/.agents/skills/tdd-implement/references/red-green.md +25 -0
- package/template/.agents/skills/tdd-implement/references/stages.md +11 -9
- package/template/.agents/skills/tdd-implement/references/verify.md +24 -0
- package/template/.agents/skills/tdd-implement/scripts/scan-sensitive.sh +37 -0
- package/template/.opencode/CONTEXT.md +7 -7
- package/template/.opencode/docs/agents/skill-design.md +3 -3
- package/template/.opencode/skills/README.md +1 -1
- package/template/.pi/CONTEXT.md +7 -7
- package/template/.pi/docs/agents/skill-design.md +3 -3
- package/template/.pi/skills/README.md +1 -1
- package/template/AGENTS.md +49 -30
- package/template/.agents/skills/ci-guard/SKILL.md +0 -50
- package/template/.agents/skills/ci-guard/agents/openai.yaml +0 -5
- package/template/.agents/skills/commit-check/SKILL.md +0 -95
- package/template/.agents/skills/commit-check/agents/openai.yaml +0 -5
- package/template/.agents/skills/commit-check/scripts/scan-sensitive.sh +0 -29
- package/template/.opencode/commands/commit-check.md +0 -9
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Deterministic staged-diff secret scan for the tdd-implement deliver gate.
|
|
3
|
+
# Only ADDED lines are inspected: removing a leaked secret must never be blocked.
|
|
4
|
+
# Match contents are never echoed, so detected credentials do not leak into agent/log output.
|
|
5
|
+
# FAIL: structured assignments and private-key blocks.
|
|
6
|
+
# WARN: bare keywords that may legitimately appear in documentation.
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
if [[ $# -gt 1 || ( $# -eq 1 && "$1" != "--staged-only" ) ]]; then
|
|
10
|
+
echo "usage: $0 [--staged-only]" >&2
|
|
11
|
+
exit 2
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
fail_patterns='(api[_-]?key|secret|token|passwd|password)[[:space:]]*[=:][[:space:]]*[^[:space:]]{8,}|BEGIN (RSA|OPENSSH|EC|DSA) PRIVATE KEY'
|
|
15
|
+
warn_patterns='(api[_-]?key|secret|token|passwd|password|\.env)'
|
|
16
|
+
|
|
17
|
+
# Strip diff metadata and deletions. The scanner cares only about content that the
|
|
18
|
+
# commit would introduce, not secrets that the commit is removing.
|
|
19
|
+
added_lines=$(
|
|
20
|
+
git diff --cached --unified=0 --no-color \
|
|
21
|
+
| awk '/^\+\+\+ / { next } /^\+/ { print substr($0, 2) }'
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
fail=0
|
|
25
|
+
|
|
26
|
+
if grep -qiE "$fail_patterns" <<< "$added_lines"; then
|
|
27
|
+
echo "❌ Possible structured secret found in ADDED staged content — remove or redact it before committing." >&2
|
|
28
|
+
fail=1
|
|
29
|
+
else
|
|
30
|
+
echo "✅ No structured secrets in added staged content."
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
if grep -qiE "$warn_patterns" <<< "$added_lines"; then
|
|
34
|
+
echo "⚠ Sensitive keyword found in ADDED staged content — inspect the staged diff manually." >&2
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
exit "$fail"
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# matt-skills
|
|
2
2
|
|
|
3
|
-
mattpocock/skills(`skills/engineering` + `skills/productivity
|
|
3
|
+
mattpocock/skills(`skills/engineering` + `skills/productivity`)的配置仓库:工作区维护完整 skill 集合,其中一部分 proprietary skill 只供本仓库使用;`template/` 只包含可分发内容,以 npm 包 `@heihei0299/matt-skills` 分发,目标仓库一条命令即完成初始化。
|
|
4
4
|
|
|
5
5
|
## 模板结构
|
|
6
6
|
|
|
@@ -8,7 +8,7 @@ mattpocock/skills(`skills/engineering` + `skills/productivity`)的配置仓
|
|
|
8
8
|
template/
|
|
9
9
|
├── AGENTS.md 项目级全局配置(行为路由 + 分文件指针)
|
|
10
10
|
├── .agents/
|
|
11
|
-
│ └── skills/
|
|
11
|
+
│ └── skills/ workspace 的完整 skill 单一源;template 只携带可分发 skill,默认安装 programming 范围,--all 展开全部可分发 skill
|
|
12
12
|
├── .pi/ pi-agent 项目配置
|
|
13
13
|
│ ├── skills/ 空占位(项目自定义技能,含 .gitkeep + README.md)
|
|
14
14
|
│ ├── prompts/ issue-audit 命令(prompt template)
|
|
@@ -17,39 +17,60 @@ template/
|
|
|
17
17
|
└── .opencode/ opencode 项目配置
|
|
18
18
|
├── skills/ 空占位(项目自定义技能,含 .gitkeep + README.md)
|
|
19
19
|
├── agents/ issue-audit 子代理定义
|
|
20
|
-
|
|
20
|
+
├── commands/ issue-audit + 可分发的显式触发技能命令(grill-to-spec/wayfinder/to-spec/to-tickets/triage/improve-codebase-architecture/teach/handoff/writing-for-agents)
|
|
21
21
|
├── docs/agents/ 5 个分文件(运行时纪律 / 技能设计 / issue tracker / triage labels / domain)
|
|
22
22
|
├── CONTEXT.md 术语表
|
|
23
23
|
├── package.json 插件依赖清单
|
|
24
24
|
└── .gitignore
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
## 独有 skill 分发边界
|
|
28
|
+
|
|
29
|
+
本仓库维护 7 个独有(proprietary)skill:
|
|
30
|
+
|
|
31
|
+
### 可分发的 5 个
|
|
32
|
+
|
|
33
|
+
- `tdd-implement`
|
|
34
|
+
- `diagnose-fix`
|
|
35
|
+
- `grill-to-spec`
|
|
36
|
+
- `scaffold-functional-test`
|
|
37
|
+
- `show-me`
|
|
38
|
+
|
|
39
|
+
默认 programming 范围中的 4 个独有 skill 是 `tdd-implement`、`diagnose-fix`、`grill-to-spec`、`show-me`;`scaffold-functional-test` 可分发但默认可选。
|
|
40
|
+
|
|
41
|
+
### 仓库内部的 2 个
|
|
42
|
+
|
|
43
|
+
- `ci-guard`
|
|
44
|
+
- `commit-check`
|
|
45
|
+
|
|
46
|
+
`ci-guard` 和 `commit-check` 只服务 matt-skills 仓库自身,不会通过 `list`、`install`、`init`、`sync`、`--all` 或 global install 分发到用户项目。workspace 保留完整集合,template 只包含可分发集合。
|
|
47
|
+
|
|
27
48
|
## 初始化
|
|
28
49
|
|
|
29
50
|
在目标仓库根目录执行一条命令:
|
|
30
51
|
|
|
31
52
|
```sh
|
|
32
|
-
npx @heihei0299/matt-skills init #
|
|
33
|
-
npx @heihei0299/matt-skills init --all #
|
|
53
|
+
npx @heihei0299/matt-skills init # 默认 programming 范围
|
|
54
|
+
npx @heihei0299/matt-skills init --all # 安装全部可分发 skill(含 productivity)
|
|
34
55
|
```
|
|
35
56
|
|
|
36
|
-
`init` 默认只在目标没有 `AGENTS.md` 时初始化;已有项目默认跳过以保护定制,显式 `init --all`
|
|
57
|
+
`init` 默认只在目标没有 `AGENTS.md` 时初始化;已有项目默认跳过以保护定制,显式 `init --all` 会刷新模板并安装/覆盖全部可分发 skill。模板已经包含可分发内容,无需二次拉取上游;repo-local skill 不会进入目标项目。
|
|
37
58
|
|
|
38
|
-
选项:`--dest <path>` 指定目标目录(默认当前目录);`--all`
|
|
59
|
+
选项:`--dest <path>` 指定目标目录(默认当前目录);`--all` 包含全部可分发的非默认 skill(包括 productivity 和 optional proprietary);已有目标使用 `init --all` 刷新,普通 `init` 跳过。
|
|
39
60
|
**增量同步(已有项目)**:已有项目更新到最新模板与技能:
|
|
40
61
|
|
|
41
62
|
```sh
|
|
42
|
-
npx @heihei0299/matt-skills sync #
|
|
43
|
-
npx @heihei0299/matt-skills sync --all #
|
|
44
|
-
npx @heihei0299/matt-skills sync --dry-run --json # 预演:只比对不写盘(默认范围,--all
|
|
63
|
+
npx @heihei0299/matt-skills sync # 默认安全增量:同步默认 programming skill(不删多余)
|
|
64
|
+
npx @heihei0299/matt-skills sync --all # 同步全部可分发 skill(不删多余)
|
|
65
|
+
npx @heihei0299/matt-skills sync --dry-run --json # 预演:只比对不写盘(默认范围,--all 可透传)
|
|
45
66
|
npx @heihei0299/matt-skills sync --dest <path> --upstream <url> --ref <ref> --json # 选项可组合
|
|
46
67
|
```
|
|
47
68
|
|
|
48
|
-
`sync`
|
|
49
|
-
|
|
50
|
-
**pi-agent 用户**:初始化命令完全相同。pi 从 `.agents/skills/`
|
|
69
|
+
`sync` 专为已有项目设计,两档语义:写盘模式下默认同步默认 programming 范围,`--all` 同步全部可分发 skill;`--dry-run` 仅对比上游、不写盘,默认比较 engineering + required 的上游部分,`--all` 比较全量上游范围,打印“上游 HEAD / 本地非独有 vs 上游 / 新增/更新/删除/一致”表,`--json` 可解析,有差异 `exit 1`。上游 dry-run/check 不比较 proprietary,因为它们不属于上游;默认安全增量写盘不删多余,模板配置增量更新,旧镜像中的共享 skill 自动清理但保留项目自定义。repo-local skill 永远不新增、不覆盖、不删除,发现历史副本时只提示保留。`--dest`、`--upstream`、`--ref`、`--json`、`--all`、`--dry-run` 可透传。
|
|
70
|
+
目标仓库会话即自动加载可分发共享技能(`.agents/skills/` 单一源)与项目级全局配置(行为路由表、分文件约定);项目自定义技能可按需放入 `.pi/skills/` 或 `.opencode/skills/`(按 harness 自动发现);`issue-audit` 以子代理 + 命令形式分发(`.opencode/agents/`、`.opencode/commands/`);可分发的显式触发技能注册为 opencode 命令(`.opencode/commands/`,`/命令名` 触发)。
|
|
71
|
+
**pi-agent 用户**:初始化命令完全相同。pi 从 `.agents/skills/` 自动发现全部可分发共享技能,无需额外指向;`.pi/skills/` 仅用于项目自定义。首次在目标仓库交互启动时 pi 会询问项目信任,用 `/trust` 保存即可。
|
|
51
72
|
|
|
52
|
-
**手动方式(备选)**:无 npx 环境时,将 `template/`
|
|
73
|
+
**手动方式(备选)**:无 npx 环境时,将 `template/` 整个文件夹复制到目标仓库根目录即可(已含全部可分发 skill):
|
|
53
74
|
|
|
54
75
|
```sh
|
|
55
76
|
cp -r template/. /path/to/target/
|
|
@@ -67,9 +88,9 @@ git clone --depth 1 https://github.com/mattpocock/skills.git /tmp/mattpocock-ski
|
|
|
67
88
|
|
|
68
89
|
| 工作区 | 模板 |
|
|
69
90
|
|--------|------|
|
|
70
|
-
| `.agents/skills
|
|
91
|
+
| `.agents/skills/`(workspace 完整 skill 集合:upstream + proprietary) | `template/.agents/skills/`(仅可分发 skill) |
|
|
71
92
|
| `.agents/skills/` 的 harness 占位说明 | `template/.pi/skills/.gitkeep` + `README.md`、`template/.opencode/skills/.gitkeep` + `README.md`(空目录占位,供项目自定义) |
|
|
72
|
-
│ │ ├── commands/ issue-audit +
|
|
93
|
+
│ │ ├── commands/ issue-audit + 可分发的显式触发技能命令(grill-to-spec/wayfinder/to-spec/to-tickets/triage/improve-codebase-architecture/teach/handoff/writing-for-agents)
|
|
73
94
|
| `.pi/prompts/issue-audit.md`(pi 命令:opencode 版适配,去 subagent frontmatter) | `template/.pi/prompts/issue-audit.md` |
|
|
74
95
|
| `AGENTS.md` | `template/AGENTS.md`(引用映射为 `.opencode/` 路径) |
|
|
75
96
|
| `CONTEXT.md` | `template/.opencode/CONTEXT.md` + `template/.pi/CONTEXT.md` |
|
|
@@ -78,7 +99,7 @@ git clone --depth 1 https://github.com/mattpocock/skills.git /tmp/mattpocock-ski
|
|
|
78
99
|
共享技能统一在 `.agents/skills` 单一源,不再双份镜像到 `.opencode/skills` / `.pi/skills`。
|
|
79
100
|
`test/template-sync.test.js` 守护同步(含路径映射),漏同步测试即红。
|
|
80
101
|
|
|
81
|
-
新增技能前先查上游 `mattpocock/skills`
|
|
102
|
+
新增技能前先查上游 `mattpocock/skills` 是否已存在;仅上游没有的技能才作为 proprietary skill 落在本仓库。Proprietary skill 再分为 distributable 和 repo-local:后者只服务本仓库,不进入 template 或任何用户安装路径。上游技能通过 `scripts/sync-upstream.js` 同步到 `.agents/skills` 后,只有可分发内容会进入模板。
|
|
82
103
|
|
|
83
104
|
## harness 支持
|
|
84
105
|
|
|
@@ -119,13 +140,13 @@ CODEX_E2E=1 npm run codex:smoke # 显式运行真实 smoke test
|
|
|
119
140
|
|
|
120
141
|
- **全局**:`~/.pi/agent/skills/`、`~/.agents/skills/`(用户级技能,自动发现);配置在 `~/.pi/agent/settings.json`
|
|
121
142
|
- **项目**:
|
|
122
|
-
- `.agents/skills/` —
|
|
143
|
+
- `.agents/skills/` — 可分发共享技能单一源(默认 programming,`--all` 全部可分发,自动发现)
|
|
123
144
|
- `.pi/skills/` — 项目自定义技能(pi 标准结构,自动发现,仅放项目本地技能)
|
|
124
145
|
- `.pi/prompts/` — pi 命令(prompt template)自动发现,如 `issue-audit.md` → `/issue-audit`
|
|
125
146
|
- `.pi/settings.json` — 已简化为空对象(历史指向 `.opencode/skills` 已移除,共享技能走 `.agents/skills`)
|
|
126
147
|
### opencode
|
|
127
148
|
|
|
128
|
-
- **项目**:`.agents/skills
|
|
149
|
+
- **项目**:`.agents/skills/`(可分发共享技能单一源,默认 programming,`--all` 全部可分发)、`.opencode/skills/`(项目自定义技能)、`.opencode/agents/`(子代理)、`.opencode/commands/`(命令:issue-audit + 可分发显式触发技能,`/命令名` 触发)、`.opencode/docs/`(文档)
|
|
129
150
|
|
|
130
151
|
同一份技能(Agent Skills 标准)与 `AGENTS.md` 行为路由在两种 harness 下均可加载:pi 与 codex/claude 从 `.agents/skills/` 自动发现;opencode 按本模板约定同样优先读取 `.agents/skills/`(`.opencode/skills/` 仅用于项目自定义)。
|
|
131
152
|
|
|
@@ -134,23 +155,23 @@ CODEX_E2E=1 npm run codex:smoke # 显式运行真实 smoke test
|
|
|
134
155
|
仓库内提供安装管理 CLI(`bin/cli.js`,依赖 `prompts`,见 `package.json`),同时作为 npm 包 `@heihei0299/matt-skills` 分发(`npx @heihei0299/matt-skills <command>`):
|
|
135
156
|
|
|
136
157
|
```sh
|
|
137
|
-
node bin/cli.js init [--dest <dir>] [--all] #
|
|
158
|
+
node bin/cli.js init [--dest <dir>] [--all] # 初始化项目:默认 programming 或全部可分发 skill
|
|
138
159
|
node bin/cli.js sync [--all] [--dry-run] [--dest <path>] [--upstream <url>] [--ref <ref>] [--json] # 同步已有项目到最新(默认编程,--all 仅同名 upsert + AGENTS.md)
|
|
139
160
|
node bin/cli.js list [--json] [--all] # 列出技能(默认编程)
|
|
140
161
|
node bin/cli.js install [选项] # 把技能复制到目标工具目录(交互式选择,默认编程)
|
|
141
162
|
node bin/cli.js check [--json] [--all] [--upstream <url>] [--ref <ref>] # 只读检查上游技能是否最新(等价 sync --dry-run,默认范围)
|
|
142
163
|
```
|
|
143
164
|
|
|
144
|
-
`init` 选项:`--dest <path>` 指定目标目录(默认当前目录);`--all`
|
|
145
|
-
`sync`
|
|
146
|
-
`check` 选项:`--json`、`--all
|
|
165
|
+
`init` 选项:`--dest <path>` 指定目标目录(默认当前目录);`--all` 包含全部可分发 skill,见「初始化」。
|
|
166
|
+
`sync` 选项:写盘时 `--all` 更新全部可分发同名技能内容(存在则覆盖,不存在则新增)并更新 `AGENTS.md`(不跳过定制),不删多余;默认写盘只同步默认 programming;`--dry-run` 只比对上游、不写盘(默认 engineering + required 上游范围,`--all` 为全量上游范围,`--json` 可解析,有差异 `exit 1`);`--dest <path>` 目标目录;`--upstream <url>` 上游地址;`--ref <ref>` 上游分支;`--json` JSON 输出;默认安全增量会保留目标定制。
|
|
167
|
+
`check` 选项:`--json`、`--all`(默认只比较 engineering + required 上游范围;proprietary 不参与上游 compare)、`--upstream <url>`、`--ref <ref>`(等价 `sync --dry-run`)。
|
|
147
168
|
|
|
148
169
|
`install` 选项:
|
|
149
170
|
|
|
150
171
|
- `--dest <dir>`:复制到指定目录(覆盖工具映射)
|
|
151
172
|
- `--tools <t1,t2>`:指定工具,项目级已统一 `codex/pi/opencode/claude → .agents/skills`(共享技能单一源,`.pi/skills`/`.opencode/skills` 仅用于项目自定义)
|
|
152
173
|
- `--global`:安装到全局目录(`~/.codex/skills`、`~/.pi/agent/skills`、`~/.config/opencode/skills`、`~/.claude/skills`);`--project` 回到项目级
|
|
153
|
-
- `--all
|
|
174
|
+
- `--all`:安装全部可分发 skill(交互勾选时默认只列 programming 范围);`--force`:覆盖已存在的技能
|
|
154
175
|
|
|
155
176
|
|
|
156
177
|
### 上游同步(自动更新)
|
|
@@ -160,14 +181,14 @@ node bin/cli.js check [--json] [--all] [--upstream <url>] [--ref <ref>]
|
|
|
160
181
|
- **本地 CLI**:`matt-skills sync` 两档——`--dry-run` 只读比对(有差异 `exit 1`,`--json` 可解析)、默认安全增量与 `sync --all` 仅同名 upsert + `AGENTS.md`;`matt-skills check [--json] [--upstream <url>] [--ref <ref>]` 为只读别名(等价 `sync --dry-run`);`matt-skills update` 已合并到 `sync`(执行提示 `update 已合并到 sync` 且 `exit 1`)
|
|
161
182
|
```sh
|
|
162
183
|
npx @heihei0299/matt-skills sync --dry-run --json # 预演只读检查,JSON 输出:{ head, counts, result: { added, updated, renamed, removed, same } }
|
|
163
|
-
npx @heihei0299/matt-skills sync # 默认安全增量(AGENTS.md
|
|
184
|
+
npx @heihei0299/matt-skills sync # 默认安全增量(AGENTS.md 定制跳过,默认 programming)
|
|
164
185
|
npx @heihei0299/matt-skills sync --all # 仅同名 upsert + AGENTS.md
|
|
165
186
|
npx @heihei0299/matt-skills check --json # 等价 sync --dry-run
|
|
166
187
|
node scripts/sync-upstream.js --check # 等价底层脚本(CLI sync/check 的实现)
|
|
167
188
|
node scripts/sync-upstream.js --apply --dry-run
|
|
168
189
|
```
|
|
169
190
|
|
|
170
|
-
实现细节:`scripts/sync-upstream.js` 为单一事实源(CLI 与 Actions 共用),以
|
|
191
|
+
实现细节:`scripts/sync-upstream.js` 为单一事实源(CLI 与 Actions 共用),以 proprietary 分类契约排除本仓库独有 skill,以 `config/engineering.json` 为编程白名单,以 `config/required.json` 为独有所需白名单;上游通过 `git clone --depth 1 https://github.com/mattpocock/skills.git` 获取,比对 `SKILL.md` 的 sha256,自动处理新增/更新/重命名/删除。上游同步只维护 workspace,模板生成时再按 distributable 边界投影。
|
|
171
192
|
上游重命名映射:`RENAMES = { "writing-great-skills": "writing-for-agents" }`,Actions/CLI 均会删除旧目录并复制新目录。
|
|
172
193
|
## 发布
|
|
173
194
|
|
|
@@ -200,7 +221,7 @@ npm publish
|
|
|
200
221
|
|
|
201
222
|
```sh
|
|
202
223
|
npm test # 全量测试
|
|
203
|
-
npm run build:template #
|
|
224
|
+
npm run build:template # 从 workspace 生成仅含可分发 skill 的 template + 空占位
|
|
204
225
|
```
|
|
205
226
|
|
|
206
227
|
交互模式依赖 `prompts`(见 `package.json`);测试见 `test/cli.test.js`、`test/cli-init.test.js`、`test/template-sync.test.js`。
|
package/bin/cli.js
CHANGED
|
@@ -4,11 +4,17 @@ import os from 'node:os';
|
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
6
|
import prompts from 'prompts';
|
|
7
|
+
import {
|
|
8
|
+
PROPRIETARY_SKILLS,
|
|
9
|
+
isDefaultProgrammingSkill,
|
|
10
|
+
isDistributableProprietarySkill,
|
|
11
|
+
isDistributableSkill,
|
|
12
|
+
isRepoLocalSkill,
|
|
13
|
+
REPO_LOCAL_SKILLS,
|
|
14
|
+
} from './skill-boundaries.js';
|
|
7
15
|
|
|
8
16
|
const SKILLS_DIR = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', '.agents', 'skills');
|
|
9
17
|
const TEMPLATE_DIR = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'template');
|
|
10
|
-
const PROPRIETARY_SKILLS = new Set(['ci-guard', 'tdd-implement', 'grill-to-spec', 'diagnose-fix', 'commit-check', 'scaffold-functional-test', 'show-me']);
|
|
11
|
-
const PROPRIETARY_DEFAULT = new Set(['tdd-implement', 'diagnose-fix', 'commit-check', 'grill-to-spec', 'show-me']); // 默认仅装核心 4 + show-me,--all 才装全部 7
|
|
12
18
|
const ENGINEERING_PATH = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'config', 'engineering.json');
|
|
13
19
|
const REQUIRED_PATH = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'config', 'required.json');
|
|
14
20
|
let ENGINEERING_SKILLS = null;
|
|
@@ -34,10 +40,10 @@ async function loadRequiredSkills() {
|
|
|
34
40
|
return REQUIRED_SKILLS;
|
|
35
41
|
}
|
|
36
42
|
function isProgrammingSkill(name, engineering, required) {
|
|
37
|
-
return
|
|
43
|
+
return isDefaultProgrammingSkill(name, engineering, required);
|
|
38
44
|
}
|
|
39
45
|
function isProgrammingAll(name, engineering) {
|
|
40
|
-
return
|
|
46
|
+
return isDistributableProprietarySkill(name) || engineering.has(name);
|
|
41
47
|
}
|
|
42
48
|
process.stdout.on('error', (err) => {
|
|
43
49
|
if (err.code === 'EPIPE') process.exit(0);
|
|
@@ -64,9 +70,9 @@ Usage:
|
|
|
64
70
|
|
|
65
71
|
Init options:
|
|
66
72
|
--dest <path> Target directory (default: current directory)
|
|
67
|
-
--all Include
|
|
73
|
+
--all Include all distributable skills; default only default programming skills
|
|
68
74
|
--help, -h Show this help
|
|
69
|
-
提示:已有 AGENTS.md 时普通 init 跳过;显式 init --all
|
|
75
|
+
提示:已有 AGENTS.md 时普通 init 跳过;显式 init --all 刷新模板并覆盖全量可分发 skills。
|
|
70
76
|
|
|
71
77
|
提示:matt-skills --help 查看全量
|
|
72
78
|
`;
|
|
@@ -82,7 +88,7 @@ Sync options:
|
|
|
82
88
|
--dest <path> Target directory (default: current directory)
|
|
83
89
|
--help, -h Show this help
|
|
84
90
|
|
|
85
|
-
说明:默认不带 --all
|
|
91
|
+
说明:默认不带 --all 仅增量同步默认 programming skill 且 AGENTS.md 有定制则跳过;--all 时同步全部可分发 skill 并强制更新 AGENTS.md。
|
|
86
92
|
|
|
87
93
|
提示:matt-skills --help 查看全量
|
|
88
94
|
`;
|
|
@@ -93,7 +99,7 @@ Usage:
|
|
|
93
99
|
matt-skills list [--all] [--json]
|
|
94
100
|
|
|
95
101
|
List options:
|
|
96
|
-
--all List all skills (default only
|
|
102
|
+
--all List all distributable skills (default only default programming skills)
|
|
97
103
|
--json Output as JSON
|
|
98
104
|
--help, -h Show this help
|
|
99
105
|
|
|
@@ -106,7 +112,7 @@ Usage:
|
|
|
106
112
|
matt-skills check [--all] [--json] [--upstream <url>] [--ref <ref>]
|
|
107
113
|
|
|
108
114
|
Check options:
|
|
109
|
-
--all Include
|
|
115
|
+
--all Include the full upstream comparison scope; default engineering + required upstream skills (proprietary excluded)
|
|
110
116
|
--json Output as JSON
|
|
111
117
|
--upstream <url> Upstream repo URL (default: https://github.com/mattpocock/skills.git)
|
|
112
118
|
--ref <ref> Upstream ref (default: HEAD)
|
|
@@ -122,7 +128,7 @@ Usage:
|
|
|
122
128
|
|
|
123
129
|
Install options:
|
|
124
130
|
--tools <a,b> Install for the given tools (codex, pi, opencode, claude); skips tool selection — 共享技能统一指向 .agents/skills,.pi/skills/.opencode/skills 仅用于项目自定义
|
|
125
|
-
--all Install all skills (default only
|
|
131
|
+
--all Install all distributable skills (default only default programming); skips skill selection
|
|
126
132
|
--force Overwrite existing skills
|
|
127
133
|
--global Install to the user's global skill directories
|
|
128
134
|
--project Install to project skill directories (default)
|
|
@@ -161,6 +167,7 @@ async function listSkills({ onlyProgramming = false } = {}) {
|
|
|
161
167
|
if (!entry.isDirectory()) continue;
|
|
162
168
|
if (entry.name.endsWith('.bak')) continue;
|
|
163
169
|
if (entry.name === 'skill-creator') continue;
|
|
170
|
+
if (isRepoLocalSkill(entry.name)) continue;
|
|
164
171
|
if (onlyProgramming && !isProgrammingSkill(entry.name, engineering, required)) continue;
|
|
165
172
|
let content;
|
|
166
173
|
try {
|
|
@@ -182,6 +189,13 @@ async function pathExists(p) {
|
|
|
182
189
|
return false;
|
|
183
190
|
}
|
|
184
191
|
}
|
|
192
|
+
|
|
193
|
+
function shouldCopyTemplatePath(src) {
|
|
194
|
+
const relative = path.relative(TEMPLATE_DIR, src);
|
|
195
|
+
const parts = relative.split(path.sep);
|
|
196
|
+
return !(parts[0] === '.agents' && parts[1] === 'skills' && isRepoLocalSkill(parts[2]));
|
|
197
|
+
}
|
|
198
|
+
|
|
185
199
|
const TOOLS = ['codex', 'pi', 'opencode', 'claude'];
|
|
186
200
|
|
|
187
201
|
// 统一源:共享技能全部在 .agents/skills,harness 的 .pi/skills/.opencode/skills 仅用于项目自定义
|
|
@@ -262,6 +276,12 @@ async function installCommand({ dest, all, force, tools, global }) {
|
|
|
262
276
|
process.stdout.write('未选择任何技能,未安装任何技能\n');
|
|
263
277
|
return;
|
|
264
278
|
}
|
|
279
|
+
const knownDistributable = new Set(skills.map((skill) => skill.name));
|
|
280
|
+
for (const name of selected) {
|
|
281
|
+
if (!isDistributableSkill(name, knownDistributable)) {
|
|
282
|
+
throw new Error(`${name} is repository-local or unavailable and cannot be distributed`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
265
285
|
for (const { tool, dir } of targets) {
|
|
266
286
|
let installed = 0;
|
|
267
287
|
let skipped = 0;
|
|
@@ -287,7 +307,11 @@ async function initCommand({ dest, all }) {
|
|
|
287
307
|
if (await pathExists(marker) && !all) {
|
|
288
308
|
process.stdout.write('模板已存在(AGENTS.md),跳过\n');
|
|
289
309
|
} else {
|
|
290
|
-
await cp(TEMPLATE_DIR, target, {
|
|
310
|
+
await cp(TEMPLATE_DIR, target, {
|
|
311
|
+
recursive: true,
|
|
312
|
+
force: true,
|
|
313
|
+
filter: shouldCopyTemplatePath,
|
|
314
|
+
});
|
|
291
315
|
process.stdout.write('模板:已复制(AGENTS.md、.agents/skills、.opencode/、.pi/)\n');
|
|
292
316
|
// 默认范围(engineering + 独有所需 + 默认独有),--all 才保留其余 productivity
|
|
293
317
|
if (onlyProgramming && path.resolve(target) !== path.resolve(path.join(path.dirname(fileURLToPath(import.meta.url)), '..'))) {
|
|
@@ -311,7 +335,7 @@ async function initCommand({ dest, all }) {
|
|
|
311
335
|
let installed = 0;
|
|
312
336
|
try {
|
|
313
337
|
const entries = await readdir(skillsDir, { withFileTypes: true });
|
|
314
|
-
installed = entries.filter((e) => e.isDirectory() && !e.name.endsWith('.bak') && e.name !== '.git' && e.name !== 'skill-creator').length;
|
|
338
|
+
installed = entries.filter((e) => e.isDirectory() && !e.name.endsWith('.bak') && e.name !== '.git' && e.name !== 'skill-creator' && !isRepoLocalSkill(e.name)).length;
|
|
315
339
|
} catch {}
|
|
316
340
|
const allSkillsFull = await listSkills({ onlyProgramming: false });
|
|
317
341
|
const engineeringForStats = await loadEngineeringSkills();
|
|
@@ -322,12 +346,12 @@ async function initCommand({ dest, all }) {
|
|
|
322
346
|
const displayTotal = onlyProgramming ? programmingCount : allSkillsFull.length;
|
|
323
347
|
const displayUpstream = onlyProgramming ? upstreamProg : upstreamFull;
|
|
324
348
|
if (path.resolve(skillsDir) === path.resolve(SKILLS_DIR)) {
|
|
325
|
-
process.stdout.write(`技能:已装 ${installed}、跳过 0
|
|
349
|
+
process.stdout.write(`技能:已装 ${installed}、跳过 0(可分发 ${allSkillsFull.length},含上游 ${upstreamFull};默认编程 ${programmingCount},含上游 ${upstreamProg})\n`);
|
|
326
350
|
} else {
|
|
327
351
|
if (onlyProgramming) {
|
|
328
|
-
process.stdout.write(`技能:已装 ${installed}
|
|
352
|
+
process.stdout.write(`技能:已装 ${installed}(默认编程 ${displayTotal},含上游 ${displayUpstream};可分发 ${allSkillsFull.length},含上游 ${upstreamFull})\n`);
|
|
329
353
|
} else {
|
|
330
|
-
process.stdout.write(`技能:已装 ${installed}
|
|
354
|
+
process.stdout.write(`技能:已装 ${installed}(可分发 ${displayTotal},含上游 ${displayUpstream})\n`);
|
|
331
355
|
}
|
|
332
356
|
}
|
|
333
357
|
process.stdout.write(`目标路径:${target}\n`);
|
|
@@ -340,7 +364,7 @@ async function syncCommand({ dest, all, dryRun, json, upstreamUrl, ref }) {
|
|
|
340
364
|
if (json) {
|
|
341
365
|
process.stdout.write(JSON.stringify({ head: cmp.head, counts: cmp.counts, result: cmp.result, onlyProgramming }, null, 2) + '\n');
|
|
342
366
|
} else {
|
|
343
|
-
const modeHint = onlyProgramming ? '(默认:engineering + 独有所需)' : '
|
|
367
|
+
const modeHint = onlyProgramming ? '(默认:engineering + 独有所需)' : '(全量上游)';
|
|
344
368
|
const lines = [];
|
|
345
369
|
lines.push(`上游 HEAD: ${cmp.head}`);
|
|
346
370
|
lines.push(`本地非独有: ${cmp.counts.local} 上游: ${cmp.counts.upstream} ${modeHint}`);
|
|
@@ -368,7 +392,11 @@ async function syncCommand({ dest, all, dryRun, json, upstreamUrl, ref }) {
|
|
|
368
392
|
// 模板同步:默认模式下过滤 skills,仅同步默认子集
|
|
369
393
|
async function copyTemplateFiltered() {
|
|
370
394
|
if (!onlyProgramming) {
|
|
371
|
-
await cp(TEMPLATE_DIR, target, {
|
|
395
|
+
await cp(TEMPLATE_DIR, target, {
|
|
396
|
+
recursive: true,
|
|
397
|
+
force: true,
|
|
398
|
+
filter: shouldCopyTemplatePath,
|
|
399
|
+
});
|
|
372
400
|
return;
|
|
373
401
|
}
|
|
374
402
|
// 默认范围:分别复制非 skills 部分,skills 由后续 allSkills 循环处理
|
|
@@ -391,7 +419,11 @@ async function syncCommand({ dest, all, dryRun, json, upstreamUrl, ref }) {
|
|
|
391
419
|
if (!(await pathExists(marker))) {
|
|
392
420
|
process.stdout.write('未检测到现有项目(AGENTS.md 不存在),将执行全新初始化\n');
|
|
393
421
|
if (onlyProgramming) await copyTemplateFiltered();
|
|
394
|
-
else await cp(TEMPLATE_DIR, target, {
|
|
422
|
+
else await cp(TEMPLATE_DIR, target, {
|
|
423
|
+
recursive: true,
|
|
424
|
+
force: true,
|
|
425
|
+
filter: shouldCopyTemplatePath,
|
|
426
|
+
});
|
|
395
427
|
process.stdout.write('模板:已复制(AGENTS.md、.agents/skills、.opencode/、.pi/)\n');
|
|
396
428
|
} else {
|
|
397
429
|
process.stdout.write('同步:检测到现有项目,将增量更新\n');
|
|
@@ -416,21 +448,30 @@ async function syncCommand({ dest, all, dryRun, json, upstreamUrl, ref }) {
|
|
|
416
448
|
}
|
|
417
449
|
} catch {}
|
|
418
450
|
} else {
|
|
419
|
-
await cp(path.join(TEMPLATE_DIR, '.agents'), path.join(target, '.agents'), {
|
|
451
|
+
await cp(path.join(TEMPLATE_DIR, '.agents'), path.join(target, '.agents'), {
|
|
452
|
+
recursive: true,
|
|
453
|
+
force: true,
|
|
454
|
+
filter: shouldCopyTemplatePath,
|
|
455
|
+
});
|
|
420
456
|
await cp(path.join(TEMPLATE_DIR, '.opencode'), path.join(target, '.opencode'), { recursive: true, force: true });
|
|
421
457
|
await cp(path.join(TEMPLATE_DIR, '.pi'), path.join(target, '.pi'), { recursive: true, force: true });
|
|
422
458
|
}
|
|
423
459
|
process.stdout.write('模板:已同步(AGENTS.md 跳过,已含定制)\n');
|
|
424
460
|
} else {
|
|
425
461
|
if (onlyProgramming) await copyTemplateFiltered();
|
|
426
|
-
else await cp(TEMPLATE_DIR, target, {
|
|
462
|
+
else await cp(TEMPLATE_DIR, target, {
|
|
463
|
+
recursive: true,
|
|
464
|
+
force: true,
|
|
465
|
+
filter: shouldCopyTemplatePath,
|
|
466
|
+
});
|
|
427
467
|
process.stdout.write('模板:已同步(AGENTS.md、.agents/skills、.opencode/、.pi/)\n');
|
|
428
468
|
}
|
|
429
469
|
}
|
|
430
|
-
// 技能同步:--all
|
|
470
|
+
// 技能同步:--all 仅更新同名可分发技能内容,存在则覆盖,不存在则新增,并更新 AGENTS.md(由上一步已处理);默认范围为默认 programming,不删多余
|
|
431
471
|
const entries = await readdir(SKILLS_DIR, { withFileTypes: true });
|
|
432
472
|
const allNames = entries.filter((e) => e.isDirectory() && !e.name.endsWith('.bak') && e.name !== 'skill-creator' && e.name !== '.git').map((e) => e.name);
|
|
433
473
|
let allSkills = allNames.sort();
|
|
474
|
+
allSkills = allSkills.filter((name) => !isRepoLocalSkill(name));
|
|
434
475
|
if (onlyProgramming) {
|
|
435
476
|
const engineering = await loadEngineeringSkills();
|
|
436
477
|
const required = await loadRequiredSkills();
|
|
@@ -438,6 +479,23 @@ async function syncCommand({ dest, all, dryRun, json, upstreamUrl, ref }) {
|
|
|
438
479
|
}
|
|
439
480
|
const skillsDir = path.join(target, '.agents', 'skills');
|
|
440
481
|
await mkdir(skillsDir, { recursive: true });
|
|
482
|
+
const preservedRepoLocal = [];
|
|
483
|
+
const preserveLocations = [
|
|
484
|
+
{
|
|
485
|
+
dir: skillsDir,
|
|
486
|
+
label: '.agents/skills',
|
|
487
|
+
isWorkspaceSource: path.resolve(skillsDir) === path.resolve(SKILLS_DIR),
|
|
488
|
+
},
|
|
489
|
+
{ dir: path.join(target, '.pi', 'skills'), label: '.pi/skills', isWorkspaceSource: false },
|
|
490
|
+
{ dir: path.join(target, '.opencode', 'skills'), label: '.opencode/skills', isWorkspaceSource: false },
|
|
491
|
+
];
|
|
492
|
+
for (const name of REPO_LOCAL_SKILLS) {
|
|
493
|
+
for (const location of preserveLocations) {
|
|
494
|
+
if (!location.isWorkspaceSource && await pathExists(path.join(location.dir, name))) {
|
|
495
|
+
preservedRepoLocal.push(`${location.label}/${name}`);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
441
499
|
let installed = 0;
|
|
442
500
|
let updated = 0;
|
|
443
501
|
for (const name of allSkills) {
|
|
@@ -468,7 +526,7 @@ async function syncCommand({ dest, all, dryRun, json, upstreamUrl, ref }) {
|
|
|
468
526
|
if (!e.isDirectory()) continue;
|
|
469
527
|
if (e.name === '.git' || e.name.endsWith('.bak')) continue;
|
|
470
528
|
if (e.name === '.gitkeep' || e.name === 'README.md') continue;
|
|
471
|
-
if (allSkills.includes(e.name)
|
|
529
|
+
if (allSkills.includes(e.name)) {
|
|
472
530
|
await rm(path.join(dir, e.name), { recursive: true, force: true });
|
|
473
531
|
}
|
|
474
532
|
}
|
|
@@ -484,7 +542,10 @@ async function syncCommand({ dest, all, dryRun, json, upstreamUrl, ref }) {
|
|
|
484
542
|
}
|
|
485
543
|
}
|
|
486
544
|
} catch {}
|
|
487
|
-
|
|
545
|
+
if (preservedRepoLocal.length) {
|
|
546
|
+
process.stdout.write(`迁移提示:${preservedRepoLocal.join(', ')} 已不再分发,现有副本已保留\n`);
|
|
547
|
+
}
|
|
548
|
+
const modeLabel = onlyProgramming ? '默认编程' : '全部可分发';
|
|
488
549
|
process.stdout.write(`技能:新增 ${installed}、更新 ${updated}(${modeLabel} ${allSkills.length})\n`);
|
|
489
550
|
process.stdout.write(`目标路径:${target}\n`);
|
|
490
551
|
}
|
|
@@ -584,7 +645,7 @@ async function checkCommand(args) {
|
|
|
584
645
|
} else {
|
|
585
646
|
const lines = [];
|
|
586
647
|
lines.push(`上游 HEAD: ${cmp.head}`);
|
|
587
|
-
const modeHint = onlyProgramming ? '(默认:engineering + 独有所需)' : '
|
|
648
|
+
const modeHint = onlyProgramming ? '(默认:engineering + 独有所需)' : '(全量上游)';
|
|
588
649
|
lines.push(`本地非独有: ${cmp.counts.local} 上游: ${cmp.counts.upstream} ${modeHint}`);
|
|
589
650
|
lines.push('');
|
|
590
651
|
const totalDiff = cmp.result.added.length + cmp.result.updated.length + cmp.result.removed.length + cmp.result.renamed.length;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
|
|
5
|
+
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
6
|
+
const CONFIG_PATH = path.join(ROOT, 'config', 'proprietary.json');
|
|
7
|
+
const config = JSON.parse(readFileSync(CONFIG_PATH, 'utf8'));
|
|
8
|
+
|
|
9
|
+
function toUniqueSet(value, key) {
|
|
10
|
+
if (!Array.isArray(value) || new Set(value).size !== value.length) {
|
|
11
|
+
throw new Error(`invalid proprietary classification: ${key} must be a unique array`);
|
|
12
|
+
}
|
|
13
|
+
return new Set(value);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const PROPRIETARY_SKILLS = toUniqueSet(config.all, 'all');
|
|
17
|
+
export const DISTRIBUTABLE_PROPRIETARY_SKILLS = toUniqueSet(config.distributable, 'distributable');
|
|
18
|
+
export const REPO_LOCAL_SKILLS = toUniqueSet(config.repoLocal, 'repoLocal');
|
|
19
|
+
export const DEFAULT_PROPRIETARY_SKILLS = toUniqueSet(config.default, 'default');
|
|
20
|
+
|
|
21
|
+
const classified = new Set([...DISTRIBUTABLE_PROPRIETARY_SKILLS, ...REPO_LOCAL_SKILLS]);
|
|
22
|
+
const missing = [...PROPRIETARY_SKILLS].filter((name) => !classified.has(name));
|
|
23
|
+
const extra = [...classified].filter((name) => !PROPRIETARY_SKILLS.has(name));
|
|
24
|
+
const overlap = [...DISTRIBUTABLE_PROPRIETARY_SKILLS].filter((name) => REPO_LOCAL_SKILLS.has(name));
|
|
25
|
+
const invalidDefaults = [...DEFAULT_PROPRIETARY_SKILLS].filter((name) => !DISTRIBUTABLE_PROPRIETARY_SKILLS.has(name));
|
|
26
|
+
if (missing.length || extra.length || overlap.length || invalidDefaults.length) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
`invalid proprietary classification: missing=${missing.join(',')} extra=${extra.join(',')} ` +
|
|
29
|
+
`overlap=${overlap.join(',')} defaults=${invalidDefaults.join(',')}`,
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function isProprietarySkill(name) {
|
|
34
|
+
return PROPRIETARY_SKILLS.has(name);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function isDistributableProprietarySkill(name) {
|
|
38
|
+
return DISTRIBUTABLE_PROPRIETARY_SKILLS.has(name);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function isRepoLocalSkill(name) {
|
|
42
|
+
return REPO_LOCAL_SKILLS.has(name);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function isDefaultProprietarySkill(name) {
|
|
46
|
+
return DEFAULT_PROPRIETARY_SKILLS.has(name);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function isDefaultProgrammingSkill(name, engineering, required) {
|
|
50
|
+
return (
|
|
51
|
+
DEFAULT_PROPRIETARY_SKILLS.has(name) ||
|
|
52
|
+
engineering.has(name) ||
|
|
53
|
+
(required && required.has(name))
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function isDistributableSkill(name, knownNames) {
|
|
58
|
+
if (!knownNames) return isDistributableProprietarySkill(name);
|
|
59
|
+
const known = knownNames instanceof Set ? knownNames : new Set(knownNames);
|
|
60
|
+
return known.has(name) && !REPO_LOCAL_SKILLS.has(name);
|
|
61
|
+
}
|
package/config/proprietary.json
CHANGED
|
@@ -1,9 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
"
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
{
|
|
2
|
+
"all": [
|
|
3
|
+
"ci-guard",
|
|
4
|
+
"tdd-implement",
|
|
5
|
+
"grill-to-spec",
|
|
6
|
+
"diagnose-fix",
|
|
7
|
+
"commit-check",
|
|
8
|
+
"scaffold-functional-test",
|
|
9
|
+
"show-me"
|
|
10
|
+
],
|
|
11
|
+
"distributable": [
|
|
12
|
+
"tdd-implement",
|
|
13
|
+
"diagnose-fix",
|
|
14
|
+
"grill-to-spec",
|
|
15
|
+
"scaffold-functional-test",
|
|
16
|
+
"show-me"
|
|
17
|
+
],
|
|
18
|
+
"repoLocal": [
|
|
19
|
+
"ci-guard",
|
|
20
|
+
"commit-check"
|
|
21
|
+
],
|
|
22
|
+
"default": [
|
|
23
|
+
"tdd-implement",
|
|
24
|
+
"diagnose-fix",
|
|
25
|
+
"grill-to-spec",
|
|
26
|
+
"show-me"
|
|
27
|
+
]
|
|
28
|
+
}
|