Skip to content

feat: ship context-plane tooling surface#58

Merged
mohanagy merged 17 commits into
mainfrom
context-plane-full
May 8, 2026
Merged

feat: ship context-plane tooling surface#58
mohanagy merged 17 commits into
mainfrom
context-plane-full

Conversation

@mohanagy
Copy link
Copy Markdown
Owner

@mohanagy mohanagy commented May 8, 2026

Summary

  • add shared context-pack and context-session layers, then expose them through new pack / prompt CLI commands and MCP context-plane tools
  • unify compare, review, and benchmark prompt generation around cache-aware prompt/session payloads with effective-cost and coverage metadata
  • refresh README, examples, and benchmark proof language to match the implemented context-plane surface, and restore clean-install compatibility on this environment

Test Plan

  • npm run typecheck
  • npm run test:run
  • npm run build
  • npm pack --dry-run

Summary by CodeRabbit

  • New Features

    • Added pack and prompt CLI commands, provider-specific prompt compilation, context-pack tooling, and three context-session MCP tools (context_pack, context_prompt, context_session_reset).
    • Session-aware prompts with session-delta follow-ups and cache-reuse payloads.
  • Enhancements

    • Effective (cache-adjusted) token accounting surfaced in benchmarks, compare, and reports.
  • Documentation

    • README/docs updated to present the “context plane”/“context compiler”, CLI usage, tool profiles, and effective-cost framing.
  • Tests

    • Expanded unit tests for CLI, MCP tools, sessions, benchmarks, and context-pack behavior.
  • Chores

    • Package metadata (description/keywords) updated.

mohanagy and others added 15 commits May 8, 2026 06:03
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Restore the at-least-one-node behavior in compileContextPack so review packs do not become empty when the first candidate exceeds budget. Add a focused regression test covering the over-budget first review node case.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep raw full-prompt token counts distinct from effective session-aware counts in compare reports, and add regression coverage for follow-up delta prompts.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Restore the pre-Task 6 vite version and remove the unrelated package metadata assertions so the Task 6 surface stays focused on docs/proof framing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add get_neighbors to the full-profile README tool list and
assert the README stays aligned with the shipped MCP surface.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 8, 2026

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 293fb90f-76e3-4d33-8d01-a1d153c43f90

📥 Commits

Reviewing files that changed from the base of the PR and between 65d8637 and 8b57694.

📒 Files selected for processing (2)
  • src/runtime/context-session.ts
  • tests/unit/context-session.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/unit/context-session.test.ts
  • src/runtime/context-session.ts

📝 Walkthrough

Walkthrough

This PR introduces a comprehensive "context plane" and "context compiler" system. It adds contract types for context packs and sessions, implements compilation and session state management, refactors retrieval/impact/compare to attach evidence metadata, builds a structured prompt system with cache reuse, and extends MCP with new context-aware tools. The CLI gains pack and prompt commands, the benchmark runner supports session-based prompt caching, and documentation positions the new surfaces with effective-cost framing.

Changes

Context Plane & Compiler Implementation

