Files
reverse-engineering-anything/src/contracts/sessionToolSchemas.ts
T
Kaoru0822andClaude Opus 5.5 710fad8acf feat(evidence): discover missing Evidence links without transferring records (#8633)
* feat(evidence): discover missing Evidence links without transferring records

An agent could only learn that a retained record's source was absent by reading
complete records or by having a downstream analysis refuse. The summary said
nothing about links, and complete-record retention was easy to mistake for
source closure.

- Add detail: links to get_evidence_bundle and CLI inspect-evidence-bundle:
  paged link rows with retained or missing status and no record payloads, for
  selected records against the whole session or file.
- Add retained-closure traversal, the walk composed workflows require, reporting
  complete or incomplete. Direct reads make no closure claim.
- Count direct and missing direct links in the summary.

Fixes #8454

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

* fix(evidence): count a repeated Evidence link once in every delivery

The Evidence schema does not deduplicate evidence_links, so the summary counted
a repeated link twice while link rows and counts reported it once. Both now read
one helper for a record's distinct direct links.

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

* test(evidence): validate link delivery against the advertised schemas

The test never called tools/list, so neither the shared validator nor the MCP
client checked its replies against what each profile advertises. A schema that
rejected the links result could have passed. Fetch the advertised definition and
validate every request and reply against it.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 05:14:34 -08:00

100 lines
3.4 KiB
TypeScript

import { z } from "zod";
import { absoluteLocalPathStringSchema } from "../domain/localPath.js";
import { bundleComparisonInputSchema } from "../domain/bundleComparison.js";
import { prefixedDigestSchema } from "./../domain/digests.js";
import {
EVIDENCE_LINK_INSPECTION_LIMIT,
EVIDENCE_RECORD_SELECTION_LIMIT,
evidenceLinkStatusFilterSchema,
evidenceLinkTraversalSchema,
evidenceRecordFiltersSchema,
} from "../domain/evidenceRecordSummary.js";
import { residualUnknownSchema } from "../domain/residualUnknown.js";
/** Complete retained Evidence, discovery metadata, a page of complete records, or link membership. */
export const getEvidenceBundleInputSchema = z.strictObject({
detail: z
.enum(["complete", "summary", "records", "links"])
.default("complete"),
filters: evidenceRecordFiltersSchema.optional(),
offset: z
.int()
.nonnegative()
.optional()
.describe("records or links: first matching row to return; default 0."),
limit: z
.int()
.positive()
.optional()
.describe(
`records: maximum complete records, default ${String(EVIDENCE_RECORD_SELECTION_LIMIT)}. links: maximum link rows, default ${String(EVIDENCE_LINK_INSPECTION_LIMIT)}.`,
),
traversal: evidenceLinkTraversalSchema
.optional()
.describe(
"links only: direct (default) reads the selected records' own links; retained-closure also follows retained links.",
),
link_status: evidenceLinkStatusFilterSchema
.optional()
.describe(
"links only: rows to return, default missing. Counts always cover every inspected link.",
),
});
/** Optional document selection for volatile navigation context. */
export const navigationContextInputSchema = z.strictObject({
document: z.string().min(1).optional(),
});
/** Explicit reproducible address context query. */
export const addressContextInputSchema = z.strictObject({
address: z.string().min(1),
document: z.string().min(1).optional(),
});
/** Session-owned Evidence bundle import options. */
export const importEvidenceBundleInputSchema = z.strictObject({
path: absoluteLocalPathStringSchema.describe(
"Absolute local filesystem path for the evidence bundle to import; relative paths are rejected.",
),
});
/** MCP compares files selected on the server host, so require explicit paths. */
export const bundleComparisonMcpInputSchema =
bundleComparisonInputSchema.extend({
left_bundle_path: absoluteLocalPathStringSchema.describe(
"Absolute local filesystem path to the left Evidence bundle.",
),
right_bundle_path: absoluteLocalPathStringSchema.describe(
"Absolute local filesystem path to the right Evidence bundle.",
),
});
/** Residual-unknown list filters. */
export const listUnknownsInputSchema = z.strictObject({
status: residualUnknownSchema.shape.status.optional(),
severity: residualUnknownSchema.shape.severity.optional(),
domain: residualUnknownSchema.shape.domain.optional(),
offset: z
.int()
.min(0)
.max(Number.MAX_SAFE_INTEGER)
.default(0)
.describe("Zero-based offset in the stable filtered unknown ID order."),
limit: z
.int()
.positive()
.max(Number.MAX_SAFE_INTEGER)
.optional()
.describe(
"Optional maximum number of heads to return. Omit to return every matching head from offset.",
),
});
/** Exact residual-unknown identity to revalidate. */
export const verifyUnknownResolutionInputSchema = z.strictObject({
unknown_id: prefixedDigestSchema("unk"),
});