Skip to content

重构:脚本共享路径与读取函数收进 _skill_io,npm 包不再发布 CI 专用脚本 - #304

Merged
xr843 merged 5 commits into
mainfrom
refactor/shared-skill-io
Oct 3, 2026
Merged

xr843 merged 5 commits into
mainfrom
refactor/shared-skill-io

Conversation

@xr843

@xr843 xr843 commented Oct 3, 2026 •

Copy link
Copy Markdown
Owner

审计实测:24 个脚本各自写一遍 ROOT / PREBUILT_DIR = Path(__file__)...,现成的 scripts/_masterpaths.py 只有 4 个在用;frontmatter 解析有 6 份实现,load_fixtures、parse_sections、_read_json 各重复两份。另外 npm 包把 scripts/ 整个发出去,连只在本仓 CI 里跑的门禁也在里面。本 PR 只做重构,不改任何门禁的输出、消息和退出码。

共享模块 scripts/_skill_io.py。 内容包括:路径常量(ROOT / SCRIPTS_DIR / PREBUILT_DIR)、frontmatter 读取、fidelity fixture 加载、JSON 读取,以及 cite.py / query.py 共用的 ## 分段函数。导入时只用标准库(pyyaml 用到时才导入),兼容 Python 3.9。frontmatter 仍保留两种读法:validate.py 按整行围栏切分,sources: 类读取则按前两个 --- 子串切分。两者在畸形输入上本来就不一致,14 个边界用例里有 7 个结果不同(开头空行、值里含 a---b、----、非 mapping 等)。所以先把旧实现的输出录成表格测试(scripts/tests/test_skill_io.py)再迁移,并断言两种读法在每份 prebuilt SKILL.md 上结果相同。两份 _read_json 各自的失败形态(返回 None 或返回 {"__error__": ...})都保留。load_fixtures 保留模块级包装,测试对 PREBUILT 的 monkeypatch 照样生效。

没迁的部分及原因。 run-gates.py 保留自己的 ROOT:check-gate-liveness.py 会从任意 --root 按路径加载它,如果改用已缓存的兄弟模块,会指向错误的目录树。tools/ 一行未改:create-master 安装时只拷 tools/,不拷 scripts/(见 skill-catalog.json 的 bundle_paths),所以 tools/ 必须自给自足,verify_sources.py 的两处和 master_builder.py 的一处 frontmatter 读取原样保留,模块文档里写明了原因。_masterpaths.py 用的是 abspath(不解析符号链接),和 resolve() 语义不同,也未合并。新增的 scripts/tests/conftest.py 把 scripts/ 加进 sys.path,单独跑某个测试文件时也能导入兄弟模块(persona-fidelity CI 就是单文件跑的)。

test-fidelity.py 的 run_tests。 dry-run、plan、SDK client、审计输入这几块,以及三处重复的 tool log 写入,拆成具名 helper。检查顺序、错误消息、结果 dict 的键序都不变。线程池部分没动:grade_one / run_subagent 是闭包,引用了 suite 状态,拆开风险高。

