docs(prompt): align prompt injection guidance and runtime copy
This commit is contained in:
@@ -33,12 +33,76 @@ Read actual source, tests, config, and docs before editing or making exact runti
|
|||||||
|
|
||||||
**Trust boundary:** index routes, map orients, source decides.
|
**Trust boundary:** index routes, map orients, source decides.
|
||||||
|
|
||||||
### Retrieval
|
## Prompt Injection Policy
|
||||||
|
|
||||||
|
The Pi extension can automatically inject lightweight project-map guidance into the agent context according to the configured `promptInjectionMode`.
|
||||||
|
|
||||||
|
### Before init
|
||||||
|
When no `.pi-map.md` / `.pi-map.index.md` artifacts exist, only a visible startup hint is injected. It tells the agent that the project-map extension is active and to run `project_map_init`. No synthetic or fake map content is ever injected before real artifacts exist.
|
||||||
|
|
||||||
|
### After init
|
||||||
|
Once real artifacts exist, the runtime guarantees that the root pair is loaded before any budgeted expansion:
|
||||||
|
|
||||||
|
- root `.pi-map.index.md`
|
||||||
|
- root `.pi-map.md`
|
||||||
|
|
||||||
|
Additional directory pairs are expanded only while the configured context budget allows, in shallow-first order.
|
||||||
|
|
||||||
|
### Trust boundary
|
||||||
|
Injected maps and indexes are navigation and orientation aids, not final authority:
|
||||||
|
|
||||||
|
> **index routes, map orients, source decides**
|
||||||
|
|
||||||
|
If an injected artifact and the source disagree, source wins. Always verify critical behavior from source before editing or making exact runtime claims.
|
||||||
|
|
||||||
|
### Mode ladder
|
||||||
|
- `off`: no automatic injection beyond existing tool/docs discovery.
|
||||||
|
- `advisory`: inject startup/init hints and allow optional root-pair preload; use light reminders.
|
||||||
|
- `strong` (default): inject the root pair, expand under the configured budget, run reinjection checks on relevant turns, and remind before edits or architecture-sensitive reasoning.
|
||||||
|
- `strict`: same as `strong`, plus require an explicit bypass justification before sensitive edits or architectural claims when the protocol path is missing.
|
||||||
|
|
||||||
|
The **protocol path** is present when the outgoing context contains the canonical injected root-pair block and the trust-boundary instruction. In `strict` mode, sensitive actions without it are blocked unless the agent includes `[PI_MAP_BYPASS: <brief justification>]`.
|
||||||
|
|
||||||
|
### Context budget
|
||||||
|
The default budget is **15% of the active model context window**, capped at **100k tokens**. The smaller of the relative and absolute values wins. If the runtime cannot discover the active model's context window, it falls back to the absolute cap.
|
||||||
|
|
||||||
|
Configure it in `.pi-project-map.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"promptInjectionMode": "strong",
|
||||||
|
"contextBudgetPercent": 15,
|
||||||
|
"contextBudgetMaxTokens": 100000
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Retrieval
|
||||||
When you have a specific query (e.g. "authentication logic" or "routing metadata"):
|
When you have a specific query (e.g. "authentication logic" or "routing metadata"):
|
||||||
1. Run `project-map context <query>` or use the Pi tool `project_map_context`
|
1. Run `project-map context <query>` or use the Pi tool `project_map_context`
|
||||||
2. Read the returned **Context bundle** — it contains relevant indexes, maps, likely files, and symbols
|
2. Read the returned **Context bundle** — it contains relevant indexes, maps, likely files, and symbols
|
||||||
3. Always verify critical behavior from source before editing
|
3. Always verify critical behavior from source before editing
|
||||||
|
|
||||||
|
Retrieval via `project_map_context` (tool) or `project-map context` (CLI) remains a separate, on-demand path. Use it for targeted navigation when you have a specific query; automatic injection does not replace it.
|
||||||
|
|
||||||
|
### Integration-test expectations and known limitations
|
||||||
|
The implementation is validated by integration tests covering:
|
||||||
|
|
||||||
|
- pre-init hint behavior,
|
||||||
|
- post-init root-pair preload,
|
||||||
|
- budgeted expansion behavior,
|
||||||
|
- canonical-marker dedupe,
|
||||||
|
- reinjection after compaction,
|
||||||
|
- reinjection after root-pair artifact changes,
|
||||||
|
- mixed visibility behavior,
|
||||||
|
- guidance-mode differences,
|
||||||
|
- strict-mode bypass behavior.
|
||||||
|
|
||||||
|
Known limitations:
|
||||||
|
|
||||||
|
- Token estimation is best-effort (≈ 4 chars per token); actual provider token counts may differ.
|
||||||
|
- Relevant-turn detection uses explicit event types when available and falls back to heuristics on generic turns.
|
||||||
|
- Message-layer scanning is preferred; provider-payload serialization quirks require a fallback scan path.
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -64,10 +128,17 @@ Create `.pi-project-map.json` in the project root:
|
|||||||
"contextBudget": 4000,
|
"contextBudget": 4000,
|
||||||
"autoInjectPrompt": true,
|
"autoInjectPrompt": true,
|
||||||
"tagCap": 8,
|
"tagCap": 8,
|
||||||
"workflowHintCap": 5
|
"workflowHintCap": 5,
|
||||||
|
"promptInjectionMode": "strong",
|
||||||
|
"contextBudgetPercent": 15,
|
||||||
|
"contextBudgetMaxTokens": 100000
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- `promptInjectionMode`: `off`, `advisory`, `strong` (default), or `strict`.
|
||||||
|
- `contextBudgetPercent`: relative share of the active model context window used for automatic map/index injection.
|
||||||
|
- `contextBudgetMaxTokens`: hard absolute cap on the injection budget.
|
||||||
|
|
||||||
## Design
|
## Design
|
||||||
|
|
||||||
See [design-doc.md](design-doc.md) for the full specification.
|
See [design-doc.md](design-doc.md) for the full specification.
|
||||||
|
|||||||
@@ -41,6 +41,32 @@ Read actual source before editing or asserting exact behavior.
|
|||||||
|
|
||||||
**Trust boundary:** index routes, map orients, source decides.
|
**Trust boundary:** index routes, map orients, source decides.
|
||||||
|
|
||||||
|
## Prompt Injection Policy
|
||||||
|
|
||||||
|
This skill can automatically inject lightweight project-map guidance into your context. The behavior is controlled by `promptInjectionMode` in `.pi-project-map.json`.
|
||||||
|
|
||||||
|
### Before init
|
||||||
|
When no `.pi-map.md` / `.pi-map.index.md` artifacts exist, you see a visible startup hint telling you to run `project_map_init`. No synthetic map content is injected before real artifacts exist.
|
||||||
|
|
||||||
|
### After init
|
||||||
|
Once artifacts exist, the runtime guarantees that the root pair is loaded first:
|
||||||
|
|
||||||
|
- root `.pi-map.index.md`
|
||||||
|
- root `.pi-map.md`
|
||||||
|
|
||||||
|
Additional directory pairs may be added while the configured context budget allows.
|
||||||
|
|
||||||
|
### Mode ladder
|
||||||
|
- `off`: no automatic injection beyond existing tool/docs discovery.
|
||||||
|
- `advisory`: startup/init hints are shown; you may read the root pair manually when you want routing/orientation context.
|
||||||
|
- `strong` (default): the root pair is injected automatically, expansion stays within the context budget, and reinjection checks run on relevant turns (agent start, before edits, before architecture-sensitive reasoning, after compaction, after root-pair artifact changes).
|
||||||
|
- `strict`: same as `strong`, but before sensitive edits or architectural claims you must either have the protocol path in context or include an explicit bypass marker: `[PI_MAP_BYPASS: <brief justification>]`.
|
||||||
|
|
||||||
|
The **protocol path** means the outgoing context contains the canonical injected root-pair block and the trust-boundary instruction (`index routes, map orients, source decides`).
|
||||||
|
|
||||||
|
### Context budget
|
||||||
|
Default budget: **15% of the active model context window**, capped at **100k tokens**. The smaller of the relative and absolute values wins. If the runtime cannot discover the active model's context window, it uses the absolute cap.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Create `.pi-project-map.json` in the project root:
|
Create `.pi-project-map.json` in the project root:
|
||||||
@@ -48,10 +74,17 @@ Create `.pi-project-map.json` in the project root:
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"tagCap": 8,
|
"tagCap": 8,
|
||||||
"workflowHintCap": 5
|
"workflowHintCap": 5,
|
||||||
|
"promptInjectionMode": "strong",
|
||||||
|
"contextBudgetPercent": 15,
|
||||||
|
"contextBudgetMaxTokens": 100000
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- `promptInjectionMode`: `off`, `advisory`, `strong` (default), or `strict`.
|
||||||
|
- `contextBudgetPercent`: relative share of the active model context window to use for automatic map/index injection.
|
||||||
|
- `contextBudgetMaxTokens`: hard absolute cap on the injection budget.
|
||||||
|
|
||||||
## Agent Instructions
|
## Agent Instructions
|
||||||
|
|
||||||
When project map artifacts exist in the repo:
|
When project map artifacts exist in the repo:
|
||||||
@@ -61,7 +94,8 @@ When project map artifacts exist in the repo:
|
|||||||
3. Read the local `.pi-map.md` plus source before editing
|
3. Read the local `.pi-map.md` plus source before editing
|
||||||
4. Run `project-map patch <path>` after editing source
|
4. Run `project-map patch <path>` after editing source
|
||||||
5. Run `project-map validate` before freshness-sensitive architectural decisions
|
5. Run `project-map validate` before freshness-sensitive architectural decisions
|
||||||
6. For **targeted navigation**, use `project_map_context` (Pi tool) or `project-map context` (CLI) with a natural-language query. It returns a compact markdown bundle with the strongest-match indexes, maps, likely files, and symbols.
|
6. In `strict` mode, include `[PI_MAP_BYPASS: <brief justification>]` only when you deliberately need to proceed without the protocol path
|
||||||
|
7. For **targeted navigation**, use `project_map_context` (Pi tool) or `project-map context` (CLI) with a natural-language query. It returns a compact markdown bundle with the strongest-match indexes, maps, likely files, and symbols.
|
||||||
|
|
||||||
## Retrieval Model
|
## Retrieval Model
|
||||||
|
|
||||||
|
|||||||
+63
-5
@@ -252,6 +252,39 @@ The LLM client's response is parsed to extract `PURPOSE`, `DEPS`, `CONCEPTS`, `R
|
|||||||
2. For architecture/system or ambiguous tasks, agent also reads the root `.pi-map.md`.
|
2. For architecture/system or ambiguous tasks, agent also reads the root `.pi-map.md`.
|
||||||
3. Agent does **not** preload every directory map by default.
|
3. Agent does **not** preload every directory map by default.
|
||||||
|
|
||||||
|
In the Pi extension, this session-start consumption is assisted by automatic prompt injection:
|
||||||
|
|
||||||
|
- **Before init**: only a lightweight visible startup hint is injected, telling the agent to run `project_map_init`. No synthetic map content is injected.
|
||||||
|
- **After init**: the root pair (`.pi-map.index.md` + `.pi-map.md`) is guaranteed to be preloaded automatically. Additional directory pairs are expanded only while the configured context budget allows.
|
||||||
|
|
||||||
|
### Automatic Prompt Injection
|
||||||
|
|
||||||
|
The Pi extension uses event hooks (`before_agent_start`, `context`, etc.) to maintain guidance context.
|
||||||
|
|
||||||
|
- The **mode ladder** controls how much is injected:
|
||||||
|
- `off`: no automatic injection.
|
||||||
|
- `advisory`: visible startup/init hints and optional root-pair preload.
|
||||||
|
- `strong` (default): root pair + budgeted expansion + relevant-turn reinjection checks.
|
||||||
|
- `strict`: same as `strong`, plus explicit bypass justification for sensitive edits/architectural claims when the protocol path is missing.
|
||||||
|
- The **protocol path** requires both the canonical injected root-pair block and the trust-boundary instruction (`index routes, map orients, source decides`) to be present in outgoing context.
|
||||||
|
- **Reinjection avoidance** scans actual outgoing messages (and falls back to provider payload) for a stable canonical marker before adding the root pair again.
|
||||||
|
- **Relevant-turn triggers** are: agent start, before edits, before architecture-sensitive reasoning, after compaction, and after root-pair artifact changes.
|
||||||
|
- **Visibility** is mixed: startup/init hints are user-visible; raw injected artifact blocks are agent-visible by default.
|
||||||
|
|
||||||
|
### Context Budget
|
||||||
|
|
||||||
|
Default automatic-injection budget: **15% of the active model context window**, capped at **100k tokens**. The smaller of the relative and absolute values wins. If the runtime cannot discover the active model's context window, it falls back to the absolute cap.
|
||||||
|
|
||||||
|
Configurable via `.pi-project-map.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"promptInjectionMode": "strong",
|
||||||
|
"contextBudgetPercent": 15,
|
||||||
|
"contextBudgetMaxTokens": 100000
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### During Session
|
### During Session
|
||||||
- Use directory indexes first to decide what to open next.
|
- Use directory indexes first to decide what to open next.
|
||||||
- For **targeted queries**, run `project_map_context` (tool) or `project-map context` (CLI). The retrieval engine scores all paired metadata and returns a compact markdown bundle with the top-3 strongest matches: indexes, maps, likely files, and symbols.
|
- For **targeted queries**, run `project_map_context` (tool) or `project-map context` (CLI). The retrieval engine scores all paired metadata and returns a compact markdown bundle with the top-3 strongest matches: indexes, maps, likely files, and symbols.
|
||||||
@@ -262,6 +295,7 @@ The LLM client's response is parsed to extract `PURPOSE`, `DEPS`, `CONCEPTS`, `R
|
|||||||
- Tier 0 stays tiny and stable.
|
- Tier 0 stays tiny and stable.
|
||||||
- Tier 1 loads only likely relevant indexes/maps.
|
- Tier 1 loads only likely relevant indexes/maps.
|
||||||
- Tier 2 is real source, tests, config, and docs.
|
- Tier 2 is real source, tests, config, and docs.
|
||||||
|
- Automatic injection stays within the configured budget and avoids redundant reinjection by scanning outgoing context.
|
||||||
|
|
||||||
## 6. Stale Data Mitigation
|
## 6. Stale Data Mitigation
|
||||||
|
|
||||||
@@ -320,9 +354,10 @@ pi-project-map/
|
|||||||
│ ├── llm-extract.ts # LLM prompt templates for extraction
|
│ ├── llm-extract.ts # LLM prompt templates for extraction
|
||||||
│ ├── merge.ts # Merge AST + LLM outputs
|
│ ├── merge.ts # Merge AST + LLM outputs
|
||||||
│ ├── format.ts # Dense markdown formatter
|
│ ├── format.ts # Dense markdown formatter
|
||||||
│ └── config.ts # Skill configuration (thresholds, ignore patterns)
|
│ ├── config.ts # Skill configuration (thresholds, ignore patterns)
|
||||||
|
│ └── prompt-injection.ts # Runtime guidance injection policy and helpers
|
||||||
├── hooks/
|
├── hooks/
|
||||||
│ └── on-prompt.ts # Injects maintenance command into prompts
|
│ └── on-prompt.ts # Injects maintenance command into prompts (legacy; Pi extension uses event hooks)
|
||||||
└── README.md # Setup and usage for humans
|
└── README.md # Setup and usage for humans
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -333,9 +368,19 @@ pi-project-map/
|
|||||||
- `project-map:context <query>` — Retrieve a compact markdown bundle of the most relevant directories, files, and symbols for a natural-language query.
|
- `project-map:context <query>` — Retrieve a compact markdown bundle of the most relevant directories, files, and symbols for a natural-language query.
|
||||||
- `project-map:reinit [path]` — Force re-initialization of entire project or subtree.
|
- `project-map:reinit [path]` — Force re-initialization of entire project or subtree.
|
||||||
|
|
||||||
### Prompt Hook
|
### Prompt Injection Hooks
|
||||||
- On every prompt, the skill appends a lightweight instruction:
|
|
||||||
> "If you modify any source file, run `project-map:patch <path>` to update the analysis. If you suspect staleness, run `project-map:validate`."
|
The Pi extension registers event hooks instead of a single per-prompt append:
|
||||||
|
|
||||||
|
- `before_agent_start`: emits the pre-init hint when no artifacts exist, or preloads the root pair (plus budgeted expansion) after init.
|
||||||
|
- `context`: performs relevant-turn reinjection checks, detects compaction/artifact-change invalidation, and enforces `strict`-mode bypass guards.
|
||||||
|
- `before_provider_request`: optional fallback for marker scanning when message-layer detection is insufficient.
|
||||||
|
|
||||||
|
The injected maintenance reminder is:
|
||||||
|
|
||||||
|
> Start with the root `.pi-map.index.md`, use indexes first for routing, read the local `.pi-map.md` plus source before edits, run `project_map_patch` after source edits, and run `project_map_validate` before freshness-sensitive architectural handoff.
|
||||||
|
|
||||||
|
This is layered on top of the canonical root-pair block, which includes the trust boundary (`index routes, map orients, source decides`).
|
||||||
|
|
||||||
## 9. Risks and Tradeoffs
|
## 9. Risks and Tradeoffs
|
||||||
|
|
||||||
@@ -347,6 +392,19 @@ pi-project-map/
|
|||||||
| Expensive init on large repos | Medium | Medium | Parallelization, caching, optional incremental init |
|
| Expensive init on large repos | Medium | Medium | Parallelization, caching, optional incremental init |
|
||||||
| Overlap with LSP/typedoc | Low | Low | This is agent-context, not IDE tooling. Different use case. |
|
| Overlap with LSP/typedoc | Low | Low | This is agent-context, not IDE tooling. Different use case. |
|
||||||
| AST parser unavailable | Medium | Low | Graceful fallback to LLM-only extraction |
|
| AST parser unavailable | Medium | Low | Graceful fallback to LLM-only extraction |
|
||||||
|
| Message-level marker scanning misses provider serialization quirks | Medium | Medium | Add payload fallback scanning |
|
||||||
|
| Root-pair marker becomes brittle | Low | Medium | Stable deterministic boundaries and normalized artifact identity lines |
|
||||||
|
| 15% / 100k default budget too aggressive for some fleets | Low | Medium | Both knobs are configurable |
|
||||||
|
| Relevant-turn detection fuzzy | Medium | Medium | Centralized heuristics + extensive integration tests |
|
||||||
|
| `strict` mode friction | Low | Medium | Keep `strong` as default; isolate strict-only bypass behavior |
|
||||||
|
|
||||||
|
### Prompt Injection Known Limitations
|
||||||
|
|
||||||
|
- Token estimation is best-effort (≈ 4 chars per token); actual provider token counts may differ.
|
||||||
|
- Relevant-turn detection relies on explicit event types when available, with heuristic fallback for generic turns.
|
||||||
|
- Provider payload serialization may require the fallback scan path.
|
||||||
|
- The mode ladder is config-driven in v1; future UX may expose runtime controls.
|
||||||
|
- Retrieval (`project_map_context`) remains separate from automatic injection.
|
||||||
|
|
||||||
## 10. Concrete Example: Full Project Snapshot
|
## 10. Concrete Example: Full Project Snapshot
|
||||||
|
|
||||||
|
|||||||
@@ -255,8 +255,8 @@ export function buildPreInitHint(): string {
|
|||||||
return [
|
return [
|
||||||
"📋 Project maps not initialized.",
|
"📋 Project maps not initialized.",
|
||||||
"",
|
"",
|
||||||
"Run `project_map_init` to generate paired `.pi-map.md` and `.pi-map.index.md` artifacts for this project.",
|
"The project-map extension is active. Run `project_map_init` to generate paired `.pi-map.md` and `.pi-map.index.md` artifacts for this project.",
|
||||||
"After init, the agent will automatically use the root index for routing and the root map for orientation.",
|
"After init, the root pair will be preloaded automatically (default mode: strong). Source remains the final authority before edits.",
|
||||||
].join("\n");
|
].join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -638,7 +638,7 @@ export function buildInjectionPayload(
|
|||||||
|
|
||||||
// Maintenance reminder (lightweight)
|
// Maintenance reminder (lightweight)
|
||||||
const reminder =
|
const reminder =
|
||||||
"📋 Project map active: Start with the root `.pi-map.index.md`, use indexes first for routing, read the local `.pi-map.md` plus source before edits, run `project_map_patch` after source edits, and run `project_map_validate` before freshness-sensitive architectural handoff.";
|
"📋 Project map active: Start with the root `.pi-map.index.md`, use indexes first for routing, read the local `.pi-map.md` plus source before edits, run `project_map_patch` after source edits, and run `project_map_validate` before freshness-sensitive architectural handoff. Trust boundary: index routes, map orients, source decides.";
|
||||||
parts.push(reminder);
|
parts.push(reminder);
|
||||||
usedTokens += estimateTokens(reminder);
|
usedTokens += estimateTokens(reminder);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user