test(pi): validate package integrity in CI (PF-3852) - #43
Conversation
The package ships no code, so nothing here fails loudly. A malformed skill
description means pi silently does not load that skill; a dropped `files` entry
means the tarball publishes and installs with skills missing; a tool the skills
teach but that is not in `directTools` means the model calls something that was
never registered. All three are invisible until a user hits them.
`pi/test/validate.mjs` — dependency-free, runs locally as `node test/validate.mjs`:
| Check | Catches |
|---|---|
| manifest | `pi.mcp`/`pi.skills` pointing at missing paths; a dropped `pi-package` keyword, which is the entire gallery discovery mechanism |
| mcp | `type: "http"` creeping back (the adapter has no such field); the `${VAR:-}` interpolation form, which ships as a literal header; empty or duplicated `directTools` |
| skills | frontmatter name/description rules pi enforces, name/directory mismatch, duplicate names, and skill-relative `.md` references that do not resolve |
| skills-vs-directTools | a tool taught by the skills but not registered |
| files | a missing `files` entry, or `test/` leaking into the tarball |
Written after the check found two real bugs in the branch below it, both now
fixed there: `batch_status`/`batch_cancel` were taught by the automation skill
but absent from `directTools`, and `tinyfish-authenticated` cited
`references/anti-bot.md` and `references/goals.md`, which live under
`tinyfish-automation` and so did not resolve from where that skill sits. The
second is inherited from `grok/`, which still has it.
Every check is negative-tested: each one was made to fire by introducing exactly
the regression it guards.
`pi-ci.yml` runs the validator plus tarball verification on PRs — pi-publish.yml
already checks the tarball, but only on push to main, so nothing was validating
`pi/` on the PR that breaks it.
The second job installs pi and `pi-mcp-adapter` the way a user does, registers
the package, and asserts the adapter resolves server `tiny-fish_pi__tinyfish`
with `directTools` intact. That is the contract the skills are written against
and it lives in someone else's package, so a silent upstream change to the name
derivation should break our build rather than our users. No model, no
credentials, no network calls to us — deterministic and free.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CBf5rnVYQYcxE8bLjfQuUP
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Essentials Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
|
Note on why Every CI workflow in this repo filters on Not a problem with the workflow, but it does mean GitHub hasn't executed it yet. I ran both jobs' exact commands locally instead: Worth a look at the first green |
Stacked on #42. Answers "is there a way to test that this package works?"
The package ships no code, so nothing here fails loudly. That is the whole problem:
filesentry → the tarball publishes and installs, just with skills missingdirectTools→ the model calls something never registeredNone of it surfaces until a user hits it. These checks make each one fail at PR time instead.
pi/test/validate.mjsDependency-free, runs locally as
node test/validate.mjs, excluded from the tarball.manifestpi.mcp/pi.skillspointing at missing paths; a droppedpi-packagekeyword, which is the entire gallery discovery mechanismmcptype: "http"creeping back (the adapter has no such field); the${VAR:-}interpolation form, which ships as a literal header value; empty or duplicateddirectToolsskills.mdreferences that do not resolveskills-vs-directToolsfilesfilesentry, ortest/leaking into the tarballEvery check is negative-tested — each was made to fire by introducing exactly the regression it guards, then reverted.
It found two real bugs, both fixed in the branches below
batch_status/batch_cancelwere taught by the automation skill but missing fromdirectTools— a model following that skill would have called tools that never registered. Fixed in feat(pi): package scaffold and MCP registration (PF-3852) #40 (now 10 tools).tinyfish-authenticatedcitedreferences/anti-bot.mdandreferences/goals.md, which live undertinyfish-automationand so did not resolve from where that skill sits. Fixed in feat(pi): TinyFish skills and README (PF-3852) #41 to use resolvable../tinyfish-automation/...paths.grok/still has this one — worth a separate look, not touched here.That is two bugs in a package I had already verified by hand in a live pi session, which is the argument for the checks existing.
pi-ci.ymlTwo jobs.
validate— runs the validator plus tarball verification on PRs.pi-publish.ymlalready verifies the tarball, but only on push tomain, so nothing was validatingpi/on the PR that breaks it.install— installs pi andpi-mcp-adapterthe way a user does, registers the package, and asserts the adapter resolves servertiny-fish_pi__tinyfishwithdirectToolsintact. That is the contract the skills are written against, and it lives in someone else's package: if the adapter changes how it derives server names, that should break our build rather than our users. No model, no credentials, no network calls to us — deterministic and free. Verified locally by running the job's exact commands.Deliberately not covered
Validating
directToolsnames against the live MCP server'stools/listwould catch product-side drift — a server-side rename silently stops a tool registering. It needs a TinyFish API key, and this repo has no such secret (ux-labs usesMINO_PROD_API_KEY). Worth a scheduled job later; flagging rather than half-building it.🤖 Generated with Claude Code
https://claude.ai/code/session_01CBf5rnVYQYcxE8bLjfQuUP