8.5 KiB
Design: Project Map Prompt Injection
Status
| Field | Value |
|---|---|
| Phase | Design |
| Based on | Spec |
| Next | Tasks |
Design summary
This change adds a runtime guidance layer on top of the paired map/index artifact system. The implementation should not redesign map generation or retrieval. Instead, it should add a well-scoped injection pipeline that:
- emits honest startup hints before init,
- preloads the root pair after init,
- expands under a hybrid budget,
- avoids redundant reinjection by scanning real outgoing context,
- varies guidance strength through explicit modes,
- proves correctness with integration-heavy validation.
Affected areas
Source files likely to change
pi-extension.ts- shared config handling (
src/config.tsor equivalent) - runtime helpers for map/index discovery and injection selection
- tests covering extension lifecycle and per-turn behavior
- docs/runtime guidance surfaces if needed
New modules likely to appear
src/prompt-injection.tsor equivalent runtime helper- optional helper for canonical marker construction / detection
- optional helper for token-budget estimation across paired artifacts
Architecture changes
1. Injection policy helper
Centralize prompt-injection logic in one helper rather than scattering it across hooks.
Suggested responsibilities:
- determine current mode (
off/advisory/strong/strict), - detect whether artifacts exist,
- build pre-init startup hint,
- build post-init root-pair payload,
- estimate expansion budget,
- choose additional artifacts under the budget,
- construct a canonical injected marker/block,
- scan outgoing context or payload for that marker,
- decide whether reinjection is required.
This helper is the main guard against drift between startup hints, context hooks, and strict-mode checks.
2. Injection surfaces
Use different extension surfaces for different responsibilities.
Pre-init / startup hint
Use before_agent_start for lightweight startup guidance before real artifacts exist.
Required behavior:
- inject only a hint,
- tell the agent to run
project_map_init, - keep the hint visible and inspectable.
Post-init root-pair preload
Use before_agent_start to guarantee the initial post-init root-pair preload for a prompt.
Required behavior:
- inject root
.pi-map.index.md, - inject root
.pi-map.md, - optionally append brief protocol text only if needed by the selected mode.
Relevant-turn reinjection
Use context for relevant-turn checks.
Required behavior:
- inspect
event.messages, - decide whether the canonical block is already present,
- only add the root pair / budgeted expansion if absent,
- avoid rescanning on every trivial turn in
strongmode.
Payload fallback
Use before_provider_request only as a fallback or debugging surface when message-layer detection is insufficient.
3. Canonical marker design
Deduplication depends on stable canonical detection.
The implementation should stamp injected content with a canonical marker block.
Recommended v1 shape:
- a deterministic wrapper such as
<!-- PI_MAP_ROOT_PAIR_START -->/<!-- PI_MAP_ROOT_PAIR_END -->, - normalized artifact identity lines for root
.pi-map.index.mdand root.pi-map.md, - trust-boundary text within the same wrapped block when the active mode requires it.
Marker rules:
- stable across turns,
- independent of provider formatting quirks,
- easy to scan in both
event.messagesand final provider payload, - robust enough that root-pair presence can be detected without brittle full-text matching.
4. Budgeting
Budgeting should be deterministic and layered.
Context-window discovery and fallback
- Prefer active-model context-window metadata exposed by Pi runtime/model selection.
- If context-window metadata is unavailable, fall back to the configured absolute cap.
- The fallback path should be explicit in logs/debug behavior so budget decisions remain auditable.
Required order
- compute effective budget from relative percentage + optional absolute cap,
- reserve the root pair first,
- expand outward using a deterministic traversal order,
- stop when the budget would be exceeded.
Traversal strategy
The spec does not force exact traversal heuristics, but the design should prefer:
- root pair first,
- shallow structural coverage before deep leaves,
- predictable order over opaque scoring.
This keeps automatic injection understandable and auditable.
5. Mode control surface
Expose a config/runtime setting for the four modes.
Because the current project config is loaded from flat JSON in .pi-project-map.json, v1 should prefer a flat compatible shape rather than forcing an immediate nested/YAML migration.
Suggested v1 config shape:
{
"promptInjectionMode": "strong",
"contextBudgetPercent": 15,
"contextBudgetMaxTokens": 100000
}
Migration note:
- keep existing flat JSON loading in
src/config.ts, - treat these as new additive keys,
- decide explicitly whether existing
contextBudgetis deprecated, ignored for injection, or retained only for older LLM-analysis paths.
Optional runtime UX may later mirror thinking-level controls, but v1 implementation can start with config-driven mode selection as long as the semantics are the same.
6. Mode semantics
off
- no automatic artifact injection,
- no startup/init hint beyond existing tool/docs discovery.
advisory
- startup/init hints enabled,
- optional root-pair preload,
- light reminders,
- weaker reinjection behavior.
strong
- root-pair preload required,
- budgeted expansion required,
- relevant-turn reinjection checks required,
- reminders before edits and architecture-sensitive reasoning.
strict
- everything in
strong, plus: - when protocol path is missing during sensitive actions, require explicit bypass justification.
7. Relevant-turn detection
strong mode should not rescan on every turn.
Relevant-turn triggers should be mapped to concrete runtime signals where possible:
- agent start,
- edit intent / edit tool preparation,
- architecture-sensitive planning prompts,
- compaction completion,
- root-pair artifact change detection.
This will likely require some combination of:
- hook-local heuristics,
- observed tool calls,
- file timestamp/hash checks for root artifacts,
- compaction event handling.
8. Visibility model
The design should preserve mixed visibility.
- startup hints: visible and inspectable,
- raw injected artifact blocks: agent-visible by default,
- the fact that automatic injection exists should remain discoverable.
The implementation may use hidden custom message types for artifact payloads, but should not make startup/init behavior opaque.
9. Validation strategy
This change is validation-heavy.
Unit tests alone are not enough, because the main risk is runtime interaction between hooks, message mutation, compaction, and reinjection.
Integration focus areas
- startup before init,
- startup after init,
- root-pair marker insertion,
- reinjection suppression when marker already exists,
- reinjection after compaction,
- reinjection after artifact mutation,
- mode differences,
- strict-mode bypass path,
- mixed visibility expectations,
- synthetic event-sequence coverage for relevant-turn heuristics such as edit-intent, architecture-sensitive reasoning, compaction, and artifact invalidation.
10. Documentation impact
Runtime guidance docs must align with the spec, but retrieval docs remain separate.
Docs should teach:
- startup hint before init,
- root-pair automatic preload after init,
- trust boundary,
- mode ladder,
- relevant-turn reinjection behavior,
- integration-test importance.
Risks
| Risk | Mitigation |
|---|---|
| Message-level scanning misses provider serialization quirks | Add payload fallback via before_provider_request |
| Root-pair marker becomes brittle | Use deterministic boundaries and normalized artifact identity lines |
| 15% + 100k is too aggressive in some fleets | Keep both knobs configurable and document the opinionated default |
| Relevant-turn detection becomes fuzzy | Centralize detection heuristics and prove them with integration tests |
strict mode causes friction |
Keep strong as default and isolate strict-only bypass behavior |
Settled defaults
- Root pair is always guaranteed after init.
- Reinjection avoidance is based on canonical outgoing-context scanning.
- Retrieval remains out of scope.
- Mixed visibility is the intended baseline.
- Four modes exist, with
strongas default. - Default budget is 15% of active context window, capped at 100k tokens.