Files
rea/src/application/binary/BinarySessionPort.ts
T
Kaoru0822andClaude Opus 5.5 5a22ae6bc8 fix(mcp)!: return a compact binary_session status by default (#7127)
* fix(mcp)!: return a compact binary_session status by default

binary_session {} with no target open returned about 66 KB, most of it
provider rejection diagnostics and candidate capability sets that the
skill's recovery flow re-reads on every retry. 6.8.0 grew it by 21%
because the shared regex capability limitation began repeating setting
bounds and step-by-step recovery for every search operation of every
provider (#6099, #6267, #6301, #7049) and IDA gained that limitation for
its two search operations (#4862).

The regex limitation now states the effective deadline and heap, their
sources and where to change them; the deadline and heap errors keep the
full recovery. binary_session gains detail: summary (default) or
complete. The summary keeps open state, target identity, the binding,
route capabilities, run, activity and health status, each candidate's
availability and target-support status, code and reason, and every
tool's availability, reason, remediation and modes, and lists the
fields it leaves out in omitted_fields. Complete detail returns the
previous shape. The CLI capabilities and providers commands keep
complete provider facts through the same application projection.

BREAKING CHANGE: binary_session {} no longer returns
analysis_provider_candidates[].availability.diagnostics,
target_support.diagnostics or capabilities, or tool_availability group
surface, effects and annotations. Pass {"detail": "complete"} to get
them.

Fixes #7109

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(mcp): key binary_session output fields by detail

The output schema accepted detail: "complete" with summary candidates or
tool groups, and a summary without omitted_fields, so detail did not
tell callers which fields existed. Each session kind is now crossed
with a detail-specific shape: a summary requires omitted_fields and
summary-only candidates and tool groups; complete requires diagnostics,
candidate capabilities and static tool flags and forbids omitted_fields.
Both the canonical schema and the SDK-validated advertised schema reject
mismatched shapes.

The verifier helper accepts summary candidates only for a validated MCP
summary; CLI provider output still requires candidate capabilities.
Regex limitation tests check values, sources and setting names instead
of whole sentences.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 05:29:03 -07:00

125 lines
5.4 KiB
TypeScript

import type { InvestigationRecordPort } from "../investigation/InvestigationRecordPort.js";
import type { ExecutableFormatHint } from "../../domain/dosCom.js";
import type {
BinaryArchitecture,
BinaryTarget,
} from "../../domain/binaryTargetTypes.js";
import type { JsonValue } from "../../domain/jsonValue.js";
import type { AnalysisSnapshot } from "../../domain/analysisSnapshot.js";
import type { AnalysisProfileCommitment } from "../../domain/analysisProfile.js";
import type { AnalysisProviderSelector } from "../../contracts/providerSelection.js";
import type { BinarySessionDetail } from "../../contracts/sessionStatusContract.js";
import type { AnalysisError } from "../../domain/analysisErrorBase.js";
import type { Result } from "../../domain/result.js";
import type { EvidenceIntegrityError } from "../../domain/evidenceErrors.js";
import type { AnalysisSnapshotLoader } from "./BinarySessionOpen.js";
import type { WorkflowSnapshotRecordInput } from "./BinarySessionRecords.js";
import type { ResolvedAppBundleResourceRoot } from "../AppBundleExecutable.js";
import type {
AnalysisExecution,
AnalysisOperation,
AnalysisOperationPort,
ExecutionOptions,
ProviderIdentity,
} from "../AnalysisProvider.js";
/** Receipt for an atomically saved snapshot followed by provider cleanup. */
export interface SavedAnalysisSnapshot {
readonly path: string;
readonly bytes: number;
/** Eligible primitive query bindings. */
readonly primitive_entries: number;
/** Eligible composed workflow bindings, separate from primitive queries. */
readonly workflow_entries: number;
/** All retained Evidence records, including observations without a replay binding. */
readonly evidence_records: number;
}
/** Target lifecycle used by CLI and MCP without exposing a concrete provider. */
export interface BinarySessionPort
extends AnalysisOperationPort, InvestigationRecordPort {
/** Execute only against a positively ready, already-created provider client. */
executeIfProviderReady(
operation: AnalysisOperation,
parameters: Readonly<Record<string, JsonValue>>,
options?: Pick<ExecutionOptions, "signal" | "selectorOrigin">,
): Promise<Result<AnalysisExecution, AnalysisError> | undefined>;
/** Hold the active target binding through a complete composed operation. */
withAdmittedAnalysis<Value>(
operationName: string,
signal: AbortSignal | undefined,
operation: (analysis: AnalysisOperationPort) => Promise<Value>,
): Promise<Result<Value, AnalysisError>>;
/** Serialize an external mutation and retire any active target afterward. */
withAdmittedExternalMutation<Value>(
_path: string | undefined,
signal: AbortSignal | undefined,
operation: () => Promise<Result<Value, AnalysisError>>,
retirementFailure: (
value: Result<Value, AnalysisError>,
error: AnalysisError,
) => AnalysisError,
operationName?: string,
cleanupRecovery?: (
failure: AnalysisError | undefined,
) => Promise<Result<null, AnalysisError>>,
): Promise<Result<Result<Value, AnalysisError>, AnalysisError>>;
open(
path: string,
options?: {
readonly signal?: AbortSignal;
readonly targetKind?: BinaryTarget["kind"];
readonly formatHint?: ExecutableFormatHint;
readonly architecture?: BinaryArchitecture;
readonly entryPoint?: string;
readonly snapshot?: AnalysisSnapshot;
readonly loadSnapshot?: AnalysisSnapshotLoader;
readonly providerId?: AnalysisProviderSelector;
},
): Promise<Result<BinaryTarget, AnalysisError>>;
/** Open a resource-only app root without selecting or inventing an executable target. */
openBundleResources(
path: string,
options?: Pick<ExecutionOptions, "signal">,
): Promise<Result<ResolvedAppBundleResourceRoot, AnalysisError>>;
close(
options?: Pick<ExecutionOptions, "progress"> & {
readonly retainProviderDocuments?: boolean;
},
): Promise<Result<null, AnalysisError>>;
/** Save a snapshot and close while excluding later provider requests. */
closeWithSnapshot(
path: string,
overwrite: boolean,
options?: Pick<ExecutionOptions, "progress">,
): Promise<Result<SavedAnalysisSnapshot, AnalysisError>>;
/** Default complete detail; summary omits provider diagnostics and candidate capabilities. */
status(options?: {
readonly signal?: AbortSignal;
readonly detail?: BinarySessionDetail;
}): Promise<JsonValue>;
activeTarget(): BinaryTarget | undefined;
/** Read a snapshot with failed descriptors retained for session cleanup retry. */
readAnalysisSnapshot(
path: string,
signal?: AbortSignal,
): Promise<Result<AnalysisSnapshot, AnalysisError>>;
exportAnalysisSnapshot(): Result<AnalysisSnapshot, AnalysisError>;
importAnalysisSnapshot(
snapshot: AnalysisSnapshot,
): Result<number, AnalysisError>;
providerIdentity(operation?: AnalysisOperation): ProviderIdentity;
analysisProfile(
operation?: AnalysisOperation,
): AnalysisProfileCommitment | undefined;
allowsSnapshotReplay(operation: AnalysisOperation): boolean;
/** Invalidate cached Evidence before an external command may mutate the target. */
invalidateSnapshotForExternalMutation(): void;
recordWorkflowSnapshot(
input: WorkflowSnapshotRecordInput,
): Result<null, EvidenceIntegrityError>;
onAvailabilityChanged?(listener: () => void | Promise<void>): () => void;
onAnalysisSnapshotChanged?(listener: () => void | Promise<void>): () => void;
}