@caesarloo/dsh-skill-audit 0.2.2 → 0.2.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@caesarloo/dsh-skill-audit",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Audit DSH skills automatically: a host-layer tools/post-execute plugin that ships both the skill body and the audit engine, runs the engine after skill files change (write/edit/shell) or after a bulk restore/backup (any tool invoked with mode: restore|backup), feeding findings back to the model as context; also registers the skill_audit tool.",
5
5
  "keywords": [
6
6
  "dsh",
package/skill/SKILL.md CHANGED
@@ -100,7 +100,7 @@ powershell -NoProfile -ExecutionPolicy Bypass -File "$env:USERPROFILE\.dsh\skill
100
100
  |---|---|---|---|
101
101
  | F1 | frontmatter 契约 | fail/warn | `name`、`description` 必填;`name` 必须 kebab-case 且与目录名一致;缺 `whenToUse`/`version`/`last_updated` → warn |
102
102
  | S1 | 脚本可用性 | fail | 技能内每个 `.ps1` 必须 UTF-8 **with BOM**,且 `Parser::ParseFile` 报错数为 0。无 BOM 的中文脚本在 Windows PowerShell 5.1 下按 GBK 解码 → 解析失败(`Missing closing ')'`),**更新过来即不可用** |
103
- | R1 | 引用完整性 | fail/warn | SKILL.md 里 `scripts/xxx.ps1` 这类相对引用必须真实存在。**子目录存在而文件缺失 → fail**(真断裂);**引用落在同根下的另一个技能里 → warn「跨技能引用」**(应改为点名技能名 + `related_skills`,见 §5.1);**连子目录都没有 → warn**(运行时生成或外部来源) |
103
+ | R1 | 引用完整性 | fail/warn | SKILL.md 里 `scripts/xxx.ps1` 这类相对引用必须真实存在。**子目录存在而文件缺失 → fail**(真断裂);**引用落在同根下的另一个技能里 → warn「跨技能引用」**(应改为点名技能名 + `related_skills`,见 §5.1)——**相对与绝对两种形态都判**:相对形态按引用解析,绝对形态(`…\skills\<别的技能>\…`)按路径里的技能名比对(自身路径除外,示例/占位符行跳过);**连子目录都没有 → warn**(运行时生成或外部来源) |
104
104
  | R2 | 脚本被引用 | info | 技能内脚本未被 SKILL.md 提及(可能是死资产,也可能是刻意留的工具) |
105
105
  | F2 | 依赖声明 | warn | `metadata.hermes.related_skills` 的**自依赖 / 重复项**。**存在性刻意不查**:技能名可由插件运行时注册(磁盘无 SKILL.md),静态脚本查不到 → 查了必误报。悬空声明检测需活的技能目录,属插件侧(§2.0) |
106
106
  | E1 | 审核扩展 | warn | `audit_extension` 声明的扩展缺失 / 无 BOM / 解析失败 / 执行抛错 → 记在**声明该扩展的技能**上;抛过错的扩展立即停用且只报一次(见 §4.1) |
@@ -12,7 +12,9 @@
12
12
  解码会解析失败 → fail
13
13
  R1 引用完整性:SKILL.md 里 `scripts/xxx.ps1` 这类相对路径引用必须真实存在;
14
14
  子目录在而文件缺 = fail(真断裂);引用落在**别的技能**里 = warn(跨技能引用,
15
- 应改为点名技能名 + related_skills);都不在 = warn(运行时生成/外部来源) → fail / warn
15
+ 应改为点名技能名 + related_skills);都不在 = warn(运行时生成/外部来源)。
16
+ 跨技能引用**相对与绝对两种形态都判**:相对形态按引用解析,绝对形态
17
+ (`…\skills\<别的技能>\…`)按路径里的技能名比对(自身路径除外) → fail / warn
16
18
  R2 脚本被引用:技能内脚本未被 SKILL.md 提及 → info
17
19
  F2 依赖声明:related_skills 的自依赖 / 重复项(**存在性不在此判定**:技能名可由
18
20
  插件运行时注册、磁盘无 SKILL.md,静态检查必误报 → 归插件侧) → warn
@@ -359,6 +361,28 @@ function Invoke-SkillAudit {
359
361
  [void]$findings.Add((New-Finding 'R1' 'fail' "SKILL.md 引用的资源不存在:$ref" 'SKILL.md' $ref))
360
362
  }
361
363
  }
364
+ # —— R1 补充:**绝对形态**的跨技能路径引用 ——
365
+ # 上面的 Get-RelRefs 只收相对引用(scripts/x.ps1),于是 `…\skills\<别的技能>\…` 这种绝对
366
+ # 形态从不进入任何判据:2026-09-18 实测,某技能正文引用了**已被整目录移除**的技能路径,
367
+ # 全量审核全绿、一条都没报(它既不是 BOM 问题,也不是"本技能内文件缺失")。
368
+ # 判据:路径段里的技能名 ≠ 本技能名 → 跨技能引用(与相对形态同码同级别,修法也一样)。
369
+ # 两类排除:① 自身路径;② 示例/占位符行(`<DSH_HOME>/skills/…`、`xxx`)——后者仅在
370
+ # 该技能名**不是**同根下真实存在的技能时才跳过,免得把真死引用当举例放过。
371
+ $seenAbsOwner = @{}
372
+ foreach ($m in [regex]::Matches($text, '(?<![\w.-])skills[\\/]([A-Za-z0-9][A-Za-z0-9._-]*)[\\/]')) {
373
+ $owner = $m.Groups[1].Value
374
+ if ($owner -eq $name) { continue }
375
+ if ($seenAbsOwner.ContainsKey($owner)) { continue }
376
+ $lineStart = $text.LastIndexOf("`n", [Math]::Max(0, $m.Index - 1))
377
+ if ($lineStart -lt 0) { $lineStart = 0 }
378
+ $lineEnd = $text.IndexOf("`n", $m.Index)
379
+ if ($lineEnd -lt 0) { $lineEnd = $text.Length }
380
+ $line = $text.Substring($lineStart, $lineEnd - $lineStart)
381
+ $ownerIsReal = Test-Path -LiteralPath (Join-Path $SkillsRoot $owner)
382
+ if (-not $ownerIsReal -and $line -match '<[^>]*>|(?i)xxx|\*') { continue }
383
+ $seenAbsOwner[$owner] = $true
384
+ [void]$findings.Add((New-Finding 'R1' 'warn' "跨技能路径引用(绝对形态):$($m.Value) 指向另一个技能 $owner —— 正文应只点名技能名,并在 frontmatter 登记 metadata.hermes.related_skills;对方改名或移除后即成死引用" 'SKILL.md' $m.Value))
385
+ }
362
386
  # 反向:脚本资产未被任何地方引用(提示,不算失败)
363
387
  foreach ($f in $ps1) {
364
388
  $rel = $f.FullName.Substring($SkillDir.Length).TrimStart('\')