v3.21.6 — Extension trust, tool-gate hardening, and service-knowledge project packs
Package: @jaggerxtrm/specialists · Version: 3.21.6 · Runtime: pi 3.21.6 (linked via sp --help; invoked for help text only)
Feeds release-notes bead
xtrm-j8kcj.5. Narrative only — nodist/orsrc/changes.
Summary
3.21.6 is a trust-boundary and fail-closed hardening release. Dynamic extension sources, deny-list tool gating, prompt integrity, RPC lifecycle, mandatory-rules overlays, traversal containment, service-knowledge project-pack binding, pre-script handling, tool-catalog resolution, and doctor resilience all move to explicit fail-closed semantics. No new user-facing commands are added; previously shipped surfaces remain compatible. The bounded host-read waiver for sp script/sp serve remains in effect and expires at 3.21.7.
Dynamic extension sources
execution.extensionsis now a source-string map. Keys are trusted executable sources; only reviewed config files may set them.gitnexus: falseopts out of the default GitNexus MCP injection.serenais retired and ignored (any value is accepted for legacy configs but has no effect). Every other key withtrueis forwarded to Pi as a repeated-e <source>argument in insertion order;false/nullskips the source.- Per-key merge across package, global, and repo layers preserves siblings. Fail-closed duplicate detection rejects two distinct
npm:keys for the same package (for example a pinned canonicalnpm:@jaggerxtrm/pi-service-knowledge@1.10.0plus a floatingnpm:@scope/pkg) before Pi spawns; fix by aligning to the exact pinned spec. - Remote sources (
npm:,git:,http:,https:) omit--offlinefor the entire Pi invocation; local-only runs retain--offline. - See
src/pi/session.ts:resolveExecutionExtensionSelection,docs/pi-session.md, anddocs/overrides-guide.md.
Deny-list tool gate and fail-closed active-tool policy
- Configured extension sources are not equivalent to active tools. At
session_start, the runtime advertises only the intersection of the requested permission tier and runtime-confirmed healthy extension tools. - With extension sources enabled, the launch uses
--no-builtin-toolsand appends the bundled extension policy extension last (-epolicy). The policy re-activates only the granted natives plus every tool registered by the enabled sources. Native restrictions stay fail-closed: anything not explicitly granted is never activated, and Pi rejects inactive tools at call time. - Without extension sources, the launch keeps the strict
--toolsallowlist (byte-identical legacy behavior). - Hard-fail: if extension sources are enabled and the bundled policy artifact is missing, the launch aborts with guidance to reinstall or rebuild the package. Warn-and-continue is never used.
Prompt-integrity fixes
render-tasknever emits unresolved template placeholders (e.g. literal$bead_idor$pre_script_output). Missing placeholder data now surfaces as an error rather than a silent literal.- Every turn-1 initial prompt carries the exact bead id, preventing drift when prompt variables are unset.
RPC fail-fast
- Pending Pi RPC calls are rejected immediately when the Pi child exits, rather than hanging until timeout. This closes the window where a dead child masked a launch failure as a stall.
Mandatory-rules template_sets and overlay hardening
mandatory_rules.template_setsis now a user-selectable field:nullinherits package defaults,[]clears specialist-specific sets (required/default index sets still load), and a non-empty array replaces them.mandatory_rules.inline_rulesandmandatory_rules.disable_default_globalsremain package-canonical only and are blocked at global/repo layers.- Overlays validate kebab-case and path containment for set ids before merge, and
sp list-rulesreflects true layered merge with runtime parity for required/default sets. - See
docs/overrides-guide.mdandconfig/mandatory-rules/README.md.
Traversal containment
- Mandatory-rules set ids and service-knowledge pack discovery enforce path containment: symlinked, escaping, unreadable, or malformed candidates fail instead of falling back.
Service-knowledge binding, pinning, and project-pack resolution
service-knowledge-syncbinds to a project-pack skill directory (.xtrm/skills/<pack>/service-knowledge/withservice-registry.json/services/) rather than a stale global install. Shared executable machinery remains at.xtrm/skills/default/service-knowledge/scripts/; the runtime does not copy scripts into each pack umbrella.- Resolution is deterministic and fail-closed: one matching pack wins; multiple matches fail as ambiguous; malformed/unreadable/symlinked/escaping candidates fail; zero matches permit the home/global fallback chain. Direct/script paths are canonicalized against canonical allowed roots before Pi starts.
- The service-knowledge extension source is pinned to an exact reviewed npm spec; floating or range specs are rejected.
Pre-script fail-fast and output bounds
- Required pre-scripts are fail-fast: failures return
pre_script_failedwithout model fallback or retry. Both raw and rendered preflight output are bounded before bead or prompt inclusion.
Runtime tool-catalog fail-closed
- Tool catalog resolution is fail-closed across tracked, script, serve, MCP, and pipeline paths. A missing, unreadable, malformed, or empty catalog aborts before Pi or model startup. The runtime never omits
--toolsfor a requested tier. Reinstall or rebuild the Specialists package ifconfig/catalog/index.jsonis unavailable.
Doctor fail-safes
sp doctor --specialistssurvives malformed global~/.config/specialists/user.jsonand surfaces guidance instead of crashing.
Compatibility notes
- Serena extension injection and the
serena-poolpre-spawn hook remain retired.execution.extensions.serenais accepted for legacy files but ignored. sp list-rules --jsonandsp viewnow reflect the layered mandatory-rules state described above.sp serveremainsREAD_ONLYand rejectsskills.scripts;sp scriptmay opt in via--allow-local-scriptsand--allow-write-capablefor trusted single-tenant callers only.
Known limits
- Host-read waiver (3.21.6):
--allow-skillsand--allow-skills-rootsdo not create a filesystem read boundary. Allowed tools, extensions, MCP processes, and child processes can still read paths visible to the runtime identity. 3.21.6 permits only trusted single-tenant callers with private authenticated ingress, a dedicated container or OS account, minimal mounts, least-privilege credentials, trusted definitions, and reviewed extension sources. Untrusted, public, cross-tenant, and multi-tenant deployments are excluded. The waiver does not authorize publication and expires at 3.21.7, when host-read isolation is expected to be re-evaluated. - Package/version:
@jaggerxtrm/specialists@3.21.6,service-knowledge-sync1.10.0, coordinated Core headsef14bf44030ee6cd02d4dd21f0856f067baf54f3/f683f5f6172bdb7ab4a7b7324b7feabd9b918b31as validation evidence (not a published compatibility guarantee).
Verification
bun run changelog:checkpasses;bun run lint(tsc --noEmit) passes where defined. Nodist/orsrc/edits, no tag, and no publish were performed in this campaign. Behavior claims above were verified againstsrc/pi/session.ts,docs/pi-session.md,docs/overrides-guide.md,docs/specialists-service.md,docs/authoring.md, andsp --helpoutput for the linked 3.21.6 runtime.