Layer / File(s) Summary
Data Contracts
src/contracts/context-pack.ts, src/contracts/context-session.ts
New TypeScript interfaces define task classification, evidence classes, node/relationship/community structures, claims, coverage tracking, expandable refs, and session state/delta models.
Context Pack Runtime
src/runtime/context-pack.ts
Implements classifyTaskContract, estimateContextPackEntryTokens, compileContextPack (budget-constrained selection), and compactContextPack (modes: retrieve/review) to manage context packs and compute claims/coverage/expandable previews.
Context Session Runtime
src/runtime/context-session.ts
Implements createContextSessionState and buildContextSession with deterministic hashing, per-ref token estimation, added/updated/reused/invalidated tracking, and reused token count computation.
Retrieve with Evidence
src/runtime/retrieve.ts
retrieveContext now assigns evidence_class to matched nodes and returns enriched RetrieveResult including task_contract, claims, expandable, and coverage via the context-pack builder; compaction strips evidence_class for stdio outputs.
Feature Map & Relevant Files
src/runtime/feature-map.ts, src/runtime/relevant-files.ts
Feature map and relevant-files outputs extended to include claims, expandable refs, optional coverage, and missing_context derived from retrieval results when present.
PR Impact with Evidence
src/runtime/pr-impact.ts
Refactored to map candidate kinds to evidence_class, create fallback coverage, convert PrReviewBundle → CompiledContextPack, and compact review bundles via compactContextPack for review semantics.
Context Prompt Builder
src/infrastructure/context-prompt.ts
New buildContextPrompt: composes stable prefix + dynamic suffix, generates session_payload (full or session-delta), uses buildContextSession, and computes token metrics including effective and reused-context tokens.
Compare & Review-Compare
src/infrastructure/compare.ts, src/infrastructure/review-compare.ts
Compare now threads ContextSessionState across baseline/graphify prompts, builds stable sections, writes session_payload artifacts, tracks effective prompt tokens and reused-context tokens, and surfaces these metrics in reports and summaries.
CLI Parser & Main
src/cli/parser.ts, src/cli/main.ts
Adds parsePackArgs/parsePromptArgs and option types, validates graph paths, and adds pack and prompt subcommands wired to runContextPack/runContextPrompt handlers.
Pack & Prompt Commands
src/infrastructure/context-pack-command.ts, src/infrastructure/context-prompt-command.ts
runContextPackCommand orchestrates explain/review/impact pack generation with dependency injection and compacting; runContextPromptCommand loads graph, retrieves context, builds a prompt pack, compiles provider-specific payloads (Claude session_payload vs Gemini prompt), and returns JSON.
MCP Tool Definitions & Prompts
src/runtime/stdio/definitions.ts, src/runtime/stdio/prompts.ts
Adds MCP tools context_pack, context_prompt, context_session_reset and corresponding MCP_PROMPTS; prompt metadata and completion handlers extended.
Stdio Server & MCP Tools
src/runtime/stdio-server.ts, src/runtime/stdio/tools.ts
Stdio server adds per-session contextPromptSessions (cap + eviction) and exposes get/set/clear helpers; tools implement context_pack/context_prompt/context_session_reset with session validation, impact-target selection, provider-aware compilation, and merged context metadata in compact responses.
Benchmark & Runner
src/infrastructure/benchmark.ts, src/infrastructure/benchmark/runner.ts, src/infrastructure/benchmark/questions.ts
Benchmark runner threads session_state between runs; per-question runs include effective_query_tokens and reused_context_tokens; aggregated results include avg_effective_query_tokens, avg_reused_context_tokens, and effective_reduction_ratio; printBenchmark conditionally prints cache-adjusted averages.
Documentation & Packaging
README.md, examples/*, docs/benchmarks/*, package.json
Reframes graphify-ts as a “context plane” and “context compiler,” documents graphify-ts pack/graphify-ts prompt CLI commands and MCP context-plane tools, and introduces effective-cost token framing; updates package description and keywords.
Tests
tests/unit/*
Adds and updates many tests covering context-pack compile/compact, context-prompt session deltas, retrieve evidence/compaction, pr_impact behaviors, compare/benchmark session reuse, stdio prompts/tools/profile gating, and docs/package metadata assertions.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • mohanagy/graphify-ts#24: Retrieval pipeline and RetrieveResult shape extensions overlap with this PR’s retrieve/context-pack enrichment.
  • mohanagy/graphify-ts#19: Compare/report interface and token-reporting changes relate to the compare/session modifications here.
  • mohanagy/graphify-ts#25: Overlapping stdio/feature_map/relevant_files changes and MCP tool surface adjustments.

"A rabbit packed the context tight,
Stable refs saved tokens through the night.
From graph to prompt the compiler sings,
Delta hops and cached wings — joy it brings!"

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch context-plane-full

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (7)
tests/unit/stdio-tool-profile.test.ts (1)

215-235: ⚡ Quick win

Exercise the tools/call gate for all three full-only context tools.

This only proves context_pack is blocked in the core profile. If context_prompt or context_session_reset end up mis-registered, tools/list would still pass while invocation stays incorrectly reachable. A small parameterized assertion over all three names would close that gap.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/stdio-tool-profile.test.ts` around lines 215 - 235, The test only
checks that 'context_pack' is blocked; update the spec in the it block to
iterate over all three full-only tool names (context_pack, context_prompt,
context_session_reset) and for each call handleStdioRequest (using
withProfile('core', ...)) assert the response.error has code -32601 and that the
message contains the tool name and 'GRAPHIFY_TOOL_PROFILE=full'; locate the
current test that calls handleStdioRequest and replace the single-name assertion
with a small loop/parameterized map over the three names so each is exercised
the same way.
tests/unit/context-pack-command.test.ts (1)

164-246: ⚡ Quick win

Make the impact-target test prove the selection logic.

The fixture only returns one matched node, so this currently validates the happy path, not “highest-signal” selection. Add at least one lower-signal candidate and assert analyzeImpact() still receives AuthService; otherwise a first-match/last-match regression would slip through.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/context-pack-command.test.ts` around lines 164 - 246, The test
currently only returns one matched node so it doesn't verify “highest-signal”
selection; update the retrieveContext mock (the object returned by
dependencies.retrieveContext in this test) to include at least one additional
matched_nodes entry with a lower signal (e.g., lower match_score and/or less
favorable relevance_band, label like 'OtherService'), then keep the existing
expectation that analyzeImpact is called with { label: 'AuthService', depth: 3 }
and the same output assertion to prove the highest-signal node ('AuthService')
is chosen by runContextPackCommand.
tests/unit/retrieve.test.ts (1)

2718-2731: ⚡ Quick win

Also lock down expandable in the stdio compaction test.

This helper now carries truncated-evidence hints, but the new assertion only preserves claims and coverage. If compactRetrieveResultForStdio() starts dropping expandable, MCP clients would silently lose the “fetch more context” signal without this test catching it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/retrieve.test.ts` around lines 2718 - 2731, The stdio compaction
test omits asserting the expandable field, so add an assertion that
compactRetrieveResultForStdio preserves the expandable signal: after computing
compactResult in the test (it 'strips evidence_class from compact stdio retrieve
payloads'), assert that compactResult.expandable equals rawResult.expandable (or
that compactResult has the expandable property and its value matches
rawResult.expandable) so the test will fail if compactRetrieveResultForStdio
starts dropping expandable.
tests/unit/context-prompt.test.ts (1)

75-75: ⚡ Quick win

Make the invalidation assertion formatting-tolerant.

This assertion is tied to exact JSON whitespace, so harmless serialization formatting changes can break the test without behavior regressions.

Suggested test tweak
-    expect(followUp.session_payload).toContain('"invalidated": [\n    "beta"\n  ]')
+    expect(followUp.session_payload).toMatch(/"invalidated":\s*\[\s*"beta"\s*\]/)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/context-prompt.test.ts` at line 75, The assertion is brittle
because it depends on exact JSON whitespace; instead parse the JSON from
followUp.session_payload and assert the invalidated array contains "beta".
Locate the test that uses followUp.session_payload and replace the
string-contains check with JSON.parse(followUp.session_payload) and an assertion
like parsed.invalidated.includes('beta') (or the test framework equivalent,
e.g., expect(parsed.invalidated).toContain('beta')) to make the check
formatting-tolerant.
tests/unit/review-compare.test.ts (1)

173-181: ⚡ Quick win

Avoid source-string coupling in this unit test.

This test enforces internal implementation details via string matching, which is fragile against harmless refactors. Prefer asserting behavior/output contracts instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/review-compare.test.ts` around lines 173 - 181, The unit test is
brittle because it inspects source strings of generateReviewCompareArtifacts;
instead, update the test to assert behavior by importing
generateReviewCompareArtifacts and the shared helper renderReviewPrompt (or
mocking/spying on it) and verifying that calling generateReviewCompareArtifacts
results in invoking renderReviewPrompt and/or produces the expected output
contract, rather than searching for 'renderReviewPrompt(' or
'buildContextPrompt(' in the file text; replace the readFileSync/string matching
logic with a behavioral assertion using the function
generateReviewCompareArtifacts and a spy/mock on renderReviewPrompt.
src/infrastructure/context-prompt.ts (1)

45-47: 💤 Low value

Consider documenting the reserved ref prefix.

The __stable_prefix: prefix for internal refs (instructions, title) could theoretically collide with user-provided section refs. Consider adding a brief comment noting this is a reserved namespace, or validating user refs don't use this prefix.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/infrastructure/context-prompt.ts` around lines 45 - 47, Document that
"__stable_prefix:" is a reserved namespace and prevent collisions by either
adding a clear inline comment next to STABLE_PREFIX_INSTRUCTIONS_REF and
STABLE_PREFIX_TITLE_REF stating they are internal/reserved, and/or add
validation where user section refs are accepted (e.g., in the function that
processes user refs) to reject or escape refs that start with
"__stable_prefix:". Update symbols STABLE_PREFIX_INSTRUCTIONS_REF and
STABLE_PREFIX_TITLE_REF and the user-ref validation logic so any user-provided
ref beginning with that prefix triggers an error or is normalized.
src/runtime/stdio/tools.ts (1)

428-429: 💤 Low value

Inconsistent indentation.

Lines 428-429 have extra leading spaces compared to the surrounding code in the same object literal.

🔧 Suggested fix
           ...(retrieveCommunity !== null ? { community: retrieveCommunity } : {}),
-          ...(retrieveFileType ? { fileType: retrieveFileType } : {}),
-        }))
+        ...(retrieveFileType ? { fileType: retrieveFileType } : {}),
+      }))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/runtime/stdio/tools.ts` around lines 428 - 429, The object spread line
with ...(retrieveFileType ? { fileType: retrieveFileType } : {}) inside the
object literal in src/runtime/stdio/tools.ts is indented inconsistently; fix it
by aligning the leading spaces to match the surrounding properties in the same
object (adjust the indentation of the spread expression so it lines up with the
other entries in the object where it appears).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/infrastructure/context-prompt-command.ts`:
- Around line 74-80: The returned JSON always hardcodes task: "explain" which
mislabels outputs; update the return in runContextPromptCommand to use the
actual task from the input (e.g., options.task) or omit the task key when not
provided so downstream consumers see correct metadata; locate the return that
builds providerCompiled and replace the fixed "explain" with a conditional
inclusion of options.task (or remove the field) while leaving provider, prompt,
graph_path, and compiled as-is.
- Around line 38-57: In compilePromptForProvider, keep token_count semantically
consistent by returning the full prompt cost (promptPack.token_count) for all
providers; for the 'claude' branch add a separate field
session_payload_token_count (or session_payload_size) that contains
promptPack.session_payload_token_count and still include effective_token_count,
reused_context_tokens and session_state as before so the raw-vs-effective split
is preserved; ensure the Gemini (non-claude) branch remains unchanged and that
the returned object keys (provider, format, prompt, token_count,
session_payload_token_count, effective_token_count, reused_context_tokens,
session_state) are present only where appropriate.

In `@src/runtime/context-session.ts`:
- Around line 77-97: The reused_token_count is currently computed by
concatenating reused ref texts into reusedContent and re-tokenizing via
estimateQueryTokens, which can cause order-dependent drift; instead compute
reused_token_count by summing each reused ref's existing token count (e.g.,
ref.token_count or ref.tokensCount) from orderedRefs where
reusedRefSet.has(ref.ref), and only fall back to
estimateQueryTokens(ref.content) for refs that lack a stored token count; update
the session_delta.reused_token_count assignment to use this summed-per-ref value
rather than estimateQueryTokens(reusedContent).

In `@src/runtime/relevant-files.ts`:
- Around line 149-152: The current assignment unconditionally sets
missing_context to [] which conflates “no coverage computed” with “no missing
context”; update the object construction around retrieveResult to only include
missing_context when retrieveResult.coverage is present (or make it nullable) so
downstream can distinguish the cases—e.g., mirror the coverage spread pattern
using retrieveResult.coverage and retrieveResult.coverage.missing_required (or
set missing_context to null when coverage exists but missing_required is
absent); touch the lines referencing retrieveResult.coverage, missing_context,
and missing_required to implement this conditional inclusion.

In `@src/runtime/stdio-server.ts`:
- Around line 588-591: The current setContextPromptSession implementation stores
every sessionId indefinitely; modify setContextPromptSession (and reuse
ensureContextPromptSessions/sessionState) to enforce a fixed max size (e.g.,
MAX_CONTEXT_PROMPT_SESSIONS) and perform FIFO eviction: when inserting a new
sessionId, if the Map size exceeds the limit, remove the oldest entry (use the
Map's insertion order to find the first key) before calling set(sessionId,
nextState); keep clearContextPromptSession as-is to delete specific entries.
Ensure the MAX constant is defined near the other session-state logic and apply
the same bounded Map handling for any other callers of
ensureContextPromptSessions.

In `@src/runtime/stdio/definitions.ts`:
- Around line 236-278: The new tools are defined but not exposed because
activeMcpTools() still defaults to the core profile and CORE_TOOL_NAMES omits
the three new tool names; update the MCP exposure by adding 'context_pack',
'context_prompt', and 'context_session_reset' to CORE_TOOL_NAMES (or change
activeMcpTools() default/profile logic to include them) so these definitions are
included in the default/core toolset that activeMcpTools() returns.

---

Nitpick comments:
In `@src/infrastructure/context-prompt.ts`:
- Around line 45-47: Document that "__stable_prefix:" is a reserved namespace
and prevent collisions by either adding a clear inline comment next to
STABLE_PREFIX_INSTRUCTIONS_REF and STABLE_PREFIX_TITLE_REF stating they are
internal/reserved, and/or add validation where user section refs are accepted
(e.g., in the function that processes user refs) to reject or escape refs that
start with "__stable_prefix:". Update symbols STABLE_PREFIX_INSTRUCTIONS_REF and
STABLE_PREFIX_TITLE_REF and the user-ref validation logic so any user-provided
ref beginning with that prefix triggers an error or is normalized.

In `@src/runtime/stdio/tools.ts`:
- Around line 428-429: The object spread line with ...(retrieveFileType ? {
fileType: retrieveFileType } : {}) inside the object literal in
src/runtime/stdio/tools.ts is indented inconsistently; fix it by aligning the
leading spaces to match the surrounding properties in the same object (adjust
the indentation of the spread expression so it lines up with the other entries
in the object where it appears).

In `@tests/unit/context-pack-command.test.ts`:
- Around line 164-246: The test currently only returns one matched node so it
doesn't verify “highest-signal” selection; update the retrieveContext mock (the
object returned by dependencies.retrieveContext in this test) to include at
least one additional matched_nodes entry with a lower signal (e.g., lower
match_score and/or less favorable relevance_band, label like 'OtherService'),
then keep the existing expectation that analyzeImpact is called with { label:
'AuthService', depth: 3 } and the same output assertion to prove the
highest-signal node ('AuthService') is chosen by runContextPackCommand.

In `@tests/unit/context-prompt.test.ts`:
- Line 75: The assertion is brittle because it depends on exact JSON whitespace;
instead parse the JSON from followUp.session_payload and assert the invalidated
array contains "beta". Locate the test that uses followUp.session_payload and
replace the string-contains check with JSON.parse(followUp.session_payload) and
an assertion like parsed.invalidated.includes('beta') (or the test framework
equivalent, e.g., expect(parsed.invalidated).toContain('beta')) to make the
check formatting-tolerant.

In `@tests/unit/retrieve.test.ts`:
- Around line 2718-2731: The stdio compaction test omits asserting the
expandable field, so add an assertion that compactRetrieveResultForStdio
preserves the expandable signal: after computing compactResult in the test (it
'strips evidence_class from compact stdio retrieve payloads'), assert that
compactResult.expandable equals rawResult.expandable (or that compactResult has
the expandable property and its value matches rawResult.expandable) so the test
will fail if compactRetrieveResultForStdio starts dropping expandable.

In `@tests/unit/review-compare.test.ts`:
- Around line 173-181: The unit test is brittle because it inspects source
strings of generateReviewCompareArtifacts; instead, update the test to assert
behavior by importing generateReviewCompareArtifacts and the shared helper
renderReviewPrompt (or mocking/spying on it) and verifying that calling
generateReviewCompareArtifacts results in invoking renderReviewPrompt and/or
produces the expected output contract, rather than searching for
'renderReviewPrompt(' or 'buildContextPrompt(' in the file text; replace the
readFileSync/string matching logic with a behavioral assertion using the
function generateReviewCompareArtifacts and a spy/mock on renderReviewPrompt.

In `@tests/unit/stdio-tool-profile.test.ts`:
- Around line 215-235: The test only checks that 'context_pack' is blocked;
update the spec in the it block to iterate over all three full-only tool names
(context_pack, context_prompt, context_session_reset) and for each call
handleStdioRequest (using withProfile('core', ...)) assert the response.error
has code -32601 and that the message contains the tool name and
'GRAPHIFY_TOOL_PROFILE=full'; locate the current test that calls
handleStdioRequest and replace the single-name assertion with a small
loop/parameterized map over the three names so each is exercised the same way.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3259743d-fd04-4b30-aa6e-bf2f5e2992a5

📥 Commits

Reviewing files that changed from the base of the PR and between f271130 and bf8c0ad.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (45)
  • README.md
  • docs/benchmarks/2026-04-30-govalidate/README.md
  • docs/benchmarks/2026-05-02-govalidate-pr-review/README.md
  • examples/mcp-tool-examples.md
  • examples/why-graphify.md
  • package.json
  • src/cli/main.ts
  • src/cli/parser.ts
  • src/contracts/context-pack.ts
  • src/contracts/context-session.ts
  • src/infrastructure/benchmark.ts
  • src/infrastructure/benchmark/questions.ts
  • src/infrastructure/benchmark/runner.ts
  • src/infrastructure/compare.ts
  • src/infrastructure/context-pack-command.ts
  • src/infrastructure/context-prompt-command.ts
  • src/infrastructure/context-prompt.ts
  • src/infrastructure/review-compare.ts
  • src/runtime/context-pack.ts
  • src/runtime/context-session.ts
  • src/runtime/feature-map.ts
  • src/runtime/pr-impact.ts
  • src/runtime/relevant-files.ts
  • src/runtime/retrieve.ts
  • src/runtime/stdio-server.ts
  • src/runtime/stdio/definitions.ts
  • src/runtime/stdio/prompts.ts
  • src/runtime/stdio/tools.ts
  • tests/unit/benchmark-artifact.test.ts
  • tests/unit/benchmark.test.ts
  • tests/unit/cli.test.ts
  • tests/unit/compare.test.ts
  • tests/unit/context-pack-command.test.ts
  • tests/unit/context-pack.test.ts
  • tests/unit/context-prompt-command.test.ts
  • tests/unit/context-prompt.test.ts
  • tests/unit/package-metadata.test.ts
  • tests/unit/pr-impact.test.ts
  • tests/unit/retrieve.test.ts
  • tests/unit/review-compare.test.ts
  • tests/unit/stdio-pr-impact.test.ts
  • tests/unit/stdio-prompts.test.ts
  • tests/unit/stdio-server.test.ts
  • tests/unit/stdio-tool-profile.test.ts
  • tests/unit/why-graphify-doc.test.ts

Comment thread src/infrastructure/context-prompt-command.ts
Comment thread src/infrastructure/context-prompt-command.ts
Comment thread src/runtime/context-session.ts Outdated
Comment thread src/runtime/relevant-files.ts Outdated
Comment thread src/runtime/stdio-server.ts
Comment on lines +236 to +278
{
name: 'context_pack',
description:
'Build a compact explain/review/impact context pack for a downstream agent. Use when you need expandable refs plus coverage and missing-context signals instead of the full graph payload.',
inputSchema: {
type: 'object',
required: ['prompt'],
properties: {
prompt: { type: 'string', description: 'Task prompt or question to build context for' },
task: { type: 'string', enum: ['explain', 'review', 'impact'], description: 'Context-pack mode (default: explain)' },
budget: { type: 'number', description: 'Optional: maximum token budget for the pack (default 3000)' },
},
},
},
{
name: 'context_prompt',
description:
'Compile a provider-ready context prompt. Use provider=claude with session_id for cache-aware follow-ups, or provider=gemini for a plain prompt string.',
inputSchema: {
type: 'object',
required: ['prompt', 'provider'],
properties: {
prompt: { type: 'string', description: 'Task prompt or question to compile' },
provider: { type: 'string', enum: ['claude', 'gemini'], description: 'Target prompt consumer' },
budget: { type: 'number', description: 'Optional: retrieval budget used to gather graph evidence (default 3000)' },
session_id: { type: 'string', description: 'Optional: server-managed Claude session key for cache-aware follow-ups.' },
reset_session: { type: 'boolean', description: 'Optional: clear any stored server-side session before compiling this prompt.' },
session_state: { type: 'object', description: 'Optional: explicit previous session_state payload to continue without using session_id.' },
},
},
},
{
name: 'context_session_reset',
description:
'Reset a stored context_prompt session when switching topics or when you want the next Claude prompt to resend the full stable context.',
inputSchema: {
type: 'object',
required: ['session_id'],
properties: {
session_id: { type: 'string', description: 'Server-managed context_prompt session key to clear' },
},
},
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

These tools still won't show up on the default MCP server profile.

Registering the definitions here is not enough by itself: activeMcpTools() defaults to the core profile, and CORE_TOOL_NAMES in this file still omits context_pack, context_prompt, and context_session_reset. In a normal server boot, these new tools stay filtered out unless the user explicitly opts into GRAPHIFY_TOOL_PROFILE=full, which means the shipped MCP surface is narrower than this PR advertises.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/runtime/stdio/definitions.ts` around lines 236 - 278, The new tools are
defined but not exposed because activeMcpTools() still defaults to the core
profile and CORE_TOOL_NAMES omits the three new tool names; update the MCP
exposure by adding 'context_pack', 'context_prompt', and 'context_session_reset'
to CORE_TOOL_NAMES (or change activeMcpTools() default/profile logic to include
them) so these definitions are included in the default/core toolset that
activeMcpTools() returns.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/runtime/context-session.ts (1)

38-74: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use null-prototype object and Object.hasOwn() for safe property storage.

Line 42 writes arbitrary ref keys into a plain object, and line 72 uses ref in nextRefs. While current ref values are hardcoded constants and safe section names, using a null-prototype object with Object.hasOwn() protects against accidental introduction of special keys (like __proto__, constructor) in future code changes.

Proposed fix
-  const nextRefs: ContextSessionState['refs'] = {}
+  const nextRefs: ContextSessionState['refs'] = Object.create(null) as ContextSessionState['refs']
@@
   const invalidated = Object.keys(baseState.refs)
-    .filter((ref) => !(ref in nextRefs))
+    .filter((ref) => !Object.hasOwn(nextRefs, ref))
     .sort((left, right) => left.localeCompare(right))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/runtime/context-session.ts` around lines 38 - 74, Create nextRefs as a
null-prototype object (e.g., Object.create(null)) and replace any uses of the
"in" operator with Object.hasOwn(nextRefs, ref) to avoid prototype key
collisions; specifically update the nextRefs initialization
(ContextSessionState['refs'] nextRefs), the invalidated computation (replace
"ref in nextRefs" with !Object.hasOwn(nextRefs, ref)), and the reusedTokenCount
reduce (when reading nextRefs[ref]?.token_count guard with
Object.hasOwn(nextRefs, ref) or prefer baseState.refs[ref]?.token_count ??
(Object.hasOwn(nextRefs, ref) ? nextRefs[ref].token_count : 0)) so all property
checks and reads on nextRefs are prototype-safe.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/runtime/context-session.ts`:
- Around line 33-69: Detect and ignore duplicate ref keys before building
session deltas: when iterating sortedRefs in the loop that builds
nextRefs/added/updated/reused_refs, keep a Set (e.g., seenRefs) of ref.ref
values and skip any subsequent entries with the same ref.ref so only the first
occurrence is processed; this ensures nextRefs, added, updated and reused_refs
remain consistent with baseState.refs (update the loop that references
sortedRefs, nextRefs, added, updated, reused_refs and baseState.refs
accordingly), and optionally emit a warning/log when a duplicate is skipped for
visibility.

---

Duplicate comments:
In `@src/runtime/context-session.ts`:
- Around line 38-74: Create nextRefs as a null-prototype object (e.g.,
Object.create(null)) and replace any uses of the "in" operator with
Object.hasOwn(nextRefs, ref) to avoid prototype key collisions; specifically
update the nextRefs initialization (ContextSessionState['refs'] nextRefs), the
invalidated computation (replace "ref in nextRefs" with !Object.hasOwn(nextRefs,
ref)), and the reusedTokenCount reduce (when reading nextRefs[ref]?.token_count
guard with Object.hasOwn(nextRefs, ref) or prefer
baseState.refs[ref]?.token_count ?? (Object.hasOwn(nextRefs, ref) ?
nextRefs[ref].token_count : 0)) so all property checks and reads on nextRefs are
prototype-safe.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5ce0846d-5474-4829-b6cb-00934bf16fa6

📥 Commits

Reviewing files that changed from the base of the PR and between bf8c0ad and 65d8637.

📒 Files selected for processing (13)
  • src/infrastructure/context-prompt-command.ts
  • src/infrastructure/context-prompt.ts
  • src/runtime/context-session.ts
  • src/runtime/feature-map.ts
  • src/runtime/relevant-files.ts
  • src/runtime/stdio-server.ts
  • src/runtime/stdio/tools.ts
  • tests/unit/context-prompt-command.test.ts
  • tests/unit/context-session.test.ts
  • tests/unit/feature-map.test.ts
  • tests/unit/relevant-files.test.ts
  • tests/unit/stdio-server.test.ts
  • tests/unit/stdio-tool-profile.test.ts
✅ Files skipped from review due to trivial changes (2)
  • tests/unit/context-session.test.ts
  • src/runtime/stdio/tools.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/infrastructure/context-prompt.ts
  • tests/unit/context-prompt-command.test.ts
  • tests/unit/stdio-server.test.ts

Comment thread src/runtime/context-session.ts
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mohanagy mohanagy merged commit 97da1d4 into main May 8, 2026
7 checks passed
@mohanagy mohanagy deleted the context-plane-full branch May 8, 2026 10:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant