Files
pygienium/AGENTS.md
Michael Freno 6213281b3c fix: give sub-agents the provider their pinned model needs
Sub-agent sessions are created with `noExtensions: true`, which also
removes every provider an extension registered through
`pi.registerProvider` from the sub-session's own ModelRuntime. Since
bff187d pinned sub-agents to the invoking session's model, every check
depends on a provider registration it deliberately does not load, so
scans died in about 20ms with "No API key found for neuralwatt" on a
perfectly healthy login — the key was in auth.json, the provider simply
did not exist in that session's runtime.

Thread the invoking session's registry down to the runner and
re-register just the pinned model's provider there, through an inline
extension factory: inline factories load regardless of `noExtensions`,
so the sub-agent authenticates exactly as the host does while every
other extension stays out of its scope. Registrations are narrowed once
at the extension entry point (`asProviderRegistry`) and relayed
untouched — a native provider keeps its own stream and auth wiring.

The generated omp port keeps its isolation: it disables extension
discovery and has no extension registrations to forward, so it carries
the same shapes with a stub for the helper.

Tests: new tests/provider-forwarding.test.ts pins the narrowing and the
relay (native wins over config-only, nothing forwarded for a built-in);
it fails on the previous tree, where the helper does not exist. Full
suite 162 pass with one pre-existing failure (MISC-46, worktree-only).
bun run typecheck clean; port-to-omp regenerates and typechecks.

MISC-45

Co-Authored-By: nw-flash-flex <noreply@neuralwatt.com>
2026-10-20 17:43:54 -04:00

3.0 KiB

AGENTS.md

Pygienium is a pi extension: code-hygiene checks that scan a target with isolated sub-agent sessions (analysis), optionally apply fixes, then verify artifacts. Sub-agents are defined as markdown in agents/*.md (YAML frontmatter: name, allowedTools; body = system prompt).

Commands

  • bun run typecheck — tsc --noEmit on src/
  • bun test — full suite (bun test)

Layout

  • src/checks/ — check definitions; self-register on import (registerCheck)
  • src/agent-runner.ts — spawns sub-agent sessions; runner injectable (setAgentRunner), tests use fakeAgentRunner (no real model calls)
  • src/commands.ts — slash-command handlers, exported for direct test invocation with a stub PygieniumCtx
  • tests/ — bun tests; stub ctx with { cwd, mode: "print", hasUI: false, ui: undefined } as PygieniumCtx
  • port-to-omp.mjs — regenerates the self-contained omp port (see commit process)

Conventions

  • Checks: gate (skip reason), buildScanTask, optional buildFixTask, optional verify. Scan tasks embed !write/!echo lines as deterministic fallback for the fake runner.
  • Sub-agent sessions must be pinned to the invoking session's model: thread ctx.model through PygieniumCtx → run options → AgentTaskOptions.model → createAgentSession({ model }).
  • A pinned model needs its provider too: a provider an extension registered (pi.registerProvider) exists only in the invoking ModelRegistry, and the sub-session runs noExtensions, so thread ctx.modelRegistry (narrowed by asProviderRegistry) through the same chain to AgentTaskOptions.modelRegistry → providerForwardingExtension, which re-registers that one provider through an inline factory. Drop that link and every check dies with No API key found for <provider>.
  • Keep files modular; no compatibility shims.

Commit process (IMPORTANT)

Commits are gated by the pre-commit hook (enable: git config core.hooksPath .githooks). It regenerates the omp port into a temp dir and typechecks it — exactly what CI runs. A failing hook blocks the commit; never bypass with --no-verify.

port-to-omp.mjs rewrites source via exact-string matchers (FILE_RULES). Editing these files requires keeping the matching ops in sync or the port regeneration throws and the commit is blocked:

  • src/index.ts — removes mode: ctx.mode from the pygieniumCtx literal
  • src/commands.ts — removes mode from the PygieniumCtx Pick; swaps ctx.mode for ctx.hasUI in print
  • src/agent-runner.ts — swaps the SDK import + loader for the omp SDK's createAgentSession options (toolNames, systemPrompt, agentRegistry, …); reduces ProviderRegistry to an SDK-free shape and stubs providerForwardingExtension (the port disables extension discovery, so it has nothing to forward)
  • src/agents.ts — find → glob

After touching any of those, run bun port-to-omp.mjs --out <tmp> and (cd <tmp> && bun run typecheck) before committing; the hook does the same.