verification.ts: added a structuredTEST_DISCIPLINE_RULESset and renders it as a dedicated### Test Disciplinesubsection inside## Verification.- Added semantic rule coverage under
test/suite/prompt-verification-discipline.test.ts, avoiding raw prompt sentence pinning while still checking that the structured rule set is injected.
- The shared verification prompt did not tell agents how to handle test code specifically. That left room for flaky waits, fixed sleep-based async tests, over-isolated mocks, and prompt tests that merely assert current prompt text.
- The new rules live in
verification.tsbecause they define validation quality, not model-family tuning.
- This is shared base-prompt behavior for every preset and fallback prompt. Per-extension prompt riders would apply too late or only in specific extension configurations.
- LOW:
verification.tsif upstream rewrites the V1/V2/V3 verification section.
agent-session.ts:_rebuildSystemPrompt()callsbuildDynamicSystemPrompt()instead ofbuildSystemPrompt(). References toloaderSystemPrompt(SYSTEM.md) andloaderAppendSystemPrompt(APPEND_SYSTEM.md) removed.resource-loader.ts: Removed SYSTEM.md / APPEND_SYSTEM.md discovery, loading, override, and storage.getSystemPrompt()returnsundefined,getAppendSystemPrompt()returns[]. Interface methods kept for compatibility.- New directory
dynamic-prompt/with 7 files:types.ts— AvailableTool interfacetool-categorization.ts— categorizeTools(), getToolsPromptDisplay()intent-gate.ts— Phase 0 intent gate with dynamic key triggerstool-section.ts— Categorized tool display with snippets and guidelinespolicies.ts— Hard blocks and anti-patternsbuild.ts— buildDynamicSystemPrompt() assemblerindex.ts— re-exports
- Replace static pi default prompt with dynamic prompt that adapts to registered tools
- Add intent classification gate (Phase 0) to system prompt
- Remove SYSTEM.md / APPEND_SYSTEM.md file-based prompt overrides
The base prompt itself (what _rebuildSystemPrompt produces) needed replacement. Extensions can only modify it per-turn via before_agent_start, not replace the default builder.
agent-session.ts— 1 import changed, ~6 lines removed in_rebuildSystemPrompt()resource-loader.ts— ~77 lines removed (SYSTEM.md/APPEND_SYSTEM.md machinery)
agent-session.tsline ~904: thebuildSystemPrompt()call. Resolution: keepbuildDynamicSystemPrompt(), update args if upstream adds new parameters.resource-loader.ts:reload()method near line 450. Resolution: drop any new SYSTEM.md/APPEND_SYSTEM.md code upstream adds.
build.ts: Hero line changed from coding-specific ("expert coding assistant operating inside pi") to generic ("You are a helpful assistant."). Two supporting coding-context lines removed.types.ts:AvailableTool.categoryunion narrowed from 6 to 4 values (removed"lsp"|"ast").tool-categorization.ts: Removedlsp_andast_grepprefix detection ingetToolCategory(). Removedlsp_*andast_grepentries fromgetToolsPromptDisplay().tool-section.ts: Removed"lsp"and"ast"fromCATEGORY_ORDERandCATEGORY_LABELS.- Tests updated:
build.test.ts,tool-categorization.test.ts,intent-gate.test.ts,tool-section.test.ts— all lsp/ast-specific test cases removed or converted.
- System prompt should be domain-agnostic (not coding-specific).
- LSP and AST tool categories are not used in this fork's tool set.
These are core type definitions and prompt builder internals, not per-turn modifications.
All changes are within the dynamic-prompt/ directory which is already a fork modification.
types.ts: If upstream adds the"lsp" | "ast"categories. Resolution: keep narrowed union.tool-categorization.ts,tool-section.ts: If upstream references lsp/ast categories. Resolution: drop those references.
intent-gate.ts: Replaced "verbalize intent" wording with an internal-only routing step.intent-gate.ts: Added explicit guardrails to avoid exposing prompt scaffolding such as "Thinking level", "Step 0", or XML tool-call examples in user-facing output.test/dynamic-prompt/intent-gate.test.ts: Updated coverage to assert the internal-only wording.test/dynamic-prompt/build.test.ts: Added regression coverage to keep the assembled prompt from reintroducingI detect ...scaffolding.
- Gemini 3.1 Pro preview with MorphXML-style tool calling could echo prompt scaffolding into normal assistant output.
- The prior instruction explicitly asked the model to verbalize its routing decision, which encouraged user-visible leakage of internal planning text.
intent-gate.ts: Reversed the 2026-04-10 "internal-only" guard. The intent gate now requires the model to emit a one-line routing line in the formatI read this as [intent] - [plan].before acting. The guard against narrating prompt scaffolding ("Step 0", "Thinking level", XML examples) is preserved; only the routing line itself is mandated.build.ts: Replaced the"You are a helpful assistant."opener with a senpi identity section. Added five new reusable sections to the assembled prompt: identity, parallel tool calls, exploration discipline, verification rigor (V1/V2/V3 tiers), and style. Added an optionaltuningSectionfield for per-model addenda.- New files in
dynamic-prompt/:identity.ts,parallel-tools.ts,exploration.ts,verification.ts,style.ts. Each exports a singlebuild*Section()function consumed bybuild.tsand re-exported fromindex.ts. test/dynamic-prompt/intent-gate.test.tsandtest/dynamic-prompt/build.test.ts: Updated to assert the verbalization mandate and the new sections.
- The default fallback prompt was producing weak, generic-LLM-bot output ("You are a helpful assistant." with bare intent gate, tool list, and policies). The README already advertised forced intent verbalization, but the code contradicted it. Strengthening the default reconciles README and code, and gives every model that lacks a preset a strong neutral senpi prompt.
- The 2026-04-10 leakage fix was a Gemini-specific patch applied as a global silencer. The proper place for that patch is a Gemini-specific overlay (or a per-model preset), not the shared default. Revoking it here while preserving the "do not narrate prompt scaffolding" guard restores the verbalization for every other model.
- The bold parallel-tool-calls section ("if a directory or symbol is even loosely relevant to the request, run
grep,ls, andreadin parallel") was missing entirely. Adding it makes the default suitable for agentic use without falling back to model-specific presets.
These are core builder internals and the shared shape of every prompt the agent emits in the absence of a preset. Extensions can only inject before/after a turn; they cannot replace the default builder.
All changes are within the existing dynamic-prompt/ directory.
intent-gate.ts: If upstream re-introduces an "internal only" routing rule. Resolution: keep the verbalization mandate; reapply any additional anti-leakage guard on top of it.build.ts: If upstream rewrites the assembly. Resolution: keep the senpi identity and the new section calls.
extensions/builtin/prompt-preset/: Deleted the three persona-named preset files. Replaced with model-named files:claude-opus.ts,kimi-k2-6.ts,gpt-5.ts. Each new preset is a thin wrapper that callsbuildDynamicSystemPromptwith a smalltuningSectioncarrying only the model-specific notes.presets.ts: Renamed theis*Modelhelpers to model-family-named functions (isGpt5FamilyModel,isClaudeOpusModel). SplitresolvePresetintoresolvePresetName(cheap, used by the startup header) andresolvePreset(builds the full prompt). Settings overrides accept the new model-named values.settings.ts:PromptPresetNameis now"auto" | "claude-opus" | "kimi-k2-6" | "gpt-5".index.ts(extension wiring): Passes the fullBuildDynamicSystemPromptOptions(includingcwd,contextFiles,skills) through to the preset builders so presets reuse the strengthened default.- All three
test/suite/prompt-presets-*.test.tsfiles: Updated assertions to match the new preset names and the senpi-neutral identity.
- Senpi is a neutral coding agent. Persona-named presets collapsed identity into specific personas and made model selection hard to reason about. Naming presets after the model family they target makes the link from
--modelto active preset obvious. - The old presets duplicated identity, intent, exploration, and verification language. Each was 100+ lines of mostly-shared content. The new architecture (default carries the shared behavior, preset carries only the model-specific tuning) cuts each preset to ~10 lines and keeps tuning easy to review.
Preset selection is wired through a builtin extension that already lives in this directory. The rename touches that extension's settings, selector, and tests as a single unit.
All changes are within extensions/builtin/prompt-preset/ and the matching tests under test/suite/.
presets.ts,settings.ts: If upstream renames or reshapes the preset settings. Resolution: keep the model-named taxonomy.