skills-manager-cli 2026.10.26 → 2026.10.27

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/README.md CHANGED
@@ -46,7 +46,7 @@ npx skills-manager-cli
46
46
 
47
47
  ![skills-manager demo](docs/assets/demo.gif)
48
48
 
49
- *`--help` and the resident context-cost ledger (`cost`) in action.*
49
+ *`--help` and the resident context-cost ledger (`cost`) in action. After bootstrap, try `cost --share` and `doctor` — both are printed as pasteable demos.*
50
50
 
51
51
  That is the whole setup. Bootstrap creates the skill hub (`~/.skills-manager`), installs the **manager skill** into it from the bundled copy, and mounts it (symlink) into the agents it detects on your machine — you confirm the list in the one prompt it shows.
52
52
 
@@ -70,8 +70,41 @@ npx skills-manager-cli # bootstrap the hub + manager skill
70
70
  skills-manager init --dry-run # preview importing existing runtime skills
71
71
  # or ask your agent: Import my existing skills into skills-manager
72
72
  skills-manager cost --share # privacy-safe paste card of your resident skill tax
73
+ skills-manager doctor --share # privacy-safe hub health card (counts only)
74
+ skills-manager update --check # freshness vs skill subtree tree-SHA (git) — no cry-wolf
75
+ skills-manager audit security --strict # CI gate: fail only on high-severity findings
76
+ skills-manager audit overlap # which skills compete for the same request (wrong-skill triggers)
77
+ skills-manager audit descriptions # descriptions that will never trigger (no "use when", vague, too long)
78
+ skills-manager sync init --remote <url> # multi-machine hub git sync (unique vs installers)
79
+ skills-manager sync status --share # privacy-safe paste card of sync posture
73
80
  ```
74
81
 
82
+ `cost --share` prints a paste-ready card (no absolute paths). Example shape:
83
+
84
+ ```text
85
+ Resident skill tax · char-approx · skills-manager
86
+ ≈1.2k tokens / message · 12 skill(s) · 2 path(s)
87
+ Paths: user/claude-code+zed · project/cursor
88
+ Heaviest: big-skill ≈400 · mid ≈200 · small ≈80
89
+ Try: npx skills-manager-cli
90
+ Reproduce: skills-manager cost --share
91
+ https://github.com/shenysun/skills-manager
92
+ ```
93
+
94
+ **CI?** Drop [`examples/github-actions/audit-security.yml`](examples/github-actions/audit-security.yml) into `.github/workflows/` on a hub repo (`skills/` + `registry.yaml`). It runs `audit security --strict --format github` on PR/push — fails only on high-severity findings, and annotates the PR Files tab.
95
+
96
+ Every gate exits 1 on failure and writes its verdict to stderr, so stdout (text/JSON) stays stable:
97
+
98
+ | Gate | Command | Fails when | Network |
99
+ | --- | --- | --- | --- |
100
+ | Security | `audit security --strict` | any high-severity finding | no |
101
+ | Provenance | `provenance list --fail-on-imported` | an imported skill has no usable source (can't get updates) | no |
102
+ | Resident cost | `cost --budget <tokens>` | total resident tokens exceed the budget | no |
103
+ | Freshness | `update --check --fail-on-stale` | any skill is stale, or a check fails | yes (`GH_TOKEN` helps) |
104
+ | **All of the above** | `check [--budget <tokens>] [--freshness]` | any enabled gate fails (security + provenance always; budget/freshness opt-in) — copy [`examples/github-actions/hub-check.yml`](examples/github-actions/hub-check.yml) | only with `--freshness` |
105
+
106
+ Details: [docs/CLI.md](docs/CLI.md).
107
+
75
108
  Runtime copies become hub-backed; originals are backed up first.
76
109
 
77
110
  ## How it works
@@ -132,10 +165,12 @@ Skill home resolution priority:
132
165
  npx skills-manager-cli # bootstrap (default when no subcommand)
133
166
  skills-manager bootstrap --agent claude-code # scripted bootstrap / mount later
134
167
  skills-manager doctor
168
+ skills-manager doctor --share # privacy-safe hub health paste card
135
169
  skills-manager list
136
170
  skills-manager add owner/repo --all --yes
137
171
  skills-manager distribute --to user --skill my-skill --agent claude-code
138
172
  skills-manager update --plan
173
+ skills-manager update --check # tree-SHA freshness (git/marketplace)
139
174
  skills-manager update --skill my-skill
140
175
  skills-manager init --dry-run # preview runtime-skill import
141
176
  skills-manager init --prefer claude-code hub # this-run conflict priority
@@ -144,11 +179,16 @@ skills-manager backup list # inspect init backups
144
179
  skills-manager backup restore my-skill # roll one import back
145
180
  skills-manager edit my-skill --source-git owner/repo --subpath skills/my-skill
146
181
  skills-manager provenance list # skills still missing a source
182
+ skills-manager provenance list --fail-on-imported # fail (exit 1) when any imported skill still lacks a source
147
183
  skills-manager provenance adopt # backfill lockfile evidence
148
184
  skills-manager categories set my-skill frontend # tag with a domain category
149
185
  skills-manager categories apply frontend -a claude-code # load only that domain
150
186
  skills-manager categories status # applied sets + drift
151
187
  skills-manager cost # resident context-cost ledger (report-only recall suggestions)
188
+ skills-manager cost --budget 2000 # fail (exit 1) when resident context tax exceeds a token budget
189
+ skills-manager sync init --remote <url> # multi-machine hub git sync
190
+ skills-manager sync status --share # privacy-safe paste card of sync posture
191
+ skills-manager update --check --fail-on-stale # fail (exit 1) when any hub skill is stale vs upstream tree-SHA
152
192
  skills-manager archive old-skill
153
193
  ```
