From f8248417d7f66d6abd46095a877959348d75dd7e Mon Sep 17 00:00:00 2001 From: morluto <76467478+morluto@users.noreply.github.com> Date: Sat, 24 Oct 2026 04:03:06 +0800 Subject: [PATCH] fix(capabilities): report missing navigation targets --- src/application/CapabilityInventory.test.ts | 16 ++++++++++++++++ src/application/CapabilityInventory.ts | 6 ++++-- src/contracts/sessionToolContracts.ts | 13 ++++++++----- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/application/CapabilityInventory.test.ts b/src/application/CapabilityInventory.test.ts index c441d10194..1a27a69550 100644 --- a/src/application/CapabilityInventory.test.ts +++ b/src/application/CapabilityInventory.test.ts @@ -415,6 +415,22 @@ describe("compact tool availability", () => { }); describe("partial navigation availability", () => { + it("requires a target before diagnosing navigation provider modes", () => { + expect(entry("get_navigation_context", status())).toMatchObject({ + available: false, + reason: "target_required", + default_mode_available: false, + modes: [ + { name: "current_selection", available: false }, + { name: "explicit_document", available: false }, + ], + }); + expect( + TOOL_CONTRACTS.find((tool) => tool.name === "get_navigation_context"), + ).toMatchObject({ + requiresActiveTarget: true, + }); + }); it("allows explicit documents when the provider has no current-document getter", () => { const capabilities = [ "current_document", diff --git a/src/application/CapabilityInventory.ts b/src/application/CapabilityInventory.ts index d2cd567c23..81795cbe21 100644 --- a/src/application/CapabilityInventory.ts +++ b/src/application/CapabilityInventory.ts @@ -383,12 +383,14 @@ const availabilityFor = (context: AvailabilityContext): Availability => { context.name === "inspect_web_event_listeners" ) return { reason: "available", remediation: null }; - if (context.name === "get_navigation_context") - return availabilityForModes( + if (context.name === "get_navigation_context") { + const modes = availabilityForModes( NAVIGATION_CONTEXT_MODES, "current_selection", context.descriptors, ); + return { ...modes, ...targetAvailability(context) }; + } const javascriptApplication = javascriptApplicationAvailability(context); if (javascriptApplication !== null) return javascriptApplication; const failure = optionalProviderFailureFor(context); diff --git a/src/contracts/sessionToolContracts.ts b/src/contracts/sessionToolContracts.ts index 6fbb906faa..87ac16b2c7 100644 --- a/src/contracts/sessionToolContracts.ts +++ b/src/contracts/sessionToolContracts.ts @@ -168,11 +168,14 @@ export const SESSION_TOOL_CONTRACTS = [ "Return every retained Evidence record and residual unknown as a complete canonical bundle by default. detail=summary discovers retained records without copying or transferring their payloads; optionally filter by exact Evidence ID, operation, target SHA-256, analysis-profile digest or canonical native procedure address. Metadata distinguishes complete record retention from native value-flow truncation or unavailable/unknown coverage. Use a discovered evidence_id with inspect_analysis_view without restarting a provider. Filters apply only to summary delivery.", getEvidenceBundleInputSchema, ), - session( - "get_navigation_context", - "Return the selected document, current address, and containing/current procedure in one provider-neutral result. The result reflects sequential provider observations, not an atomic cursor snapshot; a cursor outside any procedure returns procedure: null.", - navigationContextInputSchema, - ), + { + ...session( + "get_navigation_context", + "Return the selected document, current address, and containing/current procedure in one provider-neutral result. The result reflects sequential provider observations, not an atomic cursor snapshot; a cursor outside any procedure returns procedure: null.", + navigationContextInputSchema, + ), + requiresActiveTarget: true, + }, session( "inspect_address_context", "Inspect one explicit reproducible address for its analyzed name, containing procedure, regular and inline comments, and matching bookmarks. Each unsupported facet returns a typed unavailable outcome; use xrefs, assembly, or pseudocode for those deeper views.",