Skip to content

v3.21.6

Latest

Choose a tag to compare

@Jaggerxtrm Jaggerxtrm released this 03 Sep 15:41

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 — no dist/ or src/ 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.extensions is now a source-string map. Keys are trusted executable sources; only reviewed config files may set them.
  • gitnexus: false opts out of the default GitNexus MCP injection. serena is retired and ignored (any value is accepted for legacy configs but has no effect). Every other key with true is forwarded to Pi as a repeated -e <source> argument in insertion order; false/null skips 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 canonical npm:@jaggerxtrm/pi-service-knowledge@1.10.0 plus a floating npm:@scope/pkg) before Pi spawns; fix by aligning to the exact pinned spec.
  • Remote sources (npm:, git:, http:, https:) omit --offline for the entire Pi invocation; local-only runs retain --offline.
  • See src/pi/session.ts:resolveExecutionExtensionSelection, docs/pi-session.md, and docs/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-tools and appends the bundled extension policy extension last (-e policy). 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 --tools allowlist (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-task never emits unresolved template placeholders (e.g. literal $bead_id or $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_sets is now a user-selectable field: null inherits package defaults, [] clears specialist-specific sets (required/default index sets still load), and a non-empty array replaces them. mandatory_rules.inline_rules and mandatory_rules.disable_default_globals remain 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-rules reflects true layered merge with runtime parity for required/default sets.
  • See docs/overrides-guide.md and config/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-sync binds to a project-pack skill directory (.xtrm/skills/<pack>/service-knowledge/ with service-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_failed without 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 --tools for a requested tier. Reinstall or rebuild the Specialists package if config/catalog/index.json is unavailable.

Doctor fail-safes

  • sp doctor --specialists survives malformed global ~/.config/specialists/user.json and surfaces guidance instead of crashing.

Compatibility notes

  • Serena extension injection and the serena-pool pre-spawn hook remain retired. execution.extensions.serena is accepted for legacy files but ignored.
  • sp list-rules --json and sp view now reflect the layered mandatory-rules state described above.
  • sp serve remains READ_ONLY and rejects skills.scripts; sp script may opt in via --allow-local-scripts and --allow-write-capable for trusted single-tenant callers only.

Known limits

  • Host-read waiver (3.21.6): --allow-skills and --allow-skills-roots do 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-sync 1.10.0, coordinated Core heads ef14bf44030ee6cd02d4dd21f0856f067baf54f3/f683f5f6172bdb7ab4a7b7324b7feabd9b918b31 as validation evidence (not a published compatibility guarantee).

Verification

  • bun run changelog:check passes; bun run lint (tsc --noEmit) passes where defined. No dist/ or src/ edits, no tag, and no publish were performed in this campaign. Behavior claims above were verified against src/pi/session.ts, docs/pi-session.md, docs/overrides-guide.md, docs/specialists-service.md, docs/authoring.md, and sp --help output for the linked 3.21.6 runtime.