154
194
 
package/README.zh-CN.md CHANGED
@@ -46,7 +46,7 @@ npx skills-manager-cli
46
46
 
47
47
  ![skills-manager demo](docs/assets/demo.gif)
48
48
 
49
- *演示:`--help` 与常驻上下文成本账本(`cost`)。*
49
+ *演示:`--help` 与常驻上下文成本账本(`cost`)。bootstrap 结束后还会打印可粘贴的 `cost --share` 与 `doctor` demo。*
50
50
 
51
51
  这就是全部的安装步骤。bootstrap 会创建技能库(`~/.skills-manager`),从包内副本把 **manager skill** 种进库,并(以软链接)挂载到它检测到的 agent——展示一次多选让你确认清单。
52
52
 
@@ -70,8 +70,41 @@ npx skills-manager-cli # 引导创建 hub + manager skill
70
70
  skills-manager init --dry-run # 预览导入现有运行时 skill
71
71
  # 或对 agent 说:把我现有的 skills 导入 skills-manager
72
72
  skills-manager cost --share # 可粘贴分享的常驻 skill 税卡片(无绝对路径)
73
+ skills-manager doctor --share # 可粘贴的 hub 健康卡片(仅计数,无路径/技能名)
74
+ skills-manager update --check # 新鲜度:skill 子目录 tree-SHA(git)——不上游无关提交的狼来了
75
+ skills-manager audit security --strict # CI 闸:仅 high 严重度发现时失败
76
+ skills-manager audit overlap # 哪些 skill 在抢同一个请求(误触发错的 skill)
77
+ skills-manager audit descriptions # 永远不会被触发的 description(缺「何时用」、太含糊、太长)
78
+ skills-manager sync init --remote <url> # 多机 hub git 同步(相对安装器的差异化)
79
+ skills-manager sync status --share # 可粘贴分享的同步姿态卡片(无 hub 路径 / remote URL)
73
80
  ```
74
81
 
82
+ `cost --share` 输出可直接粘贴的卡片(不含绝对路径)。示例形状:
83
+
84
+ ```text
85
+ Resident skill tax · char-approx · skills-manager
86
+ ≈1.2k tokens / message · 12 skill(s) · 2 path(s)
87
+ Paths: user/claude-code+zed · project/cursor
88
+ Heaviest: big-skill ≈400 · mid ≈200 · small ≈80
89
+ Try: npx skills-manager-cli
90
+ Reproduce: skills-manager cost --share
91
+ https://github.com/shenysun/skills-manager
92
+ ```
93
+
94
+ **上 CI?** 把 [`examples/github-actions/audit-security.yml`](examples/github-actions/audit-security.yml) 拷进 hub 仓库的 `.github/workflows/`(仓库根需是 `skills/` + `registry.yaml`)。PR/push 时跑 `audit security --strict --format github`——仅 high 严重度发现会失败,并在 PR Files 页打注解。
95
+
96
+ 每个闸失败即退出 1,结论写 stderr,stdout(文本/JSON)保持稳定:
97
+
98
+ | 闸 | 命令 | 何时失败 | 联网 |
99
+ | --- | --- | --- | --- |
100
+ | 安全 | `audit security --strict` | 存在 high 严重度发现 | 否 |
101
+ | 来源 | `provenance list --fail-on-imported` | 有导入 skill 缺可用来源(拿不到更新) | 否 |
102
+ | 常驻成本 | `cost --budget <tokens>` | 常驻总 token 超出预算 | 否 |
103
+ | 新鲜度 | `update --check --fail-on-stale` | 任一 skill 过期,或检测失败 | 是(建议设 `GH_TOKEN`) |
104
+ | **以上全部** | `check [--budget <tokens>] [--freshness]` | 任一启用的闸失败(安全 + 来源必跑;预算/新鲜度按需开启)——可直接拷贝 [`examples/github-actions/hub-check.yml`](examples/github-actions/hub-check.yml) | 仅 `--freshness` 时 |
105
+
106
+ 详见 [docs/CLI.zh-CN.md](docs/CLI.zh-CN.md)。
107
+
75
108
  运行时副本改为由 hub 托管;原文件会先备份。
76
109
 
77
110
  ## 工作原理
@@ -132,10 +165,12 @@ apply 是显式的、可逆的快照:缺的分发、集合外(含未打标
132
165
  npx skills-manager-cli # bootstrap(不带子命令时的默认行为)
133
166
  skills-manager bootstrap --agent claude-code # 脚本化 bootstrap / 之后再挂载
134
167
  skills-manager doctor
168
+ skills-manager doctor --share # 可粘贴的 hub 健康卡片(仅计数)
135
169
  skills-manager list
136
170
  skills-manager add owner/repo --all --yes
137
171
  skills-manager distribute --to user --skill my-skill --agent claude-code
138
172
  skills-manager update --plan
173
+ skills-manager update --check # tree-SHA 新鲜度(git/marketplace)
139
174
  skills-manager update --skill my-skill
140
175
  skills-manager init --dry-run # 预览运行时技能导入
141
176
  skills-manager init --prefer claude-code hub # 本次导入的冲突优先级
@@ -144,11 +179,16 @@ skills-manager backup list # 查看 init 备份
144
179
  skills-manager backup restore my-skill # 回滚某次导入
145
180
  skills-manager edit my-skill --source-git owner/repo --subpath skills/my-skill
146
181
  skills-manager provenance list # 仍缺来源的技能清单
182
+ skills-manager provenance list --fail-on-imported # 仍有「导入却无来源」的 skill 时失败(exit 1)
147
183
  skills-manager provenance adopt # 补采锁文件证据
148
184
  skills-manager categories set my-skill 前端 # 打领域类别标签
149
185
  skills-manager categories apply 前端 -a claude-code # 只加载该领域
150
186
  skills-manager categories status # 已应用集合 + 漂移
151
187
  skills-manager cost # 常驻上下文成本账本(只报告不执行的收回建议)
188
+ skills-manager cost --budget 2000 # 常驻上下文税超出 token 预算时失败(exit 1)
189
+ skills-manager sync init --remote <url> # 多机 hub git 同步
190
+ skills-manager sync status --share # 可粘贴分享的同步姿态卡片
191
+ skills-manager update --check --fail-on-stale # 任一 hub skill 相对上游树 SHA 过期时失败(exit 1)
152
192
  skills-manager archive old-skill
153
193
  ```