npm 包。 逐一 grep 了 bin/、hooks/、tools/、prebuilt/**、SKILL.md、README 和 plugin manifest,并核对了脚本之间的 import / spec 加载关系,确认有 18 个脚本只被 run-gates.py、check-gate-liveness.py 或 CI 调用,其中几个还依赖从未打进包的 eval/ 或 tests/。用 "!scripts/<x>.py" 把它们排除。有 SKILL.md、README 或已发布脚本引用的一律保留,validate-routing.py 只在 master-help SKILL.md 里作为说明被提到,属于模糊情况,也保留。新增一条 CLI 测试:已发布脚本 import 或 spec 加载的兄弟脚本如果没发布,测试就失败(临时排除 _masterpaths.py 验证过,它确实会变红)。

验证

  • 前后快照对比:对 35 条命令(全部 content 门禁、--json 变体、cite/query、test-fidelity --dry-run/--plan、regrade/reaudit 等)分别在干净树和 5 份故意弄坏的副本上运行(frontmatter YAML 非法、开头空行加 fojin_text_id 改错、fixture 缺字段加垃圾条目、routing.json 与 gemini-extension.json 写坏、frontmatter 不闭合),对比 main(rebase 后的 git archive 2873ac8)与本分支的结果。216 份输出中,退出码全部一致,stdout 只有 4 份不同,且都只差崩溃 traceback 里的栈帧(多一层 _skill_io),最终异常行完全相同。
  • 第一次对比发现 validate.py 的 missing-field 报错顺序在前后两侧不一样。查明是 REQUIRED_FIELDS 等集合受 hash 随机化影响:同一棵树连跑 3 次,md5 都不同,这是原有行为。之后统一固定 PYTHONHASHSEED=0 重跑。
  • python3 scripts/run-gates.py 全量:23 道全部通过,退出码 0;pytest 1547 passed、2 skipped(新增 65 条),CLI 127 个测试通过。--only eval-sdk 中 smoke 与 --break 均符合预期;check-eval-sdk-surface 在本机因 SDK 版本与钉版不符而失败,在 main 上同样失败,CI 会装钉版。
  • scripts/tests/ 与 tests/ 下每个测试文件单独运行,全部通过。
  • Python 3.9.25(uv)compileall tools scripts 通过。test-fidelity.py 的 pytest 覆盖率仍为 91%,_skill_io.py 为 100%。
  • npm pack --dry-run:246 → 229 个文件,tarball 562,227 → 510,086 字节(-9.3%),解包后 1,710,423 → 1,548,875 字节。打包安装测试(packed npm artifact installs all skills…)通过。另外把新 tarball 解开,在包目录里直接跑 cite、query、validate --strict、validate-fidelity、validate-citation-contract、validate-routing、test-fidelity --all --dry-run 等 14 个已发布脚本,全部能运行。validate-promptfoo-configs 因包里没有 tests/persona/ 退出 1,main 的包也一样。

未运行任何付费评测。

发现但未修(本 PR 只做重构):按 --- 切分的读法遇到值里含 --- 会把 frontmatter 截断;validate.py 报告顺序不确定;load_fixtures 沿用平台默认编码读取。

xr843 added 5 commits October 3, 2026 15:06
One copy of the repo / prebuilt paths, SKILL.md frontmatter reading, the
fidelity-fixture loader, JSON reading and the ## section splitter. The
characterization tests were recorded from the readers being replaced: the
line-fenced and split-on-`---` frontmatter readers disagree on seven of
14 edge cases (leading blank line, `a---b` in a value, `----`, non-mapping,
...), so both are kept and pinned, and they are checked to agree on every
prebuilt SKILL.md. scripts/tests/conftest.py puts scripts/ on sys.path so a
single test file can load a script that imports a sibling.
…kill_io

Twenty-four scripts drop their own `Path(__file__).resolve().parent.parent`;
validate.py and validate-self-audit-sources.py use the shared frontmatter
readers, cite.py / query.py the shared section splitter, regrade-report.py /
validate-fixture-terms.py the shared fixture loader, and
check-manifest-versions.py / validate-routing.py the shared JSON reader, each
keeping its own failure shape.

run-gates.py keeps its own ROOT: check-gate-liveness.py loads it by path from
an arbitrary --root, where a cached sibling module would point at the wrong
tree. tools/ is untouched; the create-master install copies tools/ without
scripts/.

Every validator's stdout and exit code, on the tree and on five broken copies
(invalid YAML, leading blank line, broken fixture, broken JSON, unclosed
frontmatter), is unchanged with PYTHONHASHSEED fixed; only crash tracebacks
gain a frame.
_cap_tests, _dry_run_suite, _plan_suite, _make_sender, _load_audit_inputs
and _attach_tool_log take over the blocks run_tests ran inline; the order of
checks, the error messages and the result dicts' key order are unchanged.
The thread-pool section stays inline: grade_one and run_subagent close over
the suite state. Dry-run and --plan output for every suite and the eval-SDK
smoke are identical before and after.
Nothing in bin/, hooks/, tools/, prebuilt/, SKILL.md or the READMEs invokes
run-gates.py, check-gate-liveness.py, regrade/reaudit-report.py, the eval-SDK
checks or the content gates that only run-gates lists; several also need
eval/ or tests/, which never shipped. Everything a persona, the README or a
shipped script references still ships (cite, query, validate and its
sub-checks, validate-fidelity, test-fidelity, validate-citation-contract,
validate-routing, verify_citations and the _ helpers).

244 -> 227 files, tarball 546,942 -> 494,837 bytes. A CLI test fails if a
shipped script imports or spec-loads a sibling that does not ship.
@xr843
xr843 force-pushed the refactor/shared-skill-io branch from 49e86f8 to 6ba39c5 Compare October 3, 2026 07:08
@xr843
xr843 merged commit 56196ef into main Oct 3, 2026
15 checks passed
@xr843
xr843 deleted the refactor/shared-skill-io branch October 3, 2026 07:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant