Orchestrata Ultimate › Plans › context-injection-evolution-plan
Context Injection Evolution Plan
Source: plans/context-injection-evolution-plan.md at 8a2cb42ad · last changed 2026-07-27 · first committed 2026-07-13 · 367 lines.
Prose pending.
Plan text
Context Injection Evolution Plan
Analysis of how the project currently assembles an agent's prompt context, plus a concrete plan to make far better use of the AST, Neo4j knowledge graph, and session/plan/memory context — while keeping prompts inside a bounded, sliding context window.
1. Current state and gaps
1.1 What a volk receives today
The pipeline uses a layered prepend model: each context source is rendered as markdown and glued in front of the user message (src/orchestrata_ultimate/llm/client.py).
| Layer | Wired? | Source |
|---|---|---|
| System prompt | Yes | Static per-volk persona string. |
| Raw intent | Partial | Only U:Cx (Concierge) sees the original human text. |
| Prior-stage artifacts | Yes | Manual payload key-copying in each volk's process() plus automatic digest via context_providers/artifact_digest.py in the assembler. |
| KG code context | Yes | knowledge_graph/context_injector.py::ContextInjector for subjects in INJECT_SUBJECTS. |
| Task-type context pack | Yes | context_pack.frame/select/pack/render via inject_for_task, consumed through the assembler. |
| Memory recall | Yes | memory/memory_context.py; both runners bind a MemoryEngine per thread_id and the assembler prepends summary + recall. |
| Session / goal / project state | Partial | context_providers/mission_context.py renders a compact block from ContextData, but the runner does not yet load the active session's ContextData into the assembler. |
| ArtifactStore feedback | Yes | context_providers/artifact_digest.py reads ArtifactStore.by_thread(thread_id) in the assembler. |
The live injector already does several things well:
- It is subject-gated (
implement,fix_issues,review_and_test,design_review,scope_review,ux_design). - It returns a token-capped prompt (
GraphContext.to_prompt(max_context_tokens=4000)). - It includes semantic layer facts: requirements via
TRACES_TOand decisions viaAPPLIES_TO. - The newer
ContextPackpath is deterministic, editable, and budgeted (packer.py).
1.2 Key gaps
- No cross-layer budget.
GraphContext,ContextPack, memory recall, and the user message each have their own limits, but no component tracks the total prompt size. - Session/plan state is missing. Volks have no compact view of the active goal, pending work items, handoff notes, or the current plan step.
- Artifact feedback is manual. Prior-stage outputs rely on each volk copying the right payload keys.
- Memory is inconsistently wired. Recall only works when a
MemoryEngineis registered for the thread. - AST is underused. The AST engine (
scripts/serialize_codebase_ast.py) produces branches, complexity, call graphs, untyped/dead-param reports, and skeletons, but none of it reaches volk prompts. - Graph traversal is shallow. The live injector uses basename matching and a small fixed Cypher expansion; it does not exploit call-graph directionality, centrality, or semantic search.
- No feedback loop.
GraphContextValidatorchecks whether the response references injected entities, but a failed validation does not reformulate the injected context. - No on-demand retrieval. Everything is prepended. Volks cannot ask for more context when they need it.
2. Leveraging the AST
2.1 What the AST engine already provides
scripts/serialize_codebase_ast.py (and its FastAPI wrapper scripts/ast_api.py) reads live Python source and produces structured, prompt-usable output:
| Subcommand | Prompt value |
|---|---|
symbols |
Exact API surface: classes, functions, signatures, files, lines. |
branches |
Decision points (if, except, ternary) per function — exposes edge cases the agent must handle. |
complexity |
Cyclomatic complexity ranking — surfaces refactor hotspots. |
call-graph / refs |
Caller/callee neighborhoods and symbol usages. |
gen-tests |
Branch-level pytest scaffolds the agent must make pass. |
gen-skeleton |
Typed, @traces'd Python skeletons + leafmap.json / trace-map.json from a Mermaid contract. |
trace-lint |
Dangling / placeholder / malformed @traces findings. |
untyped, dead-params, unused, find-cycles |
Code-health backlog items. |
The AST is also synced into Neo4j by src/orchestrata_ultimate/knowledge_graph/sync.py as 12 node labels (Project, Package, Module, Class, Function, Method, Parameter, Requirement, ImportNode, DecoratorNode, Spec, RequirementItem) and 18 relationship types (DEFINES, HAS_METHOD, IMPORTS, CALLS, INHERITS_FROM, TRACES_TO, TESTED_BY, etc.).
2.2 Proposed AST-driven context features
- Branch-aware prompts. Before modifying a function, run
serialize codebase_ast branches --name <symbol>and inject the decision points. The agent must explicitly address eachif/exceptpath. - Complexity-first dispatch. For
fix_issuesorreview_and_test, inject the top-N complexity hotspots so the agent prioritizes high-risk functions. - Call-graph neighborhood. For an
implementorfix_issuespacket, fetchcall-graph --name <symbol>callers and callees and add them to the KG context. This reduces duplicate-code risk better than file-level imports. - Skeleton contract workflow. Use
gen-skeleton <contract.mmd>to emit the exact target shape, hand it to the agent as the implementation contract, then runskeleton-diffto detect structural escapes. - Trace-lint preflight. Before a task claiming to satisfy requirements, run
trace-lintand inject any dangling/placeholder findings. The agent must resolve them before marking work done. - Untested-branch scaffolding. Combine
branches+gen-teststo generate branch-level tests and require the agent to make them pass. - API-on-demand. Keep
scripts/ast_api.pyrunning so volks can call/symbols,/branches,/refs,/complexitydynamically instead of parsing source themselves.
3. Leveraging the Knowledge Graph
3.1 What the KG already provides
canonical_schema.py: 51 node labels and canonical identity ({project}:{natural_id}).query_engine.py: generic Cypher, multi-hop traversal, provenance lookup, lexical search.context_injector.py: file/relationship/test/requirement/decision context.context_pack/: deterministic, task-type-templated, ranked, budgeted context packs.graph_context_validator.py: checks that responses reference injected public entities.relevance.py+prolog/kg_relevance.pl: Prolog-deducedcore/related/peripheraltiers.semantic_search.py: Memgraph-based vector + keyword search over code chunks.
3.2 Proposed KG-driven improvements
- Canonical-id lookups. Replace
f.path CONTAINS $basenamematching inContextInjector._query_contextwith exactFile.idlookups ({project}:{path}), then expand viaDEFINES. - Call-graph-biased expansion. Weight
CALLSedges higher thanIMPORTS; use in-degree centrality to surface hub functions. - Requirement closure. Expand
TRACES_TOtoRequirementItem, then to parentRequirement/Spec, so the full "why" hierarchy is visible. - Populate missing sections.
GraphContext.recent_changesandsimilar_patternsare currently empty. Queryupdated_at/synced_atfor recency and sharedINHERITS_FROMbases for patterns. - Semantic search bridge. Map top Memgraph vector-search chunks back to Neo4j
File/Class/Functionnodes by(file_path, start_line, end_line)and feed them as extra root entities intoanalyze_request. - Validation feedback loop. Make
GraphContextValidatornode-aware (parse pack provenance or pass node ids). On failure, expandk_hopor include moreTRACES_TO/TESTED_BYedges and re-pack. - Runtime signal ingestion. Write
Message,GatewayEvent,Decision,ToolCallnodes (Tier H labels) into Neo4j so Prolog relevance rules can prioritize recently changed or failing nodes forDEBUGtasks. - Unify requirement identity. Merge or relate
Requirement(code traces) andRequirementItem(spec traces) so requirement-sharing logic works across both. - Cache invalidation. Tie
query_engine.pyLRU cache to graphsynced_ator transaction ID so syncs clear stale entries.
4. Leveraging Session, Plan, and Memory Context
4.1 What session context already provides
src/orchestrata_ultimate/session/models.py defines:
ProjectState: active session, version, branch, test state, status, current goal, portfolio goals.SessionRecord: purpose, objectives, work log, artifacts, choices, achievements, upcoming, handoff.HandoffData: decisions, blockers, active work, key files, commands, alerts.WorkItem: deferred tasks with priority, state, notes.Goal(SPEC-023): statement, criteria, tasks, progress, blockers.
ContextFileManager (session/context.py) already renders context.md via Jinja2 templates in session/templates/. The memory engine (memory/) provides hot (Redis) and cold (Neo4j) stores with a deterministic hash embedder and ContextCompressor. ArtifactStore captures per-stage outputs.
4.2 Proposed session-driven context features
- Mission block injection. Load
ContextDataonce per pipeline run and render a compact block containing:ProjectStatestatus, branch, test state.- Active
Goalstatement and unmet criteria. - Top pending
WorkItems. - Latest
HandoffData(decisions, blockers, key files, alerts).
- Memory summary + recall. At pipeline start, call
MemoryEngine.summarize(context_id=thread_id, max_tokens=512)for a run-level summary; keep per-taskrecall()for specifics. Prepend both. - Artifact feedback loop. After each stage,
ArtifactStore.add()already captures outputs. Queryartifacts.by_thread(thread_id)and inject a chronological digest (stage, type, file path, 200-char preview). - Plan window injection. Parse
plans/execution-plan.md(or the active plan document) into steps. Maintain acurrent_steppointer inProjectStateorGoal. Inject the current step in full plus the next 2 steps as titles. - Canonical ArtifactStore. Consolidate
kernel/pipeline_artifacts.py::ArtifactStoreandorchestrator/artifact_store.pyso both runners feed the same artifact context.
5. Target architecture: Unified Context Assembler
Introduce one service that composes all context sources under a single token budget.
┌─────────────────────────────────────────────────────────────┐
│ UnifiedContextAssembler │
│ inputs: payload, subject, task_type, thread_id, volk_alias │
│ output: context_parts dict + token accounting │
└─────────────────────────────────────────────────────────────┘
│
▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Session/Goal │ │ Memory │ │ Artifact │ │ KG / AST │
│ Context │ │ Summary │ │ Digest │ │ Context │
└──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
│ │ │ │
└────────────────┴────────────────┴────────────────┘
│
▼
┌───────────────────────┐
│ ContextBudget │
│ (enforced layering) │
└───────────────────────┘
│
▼
┌───────────────────────┐
│ effective_message │
│ = join(parts) + user │
└───────────────────────┘
Responsibilities:
- Fetch each source independently.
- Allocate a hard per-layer token budget.
- Evict lowest-relevance items first when a layer overflows.
- Cache rendered packs per
(snapshot_id, volk_alias, subject). - Expose a
get_context(entity, depth=1)tool so volks can pull more on demand. - Emit structured context-usage telemetry.
Integration points:
kernel/pipeline_kg.py::_maybe_inject_contextbecomes the orchestration site.orchestrator/pipeline_runner.py::_run_stagecalls the same assembler (closes the two-runner divergence).llm/client.pyacceptscontext_partsdirectly instead of a singlegraph_contextstring, or the assembler is called upstream.
5.1 The voluntary-use problem
Historical experiments show a consistent failure mode: even when instructions tell the model to use provided context, the model does not voluntarily pull or reference the data. It falls back on training-data shortcuts, hallucinates, or ignores the injected material.
This means context injection cannot rely on politeness. The system must force usage:
- Prepend, don't side-channel. Put context inside the user message tokens so the model must process it (already done in
llm/client.py). - Make references mandatory. Require the output to list every entity it used: classes, functions, requirements, decisions, prior artifacts. A response with no citations is invalid.
- Validate citations.
GraphContextValidatormust check that cited entities were actually injected and that injected critical entities were cited. - Use small, unavoidable context. Inject only the entities the task cannot succeed without. A smaller critical set is harder to ignore than a large optional encyclopedia.
- Structured output. When possible, make the volk fill a template (e.g., "Entities modified:" + "Requirements satisfied:" + "Decisions respected:") rather than write free prose.
- Mandatory tool calls for expansion. On-demand retrieval should not be optional. The task prompt can require the model to call
get_code/get_testsbefore producing output, and the pipeline rejects output that skipped the tool call. - Retry with escalation. First failure: re-prompt with a warning. Second failure: shrink context to the single most relevant entity and ask again. Third failure: escalate to human.
- Reward signal via provenance.
ContextPackalready carries provenance comments. Extend this to require the model to echo thenode_ids it acted on; score responses by citation coverage.
6. Context-window management strategy
6.1 Budget model
Reserve slots explicitly before the model sees the prompt. Example budget for a 128k-context model with ~8k output:
| Slot | Tokens | Policy |
|---|---|---|
| System prompt | 800 | Fixed. |
| Mission / session state | 400 | Fixed; summarize if needed. |
| Plan window | 600 | Current step full; done/next summaries. |
| Memory summary + recall | 700 | Summary 500 + recall 200. |
| Artifact digest | 500 | Most recent first. |
| Graph context | 2000 | Evict peripheral → related → core. |
| Task context pack | 1000 | Task-type-specific. |
| User message | remaining | Guard headroom. |
| Output reserve | 800 | Never steal from this. |
The assembler rejects or degrades gracefully when the total exceeds the model window.
6.2 Sliding plan window
For long-running plans:
- Current step: full text (goal, actions, verification, expected output).
- Completed steps: one-sentence summary each; drop summaries older than the last 3 steps unless causally linked to the current step.
- Upcoming steps: title + one-line description only.
- Store
current_stepinProjectStateand update it as the orchestrator advances.
6.3 Eviction policy
Use the existing ranking signals:
- Drop
TIER_PERIPHERALnodes. - Drop
TIER_RELATEDnodes. - Within a tier, drop highest
hop_distancefirst. - Never evict: active goal, current-step plan, blockers, failing tests, prior decisions, current diff.
6.4 On-demand retrieval
Instead of prepending everything, expose tools:
get_code(entity_id, include_callers=false, depth=1)— fetch a class/function and neighbors.get_tests(entity_id)— fetch covering tests.get_requirements(entity_id)— fetch traced requirements.get_artifact(artifact_id)— fetch a prior-stage artifact.search_code(query, limit=5)— semantic + lexical search.
This keeps the default prompt small and lets volks expand context only when needed.
7. Phased implementation plan
Phase 0 — Foundations (suggested first milestone)
Goal: establish budget accounting, a single assembler, and close the most urgent gaps.
| # | Task | Files to touch | Acceptance criteria |
|---|---|---|---|
| 0.1 | Add ContextBudget dataclass |
src/orchestrata_ultimate/context/budget.py |
Model with slots for system, mission, plan, memory, artifacts, graph, task, user, output; total-window validation; per-layer reservation. |
| 0.2 | Add UnifiedContextAssembler skeleton |
src/orchestrata_ultimate/context/assembler.py |
Class accepts payload, subject, task_type, thread_id, volk_alias; returns {system, mission, memory, artifacts, graph, task, user} context parts and token counts; has a no-op implementation for graph/task that delegates to existing injector. |
| 0.3 | Artifact feedback via store-agnostic digest | src/orchestrata_ultimate/context/providers/artifact_digest.py (new), src/orchestrata_ultimate/context/assembler.py |
Render a chronological digest from either ArtifactStore implementation without a broad refactor. Closes Gap E immediately. |
| 0.4 | Inject session / mission context | src/orchestrata_ultimate/context/providers/mission_context.py (new), src/orchestrata_ultimate/context/assembler.py |
Render a ≤400-token block from ContextData with active goal, top 5 pending work items, and latest handoff decisions/blockers. |
| 0.5 | Wire assembler into both runners | src/orchestrata_ultimate/kernel/pipeline_kg.py, src/orchestrata_ultimate/orchestrator/pipeline_runner.py |
Both runners call UnifiedContextAssembler.assemble() and pass the resulting context parts to call_llm (or keep the existing graph_context kwarg but populated by the assembler). |
| 0.6 | Add context-usage telemetry | src/orchestrata_ultimate/context/assembler.py, logging |
Every LLM call logs context_usage JSON with tokens per layer. |
| 0.7 | Mandate citation output format | src/orchestrata_ultimate/core/graph_directives.py, per-volk system prompts |
Every volk prompt includes an instruction to list every entity (class/function/requirement/decision/artifact) it used. System prompt templates updated. |
| 0.8 | Make validator citation-aware | src/orchestrata_ultimate/knowledge_graph/graph_context_validator.py |
Validator parses citations from the response and checks that (a) cited entities were injected, (b) injected TIER_CORE entities were cited. Returns missing citations. |
Phase 1 — AST-driven context
Goal: feed AST-derived facts into the assembler.
| # | Task | Files to touch | Acceptance criteria |
|---|---|---|---|
| 1.1 | AST API client | src/orchestrata_ultimate/tools/ast_client.py (new) |
Typed client for scripts/ast_api.py endpoints (/symbols, /branches, /complexity, /call-graph, /refs, /gen-tests, /trace-lint). Caches responses per file mtime. |
| 1.2 | Branch context provider | src/orchestrata_ultimate/context/providers/ast_branches.py (new) |
Given target symbols, returns a markdown block of if/except/ternary decision points. |
| 1.3 | Complexity hotspot provider | src/orchestrata_ultimate/context/providers/ast_complexity.py (new) |
Returns top-N complexity functions in target files. |
| 1.4 | Call-graph neighborhood provider | src/orchestrata_ultimate/context/providers/ast_call_graph.py (new) |
Returns callers/callees for target symbols. |
| 1.5 | Trace-lint preflight provider | src/orchestrata_ultimate/context/providers/ast_trace_lint.py (new) |
Runs trace-lint on target files and returns findings; assembler includes them for implement/review_and_test subjects. |
| 1.6 | Skeleton contract integration | src/orchestrata_ultimate/agents/volks/codedirector/scaffold/generator.py, src/orchestrata_ultimate/context/assembler.py |
When a payload carries a Mermaid contract, run gen-skeleton and inject the skeleton + leafmap as task_context. |
| 1.7 | Tests for providers | tests/context/providers/test_*.py |
Each provider has unit tests with real AST fixtures; no mocks. |
Phase 2 — KG enhancements
Goal: richer, canonical, feedback-aware graph context.
| # | Task | Files to touch | Acceptance criteria |
|---|---|---|---|
| 2.1 | Canonical file lookups | src/orchestrata_ultimate/knowledge_graph/context_injector.py |
_query_context resolves target files to File.id first; no more path CONTAINS basename heuristic. |
| 2.2 | Populate recent changes | src/orchestrata_ultimate/knowledge_graph/context_injector.py |
GraphContext.recent_changes queries File/Class/Function.updated_at and returns the most recently synced N items. |
| 2.3 | Populate similar patterns | src/orchestrata_ultimate/knowledge_graph/context_injector.py |
GraphContext.similar_patterns returns files/classes sharing a base class or implementing the same protocol. |
| 2.4 | Requirement closure | src/orchestrata_ultimate/knowledge_graph/context_injector.py |
_query_semantic_context walks TRACES_TO → RequirementItem → Requirement → Spec and renders the hierarchy. |
| 2.5 | Semantic search bridge | src/orchestrata_ultimate/knowledge_graph/context_pack/selector.py, src/orchestrata_ultimate/knowledge_graph/semantic_bridge.py (new) |
Memgraph vector-search top-k chunks are mapped to Neo4j nodes by (path, line_range) and added as extra root entities in analyze_request. |
| 2.6 | Validator feedback loop | src/orchestrata_ultimate/knowledge_graph/graph_context_validator.py, src/orchestrata_ultimate/context/assembler.py |
Validator receives injected node ids; on failure, assembler re-runs select with larger k_hop and/or expands TESTED_BY/TRACES_TO edges, then re-packs. |
| 2.7 | Runtime Tier H ingestion | src/orchestrata_ultimate/knowledge_graph/runtime_writer.py (new), prolog/kg_relevance.pl |
Writer creates Message/GatewayEvent/Decision/ToolCall nodes; Prolog rules use kg_recent/1 and kg_failed/1 to boost relevance for DEBUG. |
| 2.8 | Unify requirement nodes | src/orchestrata_ultimate/session/kg_sync/_stage_specs_traces.py, src/orchestrata_ultimate/knowledge_graph/canonical_schema.py |
Requirement and RequirementItem are linked by Requirement-[:HAS_ITEM]->RequirementItem; both participate in requirement-sharing logic. |
Phase 3 — Session, memory, and plan window
Goal: make long-running sessions coherent and plan-aware.
| # | Task | Files to touch | Acceptance criteria |
|---|---|---|---|
| 3.1 | Memory summarization | src/orchestrata_ultimate/memory/memory_engine.py, src/orchestrata_ultimate/agents/volks/memory_context.py |
Add summarize(context_id, max_tokens) using ContextCompressor; cache result per thread; assembler prepends it. |
| 3.2 | Universal memory binding | src/orchestrata_ultimate/kernel/pipeline.py, src/orchestrata_ultimate/orchestrator/pipeline_runner.py, src/orchestrata_ultimate/agents/kernel_handler.py |
Both runners register a MemoryEngine for the thread in a try/finally. |
| 3.3 | Plan parser | src/orchestrata_ultimate/planning/plan_parser.py (new) |
Parse plans/execution-plan.md (or any active plan markdown) into (step_num, title, goal, actions, verify, expected) tuples. |
| 3.4 | Plan window provider | src/orchestrata_ultimate/context/providers/plan_window.py (new) |
Given current_step, renders current step full + next 2 titles + last 3 done summaries. |
| 3.5 | Current-step tracking | src/orchestrata_ultimate/session/models.py (ProjectState/Goal), src/orchestrata_ultimate/session/controller/_goals.py |
Goal gains current_step field; goal advance CLI updates it; assembler reads it. |
| 3.6 | Artifact digest provider | src/orchestrata_ultimate/context/providers/artifact_digest.py (new) |
Queries canonical ArtifactStore.by_thread(thread_id) and returns chronological digest. |
| 3.7 | End-to-end long-session test | tests/session/test_context_window.py |
Simulate 20 turns; verify token budget holds and older turns are summarized, not dropped silently. |
Phase 4 — Optimization and observability
Goal: make context assembly fast, fresh, and measurable.
| # | Task | Files to touch | Acceptance criteria |
|---|---|---|---|
| 4.1 | Context pack caching | src/orchestrata_ultimate/context/assembler.py |
Cache ContextPack.render() output by (snapshot_id, volk_alias, subject) for the lifetime of a pipeline run. |
| 4.2 | Incremental sync hooks | src/orchestrata_ultimate/knowledge_graph/sync.py, scripts/sync_ast_to_neo4j.py |
Add incremental_sync(module_paths); wire a post-save hook or watcher in development mode. |
| 4.3 | Query cache invalidation | src/orchestrata_ultimate/knowledge_graph/query_engine.py |
LRU cache key includes graph synced_at; stale entries evicted after sync. |
| 4.4 | On-demand context tools | src/orchestrata_ultimate/agents/volks/tools/context_tools.py (new) |
Implement get_code, get_tests, get_requirements, search_code tools registered in the volk tool registry. |
| 4.5 | Context dashboard | docs/context-telemetry.md (new), logging |
Document context_usage log format; add a small script scripts/context_usage_report.py to aggregate per-volk / per-subject token spend. |
| 4.6 | Budget-driven stress test | tests/context/test_budget.py |
Generate oversized context; verify assembler degrades gracefully (drops peripheral first, never exceeds model window, logs degradation reason). |
Phase 5 — Cleanup (after the initial wave)
Goal: pay down the technical debt left behind to keep the initial wave small.
| # | Task | Files to touch | Acceptance criteria |
|---|---|---|---|
| 5.1 | Canonicalize ArtifactStore implementations |
src/orchestrata_ultimate/kernel/pipeline_artifacts.py, src/orchestrata_ultimate/orchestrator/artifact_store.py, all callers |
Merge the two PipelineArtifact/ArtifactStore implementations into one canonical version; update imports and tests in both runners and verification gate. |
| 5.2 | Remove basename heuristic from ContextInjector |
src/orchestrata_ultimate/knowledge_graph/context_injector.py |
_query_context uses canonical File.id / File.path + project_id lookups; no more path CONTAINS basename. |
| 5.3 | Consolidate context provider package | src/orchestrata_ultimate/context/ or src/orchestrata_ultimate/context/providers/ |
Decide whether budget/assembler/providers belong under KG or a top-level context package; move and update imports if needed. |
8. Acceptance criteria for the whole effort
- Every volk call logs
context_usagewith tokens per layer. - Both
PipelineRunnerimplementations use the sameUnifiedContextAssembler. - Session state (goal, handoff, pending work) is injected for all
INJECT_SUBJECTS. - Memory recall works in both choreographed and orchestrated runners.
- Artifact feedback is automatic, not manual payload copying.
- AST-derived context (branches, complexity, call graph, trace-lint) is available to at least
implement,fix_issues, andreview_and_testsubjects. - Graph context uses canonical
File.idlookups and includes recent changes / similar patterns. GraphContextValidatorfailure triggers a one-step context expansion retry.- A plan window (current step + compact done/upcoming) is injected for long-running plan execution.
- Total prompt size never exceeds the configured model window; peripheral nodes are evicted first.
- Volk outputs cite injected entities;
GraphContextValidatorrejects outputs missing mandatory citations.
9. Risks and non-goals
Risks
- Models ignore context even when instructed. This is the historical pattern the plan is designed around; mitigation is mandatory citations + validator + retry, not bigger prompts.
- Increasing context size can raise cost and latency even within budget. Measure per-call spend with telemetry.
- Over-eager eviction can drop critical nodes. Keep a "do not evict" list and test it.
- Bridging Memgraph semantic search into Neo4j adds coupling. Consider converging on one store if Memgraph dependency becomes a burden.
- Runtime Tier H ingestion can write a lot of data. Use TTL or periodic compaction.
Non-goals
- This plan does not replace the existing
@tracessystem; it complements it. - It does not mandate a single LLM model; budget sizes should be model-configurable.
- It does not require removing
ContextInjectororContextPack; it evolves them behind the assembler.
10. Summary of immediate next actions
If you want to start tomorrow, do these in order:
- Create
ContextBudgetandUnifiedContextAssemblerskeleton. - Pick one
ArtifactStoreand migrate the other runner to it. - Inject a mission block from
ContextDataforINJECT_SUBJECTS. - Fix
ContextInjector._query_contextto use canonicalFile.idlookups. - Add
MemoryEngine.summarizeand bind memory universally in both runners. - Mandate citations in every volk prompt and make
GraphContextValidatorenforce them.
Those six items close gaps D, E, and C from docs/context-injection.md and address the observed voluntary-use failure mode.