154
194
 
@@ -67,6 +67,11 @@ export async function runBootstrap(opts, cmd) {
67
67
  console.log('\nAll set. Go back to your agent and say:');
68
68
  console.log(` “${STARTER_PROMPT_ZH}”`);
69
69
  console.log(` (“${STARTER_PROMPT_EN}”)`);
70
+ // Growth wedge: surface the pasteable demos that land after the next npm cut
71
+ // (cost --share + doctor already ships security.high / residentCost rollups).
72
+ console.log('\nAlso try (CLI demos — paste anywhere):');
73
+ console.log(' skills-manager cost --share # privacy-safe resident skill tax card');
74
+ console.log(' skills-manager doctor # health + security.high + residentCost');
70
75
  }
71
76
  /** `--agent` wins; one detected agent needs no question; several get the picker in a TTY, all of them otherwise. */
72
77
  async function chooseAgents(opts, detected, resolveGlobalDir) {
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/cli/bootstrap.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/cli/bootstrap.ts"],"names":[],"mappings":"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"}
@@ -68,7 +68,7 @@ export function renderPresetCostLine(cost) {
68
68
  /**
69
69
  * Privacy-safe paste card for `skills-manager cost --share` (growth wedge):
70
70
  * no absolute paths, agent-family labels only, top skills by total tokens,
71
- * a one-line CTA + repo URL. Same ledger, thinner surface.
71
+ * Try/Reproduce CTA + repo URL (not a circular "Share: cost --share"). Same ledger, thinner surface.
72
72
  */
73
73
  export function renderCostShare(ledger) {
74
74
  const skillTotals = new Map();
@@ -105,7 +105,8 @@ export function renderCostShare(ledger) {
105
105
  }
106
106
  if (ledger.unmanaged > 0)
107
107
  lines.push(`${ledger.unmanaged} unmanaged skill(s) not counted`);
108
- lines.push('Share: skills-manager cost --share');
108
+ lines.push('Try: npx skills-manager-cli');
109
+ lines.push('Reproduce: skills-manager cost --share');
109
110
  lines.push('https://github.com/shenysun/skills-manager');
110
111
  return `${lines.join('\n')}\n`;
111
112
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cost-output.js","sourceRoot":"","sources":["../../src/cli/cost-output.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cost-output.js","sourceRoot":"","sources":["../../src/cli/cost-output.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAwC,MAAM,yCAAyC,CAAC;AAEnH;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAkB;IACjD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,0BAA0B,MAAM,CAAC,MAAM,aAAa,kBAAkB,CAAC,MAAM,CAAC,WAAW,CAAC,kBAAkB,MAAM,CAAC,KAAK,CAAC,MAAM,kBAAkB,CAAC,CAAC;IAC9J,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QAC1E,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,UAAU,KAAK,KAAK,CAAC,IAAI,aAAa,MAAM,OAAO,kBAAkB,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC3G,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QAC5E,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YAChC,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACrH,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9G,CAAC;IACH,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,SAAS,iCAAiC,CAAC,CAAC;IACjE,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;QACrC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,KAAK,MAAM,KAAK,CAAC,WAAW,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5G,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;IACvC,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,WAAW,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,IAAI,WAAW,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC;IAClI,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;IAC/D,IAAI,KAAK,EAAE,CAAC;QACV,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrB,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IACjC,CAAC;IACD,IAAI,WAAW,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpC,KAAK,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;QACzE,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;YACxC,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,eAAe,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;YACjG,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IACD,IAAI,WAAW,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,WAAW,CAAC,eAAe,CAAC,MAAM,CAAC;QACjD,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,8BAA8B,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;QAChF,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,eAAe,EAAE,CAAC;YAC/C,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,IAAI,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;YACtF,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IACD,IAAI,WAAW,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC,+FAA+F,CAAC,CAAC;QAC5G,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,SAAS,EAAE,CAAC;YACzC,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,WAAW,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAClG,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ;gBAAE,KAAK,CAAC,IAAI,CAAC,OAAO,OAAO,EAAE,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IACD,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AACjC,CAAC;AAED;;oBAEoB;AACpB,MAAM,UAAU,oBAAoB,CAAC,IAAoB;IACvD,OAAO,kBAAkB,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,wBAAwB,IAAI,CAAC,MAAM,GAAG,CAAC;AACjG,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,MAAkB;IAChD,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC9C,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YAChC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QAChF,CAAC;IACH,CAAC;IACD,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI,CAAC;IACpC,MAAM,QAAQ,GAAG,CAAC,GAAG,WAAW,CAAC,OAAO,EAAE,CAAC;SACxC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SACvD,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;SACX,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,IAAI,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAEtE,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QAC1C,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACzE,OAAO,GAAG,KAAK,CAAC,IAAI,IAAI,MAAM,EAAE,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,wBAAwB,MAAM,CAAC,MAAM,mBAAmB,CAAC,CAAC;IACrE,KAAK,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,MAAM,CAAC,WAAW,CAAC,uBAAuB,UAAU,eAAe,MAAM,CAAC,KAAK,CAAC,MAAM,UAAU,CAAC,CAAC;IACnI,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACtE,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,aAAa,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACzE,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC;IACpD,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC;IACtD,IAAI,QAAQ,GAAG,CAAC,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,QAAQ,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,QAAQ,6BAA6B,CAAC,CAAC;QACvE,IAAI,SAAS,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,SAAS,YAAY,CAAC,CAAC;QACxD,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC5C,CAAC;IACD,IAAI,MAAM,CAAC,SAAS,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,SAAS,iCAAiC,CAAC,CAAC;IAC3F,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;IAC1C,KAAK,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;IACrD,KAAK,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;IACzD,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AACjC,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { formatApproxTokens } from '../core/services/cost-ledger-service.js';
2
+ /**
3
+ * Privacy-safe paste card for `skills-manager doctor --share` (growth wedge):
4
+ * counts and magnitudes only — never skillHome, broken-link paths, skill names,
5
+ * or warning text that may embed absolute paths. Try/Reproduce CTA + repo URL.
6
+ */
7
+ export function renderDoctorShare(report) {
8
+ const cost = report.residentCost;
9
+ const dist = report.distribution;
10
+ const lines = [];
11
+ lines.push('Hub health · skills-manager');
12
+ lines.push(`${report.skillCount} skill(s) · managed ${dist.managedEntries} · outdated ${dist.outdated} · foreign ${dist.foreign}`);
13
+ lines.push(`Resident: ${formatApproxTokens(cost.totalTokens)} tokens / message · ${cost.method}`);
14
+ const scattered = cost.suggestions.scattered.length;
15
+ if (scattered > 0)
16
+ lines.push(`Watch: ${scattered} scattered`);
17
+ lines.push(`Security: ${report.security.high} high · ${report.security.scanner} · scanned ${report.security.scanned}`);
18
+ lines.push(report.warnings.length === 0 ? 'Warnings: none' : `Warnings: ${report.warnings.length}`);
19
+ if (report.brokenLinks.length > 0)
20
+ lines.push(`Broken links: ${report.brokenLinks.length}`);
21
+ if (report.importedWithoutSource.length > 0) {
22
+ lines.push(`Imported without source: ${report.importedWithoutSource.length}`);
23
+ }
24
+ lines.push('Try: npx skills-manager-cli');
25
+ lines.push('Reproduce: skills-manager doctor --share');
26
+ lines.push('https://github.com/shenysun/skills-manager');
27
+ return `${lines.join('\n')}\n`;
28
+ }
29
+ //# sourceMappingURL=doctor-output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor-output.js","sourceRoot":"","sources":["../../src/cli/doctor-output.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAG7E;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAoB;IACpD,MAAM,IAAI,GAAG,MAAM,CAAC,YAAY,CAAC;IACjC,MAAM,IAAI,GAAG,MAAM,CAAC,YAAY,CAAC;IACjC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;IAC1C,KAAK,CAAC,IAAI,CACR,GAAG,MAAM,CAAC,UAAU,uBAAuB,IAAI,CAAC,cAAc,eAAe,IAAI,CAAC,QAAQ,cAAc,IAAI,CAAC,OAAO,EAAE,CACvH,CAAC;IACF,KAAK,CAAC,IAAI,CAAC,aAAa,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC,uBAAuB,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAClG,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC;IACpD,IAAI,SAAS,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,SAAS,YAAY,CAAC,CAAC;IAC/D,KAAK,CAAC,IAAI,CACR,aAAa,MAAM,CAAC,QAAQ,CAAC,IAAI,WAAW,MAAM,CAAC,QAAQ,CAAC,OAAO,cAAc,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,CAC3G,CAAC;IACF,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,aAAa,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACpG,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,iBAAiB,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5F,IAAI,MAAM,CAAC,qBAAqB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5C,KAAK,CAAC,IAAI,CAAC,4BAA4B,MAAM,CAAC,qBAAqB,CAAC,MAAM,EAAE,CAAC,CAAC;IAChF,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;IAC1C,KAAK,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;IACvD,KAAK,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;IACzD,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AACjC,CAAC"}
package/dist/cli/main.js CHANGED
@@ -5,6 +5,8 @@ import { createRuntimeServices, projectRootFromImportMeta } from '../infra/runti
5
5
  import { isInsecureHttpSource, normalizeGitSourceUrl } from '../core/services/source-service.js';
6
6
  import { isUpdatableSourceType } from '../core/services/update-service.js';
7
7
  import { parseFormatFlag } from '../core/services/url-payload.js';
8
+ import { findDescriptionOverlaps, renderOverlapReport } from '../core/services/description-overlap.js';
9
+ import { lintDescriptions, renderDescriptionLint } from '../core/services/description-lint.js';
8
10
  import { confirmInsecureHttp } from './insecure-http-confirm.js';
9
11
  import { SkillsManagerError } from '../shared/errors.js';
10
12
  import { redactCheckout, redactDiscovered } from '../shared/redact.js';
@@ -14,6 +16,9 @@ import { HttpDownloadClient } from '../infra/http-download-client.js';
14
16
  import { DetectionService, detectionLogPath } from '../core/services/detection-service.js';
15
17
  import { runBootstrap, managerSkillBundle } from './bootstrap.js';
16
18
  import { renderCostLedger, renderCostShare, renderPresetCostLine } from './cost-output.js';
19
+ import { renderDoctorShare } from './doctor-output.js';
20
+ import { renderSyncShare } from './sync-output.js';
21
+ import { formatGithubAnnotations } from '../core/services/security-scan.js';
17
22
  const pkg = createRequire(import.meta.url)('../../package.json');
18
23
  const projectRoot = projectRootFromImportMeta(import.meta.url);
19
24
  function services(cmd, options = {}) {
@@ -82,6 +87,9 @@ const webCommand = (cmd, description) => cmd
82
87
  .option('--host <host>', 'host', '127.0.0.1')
83
88
  .option('--no-open', 'do not open a browser')
84
89
  .action(async (opts, self) => {
90
+ const port = Number(opts.port);
91
+ if (!/^\d+$/.test(String(opts.port)) || port > 65535)
92
+ throw new Error(`--port expects an integer from 0 to 65535, got "${opts.port}"`);
85
93
  const globalOpts = self.optsWithGlobals();
86
94
  // Single entry point (ADR-0014): the dashboard never creates the hub — bootstrap does.
87
95
  const probe = createRuntimeServices({ home: globalOpts.home }, projectRoot);
@@ -91,23 +99,31 @@ const webCommand = (cmd, description) => cmd
91
99
  selfCheckManagerSkill(probe);
92
100
  // Lazy: fastify/shiki/markdown load only for the dashboard command, not on every CLI invocation.
93
101
  const { startDashboardServer } = await import('../dashboard/server/main.js');
94
- return startDashboardServer({ home: globalOpts.home, port: Number(opts.port), host: opts.host, open: opts.open, projectRoot });
102
+ return startDashboardServer({ home: globalOpts.home, port, host: opts.host, open: opts.open, projectRoot });
95
103
  });
96
104
  webCommand(program.command('web'), 'Start the local web dashboard');
97
105
  webCommand(program.command('dashboard', { hidden: true }), 'Deprecated alias for web');
98
106
  program.command('doctor')
99
107
  .description('Run health checks')
108
+ .option('--share', 'privacy-safe paste card (counts only — no paths / skill names) for X / HN / chat')
100
109
  .option('--migrate-views', 'distribute leftover hub views to user runtimes')
101
110
  .option('--delete-views', 'with --migrate-views, remove generated view symlinks')
102
111
  .option('--force', 'with --migrate-views, overwrite unmanaged runtime paths')
103
112
  .action((opts, cmd) => {
104
113
  const s = services(cmd);
114
+ if (opts.share && opts.migrateViews)
115
+ throw new Error('use either --share or --migrate-views, not both');
105
116
  if (opts.migrateViews) {
106
117
  const migrated = s.distribute.migrateViews({ deleteViews: Boolean(opts.deleteViews), force: Boolean(opts.force) });
107
118
  s.activity.record({ action: 'cli-migrate-views', summary: 'Migrated leftover hub views', details: migrated });
108
119
  return print({ migrated, doctor: s.doctor.check() });
109
120
  }
110
- print(s.doctor.check());
121
+ const report = s.doctor.check();
122
+ if (opts.share) {
123
+ process.stdout.write(renderDoctorShare(report));
124
+ return;
125
+ }
126
+ print(report);
111
127
  });
112
128
  program.command('status')
113
129
  .description('Summarize managed distribution health (managed/foreign/outdated/stale)')
@@ -393,16 +409,31 @@ provenance.command('adopt')
393
409
  provenance.command('list')
394
410
  .description('List skills still missing a source: imported-without-source vs locally authored')
395
411
  .option('--json', 'machine-readable output for agents')
412
+ .option('--fail-on-imported', 'exit 1 when any imported-without-source skill remains (CI / hub-hygiene gate; locally authored never fails)')
396
413
  .action((opts, cmd) => {
397
414
  const pending = services(cmd).provenance.pending();
398
415
  if (opts.json)
399
- return print(pending);
400
- console.log(`Imported without source (${pending.importedWithoutSource.length}):`);
401
- for (const item of pending.importedWithoutSource)
402
- console.log(` ${item.skill}${item.importedAt ? ` (imported ${item.importedAt})` : ''}`);
403
- console.log(`Locally authored, no upstream recorded (${pending.locallyAuthored.length}):`);
404
- for (const skill of pending.locallyAuthored)
405
- console.log(` ${skill}`);
416
+ print(pending);
417
+ else {
418
+ console.log(`Imported without source (${pending.importedWithoutSource.length}):`);
419
+ for (const item of pending.importedWithoutSource)
420
+ console.log(` ${item.skill}${item.importedAt ? ` (imported ${item.importedAt})` : ''}`);
421
+ console.log(`Locally authored, no upstream recorded (${pending.locallyAuthored.length}):`);
422
+ for (const skill of pending.locallyAuthored)
423
+ console.log(` ${skill}`);
424
+ }
425
+ // Hygiene gate: imported skills without a source cannot get tree-SHA updates.
426
+ // Locally authored skills are intentional and never trip this flag.
427
+ if (opts.failOnImported) {
428
+ const n = pending.importedWithoutSource.length;
429
+ if (n > 0) {
430
+ process.stderr.write(`Provenance: ${n} imported skill(s) still missing a source — FAIL (--fail-on-imported); run \`skills-manager provenance adopt\` or \`edit --source-*\`\n`);
431
+ process.exitCode = 1;
432
+ }
433
+ else {
434
+ process.stderr.write('Provenance: no imported-without-source skills — within hygiene gate\n');
435
+ }
436
+ }
406
437
  });
407
438
  // Hub git-ification for multi-machine sync (ADR-0020): each command thin, git
408
439
  // stays the merge tool, and the operator keeps every git decision.
@@ -429,10 +460,17 @@ sync.command('init')
429
460
  sync.command('status')
430
461
  .description('Read-only sync status: git-ification, remote, dirty files, ahead/behind (last fetch), last sync commit — zero network')
431
462
  .option('--json', 'machine-readable output for agents')
463
+ .option('--share', 'privacy-safe paste card (no hub path / remote URL) for X / HN / chat')
432
464
  .action((opts, cmd) => {
433
465
  const result = services(cmd).sync.status();
466
+ if (opts.json && opts.share)
467
+ throw new Error('use either --json or --share, not both');
434
468
  if (opts.json)
435
469
  return print(result);
470
+ if (opts.share) {
471
+ process.stdout.write(renderSyncShare(result));
472
+ return;
473
+ }
436
474
  // Read-only probe: no activity record — status itself must not dirty the hub.
437
475
  console.log(`hub: ${result.home}`);
438
476
  if (!result.gitified) {
@@ -588,17 +626,29 @@ program.command('cost')
588
626
  .option('--json', 'machine-readable output for agents')
589
627
  .option('--share', 'privacy-safe paste card (no absolute paths) for X / HN / chat')
590
628
  .option('--top <n>', 'how many of the most expensive descriptions to list', '5')
629
+ .option('--budget <tokens>', 'exit 1 when total resident tokens exceed this budget (CI / pre-commit gate)')
591
630
  .action((opts, cmd) => {
592
- const s = services(cmd);
593
631
  const top = Number.parseInt(opts.top, 10);
594
632
  if (!Number.isInteger(top) || top < 0)
595
633
  throw new Error(`--top expects a non-negative integer, got "${opts.top}"`);
596
634
  if (opts.json && opts.share)
597
635
  throw new Error('use either --json or --share, not both');
636
+ const budget = opts.budget === undefined ? null : Number(opts.budget);
637
+ if (budget !== null && (!Number.isInteger(budget) || budget < 0))
638
+ throw new Error(`--budget expects a non-negative integer token count, got "${opts.budget}"`);
639
+ const s = services(cmd);
598
640
  const ledger = s.cost.ledger(top);
599
641
  if (opts.json)
600
- return print(ledger);
601
- process.stdout.write(opts.share ? renderCostShare(ledger) : renderCostLedger(ledger));
642
+ print(ledger);
643
+ else
644
+ process.stdout.write(opts.share ? renderCostShare(ledger) : renderCostLedger(ledger));
645
+ // Budget gate on stderr so stdout (JSON / card) stays script-stable.
646
+ if (budget !== null) {
647
+ const over = ledger.totalTokens > budget;
648
+ process.stderr.write(`Resident budget: ${ledger.totalTokens} / ${budget} tokens — ${over ? 'OVER (exit 1); see Suggestions or run `skills-manager cost` for recalls' : 'within budget'}\n`);
649
+ if (over)
650
+ process.exitCode = 1;
651
+ }
602
652
  });
603
653
  program.command('add')
604
654
  .description('Discover from a source, then install selected skills')
@@ -646,8 +696,11 @@ program.command('update')
646
696
  .option('-s, --skill <skill...>', 'skill(s) to update')
647
697
  .option('--source <key>', 'source group key from updates plan')
648
698
  .option('--plan', 'print update plan (candidates only)')
649
- .option('--check', 'run upstream freshness detection: stale / upToDate / failed / skipped per skill (uncalibrated entries adopt their observed anchor, ADR-0013)')
699
+ .option('--check', 'run upstream freshness detection: stale / upToDate / failed / skipped per skill (git/marketplace: skill subdirectory tree SHA, not whole-repo HEAD; uncalibrated entries adopt their observed anchor, ADR-0013)')
700
+ .option('--fail-on-stale', 'with --check: also exit 1 when any skill is stale (failed checks already exit 1; CI / hub-freshness gate)')
650
701
  .action(async (opts, cmd) => {
702
+ if (opts.failOnStale && !opts.check)
703
+ throw new Error('--fail-on-stale requires --check');
651
704
  const s = services(cmd);
652
705
  if (opts.check) {
653
706
  const detection = new DetectionService({ githubApi: new GitHubApiClient(), http: new HttpDownloadClient(), fs: new NodeFileSystem() });
@@ -675,9 +728,22 @@ program.command('update')
675
728
  upToDate.push(skill.name);
676
729
  }
677
730
  print({ checked: stale.length + failed.length + upToDate.length + skipped.length, stale, upToDate, failed, skipped });
731
+ // Growth tip (stderr): JSON stdout stays script-stable; the differentiator is the git/marketplace tree-SHA anchor.
732
+ console.error('Update signal (git/marketplace): skill subdirectory tree SHA — upstream noise outside the skill never lights an update.');
678
733
  // A failed check is a failed check — scripts read the exit code (adversary M6).
679
734
  if (failed.length > 0)
680
735
  process.exitCode = 1;
736
+ // Optional CI gate: stale skills are informational by default; --fail-on-stale
737
+ // turns the tree-SHA freshness signal into a nonzero exit (stdout JSON unchanged).
738
+ if (opts.failOnStale) {
739
+ if (stale.length > 0) {
740
+ process.stderr.write(`Update check: ${stale.length} stale skill(s) — FAIL (--fail-on-stale); run \`skills-manager update --plan\` then update\n`);
741
+ process.exitCode = 1;
742
+ }
743
+ else if (failed.length === 0) {
744
+ process.stderr.write('Update check: no stale skills — within freshness gate\n');
745
+ }
746
+ }
681
747
  return;
682
748
  }
683
749
  if (opts.plan || (!opts.skill && !opts.source))
@@ -688,15 +754,139 @@ program.command('update')
688
754
  remindSecurityScan(s, result.updated);
689
755
  remindStaleTargets(s);
690
756
  });
691
- const audit = program.command('audit').description('Report-only audits over hub skills (security today; more subcommands later)');
757
+ // One exit code for CI: the offline hub gates (security high, imported-without-source)
758
+ // always run; the resident budget and the networked freshness check are opt-in.
759
+ program.command('check')
760
+ .description('Run the hub CI gates in one go: audit security (high) + provenance (imported-without-source), plus optional --budget, --freshness, --overlap and --descriptions; exit 1 if any gate fails')
761
+ .option('--budget <tokens>', 'also fail when total resident tokens exceed this budget (same as cost --budget)')
762
+ .option('--freshness', 'also run update --check (network) and fail on stale or failed detection')
763
+ .option('--overlap', 'also fail when any two skill descriptions compete (same as audit overlap --strict, threshold 0.3)')
764
+ .option('--descriptions', 'also fail on error-level description lint findings (same as audit descriptions --strict; warnings never fail)')
765
+ .option('--json', 'machine-readable gate results')
766
+ .action(async (opts, cmd) => {
767
+ const budget = opts.budget === undefined ? null : Number(opts.budget);
768
+ if (budget !== null && (!Number.isInteger(budget) || budget < 0))
769
+ throw new Error(`--budget expects a non-negative integer token count, got "${opts.budget}"`);
770
+ const s = services(cmd);
771
+ const gates = [];
772
+ const names = s.registry.listSkills().map((skill) => skill.name);
773
+ const high = s.security.countHighFindings(s.security.scanSkills(names));
774
+ gates.push({ gate: 'security', ok: high === 0, detail: `${high} high finding(s) across ${names.length} skill(s)${high ? ' — run `skills-manager audit security --strict`' : ''}` });
775
+ const imported = s.provenance.pending().importedWithoutSource.length;
776
+ gates.push({ gate: 'provenance', ok: imported === 0, detail: `${imported} imported skill(s) missing a source${imported ? ' — run `skills-manager provenance adopt`' : ''}` });
777
+ if (budget !== null) {
778
+ const total = s.cost.ledger(0).totalTokens;
779
+ gates.push({ gate: 'budget', ok: total <= budget, detail: `${total} / ${budget} resident tokens${total > budget ? ' — run `skills-manager cost` for recalls' : ''}` });
780
+ }
781
+ if (opts.overlap || opts.descriptions) {
782
+ const inputs = s.registry.listSkills().map((skill) => ({ name: skill.name, description: skill.description }));
783
+ if (opts.overlap) {
784
+ const pairs = findDescriptionOverlaps(inputs, 0.3).pairs.length;
785
+ gates.push({ gate: 'overlap', ok: pairs === 0, detail: `${pairs} competing description pair(s)${pairs ? ' — run `skills-manager audit overlap`' : ''}` });
786
+ }
787
+ if (opts.descriptions) {
788
+ const lint = lintDescriptions(inputs);
789
+ gates.push({ gate: 'descriptions', ok: lint.errors === 0, detail: `${lint.errors} error(s), ${lint.warnings} warning(s) in skill descriptions${lint.errors ? ' — run `skills-manager audit descriptions`' : ''}` });
790
+ }
791
+ }
792
+ if (opts.freshness) {
793
+ const detection = new DetectionService({ githubApi: new GitHubApiClient(), http: new HttpDownloadClient(), fs: new NodeFileSystem() });
794
+ const listed = s.registry.listSkills({ includeArchived: false });
795
+ const outcomes = await detection.detect(s, listed);
796
+ let stale = 0;
797
+ let failed = 0;
798
+ for (const outcome of outcomes.values()) {
799
+ if (outcome.detection === 'failed')
800
+ failed += 1;
801
+ else if (outcome.detection !== 'skipped' && outcome.hasUpdate)
802
+ stale += 1;
803
+ }
804
+ gates.push({ gate: 'freshness', ok: stale === 0 && failed === 0, detail: `${stale} stale, ${failed} failed (tree-SHA)${stale || failed ? ' — run `skills-manager update --check`' : ''}` });
805
+ }
806
+ const ok = gates.every((g) => g.ok);
807
+ if (opts.json)
808
+ print({ ok, gates });
809
+ else {
810
+ for (const g of gates)
811
+ console.log(`${g.ok ? 'PASS' : 'FAIL'} ${g.gate}: ${g.detail}`);
812
+ console.log(`check: ${ok ? 'PASS' : 'FAIL'} (${gates.filter((g) => g.ok).length}/${gates.length} gates)`);
813
+ }
814
+ if (!ok)
815
+ process.exitCode = 1;
816
+ });
817
+ const audit = program.command('audit').description('Report-only audits over hub skills (security, description overlap, description lint)');
692
818
  audit.command('security')
693
- .description('Scan skill tree(s) for high-signal risks: shell exec, network calls, credential paths, secret-like strings (never blocks)')
819
+ .description('Scan skill tree(s) for high-signal risks: shell exec, network calls, credential paths, secret-like strings (report-only by default)')
694
820
  .argument('[skills...]', 'canonical skill names; omit to scan every non-archived hub skill')
695
- .action((skills, _opts, cmd) => {
821
+ .option('--strict', 'exit 1 when any high-severity finding is present (warn/info never fail; default stays report-only)')
822
+ .option('--format <format>', 'json (default) or github (Actions ::error/::warning/::notice annotations for the PR file UI)', 'json')
823
+ .action((skills, opts, cmd) => {
824
+ const format = opts.format ?? 'json';
825
+ if (format !== 'json' && format !== 'github') {
826
+ throw new SkillsManagerError('invalid_format_flag', `--format must be json or github (got ${JSON.stringify(format)})`);
827
+ }
696
828
  const s = services(cmd);
697
829
  const names = skills.length > 0 ? skills : s.registry.listSkills().map((skill) => skill.name);
698
830
  const reports = s.security.scanSkills(names);
699
- print(reports.length === 1 ? reports[0] : reports);
831
+ if (format === 'github') {
832
+ const annotations = formatGithubAnnotations(reports);
833
+ if (annotations)
834
+ console.log(annotations);
835
+ }
836
+ else {
837
+ print(reports.length === 1 ? reports[0] : reports);
838
+ }
839
+ if (opts.strict && s.security.failsStrict(reports))
840
+ process.exitCode = 1;
841
+ });
842
+ audit.command('overlap')
843
+ .description('Find skills whose descriptions compete for the same trigger words (the agent may pick the wrong one); offline, report-only')
844
+ .argument('[skills...]', 'canonical skill names; omit to compare every non-archived hub skill')
845
+ .option('--threshold <score>', 'minimum overlap score from 0 to 1 to report', '0.3')
846
+ .option('--strict', 'exit 1 when any pair is reported (CI gate)')
847
+ .option('--json', 'machine-readable report')
848
+ .action((skills, opts, cmd) => {
849
+ const threshold = Number(opts.threshold);
850
+ if (!/^(0(\.\d+)?|1(\.0+)?|\.\d+)$/.test(opts.threshold) || !(threshold >= 0 && threshold <= 1)) {
851
+ throw new Error(`--threshold expects a number from 0 to 1, got "${opts.threshold}"`);
852
+ }
853
+ const s = services(cmd);
854
+ const all = s.registry.listSkills();
855
+ const missing = skills.filter((name) => !all.some((skill) => skill.name === name));
856
+ if (missing.length > 0)
857
+ throw new Error(`Skill not found: ${missing.join(', ')}. Run \`skills-manager list\` to see hub skills.`);
858
+ const picked = skills.length > 0 ? all.filter((skill) => skills.includes(skill.name)) : all;
859
+ const report = findDescriptionOverlaps(picked.map((skill) => ({ name: skill.name, description: skill.description })), threshold);
860
+ if (opts.json)
861
+ print(report);
862
+ else
863
+ process.stdout.write(renderOverlapReport(report));
864
+ if (opts.strict && report.pairs.length > 0) {
865
+ process.stderr.write(`Overlap: ${report.pairs.length} competing pair(s) — FAIL (--strict); sharpen the descriptions above\n`);
866
+ process.exitCode = 1;
867
+ }
868
+ });
869
+ audit.command('descriptions')
870
+ .description('Lint skill descriptions for what makes them fail to trigger: missing, too long, no "use when", wrong point of view, vague; offline, report-only')
871
+ .argument('[skills...]', 'canonical skill names; omit to lint every non-archived hub skill')
872
+ .option('--strict', 'exit 1 when any error-level finding is present (warnings never fail)')
873
+ .option('--json', 'machine-readable report')
874
+ .action((skills, opts, cmd) => {
875
+ const s = services(cmd);
876
+ const all = s.registry.listSkills();
877
+ const missing = skills.filter((name) => !all.some((skill) => skill.name === name));
878
+ if (missing.length > 0)
879
+ throw new Error(`Skill not found: ${missing.join(', ')}. Run \`skills-manager list\` to see hub skills.`);
880
+ const picked = skills.length > 0 ? all.filter((skill) => skills.includes(skill.name)) : all;
881
+ const report = lintDescriptions(picked.map((skill) => ({ name: skill.name, description: skill.description })));
882
+ if (opts.json)
883
+ print(report);
884
+ else
885
+ process.stdout.write(renderDescriptionLint(report));
886
+ if (opts.strict && report.errors > 0) {
887
+ process.stderr.write(`Description lint: ${report.errors} error(s) — FAIL (--strict)\n`);
888
+ process.exitCode = 1;
889
+ }
700
890
  });
701
891
  const distribute = program.command('distribute')
702
892
  .description('Distribute hub skills to user or project runtime directories')