perf(artifacts): deliver the inspected artifact graph once (#1473)
inspect_artifact nested the complete inventory Evidence and then restated every artifact node and occurrence as an observation and every edge as a derived relationship. No caller reads those copies; comparison and tests use the nested inventory Evidence. On Transmission.app the result shrinks from 2.46 MB to 1.10 MB. Observations keep the root manifest and integrity findings. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
aa23ec883f
commit
3c7b176a3d
|
|
@ -63,7 +63,7 @@ const artifact = <
|
|||
export const ARTIFACT_TOOL_CONTRACTS = [
|
||||
artifact(
|
||||
"inspect_artifact",
|
||||
"Inspect an active archive or application package in one call. Returns the complete content-addressed artifact graph, source Evidence, observations, relationships, integrity contradictions, hypotheses, unexplored branches, limitations, and next probes inline. Read-only DMG mounting is used automatically on supported macOS hosts. Integrity mismatches fail by default; record-and-continue keeps mismatches explicitly untrusted. It does not extract files; use extract_artifact to materialize its regular contents.",
|
||||
"Inspect an active archive or application package in one call. Returns the complete content-addressed artifact graph once, as the nested inventory Evidence, with root and integrity observations, integrity contradictions, hypotheses, unexplored branches, limitations, and next probes inline. Read-only DMG mounting is used automatically on supported macOS hosts. Integrity mismatches fail by default; record-and-continue keeps mismatches explicitly untrusted. It does not extract files; use extract_artifact to materialize its regular contents.",
|
||||
artifactInventoryInputSchema,
|
||||
),
|
||||
artifact(
|
||||
|
|
|
|||
|
|
@ -16,30 +16,12 @@ const artifactIdSchema = prefixedDigestSchema("art");
|
|||
|
||||
const inspectionObservationSchema = z.strictObject({
|
||||
observation_id: prefixedDigestSchema("aio"),
|
||||
kind: z.enum(["root-manifest", "artifact", "occurrence", "integrity"]),
|
||||
kind: z.enum(["root-manifest", "integrity"]),
|
||||
subject: textSchema,
|
||||
value: jsonValueSchema,
|
||||
evidence_id: evidenceIdSchema,
|
||||
});
|
||||
|
||||
const inspectionRelationshipSchema = z.strictObject({
|
||||
relationship_id: prefixedDigestSchema("air"),
|
||||
relation: z.enum([
|
||||
"contains",
|
||||
"extracts",
|
||||
"slice-of",
|
||||
"embeds",
|
||||
"loads",
|
||||
"maps-source",
|
||||
"derived-from",
|
||||
]),
|
||||
source_artifact_id: artifactIdSchema,
|
||||
target_artifact_id: artifactIdSchema,
|
||||
occurrence_id: prefixedDigestSchema("occ"),
|
||||
logical_path: textSchema.nullable(),
|
||||
evidence_id: evidenceIdSchema,
|
||||
});
|
||||
|
||||
const inspectionHypothesisSchema = z.strictObject({
|
||||
hypothesis_id: prefixedDigestSchema("aih"),
|
||||
statement: textSchema,
|
||||
|
|
@ -97,7 +79,6 @@ export const artifactInspectionResultSchema = z.strictObject({
|
|||
)
|
||||
.min(1),
|
||||
observations: z.array(inspectionObservationSchema),
|
||||
derived_relationships: z.array(inspectionRelationshipSchema),
|
||||
hypotheses: z.array(inspectionHypothesisSchema),
|
||||
contradictions: z.array(inspectionContradictionSchema),
|
||||
unexplored_branches: z.array(unexploredBranchSchema),
|
||||
|
|
@ -107,8 +88,6 @@ export const artifactInspectionResultSchema = z.strictObject({
|
|||
substeps_completed: z.literal(1),
|
||||
observations_retained: z.number().int().min(0),
|
||||
observations_omitted: z.number().int().min(0),
|
||||
relationships_retained: z.number().int().min(0),
|
||||
relationships_omitted: z.number().int().min(0),
|
||||
hypotheses_retained: z.number().int().min(0),
|
||||
hypotheses_omitted: z.number().int().min(0),
|
||||
unexplored_branches_retained: z.number().int().min(0),
|
||||
|
|
@ -136,10 +115,6 @@ export const createArtifactInspection = (
|
|||
inventory,
|
||||
inventoryEvidence.evidence_id,
|
||||
);
|
||||
const relationships = allRelationships(
|
||||
inventory,
|
||||
inventoryEvidence.evidence_id,
|
||||
);
|
||||
const hypotheses = allHypotheses(inventory, inventoryEvidence.evidence_id);
|
||||
const nextProbes = probesFor(inventory);
|
||||
const branches = allUnexploredBranches(
|
||||
|
|
@ -149,14 +124,12 @@ export const createArtifactInspection = (
|
|||
);
|
||||
const retained = {
|
||||
observations,
|
||||
relationships,
|
||||
hypotheses,
|
||||
branches,
|
||||
probes: nextProbes,
|
||||
};
|
||||
const omissions = {
|
||||
observations: 0,
|
||||
relationships: 0,
|
||||
hypotheses: 0,
|
||||
branches: 0,
|
||||
probes: 0,
|
||||
|
|
@ -184,7 +157,6 @@ export const createArtifactInspection = (
|
|||
},
|
||||
],
|
||||
observations: retained.observations,
|
||||
derived_relationships: retained.relationships,
|
||||
hypotheses: retained.hypotheses,
|
||||
contradictions: contradictions(inventory, inventoryEvidence.evidence_id),
|
||||
unexplored_branches: retained.branches,
|
||||
|
|
@ -194,8 +166,6 @@ export const createArtifactInspection = (
|
|||
substeps_completed: 1 as const,
|
||||
observations_retained: retained.observations.length,
|
||||
observations_omitted: omissions.observations,
|
||||
relationships_retained: retained.relationships.length,
|
||||
relationships_omitted: omissions.relationships,
|
||||
hypotheses_retained: retained.hypotheses.length,
|
||||
hypotheses_omitted: omissions.hypotheses,
|
||||
unexplored_branches_retained: retained.branches.length,
|
||||
|
|
@ -224,6 +194,8 @@ const parseInventoryEvidence = (input: unknown): Evidence => {
|
|||
return evidence;
|
||||
};
|
||||
|
||||
// Artifact, occurrence, and edge records stay in the nested inventory Evidence;
|
||||
// restating each one here would repeat the complete graph in every result.
|
||||
const allObservations = (
|
||||
inventory: ArtifactInventoryResult,
|
||||
evidenceId: string,
|
||||
|
|
@ -234,12 +206,6 @@ const allObservations = (
|
|||
inventory.manifest,
|
||||
evidenceId,
|
||||
),
|
||||
...inventory.nodes.map((node) =>
|
||||
observation("artifact", node.artifact_id, node, evidenceId),
|
||||
),
|
||||
...inventory.occurrences.map((occurrence) =>
|
||||
observation("occurrence", occurrence.occurrence_id, occurrence, evidenceId),
|
||||
),
|
||||
...inventory.integrity_contradictions.map((value) =>
|
||||
observation("integrity", value.contradiction_id, value, evidenceId),
|
||||
),
|
||||
|
|
@ -263,25 +229,6 @@ const observation = (
|
|||
};
|
||||
};
|
||||
|
||||
const allRelationships = (
|
||||
inventory: ArtifactInventoryResult,
|
||||
evidenceId: string,
|
||||
): ArtifactInspectionResult["derived_relationships"] =>
|
||||
inventory.edges.map((edge) => {
|
||||
const semantic = {
|
||||
relation: edge.relation,
|
||||
source_artifact_id: edge.parent_artifact_id,
|
||||
target_artifact_id: edge.child_artifact_id,
|
||||
occurrence_id: edge.occurrence_id,
|
||||
logical_path: edge.logical_path,
|
||||
evidence_id: evidenceId,
|
||||
};
|
||||
return {
|
||||
relationship_id: `air_${digestCanonicalValue(semantic, "Artifact inspection")}`,
|
||||
...semantic,
|
||||
};
|
||||
});
|
||||
|
||||
const allHypotheses = (
|
||||
inventory: ArtifactInventoryResult,
|
||||
evidenceId: string,
|
||||
|
|
|
|||
|
|
@ -60,6 +60,15 @@ describe("artifact archive inventory", () => {
|
|||
expect(inspectionEvidence.evidence_links).toEqual(
|
||||
inspection.evidence_links,
|
||||
);
|
||||
// The graph is delivered once, in the nested inventory Evidence.
|
||||
expect(
|
||||
artifactInventoryResultSchema.parse(
|
||||
inspection.substeps[0]?.evidence.normalized_result,
|
||||
).occurrences,
|
||||
).toHaveLength(3);
|
||||
expect(inspection.observations.map(({ kind }) => kind)).toEqual([
|
||||
"root-manifest",
|
||||
]);
|
||||
const cancellation = new AbortController();
|
||||
cancellation.abort();
|
||||
await expect(
|
||||
|
|
|
|||
Loading…
Reference in New Issue