Orchestrata Ultimate › Plans › context-injection-owed-work-plan

Context-Injection Owed-Work Plan

Source: plans/context-injection-owed-work-plan.md at 8a2cb42ad · last changed 2026-07-27 · first committed 2026-07-14 · 238 lines.

Prose pending.

Plan text

Context-Injection Owed-Work Plan

Scope: Close the four items left unchecked in the 2026-07-14 spec update:

Status: in progress — Waves 1-6 complete, p50 benchmark re-run complete
Target: one numbered task per commit, scripts/health_check.py green before moving on.


0. Duplicate / consolidation findings

Area Finding Impact on plan
Memory recall MemoryEngine.search() lacks the pre-filters; MemoryScope already has date_from/date_to, so max_age_seconds maps cleanly. No duplicate implementation. Add params to protocol + engine + hot/cold stores; update assembler defaults.
CI conformance gate scripts/kg_schema.py check already exists and exits non-zero on drift. Not called in .github/workflows/ci.yml. One-line CI addition after the migration lands; must not enable before graph is clean or CI will fail.
p50 benchmark scripts/benchmark_pipeline.py and tests/knowledge_graph/test_knowledge_performance.py exist, but nothing measures context_pack.select()+pack() latency. New script + test, modeled on existing benchmark style.
Writer migration Significant duplication/fragmentation: sync.py and synchronizer.py both sync code AST; session/kg_sync/_stage_code.py duplicates AST syncing with different rel names; kg_design.py writes non-canonical CodeClass/CodeFunction/DesignModule {name} nodes. Sequence: one-shot graph cleanup → migrate easiest writers first → consolidate duplicate AST sync paths last.

1. SPEC-107 FR-002 — Bounded memory recall

Current state

Goal

Add max_entries and max_age_seconds pre-filters that run before similarity scoring, keeping recall latency under 100ms and the memory layer within its token budget.

Design

  1. Extend MemoryScope (if needed) or compute date_from from max_age_seconds.
  2. Add max_entries: int | None = None and max_age_seconds: int | None = None to:
    • MemoryEngineProtocol.search() (in core/protocols.py)
    • MemoryEngine.search()
    • RedisMemoryStore.retrieve_by_scope()
    • Neo4jMemoryStore.search_by_scope()
  3. Implement pre-filter semantics:
    • max_age_seconds: set scope.date_from = now - max_age_seconds before querying stores.
    • max_entries: pass through to retrieve_by_scope / search_by_scope so Redis/Neo4j cap candidate retrieval before Python scoring.
  4. Choose production defaults in UnifiedContextAssembler (e.g. max_entries=50, max_age_seconds=3600) and update the recall_sync call.
  5. Add observed tests proving search() returns ≤ max_entries and respects age.

Files to touch

Verification

python scripts/run_tests.py tests/memory/ --skip-gates
python scripts/health_check.py

2. SPEC-106 REQ-106-006 — CI conformance gate

Current state

Goal

Wire kg_schema.py check into CI so non-canonical writes fail the build.

Design

  1. Prerequisite: run migrate_neo4j_canonical.py against the shared CI Neo4j instance so the graph is clean.
  2. Add a CI step in .github/workflows/ci.yml after the architecture checker:
    - name: Canonical KG schema conformance
      run: uv run python scripts/kg_schema.py check
    
  3. Ensure CI Neo4j is reachable via env vars (NEO4J_URI, etc.). If CI lacks a live Neo4j, instead add a local test-fleet step that spins up a container, applies DDL, runs a smoke writer, and asserts check() passes.
  4. Add a test under tests/knowledge_graph/test_canonical_schema.py that:
    • Applies canonical DDL to a test-only Neo4j clone.
    • Writes a conformant node and asserts check() is OK.
    • Writes a non-canonical node (wrong merge key) and asserts check() reports it.

Files to touch

Verification

python scripts/kg_schema.py check
python scripts/run_tests.py tests/knowledge_graph/test_canonical_schema.py --skip-gates

3. SPEC-106 REQ-106-044 — p50 < 500ms benchmark for select() + pack()

Current state

Goal

A repeatable benchmark that reports p50 latency of context_pack.analyze_request() + select() + pack() against a live Neo4j graph at repo scale, and fails if p50 > 500ms.

Design

  1. New script scripts/benchmark_context_pack.py with subcommands:
    • seed — sync the current repo into a project-qualified Neo4j graph.
    • run — run N iterations of a representative task (e.g. TaskType.REFACTOR targeting context/assembler.py), measuring end-to-end analyze_request + select + pack latency.
    • Reports: iterations, p50/p95/p99 ms, nodes selected, sections packed.
  2. New test tests/knowledge_graph/test_context_pack_performance.py marked @pytest.mark.slow that:
    • Seeds a modest but non-trivial graph (≥50 files, ≥100 classes/functions).
    • Runs ≥20 iterations.
    • Asserts p50 < 500ms.
  3. Use existing context_pack.analyze_request, select, pack, and TokenCounterProtocol (no mocking).

Files to touch

Verification

python scripts/benchmark_context_pack.py seed
python scripts/benchmark_context_pack.py run --iterations 20
python scripts/run_tests.py tests/knowledge_graph/test_context_pack_performance.py --skip-gates

4. SPEC-106 REQ-106-008 — Migrate production KG writers onto canonical schema

Current state (writer audit)

