@neat.is/types 0.5.0 → 0.5.1-dev.20260720

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -474,7 +474,15 @@ var GraphEdgeSchema = import_zod3.z.object({
474
474
  lastObserved: import_zod3.z.string().datetime().optional(),
475
475
  callCount: import_zod3.z.number().int().nonnegative().optional(),
476
476
  evidence: EdgeEvidenceSchema.optional(),
477
- signal: EdgeSignalSchema.optional()
477
+ signal: EdgeSignalSchema.optional(),
478
+ // OBSERVED grain (ADR-142): `file` when the edge originates from a source
479
+ // file's call site (a `file:` source + `evidence`), `service` for the coarse
480
+ // fallback where no call site was captured. Makes "service-grained only as a
481
+ // labeled fallback" (connector gate #803) a stored, machine-readable fact
482
+ // instead of a re-derivation from the source prefix. `.optional()` — EXTRACTED
483
+ // edges and legacy snapshots carry none; an OBSERVED edge is backfilled on its
484
+ // next observation.
485
+ grain: import_zod3.z.enum(["file", "service"]).optional()
478
486
  });
479
487
 
480
488
  // src/events.ts
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/nodes.ts","../src/edges.ts","../src/events.ts","../src/results.ts","../src/identity.ts","../src/policy.ts","../src/registry.ts","../src/divergence.ts","../src/mcp-tools.ts","../src/responses.ts","../src/confidence.ts"],"sourcesContent":["export * from './constants.js'\nexport * from './nodes.js'\nexport * from './edges.js'\nexport * from './events.js'\nexport * from './results.js'\nexport * from './identity.js'\nexport * from './policy.js'\nexport * from './registry.js'\nexport * from './divergence.js'\nexport * from './mcp-tools.js'\nexport * from './responses.js'\nexport * from './confidence.js'\nexport * from './connectors.js'\n","export const Provenance = {\n EXTRACTED: 'EXTRACTED',\n INFERRED: 'INFERRED',\n OBSERVED: 'OBSERVED',\n STALE: 'STALE',\n} as const\n\nexport type ProvenanceValue = (typeof Provenance)[keyof typeof Provenance]\n\nexport const EdgeType = {\n CALLS: 'CALLS',\n DEPENDS_ON: 'DEPENDS_ON',\n CONNECTS_TO: 'CONNECTS_TO',\n CONFIGURED_BY: 'CONFIGURED_BY',\n PUBLISHES_TO: 'PUBLISHES_TO',\n CONSUMES_FROM: 'CONSUMES_FROM',\n RUNS_ON: 'RUNS_ON',\n // A service owns its files (ADR-089 / docs/contracts/file-awareness.md §2):\n // `service ──CONTAINS──▶ file`. Structural ownership, not traffic — the\n // grouping that lets file-grained relationships roll up to a service only\n // as the honest fallback, never as a summary view.\n CONTAINS: 'CONTAINS',\n // Static module dependency between two FileNodes within a service (ADR-092,\n // file-awareness.md §10). Compile-time, not runtime — represents one file\n // importing another. Distinct from CALLS which records runtime invocations.\n IMPORTS: 'IMPORTS',\n} as const\n\nexport type EdgeTypeValue = (typeof EdgeType)[keyof typeof EdgeType]\n\nexport const NodeType = {\n ServiceNode: 'ServiceNode',\n DatabaseNode: 'DatabaseNode',\n ConfigNode: 'ConfigNode',\n InfraNode: 'InfraNode',\n FrontierNode: 'FrontierNode',\n // The primary node of the file-first graph (ADR-089). A source file owned\n // by a service; relationships originate from it. See\n // docs/contracts/file-awareness.md §1.\n FileNode: 'FileNode',\n // A server route at (method, path-template) granularity (ADR-119). Extracted\n // from a mainstream router (Express / Fastify / Next.js) so a client call\n // site can be matched to the exact route it names, rather than only to the\n // owning service. The node an OBSERVED server span lands on too, which is\n // what makes a two-sided divergence possible at route grain. See\n // docs/contracts/static-extraction.md.\n RouteNode: 'RouteNode',\n // A named GraphQL operation — one query, mutation, or subscription — at\n // (service, operationType, operationName) granularity (ADR-122). Every\n // GraphQL request rides one HTTP endpoint (POST /graphql), so at HTTP grain\n // the whole API collapses to a single edge; this node recovers the\n // operation-level topology from the execution span's `graphql.operation.*`\n // semconv. Minted observed-first from OTel; a future static GraphQL extractor\n // fuses onto the same id. See docs/contracts/otel-ingest.md.\n GraphQLOperationNode: 'GraphQLOperationNode',\n // A single gRPC method — one `rpc` in a `.proto` service — at\n // (rpcService, rpcMethod) granularity (ADR-123). gRPC used to engage only at\n // service grain: every method collapsed onto one service→service edge, so the\n // per-method topology was invisible and one-sided. This node recovers the\n // method-level shape from both sides: the OBSERVED execution span's\n // `rpc.service` / `rpc.method` semconv and the static `.proto` service/method\n // definitions. It keys on the fully-qualified `rpc.service` — the wire\n // contract both sides carry verbatim — so a declared method and an observed\n // one fuse onto the same node into a two-sided divergence. See\n // docs/contracts/otel-ingest.md and docs/contracts/static-extraction.md.\n GrpcMethodNode: 'GrpcMethodNode',\n // A live WebSocket channel — the path/channel a client connects to — at\n // (service, channel) granularity (ADR-125). A WebSocket app used to produce no\n // OBSERVED topology at all: only message-handler errors surfaced, as incidents,\n // and the channels themselves stayed invisible. This node recovers the\n // channel-level topology from the HTTP upgrade span that opens the connection —\n // a SERVER `GET` carrying the WebSocket path. It is minted OBSERVED-only: a\n // WebSocket channel is known from observation, never from static extraction, so\n // there is no declared twin to fuse with. The edge onto it reuses the existing\n // `CONNECTS_TO` (`service ──CONNECTS_TO──▶ ws-channel`) as an observed-liveness\n // edge that carries `lastObserved` and decays OBSERVED → STALE on CONNECTS_TO's\n // own staleness threshold when the channel goes quiet. See\n // docs/contracts/otel-ingest.md.\n WebSocketChannelNode: 'WebSocketChannelNode',\n} as const\n\nexport type NodeTypeValue = (typeof NodeType)[keyof typeof NodeType]\n\nimport { z } from 'zod'\n\n// Zod-side mirror of NodeType, exported for schemas that need to discriminate\n// or filter by node type at parse time (policy rules, traversal results, etc.).\n// Adding a new node type means adding it to NodeType above and to this enum.\nexport const NodeTypeSchema = z.enum([\n NodeType.ServiceNode,\n NodeType.DatabaseNode,\n NodeType.ConfigNode,\n NodeType.InfraNode,\n NodeType.FrontierNode,\n NodeType.FileNode,\n NodeType.RouteNode,\n NodeType.GraphQLOperationNode,\n NodeType.GrpcMethodNode,\n NodeType.WebSocketChannelNode,\n])\n","import { z } from 'zod'\nimport { NodeType } from './constants.js'\n\nexport const CompatibleDriverSchema = z.object({\n name: z.string(),\n minVersion: z.string(),\n})\nexport type CompatibleDriver = z.infer<typeof CompatibleDriverSchema>\n\n// How NEAT first learned of a node. Static-extraction fills in the rich\n// fields (language, version, dependencies); OTel ingest can also create a\n// minimal node when it sees a span for an unknown peer. When both layers\n// recorded the same node, the value is 'merged'. ADR-031 schema growth.\nexport const DiscoveredViaSchema = z.enum(['static', 'otel', 'merged'])\nexport type DiscoveredVia = z.infer<typeof DiscoveredViaSchema>\n\nexport const ServiceNodeSchema = z.object({\n id: z.string(),\n type: z.literal(NodeType.ServiceNode),\n name: z.string(),\n language: z.string(),\n // Deployment environment from the OTel `deployment.environment.name` attr\n // (with `deployment.environment` and resource-attr fallbacks). The literal\n // `'unknown'` is the honest sentinel when no env signal is present; static\n // extraction never sees env at extract time, so its ServiceNodes carry\n // `undefined` here and the id stays in the env-less wire format\n // `service:<name>`. See ADR-074 §2 and docs/contracts/env-dimension.md.\n env: z.string().optional(),\n // Framework recorded by the static extractor when the install plan\n // dispatches a framework-specific path (Next.js, Remix, SvelteKit, Nuxt,\n // Astro). Optional enrichment — `undefined` for lib-only packages and\n // ambiguous repos. See ADR-074 §3 / docs/contracts/framework-installers.md.\n framework: z.string().optional(),\n // The hosting platform a static extractor recognized this service as\n // deployed to (`'cloudflare'` today) — a free string, same discipline as\n // `framework`, so a future platform needs no schema change. This is the\n // frontend's icon key at the service-rollup level (ADR-133,\n // docs/contracts/static-extraction.md).\n platform: z.string().optional(),\n discoveredVia: DiscoveredViaSchema.optional(),\n version: z.string().optional(),\n dbConnectionTarget: z.string().optional(),\n repoPath: z.string().optional(),\n owner: z.string().optional(),\n dependencies: z.record(z.string(), z.string()).optional(),\n // Hostnames OTel spans might mention for this service: compose service\n // names, k8s metadata.name (and the cluster-DNS variants), Dockerfile\n // labels, etc. resolveServiceId in ingest.ts checks these before falling\n // back to a FRONTIER placeholder.\n aliases: z.array(z.string()).optional(),\n // Optional. If set, services declare their `engines.node` here so γ #74's\n // node-engine compat check has something to test against.\n nodeEngine: z.string().optional(),\n incompatibilities: z\n .array(\n // Discriminated by `kind`. `driver-engine` is the original shape and\n // stays default for backward compatibility — older snapshots without a\n // `kind` field still parse via the union's `.optional()` discriminator\n // fallback. New kinds came in with γ #74.\n z.union([\n z.object({\n kind: z.literal('driver-engine').optional(),\n driver: z.string(),\n driverVersion: z.string(),\n engine: z.string(),\n engineVersion: z.string(),\n reason: z.string(),\n }),\n z.object({\n kind: z.literal('node-engine'),\n package: z.string(),\n packageVersion: z.string().optional(),\n requiredNodeVersion: z.string(),\n declaredNodeEngine: z.string().optional(),\n reason: z.string(),\n }),\n z.object({\n kind: z.literal('package-conflict'),\n package: z.string(),\n packageVersion: z.string().optional(),\n requires: z.object({\n name: z.string(),\n minVersion: z.string(),\n }),\n foundVersion: z.string().optional(),\n reason: z.string(),\n }),\n z.object({\n kind: z.literal('deprecated-api'),\n package: z.string(),\n packageVersion: z.string().optional(),\n reason: z.string(),\n }),\n ]),\n )\n .optional(),\n})\nexport type ServiceNode = z.infer<typeof ServiceNodeSchema>\n\nexport const DatabaseNodeSchema = z.object({\n id: z.string(),\n type: z.literal(NodeType.DatabaseNode),\n name: z.string(),\n engine: z.string(),\n engineVersion: z.string(),\n compatibleDrivers: z.array(CompatibleDriverSchema),\n host: z.string().optional(),\n port: z.number().optional(),\n discoveredVia: DiscoveredViaSchema.optional(),\n})\nexport type DatabaseNode = z.infer<typeof DatabaseNodeSchema>\n\nexport const ConfigNodeSchema = z.object({\n id: z.string(),\n type: z.literal(NodeType.ConfigNode),\n name: z.string(),\n path: z.string(),\n fileType: z.string(),\n})\nexport type ConfigNode = z.infer<typeof ConfigNodeSchema>\n\nexport const InfraNodeSchema = z.object({\n id: z.string(),\n type: z.literal(NodeType.InfraNode),\n name: z.string(),\n provider: z.string(),\n region: z.string().optional(),\n kind: z.string().optional(),\n})\nexport type InfraNode = z.infer<typeof InfraNodeSchema>\n\n// Placeholder for a span peer the ingest layer couldn't resolve to a known\n// ServiceNode. Lives at id `frontier:<host>` and gets replaced by the real\n// service once a later extraction round records that host as an alias.\nexport const FrontierNodeSchema = z.object({\n id: z.string(),\n type: z.literal(NodeType.FrontierNode),\n name: z.string(),\n host: z.string(),\n firstObserved: z.string().datetime().optional(),\n lastObserved: z.string().datetime().optional(),\n})\nexport type FrontierNode = z.infer<typeof FrontierNodeSchema>\n\n// FileNode — the primary node of the file-first graph (ADR-089 /\n// docs/contracts/file-awareness.md §1). A source file owned by a service,\n// identified by `fileId(service, relPath)` → `file:<service>:<relPath>`. The\n// `service` segment scopes the relative path so the same `src/index.ts` across\n// two monorepo packages stays distinct. `path` is the service-relative path\n// with forward slashes; `language` is the optional extension-derived tag\n// (js/ts/py) and stays absent when the discoverer can't name it honestly.\nexport const FileNodeSchema = z.object({\n id: z.string(),\n type: z.literal(NodeType.FileNode),\n service: z.string(),\n path: z.string(),\n language: z.string().optional(),\n discoveredVia: DiscoveredViaSchema.optional(),\n // The raw compiled `dist/...js` frame an OBSERVED call site was captured on,\n // preserved for diagnostic when ingest resolved it through a source map to\n // this original `src/...ts` (file-awareness.md §4 / `code.original_filepath`).\n // Absent when the call site was already source-grained.\n originalPath: z.string().optional(),\n // The hosting platform this file is the entry point for (`'cloudflare'`\n // today) — set on a Worker/Pages-Function's entry file only, mirroring\n // ServiceNode's own `platform` field. See `platformName` below.\n platform: z.string().optional(),\n // The platform's own name for this file's service, when the platform names\n // things differently than NEAT's manifest-derived serviceId (a Cloudflare\n // Worker's wrangler.toml/jsonc `name`, not `package.json#name`). This is the\n // only identifier the platform's own telemetry carries, so it's what a\n // connector's resolveTarget looks up against to fuse an OBSERVED signal onto\n // this exact FileNode (ADR-133, docs/contracts/static-extraction.md /\n // docs/contracts/connectors.md).\n platformName: z.string().optional(),\n})\nexport type FileNode = z.infer<typeof FileNodeSchema>\n\n// RouteNode — a server route at (method, path-template) granularity (ADR-119 /\n// docs/contracts/static-extraction.md). Extracted from a mainstream router\n// (Express / Fastify / Next.js), identified by\n// `routeId(service, method, pathTemplate)` → `route:<service>:<METHOD> <tmpl>`.\n// `service` is the owning server service; `method` is upper-cased (`ALL` for a\n// method-agnostic route); `pathTemplate` is the declared template (`/users/:id`).\n// `path` / `line` locate the route's definition in source (file-first\n// provenance, file-awareness.md §6). `framework` names the router the route was\n// recognised from. The node an EXTRACTED client↔route CALLS edge targets, and\n// the node a future OBSERVED server span lands on — the shared target that makes\n// a route-grained two-sided divergence possible.\nexport const RouteNodeSchema = z.object({\n id: z.string(),\n type: z.literal(NodeType.RouteNode),\n name: z.string(),\n service: z.string(),\n method: z.string(),\n pathTemplate: z.string(),\n path: z.string(),\n line: z.number().int().nonnegative().optional(),\n framework: z.string().optional(),\n discoveredVia: DiscoveredViaSchema.optional(),\n})\nexport type RouteNode = z.infer<typeof RouteNodeSchema>\n\n// GraphQLOperationNode — a named GraphQL operation at\n// (service, operationType, operationName) granularity (ADR-122 /\n// docs/contracts/otel-ingest.md). Every GraphQL request rides one HTTP endpoint\n// (`POST /graphql`), so at HTTP grain the whole API collapses to a single edge;\n// this node recovers the operation-level topology the client actually named.\n// Identified by `graphqlOperationId(service, operationType, operationName)` →\n// `graphql:<service>:<type> <name>`. `service` is the serving service; `type` is\n// the operation kind (`query` / `mutation` / `subscription`); `name` mirrors\n// `operationName` for the shared node-name convention. `path` / `line` locate\n// the resolver in source when a future static GraphQL extractor fills them in —\n// absent in the observed-first cut, never fabricated (file-awareness.md §6). The\n// node is minted OBSERVED-first from the execution span's `graphql.operation.*`\n// semconv; a later static extractor fuses onto the same id, which is what makes\n// a two-sided divergence possible at operation grain.\nexport const GraphQLOperationNodeSchema = z.object({\n id: z.string(),\n type: z.literal(NodeType.GraphQLOperationNode),\n name: z.string(),\n service: z.string(),\n operationType: z.string(),\n operationName: z.string(),\n path: z.string().optional(),\n line: z.number().int().nonnegative().optional(),\n discoveredVia: DiscoveredViaSchema.optional(),\n})\nexport type GraphQLOperationNode = z.infer<typeof GraphQLOperationNodeSchema>\n\n// GrpcMethodNode — a single gRPC method at (rpcService, rpcMethod) granularity\n// (ADR-123 / docs/contracts/otel-ingest.md + static-extraction.md). gRPC used to\n// engage only at service grain, collapsing every method onto one service→service\n// edge; this node recovers the per-method topology. Identified by\n// `grpcMethodId(rpcService, rpcMethod)` → `grpc:<rpcService>/<rpcMethod>`.\n// `rpcService` is the fully-qualified proto service name — the OTel `rpc.service`\n// (`orders.OrderService`), which is the `<package>.<Service>` a `.proto`\n// declares — and `rpcMethod` is the bare method (`GetOrder`). That FQN is the\n// wire contract both the OBSERVED span and the static `.proto` carry verbatim, so\n// keying on it (globally, not scoped to the NEAT manifest name) lets an observed\n// method and its declared definition fuse onto one node; the implementing service\n// owns it through a separate `CONTAINS` edge. `path` / `line` locate the `rpc`\n// line in the `.proto` when the static producer fills them in, or the resolver\n// call site an OBSERVED span carried — absent when neither is known, never\n// fabricated (file-awareness.md §6). Minted from either side; fusing the two\n// provenances onto one node is what makes a method-grain two-sided divergence\n// possible.\nexport const GrpcMethodNodeSchema = z.object({\n id: z.string(),\n type: z.literal(NodeType.GrpcMethodNode),\n name: z.string(),\n rpcService: z.string(),\n rpcMethod: z.string(),\n path: z.string().optional(),\n line: z.number().int().nonnegative().optional(),\n discoveredVia: DiscoveredViaSchema.optional(),\n})\nexport type GrpcMethodNode = z.infer<typeof GrpcMethodNodeSchema>\n\n// WebSocketChannelNode — a live WebSocket channel at (service, channel)\n// granularity (ADR-125 / docs/contracts/otel-ingest.md). A WebSocket app used to\n// produce no OBSERVED topology — only message-handler errors, as incidents —\n// leaving the channels themselves invisible. This node recovers the channel-level\n// topology from the HTTP upgrade span that opens the connection (a SERVER `GET`\n// carrying `Upgrade: websocket` and the WebSocket path). Identified by\n// `websocketChannelId(service, channel)` → `ws:<service>:<channel>`. `service` is\n// the serving service; `channel` is the connection path/channel (`/chat`,\n// `/socket.io`), mirrored into `name` for the shared node-name convention. It is\n// minted OBSERVED-only: a WebSocket channel is known from observation, never from\n// static extraction, so — unlike RouteNode / GraphQLOperationNode / GrpcMethodNode\n// — there is no declared twin to fuse with and no static producer to fill in\n// `path` / `line`. Those stay optional and absent in this cut, never fabricated\n// (file-awareness.md §6). The edge onto it reuses the existing `CONNECTS_TO` — an\n// observed-liveness edge that carries `lastObserved` and decays OBSERVED → STALE\n// on CONNECTS_TO's own staleness threshold when the channel goes quiet.\nexport const WebSocketChannelNodeSchema = z.object({\n id: z.string(),\n type: z.literal(NodeType.WebSocketChannelNode),\n name: z.string(),\n service: z.string(),\n channel: z.string(),\n path: z.string().optional(),\n line: z.number().int().nonnegative().optional(),\n discoveredVia: DiscoveredViaSchema.optional(),\n})\nexport type WebSocketChannelNode = z.infer<typeof WebSocketChannelNodeSchema>\n\nexport const GraphNodeSchema = z.discriminatedUnion('type', [\n ServiceNodeSchema,\n DatabaseNodeSchema,\n ConfigNodeSchema,\n InfraNodeSchema,\n FrontierNodeSchema,\n FileNodeSchema,\n RouteNodeSchema,\n GraphQLOperationNodeSchema,\n GrpcMethodNodeSchema,\n WebSocketChannelNodeSchema,\n])\nexport type GraphNode = z.infer<typeof GraphNodeSchema>\n","import { z } from 'zod'\nimport { EdgeType, Provenance } from './constants.js'\n\nexport const ProvenanceSchema = z.enum([\n Provenance.EXTRACTED,\n Provenance.INFERRED,\n Provenance.OBSERVED,\n Provenance.STALE,\n])\n\nexport const EdgeTypeSchema = z.enum([\n EdgeType.CALLS,\n EdgeType.DEPENDS_ON,\n EdgeType.CONNECTS_TO,\n EdgeType.CONFIGURED_BY,\n EdgeType.PUBLISHES_TO,\n EdgeType.CONSUMES_FROM,\n EdgeType.RUNS_ON,\n EdgeType.CONTAINS,\n EdgeType.IMPORTS,\n])\n\n// Static-extraction evidence for an EXTRACTED edge (ADR-029, contract #5).\n// `file` is required — retire.ts keys ghost-edge cleanup off it. `line` and\n// `snippet` are optional because the existing extractors (configs.ts,\n// docker-compose.ts) record file-level evidence only; loosening lets those\n// edges through ADR-061's response-shape validation without forcing the\n// extractors to fabricate line numbers.\nexport const EdgeEvidenceSchema = z.object({\n file: z.string(),\n line: z.number().int().nonnegative().optional(),\n snippet: z.string().optional(),\n // HTTP shape of a recognised client call site (ADR-119). Present on a\n // client↔route CALLS edge so the edge records the method + path-template the\n // client named, alongside the file:line it named them at. Absent on every\n // other edge — a config or infra edge has no HTTP method.\n method: z.string().optional(),\n pathTemplate: z.string().optional(),\n})\nexport type EdgeEvidence = z.infer<typeof EdgeEvidenceSchema>\n\n// Runtime signal for per-edge confidence (γ #76). Populated by ingest. Three\n// continuous numbers stand in for the previous coarse 0.3/0.5/0.7/1.0 ladder:\n// how much traffic, how clean, and how recent.\nexport const EdgeSignalSchema = z.object({\n spanCount: z.number().int().nonnegative(),\n errorCount: z.number().int().nonnegative(),\n lastObservedAgeMs: z.number().nonnegative().optional(),\n})\nexport type EdgeSignal = z.infer<typeof EdgeSignalSchema>\n\n// `confidence` is in [0, 1] and graded per provenance tier (ADR-066). Producers\n// write it on every EXTRACTED and OBSERVED edge via the helpers in\n// confidence.ts; flat coarse values (the old `0.5` / `1.0` shape) are a\n// contract violation. The field stays `.optional()` for snapshot back-compat —\n// older snapshots may carry edges without confidence and persist.ts loads them\n// on the documented growth path (ADR-031).\nexport const GraphEdgeSchema = z.object({\n id: z.string(),\n source: z.string(),\n target: z.string(),\n type: EdgeTypeSchema,\n provenance: ProvenanceSchema,\n confidence: z.number().min(0).max(1).optional(),\n lastObserved: z.string().datetime().optional(),\n callCount: z.number().int().nonnegative().optional(),\n evidence: EdgeEvidenceSchema.optional(),\n signal: EdgeSignalSchema.optional(),\n})\nexport type GraphEdge = z.infer<typeof GraphEdgeSchema>\n","import { z } from 'zod'\n\n// Passthrough of OTel span attributes. Records source-attribution\n// (`code.filepath`, `code.lineno`, `code.function`), HTTP context\n// (`http.method`, `http.target`, `http.status_code`), DB context\n// (`db.system`, `db.statement`), and any other span attribute the SDK\n// emitted. Consumers (incident UI, MCP getRootCause) filter what they\n// surface. Schema growth per ADR-031 — optional, additive only.\nexport const SpanAttributesSchema = z.record(\n z.string(),\n z.union([z.string(), z.number(), z.boolean(), z.null(), z.array(z.string()), z.array(z.number()), z.array(z.boolean())]),\n)\nexport type SpanAttributes = z.infer<typeof SpanAttributesSchema>\n\nexport const ErrorEventSchema = z.object({\n id: z.string(),\n timestamp: z.string().datetime(),\n service: z.string(),\n traceId: z.string(),\n spanId: z.string(),\n errorType: z.string().optional(),\n errorMessage: z.string(),\n // OTLP span events with name=\"exception\" carry richer error data than\n // status.message. When present, these fields capture the exception type\n // and stacktrace from the SDK that recorded the error. ADR-031 schema\n // growth — added without a shape change because both fields are optional.\n exceptionType: z.string().optional(),\n exceptionStacktrace: z.string().optional(),\n // Span attributes passthrough (ADR-068 follow-up). Surfaces `code.*`\n // semconv attributes for source attribution, plus the rest of the\n // attribute set for downstream filtering.\n attributes: SpanAttributesSchema.optional(),\n affectedNode: z.string(),\n // Failing-response incidents (issue #481). A span that completes 5xx, or a\n // coalesced run of 4xx CLIENT/PRODUCER spans against one peer, records an\n // incident even though OTel leaves the CLIENT span's status UNSET. These\n // fields carry the response code and the burst shape; ADR-031 schema growth —\n // all optional, so the statusCode === 2 and exception paths keep their shape.\n // httpStatusCode — the response status (the dominant code for a burst).\n // incidentCount — how many failing responses this incident coalesces\n // (1 for a 5xx, N for a flushed 4xx burst).\n // firstTimestamp / lastTimestamp — the burst's span-time bounds.\n httpStatusCode: z.number().int().optional(),\n incidentCount: z.number().int().positive().optional(),\n firstTimestamp: z.string().datetime().optional(),\n lastTimestamp: z.string().datetime().optional(),\n})\nexport type ErrorEvent = z.infer<typeof ErrorEventSchema>\n\n// Appended one-per-line to stale-events.ndjson whenever ingest.ts demotes\n// an OBSERVED edge to STALE (per-edge-type thresholds, ADR-024). Surfaces\n// on GET /stale-events for incident triage.\nexport const StaleEventSchema = z.object({\n edgeId: z.string(),\n source: z.string(),\n target: z.string(),\n edgeType: z.string(),\n thresholdMs: z.number().nonnegative(),\n ageMs: z.number().nonnegative(),\n lastObserved: z.string(),\n transitionedAt: z.string(),\n})\nexport type StaleEvent = z.infer<typeof StaleEventSchema>\n\n// The one shape every log producer emits (docs/contracts/logs.md Rule 1,\n// ADR-132) — a native OTLP `/v1/logs` receiver (source: 'native') and each\n// connector's provider-specific mapping layer (source: '<provider>') both\n// produce this. `logs-store.ts` holds these in a bounded per-(project,\n// source) ring buffer; GET /logs is the only REST surface that reads it.\n// `source` is extensible the same way the connector provider dispatch table\n// grows one entry per provider.\nexport const LogSourceSchema = z.enum([\n 'native',\n 'supabase',\n 'railway',\n 'firebase',\n 'cloudflare',\n 'vercel',\n])\nexport type LogSource = z.infer<typeof LogSourceSchema>\n\nexport const LogEntrySchema = z.object({\n id: z.string(),\n projectName: z.string(),\n source: LogSourceSchema,\n serviceName: z.string().optional(),\n nodeId: z.string().optional(),\n // ISO8601, the event's own time — never ingest/poll time.\n timestamp: z.string().datetime(),\n // Normalized upstream to 'debug' | 'info' | 'warn' | 'error' by whichever\n // producer wrote the entry; kept as a plain string here rather than a\n // locked enum because normalization is a producer concern, not this\n // schema's.\n severity: z.string().optional(),\n message: z.string(),\n attributes: z.record(z.string(), z.unknown()).optional(),\n})\nexport type LogEntry = z.infer<typeof LogEntrySchema>\n","import { z } from 'zod'\nimport { ProvenanceSchema, EdgeTypeSchema, GraphEdgeSchema } from './edges.js'\n\nexport const RootCauseResultSchema = z.object({\n rootCauseNode: z.string(),\n rootCauseReason: z.string(),\n traversalPath: z.array(z.string()),\n edgeProvenances: z.array(ProvenanceSchema),\n confidence: z.number().min(0).max(1),\n fixRecommendation: z.string().optional(),\n})\nexport type RootCauseResult = z.infer<typeof RootCauseResultSchema>\n\nexport const BlastRadiusAffectedNodeSchema = z.object({\n nodeId: z.string(),\n // Distance from the origin in BFS hops. The origin itself is never in\n // affectedNodes, so distance 0 has no meaning — the BFS at traverse.ts\n // already skips frame 0. Tightening to positive() locks that invariant\n // mechanically (ADR-038, issue #138).\n distance: z.number().int().positive(),\n edgeProvenance: ProvenanceSchema,\n // path: origin → ... → nodeId. Length === distance + 1. Surfaced from the\n // BFS predecessor chain so consumers don't have to reconstruct it from\n // distance + the graph (ADR-038, issue #137).\n path: z.array(z.string()).min(2),\n // confidence: confidenceFromMix(...edgesAlongPath). Multiplicative cascade —\n // each hop is independent evidence and uncertainty compounds. ADR-036.\n confidence: z.number().min(0).max(1),\n})\nexport type BlastRadiusAffectedNode = z.infer<typeof BlastRadiusAffectedNodeSchema>\n\nexport const BlastRadiusResultSchema = z.object({\n origin: z.string(),\n affectedNodes: z.array(BlastRadiusAffectedNodeSchema),\n totalAffected: z.number().int().nonnegative(),\n})\nexport type BlastRadiusResult = z.infer<typeof BlastRadiusResultSchema>\n\n// Transitive get_dependencies (issue #144). Flat list with distance, edge\n// type, and provenance per dependency. Sibling shape to BlastRadius but\n// thinner — no path tracking, no confidence cascade. Use cases live in the\n// MCP get_dependencies tool (\"what does X depend on, transitively?\").\nexport const TransitiveDependencySchema = z.object({\n nodeId: z.string(),\n // Distance from the origin in BFS hops. The origin itself is never in\n // dependencies, so distance is positive (>= 1).\n distance: z.number().int().positive(),\n // Type of the edge that brought traversal to this node (CALLS,\n // CONNECTS_TO, DEPENDS_ON, etc.).\n edgeType: EdgeTypeSchema,\n // Provenance of that edge.\n provenance: ProvenanceSchema,\n})\nexport type TransitiveDependency = z.infer<typeof TransitiveDependencySchema>\n\nexport const TransitiveDependenciesResultSchema = z.object({\n origin: z.string(),\n depth: z.number().int().positive(),\n dependencies: z.array(TransitiveDependencySchema),\n total: z.number().int().nonnegative(),\n})\nexport type TransitiveDependenciesResult = z.infer<typeof TransitiveDependenciesResultSchema>\n\n// Observed-only dependencies (issue #578). \"What does this node actually call\n// at runtime?\" — the OBSERVED outbound edges, file-grained. When the queried\n// node is a ServiceNode the real runtime CALLS originate from the FileNodes it\n// owns (the call-site processor lands OBSERVED edges on files, not the service\n// root), so the query walks one hop through `service ──CONTAINS──▶ file` and\n// surfaces those file→target edges. This is not a service rollup\n// (file-awareness §3): the edges stay file-grained, with the owning file as the\n// edge source — the service is just the grouping we entered through.\n//\n// `observed` / `inboundObservedCount` separate \"no outbound deps\" from \"never\n// observed\": a pure receiver (hit at runtime but calls nothing downstream) has\n// zero dependencies yet is very much seen by OTel, so the consumer must not say\n// \"is OTel running?\" at it. `hasExtractedOutbound` gates that question to the\n// genuine no-runtime-traffic case.\nexport const ObservedDependenciesResultSchema = z.object({\n origin: z.string(),\n // OBSERVED outbound edges (CALLS/CONNECTS_TO/etc.), file-grained. Structural\n // CONTAINS ownership is never listed here — it is not a runtime dependency.\n dependencies: z.array(GraphEdgeSchema),\n // Did OTel see this node (or a file it owns) at all — as caller or callee?\n // Distinguishes a pure receiver from a node runtime has never touched.\n observed: z.boolean(),\n // Count of OBSERVED inbound edges into the node (and its owned files). A\n // non-zero count with zero dependencies is the pure-receiver signal.\n inboundObservedCount: z.number().int().nonnegative(),\n // Are there EXTRACTED outbound edges but no OBSERVED ones? Only then is\n // \"static deps exist but no runtime traffic — is OTel running?\" the honest note.\n hasExtractedOutbound: z.boolean(),\n})\nexport type ObservedDependenciesResult = z.infer<typeof ObservedDependenciesResultSchema>\n","// Identity helpers — the single source of truth for node and edge id wire\n// format. See ADR-028 (nodes), ADR-029 (edges), and docs/contracts/identity.md\n// + docs/contracts/provenance.md.\n//\n// Producers construct ids via these helpers; consumers parse via the inverses.\n// Hand-rolled template literals like `service:${name}` or\n// `${type}:OBSERVED:${source}->${target}` are contract violations\n// (caught by packages/core/test/audits/contracts.test.ts).\n\nconst SERVICE_PREFIX = 'service:'\nconst DATABASE_PREFIX = 'database:'\nconst CONFIG_PREFIX = 'config:'\nconst INFRA_PREFIX = 'infra:'\nconst FRONTIER_PREFIX = 'frontier:'\nconst FILE_PREFIX = 'file:'\nconst ROUTE_PREFIX = 'route:'\nconst GRAPHQL_OP_PREFIX = 'graphql:'\nconst GRPC_METHOD_PREFIX = 'grpc:'\nconst WEBSOCKET_CHANNEL_PREFIX = 'ws:'\n\n// ServiceNode id: `service:<name>` for env-unknown nodes (the default,\n// produced by static extraction or by ingest when the span carries no env\n// signal) and `service:<name>:<env>` for env-tagged nodes (produced by\n// ingest when the span carries `deployment.environment(.name)`).\n//\n// <name> is the manifest name verbatim (package.json#name for JS/TS,\n// pyproject [project].name for Python). Names with slashes (e.g. scoped\n// npm packages `@org/foo`) are kept as-is — no transformation. See\n// ADR-028 §5 for workspace-collision deferral.\n//\n// The env discriminator is ADR-074 §2. `env === 'unknown'` is the honest\n// \"no signal\" sentinel; emitting it as the env-less wire format keeps\n// pre-v0.3.9 snapshots byte-stable on disk.\nconst ENV_UNKNOWN = 'unknown'\n\nexport function serviceId(name: string, env?: string): string {\n if (env === undefined || env === ENV_UNKNOWN) return `${SERVICE_PREFIX}${name}`\n return `${SERVICE_PREFIX}${name}:${env}`\n}\n\n// Parse a service id into its (name, env) tuple. Returns null when the\n// input is not a service id. env is `'unknown'` when the id carries no\n// env segment (the env-less wire format).\nexport function parseServiceId(id: string): { name: string; env: string } | null {\n if (!id.startsWith(SERVICE_PREFIX)) return null\n const rest = id.slice(SERVICE_PREFIX.length)\n if (rest.length === 0) return null\n const colon = rest.indexOf(':')\n if (colon === -1) return { name: rest, env: ENV_UNKNOWN }\n return { name: rest.slice(0, colon), env: rest.slice(colon + 1) }\n}\n\n// DatabaseNode id: `database:<host>`. Port is intentionally excluded; two DBs\n// on the same host different ports collide. See ADR-028 §6 for deferral.\nexport function databaseId(host: string): string {\n return `${DATABASE_PREFIX}${host}`\n}\n\nexport function parseDatabaseId(id: string): string | null {\n return id.startsWith(DATABASE_PREFIX) ? id.slice(DATABASE_PREFIX.length) : null\n}\n\n// In-process / embedded DatabaseNode id: `database:<service>/<name>`. An\n// embedded database (SQLite, better-sqlite3, an in-memory store) crosses no\n// network boundary, so a span for it carries no peer host to key `databaseId`\n// on. Two services each reading their own `app.db` would then collapse onto one\n// node; scoping the id by the observing service keeps them distinct. `name` is\n// the logical database (`db.name`) when the span carries one, the engine string\n// otherwise. Env-unscoped like `databaseId` (env-dimension.md). See ADR-118.\nexport function localDatabaseId(service: string, name: string): string {\n return `${DATABASE_PREFIX}${service}/${name}`\n}\n\n// ConfigNode id: `config:<relPath>` where <relPath> is the path relative to\n// the scan root, with forward slashes regardless of platform. ConfigNodes\n// record file existence only (ADR-016).\nexport function configId(relPath: string): string {\n return `${CONFIG_PREFIX}${relPath}`\n}\n\nexport function parseConfigId(id: string): string | null {\n return id.startsWith(CONFIG_PREFIX) ? id.slice(CONFIG_PREFIX.length) : null\n}\n\n// InfraNode id: `infra:<kind>:<name>`. <kind> is a free string sub-type\n// (kafka-topic, redis, grpc-service, lambda, queue, etc.) per ADR-022.\nexport function infraId(kind: string, name: string): string {\n return `${INFRA_PREFIX}${kind}:${name}`\n}\n\nexport function parseInfraId(id: string): { kind: string; name: string } | null {\n if (!id.startsWith(INFRA_PREFIX)) return null\n const rest = id.slice(INFRA_PREFIX.length)\n const colon = rest.indexOf(':')\n if (colon === -1) return null\n return { kind: rest.slice(0, colon), name: rest.slice(colon + 1) }\n}\n\n// FrontierNode id: `frontier:<host>` where <host> is host:port from the OTel\n// peer attribute. Promoted to a typed node id (typically serviceId(...)) once\n// an alias resolves; the FrontierNode is removed and edges are rewritten.\nexport function frontierId(host: string): string {\n return `${FRONTIER_PREFIX}${host}`\n}\n\nexport function parseFrontierId(id: string): string | null {\n return id.startsWith(FRONTIER_PREFIX) ? id.slice(FRONTIER_PREFIX.length) : null\n}\n\n// FileNode id: `file:<service>:<relPath>` (ADR-089 / file-awareness.md §1).\n// The `service` segment is the owning service's manifest name — the same token\n// `serviceId(name)` carries — so a shared relative path across monorepo\n// packages stays distinct. `relPath` is the service-relative path with forward\n// slashes. Files belong to a package, not an environment, so the id is\n// env-unscoped (unlike ServiceNode): EXTRACTED (env-less) and OBSERVED\n// (env-tagged source service) edges land on the same FileNode, which is what\n// makes the file-grained divergence comparison possible (file-awareness.md §7).\nexport function fileId(service: string, relPath: string): string {\n return `${FILE_PREFIX}${service}:${relPath}`\n}\n\n// Parse a file id into its (service, relPath) tuple. Returns null when the\n// input isn't a file id. Splits on the first colon after the prefix: service\n// names never contain a colon (scoped npm names use `/`), and relPath is\n// normalised to forward slashes with any drive letter stripped before the id\n// is built, so the first colon is unambiguously the service/path boundary.\nexport function parseFileId(id: string): { service: string; relPath: string } | null {\n if (!id.startsWith(FILE_PREFIX)) return null\n const rest = id.slice(FILE_PREFIX.length)\n const colon = rest.indexOf(':')\n if (colon === -1) return null\n const service = rest.slice(0, colon)\n const relPath = rest.slice(colon + 1)\n if (service.length === 0 || relPath.length === 0) return null\n return { service, relPath }\n}\n\n// RouteNode id: `route:<service>:<METHOD> <pathTemplate>` (ADR-119). The\n// `service` segment is the owning (server) service's manifest name, matching\n// the FileNode / ServiceNode convention so a shared path across monorepo\n// packages stays distinct. `method` is upper-cased (`GET`, `POST`, or `ALL`\n// for a method-agnostic route); `pathTemplate` is the route's declared template\n// verbatim (`/users/:id`), lightly canonicalised (leading slash, no trailing\n// slash). The space between method and template is unambiguous — a method token\n// never contains a space and a service name never contains a colon. Routes are\n// a server-side artifact of a package, not an environment, so the id is\n// env-unscoped like FileNode: an EXTRACTED route and a future OBSERVED server\n// span land on the same node, which is what makes a two-sided divergence\n// possible at route grain.\nexport function routeId(service: string, method: string, pathTemplate: string): string {\n return `${ROUTE_PREFIX}${service}:${method.toUpperCase()} ${pathTemplate}`\n}\n\n// Parse a route id into its (service, method, pathTemplate) tuple. Returns null\n// when the input isn't a route id. Splits service on the first colon after the\n// prefix (service names carry no colon), then method on the first space.\nexport function parseRouteId(\n id: string,\n): { service: string; method: string; pathTemplate: string } | null {\n if (!id.startsWith(ROUTE_PREFIX)) return null\n const rest = id.slice(ROUTE_PREFIX.length)\n const colon = rest.indexOf(':')\n if (colon === -1) return null\n const service = rest.slice(0, colon)\n const tail = rest.slice(colon + 1)\n const space = tail.indexOf(' ')\n if (space === -1) return null\n const method = tail.slice(0, space)\n const pathTemplate = tail.slice(space + 1)\n if (service.length === 0 || method.length === 0 || pathTemplate.length === 0) return null\n return { service, method, pathTemplate }\n}\n\n// GraphQLOperationNode id: `graphql:<service>:<type> <operationName>` (ADR-122).\n// The `service` segment is the serving service's manifest name, matching the\n// FileNode / RouteNode convention so a shared operation name across monorepo\n// packages stays distinct. `type` is lower-cased (`query` / `mutation` /\n// `subscription`); `operationName` is the client-supplied operation name\n// verbatim. The space between type and name is unambiguous — a GraphQL operation\n// type never contains a space and a service name never contains a colon. A\n// GraphQL operation is a server-side artifact of a package, not an environment,\n// so the id is env-unscoped like FileNode / RouteNode: an OBSERVED execution\n// span and a future EXTRACTED schema/resolver land on the same node, which is\n// what makes an operation-grained two-sided divergence possible.\nexport function graphqlOperationId(\n service: string,\n operationType: string,\n operationName: string,\n): string {\n return `${GRAPHQL_OP_PREFIX}${service}:${operationType.toLowerCase()} ${operationName}`\n}\n\n// Parse a GraphQL operation id into its (service, operationType, operationName)\n// tuple. Returns null when the input isn't a GraphQL operation id. Splits\n// service on the first colon after the prefix (service names carry no colon),\n// then type on the first space.\nexport function parseGraphqlOperationId(\n id: string,\n): { service: string; operationType: string; operationName: string } | null {\n if (!id.startsWith(GRAPHQL_OP_PREFIX)) return null\n const rest = id.slice(GRAPHQL_OP_PREFIX.length)\n const colon = rest.indexOf(':')\n if (colon === -1) return null\n const service = rest.slice(0, colon)\n const tail = rest.slice(colon + 1)\n const space = tail.indexOf(' ')\n if (space === -1) return null\n const operationType = tail.slice(0, space)\n const operationName = tail.slice(space + 1)\n if (service.length === 0 || operationType.length === 0 || operationName.length === 0) {\n return null\n }\n return { service, operationType, operationName }\n}\n\n// GrpcMethodNode id: `grpc:<rpcService>/<rpcMethod>` (ADR-123). Unlike the\n// RouteNode / GraphQLOperationNode ids, this one is NOT scoped to the NEAT\n// manifest service name — it keys on the fully-qualified gRPC `rpc.service`\n// (`orders.OrderService`, the proto's `<package>.<Service>`) instead. That FQN is\n// the wire contract: an OTel span and a `.proto` definition both carry it\n// verbatim, and it is globally unique across a gRPC mesh (the package qualifier\n// disambiguates), so keying on it — rather than on whoever happens to serve or\n// call the method — is exactly what fuses the OBSERVED span and the EXTRACTED\n// `.proto` onto one node. The implementing service's ownership is a separate\n// `CONTAINS` edge, not part of identity. `/` separates service from method\n// unambiguously: an `rpc.service` FQN carries dots but never a slash, and a\n// method name is a bare identifier.\nexport function grpcMethodId(rpcService: string, rpcMethod: string): string {\n return `${GRPC_METHOD_PREFIX}${rpcService}/${rpcMethod}`\n}\n\n// Parse a gRPC method id into its (rpcService, rpcMethod) tuple. Returns null\n// when the input isn't a gRPC method id. Splits on the first slash after the\n// prefix — the service FQN carries no slash, the method is a bare identifier.\nexport function parseGrpcMethodId(\n id: string,\n): { rpcService: string; rpcMethod: string } | null {\n if (!id.startsWith(GRPC_METHOD_PREFIX)) return null\n const rest = id.slice(GRPC_METHOD_PREFIX.length)\n const slash = rest.indexOf('/')\n if (slash === -1) return null\n const rpcService = rest.slice(0, slash)\n const rpcMethod = rest.slice(slash + 1)\n if (rpcService.length === 0 || rpcMethod.length === 0) return null\n return { rpcService, rpcMethod }\n}\n\n// WebSocketChannelNode id: `ws:<service>:<channel>` (ADR-125). The `service`\n// segment is the serving service's manifest name, matching the FileNode /\n// RouteNode / GraphQLOperationNode convention. Unlike the gRPC id — which keys on\n// the globally-unique fully-qualified `rpc.service` — a WebSocket channel path\n// (`/chat`, `/socket.io`) carries no package qualifier and is not unique across a\n// mesh, so it is scoped to the serving service exactly as a route path is. The\n// channel is a server-side artifact of a package, not an environment, so the id\n// is env-unscoped like FileNode / RouteNode. The `channel` follows the first\n// colon after the prefix; a service name carries no colon, so a channel path that\n// itself contains a colon stays intact on the channel side.\nexport function websocketChannelId(service: string, channel: string): string {\n return `${WEBSOCKET_CHANNEL_PREFIX}${service}:${channel}`\n}\n\n// Parse a WebSocket channel id into its (service, channel) tuple. Returns null\n// when the input isn't a WebSocket channel id. Splits on the first colon after\n// the prefix — the service name carries no colon, the channel is the remainder.\nexport function parseWebsocketChannelId(\n id: string,\n): { service: string; channel: string } | null {\n if (!id.startsWith(WEBSOCKET_CHANNEL_PREFIX)) return null\n const rest = id.slice(WEBSOCKET_CHANNEL_PREFIX.length)\n const colon = rest.indexOf(':')\n if (colon === -1) return null\n const service = rest.slice(0, colon)\n const channel = rest.slice(colon + 1)\n if (service.length === 0 || channel.length === 0) return null\n return { service, channel }\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Edge ids (ADR-029, ADR-068)\n// ──────────────────────────────────────────────────────────────────────────\n//\n// Edge id wire format per provenance:\n// EXTRACTED: `${type}:${source}->${target}`\n// OBSERVED: `${type}:OBSERVED:${source}->${target}`\n// INFERRED: `${type}:INFERRED:${source}->${target}`\n// STALE never appears in an edge id; STALE is a transition of an existing\n// OBSERVED edge (ADR-024), not a creation pattern.\n//\n// Per ADR-068, edges to FrontierNodes carry whatever provenance describes\n// how the edge was learned — span-derived edges use observedEdgeId with the\n// FrontierNode id as the target string. Node-type is orthogonal to\n// provenance; the wire format reflects provenance only.\n//\n// Multiple edges between the same node pair coexist under distinct provenance\n// ids — that's what makes the EXTRACTED+OBSERVED coexistence rule\n// (contracts.md Rule 2) mechanically possible.\n\nconst EDGE_ARROW = '->'\n\nexport function extractedEdgeId(source: string, target: string, type: string): string {\n return `${type}:${source}${EDGE_ARROW}${target}`\n}\n\nexport function observedEdgeId(source: string, target: string, type: string): string {\n return `${type}:OBSERVED:${source}${EDGE_ARROW}${target}`\n}\n\nexport function inferredEdgeId(source: string, target: string, type: string): string {\n return `${type}:INFERRED:${source}${EDGE_ARROW}${target}`\n}\n\n// Parse an edge id into its parts. Returns null if the input is not a\n// well-formed edge id — covers all three creation variants (STALE rides on\n// the OBSERVED id format). Useful for consumers (traversal, MCP, persist)\n// that need to walk back from an id.\n//\n// Note: EXTRACTED ids have no provenance segment, so we detect them by\n// checking whether the second segment matches a known provenance marker.\nexport function parseEdgeId(id: string): {\n type: string\n provenance: 'EXTRACTED' | 'OBSERVED' | 'INFERRED'\n source: string\n target: string\n} | null {\n const arrowIdx = id.lastIndexOf(EDGE_ARROW)\n if (arrowIdx === -1) return null\n const left = id.slice(0, arrowIdx)\n const target = id.slice(arrowIdx + EDGE_ARROW.length)\n if (!left || !target) return null\n\n // left is one of:\n // `${type}:${source}` → EXTRACTED\n // `${type}:OBSERVED:${source}` → OBSERVED\n // `${type}:INFERRED:${source}` → INFERRED\n const firstColon = left.indexOf(':')\n if (firstColon === -1) return null\n const type = left.slice(0, firstColon)\n const rest = left.slice(firstColon + 1)\n\n for (const prov of ['OBSERVED', 'INFERRED'] as const) {\n if (rest.startsWith(`${prov}:`)) {\n return { type, provenance: prov, source: rest.slice(prov.length + 1), target }\n }\n }\n return { type, provenance: 'EXTRACTED', source: rest, target }\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Provenance ranking (ADR-029, ADR-068)\n// ──────────────────────────────────────────────────────────────────────────\n//\n// Canonical priority used by traversal and any consumer that needs to pick\n// a single edge between two nodes when multiple provenance variants exist.\n// Higher number = higher trust = preferred.\n//\n// Four entries match the four-value Provenance enum (ADR-068). Node-type\n// gating (e.g. \"stop at FrontierNodes\" per contracts.md Rule 3) is enforced\n// at the node level by traversal, independent of edge rank.\nexport const PROV_RANK: Readonly<Record<'OBSERVED' | 'INFERRED' | 'EXTRACTED' | 'STALE', number>> = Object.freeze({\n OBSERVED: 3,\n INFERRED: 2,\n EXTRACTED: 1,\n STALE: 0,\n})\n","import { z } from 'zod'\nimport { ProvenanceSchema, EdgeTypeSchema } from './edges.js'\nimport { NodeTypeSchema } from './constants.js'\n\n// Policy schema (ADR-042). Lives at <projectRoot>/policy.json. Loaded at\n// startup and reloaded on file change. Five rule types, discriminated by\n// `rule.type`. Adding a new rule type requires an ADR amendment plus a\n// corresponding evaluator in the engine (ADR-043).\n\nexport const PolicySeveritySchema = z.enum(['info', 'warning', 'error', 'critical'])\nexport type PolicySeverity = z.infer<typeof PolicySeveritySchema>\n\nexport const PolicyActionSchema = z.enum(['log', 'alert', 'block'])\nexport type PolicyAction = z.infer<typeof PolicyActionSchema>\n\n// rule.type === 'structural' — asserts the existence of an edge between\n// node-type pairs. e.g. \"every ServiceNode must have a CONNECTS_TO edge to a\n// DatabaseNode.\"\nexport const StructuralRuleSchema = z.object({\n type: z.literal('structural'),\n // Node type the rule applies to. Every node of this type must satisfy the\n // edge requirement below.\n fromNodeType: NodeTypeSchema,\n // Required outbound edge type from each fromNodeType node.\n edgeType: EdgeTypeSchema,\n // Required target node type at the other end of the edge.\n toNodeType: NodeTypeSchema,\n})\nexport type StructuralRule = z.infer<typeof StructuralRuleSchema>\n\n// rule.type === 'compatibility' — re-runs `compat.ts` against current graph\n// state. Catches OBSERVED-vs-EXTRACTED divergence: a service whose compat\n// shape failed at extract time stays flagged on every evaluation.\nexport const CompatibilityRuleSchema = z.object({\n type: z.literal('compatibility'),\n // Optional kind narrowing. When omitted, all four compat shapes\n // (driver-engine, node-engine, package-conflict, deprecated-api) run.\n kind: z\n .enum(['driver-engine', 'node-engine', 'package-conflict', 'deprecated-api'])\n .optional(),\n})\nexport type CompatibilityRule = z.infer<typeof CompatibilityRuleSchema>\n\n// rule.type === 'provenance' — asserts that edges of a given type to a given\n// target carry a specific provenance (or one of a set). e.g. \"every CALLS\n// edge to service:payments must have OBSERVED provenance.\"\nexport const ProvenanceRuleSchema = z.object({\n type: z.literal('provenance'),\n // Edge type the rule applies to.\n edgeType: EdgeTypeSchema,\n // Target node id (e.g. 'service:payments') that incoming edges of edgeType\n // must satisfy. Optional — when omitted, the rule runs against every edge\n // of edgeType regardless of target.\n targetNodeId: z.string().optional(),\n // Required provenance (single value or one-of). The audit fails if the\n // observed edge's provenance is not in this set.\n required: z.union([ProvenanceSchema, z.array(ProvenanceSchema).min(1)]),\n})\nexport type ProvenanceRule = z.infer<typeof ProvenanceRuleSchema>\n\n// rule.type === 'ownership' — every node of nodeType must declare an `owner`\n// field. The field name lives on the node attributes; the rule fires when a\n// node of the type doesn't carry it (or carries an empty string).\nexport const OwnershipRuleSchema = z.object({\n type: z.literal('ownership'),\n // Node type the rule applies to. ServiceNode is the common case; the\n // discriminator stays generic so future node types can opt in.\n nodeType: NodeTypeSchema,\n // Field name on the node attributes that must be non-empty. Defaults to\n // 'owner' if omitted.\n field: z.string().default('owner'),\n})\nexport type OwnershipRule = z.infer<typeof OwnershipRuleSchema>\n\n// rule.type === 'blast-radius' — no node of the given type may have more\n// than `maxAffected` transitively-affected downstream nodes. Computed via\n// getBlastRadius at evaluation time.\nexport const BlastRadiusRuleSchema = z.object({\n type: z.literal('blast-radius'),\n // Node type the rule applies to (ServiceNode is the common case).\n nodeType: NodeTypeSchema,\n // Cap on `totalAffected` from getBlastRadius. Inclusive — a node hitting\n // exactly this number passes; > maxAffected fails.\n maxAffected: z.number().int().positive(),\n // Depth to evaluate against. Defaults to the contract's blast-radius\n // default (10) when omitted.\n depth: z.number().int().positive().optional(),\n})\nexport type BlastRadiusRule = z.infer<typeof BlastRadiusRuleSchema>\n\nexport const PolicyRuleSchema = z.discriminatedUnion('type', [\n StructuralRuleSchema,\n CompatibilityRuleSchema,\n ProvenanceRuleSchema,\n OwnershipRuleSchema,\n BlastRadiusRuleSchema,\n])\nexport type PolicyRule = z.infer<typeof PolicyRuleSchema>\n\nexport const PolicySchema = z.object({\n // Unique within the file. Duplicates fail PolicyFileSchema.parse.\n id: z.string().min(1),\n name: z.string().min(1),\n description: z.string().optional(),\n severity: PolicySeveritySchema,\n // When omitted, the engine derives a default from severity per ADR-044\n // (info→log, warning→alert, error→alert, critical→block).\n onViolation: PolicyActionSchema.optional(),\n rule: PolicyRuleSchema,\n})\nexport type Policy = z.infer<typeof PolicySchema>\n\n// Top-level shape of policy.json. version: z.literal(1) — bumping requires\n// an ADR amendment per the schema-growth contract (ADR-031).\nexport const PolicyFileSchema = z\n .object({\n version: z.literal(1),\n policies: z.array(PolicySchema),\n })\n .superRefine((file, ctx) => {\n // id uniqueness is enforced at parse time, not at registry-add time.\n // Duplicates collapse silently otherwise — we'd evaluate the second one\n // and lose the first.\n const seen = new Set<string>()\n for (const [i, p] of file.policies.entries()) {\n if (seen.has(p.id)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['policies', i, 'id'],\n message: `duplicate policy id \"${p.id}\"`,\n })\n }\n seen.add(p.id)\n }\n })\nexport type PolicyFile = z.infer<typeof PolicyFileSchema>\n\n// Emitted by the evaluator. Appended to policy-violations.ndjson.\n// Deterministic id (per ADR-043) means re-evaluating the same graph + same\n// policies produces the same violation ids; the writer skips duplicates.\n// Hypothetical action for POST /policies/check (ADR-045). Each action shape\n// names a candidate change to the graph; the engine simulates it and returns\n// any violations that *would* result. MVP scope is the two action shapes\n// below; new shapes need an ADR amendment.\nexport const HypotheticalActionSchema = z.discriminatedUnion('kind', [\n z.object({\n kind: z.literal('promote-frontier'),\n // The FrontierNode id that would be promoted.\n frontierId: z.string().min(1),\n }),\n z.object({\n kind: z.literal('add-edge'),\n source: z.string().min(1),\n target: z.string().min(1),\n edgeType: EdgeTypeSchema,\n provenance: ProvenanceSchema,\n }),\n])\nexport type HypotheticalAction = z.infer<typeof HypotheticalActionSchema>\n\n// Body of POST /policies/check.\nexport const PoliciesCheckBodySchema = z.object({\n hypotheticalAction: HypotheticalActionSchema.optional(),\n})\nexport type PoliciesCheckBody = z.infer<typeof PoliciesCheckBodySchema>\n\n// Scope filter for the check_policies MCP tool. 'all' (default) returns\n// every current violation; 'unresolved' is reserved for future resolution\n// tracking and behaves like 'all' for the MVP; { policyId } narrows to one\n// named policy.\nexport const CheckPoliciesScopeSchema = z.union([\n z.enum(['all', 'unresolved']),\n z.object({ policyId: z.string().min(1) }),\n])\nexport type CheckPoliciesScope = z.infer<typeof CheckPoliciesScopeSchema>\n\n// Soft guardrail (ADR-108 / policies-soft-guardrail.md). The launch form of\n// \"every agent stays inside the lines\": policies INFORM, they never block. An\n// ApplicablePolicy is one policy that governs the node an agent is working at —\n// matched by a direct subject/region rule match (the node's type is the rule's\n// subject, or the node sits one hop inside the rule's region). It is delivered\n// as context, surfaced through check_policies; it carries no violation, no\n// gate, no allowed/denied verdict. `match` records why it applies:\n// - 'subject' — the node is the rule's direct subject (its type is governed).\n// - 'region' — the node sits one hop inside the rule's region (e.g. the\n// target end of a structural edge, or a node on a governed edge).\n// The far-away downstream-breaking invariants the full overlay would surface\n// (ADR-105 §5) need the unbuilt policy overlay; this MVP matches one hop only.\nexport const ApplicablePolicySchema = z.object({\n policyId: z.string().min(1),\n policyName: z.string().min(1),\n description: z.string().optional(),\n severity: PolicySeveritySchema,\n // The action the post-launch kernel gate WOULD take (ADR-093) — resolved\n // from policy.onViolation or the severity default. Shown for awareness only;\n // the soft guardrail never acts on it.\n onViolation: PolicyActionSchema,\n ruleType: z.enum(['structural', 'compatibility', 'provenance', 'ownership', 'blast-radius']),\n match: z.enum(['subject', 'region']),\n // Human-readable reason the policy applies here — rides into agent context.\n reason: z.string().min(1),\n})\nexport type ApplicablePolicy = z.infer<typeof ApplicablePolicySchema>\n\n// Response shape of GET /policies/applicable.\nexport const ApplicablePoliciesResponseSchema = z.object({\n node: z.string().min(1),\n applicable: z.array(ApplicablePolicySchema),\n})\nexport type ApplicablePoliciesResponse = z.infer<typeof ApplicablePoliciesResponseSchema>\n\nexport const PolicyViolationSchema = z.object({\n // ${policy.id}:${violation-context}. The violation-context is shape-\n // specific (e.g. nodeId for structural; edgeId for provenance).\n id: z.string().min(1),\n policyId: z.string().min(1),\n policyName: z.string().min(1),\n severity: PolicySeveritySchema,\n // Resolved at evaluation time — either the explicit policy.onViolation or\n // the severity-derived default per ADR-044.\n onViolation: PolicyActionSchema,\n ruleType: z.enum(['structural', 'compatibility', 'provenance', 'ownership', 'blast-radius']),\n subject: z\n .object({\n nodeId: z.string().optional(),\n edgeId: z.string().optional(),\n path: z.array(z.string()).optional(),\n })\n .refine(\n (s) => s.nodeId !== undefined || s.edgeId !== undefined || s.path !== undefined,\n { message: 'subject must carry at least one of nodeId, edgeId, path' },\n ),\n message: z.string().min(1),\n observedAt: z.string().datetime(),\n})\nexport type PolicyViolation = z.infer<typeof PolicyViolationSchema>\n","import { z } from 'zod'\n\n// Machine-level project registry (ADR-048). Single file at\n// `~/.neat/projects.json`, per-user, machine-local. The wire shape lives here\n// so the registry module and the daemon agree on it without a circular\n// dependency through @neat.is/core.\n\nexport const RegistryStatusSchema = z.enum(['active', 'paused', 'broken'])\nexport type RegistryStatus = z.infer<typeof RegistryStatusSchema>\n\nexport const RegistryEntrySchema = z.object({\n // Unique within the registry. Project-scoped operations (`neat watch\n // --project <name>`, `neatd reload <name>`) key on this. Collisions are a\n // hard error at registration time.\n name: z.string().min(1),\n // Resolved absolute path on disk. Path normalisation is what keeps two\n // `neat init` calls from different relative paths from creating two entries\n // for the same directory.\n path: z.string().min(1),\n // ISO8601, set at first registration.\n registeredAt: z.string(),\n // ISO8601, updated whenever the daemon successfully sees the project.\n // Optional because a freshly-registered project hasn't been seen yet.\n lastSeenAt: z.string().optional(),\n // Languages detected at `init` time. Free-form strings keyed off the\n // installer modules — `'javascript'`, `'python'`, …\n languages: z.array(z.string()),\n status: RegistryStatusSchema,\n})\nexport type RegistryEntry = z.infer<typeof RegistryEntrySchema>\n\nexport const RegistryFileSchema = z.object({\n version: z.literal(1),\n projects: z.array(RegistryEntrySchema),\n})\nexport type RegistryFile = z.infer<typeof RegistryFileSchema>\n\nexport const EMPTY_REGISTRY: RegistryFile = { version: 1, projects: [] }\n","// Divergence — the thesis surface (ADR-060). A typed result describing\n// places where what the code declares (EXTRACTED) doesn't match what\n// production observed (OBSERVED). Five locked variants discriminated by\n// `type`; new shapes require a successor ADR.\n//\n// The schema lives here because consumers across the stack (REST, MCP,\n// CLI, future frontend) need to validate the wire shape against the same\n// definition. Computation lives in packages/core/src/divergences.ts —\n// pure functions over a NeatGraph; no I/O, no mutation.\n\nimport { z } from 'zod'\nimport { EdgeTypeSchema, GraphEdgeSchema } from './edges.js'\n\nconst commonFields = {\n source: z.string(),\n target: z.string(),\n confidence: z.number().min(0).max(1),\n reason: z.string(),\n recommendation: z.string(),\n}\n\nexport const MissingObservedDivergenceSchema = z.object({\n type: z.literal('missing-observed'),\n ...commonFields,\n edgeType: EdgeTypeSchema,\n extracted: GraphEdgeSchema,\n})\nexport type MissingObservedDivergence = z.infer<typeof MissingObservedDivergenceSchema>\n\nexport const MissingExtractedDivergenceSchema = z.object({\n type: z.literal('missing-extracted'),\n ...commonFields,\n edgeType: EdgeTypeSchema,\n observed: GraphEdgeSchema,\n})\nexport type MissingExtractedDivergence = z.infer<typeof MissingExtractedDivergenceSchema>\n\n// 'incompatible' = compat.json rule fires definitively.\n// 'deprecated' = compat.json deprecated-api rule fires.\n// 'unknown' = engine version present but no compat rule covers it.\nexport const CompatibilityVerdictSchema = z.enum(['incompatible', 'deprecated', 'unknown'])\nexport type CompatibilityVerdict = z.infer<typeof CompatibilityVerdictSchema>\n\nexport const VersionMismatchDivergenceSchema = z.object({\n type: z.literal('version-mismatch'),\n ...commonFields,\n extractedVersion: z.string(),\n observedVersion: z.string(),\n compatibility: CompatibilityVerdictSchema,\n})\nexport type VersionMismatchDivergence = z.infer<typeof VersionMismatchDivergenceSchema>\n\nexport const HostMismatchDivergenceSchema = z.object({\n type: z.literal('host-mismatch'),\n ...commonFields,\n extractedHost: z.string(),\n observedHost: z.string(),\n})\nexport type HostMismatchDivergence = z.infer<typeof HostMismatchDivergenceSchema>\n\n// Free-shape reference to the compat.json rule that fired — kept as a plain\n// record so the schema stays insulated from compat.ts's internal types. The\n// `rule` field carries enough metadata to identify which rule + why.\nexport const CompatRuleRefSchema = z.object({\n kind: z.string(),\n reason: z.string(),\n package: z.string().optional(),\n driver: z.string().optional(),\n engine: z.string().optional(),\n})\nexport type CompatRuleRef = z.infer<typeof CompatRuleRefSchema>\n\nexport const CompatViolationDivergenceSchema = z.object({\n type: z.literal('compat-violation'),\n ...commonFields,\n rule: CompatRuleRefSchema,\n observed: GraphEdgeSchema,\n})\nexport type CompatViolationDivergence = z.infer<typeof CompatViolationDivergenceSchema>\n\nexport const DivergenceSchema = z.discriminatedUnion('type', [\n MissingObservedDivergenceSchema,\n MissingExtractedDivergenceSchema,\n VersionMismatchDivergenceSchema,\n HostMismatchDivergenceSchema,\n CompatViolationDivergenceSchema,\n])\nexport type Divergence = z.infer<typeof DivergenceSchema>\n\nexport const DivergenceResultSchema = z.object({\n divergences: z.array(DivergenceSchema),\n totalAffected: z.number().int().nonnegative(),\n // ISO8601 timestamp the result was computed at. Each call re-derives from\n // the live graph — there is no persisted divergence history.\n computedAt: z.string().datetime(),\n})\nexport type DivergenceResult = z.infer<typeof DivergenceResultSchema>\n\n// Locked set of divergence types. Consumers (REST query parser, CLI flag\n// parser) validate the user-supplied filter against this enum.\nexport const DivergenceTypeSchema = z.enum([\n 'missing-observed',\n 'missing-extracted',\n 'version-mismatch',\n 'host-mismatch',\n 'compat-violation',\n])\nexport type DivergenceType = z.infer<typeof DivergenceTypeSchema>\n","// Single source of truth for the MCP tool surface (ADR-091).\n// Adding or renaming a tool means editing this tuple; the MCP server\n// registration and the contracts audit both derive from it, so they\n// never disagree about what tools exist.\nexport const MCP_TOOL_NAMES = [\n 'get_root_cause',\n 'get_blast_radius',\n 'get_dependencies',\n 'get_observed_dependencies',\n 'get_incident_history',\n 'semantic_search',\n 'get_graph_diff',\n 'get_recent_stale_edges',\n 'check_policies',\n 'get_divergences',\n // Six /neat extend tools (ADR-081, ADR-086, #387).\n 'neat_list_uninstrumented',\n 'neat_lookup_instrumentation',\n 'neat_describe_project_instrumentation',\n 'neat_apply_extension',\n 'neat_dry_run_extension',\n 'neat_rollback_extension',\n] as const\n\nexport type MCPToolName = (typeof MCP_TOOL_NAMES)[number]\n","import { z } from 'zod'\nimport { GraphEdgeSchema } from './edges.js'\nimport { GraphNodeSchema } from './nodes.js'\nimport { ErrorEventSchema, LogEntrySchema, StaleEventSchema } from './events.js'\nimport { PolicyViolationSchema } from './policy.js'\nimport { RegistryEntrySchema } from './registry.js'\n\n// ADR-061 envelope rule: every GET response is a JSON object. List endpoints\n// wrap in plural-noun fields plus a count; single-item endpoints wrap the\n// item in a singular field. Bare arrays are a contract violation.\n\n// `count` is the length of the returned array; `total` is the size of the\n// underlying collection before filtering / limiting.\nconst listEnvelope = <T extends z.ZodTypeAny>(itemSchema: T) =>\n z.object({\n count: z.number().int().nonnegative(),\n total: z.number().int().nonnegative(),\n events: z.array(itemSchema),\n })\n\nexport const IncidentsResponseSchema = listEnvelope(ErrorEventSchema)\nexport type IncidentsResponse = z.infer<typeof IncidentsResponseSchema>\n\nexport const StaleEventsResponseSchema = listEnvelope(StaleEventSchema)\nexport type StaleEventsResponse = z.infer<typeof StaleEventsResponseSchema>\n\n// GET /logs response (docs/contracts/logs.md Rule 5, ADR-132). `total` is\n// the size of the filtered-but-unlimited collection (after source/service/\n// since filtering); `count` is the length of the returned, limit-capped\n// `logs` array.\nexport const LogsResponseSchema = z.object({\n count: z.number().int().nonnegative(),\n total: z.number().int().nonnegative(),\n logs: z.array(LogEntrySchema),\n})\nexport type LogsResponse = z.infer<typeof LogsResponseSchema>\n\nexport const PoliciesViolationsResponseSchema = z.object({\n violations: z.array(PolicyViolationSchema),\n})\nexport type PoliciesViolationsResponse = z.infer<typeof PoliciesViolationsResponseSchema>\n\nexport const GraphNodeResponseSchema = z.object({\n node: GraphNodeSchema,\n})\nexport type GraphNodeResponse = z.infer<typeof GraphNodeResponseSchema>\n\nexport const GraphEdgesResponseSchema = z.object({\n inbound: z.array(GraphEdgeSchema),\n outbound: z.array(GraphEdgeSchema),\n})\nexport type GraphEdgesResponse = z.infer<typeof GraphEdgesResponseSchema>\n\n// `.passthrough()` because the handler keeps legacy fields (uptime,\n// nodeCount, edgeCount, lastUpdated) for the web shell's StatusBar. The\n// canonical triple is what's required; the extras ride along.\nexport const HealthResponseSchema = z\n .object({\n ok: z.boolean(),\n project: z.string(),\n uptimeMs: z.number().int().nonnegative(),\n })\n .passthrough()\nexport type HealthResponse = z.infer<typeof HealthResponseSchema>\n\n// Daemon-wide /health (issue #343). Distinct from `HealthResponseSchema`\n// because the unscoped probe doesn't have a single project to report on —\n// readiness lives at the daemon level. `projects` is a flat array of every\n// slot currently loaded so a probe consumer can decide which subset to\n// poll per-project /health on.\nexport const DaemonHealthResponseSchema = z\n .object({\n ok: z.boolean(),\n uptimeMs: z.number().int().nonnegative(),\n projects: z.array(\n z.object({\n name: z.string(),\n nodeCount: z.number().int().nonnegative(),\n edgeCount: z.number().int().nonnegative(),\n }).passthrough(),\n ),\n })\n .passthrough()\nexport type DaemonHealthResponse = z.infer<typeof DaemonHealthResponseSchema>\n\nexport const SingleProjectResponseSchema = z.object({\n project: RegistryEntrySchema,\n})\nexport type SingleProjectResponse = z.infer<typeof SingleProjectResponseSchema>\n\n// GET /:project/connectors response (docs/contracts/rest-api.md, connectors.md\n// §8, ADR-136). One entry per `~/.neat/connectors.json` connector matching the\n// project, credential redacted to its env-ref pointer (never a resolved value),\n// carrying the live poll health the in-process status tracker records.\n\n// The derived poll state the endpoint reports:\n// idle — no poll tick has run yet\n// healthy — the most recent tick succeeded within the stale window\n// error — the most recent tick threw\n// stale — no successful poll within the stale window (a wedged/silent loop)\nexport const ConnectorPollStateSchema = z.enum(['idle', 'healthy', 'error', 'stale'])\nexport type ConnectorPollState = z.infer<typeof ConnectorPollStateSchema>\n\n// The per-connector live health block. `lastPollAt`/`lastOutcome`/`lastError`\n// are null until the first tick; `lastError` is null on a successful tick and a\n// short, secret-free string on a failing one (connectors.md §6 — never a\n// credential). `signalsLastPoll` is the count the last tick returned (0 before\n// any poll).\nexport const ConnectorStatusSchema = z.object({\n state: ConnectorPollStateSchema,\n lastPollAt: z.string().nullable(),\n lastOutcome: z.enum(['ok', 'error']).nullable(),\n lastError: z.string().nullable(),\n signalsLastPoll: z.number().int().nonnegative(),\n})\nexport type ConnectorStatus = z.infer<typeof ConnectorStatusSchema>\n\n// `credentialRef` is the redacted env-ref pointer — a single string\n// (`\"$CF_TOKEN\"`) for a single-field credential, or a field→pointer map for a\n// multi-field one. A plaintext literal redacts to `\"****\"`. Never a resolved\n// secret (ADR-136 §3).\nexport const ConnectorStatusEntrySchema = z.object({\n id: z.string(),\n provider: z.string(),\n credentialRef: z.union([z.string(), z.record(z.string(), z.string())]),\n status: ConnectorStatusSchema,\n})\nexport type ConnectorStatusEntry = z.infer<typeof ConnectorStatusEntrySchema>\n\nexport const ConnectorsStatusResponseSchema = z.object({\n connectors: z.array(ConnectorStatusEntrySchema),\n})\nexport type ConnectorsStatusResponse = z.infer<typeof ConnectorsStatusResponseSchema>\n\n// /search matches are graph nodes with an added per-match score. The\n// schema keeps `score` mandatory and lets the underlying node shape pass\n// through — GraphNodeSchema is a discriminated union and tightening here\n// would force every match into one variant.\nexport const SearchMatchSchema = z\n .object({ score: z.number() })\n .passthrough()\nexport type SearchMatch = z.infer<typeof SearchMatchSchema>\n\nexport const SearchResponseSchema = z.object({\n query: z.string(),\n provider: z.string(),\n matches: z.array(SearchMatchSchema),\n})\nexport type SearchResponse = z.infer<typeof SearchResponseSchema>\n\n// Live snapshot returned by GET /graph. Mirrors the in-memory graphology\n// instance; nothing reads graph.json at request time (Rule 6).\nexport const SerializedGraphSchema = z.object({\n nodes: z.array(GraphNodeSchema),\n edges: z.array(GraphEdgeSchema),\n})\nexport type SerializedGraph = z.infer<typeof SerializedGraphSchema>\n\n// GET /graph/diff response. The diff module owns the implementation;\n// the schema mirrors its current GraphDiff interface.\nexport const GraphDiffResultSchema = z.object({\n base: z.object({ exportedAt: z.string().optional() }),\n current: z.object({ exportedAt: z.string() }),\n added: z.object({\n nodes: z.array(GraphNodeSchema),\n edges: z.array(GraphEdgeSchema),\n }),\n removed: z.object({\n nodes: z.array(GraphNodeSchema),\n edges: z.array(GraphEdgeSchema),\n }),\n changed: z.object({\n nodes: z.array(\n z.object({\n id: z.string(),\n before: GraphNodeSchema,\n after: GraphNodeSchema,\n }),\n ),\n edges: z.array(\n z.object({\n id: z.string(),\n before: GraphEdgeSchema,\n after: GraphEdgeSchema,\n }),\n ),\n }),\n})\nexport type GraphDiffResult = z.infer<typeof GraphDiffResultSchema>\n","// Confidence grading helpers — single source of truth for ADR-066.\n//\n// EXTRACTED is graded at emit time per producer; OBSERVED is graded by the\n// signal block on the edge. PROV_RANK still locks tier ordering. The grading\n// sits within each tier so the divergence query can reweight against honest\n// values, not flat coarse ones.\n//\n// Producers in packages/core/src/extract/ import `confidenceForExtracted`\n// and pass the producer kind; ingest.ts imports `confidenceForObservedSignal`\n// and calls it at the same point it writes the signal block.\n\nimport type { EdgeSignal } from './edges.js'\n\n// Discriminator that producers pass when emitting an EXTRACTED edge. Each\n// kind maps to a numeric grade; the divergence query treats sub-floor\n// candidates as if they never existed (precision floor, NEAT_EXTRACTED_PRECISION_FLOOR).\nexport type ExtractedConfidenceKind =\n // 0.85 — direct AST / file facts. ConfigNode existence (ADR-016), package.json\n // deps, AST imports, Dockerfile RUNS_ON, docker-compose depends_on, parsed\n // database config files. Structural — what the code says it does.\n | 'structural'\n // 0.85 — framework-aware call-site recognizer matched the SDK shape. Today's\n // covers kafkajs producer.send / consumer.subscribe, AWS SDK Bucket/TableName\n // near a *Client, grpc-js Client construction with the import context,\n // import-aware *Client classification (#238), and @supabase/supabase-js /\n // @supabase/ssr createClient construction with the import in scope (#482).\n // Also covers a matched HTTP client↔route contract (ADR-119): a recognised\n // fetch / axios / node-http client call site whose (host, method, path-\n // template) resolves to a server route NEAT extracted from a mainstream\n // router. Both endpoints are recognised — a framework-aware client shape on\n // one side, a parsed route definition on the other — so the cross-service\n // CALLS edge lands at this tier rather than the looser url-literal grade.\n | 'verified-call-site'\n // 0.5 — URL-shaped literal with structural support. Today's `redis://host` /\n // `rediss://host` URL captures fit here: the scheme proves it's a redis URL,\n // but there's no call expression verifying it's actually wired into the\n // service's runtime path.\n | 'url-with-structural-support'\n // 0.7 — a scheme-qualified URL literal (http://service-c:3102, //service-c/x)\n // whose hostname resolves to a *registered* service. This is a declared HTTP\n // dependency: the source names another in-mesh service's URL. urlMatchesHost\n // requires scheme + exact hostname (+ exact port when present) and the target\n // is a known node, so it lands at the precision floor rather than below it —\n // missing-observed needs a floor-level EXTRACTED edge to measure a declared-\n // but-never-driven upstream (issue #592). Below structural/verified (no call\n // expression wraps the literal); above url-with-structural-support (a resolved\n // registered target is tighter than a bare scheme read).\n | 'url-literal-service-target'\n // 0.2 — bare URL/hostname match against a registered service with no scheme\n // to anchor it. Structurally loose and unconfirmed by any recognizer; drops\n // below the default precision floor (0.7) and never enters the graph unless\n // the floor is lowered for diagnostics.\n | 'hostname-shape-match'\n\nexport const EXTRACTED_CONFIDENCE: Record<ExtractedConfidenceKind, number> = {\n structural: 0.85,\n 'verified-call-site': 0.85,\n 'url-literal-service-target': 0.7,\n 'url-with-structural-support': 0.5,\n 'hostname-shape-match': 0.2,\n}\n\nexport function confidenceForExtracted(kind: ExtractedConfidenceKind): number {\n return EXTRACTED_CONFIDENCE[kind]\n}\n\n// OBSERVED grading from the signal block (ADR-066 §2). The piecewise function\n// reflects the three buckets the ADR locks plus the error-ratio adjustment.\n// `lastObservedAgeMs` defaults to 0 (just-observed) when the caller doesn't\n// pass a signal — upsertObservedEdge writes 0 on creation and on every span\n// update; the staleness loop is the only thing that lets the age drift.\n\nconst STRONG_SPAN_THRESHOLD = 100\nconst GOOD_SPAN_THRESHOLD = 10\nconst RECENT_AGE_MS = 60 * 60 * 1000\n\nexport function confidenceForObservedSignal(signal: EdgeSignal | undefined): number {\n // No signal block — fall back to the strong-tier ceiling. This case is\n // legacy edges loaded from a pre-v0.3.4 snapshot or hand-written test\n // fixtures; new producers always write the signal block.\n if (!signal) return 1.0\n const { spanCount, errorCount } = signal\n const ageMs = signal.lastObservedAgeMs ?? 0\n const recent = ageMs < RECENT_AGE_MS\n\n let base: number\n if (spanCount >= STRONG_SPAN_THRESHOLD && recent) {\n // Strong tier. Scale linearly from 0.95 at the threshold up to 1.0 at\n // 10× the threshold. Saturates at 1.0 above that.\n const over = Math.min(1, (spanCount - STRONG_SPAN_THRESHOLD) / (9 * STRONG_SPAN_THRESHOLD))\n base = 0.95 + 0.05 * over\n } else if (spanCount >= GOOD_SPAN_THRESHOLD && recent) {\n // Good tier. 0.7 at the threshold up to 0.9 just below the strong tier.\n const range = STRONG_SPAN_THRESHOLD - GOOD_SPAN_THRESHOLD\n const over = (spanCount - GOOD_SPAN_THRESHOLD) / range\n base = 0.7 + 0.2 * over\n } else if (spanCount > 0 && recent) {\n // Weak tier. 0.4 at one span up to 0.6 just below the good tier.\n const range = GOOD_SPAN_THRESHOLD - 1\n const over = range > 0 ? (spanCount - 1) / range : 0\n base = 0.4 + 0.2 * over\n } else if (spanCount > 0) {\n // Not recent — clamp the weak tier; staleness loop will demote this edge\n // to STALE on the next tick.\n base = 0.4\n } else {\n // Defensive: no spans on an OBSERVED edge means the upsert path was\n // skipped somewhere. Treat as no-evidence rather than max-trust.\n base = 0.4\n }\n\n // Error-ratio penalty. errorCount / spanCount on a healthy edge is 0; on a\n // failing edge it climbs. Subtract up to 0.2.\n if (spanCount > 0 && errorCount > 0) {\n const ratio = Math.min(1, errorCount / spanCount)\n base -= 0.2 * ratio\n }\n\n if (base < 0) return 0\n if (base > 1) return 1\n return Math.round(base * 1000) / 1000\n}\n\n// Precision-floor helpers (ADR-066 §3). The floor reads the\n// NEAT_EXTRACTED_PRECISION_FLOOR env var on each call so tests can flip it\n// in-process. Default 0.7. NEAT_EXTRACTED_PRECISION_FLOOR=0.0 keeps every\n// candidate (diagnostic mode).\n\nexport const DEFAULT_EXTRACTED_PRECISION_FLOOR = 0.7\n\nexport function extractedPrecisionFloor(): number {\n const raw = process.env.NEAT_EXTRACTED_PRECISION_FLOOR\n if (raw === undefined) return DEFAULT_EXTRACTED_PRECISION_FLOOR\n const n = Number(raw)\n if (!Number.isFinite(n) || n < 0 || n > 1) return DEFAULT_EXTRACTED_PRECISION_FLOOR\n return n\n}\n\nexport function passesExtractedFloor(confidence: number): boolean {\n return confidence >= extractedPrecisionFloor()\n}\n"],"mappings":"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","names":["import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/nodes.ts","../src/edges.ts","../src/events.ts","../src/results.ts","../src/identity.ts","../src/policy.ts","../src/registry.ts","../src/divergence.ts","../src/mcp-tools.ts","../src/responses.ts","../src/confidence.ts"],"sourcesContent":["export * from './constants.js'\nexport * from './nodes.js'\nexport * from './edges.js'\nexport * from './events.js'\nexport * from './results.js'\nexport * from './identity.js'\nexport * from './policy.js'\nexport * from './registry.js'\nexport * from './divergence.js'\nexport * from './mcp-tools.js'\nexport * from './responses.js'\nexport * from './confidence.js'\nexport * from './connectors.js'\n","export const Provenance = {\n EXTRACTED: 'EXTRACTED',\n INFERRED: 'INFERRED',\n OBSERVED: 'OBSERVED',\n STALE: 'STALE',\n} as const\n\nexport type ProvenanceValue = (typeof Provenance)[keyof typeof Provenance]\n\nexport const EdgeType = {\n CALLS: 'CALLS',\n DEPENDS_ON: 'DEPENDS_ON',\n CONNECTS_TO: 'CONNECTS_TO',\n CONFIGURED_BY: 'CONFIGURED_BY',\n PUBLISHES_TO: 'PUBLISHES_TO',\n CONSUMES_FROM: 'CONSUMES_FROM',\n RUNS_ON: 'RUNS_ON',\n // A service owns its files (ADR-089 / docs/contracts/file-awareness.md §2):\n // `service ──CONTAINS──▶ file`. Structural ownership, not traffic — the\n // grouping that lets file-grained relationships roll up to a service only\n // as the honest fallback, never as a summary view.\n CONTAINS: 'CONTAINS',\n // Static module dependency between two FileNodes within a service (ADR-092,\n // file-awareness.md §10). Compile-time, not runtime — represents one file\n // importing another. Distinct from CALLS which records runtime invocations.\n IMPORTS: 'IMPORTS',\n} as const\n\nexport type EdgeTypeValue = (typeof EdgeType)[keyof typeof EdgeType]\n\nexport const NodeType = {\n ServiceNode: 'ServiceNode',\n DatabaseNode: 'DatabaseNode',\n ConfigNode: 'ConfigNode',\n InfraNode: 'InfraNode',\n FrontierNode: 'FrontierNode',\n // The primary node of the file-first graph (ADR-089). A source file owned\n // by a service; relationships originate from it. See\n // docs/contracts/file-awareness.md §1.\n FileNode: 'FileNode',\n // A server route at (method, path-template) granularity (ADR-119). Extracted\n // from a mainstream router (Express / Fastify / Next.js) so a client call\n // site can be matched to the exact route it names, rather than only to the\n // owning service. The node an OBSERVED server span lands on too, which is\n // what makes a two-sided divergence possible at route grain. See\n // docs/contracts/static-extraction.md.\n RouteNode: 'RouteNode',\n // A named GraphQL operation — one query, mutation, or subscription — at\n // (service, operationType, operationName) granularity (ADR-122). Every\n // GraphQL request rides one HTTP endpoint (POST /graphql), so at HTTP grain\n // the whole API collapses to a single edge; this node recovers the\n // operation-level topology from the execution span's `graphql.operation.*`\n // semconv. Minted observed-first from OTel; a future static GraphQL extractor\n // fuses onto the same id. See docs/contracts/otel-ingest.md.\n GraphQLOperationNode: 'GraphQLOperationNode',\n // A single gRPC method — one `rpc` in a `.proto` service — at\n // (rpcService, rpcMethod) granularity (ADR-123). gRPC used to engage only at\n // service grain: every method collapsed onto one service→service edge, so the\n // per-method topology was invisible and one-sided. This node recovers the\n // method-level shape from both sides: the OBSERVED execution span's\n // `rpc.service` / `rpc.method` semconv and the static `.proto` service/method\n // definitions. It keys on the fully-qualified `rpc.service` — the wire\n // contract both sides carry verbatim — so a declared method and an observed\n // one fuse onto the same node into a two-sided divergence. See\n // docs/contracts/otel-ingest.md and docs/contracts/static-extraction.md.\n GrpcMethodNode: 'GrpcMethodNode',\n // A live WebSocket channel — the path/channel a client connects to — at\n // (service, channel) granularity (ADR-125). A WebSocket app used to produce no\n // OBSERVED topology at all: only message-handler errors surfaced, as incidents,\n // and the channels themselves stayed invisible. This node recovers the\n // channel-level topology from the HTTP upgrade span that opens the connection —\n // a SERVER `GET` carrying the WebSocket path. It is minted OBSERVED-only: a\n // WebSocket channel is known from observation, never from static extraction, so\n // there is no declared twin to fuse with. The edge onto it reuses the existing\n // `CONNECTS_TO` (`service ──CONNECTS_TO──▶ ws-channel`) as an observed-liveness\n // edge that carries `lastObserved` and decays OBSERVED → STALE on CONNECTS_TO's\n // own staleness threshold when the channel goes quiet. See\n // docs/contracts/otel-ingest.md.\n WebSocketChannelNode: 'WebSocketChannelNode',\n} as const\n\nexport type NodeTypeValue = (typeof NodeType)[keyof typeof NodeType]\n\nimport { z } from 'zod'\n\n// Zod-side mirror of NodeType, exported for schemas that need to discriminate\n// or filter by node type at parse time (policy rules, traversal results, etc.).\n// Adding a new node type means adding it to NodeType above and to this enum.\nexport const NodeTypeSchema = z.enum([\n NodeType.ServiceNode,\n NodeType.DatabaseNode,\n NodeType.ConfigNode,\n NodeType.InfraNode,\n NodeType.FrontierNode,\n NodeType.FileNode,\n NodeType.RouteNode,\n NodeType.GraphQLOperationNode,\n NodeType.GrpcMethodNode,\n NodeType.WebSocketChannelNode,\n])\n","import { z } from 'zod'\nimport { NodeType } from './constants.js'\n\nexport const CompatibleDriverSchema = z.object({\n name: z.string(),\n minVersion: z.string(),\n})\nexport type CompatibleDriver = z.infer<typeof CompatibleDriverSchema>\n\n// How NEAT first learned of a node. Static-extraction fills in the rich\n// fields (language, version, dependencies); OTel ingest can also create a\n// minimal node when it sees a span for an unknown peer. When both layers\n// recorded the same node, the value is 'merged'. ADR-031 schema growth.\nexport const DiscoveredViaSchema = z.enum(['static', 'otel', 'merged'])\nexport type DiscoveredVia = z.infer<typeof DiscoveredViaSchema>\n\nexport const ServiceNodeSchema = z.object({\n id: z.string(),\n type: z.literal(NodeType.ServiceNode),\n name: z.string(),\n language: z.string(),\n // Deployment environment from the OTel `deployment.environment.name` attr\n // (with `deployment.environment` and resource-attr fallbacks). The literal\n // `'unknown'` is the honest sentinel when no env signal is present; static\n // extraction never sees env at extract time, so its ServiceNodes carry\n // `undefined` here and the id stays in the env-less wire format\n // `service:<name>`. See ADR-074 §2 and docs/contracts/env-dimension.md.\n env: z.string().optional(),\n // Framework recorded by the static extractor when the install plan\n // dispatches a framework-specific path (Next.js, Remix, SvelteKit, Nuxt,\n // Astro). Optional enrichment — `undefined` for lib-only packages and\n // ambiguous repos. See ADR-074 §3 / docs/contracts/framework-installers.md.\n framework: z.string().optional(),\n // The hosting platform a static extractor recognized this service as\n // deployed to (`'cloudflare'` today) — a free string, same discipline as\n // `framework`, so a future platform needs no schema change. This is the\n // frontend's icon key at the service-rollup level (ADR-133,\n // docs/contracts/static-extraction.md).\n platform: z.string().optional(),\n discoveredVia: DiscoveredViaSchema.optional(),\n version: z.string().optional(),\n dbConnectionTarget: z.string().optional(),\n repoPath: z.string().optional(),\n owner: z.string().optional(),\n dependencies: z.record(z.string(), z.string()).optional(),\n // Hostnames OTel spans might mention for this service: compose service\n // names, k8s metadata.name (and the cluster-DNS variants), Dockerfile\n // labels, etc. resolveServiceId in ingest.ts checks these before falling\n // back to a FRONTIER placeholder.\n aliases: z.array(z.string()).optional(),\n // Optional. If set, services declare their `engines.node` here so γ #74's\n // node-engine compat check has something to test against.\n nodeEngine: z.string().optional(),\n incompatibilities: z\n .array(\n // Discriminated by `kind`. `driver-engine` is the original shape and\n // stays default for backward compatibility — older snapshots without a\n // `kind` field still parse via the union's `.optional()` discriminator\n // fallback. New kinds came in with γ #74.\n z.union([\n z.object({\n kind: z.literal('driver-engine').optional(),\n driver: z.string(),\n driverVersion: z.string(),\n engine: z.string(),\n engineVersion: z.string(),\n reason: z.string(),\n }),\n z.object({\n kind: z.literal('node-engine'),\n package: z.string(),\n packageVersion: z.string().optional(),\n requiredNodeVersion: z.string(),\n declaredNodeEngine: z.string().optional(),\n reason: z.string(),\n }),\n z.object({\n kind: z.literal('package-conflict'),\n package: z.string(),\n packageVersion: z.string().optional(),\n requires: z.object({\n name: z.string(),\n minVersion: z.string(),\n }),\n foundVersion: z.string().optional(),\n reason: z.string(),\n }),\n z.object({\n kind: z.literal('deprecated-api'),\n package: z.string(),\n packageVersion: z.string().optional(),\n reason: z.string(),\n }),\n ]),\n )\n .optional(),\n})\nexport type ServiceNode = z.infer<typeof ServiceNodeSchema>\n\nexport const DatabaseNodeSchema = z.object({\n id: z.string(),\n type: z.literal(NodeType.DatabaseNode),\n name: z.string(),\n engine: z.string(),\n engineVersion: z.string(),\n compatibleDrivers: z.array(CompatibleDriverSchema),\n host: z.string().optional(),\n port: z.number().optional(),\n discoveredVia: DiscoveredViaSchema.optional(),\n})\nexport type DatabaseNode = z.infer<typeof DatabaseNodeSchema>\n\nexport const ConfigNodeSchema = z.object({\n id: z.string(),\n type: z.literal(NodeType.ConfigNode),\n name: z.string(),\n path: z.string(),\n fileType: z.string(),\n})\nexport type ConfigNode = z.infer<typeof ConfigNodeSchema>\n\nexport const InfraNodeSchema = z.object({\n id: z.string(),\n type: z.literal(NodeType.InfraNode),\n name: z.string(),\n provider: z.string(),\n region: z.string().optional(),\n kind: z.string().optional(),\n})\nexport type InfraNode = z.infer<typeof InfraNodeSchema>\n\n// Placeholder for a span peer the ingest layer couldn't resolve to a known\n// ServiceNode. Lives at id `frontier:<host>` and gets replaced by the real\n// service once a later extraction round records that host as an alias.\nexport const FrontierNodeSchema = z.object({\n id: z.string(),\n type: z.literal(NodeType.FrontierNode),\n name: z.string(),\n host: z.string(),\n firstObserved: z.string().datetime().optional(),\n lastObserved: z.string().datetime().optional(),\n})\nexport type FrontierNode = z.infer<typeof FrontierNodeSchema>\n\n// FileNode — the primary node of the file-first graph (ADR-089 /\n// docs/contracts/file-awareness.md §1). A source file owned by a service,\n// identified by `fileId(service, relPath)` → `file:<service>:<relPath>`. The\n// `service` segment scopes the relative path so the same `src/index.ts` across\n// two monorepo packages stays distinct. `path` is the service-relative path\n// with forward slashes; `language` is the optional extension-derived tag\n// (js/ts/py) and stays absent when the discoverer can't name it honestly.\nexport const FileNodeSchema = z.object({\n id: z.string(),\n type: z.literal(NodeType.FileNode),\n service: z.string(),\n path: z.string(),\n language: z.string().optional(),\n discoveredVia: DiscoveredViaSchema.optional(),\n // The raw compiled `dist/...js` frame an OBSERVED call site was captured on,\n // preserved for diagnostic when ingest resolved it through a source map to\n // this original `src/...ts` (file-awareness.md §4 / `code.original_filepath`).\n // Absent when the call site was already source-grained.\n originalPath: z.string().optional(),\n // The hosting platform this file is the entry point for (`'cloudflare'`\n // today) — set on a Worker/Pages-Function's entry file only, mirroring\n // ServiceNode's own `platform` field. See `platformName` below.\n platform: z.string().optional(),\n // The platform's own name for this file's service, when the platform names\n // things differently than NEAT's manifest-derived serviceId (a Cloudflare\n // Worker's wrangler.toml/jsonc `name`, not `package.json#name`). This is the\n // only identifier the platform's own telemetry carries, so it's what a\n // connector's resolveTarget looks up against to fuse an OBSERVED signal onto\n // this exact FileNode (ADR-133, docs/contracts/static-extraction.md /\n // docs/contracts/connectors.md).\n platformName: z.string().optional(),\n})\nexport type FileNode = z.infer<typeof FileNodeSchema>\n\n// RouteNode — a server route at (method, path-template) granularity (ADR-119 /\n// docs/contracts/static-extraction.md). Extracted from a mainstream router\n// (Express / Fastify / Next.js), identified by\n// `routeId(service, method, pathTemplate)` → `route:<service>:<METHOD> <tmpl>`.\n// `service` is the owning server service; `method` is upper-cased (`ALL` for a\n// method-agnostic route); `pathTemplate` is the declared template (`/users/:id`).\n// `path` / `line` locate the route's definition in source (file-first\n// provenance, file-awareness.md §6). `framework` names the router the route was\n// recognised from. The node an EXTRACTED client↔route CALLS edge targets, and\n// the node a future OBSERVED server span lands on — the shared target that makes\n// a route-grained two-sided divergence possible.\nexport const RouteNodeSchema = z.object({\n id: z.string(),\n type: z.literal(NodeType.RouteNode),\n name: z.string(),\n service: z.string(),\n method: z.string(),\n pathTemplate: z.string(),\n path: z.string(),\n line: z.number().int().nonnegative().optional(),\n framework: z.string().optional(),\n discoveredVia: DiscoveredViaSchema.optional(),\n})\nexport type RouteNode = z.infer<typeof RouteNodeSchema>\n\n// GraphQLOperationNode — a named GraphQL operation at\n// (service, operationType, operationName) granularity (ADR-122 /\n// docs/contracts/otel-ingest.md). Every GraphQL request rides one HTTP endpoint\n// (`POST /graphql`), so at HTTP grain the whole API collapses to a single edge;\n// this node recovers the operation-level topology the client actually named.\n// Identified by `graphqlOperationId(service, operationType, operationName)` →\n// `graphql:<service>:<type> <name>`. `service` is the serving service; `type` is\n// the operation kind (`query` / `mutation` / `subscription`); `name` mirrors\n// `operationName` for the shared node-name convention. `path` / `line` locate\n// the resolver in source when a future static GraphQL extractor fills them in —\n// absent in the observed-first cut, never fabricated (file-awareness.md §6). The\n// node is minted OBSERVED-first from the execution span's `graphql.operation.*`\n// semconv; a later static extractor fuses onto the same id, which is what makes\n// a two-sided divergence possible at operation grain.\nexport const GraphQLOperationNodeSchema = z.object({\n id: z.string(),\n type: z.literal(NodeType.GraphQLOperationNode),\n name: z.string(),\n service: z.string(),\n operationType: z.string(),\n operationName: z.string(),\n path: z.string().optional(),\n line: z.number().int().nonnegative().optional(),\n discoveredVia: DiscoveredViaSchema.optional(),\n})\nexport type GraphQLOperationNode = z.infer<typeof GraphQLOperationNodeSchema>\n\n// GrpcMethodNode — a single gRPC method at (rpcService, rpcMethod) granularity\n// (ADR-123 / docs/contracts/otel-ingest.md + static-extraction.md). gRPC used to\n// engage only at service grain, collapsing every method onto one service→service\n// edge; this node recovers the per-method topology. Identified by\n// `grpcMethodId(rpcService, rpcMethod)` → `grpc:<rpcService>/<rpcMethod>`.\n// `rpcService` is the fully-qualified proto service name — the OTel `rpc.service`\n// (`orders.OrderService`), which is the `<package>.<Service>` a `.proto`\n// declares — and `rpcMethod` is the bare method (`GetOrder`). That FQN is the\n// wire contract both the OBSERVED span and the static `.proto` carry verbatim, so\n// keying on it (globally, not scoped to the NEAT manifest name) lets an observed\n// method and its declared definition fuse onto one node; the implementing service\n// owns it through a separate `CONTAINS` edge. `path` / `line` locate the `rpc`\n// line in the `.proto` when the static producer fills them in, or the resolver\n// call site an OBSERVED span carried — absent when neither is known, never\n// fabricated (file-awareness.md §6). Minted from either side; fusing the two\n// provenances onto one node is what makes a method-grain two-sided divergence\n// possible.\nexport const GrpcMethodNodeSchema = z.object({\n id: z.string(),\n type: z.literal(NodeType.GrpcMethodNode),\n name: z.string(),\n rpcService: z.string(),\n rpcMethod: z.string(),\n path: z.string().optional(),\n line: z.number().int().nonnegative().optional(),\n discoveredVia: DiscoveredViaSchema.optional(),\n})\nexport type GrpcMethodNode = z.infer<typeof GrpcMethodNodeSchema>\n\n// WebSocketChannelNode — a live WebSocket channel at (service, channel)\n// granularity (ADR-125 / docs/contracts/otel-ingest.md). A WebSocket app used to\n// produce no OBSERVED topology — only message-handler errors, as incidents —\n// leaving the channels themselves invisible. This node recovers the channel-level\n// topology from the HTTP upgrade span that opens the connection (a SERVER `GET`\n// carrying `Upgrade: websocket` and the WebSocket path). Identified by\n// `websocketChannelId(service, channel)` → `ws:<service>:<channel>`. `service` is\n// the serving service; `channel` is the connection path/channel (`/chat`,\n// `/socket.io`), mirrored into `name` for the shared node-name convention. It is\n// minted OBSERVED-only: a WebSocket channel is known from observation, never from\n// static extraction, so — unlike RouteNode / GraphQLOperationNode / GrpcMethodNode\n// — there is no declared twin to fuse with and no static producer to fill in\n// `path` / `line`. Those stay optional and absent in this cut, never fabricated\n// (file-awareness.md §6). The edge onto it reuses the existing `CONNECTS_TO` — an\n// observed-liveness edge that carries `lastObserved` and decays OBSERVED → STALE\n// on CONNECTS_TO's own staleness threshold when the channel goes quiet.\nexport const WebSocketChannelNodeSchema = z.object({\n id: z.string(),\n type: z.literal(NodeType.WebSocketChannelNode),\n name: z.string(),\n service: z.string(),\n channel: z.string(),\n path: z.string().optional(),\n line: z.number().int().nonnegative().optional(),\n discoveredVia: DiscoveredViaSchema.optional(),\n})\nexport type WebSocketChannelNode = z.infer<typeof WebSocketChannelNodeSchema>\n\nexport const GraphNodeSchema = z.discriminatedUnion('type', [\n ServiceNodeSchema,\n DatabaseNodeSchema,\n ConfigNodeSchema,\n InfraNodeSchema,\n FrontierNodeSchema,\n FileNodeSchema,\n RouteNodeSchema,\n GraphQLOperationNodeSchema,\n GrpcMethodNodeSchema,\n WebSocketChannelNodeSchema,\n])\nexport type GraphNode = z.infer<typeof GraphNodeSchema>\n","import { z } from 'zod'\nimport { EdgeType, Provenance } from './constants.js'\n\nexport const ProvenanceSchema = z.enum([\n Provenance.EXTRACTED,\n Provenance.INFERRED,\n Provenance.OBSERVED,\n Provenance.STALE,\n])\n\nexport const EdgeTypeSchema = z.enum([\n EdgeType.CALLS,\n EdgeType.DEPENDS_ON,\n EdgeType.CONNECTS_TO,\n EdgeType.CONFIGURED_BY,\n EdgeType.PUBLISHES_TO,\n EdgeType.CONSUMES_FROM,\n EdgeType.RUNS_ON,\n EdgeType.CONTAINS,\n EdgeType.IMPORTS,\n])\n\n// Static-extraction evidence for an EXTRACTED edge (ADR-029, contract #5).\n// `file` is required — retire.ts keys ghost-edge cleanup off it. `line` and\n// `snippet` are optional because the existing extractors (configs.ts,\n// docker-compose.ts) record file-level evidence only; loosening lets those\n// edges through ADR-061's response-shape validation without forcing the\n// extractors to fabricate line numbers.\nexport const EdgeEvidenceSchema = z.object({\n file: z.string(),\n line: z.number().int().nonnegative().optional(),\n snippet: z.string().optional(),\n // HTTP shape of a recognised client call site (ADR-119). Present on a\n // client↔route CALLS edge so the edge records the method + path-template the\n // client named, alongside the file:line it named them at. Absent on every\n // other edge — a config or infra edge has no HTTP method.\n method: z.string().optional(),\n pathTemplate: z.string().optional(),\n})\nexport type EdgeEvidence = z.infer<typeof EdgeEvidenceSchema>\n\n// Runtime signal for per-edge confidence (γ #76). Populated by ingest. Three\n// continuous numbers stand in for the previous coarse 0.3/0.5/0.7/1.0 ladder:\n// how much traffic, how clean, and how recent.\nexport const EdgeSignalSchema = z.object({\n spanCount: z.number().int().nonnegative(),\n errorCount: z.number().int().nonnegative(),\n lastObservedAgeMs: z.number().nonnegative().optional(),\n})\nexport type EdgeSignal = z.infer<typeof EdgeSignalSchema>\n\n// `confidence` is in [0, 1] and graded per provenance tier (ADR-066). Producers\n// write it on every EXTRACTED and OBSERVED edge via the helpers in\n// confidence.ts; flat coarse values (the old `0.5` / `1.0` shape) are a\n// contract violation. The field stays `.optional()` for snapshot back-compat —\n// older snapshots may carry edges without confidence and persist.ts loads them\n// on the documented growth path (ADR-031).\nexport const GraphEdgeSchema = z.object({\n id: z.string(),\n source: z.string(),\n target: z.string(),\n type: EdgeTypeSchema,\n provenance: ProvenanceSchema,\n confidence: z.number().min(0).max(1).optional(),\n lastObserved: z.string().datetime().optional(),\n callCount: z.number().int().nonnegative().optional(),\n evidence: EdgeEvidenceSchema.optional(),\n signal: EdgeSignalSchema.optional(),\n // OBSERVED grain (ADR-142): `file` when the edge originates from a source\n // file's call site (a `file:` source + `evidence`), `service` for the coarse\n // fallback where no call site was captured. Makes \"service-grained only as a\n // labeled fallback\" (connector gate #803) a stored, machine-readable fact\n // instead of a re-derivation from the source prefix. `.optional()` — EXTRACTED\n // edges and legacy snapshots carry none; an OBSERVED edge is backfilled on its\n // next observation.\n grain: z.enum(['file', 'service']).optional(),\n})\nexport type GraphEdge = z.infer<typeof GraphEdgeSchema>\n","import { z } from 'zod'\n\n// Passthrough of OTel span attributes. Records source-attribution\n// (`code.filepath`, `code.lineno`, `code.function`), HTTP context\n// (`http.method`, `http.target`, `http.status_code`), DB context\n// (`db.system`, `db.statement`), and any other span attribute the SDK\n// emitted. Consumers (incident UI, MCP getRootCause) filter what they\n// surface. Schema growth per ADR-031 — optional, additive only.\nexport const SpanAttributesSchema = z.record(\n z.string(),\n z.union([z.string(), z.number(), z.boolean(), z.null(), z.array(z.string()), z.array(z.number()), z.array(z.boolean())]),\n)\nexport type SpanAttributes = z.infer<typeof SpanAttributesSchema>\n\nexport const ErrorEventSchema = z.object({\n id: z.string(),\n timestamp: z.string().datetime(),\n service: z.string(),\n traceId: z.string(),\n spanId: z.string(),\n errorType: z.string().optional(),\n errorMessage: z.string(),\n // OTLP span events with name=\"exception\" carry richer error data than\n // status.message. When present, these fields capture the exception type\n // and stacktrace from the SDK that recorded the error. ADR-031 schema\n // growth — added without a shape change because both fields are optional.\n exceptionType: z.string().optional(),\n exceptionStacktrace: z.string().optional(),\n // Span attributes passthrough (ADR-068 follow-up). Surfaces `code.*`\n // semconv attributes for source attribution, plus the rest of the\n // attribute set for downstream filtering.\n attributes: SpanAttributesSchema.optional(),\n affectedNode: z.string(),\n // Failing-response incidents (issue #481). A span that completes 5xx, or a\n // coalesced run of 4xx CLIENT/PRODUCER spans against one peer, records an\n // incident even though OTel leaves the CLIENT span's status UNSET. These\n // fields carry the response code and the burst shape; ADR-031 schema growth —\n // all optional, so the statusCode === 2 and exception paths keep their shape.\n // httpStatusCode — the response status (the dominant code for a burst).\n // incidentCount — how many failing responses this incident coalesces\n // (1 for a 5xx, N for a flushed 4xx burst).\n // firstTimestamp / lastTimestamp — the burst's span-time bounds.\n httpStatusCode: z.number().int().optional(),\n incidentCount: z.number().int().positive().optional(),\n firstTimestamp: z.string().datetime().optional(),\n lastTimestamp: z.string().datetime().optional(),\n})\nexport type ErrorEvent = z.infer<typeof ErrorEventSchema>\n\n// Appended one-per-line to stale-events.ndjson whenever ingest.ts demotes\n// an OBSERVED edge to STALE (per-edge-type thresholds, ADR-024). Surfaces\n// on GET /stale-events for incident triage.\nexport const StaleEventSchema = z.object({\n edgeId: z.string(),\n source: z.string(),\n target: z.string(),\n edgeType: z.string(),\n thresholdMs: z.number().nonnegative(),\n ageMs: z.number().nonnegative(),\n lastObserved: z.string(),\n transitionedAt: z.string(),\n})\nexport type StaleEvent = z.infer<typeof StaleEventSchema>\n\n// The one shape every log producer emits (docs/contracts/logs.md Rule 1,\n// ADR-132) — a native OTLP `/v1/logs` receiver (source: 'native') and each\n// connector's provider-specific mapping layer (source: '<provider>') both\n// produce this. `logs-store.ts` holds these in a bounded per-(project,\n// source) ring buffer; GET /logs is the only REST surface that reads it.\n// `source` is extensible the same way the connector provider dispatch table\n// grows one entry per provider.\nexport const LogSourceSchema = z.enum([\n 'native',\n 'supabase',\n 'railway',\n 'firebase',\n 'cloudflare',\n 'vercel',\n])\nexport type LogSource = z.infer<typeof LogSourceSchema>\n\nexport const LogEntrySchema = z.object({\n id: z.string(),\n projectName: z.string(),\n source: LogSourceSchema,\n serviceName: z.string().optional(),\n nodeId: z.string().optional(),\n // ISO8601, the event's own time — never ingest/poll time.\n timestamp: z.string().datetime(),\n // Normalized upstream to 'debug' | 'info' | 'warn' | 'error' by whichever\n // producer wrote the entry; kept as a plain string here rather than a\n // locked enum because normalization is a producer concern, not this\n // schema's.\n severity: z.string().optional(),\n message: z.string(),\n attributes: z.record(z.string(), z.unknown()).optional(),\n})\nexport type LogEntry = z.infer<typeof LogEntrySchema>\n","import { z } from 'zod'\nimport { ProvenanceSchema, EdgeTypeSchema, GraphEdgeSchema } from './edges.js'\n\nexport const RootCauseResultSchema = z.object({\n rootCauseNode: z.string(),\n rootCauseReason: z.string(),\n traversalPath: z.array(z.string()),\n edgeProvenances: z.array(ProvenanceSchema),\n confidence: z.number().min(0).max(1),\n fixRecommendation: z.string().optional(),\n})\nexport type RootCauseResult = z.infer<typeof RootCauseResultSchema>\n\nexport const BlastRadiusAffectedNodeSchema = z.object({\n nodeId: z.string(),\n // Distance from the origin in BFS hops. The origin itself is never in\n // affectedNodes, so distance 0 has no meaning — the BFS at traverse.ts\n // already skips frame 0. Tightening to positive() locks that invariant\n // mechanically (ADR-038, issue #138).\n distance: z.number().int().positive(),\n edgeProvenance: ProvenanceSchema,\n // path: origin → ... → nodeId. Length === distance + 1. Surfaced from the\n // BFS predecessor chain so consumers don't have to reconstruct it from\n // distance + the graph (ADR-038, issue #137).\n path: z.array(z.string()).min(2),\n // confidence: confidenceFromMix(...edgesAlongPath). Multiplicative cascade —\n // each hop is independent evidence and uncertainty compounds. ADR-036.\n confidence: z.number().min(0).max(1),\n})\nexport type BlastRadiusAffectedNode = z.infer<typeof BlastRadiusAffectedNodeSchema>\n\nexport const BlastRadiusResultSchema = z.object({\n origin: z.string(),\n affectedNodes: z.array(BlastRadiusAffectedNodeSchema),\n totalAffected: z.number().int().nonnegative(),\n})\nexport type BlastRadiusResult = z.infer<typeof BlastRadiusResultSchema>\n\n// Transitive get_dependencies (issue #144). Flat list with distance, edge\n// type, and provenance per dependency. Sibling shape to BlastRadius but\n// thinner — no path tracking, no confidence cascade. Use cases live in the\n// MCP get_dependencies tool (\"what does X depend on, transitively?\").\nexport const TransitiveDependencySchema = z.object({\n nodeId: z.string(),\n // Distance from the origin in BFS hops. The origin itself is never in\n // dependencies, so distance is positive (>= 1).\n distance: z.number().int().positive(),\n // Type of the edge that brought traversal to this node (CALLS,\n // CONNECTS_TO, DEPENDS_ON, etc.).\n edgeType: EdgeTypeSchema,\n // Provenance of that edge.\n provenance: ProvenanceSchema,\n})\nexport type TransitiveDependency = z.infer<typeof TransitiveDependencySchema>\n\nexport const TransitiveDependenciesResultSchema = z.object({\n origin: z.string(),\n depth: z.number().int().positive(),\n dependencies: z.array(TransitiveDependencySchema),\n total: z.number().int().nonnegative(),\n})\nexport type TransitiveDependenciesResult = z.infer<typeof TransitiveDependenciesResultSchema>\n\n// Observed-only dependencies (issue #578). \"What does this node actually call\n// at runtime?\" — the OBSERVED outbound edges, file-grained. When the queried\n// node is a ServiceNode the real runtime CALLS originate from the FileNodes it\n// owns (the call-site processor lands OBSERVED edges on files, not the service\n// root), so the query walks one hop through `service ──CONTAINS──▶ file` and\n// surfaces those file→target edges. This is not a service rollup\n// (file-awareness §3): the edges stay file-grained, with the owning file as the\n// edge source — the service is just the grouping we entered through.\n//\n// `observed` / `inboundObservedCount` separate \"no outbound deps\" from \"never\n// observed\": a pure receiver (hit at runtime but calls nothing downstream) has\n// zero dependencies yet is very much seen by OTel, so the consumer must not say\n// \"is OTel running?\" at it. `hasExtractedOutbound` gates that question to the\n// genuine no-runtime-traffic case.\nexport const ObservedDependenciesResultSchema = z.object({\n origin: z.string(),\n // OBSERVED outbound edges (CALLS/CONNECTS_TO/etc.), file-grained. Structural\n // CONTAINS ownership is never listed here — it is not a runtime dependency.\n dependencies: z.array(GraphEdgeSchema),\n // Did OTel see this node (or a file it owns) at all — as caller or callee?\n // Distinguishes a pure receiver from a node runtime has never touched.\n observed: z.boolean(),\n // Count of OBSERVED inbound edges into the node (and its owned files). A\n // non-zero count with zero dependencies is the pure-receiver signal.\n inboundObservedCount: z.number().int().nonnegative(),\n // Are there EXTRACTED outbound edges but no OBSERVED ones? Only then is\n // \"static deps exist but no runtime traffic — is OTel running?\" the honest note.\n hasExtractedOutbound: z.boolean(),\n})\nexport type ObservedDependenciesResult = z.infer<typeof ObservedDependenciesResultSchema>\n","// Identity helpers — the single source of truth for node and edge id wire\n// format. See ADR-028 (nodes), ADR-029 (edges), and docs/contracts/identity.md\n// + docs/contracts/provenance.md.\n//\n// Producers construct ids via these helpers; consumers parse via the inverses.\n// Hand-rolled template literals like `service:${name}` or\n// `${type}:OBSERVED:${source}->${target}` are contract violations\n// (caught by packages/core/test/audits/contracts.test.ts).\n\nconst SERVICE_PREFIX = 'service:'\nconst DATABASE_PREFIX = 'database:'\nconst CONFIG_PREFIX = 'config:'\nconst INFRA_PREFIX = 'infra:'\nconst FRONTIER_PREFIX = 'frontier:'\nconst FILE_PREFIX = 'file:'\nconst ROUTE_PREFIX = 'route:'\nconst GRAPHQL_OP_PREFIX = 'graphql:'\nconst GRPC_METHOD_PREFIX = 'grpc:'\nconst WEBSOCKET_CHANNEL_PREFIX = 'ws:'\n\n// ServiceNode id: `service:<name>` for env-unknown nodes (the default,\n// produced by static extraction or by ingest when the span carries no env\n// signal) and `service:<name>:<env>` for env-tagged nodes (produced by\n// ingest when the span carries `deployment.environment(.name)`).\n//\n// <name> is the manifest name verbatim (package.json#name for JS/TS,\n// pyproject [project].name for Python). Names with slashes (e.g. scoped\n// npm packages `@org/foo`) are kept as-is — no transformation. See\n// ADR-028 §5 for workspace-collision deferral.\n//\n// The env discriminator is ADR-074 §2. `env === 'unknown'` is the honest\n// \"no signal\" sentinel; emitting it as the env-less wire format keeps\n// pre-v0.3.9 snapshots byte-stable on disk.\nconst ENV_UNKNOWN = 'unknown'\n\nexport function serviceId(name: string, env?: string): string {\n if (env === undefined || env === ENV_UNKNOWN) return `${SERVICE_PREFIX}${name}`\n return `${SERVICE_PREFIX}${name}:${env}`\n}\n\n// Parse a service id into its (name, env) tuple. Returns null when the\n// input is not a service id. env is `'unknown'` when the id carries no\n// env segment (the env-less wire format).\nexport function parseServiceId(id: string): { name: string; env: string } | null {\n if (!id.startsWith(SERVICE_PREFIX)) return null\n const rest = id.slice(SERVICE_PREFIX.length)\n if (rest.length === 0) return null\n const colon = rest.indexOf(':')\n if (colon === -1) return { name: rest, env: ENV_UNKNOWN }\n return { name: rest.slice(0, colon), env: rest.slice(colon + 1) }\n}\n\n// DatabaseNode id: `database:<host>`. Port is intentionally excluded; two DBs\n// on the same host different ports collide. See ADR-028 §6 for deferral.\nexport function databaseId(host: string): string {\n return `${DATABASE_PREFIX}${host}`\n}\n\nexport function parseDatabaseId(id: string): string | null {\n return id.startsWith(DATABASE_PREFIX) ? id.slice(DATABASE_PREFIX.length) : null\n}\n\n// In-process / embedded DatabaseNode id: `database:<service>/<name>`. An\n// embedded database (SQLite, better-sqlite3, an in-memory store) crosses no\n// network boundary, so a span for it carries no peer host to key `databaseId`\n// on. Two services each reading their own `app.db` would then collapse onto one\n// node; scoping the id by the observing service keeps them distinct. `name` is\n// the logical database (`db.name`) when the span carries one, the engine string\n// otherwise. Env-unscoped like `databaseId` (env-dimension.md). See ADR-118.\nexport function localDatabaseId(service: string, name: string): string {\n return `${DATABASE_PREFIX}${service}/${name}`\n}\n\n// ConfigNode id: `config:<relPath>` where <relPath> is the path relative to\n// the scan root, with forward slashes regardless of platform. ConfigNodes\n// record file existence only (ADR-016).\nexport function configId(relPath: string): string {\n return `${CONFIG_PREFIX}${relPath}`\n}\n\nexport function parseConfigId(id: string): string | null {\n return id.startsWith(CONFIG_PREFIX) ? id.slice(CONFIG_PREFIX.length) : null\n}\n\n// InfraNode id: `infra:<kind>:<name>`. <kind> is a free string sub-type\n// (kafka-topic, redis, grpc-service, lambda, queue, etc.) per ADR-022.\nexport function infraId(kind: string, name: string): string {\n return `${INFRA_PREFIX}${kind}:${name}`\n}\n\nexport function parseInfraId(id: string): { kind: string; name: string } | null {\n if (!id.startsWith(INFRA_PREFIX)) return null\n const rest = id.slice(INFRA_PREFIX.length)\n const colon = rest.indexOf(':')\n if (colon === -1) return null\n return { kind: rest.slice(0, colon), name: rest.slice(colon + 1) }\n}\n\n// FrontierNode id: `frontier:<host>` where <host> is host:port from the OTel\n// peer attribute. Promoted to a typed node id (typically serviceId(...)) once\n// an alias resolves; the FrontierNode is removed and edges are rewritten.\nexport function frontierId(host: string): string {\n return `${FRONTIER_PREFIX}${host}`\n}\n\nexport function parseFrontierId(id: string): string | null {\n return id.startsWith(FRONTIER_PREFIX) ? id.slice(FRONTIER_PREFIX.length) : null\n}\n\n// FileNode id: `file:<service>:<relPath>` (ADR-089 / file-awareness.md §1).\n// The `service` segment is the owning service's manifest name — the same token\n// `serviceId(name)` carries — so a shared relative path across monorepo\n// packages stays distinct. `relPath` is the service-relative path with forward\n// slashes. Files belong to a package, not an environment, so the id is\n// env-unscoped (unlike ServiceNode): EXTRACTED (env-less) and OBSERVED\n// (env-tagged source service) edges land on the same FileNode, which is what\n// makes the file-grained divergence comparison possible (file-awareness.md §7).\nexport function fileId(service: string, relPath: string): string {\n return `${FILE_PREFIX}${service}:${relPath}`\n}\n\n// Parse a file id into its (service, relPath) tuple. Returns null when the\n// input isn't a file id. Splits on the first colon after the prefix: service\n// names never contain a colon (scoped npm names use `/`), and relPath is\n// normalised to forward slashes with any drive letter stripped before the id\n// is built, so the first colon is unambiguously the service/path boundary.\nexport function parseFileId(id: string): { service: string; relPath: string } | null {\n if (!id.startsWith(FILE_PREFIX)) return null\n const rest = id.slice(FILE_PREFIX.length)\n const colon = rest.indexOf(':')\n if (colon === -1) return null\n const service = rest.slice(0, colon)\n const relPath = rest.slice(colon + 1)\n if (service.length === 0 || relPath.length === 0) return null\n return { service, relPath }\n}\n\n// RouteNode id: `route:<service>:<METHOD> <pathTemplate>` (ADR-119). The\n// `service` segment is the owning (server) service's manifest name, matching\n// the FileNode / ServiceNode convention so a shared path across monorepo\n// packages stays distinct. `method` is upper-cased (`GET`, `POST`, or `ALL`\n// for a method-agnostic route); `pathTemplate` is the route's declared template\n// verbatim (`/users/:id`), lightly canonicalised (leading slash, no trailing\n// slash). The space between method and template is unambiguous — a method token\n// never contains a space and a service name never contains a colon. Routes are\n// a server-side artifact of a package, not an environment, so the id is\n// env-unscoped like FileNode: an EXTRACTED route and a future OBSERVED server\n// span land on the same node, which is what makes a two-sided divergence\n// possible at route grain.\nexport function routeId(service: string, method: string, pathTemplate: string): string {\n return `${ROUTE_PREFIX}${service}:${method.toUpperCase()} ${pathTemplate}`\n}\n\n// Parse a route id into its (service, method, pathTemplate) tuple. Returns null\n// when the input isn't a route id. Splits service on the first colon after the\n// prefix (service names carry no colon), then method on the first space.\nexport function parseRouteId(\n id: string,\n): { service: string; method: string; pathTemplate: string } | null {\n if (!id.startsWith(ROUTE_PREFIX)) return null\n const rest = id.slice(ROUTE_PREFIX.length)\n const colon = rest.indexOf(':')\n if (colon === -1) return null\n const service = rest.slice(0, colon)\n const tail = rest.slice(colon + 1)\n const space = tail.indexOf(' ')\n if (space === -1) return null\n const method = tail.slice(0, space)\n const pathTemplate = tail.slice(space + 1)\n if (service.length === 0 || method.length === 0 || pathTemplate.length === 0) return null\n return { service, method, pathTemplate }\n}\n\n// GraphQLOperationNode id: `graphql:<service>:<type> <operationName>` (ADR-122).\n// The `service` segment is the serving service's manifest name, matching the\n// FileNode / RouteNode convention so a shared operation name across monorepo\n// packages stays distinct. `type` is lower-cased (`query` / `mutation` /\n// `subscription`); `operationName` is the client-supplied operation name\n// verbatim. The space between type and name is unambiguous — a GraphQL operation\n// type never contains a space and a service name never contains a colon. A\n// GraphQL operation is a server-side artifact of a package, not an environment,\n// so the id is env-unscoped like FileNode / RouteNode: an OBSERVED execution\n// span and a future EXTRACTED schema/resolver land on the same node, which is\n// what makes an operation-grained two-sided divergence possible.\nexport function graphqlOperationId(\n service: string,\n operationType: string,\n operationName: string,\n): string {\n return `${GRAPHQL_OP_PREFIX}${service}:${operationType.toLowerCase()} ${operationName}`\n}\n\n// Parse a GraphQL operation id into its (service, operationType, operationName)\n// tuple. Returns null when the input isn't a GraphQL operation id. Splits\n// service on the first colon after the prefix (service names carry no colon),\n// then type on the first space.\nexport function parseGraphqlOperationId(\n id: string,\n): { service: string; operationType: string; operationName: string } | null {\n if (!id.startsWith(GRAPHQL_OP_PREFIX)) return null\n const rest = id.slice(GRAPHQL_OP_PREFIX.length)\n const colon = rest.indexOf(':')\n if (colon === -1) return null\n const service = rest.slice(0, colon)\n const tail = rest.slice(colon + 1)\n const space = tail.indexOf(' ')\n if (space === -1) return null\n const operationType = tail.slice(0, space)\n const operationName = tail.slice(space + 1)\n if (service.length === 0 || operationType.length === 0 || operationName.length === 0) {\n return null\n }\n return { service, operationType, operationName }\n}\n\n// GrpcMethodNode id: `grpc:<rpcService>/<rpcMethod>` (ADR-123). Unlike the\n// RouteNode / GraphQLOperationNode ids, this one is NOT scoped to the NEAT\n// manifest service name — it keys on the fully-qualified gRPC `rpc.service`\n// (`orders.OrderService`, the proto's `<package>.<Service>`) instead. That FQN is\n// the wire contract: an OTel span and a `.proto` definition both carry it\n// verbatim, and it is globally unique across a gRPC mesh (the package qualifier\n// disambiguates), so keying on it — rather than on whoever happens to serve or\n// call the method — is exactly what fuses the OBSERVED span and the EXTRACTED\n// `.proto` onto one node. The implementing service's ownership is a separate\n// `CONTAINS` edge, not part of identity. `/` separates service from method\n// unambiguously: an `rpc.service` FQN carries dots but never a slash, and a\n// method name is a bare identifier.\nexport function grpcMethodId(rpcService: string, rpcMethod: string): string {\n return `${GRPC_METHOD_PREFIX}${rpcService}/${rpcMethod}`\n}\n\n// Parse a gRPC method id into its (rpcService, rpcMethod) tuple. Returns null\n// when the input isn't a gRPC method id. Splits on the first slash after the\n// prefix — the service FQN carries no slash, the method is a bare identifier.\nexport function parseGrpcMethodId(\n id: string,\n): { rpcService: string; rpcMethod: string } | null {\n if (!id.startsWith(GRPC_METHOD_PREFIX)) return null\n const rest = id.slice(GRPC_METHOD_PREFIX.length)\n const slash = rest.indexOf('/')\n if (slash === -1) return null\n const rpcService = rest.slice(0, slash)\n const rpcMethod = rest.slice(slash + 1)\n if (rpcService.length === 0 || rpcMethod.length === 0) return null\n return { rpcService, rpcMethod }\n}\n\n// WebSocketChannelNode id: `ws:<service>:<channel>` (ADR-125). The `service`\n// segment is the serving service's manifest name, matching the FileNode /\n// RouteNode / GraphQLOperationNode convention. Unlike the gRPC id — which keys on\n// the globally-unique fully-qualified `rpc.service` — a WebSocket channel path\n// (`/chat`, `/socket.io`) carries no package qualifier and is not unique across a\n// mesh, so it is scoped to the serving service exactly as a route path is. The\n// channel is a server-side artifact of a package, not an environment, so the id\n// is env-unscoped like FileNode / RouteNode. The `channel` follows the first\n// colon after the prefix; a service name carries no colon, so a channel path that\n// itself contains a colon stays intact on the channel side.\nexport function websocketChannelId(service: string, channel: string): string {\n return `${WEBSOCKET_CHANNEL_PREFIX}${service}:${channel}`\n}\n\n// Parse a WebSocket channel id into its (service, channel) tuple. Returns null\n// when the input isn't a WebSocket channel id. Splits on the first colon after\n// the prefix — the service name carries no colon, the channel is the remainder.\nexport function parseWebsocketChannelId(\n id: string,\n): { service: string; channel: string } | null {\n if (!id.startsWith(WEBSOCKET_CHANNEL_PREFIX)) return null\n const rest = id.slice(WEBSOCKET_CHANNEL_PREFIX.length)\n const colon = rest.indexOf(':')\n if (colon === -1) return null\n const service = rest.slice(0, colon)\n const channel = rest.slice(colon + 1)\n if (service.length === 0 || channel.length === 0) return null\n return { service, channel }\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Edge ids (ADR-029, ADR-068)\n// ──────────────────────────────────────────────────────────────────────────\n//\n// Edge id wire format per provenance:\n// EXTRACTED: `${type}:${source}->${target}`\n// OBSERVED: `${type}:OBSERVED:${source}->${target}`\n// INFERRED: `${type}:INFERRED:${source}->${target}`\n// STALE never appears in an edge id; STALE is a transition of an existing\n// OBSERVED edge (ADR-024), not a creation pattern.\n//\n// Per ADR-068, edges to FrontierNodes carry whatever provenance describes\n// how the edge was learned — span-derived edges use observedEdgeId with the\n// FrontierNode id as the target string. Node-type is orthogonal to\n// provenance; the wire format reflects provenance only.\n//\n// Multiple edges between the same node pair coexist under distinct provenance\n// ids — that's what makes the EXTRACTED+OBSERVED coexistence rule\n// (contracts.md Rule 2) mechanically possible.\n\nconst EDGE_ARROW = '->'\n\nexport function extractedEdgeId(source: string, target: string, type: string): string {\n return `${type}:${source}${EDGE_ARROW}${target}`\n}\n\nexport function observedEdgeId(source: string, target: string, type: string): string {\n return `${type}:OBSERVED:${source}${EDGE_ARROW}${target}`\n}\n\nexport function inferredEdgeId(source: string, target: string, type: string): string {\n return `${type}:INFERRED:${source}${EDGE_ARROW}${target}`\n}\n\n// Parse an edge id into its parts. Returns null if the input is not a\n// well-formed edge id — covers all three creation variants (STALE rides on\n// the OBSERVED id format). Useful for consumers (traversal, MCP, persist)\n// that need to walk back from an id.\n//\n// Note: EXTRACTED ids have no provenance segment, so we detect them by\n// checking whether the second segment matches a known provenance marker.\nexport function parseEdgeId(id: string): {\n type: string\n provenance: 'EXTRACTED' | 'OBSERVED' | 'INFERRED'\n source: string\n target: string\n} | null {\n const arrowIdx = id.lastIndexOf(EDGE_ARROW)\n if (arrowIdx === -1) return null\n const left = id.slice(0, arrowIdx)\n const target = id.slice(arrowIdx + EDGE_ARROW.length)\n if (!left || !target) return null\n\n // left is one of:\n // `${type}:${source}` → EXTRACTED\n // `${type}:OBSERVED:${source}` → OBSERVED\n // `${type}:INFERRED:${source}` → INFERRED\n const firstColon = left.indexOf(':')\n if (firstColon === -1) return null\n const type = left.slice(0, firstColon)\n const rest = left.slice(firstColon + 1)\n\n for (const prov of ['OBSERVED', 'INFERRED'] as const) {\n if (rest.startsWith(`${prov}:`)) {\n return { type, provenance: prov, source: rest.slice(prov.length + 1), target }\n }\n }\n return { type, provenance: 'EXTRACTED', source: rest, target }\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Provenance ranking (ADR-029, ADR-068)\n// ──────────────────────────────────────────────────────────────────────────\n//\n// Canonical priority used by traversal and any consumer that needs to pick\n// a single edge between two nodes when multiple provenance variants exist.\n// Higher number = higher trust = preferred.\n//\n// Four entries match the four-value Provenance enum (ADR-068). Node-type\n// gating (e.g. \"stop at FrontierNodes\" per contracts.md Rule 3) is enforced\n// at the node level by traversal, independent of edge rank.\nexport const PROV_RANK: Readonly<Record<'OBSERVED' | 'INFERRED' | 'EXTRACTED' | 'STALE', number>> = Object.freeze({\n OBSERVED: 3,\n INFERRED: 2,\n EXTRACTED: 1,\n STALE: 0,\n})\n","import { z } from 'zod'\nimport { ProvenanceSchema, EdgeTypeSchema } from './edges.js'\nimport { NodeTypeSchema } from './constants.js'\n\n// Policy schema (ADR-042). Lives at <projectRoot>/policy.json. Loaded at\n// startup and reloaded on file change. Five rule types, discriminated by\n// `rule.type`. Adding a new rule type requires an ADR amendment plus a\n// corresponding evaluator in the engine (ADR-043).\n\nexport const PolicySeveritySchema = z.enum(['info', 'warning', 'error', 'critical'])\nexport type PolicySeverity = z.infer<typeof PolicySeveritySchema>\n\nexport const PolicyActionSchema = z.enum(['log', 'alert', 'block'])\nexport type PolicyAction = z.infer<typeof PolicyActionSchema>\n\n// rule.type === 'structural' — asserts the existence of an edge between\n// node-type pairs. e.g. \"every ServiceNode must have a CONNECTS_TO edge to a\n// DatabaseNode.\"\nexport const StructuralRuleSchema = z.object({\n type: z.literal('structural'),\n // Node type the rule applies to. Every node of this type must satisfy the\n // edge requirement below.\n fromNodeType: NodeTypeSchema,\n // Required outbound edge type from each fromNodeType node.\n edgeType: EdgeTypeSchema,\n // Required target node type at the other end of the edge.\n toNodeType: NodeTypeSchema,\n})\nexport type StructuralRule = z.infer<typeof StructuralRuleSchema>\n\n// rule.type === 'compatibility' — re-runs `compat.ts` against current graph\n// state. Catches OBSERVED-vs-EXTRACTED divergence: a service whose compat\n// shape failed at extract time stays flagged on every evaluation.\nexport const CompatibilityRuleSchema = z.object({\n type: z.literal('compatibility'),\n // Optional kind narrowing. When omitted, all four compat shapes\n // (driver-engine, node-engine, package-conflict, deprecated-api) run.\n kind: z\n .enum(['driver-engine', 'node-engine', 'package-conflict', 'deprecated-api'])\n .optional(),\n})\nexport type CompatibilityRule = z.infer<typeof CompatibilityRuleSchema>\n\n// rule.type === 'provenance' — asserts that edges of a given type to a given\n// target carry a specific provenance (or one of a set). e.g. \"every CALLS\n// edge to service:payments must have OBSERVED provenance.\"\nexport const ProvenanceRuleSchema = z.object({\n type: z.literal('provenance'),\n // Edge type the rule applies to.\n edgeType: EdgeTypeSchema,\n // Target node id (e.g. 'service:payments') that incoming edges of edgeType\n // must satisfy. Optional — when omitted, the rule runs against every edge\n // of edgeType regardless of target.\n targetNodeId: z.string().optional(),\n // Required provenance (single value or one-of). The audit fails if the\n // observed edge's provenance is not in this set.\n required: z.union([ProvenanceSchema, z.array(ProvenanceSchema).min(1)]),\n})\nexport type ProvenanceRule = z.infer<typeof ProvenanceRuleSchema>\n\n// rule.type === 'ownership' — every node of nodeType must declare an `owner`\n// field. The field name lives on the node attributes; the rule fires when a\n// node of the type doesn't carry it (or carries an empty string).\nexport const OwnershipRuleSchema = z.object({\n type: z.literal('ownership'),\n // Node type the rule applies to. ServiceNode is the common case; the\n // discriminator stays generic so future node types can opt in.\n nodeType: NodeTypeSchema,\n // Field name on the node attributes that must be non-empty. Defaults to\n // 'owner' if omitted.\n field: z.string().default('owner'),\n})\nexport type OwnershipRule = z.infer<typeof OwnershipRuleSchema>\n\n// rule.type === 'blast-radius' — no node of the given type may have more\n// than `maxAffected` transitively-affected downstream nodes. Computed via\n// getBlastRadius at evaluation time.\nexport const BlastRadiusRuleSchema = z.object({\n type: z.literal('blast-radius'),\n // Node type the rule applies to (ServiceNode is the common case).\n nodeType: NodeTypeSchema,\n // Cap on `totalAffected` from getBlastRadius. Inclusive — a node hitting\n // exactly this number passes; > maxAffected fails.\n maxAffected: z.number().int().positive(),\n // Depth to evaluate against. Defaults to the contract's blast-radius\n // default (10) when omitted.\n depth: z.number().int().positive().optional(),\n})\nexport type BlastRadiusRule = z.infer<typeof BlastRadiusRuleSchema>\n\nexport const PolicyRuleSchema = z.discriminatedUnion('type', [\n StructuralRuleSchema,\n CompatibilityRuleSchema,\n ProvenanceRuleSchema,\n OwnershipRuleSchema,\n BlastRadiusRuleSchema,\n])\nexport type PolicyRule = z.infer<typeof PolicyRuleSchema>\n\nexport const PolicySchema = z.object({\n // Unique within the file. Duplicates fail PolicyFileSchema.parse.\n id: z.string().min(1),\n name: z.string().min(1),\n description: z.string().optional(),\n severity: PolicySeveritySchema,\n // When omitted, the engine derives a default from severity per ADR-044\n // (info→log, warning→alert, error→alert, critical→block).\n onViolation: PolicyActionSchema.optional(),\n rule: PolicyRuleSchema,\n})\nexport type Policy = z.infer<typeof PolicySchema>\n\n// Top-level shape of policy.json. version: z.literal(1) — bumping requires\n// an ADR amendment per the schema-growth contract (ADR-031).\nexport const PolicyFileSchema = z\n .object({\n version: z.literal(1),\n policies: z.array(PolicySchema),\n })\n .superRefine((file, ctx) => {\n // id uniqueness is enforced at parse time, not at registry-add time.\n // Duplicates collapse silently otherwise — we'd evaluate the second one\n // and lose the first.\n const seen = new Set<string>()\n for (const [i, p] of file.policies.entries()) {\n if (seen.has(p.id)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['policies', i, 'id'],\n message: `duplicate policy id \"${p.id}\"`,\n })\n }\n seen.add(p.id)\n }\n })\nexport type PolicyFile = z.infer<typeof PolicyFileSchema>\n\n// Emitted by the evaluator. Appended to policy-violations.ndjson.\n// Deterministic id (per ADR-043) means re-evaluating the same graph + same\n// policies produces the same violation ids; the writer skips duplicates.\n// Hypothetical action for POST /policies/check (ADR-045). Each action shape\n// names a candidate change to the graph; the engine simulates it and returns\n// any violations that *would* result. MVP scope is the two action shapes\n// below; new shapes need an ADR amendment.\nexport const HypotheticalActionSchema = z.discriminatedUnion('kind', [\n z.object({\n kind: z.literal('promote-frontier'),\n // The FrontierNode id that would be promoted.\n frontierId: z.string().min(1),\n }),\n z.object({\n kind: z.literal('add-edge'),\n source: z.string().min(1),\n target: z.string().min(1),\n edgeType: EdgeTypeSchema,\n provenance: ProvenanceSchema,\n }),\n])\nexport type HypotheticalAction = z.infer<typeof HypotheticalActionSchema>\n\n// Body of POST /policies/check.\nexport const PoliciesCheckBodySchema = z.object({\n hypotheticalAction: HypotheticalActionSchema.optional(),\n})\nexport type PoliciesCheckBody = z.infer<typeof PoliciesCheckBodySchema>\n\n// Scope filter for the check_policies MCP tool. 'all' (default) returns\n// every current violation; 'unresolved' is reserved for future resolution\n// tracking and behaves like 'all' for the MVP; { policyId } narrows to one\n// named policy.\nexport const CheckPoliciesScopeSchema = z.union([\n z.enum(['all', 'unresolved']),\n z.object({ policyId: z.string().min(1) }),\n])\nexport type CheckPoliciesScope = z.infer<typeof CheckPoliciesScopeSchema>\n\n// Soft guardrail (ADR-108 / policies-soft-guardrail.md). The launch form of\n// \"every agent stays inside the lines\": policies INFORM, they never block. An\n// ApplicablePolicy is one policy that governs the node an agent is working at —\n// matched by a direct subject/region rule match (the node's type is the rule's\n// subject, or the node sits one hop inside the rule's region). It is delivered\n// as context, surfaced through check_policies; it carries no violation, no\n// gate, no allowed/denied verdict. `match` records why it applies:\n// - 'subject' — the node is the rule's direct subject (its type is governed).\n// - 'region' — the node sits one hop inside the rule's region (e.g. the\n// target end of a structural edge, or a node on a governed edge).\n// The far-away downstream-breaking invariants the full overlay would surface\n// (ADR-105 §5) need the unbuilt policy overlay; this MVP matches one hop only.\nexport const ApplicablePolicySchema = z.object({\n policyId: z.string().min(1),\n policyName: z.string().min(1),\n description: z.string().optional(),\n severity: PolicySeveritySchema,\n // The action the post-launch kernel gate WOULD take (ADR-093) — resolved\n // from policy.onViolation or the severity default. Shown for awareness only;\n // the soft guardrail never acts on it.\n onViolation: PolicyActionSchema,\n ruleType: z.enum(['structural', 'compatibility', 'provenance', 'ownership', 'blast-radius']),\n match: z.enum(['subject', 'region']),\n // Human-readable reason the policy applies here — rides into agent context.\n reason: z.string().min(1),\n})\nexport type ApplicablePolicy = z.infer<typeof ApplicablePolicySchema>\n\n// Response shape of GET /policies/applicable.\nexport const ApplicablePoliciesResponseSchema = z.object({\n node: z.string().min(1),\n applicable: z.array(ApplicablePolicySchema),\n})\nexport type ApplicablePoliciesResponse = z.infer<typeof ApplicablePoliciesResponseSchema>\n\nexport const PolicyViolationSchema = z.object({\n // ${policy.id}:${violation-context}. The violation-context is shape-\n // specific (e.g. nodeId for structural; edgeId for provenance).\n id: z.string().min(1),\n policyId: z.string().min(1),\n policyName: z.string().min(1),\n severity: PolicySeveritySchema,\n // Resolved at evaluation time — either the explicit policy.onViolation or\n // the severity-derived default per ADR-044.\n onViolation: PolicyActionSchema,\n ruleType: z.enum(['structural', 'compatibility', 'provenance', 'ownership', 'blast-radius']),\n subject: z\n .object({\n nodeId: z.string().optional(),\n edgeId: z.string().optional(),\n path: z.array(z.string()).optional(),\n })\n .refine(\n (s) => s.nodeId !== undefined || s.edgeId !== undefined || s.path !== undefined,\n { message: 'subject must carry at least one of nodeId, edgeId, path' },\n ),\n message: z.string().min(1),\n observedAt: z.string().datetime(),\n})\nexport type PolicyViolation = z.infer<typeof PolicyViolationSchema>\n","import { z } from 'zod'\n\n// Machine-level project registry (ADR-048). Single file at\n// `~/.neat/projects.json`, per-user, machine-local. The wire shape lives here\n// so the registry module and the daemon agree on it without a circular\n// dependency through @neat.is/core.\n\nexport const RegistryStatusSchema = z.enum(['active', 'paused', 'broken'])\nexport type RegistryStatus = z.infer<typeof RegistryStatusSchema>\n\nexport const RegistryEntrySchema = z.object({\n // Unique within the registry. Project-scoped operations (`neat watch\n // --project <name>`, `neatd reload <name>`) key on this. Collisions are a\n // hard error at registration time.\n name: z.string().min(1),\n // Resolved absolute path on disk. Path normalisation is what keeps two\n // `neat init` calls from different relative paths from creating two entries\n // for the same directory.\n path: z.string().min(1),\n // ISO8601, set at first registration.\n registeredAt: z.string(),\n // ISO8601, updated whenever the daemon successfully sees the project.\n // Optional because a freshly-registered project hasn't been seen yet.\n lastSeenAt: z.string().optional(),\n // Languages detected at `init` time. Free-form strings keyed off the\n // installer modules — `'javascript'`, `'python'`, …\n languages: z.array(z.string()),\n status: RegistryStatusSchema,\n})\nexport type RegistryEntry = z.infer<typeof RegistryEntrySchema>\n\nexport const RegistryFileSchema = z.object({\n version: z.literal(1),\n projects: z.array(RegistryEntrySchema),\n})\nexport type RegistryFile = z.infer<typeof RegistryFileSchema>\n\nexport const EMPTY_REGISTRY: RegistryFile = { version: 1, projects: [] }\n","// Divergence — the thesis surface (ADR-060). A typed result describing\n// places where what the code declares (EXTRACTED) doesn't match what\n// production observed (OBSERVED). Five locked variants discriminated by\n// `type`; new shapes require a successor ADR.\n//\n// The schema lives here because consumers across the stack (REST, MCP,\n// CLI, future frontend) need to validate the wire shape against the same\n// definition. Computation lives in packages/core/src/divergences.ts —\n// pure functions over a NeatGraph; no I/O, no mutation.\n\nimport { z } from 'zod'\nimport { EdgeTypeSchema, GraphEdgeSchema } from './edges.js'\n\nconst commonFields = {\n source: z.string(),\n target: z.string(),\n confidence: z.number().min(0).max(1),\n reason: z.string(),\n recommendation: z.string(),\n}\n\nexport const MissingObservedDivergenceSchema = z.object({\n type: z.literal('missing-observed'),\n ...commonFields,\n edgeType: EdgeTypeSchema,\n extracted: GraphEdgeSchema,\n})\nexport type MissingObservedDivergence = z.infer<typeof MissingObservedDivergenceSchema>\n\nexport const MissingExtractedDivergenceSchema = z.object({\n type: z.literal('missing-extracted'),\n ...commonFields,\n edgeType: EdgeTypeSchema,\n observed: GraphEdgeSchema,\n})\nexport type MissingExtractedDivergence = z.infer<typeof MissingExtractedDivergenceSchema>\n\n// 'incompatible' = compat.json rule fires definitively.\n// 'deprecated' = compat.json deprecated-api rule fires.\n// 'unknown' = engine version present but no compat rule covers it.\nexport const CompatibilityVerdictSchema = z.enum(['incompatible', 'deprecated', 'unknown'])\nexport type CompatibilityVerdict = z.infer<typeof CompatibilityVerdictSchema>\n\nexport const VersionMismatchDivergenceSchema = z.object({\n type: z.literal('version-mismatch'),\n ...commonFields,\n extractedVersion: z.string(),\n observedVersion: z.string(),\n compatibility: CompatibilityVerdictSchema,\n})\nexport type VersionMismatchDivergence = z.infer<typeof VersionMismatchDivergenceSchema>\n\nexport const HostMismatchDivergenceSchema = z.object({\n type: z.literal('host-mismatch'),\n ...commonFields,\n extractedHost: z.string(),\n observedHost: z.string(),\n})\nexport type HostMismatchDivergence = z.infer<typeof HostMismatchDivergenceSchema>\n\n// Free-shape reference to the compat.json rule that fired — kept as a plain\n// record so the schema stays insulated from compat.ts's internal types. The\n// `rule` field carries enough metadata to identify which rule + why.\nexport const CompatRuleRefSchema = z.object({\n kind: z.string(),\n reason: z.string(),\n package: z.string().optional(),\n driver: z.string().optional(),\n engine: z.string().optional(),\n})\nexport type CompatRuleRef = z.infer<typeof CompatRuleRefSchema>\n\nexport const CompatViolationDivergenceSchema = z.object({\n type: z.literal('compat-violation'),\n ...commonFields,\n rule: CompatRuleRefSchema,\n observed: GraphEdgeSchema,\n})\nexport type CompatViolationDivergence = z.infer<typeof CompatViolationDivergenceSchema>\n\nexport const DivergenceSchema = z.discriminatedUnion('type', [\n MissingObservedDivergenceSchema,\n MissingExtractedDivergenceSchema,\n VersionMismatchDivergenceSchema,\n HostMismatchDivergenceSchema,\n CompatViolationDivergenceSchema,\n])\nexport type Divergence = z.infer<typeof DivergenceSchema>\n\nexport const DivergenceResultSchema = z.object({\n divergences: z.array(DivergenceSchema),\n totalAffected: z.number().int().nonnegative(),\n // ISO8601 timestamp the result was computed at. Each call re-derives from\n // the live graph — there is no persisted divergence history.\n computedAt: z.string().datetime(),\n})\nexport type DivergenceResult = z.infer<typeof DivergenceResultSchema>\n\n// Locked set of divergence types. Consumers (REST query parser, CLI flag\n// parser) validate the user-supplied filter against this enum.\nexport const DivergenceTypeSchema = z.enum([\n 'missing-observed',\n 'missing-extracted',\n 'version-mismatch',\n 'host-mismatch',\n 'compat-violation',\n])\nexport type DivergenceType = z.infer<typeof DivergenceTypeSchema>\n","// Single source of truth for the MCP tool surface (ADR-091).\n// Adding or renaming a tool means editing this tuple; the MCP server\n// registration and the contracts audit both derive from it, so they\n// never disagree about what tools exist.\nexport const MCP_TOOL_NAMES = [\n 'get_root_cause',\n 'get_blast_radius',\n 'get_dependencies',\n 'get_observed_dependencies',\n 'get_incident_history',\n 'semantic_search',\n 'get_graph_diff',\n 'get_recent_stale_edges',\n 'check_policies',\n 'get_divergences',\n // Six /neat extend tools (ADR-081, ADR-086, #387).\n 'neat_list_uninstrumented',\n 'neat_lookup_instrumentation',\n 'neat_describe_project_instrumentation',\n 'neat_apply_extension',\n 'neat_dry_run_extension',\n 'neat_rollback_extension',\n] as const\n\nexport type MCPToolName = (typeof MCP_TOOL_NAMES)[number]\n","import { z } from 'zod'\nimport { GraphEdgeSchema } from './edges.js'\nimport { GraphNodeSchema } from './nodes.js'\nimport { ErrorEventSchema, LogEntrySchema, StaleEventSchema } from './events.js'\nimport { PolicyViolationSchema } from './policy.js'\nimport { RegistryEntrySchema } from './registry.js'\n\n// ADR-061 envelope rule: every GET response is a JSON object. List endpoints\n// wrap in plural-noun fields plus a count; single-item endpoints wrap the\n// item in a singular field. Bare arrays are a contract violation.\n\n// `count` is the length of the returned array; `total` is the size of the\n// underlying collection before filtering / limiting.\nconst listEnvelope = <T extends z.ZodTypeAny>(itemSchema: T) =>\n z.object({\n count: z.number().int().nonnegative(),\n total: z.number().int().nonnegative(),\n events: z.array(itemSchema),\n })\n\nexport const IncidentsResponseSchema = listEnvelope(ErrorEventSchema)\nexport type IncidentsResponse = z.infer<typeof IncidentsResponseSchema>\n\nexport const StaleEventsResponseSchema = listEnvelope(StaleEventSchema)\nexport type StaleEventsResponse = z.infer<typeof StaleEventsResponseSchema>\n\n// GET /logs response (docs/contracts/logs.md Rule 5, ADR-132). `total` is\n// the size of the filtered-but-unlimited collection (after source/service/\n// since filtering); `count` is the length of the returned, limit-capped\n// `logs` array.\nexport const LogsResponseSchema = z.object({\n count: z.number().int().nonnegative(),\n total: z.number().int().nonnegative(),\n logs: z.array(LogEntrySchema),\n})\nexport type LogsResponse = z.infer<typeof LogsResponseSchema>\n\nexport const PoliciesViolationsResponseSchema = z.object({\n violations: z.array(PolicyViolationSchema),\n})\nexport type PoliciesViolationsResponse = z.infer<typeof PoliciesViolationsResponseSchema>\n\nexport const GraphNodeResponseSchema = z.object({\n node: GraphNodeSchema,\n})\nexport type GraphNodeResponse = z.infer<typeof GraphNodeResponseSchema>\n\nexport const GraphEdgesResponseSchema = z.object({\n inbound: z.array(GraphEdgeSchema),\n outbound: z.array(GraphEdgeSchema),\n})\nexport type GraphEdgesResponse = z.infer<typeof GraphEdgesResponseSchema>\n\n// `.passthrough()` because the handler keeps legacy fields (uptime,\n// nodeCount, edgeCount, lastUpdated) for the web shell's StatusBar. The\n// canonical triple is what's required; the extras ride along.\nexport const HealthResponseSchema = z\n .object({\n ok: z.boolean(),\n project: z.string(),\n uptimeMs: z.number().int().nonnegative(),\n })\n .passthrough()\nexport type HealthResponse = z.infer<typeof HealthResponseSchema>\n\n// Daemon-wide /health (issue #343). Distinct from `HealthResponseSchema`\n// because the unscoped probe doesn't have a single project to report on —\n// readiness lives at the daemon level. `projects` is a flat array of every\n// slot currently loaded so a probe consumer can decide which subset to\n// poll per-project /health on.\nexport const DaemonHealthResponseSchema = z\n .object({\n ok: z.boolean(),\n uptimeMs: z.number().int().nonnegative(),\n projects: z.array(\n z.object({\n name: z.string(),\n nodeCount: z.number().int().nonnegative(),\n edgeCount: z.number().int().nonnegative(),\n }).passthrough(),\n ),\n })\n .passthrough()\nexport type DaemonHealthResponse = z.infer<typeof DaemonHealthResponseSchema>\n\nexport const SingleProjectResponseSchema = z.object({\n project: RegistryEntrySchema,\n})\nexport type SingleProjectResponse = z.infer<typeof SingleProjectResponseSchema>\n\n// GET /:project/connectors response (docs/contracts/rest-api.md, connectors.md\n// §8, ADR-136). One entry per `~/.neat/connectors.json` connector matching the\n// project, credential redacted to its env-ref pointer (never a resolved value),\n// carrying the live poll health the in-process status tracker records.\n\n// The derived poll state the endpoint reports:\n// idle — no poll tick has run yet\n// healthy — the most recent tick succeeded within the stale window\n// error — the most recent tick threw\n// stale — no successful poll within the stale window (a wedged/silent loop)\nexport const ConnectorPollStateSchema = z.enum(['idle', 'healthy', 'error', 'stale'])\nexport type ConnectorPollState = z.infer<typeof ConnectorPollStateSchema>\n\n// The per-connector live health block. `lastPollAt`/`lastOutcome`/`lastError`\n// are null until the first tick; `lastError` is null on a successful tick and a\n// short, secret-free string on a failing one (connectors.md §6 — never a\n// credential). `signalsLastPoll` is the count the last tick returned (0 before\n// any poll).\nexport const ConnectorStatusSchema = z.object({\n state: ConnectorPollStateSchema,\n lastPollAt: z.string().nullable(),\n lastOutcome: z.enum(['ok', 'error']).nullable(),\n lastError: z.string().nullable(),\n signalsLastPoll: z.number().int().nonnegative(),\n})\nexport type ConnectorStatus = z.infer<typeof ConnectorStatusSchema>\n\n// `credentialRef` is the redacted env-ref pointer — a single string\n// (`\"$CF_TOKEN\"`) for a single-field credential, or a field→pointer map for a\n// multi-field one. A plaintext literal redacts to `\"****\"`. Never a resolved\n// secret (ADR-136 §3).\nexport const ConnectorStatusEntrySchema = z.object({\n id: z.string(),\n provider: z.string(),\n credentialRef: z.union([z.string(), z.record(z.string(), z.string())]),\n status: ConnectorStatusSchema,\n})\nexport type ConnectorStatusEntry = z.infer<typeof ConnectorStatusEntrySchema>\n\nexport const ConnectorsStatusResponseSchema = z.object({\n connectors: z.array(ConnectorStatusEntrySchema),\n})\nexport type ConnectorsStatusResponse = z.infer<typeof ConnectorsStatusResponseSchema>\n\n// /search matches are graph nodes with an added per-match score. The\n// schema keeps `score` mandatory and lets the underlying node shape pass\n// through — GraphNodeSchema is a discriminated union and tightening here\n// would force every match into one variant.\nexport const SearchMatchSchema = z\n .object({ score: z.number() })\n .passthrough()\nexport type SearchMatch = z.infer<typeof SearchMatchSchema>\n\nexport const SearchResponseSchema = z.object({\n query: z.string(),\n provider: z.string(),\n matches: z.array(SearchMatchSchema),\n})\nexport type SearchResponse = z.infer<typeof SearchResponseSchema>\n\n// Live snapshot returned by GET /graph. Mirrors the in-memory graphology\n// instance; nothing reads graph.json at request time (Rule 6).\nexport const SerializedGraphSchema = z.object({\n nodes: z.array(GraphNodeSchema),\n edges: z.array(GraphEdgeSchema),\n})\nexport type SerializedGraph = z.infer<typeof SerializedGraphSchema>\n\n// GET /graph/diff response. The diff module owns the implementation;\n// the schema mirrors its current GraphDiff interface.\nexport const GraphDiffResultSchema = z.object({\n base: z.object({ exportedAt: z.string().optional() }),\n current: z.object({ exportedAt: z.string() }),\n added: z.object({\n nodes: z.array(GraphNodeSchema),\n edges: z.array(GraphEdgeSchema),\n }),\n removed: z.object({\n nodes: z.array(GraphNodeSchema),\n edges: z.array(GraphEdgeSchema),\n }),\n changed: z.object({\n nodes: z.array(\n z.object({\n id: z.string(),\n before: GraphNodeSchema,\n after: GraphNodeSchema,\n }),\n ),\n edges: z.array(\n z.object({\n id: z.string(),\n before: GraphEdgeSchema,\n after: GraphEdgeSchema,\n }),\n ),\n }),\n})\nexport type GraphDiffResult = z.infer<typeof GraphDiffResultSchema>\n","// Confidence grading helpers — single source of truth for ADR-066.\n//\n// EXTRACTED is graded at emit time per producer; OBSERVED is graded by the\n// signal block on the edge. PROV_RANK still locks tier ordering. The grading\n// sits within each tier so the divergence query can reweight against honest\n// values, not flat coarse ones.\n//\n// Producers in packages/core/src/extract/ import `confidenceForExtracted`\n// and pass the producer kind; ingest.ts imports `confidenceForObservedSignal`\n// and calls it at the same point it writes the signal block.\n\nimport type { EdgeSignal } from './edges.js'\n\n// Discriminator that producers pass when emitting an EXTRACTED edge. Each\n// kind maps to a numeric grade; the divergence query treats sub-floor\n// candidates as if they never existed (precision floor, NEAT_EXTRACTED_PRECISION_FLOOR).\nexport type ExtractedConfidenceKind =\n // 0.85 — direct AST / file facts. ConfigNode existence (ADR-016), package.json\n // deps, AST imports, Dockerfile RUNS_ON, docker-compose depends_on, parsed\n // database config files. Structural — what the code says it does.\n | 'structural'\n // 0.85 — framework-aware call-site recognizer matched the SDK shape. Today's\n // covers kafkajs producer.send / consumer.subscribe, AWS SDK Bucket/TableName\n // near a *Client, grpc-js Client construction with the import context,\n // import-aware *Client classification (#238), and @supabase/supabase-js /\n // @supabase/ssr createClient construction with the import in scope (#482).\n // Also covers a matched HTTP client↔route contract (ADR-119): a recognised\n // fetch / axios / node-http client call site whose (host, method, path-\n // template) resolves to a server route NEAT extracted from a mainstream\n // router. Both endpoints are recognised — a framework-aware client shape on\n // one side, a parsed route definition on the other — so the cross-service\n // CALLS edge lands at this tier rather than the looser url-literal grade.\n | 'verified-call-site'\n // 0.5 — URL-shaped literal with structural support. Today's `redis://host` /\n // `rediss://host` URL captures fit here: the scheme proves it's a redis URL,\n // but there's no call expression verifying it's actually wired into the\n // service's runtime path.\n | 'url-with-structural-support'\n // 0.7 — a scheme-qualified URL literal (http://service-c:3102, //service-c/x)\n // whose hostname resolves to a *registered* service. This is a declared HTTP\n // dependency: the source names another in-mesh service's URL. urlMatchesHost\n // requires scheme + exact hostname (+ exact port when present) and the target\n // is a known node, so it lands at the precision floor rather than below it —\n // missing-observed needs a floor-level EXTRACTED edge to measure a declared-\n // but-never-driven upstream (issue #592). Below structural/verified (no call\n // expression wraps the literal); above url-with-structural-support (a resolved\n // registered target is tighter than a bare scheme read).\n | 'url-literal-service-target'\n // 0.2 — bare URL/hostname match against a registered service with no scheme\n // to anchor it. Structurally loose and unconfirmed by any recognizer; drops\n // below the default precision floor (0.7) and never enters the graph unless\n // the floor is lowered for diagnostics.\n | 'hostname-shape-match'\n\nexport const EXTRACTED_CONFIDENCE: Record<ExtractedConfidenceKind, number> = {\n structural: 0.85,\n 'verified-call-site': 0.85,\n 'url-literal-service-target': 0.7,\n 'url-with-structural-support': 0.5,\n 'hostname-shape-match': 0.2,\n}\n\nexport function confidenceForExtracted(kind: ExtractedConfidenceKind): number {\n return EXTRACTED_CONFIDENCE[kind]\n}\n\n// OBSERVED grading from the signal block (ADR-066 §2). The piecewise function\n// reflects the three buckets the ADR locks plus the error-ratio adjustment.\n// `lastObservedAgeMs` defaults to 0 (just-observed) when the caller doesn't\n// pass a signal — upsertObservedEdge writes 0 on creation and on every span\n// update; the staleness loop is the only thing that lets the age drift.\n\nconst STRONG_SPAN_THRESHOLD = 100\nconst GOOD_SPAN_THRESHOLD = 10\nconst RECENT_AGE_MS = 60 * 60 * 1000\n\nexport function confidenceForObservedSignal(signal: EdgeSignal | undefined): number {\n // No signal block — fall back to the strong-tier ceiling. This case is\n // legacy edges loaded from a pre-v0.3.4 snapshot or hand-written test\n // fixtures; new producers always write the signal block.\n if (!signal) return 1.0\n const { spanCount, errorCount } = signal\n const ageMs = signal.lastObservedAgeMs ?? 0\n const recent = ageMs < RECENT_AGE_MS\n\n let base: number\n if (spanCount >= STRONG_SPAN_THRESHOLD && recent) {\n // Strong tier. Scale linearly from 0.95 at the threshold up to 1.0 at\n // 10× the threshold. Saturates at 1.0 above that.\n const over = Math.min(1, (spanCount - STRONG_SPAN_THRESHOLD) / (9 * STRONG_SPAN_THRESHOLD))\n base = 0.95 + 0.05 * over\n } else if (spanCount >= GOOD_SPAN_THRESHOLD && recent) {\n // Good tier. 0.7 at the threshold up to 0.9 just below the strong tier.\n const range = STRONG_SPAN_THRESHOLD - GOOD_SPAN_THRESHOLD\n const over = (spanCount - GOOD_SPAN_THRESHOLD) / range\n base = 0.7 + 0.2 * over\n } else if (spanCount > 0 && recent) {\n // Weak tier. 0.4 at one span up to 0.6 just below the good tier.\n const range = GOOD_SPAN_THRESHOLD - 1\n const over = range > 0 ? (spanCount - 1) / range : 0\n base = 0.4 + 0.2 * over\n } else if (spanCount > 0) {\n // Not recent — clamp the weak tier; staleness loop will demote this edge\n // to STALE on the next tick.\n base = 0.4\n } else {\n // Defensive: no spans on an OBSERVED edge means the upsert path was\n // skipped somewhere. Treat as no-evidence rather than max-trust.\n base = 0.4\n }\n\n // Error-ratio penalty. errorCount / spanCount on a healthy edge is 0; on a\n // failing edge it climbs. Subtract up to 0.2.\n if (spanCount > 0 && errorCount > 0) {\n const ratio = Math.min(1, errorCount / spanCount)\n base -= 0.2 * ratio\n }\n\n if (base < 0) return 0\n if (base > 1) return 1\n return Math.round(base * 1000) / 1000\n}\n\n// Precision-floor helpers (ADR-066 §3). The floor reads the\n// NEAT_EXTRACTED_PRECISION_FLOOR env var on each call so tests can flip it\n// in-process. Default 0.7. NEAT_EXTRACTED_PRECISION_FLOOR=0.0 keeps every\n// candidate (diagnostic mode).\n\nexport const DEFAULT_EXTRACTED_PRECISION_FLOOR = 0.7\n\nexport function extractedPrecisionFloor(): number {\n const raw = process.env.NEAT_EXTRACTED_PRECISION_FLOOR\n if (raw === undefined) return DEFAULT_EXTRACTED_PRECISION_FLOOR\n const n = Number(raw)\n if (!Number.isFinite(n) || n < 0 || n > 1) return DEFAULT_EXTRACTED_PRECISION_FLOOR\n return n\n}\n\nexport function passesExtractedFloor(confidence: number): boolean {\n return confidence >= extractedPrecisionFloor()\n}\n"],"mappings":"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","names":["import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod"]}