Writer Labels/keys used Canonical? Notes
knowledge_graph/sync.py File/Class/Function/Method/Parameter/Package/Module/Requirement/Test with {id: r.id}; rels DEFINES, IMPORTS, CALLS, TESTED_BY, HAS_METHOD, INHERITS_FROM Mostly yes, but HAS_METHOD should be DEFINES and INHERITS_FROM should be INHERITS per canon Real AST sync writer
knowledge_graph/synchronizer.py File {path: $path}, Class/Function {id: r.id}, rels DEFINES, HAS_METHOD, CALLS, INHERITS, IMPORTS File key wrong; HAS_METHOD wrong Duplicates AST sync; appears to be the older/legacy implementation
session/kg_sync/_stage_code.py Class {id}, Function {id}, rels DEFINES, HAS_METHOD, HAS_CLASS, HAS_FUNCTION HAS_CLASS/HAS_FUNCTION wrong Another AST sync duplicate
session/kg_sync/_stage_session.py Project {id: $id}, Session {seq: $seq} Project key should be slug; Session key should be session_id Session/project writer
session/kg_sync/_stage_specs_traces.py Spec {id}, Requirement {id}, RequirementItem {id}, rels HAS_SPEC, DEFINES_REQUIREMENT, HAS_ITEM, TRACES_TO, IMPLEMENTS Mostly canonical Good candidate for first migration validation
session/kg_sync/_stage_folders.py Directory {id}, File {id}, rels HAS_ROOT_DIR, CONTAINS Directory/File keys canonical Mostly OK
kernel/pipeline_kg.py Volk {alias}, Artifact {id}, PipelineRun {id}, Intent {id}, Decision {id}, rels MADE, APPLIES_TO, JUSTIFIED_BY, GENERATED_BY, EXECUTED_BY, TRIGGERED Yes Already canonical; just verify
knowledge_graph/kg_design.py Project {slug}, Spec {id}, UserStory {id}, Requirement {id} canonical; but DesignModule {name}, DesignClass {name}, CodeClass {name, project}, CodeFunction {name, project} Non-canonical design/code nodes Design-layer writer; may need schema reconciliation
knowledge_graph/runtime_writer.py Message {message_id}, ToolCall {id}, Decision {id}, GatewayEvent {entry_id}, rel MENTIONS Yes Already canonical

Consolidation opportunities

  1. sync.py vs synchronizer.py — both sync AST to KG. Determine which is the production path and retire the other, or make synchronizer.py a thin wrapper around sync.py.
  2. session/kg_sync/_stage_code.py — likely superseded by sync.py; if still used, converge rel names onto DEFINES only.
  3. Design-layer non-canonical labels — CodeClass/CodeFunction overlap with Tier A Class/Function. Decide whether design artifacts are a distinct tier (then add them to canonical_schema.py with proper keys) or map them onto canonical code nodes.

Execution order

Wave 1 — Graph cleanup (one-time)
  1. Run python scripts/migrate_neo4j_canonical.py against the shared Neo4j instance.
  2. Verify python scripts/kg_schema.py check returns OK.
  3. Back up the graph before running.
Wave 2 — Already-canonical writers (validation only)
  1. kernel/pipeline_kg.py — add conformance assertions in tests.
  2. knowledge_graph/runtime_writer.py — already canonical; add test.
  3. session/kg_sync/_stage_specs_traces.py and _stage_folders.py — verify, fix minor rel names if needed.
Wave 3 — Key canonicalisation
  1. session/kg_sync/_stage_session.py:
    • Project {id: $id} → Project {slug: $id} (or backfill slug property).
    • Session {seq: $seq} → Session {session_id: $seq} (or write both).
  2. knowledge_graph/synchronizer.py:
    • File {path: $path} → File {id: $project_id:$path} and keep path property.
  3. Update tests for each writer to assert canonical keys.
Wave 4 — Relationship canonicalisation
  1. knowledge_graph/sync.py:
    • INHERITS_FROM → INHERITS.
    • (c)-[:HAS_METHOD]->(m) → (c)-[:DEFINES]->(fn:Function) where fn carries class_id.
  2. knowledge_graph/synchronizer.py and session/kg_sync/_stage_code.py:
    • HAS_CLASS/HAS_FUNCTION/HAS_METHOD → DEFINES.
  3. Update canonical_schema.py if any new rel constants are needed.
Wave 5 — Consolidate duplicate AST sync
  1. Decide single source of truth for code-to-KG sync. Recommendation: knowledge_graph/sync.py (it already uses project-qualified ids and is the newer implementation).
  2. Make synchronizer.py delegate to sync.py or delete it if unused.
  3. Make session/kg_sync/_stage_code.py delegate to sync.py or delete it.
  4. Remove dead code only after serialize_codebase_ast.py refs confirms zero references.
Wave 6 — Design-layer reconciliation
  1. Add canonical labels/keys for design artifacts or merge CodeClass/CodeFunction into canonical Class/Function.
  2. Update kg_design.py accordingly.
  3. This is the highest-risk wave; do it last and with a dedicated test-fleet run.

Files to touch (incremental, one wave per commit)

Verification (after each wave)

python scripts/kg_schema.py check
python scripts/run_tests.py tests/knowledge_graph/ --skip-gates
python scripts/health_check.py

Order Task Why
1 Bounded memory recall (FR-002) Isolated; no graph migration; unblocks assembler optimization.
2 p50 benchmark (REQ-106-044) Establish baseline before writer migration changes query patterns.
3 One-time graph cleanup + CI gate (REQ-106-006) Must clean graph before CI gate can be enabled.
4 Writer migration Wave 2 (canonical validation) Low-risk, proves CI gate works.
5 Writer migration Wave 3 (key canonicalisation) Fixes the most common check() failures.
6 Writer migration Wave 4 (relationship canonicalisation) Fixes remaining rel-name drift.
7 Writer migration Wave 5 (consolidate AST sync) Removes duplicate code.
8 Writer migration Wave 6 (design-layer reconciliation) Highest risk; do last.
9 Re-run p50 benchmark Verify migration did not regress latency.

6. Definition of done