Story navigation and details

Source-grounded

Thirteen private @topo/* runtime modules bundled by @jdylanmc/topo-code. Arrows are selected direct dependencies from package manifests, arranged as a readable composition spine, not a complete edge drawing or runtime call graph. Select a module for every declared incoming/outgoing internal dependency and its responsibility. Build-only eslint-config is excluded from this view; tooling and external context live in the companion map.

  • @topo/story Open Source-anchor resolution and freshnessOpen Dependency context by role: Code analysisOpen Dependency context by role: Language parsingOpen Dependency context by role: Schema contractsOpen Dependency context by role: JSON validationOpen Dependency context by role: Build, test, docsOpen Dependency context by role: Development toolsOpen @topo/diagram-core: public surface: @topo/story

    Parses authored stories and resolves file/symbol/excerpt anchors against a source snapshot. Defines the renderer-neutral story contract. All declared internal dependencies (not runtime calls): @topo/story -> @topo/languages [dependencies: workspace:*] Referenced by internal modules: @topo/cli -> @topo/story [dependencies: workspace:*] @topo/diagram-core -> @topo/story [dependencies: workspace:*] Stable drilldown identity: story. Open the source-backed sequence for this module's core algorithm.

    packages/story/package.json:1-33
    {
      "name": "@topo/story",
      "version": "0.0.0",
      "private": true,
      "type": "module",
      "files": [
        "dist",
        "story.schema.json"
      ],
      "exports": {
        ".": {
          "types": "./dist/index.d.ts",
          "default": "./dist/index.js"
        },
        "./story.schema.json": "./story.schema.json"
      },
      "scripts": {
        "build": "tsc -b",
        "typecheck": "tsc -b --pretty false",
        "test": "vitest run"
      },
      "dependencies": {
        "@topo/languages": "workspace:*",
        "typescript-compiler-api": "npm:typescript@6.0.3"
      },
      "devDependencies": {
        "@types/node": "^22",
        "ajv": "8.17.1",
        "typescript": "^7.0.2",
        "vite": "8.2.2",
        "vitest": "^5.0.0"
      }
    }
    
    packages/story/src/index.ts:1-604
    import { constants } from "node:fs";
    import { open, realpath, stat } from "node:fs/promises";
    import { isAbsolute, relative, resolve, sep } from "node:path";
    import ts from "typescript-compiler-api";
    import { createHash } from "node:crypto";
    import { resolveRustSymbol } from "@topo/languages";
    
    export interface SourceAnchor {
      readonly id: string;
      readonly path: string;
      readonly symbol?: string;
      readonly pattern?: string;
      readonly language?: "typescript" | "javascript" | "rust" | "text";
      readonly sha256?: string;
    }
    
    export interface StoryTarget {
      readonly storyId: string;
      readonly nodeId?: string;
    }
    
    export interface StorySection {
      readonly id: string;
      readonly title: string;
      readonly body: string;
      readonly summary?: string;
      readonly semanticRole?: string;
      readonly drilldown?: StoryTarget;
      readonly anchorIds: readonly string[];
      readonly kind?: "step" | "decision" | "data";
    }
    
    export interface StoryConnection {
      readonly from: string;
      readonly to: string;
      readonly label?: string;
      readonly variant?: "return";
      readonly classification?: "source-traced" | "inferred";
      readonly anchorIds?: readonly string[];
      readonly rationale?: string;
    }
    
    export type DiagramFamily =
      | "architecture"
      | "workflow"
      | "sequence"
      | "dataflow"
      | "lifecycle";
    
    export type StoryClassification = "source-grounded" | "capability-demo";
    
    export interface StoryDocument {
      readonly schemaVersion: "1.0";
      readonly diagramFamily?: DiagramFamily;
      readonly classification?: StoryClassification;
      readonly renderer?: "archify" | "graphviz";
      readonly id: string;
      readonly title: string;
      readonly summary: string;
      readonly category?: string;
      readonly parent?: StoryTarget & { readonly nodeId: string };
      readonly sequenceLayout?: { readonly minimumParticipantGap: number };
      readonly anchors: readonly SourceAnchor[];
      readonly sections: readonly StorySection[];
      readonly connections: readonly StoryConnection[];
    }
    
    export interface ResolvedSourceAnchor extends SourceAnchor {
      readonly location: {
        readonly startLine: number;
        readonly endLine: number;
      };
      readonly excerpt: string;
    }
    
    export interface ResolvedStoryDocument {
      readonly document: StoryDocument;
      readonly documentPath: string;
      readonly repositoryRoot: string;
      readonly source: {
        readonly revision: string;
        readonly dirty: boolean;
      };
      readonly anchors: readonly ResolvedSourceAnchor[];
    }
    
    export interface StoryArtifact {
      readonly kind: "html";
      readonly mediaType: "text/html";
      readonly contents: string;
      readonly assets?: Readonly<Record<string, string>>;
      readonly renderer: {
        readonly name: string;
        readonly pin: string;
        readonly sha256?: string;
        readonly sourceOutputSha256?: string;
        readonly outputSha256?: string;
        readonly adaptation?: string;
      };
    }
    
    export interface StoryRenderer {
      render(story: ResolvedStoryDocument): StoryArtifact | Promise<StoryArtifact>;
    }
    
    export class StoryDocumentError extends Error {
      constructor(
        readonly documentPath: string,
        readonly anchorId: string | undefined,
        readonly code: string,
        message: string,
      ) {
        super(
          `${documentPath}${anchorId ? ` anchor "${anchorId}"` : ""} [${code}]: ${message}`,
        );
        this.name = "StoryDocumentError";
      }
    }
    
    export function parseStoryDocument(
      serialized: string,
      documentPath: string,
    ): StoryDocument {
      let value: unknown;
      try {
        value = JSON.parse(serialized) as unknown;
      } catch {
        throw invalidDocument(documentPath, "invalid JSON");
      }
      assertStoryDocument(value, documentPath);
      return value;
    }
    
    export function assertStoryDocument(
      value: unknown,
      documentPath = "<story>",
    ): asserts value is StoryDocument {
      const issue = validateStoryDocument(value);
      if (issue !== undefined) {
        throw invalidDocument(documentPath, issue);
      }
    }
    
    export async function resolveStoryDocument(
      root: string,
      document: StoryDocument,
      documentPath: string,
      source: { revision: string; dirty: boolean },
      loadSource?: (path: string) => Promise<string | undefined>,
    ): Promise<ResolvedStoryDocument> {
      const repositoryRoot =
        loadSource === undefined ? await realpath(root) : resolve(root);
      const anchors: ResolvedSourceAnchor[] = [];
      for (const anchor of document.anchors) {
        assertRepositoryPath(root, documentPath, anchor);
        const contents = loadSource === undefined
          ? await readRepositorySource(repositoryRoot, documentPath, anchor)
          : await loadSource(anchor.path);
        if (contents === undefined) {
          throw anchorError(
            documentPath,
            anchor.id,
            "missing-file",
            `source file "${anchor.path}" does not exist`,
          );
        }
        anchors.push(await resolveAnchor(documentPath, anchor, contents));
      }
      return { document, documentPath, repositoryRoot, source, anchors };
    }
    
    function invalidDocument(documentPath: string, message: string): StoryDocumentError {
      return new StoryDocumentError(
        documentPath,
        undefined,
        "invalid-document",
        `invalid story document: ${message}`,
      );
    }
    
    function anchorError(
      documentPath: string,
      anchorId: string,
      code: string,
      message: string,
    ): StoryDocumentError {
      return new StoryDocumentError(documentPath, anchorId, code, message);
    }
    
    function isRecord(value: unknown): value is Record<string, unknown> {
      return typeof value === "object" && value !== null && !Array.isArray(value);
    }
    
    function exactKeys(
      value: Record<string, unknown>,
      required: readonly string[],
      optional: readonly string[] = [],
    ): string | undefined {
      for (const key of required) {
        if (!(key in value)) return `missing "${key}"`;
      }
      const allowed = new Set([...required, ...optional]);
      const extra = Object.keys(value).find((key) => !allowed.has(key));
      return extra === undefined ? undefined : `unexpected "${extra}"`;
    }
    
    function nonemptyString(value: unknown): value is string {
      return typeof value === "string" && value.length > 0;
    }
    
    function uniqueStrings(value: unknown): value is string[] {
      return Array.isArray(value) &&
        value.every(nonemptyString) &&
        new Set(value).size === value.length;
    }
    
    function validateStoryTarget(value: unknown, requireNode: boolean): string | undefined {
      if (!isRecord(value)) return "must be an object";
      const keys = exactKeys(value, requireNode ? ["storyId", "nodeId"] : ["storyId"], requireNode ? [] : ["nodeId"]);
      if (keys) return keys;
      if (typeof value.storyId !== "string" || !/^[a-z0-9][a-z0-9-]*$/.test(value.storyId)) {
        return "storyId must be a valid story id";
      }
      if (value.nodeId !== undefined && !nonemptyString(value.nodeId)) return "nodeId must be nonempty";
      return undefined;
    }
    
    function validateStoryDocument(value: unknown): string | undefined {
      if (!isRecord(value)) return "root must be an object";
      const rootKeys = exactKeys(
        value,
        ["schemaVersion", "id", "title", "summary", "anchors", "sections", "connections"],
        ["category", "diagramFamily", "classification", "renderer", "parent", "sequenceLayout"],
      );
      if (rootKeys) return rootKeys;
      if (value.schemaVersion !== "1.0") return 'schemaVersion must be "1.0"';
      if (value.renderer !== undefined && value.renderer !== "archify" && value.renderer !== "graphviz") return "renderer must be archify or graphviz";
      if (value.renderer === "graphviz" && value.diagramFamily !== "workflow") return "graphviz requires diagramFamily workflow";
      if (
        value.diagramFamily !== undefined &&
        !["architecture", "workflow", "sequence", "dataflow", "lifecycle"]
          .includes(String(value.diagramFamily))
      ) {
        return "diagramFamily must be a supported native family";
      }
      if (
        value.classification !== undefined &&
        value.classification !== "source-grounded" &&
        value.classification !== "capability-demo"
      ) {
        return "classification must be source-grounded or capability-demo";
      }
      if (!nonemptyString(value.id) || !/^[a-z0-9][a-z0-9-]*$/.test(value.id)) {
        return "id must use lowercase letters, digits, and hyphens";
      }
      if (!nonemptyString(value.title)) return "title must be nonempty";
      if (!nonemptyString(value.summary)) return "summary must be nonempty";
      if (value.sequenceLayout !== undefined) {
        if (value.diagramFamily !== "sequence" || !isRecord(value.sequenceLayout)) {
          return "sequenceLayout requires a sequence diagram and an object";
        }
        const keys = exactKeys(value.sequenceLayout, ["minimumParticipantGap"], []);
        if (keys) return `sequenceLayout ${keys}`;
        const gap = value.sequenceLayout.minimumParticipantGap;
        if (typeof gap !== "number" || !Number.isSafeInteger(gap) || gap < 108) {
          return "sequenceLayout.minimumParticipantGap must be an integer of at least 108 SVG units";
        }
      }
      if (value.parent !== undefined) {
        const error = validateStoryTarget(value.parent, true);
        if (error) return `parent ${error}`;
      }
      if (
        value.category !== undefined &&
        (!nonemptyString(value.category) || value.category.trim().length === 0)
      ) {
        return "category must be nonempty";
      }
      if (!Array.isArray(value.anchors)) return "anchors must be an array";
      if (!Array.isArray(value.sections) || value.sections.length === 0) {
        return "sections must be a nonempty array";
      }
      if (!Array.isArray(value.connections)) return "connections must be an array";
      const diagramFamily = value.diagramFamily ?? "architecture";
      const sourceGrounded = value.classification !== "capability-demo";
      if (sourceGrounded && value.anchors.length === 0) {
        return "source-grounded stories must define at least one anchor";
      }
    
      const anchorIds = new Set<string>();
      for (const [index, anchorValue] of value.anchors.entries()) {
        if (!isRecord(anchorValue)) return `anchors[${index}] must be an object`;
        const keys = exactKeys(anchorValue, ["id", "path"], ["symbol", "pattern", "language", "sha256"]);
        if (keys) return `anchors[${index}] ${keys}`;
        if (!nonemptyString(anchorValue.id)) return `anchors[${index}].id must be nonempty`;
        if (anchorIds.has(anchorValue.id)) return `duplicate anchor id "${anchorValue.id}"`;
        anchorIds.add(anchorValue.id);
        if (!nonemptyString(anchorValue.path)) return `anchors[${index}].path must be nonempty`;
        if (anchorValue.language !== undefined && !["typescript", "javascript", "rust", "text"].includes(String(anchorValue.language))) return `anchors[${index}].language is unsupported`;
        if (anchorValue.sha256 !== undefined && (typeof anchorValue.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(anchorValue.sha256))) return `anchors[${index}].sha256 must be a SHA-256 file digest`;
        if (value.renderer === "graphviz" && anchorValue.sha256 === undefined) return `technical anchors[${index}] require sha256 for stale-source rejection`;
        if (anchorValue.symbol !== undefined && !nonemptyString(anchorValue.symbol)) {
          return `anchors[${index}].symbol must be nonempty`;
        }
        if (anchorValue.pattern !== undefined) {
          if (!nonemptyString(anchorValue.pattern)) {
            return `anchors[${index}].pattern must be nonempty`;
          }
        }
      }
    
      const sectionIds = new Set<string>();
      for (const [index, sectionValue] of value.sections.entries()) {
        if (!isRecord(sectionValue)) return `sections[${index}] must be an object`;
        const keys = exactKeys(sectionValue, ["id", "title", "body", "anchorIds"], ["kind", "summary", "semanticRole", "drilldown"]);
        if (keys) return `sections[${index}] ${keys}`;
        if (sectionValue.kind !== undefined && (!["step", "decision", "data"].includes(String(sectionValue.kind)) || value.renderer !== "graphviz")) return `sections[${index}].kind requires the explicit graphviz backend`;
        if (!nonemptyString(sectionValue.id)) return `sections[${index}].id must be nonempty`;
        if (sectionIds.has(sectionValue.id)) return `duplicate section id "${sectionValue.id}"`;
        sectionIds.add(sectionValue.id);
        if (!nonemptyString(sectionValue.title)) return `sections[${index}].title must be nonempty`;
        if (!nonemptyString(sectionValue.body)) return `sections[${index}].body must be nonempty`;
        if (sectionValue.drilldown !== undefined) {
          const error = validateStoryTarget(sectionValue.drilldown, false);
          if (error) return `sections[${index}].drilldown ${error}`;
        }
        if (sectionValue.summary !== undefined &&
            (!nonemptyString(sectionValue.summary) || diagramFamily !== "architecture")) {
          return `sections[${index}].summary requires a nonempty architecture caption`;
        }
        if (sectionValue.semanticRole !== undefined &&
            (typeof sectionValue.semanticRole !== "string" ||
              !/^(?!constructor$)[a-z][a-z0-9-]{0,63}$/.test(sectionValue.semanticRole) ||
              (diagramFamily !== "architecture" && diagramFamily !== "sequence"))) {
          return `sections[${index}].semanticRole requires an architecture or sequence role slug`;
        }
        if (!uniqueStrings(sectionValue.anchorIds)) {
          return `sections[${index}].anchorIds must contain unique nonempty strings`;
        }
        if (sourceGrounded && sectionValue.anchorIds.length === 0) {
          return `sections[${index}].anchorIds must reference source evidence`;
        }
        const missingAnchor = sectionValue.anchorIds.find((id) => !anchorIds.has(id));
        if (missingAnchor) return `sections[${index}] references unknown anchor "${missingAnchor}"`;
      }
    
      for (const [index, connectionValue] of value.connections.entries()) {
        if (!isRecord(connectionValue)) return `connections[${index}] must be an object`;
        const keys = exactKeys(connectionValue, ["from", "to"], ["label", "variant", "classification", "anchorIds", "rationale"]);
        if (keys) return `connections[${index}] ${keys}`;
        if (!nonemptyString(connectionValue.from) || !sectionIds.has(connectionValue.from)) {
          return `connections[${index}].from must reference a section`;
        }
        if (!nonemptyString(connectionValue.to) || !sectionIds.has(connectionValue.to)) {
          return `connections[${index}].to must reference a section`;
        }
        if (connectionValue.label !== undefined && !nonemptyString(connectionValue.label)) {
          return `connections[${index}].label must be nonempty`;
        }
        if (value.renderer === "graphviz" && connectionValue.classification === undefined) return `technical connections[${index}] require an explicit classification`;
        if (connectionValue.classification !== undefined) {
          if (!["source-traced", "inferred"].includes(String(connectionValue.classification))) return `connections[${index}].classification must be source-traced or inferred; authored traces are not scanner-derived facts`;
          if (!nonemptyString(connectionValue.rationale)) return `connections[${index}] require a rationale`;
          if (!uniqueStrings(connectionValue.anchorIds) || connectionValue.anchorIds.some((id) => !anchorIds.has(id))) return `connections[${index}] require valid anchorIds`;
          if (connectionValue.classification === "source-traced" && connectionValue.anchorIds.length === 0) return `source-traced connections[${index}] require exact source evidence`;
          for (const anchorId of connectionValue.anchorIds) {
            if (!value.anchors.some((anchor) => isRecord(anchor) && anchor.id === anchorId && typeof anchor.sha256 === "string")) return `connections[${index}] require snapshot-bound anchors`;
          }
        } else if (connectionValue.anchorIds !== undefined || connectionValue.rationale !== undefined) {
          return `connections[${index}] evidence requires classification`;
        }
        if (
          connectionValue.variant !== undefined &&
          connectionValue.variant !== "return"
        ) {
          return `connections[${index}].variant must be "return"`;
        }
        if (
          connectionValue.variant === "return" &&
          diagramFamily !== "sequence"
        ) {
          return `connections[${index}] return variant is only supported for sequence stories`;
        }
        if (
          (diagramFamily === "sequence" || diagramFamily === "dataflow") &&
          connectionValue.label === undefined
        ) {
          return `${diagramFamily} connections[${index}].label is required`;
        }
      }
      return undefined;
    }
    
    function assertRepositoryPath(
      root: string,
      documentPath: string,
      anchor: SourceAnchor,
    ): void {
      const absolute = resolve(root, anchor.path);
      const rel = relative(root, absolute);
      if (
        isAbsolute(anchor.path) ||
        rel === ".." ||
        rel.startsWith(`..${sep}`) ||
        isAbsolute(rel)
      ) {
        throw anchorError(
          documentPath,
          anchor.id,
          "invalid-path",
          `source path "${anchor.path}" escapes the repository`,
        );
      }
    }
    
    async function readRepositorySource(
      repositoryRoot: string,
      documentPath: string,
      anchor: SourceAnchor,
    ): Promise<string | undefined> {
      const requested = resolve(repositoryRoot, anchor.path);
      let actual: string;
      try {
        actual = await realpath(requested);
      } catch (error) {
        if (
          error instanceof Error &&
          "code" in error &&
          error.code === "ENOENT"
        ) {
          return undefined;
        }
        throw error;
      }
      if (actual !== requested) {
        throw anchorError(
          documentPath,
          anchor.id,
          "invalid-path",
          `source path "${anchor.path}" must not resolve through a symlink`,
        );
      }
      const rel = relative(repositoryRoot, actual);
      if (rel === ".." || rel.startsWith(`..${sep}`) || isAbsolute(rel)) {
        throw anchorError(
          documentPath,
          anchor.id,
          "invalid-path",
          `source path "${anchor.path}" must be a regular file inside the repository`,
        );
      }
      const initial = await stat(requested);
      if (!initial.isFile()) {
        throw anchorError(
          documentPath,
          anchor.id,
          "invalid-path",
          `source path "${anchor.path}" must be a regular file inside the repository`,
        );
      }
      const handle = await open(
        requested,
        constants.O_RDONLY | constants.O_NOFOLLOW,
      );
      try {
        const opened = await handle.stat();
        if (
          !opened.isFile() ||
          opened.dev !== initial.dev ||
          opened.ino !== initial.ino
        ) {
          throw anchorError(
            documentPath,
            anchor.id,
            "invalid-path",
            `source path "${anchor.path}" changed before it was read`,
          );
        }
        const contents = await handle.readFile("utf8");
        const openedAfter = await handle.stat();
        const currentActual = await realpath(requested);
        const current = await stat(requested);
        if (
          currentActual !== requested ||
          !current.isFile() ||
          current.dev !== opened.dev ||
          current.ino !== opened.ino ||
          openedAfter.size !== opened.size ||
          openedAfter.mtimeMs !== opened.mtimeMs ||
          openedAfter.ctimeMs !== opened.ctimeMs
        ) {
          throw anchorError(
            documentPath,
            anchor.id,
            "invalid-path",
            `source path "${anchor.path}" changed while it was being read`,
          );
        }
        return contents;
      } finally {
        await handle.close();
      }
    }
    
    function declarationName(node: ts.Node): string | undefined {
      if (!("name" in node)) return undefined;
      const name = (node as ts.NamedDeclaration).name;
      return name && ts.isIdentifier(name) ? name.text : undefined;
    }
    
    function findSymbolRange(
      sourceFile: ts.SourceFile,
      symbol: string,
    ): { start: number; end: number } | undefined {
      let result: ts.Node | undefined;
      const visit = (node: ts.Node): void => {
        if (result !== undefined) return;
        if (declarationName(node) === symbol) {
          result = node;
          return;
        }
        ts.forEachChild(node, visit);
      };
      visit(sourceFile);
      return result === undefined
        ? undefined
        : {
          start: result.getStart(sourceFile),
          end: result.getEnd(),
        };
    }
    
    async function resolveAnchor(
      documentPath: string,
      anchor: SourceAnchor,
      contents: string,
    ): Promise<ResolvedSourceAnchor> {
      if (anchor.sha256 !== undefined && createHash("sha256").update(contents).digest("hex") !== anchor.sha256) {
        throw anchorError(documentPath, anchor.id, "stale-source", `source "${anchor.path}" changed; inspect the change and deliberately update its digest, preserving anchor identity`);
      }
      const sourceFile = ts.createSourceFile(
        anchor.path,
        contents,
        ts.ScriptTarget.Latest,
        true,
      );
      let start = 0;
      let end = contents.length;
      if (anchor.symbol !== undefined) {
        const language = anchor.language ?? (anchor.path.endsWith(".rs") ? "rust" : "typescript");
        if (language === "text") throw anchorError(documentPath, anchor.id, "unsupported-symbol", "text anchors support exact patterns, not compiler symbols");
        const rust = language === "rust" ? await resolveRustSymbol(anchor.path, contents, anchor.symbol) : undefined;
        const symbol = rust === undefined ? findSymbolRange(sourceFile, anchor.symbol) : {
          start: sourceFile.getPositionOfLineAndCharacter(rust.startLine - 1, rust.startColumn - 1),
          end: sourceFile.getPositionOfLineAndCharacter(rust.endLine - 1, rust.endColumn - 1),
        };
        if (symbol === undefined) {
          throw anchorError(
            documentPath,
            anchor.id,
            "missing-symbol",
            `symbol "${anchor.symbol}" was not found in "${anchor.path}"`,
          );
        }
        start = symbol.start;
        end = symbol.end;
      }
      if (anchor.pattern !== undefined) {
        const scope = contents.slice(start, end);
        const offset = scope.indexOf(anchor.pattern);
        if (offset < 0) {
          throw anchorError(
            documentPath,
            anchor.id,
            "missing-pattern",
            anchor.symbol === undefined
              ? `pattern "${anchor.pattern}" was not found in "${anchor.path}"`
              : `pattern "${anchor.pattern}" was not found within symbol "${anchor.symbol}" in "${anchor.path}"`,
          );
        }
        if (
          anchor.symbol === undefined &&
          scope.indexOf(anchor.pattern, offset + 1) >= 0
        ) {
          throw anchorError(
            documentPath,
            anchor.id,
            "ambiguous-pattern",
            `pattern "${anchor.pattern}" occurs more than once in "${anchor.path}"`,
          );
        }
        start += offset;
        end = start + anchor.pattern.length;
      }
      const startLine = sourceFile.getLineAndCharacterOfPosition(start).line + 1;
      const endLine = sourceFile.getLineAndCharacterOfPosition(
        Math.max(start, end - 1),
      ).line + 1;
      return {
        ...anchor,
        location: { startLine, endLine },
        excerpt: contents.slice(start, end),
      };
    }
    
  • @topo/languages Open Dependency context by role: Code analysisOpen Dependency context by role: Language parsingOpen Dependency context by role: Build, test, docsOpen Dependency context by role: Development tools

    Selects the first-party TypeScript/JavaScript scanner, partial Rust adapter, and Tauri bridge. Owns captured source inventory and language evidence; never runs a model or Cargo build. All declared internal dependencies (not runtime calls): @topo/languages -> @topo/scanner [dependencies: workspace:*] @topo/languages -> @topo/schema [dependencies: workspace:*] Referenced by internal modules: @topo/story -> @topo/languages [dependencies: workspace:*] @topo/cli -> @topo/languages [dependencies: workspace:*] Stable drilldown identity: languages. Module-specific detail maps will be curated later; there is no placeholder target.

    packages/languages/package.json:1-31
    {
      "name": "@topo/languages",
      "version": "0.0.0",
      "private": true,
      "type": "module",
      "exports": {
        ".": {
          "types": "./dist/index.d.ts",
          "default": "./dist/index.js"
        }
      },
      "scripts": {
        "build": "tsc -b",
        "typecheck": "tsc -b --pretty false",
        "test": "node --test test/*.test.mjs"
      },
      "dependencies": {
        "@topo/scanner": "workspace:*",
        "@topo/schema": "workspace:*",
        "typescript-compiler-api": "npm:typescript@6.0.3"
      },
      "optionalDependencies": {
        "@ast-grep/lang-rust": "0.0.7",
        "@ast-grep/napi": "0.45.3",
        "@iarna/toml": "2.2.5"
      },
      "devDependencies": {
        "@types/node": "^22",
        "typescript": "^7.0.2"
      }
    }
    
    packages/languages/src/index.ts:1-306
    import { basename } from "node:path";
    import type { ScanRepositoryOptions, ScanResult } from "@topo/scanner";
    import {
      assertGraphDocument, createGraphDocument, createPathNodeId,
      type GraphDocument, type JsonValue, type LogicalArchitectureDocument, type SourceLocation as GraphLocation,
    } from "@topo/schema";
    import type { Contribution, Entity, Relationship, ScanContext, SourceLocation } from "./contract-types.js";
    import { assertInventoryCurrent, captureInventory } from "./inventory.mjs";
    import { factId, hash, serialize } from "./contract.mjs";
    
    export type { Contribution, Entity, Relationship, ScanContext, SourceLocation } from "./contract-types.js";
    export { RUST_DECLARATION_KINDS } from "./contract.mjs";
    export const LANGUAGE_EVIDENCE_KEY = "dev.topo.languages";
    export interface PluginSelection {
      languages: readonly ("typescript" | "rust")[];
      frameworks: readonly "tauri"[];
    }
    export interface PluginManifest {
      readonly id: string;
      readonly kind: "language" | "framework";
      readonly contractVersion: "1.0";
      readonly requires: readonly string[];
    }
    export const FIRST_PARTY_PLUGINS: readonly PluginManifest[] = [
      { id: "typescript", kind: "language", contractVersion: "1.0", requires: [] },
      { id: "rust", kind: "language", contractVersion: "1.0", requires: [] },
      { id: "tauri", kind: "framework", contractVersion: "1.0", requires: ["typescript", "rust"] },
    ];
    export interface LanguageEvidence {
      schemaVersion: "1.0";
      source: { sha256: string; files: { path: string; sha256: string; language: string }[] };
      contributions: Contribution[];
    }
    
    export function validateSelection(selection: PluginSelection): void {
      if (!selection.languages.length) throw new Error("Select at least one first-party language");
      const selected = [...selection.languages, ...selection.frameworks];
      if (new Set(selected).size !== selected.length) throw new Error("Duplicate selected adapter");
      for (const [kind, ids] of [["language", selection.languages], ["framework", selection.frameworks]] as const) {
        for (const id of ids) {
          const plugin = FIRST_PARTY_PLUGINS.find((candidate) => candidate.id === id && candidate.kind === kind);
          if (!plugin) throw new Error(`Unknown ${kind} adapter: ${id}`);
          for (const required of plugin.requires) {
            if (!selected.some((id) => id === required)) {
              throw new Error(`${id} requires explicitly selected ${required}`);
            }
          }
        }
      }
    }
    
    export async function rustContribution(context: ScanContext): Promise<Contribution> {
      let adapter: typeof import("./plugins/rust.mjs");
      try {
        adapter = await import("./plugins/rust.mjs");
      } catch (error) {
        throw new Error(
          "Rust adapter unavailable. Install optional @ast-grep/napi@0.45.3, @ast-grep/lang-rust@0.0.7 and @iarna/toml@2.2.5 with compatible native prebuilds. No compiler/install hook is run by topo; select only typescript to operate without Rust.",
          { cause: error },
        );
      }
      return adapter.scanRust(context);
    }
    
    function graphLocation(value: SourceLocation): GraphLocation {
      return {
        path: value.path, start: { line: value.startLine, column: value.startColumn },
        end: { line: value.endLine, column: value.endColumn },
      };
    }
    
    function factLocation(value: GraphLocation): SourceLocation {
      return {
        path: value.path, startLine: value.start.line, startColumn: value.start.column,
        endLine: value.end?.line ?? value.start.line, endColumn: value.end?.column ?? value.start.column,
      };
    }
    
    function json(value: unknown): JsonValue {
      if (value === null || typeof value === "string" || typeof value === "boolean") return value;
      if (typeof value === "number" && Number.isFinite(value)) return value;
      if (Array.isArray(value)) return value.map(json);
      if (typeof value === "object" && value !== null && Object.getPrototypeOf(value) === Object.prototype) {
        return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, json(child)]));
      }
      throw new Error("Adapter evidence must contain only finite JSON values");
    }
    
    function typescriptContribution(result: ScanResult): Contribution {
      return {
        plugin: { id: "typescript", kind: "language", version: "1.0",
          languages: ["typescript", "javascript"], capabilities: ["compiler-declarations", "static-references"] },
        entities: result.logicalArchitecture.entities.map((entity) => {
          const location = entity.declarations[0];
          if (!location) throw new Error(`TypeScript declaration has no source: ${entity.id}`);
          return { id: entity.id, language: /\.[cm]?jsx?$/.test(location.path) ? "javascript" : "typescript",
            kind: entity.kind, name: entity.name, qualifiedName: `${location.path}::${entity.name}`,
            location: factLocation(location), exported: entity.exported, signatures: entity.signatures, attributes: [] };
        }),
        relationships: result.logicalArchitecture.relationships.map((edge) => ({
          id: edge.id, from: edge.sourceId, to: edge.targetId, kind: edge.kind,
          method: "typescript-compiler-static-reference", evidence: edge.locations.map(factLocation),
        })),
        unresolved: [],
        diagnostics: result.diagnostics,
        coverage: {
          status: result.authoritative ? "complete" : "partial",
          analyzedFiles: result.graph.nodes.filter((node) => node.identity.kind === "path").map((node) => node.identity.value),
          limitations: ["Static TypeScript/JavaScript references are not runtime reachability or exhaustive impact. Unresolved imports are diagnostics, not guessed edges."],
        },
        extensions: {},
      };
    }
    
    function assertFacts(evidence: LanguageEvidence, files: ScanContext["files"]): void {
      const sources = new Map(files.map((file) => [file.path, file.contents]));
      const ids = new Set(files.map((file) => factId("core", "file", file.path, file.path)));
      function location(loc: SourceLocation) {
        const source = sources.get(loc.path);
        if (source === undefined) throw new Error(`Adapter evidence references uncaptured source: ${loc.path}`);
        const lines = source.split(/\r?\n/);
        if (![loc.startLine, loc.endLine, loc.startColumn, loc.endColumn].every((n) => Number.isSafeInteger(n) && n > 0) ||
            loc.endLine < loc.startLine || loc.endLine > lines.length ||
            loc.startColumn > lines[loc.startLine - 1]!.length + 1 || loc.endColumn > lines[loc.endLine - 1]!.length + 1 ||
            loc.endLine === loc.startLine && loc.endColumn < loc.startColumn) {
          throw new Error(`Invalid adapter evidence range: ${loc.path}`);
        }
      }
      for (const contribution of evidence.contributions) {
        if (contribution.plugin.version !== "1.0") throw new Error("Unsupported adapter contract");
        for (const entity of contribution.entities) {
          if (!entity.id || ids.has(entity.id)) throw new Error(`Duplicate adapter entity: ${entity.id}`);
          ids.add(entity.id);
          location(entity.location);
        }
      }
      const edges = new Set<string>();
      for (const contribution of evidence.contributions) {
        for (const entity of contribution.entities) {
          if (entity.ownerId && !ids.has(entity.ownerId)) throw new Error(`Unknown owner: ${entity.ownerId}`);
        }
        for (const edge of contribution.relationships) {
          if (!edge.id || edges.has(edge.id) || !ids.has(edge.from) || !ids.has(edge.to) || !edge.evidence.length || !edge.method) {
            throw new Error(`Invalid adapter relationship: ${edge.id}`);
          }
          edges.add(edge.id);
          edge.evidence.forEach(location);
        }
        for (const unresolved of contribution.unresolved) {
          location(unresolved.location);
          if (!unresolved.reason) throw new Error("Unresolved adapter evidence requires a reason");
        }
      }
      json(evidence);
    }
    
    /** Core-owned selection; no arbitrary loader, Cargo, compiler build or model execution. */
    export async function scanProject(
      options: ScanRepositoryOptions,
      selection: PluginSelection = { languages: ["typescript"], frameworks: [] },
    ): Promise<ScanResult> {
      validateSelection(selection);
      const { createTypeScriptScannerAdapter, ScanError } = await import("@topo/scanner");
      if (selection.languages.length === 1 && selection.languages[0] === "typescript" && !selection.frameworks.length) {
        return createTypeScriptScannerAdapter().scan(options);
      }
      const captured = await captureInventory(options.root);
      const repositoryId = options.repositoryId ?? basename(options.root);
      const hasTypeScript = captured.files.some((file: { path: string }) => /\.(?:[cm]?[jt]s|[jt]sx)$/.test(file.path));
      let result: ScanResult | undefined;
      const contributions: Contribution[] = [];
      if (selection.languages.includes("typescript") && hasTypeScript) {
        result = await createTypeScriptScannerAdapter().scan({ ...options, quality: { ...options.quality, allowPartial: true } });
        contributions.push(typescriptContribution(result));
      } else if (selection.languages.includes("typescript")) {
        contributions.push({
          plugin: { id: "typescript", kind: "language", version: "1.0",
            languages: ["typescript", "javascript"], capabilities: ["compiler-declarations", "static-references"] },
          entities: [], relationships: [], unresolved: [], diagnostics: [], extensions: {},
          coverage: { status: "unsupported", analyzedFiles: [], limitations: ["No TypeScript/JavaScript source was captured for the selected adapter."] },
        });
      }
      if (selection.languages.includes("rust")) contributions.push(await rustContribution(captured));
      if (selection.frameworks.includes("tauri")) {
        const { scanTauri } = await import("./plugins/tauri.mjs");
        contributions.push(await scanTauri(captured, contributions));
      }
      const languageEvidence: LanguageEvidence = { schemaVersion: "1.0", source: captured.snapshot, contributions };
      assertFacts(languageEvidence, captured.files);
      const diagnostics = contributions.flatMap((contribution) => [
        ...contribution.diagnostics,
        ...contribution.coverage.limitations.map((message) => ({
          code: `${contribution.plugin.id}.coverage`, severity: "warning" as const, message,
        })),
      ]);
      const authoritative = contributions.every((item) => item.coverage.status === "complete");
      if (!authoritative && !options.quality?.allowPartial) {
        throw new ScanError("Selected adapters produced partial evidence; use --allow-partial to publish it (exit 2).", diagnostics);
      }
      const graph = result?.graph ?? createGraphDocument({
        graphId: `repo:${repositoryId}`, repository: { id: repositoryId, label: repositoryId,
          ...(options.revision === undefined ? {} : { revision: options.revision }) },
      });
      const knownPaths = new Set(graph.nodes.filter((node) => node.identity.kind === "path").map((node) => node.identity.value));
      for (const file of captured.files) {
        if (file.language !== "rust" && !/(?:^|\/)Cargo\.toml$/.test(file.path)) continue;
        if (!knownPaths.has(file.path)) graph.nodes.push({
          id: createPathNodeId(file.path), label: file.path, kind: "file",
          identity: { kind: "path", value: file.path }, fingerprint: `sha256:${file.sha256}`,
        });
      }
      graph.nodes.sort((a, b) => a.id.localeCompare(b.id, "en"));
      for (const contribution of contributions.filter((item) => item.plugin.id !== "typescript")) {
        graph.modules.push({ id: `@topo/${contribution.plugin.id}`, version: "1.0.0", schemaVersion: "1.0" });
      }
      graph.extensions[LANGUAGE_EVIDENCE_KEY] = json(languageEvidence);
      graph.extensions["dev.topo.scanner"] = json({ authoritative, status: authoritative ? "complete" : "partial", diagnostics });
      assertGraphDocument(graph);
      await assertInventoryCurrent(captured);
      if (options.revision !== undefined && options.revision !== captured.repository.revision) throw new Error("Source revision changed during scan");
      const logicalArchitecture: LogicalArchitectureDocument = result?.logicalArchitecture ?? {
        schemaVersion: "1.0" as const, graphId: graph.graphId,
        ...(options.revision === undefined ? {} : { revision: options.revision }),
        snapshotId: `sha256:${captured.snapshot.sha256}`, positionNamespaceId: `repo:${repositoryId}`,
        coverage: { languages: ["javascript", "typescript"], relationshipKinds: [], completeSourceInventory: false, runtimeBehavior: false },
        entities: [], relationships: [], responsibilities: [], unassignedEntityIds: [], diagnostics: [],
      };
      const metrics = result?.metrics ?? {
        configCount: 0, workspacePackageCount: 0, coveredWorkspacePackageCount: 0,
        sourceFileCount: 0,
        assetFileCount: 0, linesOfCode: 0, localImportCount: 0, assetImportCount: 0,
        externalImportCount: 0, unresolvedImportCount: 0,
      };
      const rustPaths = new Set(contributions.find((item) => item.plugin.id === "rust")?.coverage.analyzedFiles ?? []);
      const rustFiles = captured.files.filter((file) => file.language === "rust" && rustPaths.has(file.path));
      return { graph, logicalArchitecture, diagnostics, authoritative, metrics: {
        ...metrics,
        sourceFileCount: metrics.sourceFileCount + rustFiles.length,
        linesOfCode: metrics.linesOfCode + rustFiles
          .reduce((total, file) => total + file.contents.split(/\r?\n/).filter((line) => line.trim()).length, 0),
      } };
    }
    
    export async function resolveRustSymbol(path: string, contents: string, symbol: string): Promise<SourceLocation> {
      const contribution = await rustContribution({ root: "", files: [{ path, contents, sha256: hash(contents) }] });
      const candidates = contribution.entities.filter((entity) => entity.name === symbol || entity.qualifiedName === symbol);
      if (candidates.length !== 1) throw new Error(`Rust symbol "${symbol}" in "${path}" is ${candidates.length ? "ambiguous; use a lexical qualifiedName" : "missing"}`);
      if (contribution.unresolved.some((item) => item.kind === "syntax-error")) throw new Error(`Rust source "${path}" has parser recovery; use an exact pattern after repairing it`);
      return candidates[0]!.location;
    }
    
    export function languageEvidence(graph: GraphDocument): JsonValue | undefined {
      return graph.extensions[LANGUAGE_EVIDENCE_KEY];
    }
    
    export function sourceFileFactId(path: string): string {
      return factId("core", "file", path, path);
    }
    
    /** Only the displayable contract crosses from a stored snapshot into viewers. */
    export function readLanguageFacts(graph: GraphDocument): { entities: Entity[]; relationships: Relationship[] } {
      const value = graph.extensions[LANGUAGE_EVIDENCE_KEY];
      if (value === undefined) return { entities: [], relationships: [] };
      function object(value: unknown): Record<string, unknown> {
        if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error("Malformed language evidence object");
        return value as Record<string, unknown>;
      }
      function text(value: unknown): string {
        if (typeof value !== "string" || !value) throw new Error("Malformed language evidence string");
        return value;
      }
      function list(value: unknown): unknown[] {
        if (!Array.isArray(value)) throw new Error("Malformed language evidence collection");
        return value;
      }
      function location(value: unknown): SourceLocation {
        const item = object(value);
        function position(key: string): number {
          const number = item[key];
          if (typeof number !== "number" || !Number.isSafeInteger(number) || number < 1) throw new Error("Malformed language evidence location");
          return number;
        }
        return { path: text(item.path), startLine: position("startLine"), startColumn: position("startColumn"), endLine: position("endLine"), endColumn: position("endColumn") };
      }
      const document = object(value);
      if (document.schemaVersion !== "1.0") throw new Error("Unsupported language evidence version; scan again");
      const entities: Entity[] = [], relationships: Relationship[] = [];
      for (const contribution of list(document.contributions).map(object)) {
        for (const item of list(contribution.entities).map(object)) {
          if (typeof item.exported !== "boolean") throw new Error("Malformed language entity visibility");
          entities.push({
            id: text(item.id), name: text(item.name), kind: text(item.kind), language: text(item.language),
            qualifiedName: text(item.qualifiedName), exported: item.exported, location: location(item.location),
            signatures: list(item.signatures).map(text), attributes: list(item.attributes).map(text),
            ...(item.ownerId === undefined ? {} : { ownerId: text(item.ownerId) }),
          });
        }
        for (const item of list(contribution.relationships).map(object)) {
          relationships.push({ id: text(item.id), from: text(item.from), to: text(item.to),
            kind: text(item.kind), method: text(item.method), evidence: list(item.evidence).map(location) });
        }
      }
      return { entities, relationships };
    }
    
    export { graphLocation, serialize };
    
  • @topo/scanner Open Compiler-backed evidence extractionOpen Dependency context by role: Code analysisOpen Dependency context by role: Language parsingOpen Dependency context by role: Path selectionOpen Dependency context by role: Ignore matchingOpen Dependency context by role: Build, test, docsOpen Dependency context by role: Development tools

    Extracts TypeScript/JavaScript declarations, references, and graph evidence with the pinned compiler API and repository file-selection rules. All declared internal dependencies (not runtime calls): @topo/scanner -> @topo/schema [dependencies: workspace:*] Referenced by internal modules: @topo/languages -> @topo/scanner [dependencies: workspace:*] @topo/cli -> @topo/scanner [dependencies: workspace:*] Stable drilldown identity: scanner. Open the source-backed sequence for this module's core algorithm.

    packages/scanner/package.json:1-32
    {
      "name": "@topo/scanner",
      "version": "0.0.0",
      "private": true,
      "type": "module",
      "files": [
        "dist"
      ],
      "exports": {
        ".": {
          "types": "./dist/index.d.ts",
          "default": "./dist/index.js"
        }
      },
      "scripts": {
        "build": "tsc -b",
        "fixture": "node dist/fixture.js",
        "typecheck": "tsc -b --pretty false",
        "test": "vitest run src"
      },
      "dependencies": {
        "@topo/schema": "workspace:*",
        "ignore": "^7.0.0",
        "typescript-compiler-api": "npm:typescript@6.0.3"
      },
      "devDependencies": {
        "@types/node": "^22.0.0",
        "typescript": "^7.0.2",
        "vite": "8.2.2",
        "vitest": "^5.0.0"
      }
    }
    
    packages/scanner/src/typescript-scanner.ts:1-1452
    import { createHash } from "node:crypto";
    import { readFile, realpath } from "node:fs/promises";
    import path from "node:path";
    import {
      GRAPH_SCHEMA_VERSION,
      createAttributeId,
      createContainerId,
      createEdgeId,
      createExternalNodeId,
      createGraphDocument,
      createPathNodeId,
      serializeGraphDocument,
      type Evidence,
      type GraphContainer,
      type GraphEdge,
      type GraphNode,
      type JsonValue,
      type Provenance,
    } from "@topo/schema";
    import ts from "typescript-compiler-api";
    import {
      assertDirectory,
      discoverDeclaredPackageNames,
      discoverWorkspacePackages,
      isConfigFile,
      isSourceFile,
      toRepositoryPath,
      walkFiles,
      type WorkspacePackage,
    } from "./files.js";
    import { parseScanRepositoryOptions } from "./input.js";
    import {
      SCANNER_MODULE_ID,
      SCANNER_VERSION,
      ScanError,
      TYPESCRIPT_SCANNER_MANIFEST,
      type ScanDiagnostic,
      type ScanMetrics,
      type ScanRepositoryOptions,
      type ScanResult,
      type ScannerAdapter,
    } from "./types.js";
    import { extractLogicalArchitecture } from "./semantic.js";
    
    interface SourceRecord {
      absolutePath: string;
      repositoryPath: string;
      compilerOptions: ts.CompilerOptions;
      moduleResolutionCache: ts.ModuleResolutionCache;
      imports: string[];
      fingerprint: string;
      lines: number;
    }
    
    interface AssetRecord {
      absolutePath: string;
      repositoryPath: string;
      fingerprint: string;
    }
    
    interface OutputMapping {
      configPath: string;
      rootDirectory: string;
      outputDirectory: string;
    }
    
    interface ImportRecord {
      source: SourceRecord;
      specifier: string;
      anchor: string;
    }
    
    function assetEvidence(asset: AssetRecord): Evidence {
      return {
        id: `evidence:asset:${asset.repositoryPath}`,
        kind: "source",
        label: asset.repositoryPath,
        fingerprint: asset.fingerprint,
        anchor: { path: asset.repositoryPath },
        locator: `path:${asset.repositoryPath}`,
      };
    }
    
    const DEFAULT_QUALITY = {
      allowPartial: false,
      minimumFileCount: 1,
      maxUnresolvedImportRatio: 0,
      requireWorkspaceCoverage: true,
    } as const;
    
    function compareText(left: string, right: string): number {
      return left < right ? -1 : left > right ? 1 : 0;
    }
    
    function sha256(content: string): string {
      return `sha256:${createHash("sha256").update(content).digest("hex")}`;
    }
    
    function formatTypeScriptDiagnostic(
      root: string,
      diagnostic: ts.Diagnostic,
    ): ScanDiagnostic {
      return {
        code: "typescript-config",
        severity: "error",
        message: ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"),
        ...(diagnostic.file === undefined
          ? {}
          : { path: toRepositoryPath(root, diagnostic.file.fileName) }),
      };
    }
    
    function isWithin(root: string, target: string): boolean {
      const relative = path.relative(root, target);
      return (
        relative === "" ||
        (!relative.startsWith(`..${path.sep}`) && relative !== ".." && !path.isAbsolute(relative))
      );
    }
    
    function importSpecifiers(sourceFile: ts.SourceFile): ImportRecord["specifier"][] {
      const specifiers: string[] = [];
      const add = (value: ts.Expression | undefined): void => {
        if (value !== undefined && ts.isStringLiteralLike(value)) {
          specifiers.push(value.text);
        }
      };
    
      for (const statement of sourceFile.statements) {
        if (ts.isImportDeclaration(statement) || ts.isExportDeclaration(statement)) {
          add(statement.moduleSpecifier);
        } else if (
          ts.isImportEqualsDeclaration(statement) &&
          ts.isExternalModuleReference(statement.moduleReference)
        ) {
          add(statement.moduleReference.expression);
        }
      }
    
      const visit = (node: ts.Node): void => {
        if (
          ts.isCallExpression(node) &&
          node.arguments.length === 1 &&
          (node.expression.kind === ts.SyntaxKind.ImportKeyword ||
            (ts.isIdentifier(node.expression) &&
              node.expression.text === "require"))
        ) {
          add(node.arguments[0]);
        }
        ts.forEachChild(node, visit);
      };
      ts.forEachChild(sourceFile, visit);
      return specifiers;
    }
    
    function scriptKind(filePath: string): ts.ScriptKind {
      switch (path.extname(filePath).toLowerCase()) {
        case ".js":
        case ".cjs":
        case ".mjs":
          return ts.ScriptKind.JS;
        case ".jsx":
          return ts.ScriptKind.JSX;
        case ".tsx":
          return ts.ScriptKind.TSX;
        case ".json":
          return ts.ScriptKind.JSON;
        default:
          return ts.ScriptKind.TS;
      }
    }
    
    async function createSourceRecord(
      root: string,
      absolutePath: string,
      compilerOptions: ts.CompilerOptions,
      moduleResolutionCache: ts.ModuleResolutionCache,
    ): Promise<SourceRecord> {
      const repositoryPath = toRepositoryPath(root, absolutePath);
      const content = await readFile(absolutePath, "utf8");
      const sourceFile = ts.createSourceFile(
        absolutePath,
        content,
        ts.ScriptTarget.Latest,
        false,
        scriptKind(absolutePath),
      );
      return {
        absolutePath,
        repositoryPath,
        compilerOptions,
        moduleResolutionCache,
        imports: importSpecifiers(sourceFile),
        fingerprint: sha256(content),
        lines: content.length === 0 ? 0 : content.split(/\r\n?|\n/u).length,
      };
    }
    
    function validateConfiguredTypeLibraries(
      root: string,
      configPath: string,
      compilerOptions: ts.CompilerOptions,
      diagnostics: ScanDiagnostic[],
    ): void {
      for (const typeLibrary of compilerOptions.types ?? []) {
        const resolution = ts.resolveTypeReferenceDirective(
          typeLibrary,
          configPath,
          compilerOptions,
          ts.sys,
        );
        if (resolution.resolvedTypeReferenceDirective === undefined) {
          diagnostics.push({
            code: "missing-type-library",
            severity: "error",
            message: `Cannot resolve configured type library "${typeLibrary}".`,
            path: toRepositoryPath(root, configPath),
            specifier: typeLibrary,
          });
        }
      }
    }
    
    async function loadConfiguredSources(
      root: string,
      configPaths: readonly string[],
      diagnostics: ScanDiagnostic[],
      outputMappings: OutputMapping[],
      inventoryPaths: ReadonlySet<string>,
    ): Promise<Map<string, SourceRecord>> {
      const records = new Map<string, SourceRecord>();
      const ignoredConfigSources = new Set<string>();
    
      for (const configPath of configPaths) {
        const config = ts.readConfigFile(configPath, ts.sys.readFile);
        if (config.error !== undefined) {
          diagnostics.push(formatTypeScriptDiagnostic(root, config.error));
          continue;
        }
        const parsed = ts.parseJsonConfigFileContent(
          config.config,
          ts.sys,
          path.dirname(configPath),
          undefined,
          configPath,
        );
        diagnostics.push(
          ...parsed.errors.map((diagnostic) =>
            formatTypeScriptDiagnostic(root, diagnostic),
          ),
        );
        validateConfiguredTypeLibraries(
          root,
          configPath,
          parsed.options,
          diagnostics,
        );
        if (
          parsed.options.rootDir !== undefined &&
          parsed.options.outDir !== undefined
        ) {
          outputMappings.push({
            configPath: toRepositoryPath(root, configPath),
            rootDirectory: path.resolve(parsed.options.rootDir),
            outputDirectory: path.resolve(parsed.options.outDir),
          });
        }
        const moduleResolutionCache = ts.createModuleResolutionCache(
          path.dirname(configPath),
          (fileName) => fileName,
          parsed.options,
        );
        await collectConfiguredFiles(
          root,
          parsed.fileNames,
          parsed.options,
          moduleResolutionCache,
          records,
          inventoryPaths,
          ignoredConfigSources,
        );
      }
    
      if (ignoredConfigSources.size > 0) {
        const paths = [...ignoredConfigSources].sort(compareText);
        diagnostics.push({
          code: "ignored-config-source",
          severity: "warning",
          message: `${paths.length} TypeScript-configured files were excluded by Git or ignore rules: ${paths.join(", ")}.`,
        });
      }
    
      return records;
    }
    
    async function collectConfiguredFiles(
      root: string,
      fileNames: readonly string[],
      compilerOptions: ts.CompilerOptions,
      moduleResolutionCache: ts.ModuleResolutionCache,
      records: Map<string, SourceRecord>,
      inventoryPaths?: ReadonlySet<string>,
      ignoredConfigSources?: Set<string>,
    ): Promise<void> {
      for (const fileName of fileNames) {
        const absolutePath = path.resolve(fileName);
        if (inventoryPaths !== undefined && !inventoryPaths.has(absolutePath)) {
          ignoredConfigSources?.add(toRepositoryPath(root, absolutePath));
          continue;
        }
        if (
          !isWithin(root, absolutePath) ||
          !isSourceFile(absolutePath)
        ) {
          continue;
        }
        const repositoryPath = toRepositoryPath(root, absolutePath);
        if (records.has(repositoryPath)) {
          continue;
        }
        records.set(
          repositoryPath,
          await createSourceRecord(
            root,
            absolutePath,
            compilerOptions,
            moduleResolutionCache,
          ),
        );
      }
    }
    
    async function loadInferredSources(
      root: string,
      sourcePaths: readonly string[],
    ): Promise<Map<string, SourceRecord>> {
      const options: ts.CompilerOptions = {
        allowJs: true,
        checkJs: false,
        module: ts.ModuleKind.NodeNext,
        moduleResolution: ts.ModuleResolutionKind.NodeNext,
        target: ts.ScriptTarget.ES2022,
      };
      const records = new Map<string, SourceRecord>();
      const moduleResolutionCache = ts.createModuleResolutionCache(
        root,
        (fileName) => fileName,
        options,
      );
      await collectConfiguredFiles(
        root,
        sourcePaths,
        options,
        moduleResolutionCache,
        records,
      );
      return records;
    }
    
    function packageName(specifier: string): string {
      if (specifier.startsWith("@")) {
        return specifier.split("/").slice(0, 2).join("/");
      }
      return specifier.split("/")[0] ?? specifier;
    }
    
    function isPathAlias(
      specifier: string,
      compilerOptions: ts.CompilerOptions,
    ): boolean {
      return Object.keys(compilerOptions.paths ?? {}).some((pattern) => {
        const [prefix, suffix = ""] = pattern.split("*");
        return (
          specifier.startsWith(prefix ?? "") &&
          specifier.endsWith(suffix) &&
          specifier.length >= (prefix?.length ?? 0) + suffix.length
        );
      });
    }
    
    function workspaceForSpecifier(
      specifier: string,
      workspaces: readonly WorkspacePackage[],
    ): WorkspacePackage | undefined {
      return workspaces.find(
        (workspace) =>
          specifier === workspace.name ||
          specifier.startsWith(`${workspace.name}/`),
      );
    }
    
    function manifestEntryStrings(value: unknown): string[] {
      if (typeof value === "string") {
        return [value];
      }
      if (value === null || typeof value !== "object" || Array.isArray(value)) {
        return [];
      }
      return Object.values(value).flatMap(manifestEntryStrings);
    }
    
    function hasExactWorkspaceExport(
      exports: unknown,
      subpath: string,
    ): boolean {
      return (
        exports === null ||
        typeof exports !== "object" ||
        Array.isArray(exports)
          ? false
          : Object.hasOwn(exports, subpath)
      );
    }
    
    function sourceCandidatePathsForEntries(
      workspace: WorkspacePackage,
      entries: readonly string[],
    ): string[] {
      const candidates = new Set<string>();
      for (const entry of entries) {
        const normalized = entry.replace(/^\.\//u, "");
        candidates.add(path.resolve(workspace.directory, normalized));
        if (normalized.startsWith("dist/")) {
          candidates.add(
            path.resolve(
              workspace.directory,
              `src/${normalized.slice("dist/".length)}`,
            ),
          );
        }
      }
      return [...candidates];
    }
    
    function sourceCandidatePaths(
      workspace: WorkspacePackage,
      specifier: string,
    ): string[] {
      const suffix =
        specifier === workspace.name
          ? ""
          : specifier.slice(workspace.name.length + 1);
      const manifest = workspace.manifest;
      const declared =
        suffix.length === 0
          ? [
              ...manifestEntryStrings(manifest.source),
              ...manifestEntryStrings(manifest.module),
              ...manifestEntryStrings(manifest.main),
              ...manifestEntryStrings(manifest.types),
            ]
          : manifest.exports === undefined
            ? [suffix]
            : [];
      const bases = [...declared, ...(suffix.length === 0 ? ["src/index"] : [])];
      return sourceCandidatePathsForEntries(workspace, bases);
    }
    
    function resolveSourceCandidate(
      candidates: readonly string[],
      sourceByAbsolutePath: ReadonlyMap<string, SourceRecord>,
    ): SourceRecord | undefined {
      return resolveSourceCandidates(candidates, sourceByAbsolutePath)[0];
    }
    
    function resolveSourceCandidates(
      candidates: readonly string[],
      sourceByAbsolutePath: ReadonlyMap<string, SourceRecord>,
    ): SourceRecord[] {
      const extensions = [
        "",
        ".ts",
        ".tsx",
        ".mts",
        ".cts",
        ".js",
        ".jsx",
        ".mjs",
        ".cjs",
        "/index.ts",
        "/index.tsx",
        "/index.mts",
        "/index.cts",
        "/index.js",
        "/index.jsx",
      ];
      const matches = new Map<string, SourceRecord>();
      for (const candidate of candidates) {
        const withoutOutputExtension = candidate.replace(
          /\.(?:d\.ts|[cm]?[jt]sx?)$/u,
          "",
        );
        for (const extension of extensions) {
          const source = sourceByAbsolutePath.get(
            path.resolve(`${withoutOutputExtension}${extension}`),
          );
          if (source !== undefined) {
            matches.set(source.absolutePath, source);
          }
        }
      }
      return [...matches.values()];
    }
    
    const GENERATED_SOURCE_EXTENSIONS = [
      [".d.mts", [".mts", ".mjs"]],
      [".d.cts", [".cts", ".cjs"]],
      [".d.ts", [".ts", ".tsx", ".js", ".jsx"]],
      [".mjs", [".mts", ".mjs"]],
      [".cjs", [".cts", ".cjs"]],
      [".jsx", [".tsx", ".jsx"]],
      [".js", [".ts", ".tsx", ".js", ".jsx"]],
    ] as const;
    
    function generatedSourcePaths(outputPath: string): string[] {
      for (const [outputExtension, sourceExtensions] of GENERATED_SOURCE_EXTENSIONS) {
        if (outputPath.endsWith(outputExtension)) {
          const basePath = outputPath.slice(0, -outputExtension.length);
          return sourceExtensions.map(
            (sourceExtension) => `${basePath}${sourceExtension}`,
          );
        }
      }
      return [];
    }
    
    function resolveGeneratedOutput(
      resolvedFileName: string,
      outputMappings: readonly OutputMapping[],
      sourceByAbsolutePath: ReadonlyMap<string, SourceRecord>,
    ):
      | { kind: "none" }
      | { kind: "resolved"; source: SourceRecord }
      | { kind: "ambiguous"; configPaths: string[] } {
      const matches = new Map<string, { source: SourceRecord; configPath: string }>();
      for (const mapping of outputMappings) {
        if (!isWithin(mapping.outputDirectory, resolvedFileName)) {
          continue;
        }
        const relativeOutputPath = path.relative(
          mapping.outputDirectory,
          resolvedFileName,
        );
        const sourcePath = path.join(mapping.rootDirectory, relativeOutputPath);
        for (const generatedSourcePath of generatedSourcePaths(sourcePath)) {
          const source = sourceByAbsolutePath.get(generatedSourcePath);
          if (source !== undefined) {
            matches.set(source.absolutePath, {
              source,
              configPath: mapping.configPath,
            });
          }
        }
      }
      if (matches.size === 0) {
        return { kind: "none" };
      }
      if (matches.size === 1) {
        return { kind: "resolved", source: [...matches.values()][0]!.source };
      }
      return {
        kind: "ambiguous",
        configPaths: [...new Set(
          [...matches.values()].map((match) => match.configPath),
        )].sort(compareText),
      };
    }
    
    function compilerPathCandidates(
      root: string,
      canonicalRoot: string,
      resolvedFileName: string,
    ): string[] {
      const candidates = new Set<string>([path.resolve(resolvedFileName)]);
      const canonicalPath =
        ts.sys.realpath?.(resolvedFileName) ?? path.resolve(resolvedFileName);
      candidates.add(path.resolve(canonicalPath));
      if (isWithin(canonicalRoot, canonicalPath)) {
        candidates.add(
          path.resolve(root, path.relative(canonicalRoot, canonicalPath)),
        );
      }
      return [...candidates];
    }
    
    function resolveCompilerSelectedSource(
      root: string,
      canonicalRoot: string,
      resolvedFileName: string,
      outputMappings: readonly OutputMapping[],
      sourceByAbsolutePath: ReadonlyMap<string, SourceRecord>,
    ):
      | { kind: "none" }
      | { kind: "resolved"; source: SourceRecord }
      | { kind: "ambiguous"; configPaths: string[] } {
      const candidates = compilerPathCandidates(
        root,
        canonicalRoot,
        resolvedFileName,
      );
      for (const candidate of candidates) {
        const source = sourceByAbsolutePath.get(candidate);
        if (source !== undefined) {
          return { kind: "resolved", source };
        }
      }
      for (const candidate of candidates) {
        if (!isWithin(root, candidate)) {
          continue;
        }
        const generated = resolveGeneratedOutput(
          candidate,
          outputMappings,
          sourceByAbsolutePath,
        );
        if (generated.kind !== "none") {
          return generated;
        }
      }
      return { kind: "none" };
    }
    
    function canonicalPath(fileName: string): string {
      const resolved = path.resolve(fileName);
      const canonical = ts.sys.realpath?.(resolved) ?? resolved;
      return ts.sys.useCaseSensitiveFileNames
        ? canonical
        : canonical.toLowerCase();
    }
    
    function physicalWorkspacePackageState(
      workspace: WorkspacePackage,
      containingFile: string,
    ): "absent" | "workspace" | "other" {
      const packageSegments = workspace.name.split("/");
      let directory = path.dirname(containingFile);
      while (true) {
        const packageDirectory = path.join(
          directory,
          "node_modules",
          ...packageSegments,
        );
        if (ts.sys.fileExists(path.join(packageDirectory, "package.json"))) {
          return canonicalPath(packageDirectory) ===
            canonicalPath(workspace.directory)
            ? "workspace"
            : "other";
        }
        const parent = path.dirname(directory);
        if (parent === directory) {
          return "absent";
        }
        directory = parent;
      }
    }
    
    function createWorkspaceModuleResolutionHost(
      root: string,
      canonicalRoot: string,
      workspace: WorkspacePackage,
      outputMappings: readonly OutputMapping[],
      sourceByAbsolutePath: ReadonlyMap<string, SourceRecord>,
      allowGeneratedOutput: boolean,
    ): ts.ModuleResolutionHost {
      const packageSegments = workspace.name.split("/");
      const virtualPackageDirectories = [...new Set([root, canonicalRoot])]
        .map((workspaceRoot) =>
          path.join(workspaceRoot, "node_modules", ...packageSegments),
        );
      const workspaceMappings = outputMappings.filter(
        (mapping) =>
          isWithin(workspace.directory, mapping.rootDirectory) &&
          isWithin(workspace.directory, mapping.outputDirectory),
      );
      const toWorkspacePath = (fileName: string): string | undefined => {
        for (const virtualDirectory of virtualPackageDirectories) {
          if (isWithin(virtualDirectory, fileName)) {
            return path.resolve(
              workspace.directory,
              path.relative(virtualDirectory, fileName),
            );
          }
        }
        return undefined;
      };
      const hasGeneratedPath = (fileName: string): boolean =>
        resolveGeneratedOutput(
          fileName,
          workspaceMappings,
          sourceByAbsolutePath,
        ).kind === "resolved";
      const hasGeneratedDirectory = (directory: string): boolean =>
        workspaceMappings.some(
          (mapping) =>
            isWithin(directory, mapping.outputDirectory) ||
            isWithin(mapping.outputDirectory, directory),
        );
    
      return {
        fileExists(fileName) {
          if (ts.sys.fileExists(fileName)) {
            return true;
          }
          const workspacePath = toWorkspacePath(fileName);
          return workspacePath !== undefined &&
            (ts.sys.fileExists(workspacePath) ||
              (allowGeneratedOutput && hasGeneratedPath(workspacePath)));
        },
        readFile(fileName) {
          const workspacePath = toWorkspacePath(fileName);
          return ts.sys.readFile(workspacePath ?? fileName);
        },
        directoryExists(directory) {
          if (ts.sys.directoryExists?.(directory) === true) {
            return true;
          }
          if (
            virtualPackageDirectories.some((virtualDirectory) =>
              isWithin(directory, virtualDirectory),
            )
          ) {
            return true;
          }
          const workspacePath = toWorkspacePath(directory);
          return workspacePath !== undefined &&
            (ts.sys.directoryExists?.(workspacePath) === true ||
              (allowGeneratedOutput && hasGeneratedDirectory(workspacePath)));
        },
        realpath(fileName) {
          const workspacePath = toWorkspacePath(fileName);
          if (workspacePath !== undefined) {
            return ts.sys.realpath?.(workspacePath) ?? workspacePath;
          }
          return ts.sys.realpath?.(fileName) ?? fileName;
        },
        getCurrentDirectory: () => root,
        useCaseSensitiveFileNames: ts.sys.useCaseSensitiveFileNames,
      };
    }
    
    function resolveWorkspaceModuleName(
      root: string,
      canonicalRoot: string,
      workspace: WorkspacePackage,
      source: SourceRecord,
      specifier: string,
      outputMappings: readonly OutputMapping[],
      sourceByAbsolutePath: ReadonlyMap<string, SourceRecord>,
    ): ts.ResolvedModuleFull | undefined {
      for (const allowGeneratedOutput of [false, true]) {
        const resolved = ts.resolveModuleName(
          specifier,
          source.absolutePath,
          source.compilerOptions,
          createWorkspaceModuleResolutionHost(
            root,
            canonicalRoot,
            workspace,
            outputMappings,
            sourceByAbsolutePath,
            allowGeneratedOutput,
          ),
          ts.createModuleResolutionCache(
            path.dirname(source.absolutePath),
            (fileName) =>
              ts.sys.useCaseSensitiveFileNames
                ? fileName
                : fileName.toLowerCase(),
            source.compilerOptions,
          ),
        ).resolvedModule;
        if (resolved !== undefined) {
          return resolved;
        }
      }
      return undefined;
    }
    
    function assetSpecifierPath(specifier: string): string | undefined {
      if (!specifier.startsWith(".")) {
        return undefined;
      }
      const literalPath = specifier.split(/[?#]/u, 1)[0];
      return literalPath !== undefined &&
        path.extname(literalPath).toLowerCase() === ".css"
        ? literalPath
        : undefined;
    }
    
    function externalLocator(specifier: string): string {
      return specifier.startsWith("node:")
        ? specifier
        : `npm:${packageName(specifier)}`;
    }
    
    function provenance(evidenceIds: string[]): Provenance {
      return {
        kind: "observed",
        moduleId: SCANNER_MODULE_ID,
        method: "typescript-compiler-api",
        evidenceIds: [...evidenceIds].sort(compareText),
      };
    }
    
    function directoriesForPaths(
      rootLabel: string,
      repositoryPaths: readonly string[],
    ): GraphContainer[] {
      const directories = new Set<string>(["."]);
      for (const repositoryPath of repositoryPaths) {
        let directory = path.posix.dirname(repositoryPath);
        while (directory !== ".") {
          directories.add(directory);
          directory = path.posix.dirname(directory);
        }
      }
    
      return [...directories]
        .sort(compareText)
        .map((directory) => {
          const memberIds = repositoryPaths
            .filter(
              (repositoryPath) =>
                path.posix.dirname(repositoryPath) === directory,
            )
            .map((repositoryPath) => createPathNodeId(repositoryPath))
            .sort(compareText);
          return {
            id: createContainerId("directory", directory),
            label:
              directory === "." ? rootLabel : path.posix.basename(directory),
            type: "directory",
            memberIds,
            ...(directory === "."
              ? {}
              : {
                  parentId: createContainerId(
                    "directory",
                    path.posix.dirname(directory),
                  ),
                }),
          };
        });
    }
    
    function sourceEvidence(source: SourceRecord): Evidence {
      return {
        id: `evidence:source:${source.repositoryPath}`,
        kind: "source",
        label: source.repositoryPath,
        fingerprint: source.fingerprint,
        anchor: { path: source.repositoryPath },
        locator: `path:${source.repositoryPath}`,
      };
    }
    
    function importEvidence(
      source: SourceRecord,
      specifier: string,
    ): Evidence {
      const anchor = sha256(`import:${specifier}`).slice("sha256:".length, 24);
      return {
        id: `evidence:import:${source.repositoryPath}:${anchor}`,
        kind: "source",
        label: `${source.repositoryPath} imports ${specifier}`,
        fingerprint: source.fingerprint,
        anchor: {
          path: source.repositoryPath,
          symbol: `import:${specifier}`,
          contentPattern: JSON.stringify(specifier),
        },
        locator: `path:${source.repositoryPath}#import:${JSON.stringify(specifier)}`,
      };
    }
    
    function qualityDiagnostics(
      metrics: ScanMetrics,
      quality: Required<NonNullable<ScanRepositoryOptions["quality"]>>,
      unsupportedCargo: boolean,
    ): ScanDiagnostic[] {
      const diagnostics: ScanDiagnostic[] = [];
      if (metrics.sourceFileCount < quality.minimumFileCount) {
        diagnostics.push({
          code: "insufficient-source-files",
          severity: "error",
          message: `Found ${metrics.sourceFileCount} supported source files; at least ${quality.minimumFileCount} required.`,
        });
      }
      const importTotal = metrics.localImportCount + metrics.unresolvedImportCount;
      const unresolvedRatio =
        importTotal === 0 ? 0 : metrics.unresolvedImportCount / importTotal;
      if (unresolvedRatio > quality.maxUnresolvedImportRatio) {
        diagnostics.push({
          code: "unresolved-import-ratio",
          severity: "error",
          message: `Unresolved local/workspace import ratio ${unresolvedRatio.toFixed(6)} exceeds ${quality.maxUnresolvedImportRatio}.`,
        });
      }
      if (
        quality.requireWorkspaceCoverage &&
        metrics.coveredWorkspacePackageCount < metrics.workspacePackageCount
      ) {
        diagnostics.push({
          code: "incomplete-workspace-coverage",
          severity: "error",
          message: `Covered ${metrics.coveredWorkspacePackageCount} of ${metrics.workspacePackageCount} workspace packages.`,
        });
      }
      if (unsupportedCargo) {
        diagnostics.push({
          code: "unsupported-cargo-workspace",
          severity: "error",
          message:
            "Cargo workspaces are not supported by the TypeScript/JavaScript scanner.",
          path: "Cargo.toml",
        });
      }
      return diagnostics;
    }
    
    export async function scanRepository(
      input: ScanRepositoryOptions,
    ): Promise<ScanResult> {
      const options = parseScanRepositoryOptions(input);
      const quality = { ...DEFAULT_QUALITY, ...options.quality };
      await assertDirectory(options.root);
      const canonicalRoot = await realpath(options.root);
    
      const files = await walkFiles(options.root);
      const inventoryPaths = new Set(files.map((filePath) => path.resolve(filePath)));
      const configPaths = files.filter(isConfigFile).sort(compareText);
      const sourcePaths = files.filter(isSourceFile).sort(compareText);
      const workspaces = await discoverWorkspacePackages(options.root, files);
      const declaredPackageNames = await discoverDeclaredPackageNames(
        options.root,
        files,
      );
      const diagnostics: ScanDiagnostic[] = [];
      const outputMappings: OutputMapping[] = [];
      const configuredSources = await loadConfiguredSources(
        options.root,
        configPaths,
        diagnostics,
        outputMappings,
        inventoryPaths,
      );
      const unconfiguredPaths = sourcePaths.filter(
        (sourcePath) =>
          !configuredSources.has(toRepositoryPath(options.root, sourcePath)),
      );
      const inferredSources = await loadInferredSources(
        options.root,
        unconfiguredPaths,
      );
      const sources = new Map([...configuredSources, ...inferredSources]);
      if (configuredSources.size > 0 && inferredSources.size > 0) {
        diagnostics.push({
          code: "inferred-source-configuration",
          severity: "warning",
          message: `${inferredSources.size} source files were not covered by a discovered TypeScript config and used default compiler options.`,
        });
      }
      const sortedSources = [...sources.values()].sort((left, right) =>
        compareText(left.repositoryPath, right.repositoryPath),
      );
      const sourceByAbsolutePath = new Map(
        sortedSources.map((source) => [path.resolve(source.absolutePath), source]),
      );
      const filePaths = inventoryPaths;
    
      const nodes = new Map<string, GraphNode>();
      const evidence = new Map<string, Evidence>();
      const assets = new Map<string, AssetRecord>();
      for (const source of sortedSources) {
        const nodeId = createPathNodeId(source.repositoryPath);
        nodes.set(nodeId, {
          id: nodeId,
          label: path.posix.basename(source.repositoryPath),
          kind: "file",
          identity: { kind: "path", value: source.repositoryPath },
          fingerprint: source.fingerprint,
        });
        const item = sourceEvidence(source);
        evidence.set(item.id, item);
      }
    
      const edgeEvidence = new Map<
        string,
        { sourceId: string; targetId: string; evidenceIds: Set<string> }
      >();
      let localImportCount = 0;
      let assetImportCount = 0;
      let externalImportCount = 0;
      let unresolvedImportCount = 0;
    
      for (const source of sortedSources) {
        const imports = [...source.imports].sort(compareText);
        for (const specifier of imports) {
          const importItem = importEvidence(source, specifier);
          const assetPath = assetSpecifierPath(specifier);
          if (assetPath !== undefined) {
            const absoluteAssetPath = path.resolve(
              path.dirname(source.absolutePath),
              assetPath,
            );
            if (
              !isWithin(options.root, absoluteAssetPath) ||
              !filePaths.has(absoluteAssetPath)
            ) {
              unresolvedImportCount += 1;
              diagnostics.push({
                code: "unresolved-local-asset",
                severity: "error",
                message: `Could not resolve local CSS asset "${specifier}" from "${source.repositoryPath}".`,
                path: source.repositoryPath,
                specifier,
              });
              continue;
            }
            let asset = assets.get(absoluteAssetPath);
            if (asset === undefined) {
              const content = await readFile(absoluteAssetPath, "utf8");
              asset = {
                absolutePath: absoluteAssetPath,
                repositoryPath: toRepositoryPath(
                  options.root,
                  absoluteAssetPath,
                ),
                fingerprint: sha256(content),
              };
              assets.set(absoluteAssetPath, asset);
              const assetId = createPathNodeId(asset.repositoryPath);
              nodes.set(assetId, {
                id: assetId,
                label: path.posix.basename(asset.repositoryPath),
                kind: "asset",
                identity: { kind: "path", value: asset.repositoryPath },
                fingerprint: asset.fingerprint,
              });
              const item = assetEvidence(asset);
              evidence.set(item.id, item);
            }
            const sourceId = createPathNodeId(source.repositoryPath);
            const targetId = createPathNodeId(asset.repositoryPath);
            const edgeId = createEdgeId("imports", sourceId, targetId);
            evidence.set(importItem.id, importItem);
            const accumulated = edgeEvidence.get(edgeId) ?? {
              sourceId,
              targetId,
              evidenceIds: new Set<string>(),
            };
            accumulated.evidenceIds.add(importItem.id);
            edgeEvidence.set(edgeId, accumulated);
            assetImportCount += 1;
            continue;
          }
          const resolved = ts.resolveModuleName(
            specifier,
            source.absolutePath,
            source.compilerOptions,
            ts.sys,
            source.moduleResolutionCache,
          ).resolvedModule;
          let targetId: string | undefined;
          const workspace = workspaceForSpecifier(specifier, workspaces);
    
          if (workspace !== undefined) {
            let target: SourceRecord | undefined;
            if (resolved !== undefined) {
              const selected = resolveCompilerSelectedSource(
                options.root,
                canonicalRoot,
                resolved.resolvedFileName,
                outputMappings,
                sourceByAbsolutePath,
              );
              if (selected.kind === "resolved") {
                target = selected.source;
              } else if (selected.kind === "ambiguous") {
                unresolvedImportCount += 1;
                diagnostics.push({
                  code: "ambiguous-generated-output",
                  severity: "error",
                  message: `Generated output import "${specifier}" from "${source.repositoryPath}" maps to multiple source projects: ${selected.configPaths.join(", ")}.`,
                  path: source.repositoryPath,
                  specifier,
                });
                continue;
              } else if (
                resolved.resolvedFileName
                  .split(path.sep)
                  .includes("node_modules") ||
                !isWithin(options.root, resolved.resolvedFileName)
              ) {
                const locator = externalLocator(specifier);
                targetId = createExternalNodeId(locator);
                externalImportCount += 1;
                nodes.set(targetId, {
                  id: targetId,
                  label: packageName(specifier),
                  kind: "external",
                  identity: { kind: "external", value: locator },
                });
              }
            } else {
              const suffix =
                specifier === workspace.name
                  ? ""
                  : specifier.slice(workspace.name.length + 1);
              const exportedSubpath =
                suffix.length === 0
                  ? workspace.manifest.exports !== undefined
                  : hasExactWorkspaceExport(
                      workspace.manifest.exports,
                      `./${suffix}`,
                    );
              const physicalPackage = physicalWorkspacePackageState(
                workspace,
                source.absolutePath,
              );
              if (exportedSubpath && physicalPackage !== "other") {
                const virtualResolved = resolveWorkspaceModuleName(
                  options.root,
                  canonicalRoot,
                  workspace,
                  source,
                  specifier,
                  outputMappings,
                  sourceByAbsolutePath,
                );
                if (virtualResolved !== undefined) {
                  const selected = resolveCompilerSelectedSource(
                    options.root,
                    canonicalRoot,
                    virtualResolved.resolvedFileName,
                    outputMappings,
                    sourceByAbsolutePath,
                  );
                  if (selected.kind === "resolved") {
                    target = selected.source;
                  } else if (selected.kind === "ambiguous") {
                    unresolvedImportCount += 1;
                    diagnostics.push({
                      code: "ambiguous-generated-output",
                      severity: "error",
                      message: `Generated output import "${specifier}" from "${source.repositoryPath}" maps to multiple source projects: ${selected.configPaths.join(", ")}.`,
                      path: source.repositoryPath,
                      specifier,
                    });
                    continue;
                  }
                }
              } else if (physicalPackage !== "other") {
                target = resolveSourceCandidate(
                  sourceCandidatePaths(workspace, specifier),
                  sourceByAbsolutePath,
                );
              }
            }
            if (targetId === undefined) {
              if (target !== undefined) {
                targetId = createPathNodeId(target.repositoryPath);
                localImportCount += 1;
              } else {
                unresolvedImportCount += 1;
                diagnostics.push({
                  code: "unresolved-workspace-import",
                  severity: "error",
                  message: `Could not resolve workspace import "${specifier}" from "${source.repositoryPath}".`,
                  path: source.repositoryPath,
                  specifier,
                });
                continue;
              }
            }
          } else if (
            resolved !== undefined &&
            resolved.resolvedFileName
              .split(path.sep)
              .includes("node_modules")
          ) {
            const locator = externalLocator(specifier);
            targetId = createExternalNodeId(locator);
            externalImportCount += 1;
            nodes.set(targetId, {
              id: targetId,
              label: packageName(specifier),
              kind: "external",
              identity: { kind: "external", value: locator },
            });
          } else if (resolved !== undefined && isWithin(options.root, resolved.resolvedFileName)) {
            const target = sourceByAbsolutePath.get(
              path.resolve(resolved.resolvedFileName),
            );
            if (target !== undefined) {
              targetId = createPathNodeId(target.repositoryPath);
              localImportCount += 1;
            } else {
              const generated = resolveGeneratedOutput(
                path.resolve(resolved.resolvedFileName),
                outputMappings,
                sourceByAbsolutePath,
              );
              if (generated.kind === "resolved") {
                targetId = createPathNodeId(generated.source.repositoryPath);
                localImportCount += 1;
              } else if (generated.kind === "ambiguous") {
                unresolvedImportCount += 1;
                diagnostics.push({
                  code: "ambiguous-generated-output",
                  severity: "error",
                  message: `Generated output import "${specifier}" from "${source.repositoryPath}" maps to multiple source projects: ${generated.configPaths.join(", ")}.`,
                  path: source.repositoryPath,
                  specifier,
                });
                continue;
              }
            }
          } else if (
            resolved !== undefined &&
            !isWithin(options.root, resolved.resolvedFileName)
          ) {
            const locator = externalLocator(specifier);
            targetId = createExternalNodeId(locator);
            externalImportCount += 1;
            nodes.set(targetId, {
              id: targetId,
              label: packageName(specifier),
              kind: "external",
              identity: { kind: "external", value: locator },
            });
          } else {
            const local =
              specifier.startsWith(".") ||
              specifier.startsWith("/") ||
              (isPathAlias(specifier, source.compilerOptions) &&
                !declaredPackageNames.has(packageName(specifier)));
            if (local) {
              unresolvedImportCount += 1;
              diagnostics.push({
                code: "unresolved-local-import",
                severity: "error",
                message: `Could not resolve local import "${specifier}" from "${source.repositoryPath}".`,
                path: source.repositoryPath,
                specifier,
              });
              continue;
            }
            const locator = externalLocator(specifier);
            targetId = createExternalNodeId(locator);
            externalImportCount += 1;
            nodes.set(targetId, {
              id: targetId,
              label: packageName(specifier),
              kind: "external",
              identity: { kind: "external", value: locator },
            });
          }
    
          if (targetId === undefined) {
            unresolvedImportCount += 1;
            diagnostics.push({
              code: "resolved-import-outside-scan",
              severity: "error",
              message: `Resolved import "${specifier}" is not represented by a scanned source file.`,
              path: source.repositoryPath,
              specifier,
            });
            continue;
          }
    
          const sourceId = createPathNodeId(source.repositoryPath);
          const edgeId = createEdgeId("imports", sourceId, targetId);
          evidence.set(importItem.id, importItem);
          const accumulated = edgeEvidence.get(edgeId) ?? {
            sourceId,
            targetId,
            evidenceIds: new Set<string>(),
          };
          accumulated.evidenceIds.add(importItem.id);
          edgeEvidence.set(edgeId, accumulated);
        }
      }
    
      const edges: GraphEdge[] = [...edgeEvidence.entries()]
        .sort(([left], [right]) => compareText(left, right))
        .map(([id, edge]) => ({
          id,
          label: "imports",
          type: "imports",
          sourceId: edge.sourceId,
          targetId: edge.targetId,
          provenance: provenance([...edge.evidenceIds]),
        }));
      const coveredWorkspacePackageCount = workspaces.filter((workspace) =>
        sortedSources.some(
          (source) =>
            source.absolutePath.startsWith(`${workspace.directory}${path.sep}`),
        ),
      ).length;
      const metrics: ScanMetrics = {
        configCount: configPaths.length,
        workspacePackageCount: workspaces.length,
        coveredWorkspacePackageCount,
        sourceFileCount: sortedSources.length,
        assetFileCount: assets.size,
        linesOfCode: sortedSources.reduce((sum, source) => sum + source.lines, 0),
        localImportCount,
        assetImportCount,
        externalImportCount,
        unresolvedImportCount,
      };
      const rootCargo = files.includes(path.join(options.root, "Cargo.toml"));
      diagnostics.push(...qualityDiagnostics(metrics, quality, rootCargo));
      diagnostics.sort(
        (left, right) =>
          compareText(left.path ?? "", right.path ?? "") ||
          compareText(left.code, right.code) ||
          compareText(left.specifier ?? "", right.specifier ?? ""),
      );
    
      const errors = diagnostics.filter(
        (diagnostic) => diagnostic.severity === "error",
      );
      const fatalEmpty = sortedSources.length === 0;
      if (
        errors.length > 0 &&
        (!quality.allowPartial || fatalEmpty)
      ) {
        throw new ScanError(
          `Repository scan failed with ${errors.length} error diagnostic${errors.length === 1 ? "" : "s"}.`,
          diagnostics,
        );
      }
    
      const authoritative = errors.length === 0;
      const repositoryId =
        options.repositoryId ?? path.basename(options.root);
      const rootLabel = path.basename(options.root);
      const scannerExtension: JsonValue = {
        authoritative,
        status: authoritative ? "complete" : "partial",
        adapter: {
          id: TYPESCRIPT_SCANNER_MANIFEST.id,
          version: TYPESCRIPT_SCANNER_MANIFEST.version,
          contractVersion: TYPESCRIPT_SCANNER_MANIFEST.contractVersion,
          capabilities: {
            languages: [...TYPESCRIPT_SCANNER_MANIFEST.capabilities.languages],
            granularity: [...TYPESCRIPT_SCANNER_MANIFEST.capabilities.granularity],
            relationships: [
              ...TYPESCRIPT_SCANNER_MANIFEST.capabilities.relationships,
            ],
            moduleResolution:
              TYPESCRIPT_SCANNER_MANIFEST.capabilities.moduleResolution,
            workspaceManifests: [
              ...TYPESCRIPT_SCANNER_MANIFEST.capabilities.workspaceManifests,
            ],
            opaqueAssets: [
              ...TYPESCRIPT_SCANNER_MANIFEST.capabilities.opaqueAssets,
            ],
            partialResults:
              TYPESCRIPT_SCANNER_MANIFEST.capabilities.partialResults,
          },
        },
        metrics: { ...metrics },
        diagnostics: diagnostics.map((diagnostic) => ({
          code: diagnostic.code,
          severity: diagnostic.severity,
          message: diagnostic.message,
          ...(diagnostic.path === undefined ? {} : { path: diagnostic.path }),
          ...(diagnostic.specifier === undefined
            ? {}
            : { specifier: diagnostic.specifier }),
        })),
      };
      const graph = createGraphDocument({
        graphId: `repo:${repositoryId}`,
        repository: {
          id: repositoryId,
          label: rootLabel,
          ...(options.revision === undefined
            ? {}
            : { revision: options.revision }),
        },
        modules: [
          {
            id: SCANNER_MODULE_ID,
            version: SCANNER_VERSION,
            schemaVersion: GRAPH_SCHEMA_VERSION,
          },
        ],
        nodes: [...nodes.values()].sort((left, right) =>
          compareText(left.id, right.id),
        ),
        edges,
        containers: directoriesForPaths(
          rootLabel,
          [
            ...sortedSources.map((source) => source.repositoryPath),
            ...[...assets.values()].map((asset) => asset.repositoryPath),
          ].sort(compareText),
        ),
        attributes: sortedSources.flatMap((source) => {
          const nodeId = createPathNodeId(source.repositoryPath);
          const evidenceId = `evidence:source:${source.repositoryPath}`;
          return [
            {
              id: createAttributeId(nodeId, "dev.topo.source.lines"),
              subject: { kind: "node" as const, id: nodeId },
              key: "dev.topo.source.lines",
              value: source.lines,
              provenance: provenance([evidenceId]),
              evidenceIds: [evidenceId],
              confidence: 1,
              witnesses: [
                {
                  nodeId,
                  fingerprint: source.fingerprint,
                  relationship: "self" as const,
                },
              ],
            },
          ];
        }),
        evidence: [...evidence.values()].sort((left, right) =>
          compareText(left.id, right.id),
        ),
        extensions: {
          "dev.topo.scanner": scannerExtension,
        },
      });
      serializeGraphDocument(graph);
      const logicalArchitecture = await extractLogicalArchitecture({
        root: options.root,
        graphId: graph.graphId,
        graph,
        authoritative,
        ...(options.revision ? { revision: options.revision } : {}),
        sources: sortedSources,
        ...(options.responsibilityFile ? { responsibilityFile: options.responsibilityFile } : {}),
      });
      return { graph, logicalArchitecture, diagnostics, metrics, authoritative };
    }
    
    export function createTypeScriptScannerAdapter(): ScannerAdapter {
      return {
        manifest: TYPESCRIPT_SCANNER_MANIFEST,
        scan(options: unknown) {
          return scanRepository(parseScanRepositoryOptions(options));
        },
      };
    }
    
  • @topo/schema Open Dependency context by role: Schema contractsOpen Dependency context by role: JSON validationOpen Dependency context by role: Build, test, docsOpen Dependency context by role: Development tools

    Defines graph/artifact types, JSON schemas, validation, stable IDs, canonical serialization and compatibility rules. All declared internal dependencies (not runtime calls): No matching declarations. Referenced by internal modules: @topo/languages -> @topo/schema [dependencies: workspace:*] @topo/scanner -> @topo/schema [dependencies: workspace:*] @topo/reports -> @topo/schema [dependencies: workspace:*] @topo/cli -> @topo/schema [dependencies: workspace:*] @topo/views -> @topo/schema [dependencies: workspace:*] @topo/site -> @topo/schema [dependencies: workspace:*] @topo/workspace -> @topo/schema [dependencies: workspace:*] @topo/modules -> @topo/schema [dependencies: workspace:*] @topo/enrichment -> @topo/schema [dependencies: workspace:*] @topo/graph -> @topo/schema [dependencies: workspace:*] Stable drilldown identity: schema. Module-specific detail maps will be curated later; there is no placeholder target.

    packages/schema/package.json:1-34
    {
      "name": "@topo/schema",
      "version": "0.0.0",
      "private": true,
      "type": "module",
      "files": [
        "dist",
        "graph.schema.json"
      ],
      "exports": {
        ".": {
          "types": "./dist/index.d.ts",
          "default": "./dist/index.js"
        },
        "./graph.schema.json": "./graph.schema.json"
      },
      "scripts": {
        "build": "node scripts/generate-validator.mjs --check && tsc -b && node scripts/smoke-validator.mjs",
        "schema:generate": "node scripts/generate-validator.mjs",
        "schema:check": "node scripts/generate-validator.mjs --check",
        "typecheck": "node scripts/generate-validator.mjs --check && tsc -b --pretty false",
        "test": "node scripts/generate-validator.mjs --check && vitest run"
      },
      "dependencies": {
        "ajv": "8.17.1",
        "ajv-formats": "3.0.1"
      },
      "devDependencies": {
        "@types/node": "^22",
        "typescript": "^7.0.2",
        "vite": "8.2.2",
        "vitest": "^5.0.0"
      }
    }
    
    packages/schema/src/index.ts:1-10
    export * from "./canonical.js";
    export * from "./compatibility.js";
    export * from "./factories.js";
    export * from "./ids.js";
    export * from "./json.js";
    export * from "./layout.js";
    export * from "./logical-architecture.js";
    export * from "./model.js";
    export * from "./schema.js";
    export * from "./validation.js";
    
  • @topo/reports Open Dependency context by role: Build, test, docsOpen Dependency context by role: Development tools

    Parses normalized reports, checks them against graph evidence, and produces dashboard artifacts. All declared internal dependencies (not runtime calls): @topo/reports -> @topo/schema [dependencies: workspace:*] Referenced by internal modules: @topo/cli -> @topo/reports [dependencies: workspace:*] Stable drilldown identity: reports. Module-specific detail maps will be curated later; there is no placeholder target.

    packages/reports/package.json:1-26
    {
      "name": "@topo/reports",
      "version": "0.0.0",
      "private": true,
      "type": "module",
      "exports": {
        ".": {
          "types": "./dist/index.d.ts",
          "default": "./dist/index.js"
        }
      },
      "scripts": {
        "build": "tsc -b",
        "typecheck": "tsc -b --pretty false",
        "test": "vitest run"
      },
      "dependencies": {
        "@topo/schema": "workspace:*"
      },
      "devDependencies": {
        "@types/node": "^22.20.1",
        "typescript": "^7.0.2",
        "vite": "8.2.2",
        "vitest": "^5.0.0"
      }
    }
    
    packages/reports/src/index.ts:1-197
    import { createHash } from "node:crypto";
    import { normalizeRepositoryPath, serializeJson, type GraphDocument, type JsonValue } from "@topo/schema";
    
    export interface ReportSource {
      id: string;
      tool: string;
      adapterVersion: string;
      repositoryId: string;
      revision: string;
      collectedAt: string;
    }
    
    export interface ReportMetric {
      path: string;
      key: string;
      value: number;
      unit: "count" | "percent" | "ratio" | "milliseconds";
    }
    
    export interface ReportFinding {
      id: string;
      path: string;
      severity: "info" | "warning" | "error";
      message: string;
    }
    
    export interface ReportDocument {
      schemaVersion: "1.0";
      id: string;
      source: ReportSource;
      configuration: Record<string, JsonValue>;
      metrics: ReportMetric[];
      findings: ReportFinding[];
    }
    
    export interface DashboardDocument {
      schemaVersion: "1.0";
      repositoryId: string;
      revision: string;
      inputs: Array<{ id: string; source: ReportSource; configuration: Record<string, JsonValue>; fingerprint: string }>;
      metrics: Array<ReportMetric & { reportId: string; sourceId: string; nodeId: string; provenance: "observed" }>;
      findings: Array<ReportFinding & { reportId: string; sourceId: string; nodeId: string; provenance: "observed" }>;
    }
    
    function object(value: unknown, label: string, keys: string[]): Record<string, unknown> {
      if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error(`${label} must be an object`);
      if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) {
        throw new Error(`${label} must be a plain JSON object`);
      }
      const record = value as Record<string, unknown>;
      const extra = Object.keys(record).filter((key) => !keys.includes(key));
      if (extra.length) throw new Error(`${label} has unknown keys: ${extra.join(", ")}`);
      return record;
    }
    
    function text(value: unknown, label: string): string {
      if (typeof value !== "string" || !value.trim()) throw new Error(`${label} must be a nonempty string`);
      return value;
    }
    
    function path(value: unknown): string {
      const input = text(value, "Report path");
      if (/^[a-z]:/i.test(input) || input.includes("\0")) throw new Error("Report paths must be repository-relative");
      const normalized = normalizeRepositoryPath(input);
      if (normalized.split("/").some((part) => !part || part === ".")) throw new Error("Report paths must be canonical");
      return normalized;
    }
    
    function json(value: unknown): JsonValue {
      if (value === null || typeof value === "string" || typeof value === "boolean") return value;
      if (typeof value === "number" && Number.isFinite(value)) return value;
      if (Array.isArray(value)) return value.map(json);
      if (typeof value === "object" && value !== null) {
        if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) {
          throw new Error("Report configuration must contain only plain JSON objects");
        }
        return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, json(item)]));
      }
      throw new Error("Report configuration must contain only finite JSON values");
    }
    
    function array(value: unknown, label: string): unknown[] {
      if (!Array.isArray(value)) throw new Error(`${label} must be an array`);
      return value;
    }
    
    function compare(left: string, right: string): number {
      return left < right ? -1 : left > right ? 1 : 0;
    }
    
    export function parseReport(input: unknown): ReportDocument {
      const value = object(input, "Report", ["schemaVersion", "id", "source", "configuration", "metrics", "findings"]);
      if (value.schemaVersion !== "1.0") throw new Error(`Unsupported report schema version: ${String(value.schemaVersion)}`);
      const sourceValue = object(value.source, "Report source", ["id", "tool", "adapterVersion", "repositoryId", "revision", "collectedAt"]);
      const source: ReportSource = {
        id: text(sourceValue.id, "Source id"),
        tool: text(sourceValue.tool, "Source tool"),
        adapterVersion: text(sourceValue.adapterVersion, "Adapter version"),
        repositoryId: text(sourceValue.repositoryId, "Repository id"),
        revision: text(sourceValue.revision, "Source revision"),
        collectedAt: text(sourceValue.collectedAt, "Collection time"),
      };
      if (!/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(?:\.\d{3})?Z$/.test(source.collectedAt) ||
          !Number.isFinite(Date.parse(source.collectedAt)) ||
          new Date(source.collectedAt).toISOString().replace(".000Z", "Z") !== source.collectedAt.replace(".000Z", "Z")) {
        throw new Error("Collection time must be an ISO UTC timestamp");
      }
      const configuration = json(object(value.configuration, "Report configuration", Object.keys(
        typeof value.configuration === "object" && value.configuration !== null ? value.configuration : {},
      )));
      if (typeof configuration !== "object" || configuration === null || Array.isArray(configuration)) {
        throw new Error("Report configuration must be an object");
      }
      const metrics = array(value.metrics, "Report metrics").map((inputMetric): ReportMetric => {
        const metric = object(inputMetric, "Metric", ["path", "key", "value", "unit"]);
        const metricPath = path(metric.path);
        const key = text(metric.key, "Metric key");
        if (typeof metric.value !== "number" || !Number.isFinite(metric.value)) throw new Error(`Metric ${key} must be finite`);
        const unit = metric.unit;
        if (unit !== "count" && unit !== "percent" && unit !== "ratio" && unit !== "milliseconds") throw new Error(`Unsupported unit: ${String(unit)}`);
        if (metric.value < 0 || (unit === "percent" && metric.value > 100) || (unit === "ratio" && metric.value > 1) ||
            (unit === "count" && !Number.isSafeInteger(metric.value))) throw new Error(`Metric ${key} is outside its unit range`);
        return { path: metricPath, key, value: metric.value, unit };
      }).sort((a, b) => compare(`${a.path}\0${a.key}`, `${b.path}\0${b.key}`));
      const findings = array(value.findings, "Report findings").map((inputFinding): ReportFinding => {
        const finding = object(inputFinding, "Finding", ["id", "path", "severity", "message"]);
        const severity = finding.severity;
        if (severity !== "info" && severity !== "warning" && severity !== "error") throw new Error("Invalid finding severity");
        return { id: text(finding.id, "Finding id"), path: path(finding.path), severity, message: text(finding.message, "Finding message") };
      }).sort((a, b) => compare(a.id, b.id));
      if (new Set(metrics.map((metric) => `${metric.path}\0${metric.key}`)).size !== metrics.length) throw new Error("Duplicate report metric");
      if (new Set(findings.map((finding) => finding.id)).size !== findings.length) throw new Error("Duplicate report finding");
      return { schemaVersion: "1.0", id: text(value.id, "Report id"), source, configuration, metrics, findings };
    }
    
    export function serializeReport(report: ReportDocument): string {
      return serializeJson(reportJson(parseReport(report)));
    }
    
    function reportJson(report: ReportDocument): JsonValue {
      return {
        ...report,
        source: { ...report.source },
        metrics: report.metrics.map((metric) => ({ ...metric })),
        findings: report.findings.map((finding) => ({ ...finding })),
      };
    }
    
    export function normalizeReports(inputs: unknown[], graph: GraphDocument): DashboardDocument {
      if (!inputs.length) throw new Error("At least one report is required");
      const revision = graph.repository.revision;
      if (!revision) throw new Error("Report ingestion requires a versioned repository revision");
      const reports = new Map<string, { report: ReportDocument; fingerprint: string }>();
      const nodesByPath = new Map(graph.nodes.filter((node) => node.identity.kind === "path").map((node) => [node.identity.value, node.id]));
      for (const input of inputs) {
        const report = parseReport(input);
        if (report.source.repositoryId !== graph.repository.id) throw new Error(`Report ${report.id} belongs to another repository`);
        if (report.source.revision !== revision) throw new Error(`Stale report ${report.id}: expected revision ${revision}, received ${report.source.revision}`);
        const fingerprint = createHash("sha256").update(serializeReport(report)).digest("hex");
        const prior = reports.get(report.id);
        if (prior && prior.fingerprint !== fingerprint) throw new Error(`Conflicting report id: ${report.id}`);
        reports.set(report.id, { report, fingerprint });
      }
      const dashboard: DashboardDocument = {
        schemaVersion: "1.0", repositoryId: graph.repository.id, revision, inputs: [], metrics: [], findings: [],
      };
      const metricEvidence = new Map<string, { value: number; unit: ReportMetric["unit"]; reportId: string }>();
      for (const { report, fingerprint } of [...reports.values()].sort((a, b) => compare(a.report.id, b.report.id))) {
        dashboard.inputs.push({ id: report.id, source: { ...report.source }, configuration: report.configuration, fingerprint });
        for (const metric of report.metrics) {
          const nodeId = nodesByPath.get(metric.path);
          if (!nodeId) throw new Error(`Report ${report.id} references unscanned file ${metric.path}`);
          const key = `${metric.path}\0${metric.key}`;
          const prior = metricEvidence.get(key);
          if (prior && (prior.value !== metric.value || prior.unit !== metric.unit)) {
            throw new Error(`Conflicting sources for ${metric.path} ${metric.key}: reports ${prior.reportId} and ${report.id}`);
          }
          metricEvidence.set(key, { value: metric.value, unit: metric.unit, reportId: report.id });
          dashboard.metrics.push({ ...metric, reportId: report.id, sourceId: report.source.id, nodeId, provenance: "observed" });
        }
        for (const finding of report.findings) {
          const nodeId = nodesByPath.get(finding.path);
          if (!nodeId) throw new Error(`Report ${report.id} references unscanned file ${finding.path}`);
          dashboard.findings.push({ ...finding, reportId: report.id, sourceId: report.source.id, nodeId, provenance: "observed" });
        }
      }
      return dashboard;
    }
    
    export function serializeDashboard(dashboard: DashboardDocument): string {
      return serializeJson({
        ...dashboard,
        inputs: dashboard.inputs.map((input) => ({ ...input, source: { ...input.source } })),
        metrics: dashboard.metrics.map((metric) => ({ ...metric })),
        findings: dashboard.findings.map((finding) => ({ ...finding })),
      });
    }
    
  • @topo/cli Open @topo/cli: public surfaceOpen Dependency context by role: Build, test, docsOpen Dependency context by role: Development toolsOpen @topo/diagram-core: public surface: @topo/cliOpen From idea to architecture: Topocode CLI

    Implements init, scan, story validation/preview, serving, bundling, ingestion, and explicit enrichment; generates Home and story navigation. All declared internal dependencies (not runtime calls): @topo/cli -> @topo/diagram-core [dependencies: workspace:*] @topo/cli -> @topo/enrichment [dependencies: workspace:*] @topo/cli -> @topo/graph [dependencies: workspace:*] @topo/cli -> @topo/languages [dependencies: workspace:*] @topo/cli -> @topo/modules [dependencies: workspace:*] @topo/cli -> @topo/reports [dependencies: workspace:*] @topo/cli -> @topo/scanner [dependencies: workspace:*] @topo/cli -> @topo/schema [dependencies: workspace:*] @topo/cli -> @topo/site [dependencies: workspace:*] @topo/cli -> @topo/story [dependencies: workspace:*] @topo/cli -> @topo/views [dependencies: workspace:*] @topo/cli -> @topo/workspace [dependencies: workspace:*] Referenced by internal modules: No matching declarations. Stable drilldown identity: cli. Open this module's public-surface diagram to inspect its exposed interfaces and references.

    packages/cli/package.json:1-40
    {
      "name": "@topo/cli",
      "version": "0.0.0",
      "private": true,
      "type": "module",
      "bin": {
        "topo": "./dist/main.js"
      },
      "exports": {
        ".": {
          "types": "./dist/index.d.ts",
          "default": "./dist/index.js"
        }
      },
      "scripts": {
        "build": "tsc -b && node ../../scripts/package-skills.mjs",
        "typecheck": "tsc -b --pretty false",
        "test": "vitest run --no-file-parallelism"
      },
      "dependencies": {
        "@topo/diagram-core": "workspace:*",
        "@topo/enrichment": "workspace:*",
        "@topo/graph": "workspace:*",
        "@topo/languages": "workspace:*",
        "@topo/modules": "workspace:*",
        "@topo/reports": "workspace:*",
        "@topo/scanner": "workspace:*",
        "@topo/schema": "workspace:*",
        "@topo/site": "workspace:*",
        "@topo/story": "workspace:*",
        "@topo/views": "workspace:*",
        "@topo/workspace": "workspace:*"
      },
      "devDependencies": {
        "@types/node": "^22.20.1",
        "typescript": "^7.0.2",
        "vite": "8.2.2",
        "vitest": "^5.0.0"
      }
    }
    
    packages/cli/src/main.ts:1-289
    #!/usr/bin/env node
    import { dirname, resolve } from "node:path";
    import { readFile, readdir, stat } from "node:fs/promises";
    import { fileURLToPath, pathToFileURL } from "node:url";
    import { parseArgs } from "node:util";
    import { BUILTIN_MODULE_MANIFESTS, validateModuleCatalog } from "@topo/modules";
    import { initializeWorkspace, isMissing, workspacePath } from "@topo/workspace";
    import { runEnrichment } from "./enrichment.js";
    import { bundleSite } from "./bundle.js";
    import { generateArtifacts, ingestReports } from "./pipeline.js";
    import { serveSite } from "./server.js";
    import {
      assertCatalogueCurrent,
      buildCatalogue,
      initializeSite,
      writeBuiltCatalogue,
    } from "./catalogue.js";
    import { validateStory } from "./story-validation.js";
    import { prepareProjectSkills } from "./skills.js";
    
    const HELP = `Topocode: local, deterministic repository maps
    
      topo init [repository] [--skills]
      topo scan [repository] [--allow-partial] [--responsibilities path]
      topo ingest <repository> <report.json> [more.json ...]
      topo enrich [repository]
      topo preview <repository> <story>
      topo story validate <repository> <story>
      topo story preview <repository> <story>
      topo serve [repository] [--port 4173]
      topo bundle [repository] [--output directory] [--base-path /path/]
    
    Requires a Git repository and Node.js 22 or newer.
    Scan is strict by default. --allow-partial publishes a visibly incomplete
    preview and exits 2; it never turns partial evidence into success.
    Serve binds only to 127.0.0.1. Config and authored metadata are never overwritten.
    Init creates a ready-to-serve diagram home without scanning or opening a browser.
    Scan adds repository exploration; story preview refreshes all committed stories.
    `;
    
    async function siteAssets(): Promise<string> {
      const assets = dirname(fileURLToPath(import.meta.resolve("@topo/site/notices")));
      try {
        await Promise.all(["LICENSE.txt", "THIRD_PARTY_NOTICES.txt"].map((name) => readFile(resolve(assets, name))));
      } catch (error) {
        if (!isMissing(error)) throw error;
        throw new Error("Built site license notices are missing; rebuild the Topocode checkout or reinstall @jdylanmc/topo-code.");
      }
      return assets;
    }
    
    export function validateConfiguredModules(modules: readonly string[]): void {
      validateModuleCatalog(BUILTIN_MODULE_MANIFESTS);
      const duplicates = modules.filter((id, index) => modules.indexOf(id) !== index);
      if (duplicates.length) {
        throw new Error(`Duplicate configured modules: ${[...new Set(duplicates)].join(", ")}`);
      }
      const builtins = new Set<string>(BUILTIN_MODULE_MANIFESTS.map((manifest) => manifest.id));
      const unknown = modules.filter((id) => !builtins.has(id));
      if (unknown.length) throw new Error(`Unknown configured modules: ${unknown.join(", ")}`);
    }
    
    export async function runCli(args: string[]): Promise<number> {
      const { positionals, values } = parseArgs({
        args,
        allowPositionals: true,
        options: {
          help: { type: "boolean", short: "h" },
          skills: { type: "boolean" },
          port: { type: "string" },
          "allow-partial": { type: "boolean" },
          responsibilities: { type: "string" },
          output: { type: "string" },
          "base-path": { type: "string" },
        },
      });
      const primaryCommand = positionals[0] ?? "help";
      const command = primaryCommand === "story"
        ? `story-${positionals[1] ?? ""}`
        : primaryCommand;
      if (values.help || command === "help") {
        console.log(HELP);
        return 0;
      }
      if (![
        "init",
        "scan",
        "ingest",
        "enrich",
        "preview",
        "serve",
        "bundle",
        "story-validate",
        "story-preview",
      ].includes(command)) {
        throw new Error(`Unknown command: ${positionals.slice(0, 2).join(" ")}`);
      }
      if (values.port !== undefined && command !== "serve") throw new Error("--port is only valid with serve");
      if (values.skills !== undefined && command !== "init") throw new Error("--skills is only valid with init");
      if (values.output !== undefined && command !== "bundle") throw new Error("--output is only valid with bundle");
      if (values["base-path"] !== undefined && command !== "bundle") throw new Error("--base-path is only valid with bundle");
      if (values["allow-partial"] !== undefined && command !== "scan") throw new Error("--allow-partial is only valid with scan");
      if (values.responsibilities !== undefined && command !== "scan") throw new Error("--responsibilities is only valid with scan");
      const storyCommand = command === "story-validate" || command === "story-preview";
      if (
        (!["ingest", "preview"].includes(command) && !storyCommand && positionals.length > 2) ||
        (storyCommand && positionals.length > 4)
      ) {
        throw new Error(`Too many arguments for ${primaryCommand}`);
      }
      const root = resolve(positionals[storyCommand ? 2 : 1] ?? ".");
      if (command === "init") {
        const installSkills = values.skills ? await prepareProjectSkills(root) : undefined;
        const assets = await siteAssets();
        const result = await initializeWorkspace(root);
        await initializeSite(root, assets);
        if (installSkills) console.log(`Installed ${await installSkills()} project skill/instruction files (identical files preserved).`);
        console.log(`${result.created ? "Initialized" : "Preserved"} ${root}/.topo`);
        console.log(`Site ready; run topo serve "${root}"`);
        return 0;
      }
      if (command === "serve") {
        if (values.port !== undefined && !/^\d+$/.test(values.port)) throw new Error("--port must be a nonnegative integer");
        const { server, url } = await serveSite(root, values.port === undefined ? 4173 : Number(values.port));
        console.log(`Topocode: ${url}`);
        let stopping = false;
        const stop = () => {
          if (stopping) return;
          stopping = true;
          server.close((error) => {
            if (error) { console.error(error.message); process.exitCode = 1; }
          });
          server.closeAllConnections();
        };
        process.once("SIGINT", stop);
        process.once("SIGTERM", stop);
        return 0;
      }
      if (command === "bundle") {
        const output = values.output === undefined
          ? await workspacePath(root, "bundle")
          : resolve(values.output);
        const result = await bundleSite(root, output, {
          ...(values["base-path"] === undefined
            ? {}
            : { basePath: values["base-path"] }),
        });
        console.log(
          `Bundled static site in ${result.siteDirectory} for ${result.basePath}`,
        );
        return 0;
      }
      if (command === "story-validate") {
        if (positionals.length !== 4) {
          throw new Error(
            "story validate requires a repository and one story document",
          );
        }
        const result = await validateStory(root, resolve(positionals[3]!));
        console.log(
          `Validated ${result.documentPath} (${result.document.id}) against ${result.source.revision}${result.source.dirty ? " with working tree changes" : ""}`,
        );
        for (const anchor of result.anchors) {
          console.log(
            `  ${anchor.id}: ${anchor.path}:${anchor.location.startLine}-${anchor.location.endLine}`,
          );
        }
        console.warn(
          "Structural and anchor validation does not establish semantic accuracy or complete explanation coverage.",
        );
        return 0;
      }
      if (command === "preview" || command === "story-preview") {
        const documentIndex = storyCommand ? 3 : 2;
        if (positionals.length !== (storyCommand ? 4 : 3)) {
          throw new Error(
            `${primaryCommand === "story" ? "story preview" : "preview"} requires a repository and one story document`,
          );
        }
        try {
          if (!(await stat(await workspacePath(root, "cache/site/index.html"))).isFile()) {
            throw new Error("Site index is not a file; repair the generated site before preview");
          }
        } catch (error) {
          if (!isMissing(error)) throw error;
          throw new Error("Site is not initialized; run topo init first");
        }
        const catalogue = await buildCatalogue(root);
        const requested = resolve(positionals[documentIndex]!);
        const selected = catalogue.stories.find(
          (story) => resolve(root, story.documentPath) === requested,
        );
        if (selected === undefined) {
          throw new Error("preview requires a committed story under stories/");
        }
        const { config } = await initializeWorkspace(root);
        await writeBuiltCatalogue(
          root,
          catalogue,
          { title: config.repositoryId, ...config.catalogue },
        );
        if (catalogue.source.dirty) {
          console.warn(
            "Rendering against uncommitted source changes; anchors describe the working tree, not only HEAD.",
          );
        }
        console.log(
          `Rendered ${selected.documentPath} with ${selected.renderer.name} (${selected.renderer.pin})`,
        );
        console.log(
          `Story generated at ${await workspacePath(root, `cache/site/stories/${selected.document.id}/index.html`)}; run topo serve "${root}" and open /stories/${selected.document.id}/`,
        );
        return 0;
      }
      if (command === "enrich") {
        const controller = new AbortController();
        const abort = () => controller.abort();
        process.once("SIGINT", abort);
        process.once("SIGTERM", abort);
        try {
          const result = await runEnrichment(root, { signal: controller.signal });
          console.log(`Enriched analysis ${result.analysisHash}; ${result.comments} comments`);
          return 0;
        } finally {
          process.removeListener("SIGINT", abort);
          process.removeListener("SIGTERM", abort);
        }
      }
      const { config } = await initializeWorkspace(root);
      validateConfiguredModules(config.modules);
      const assets = await siteAssets();
      const catalogue = await buildCatalogue(root);
      const state = catalogue.source;
      if (command === "ingest") {
        if (positionals.length < 3) throw new Error("ingest requires a repository and at least one report file");
        if (state.dirty) throw new Error("Report ingestion requires clean source files at the scanned revision; .topo artifacts are excluded.");
        const result = await ingestReports(
          root,
          positionals.slice(2).map((path) => resolve(path)),
          assets,
          state.revision,
          catalogue,
        );
        for (const warning of result.warnings) console.warn(warning);
        console.log(`Ingested ${result.dashboard.inputs.length} reports; ${result.dashboard.metrics.length} metrics, ${result.dashboard.findings.length} findings`);
        return 0;
      }
      if (state.dirty) {
        console.warn("Scanning uncommitted source changes; node fingerprints describe the working tree, not only HEAD.");
        if ((await readdir(await workspacePath(root, "reports/inputs"))).some((name) => name.endsWith(".json"))) {
          throw new Error("Persisted revision-bound reports cannot be applied to dirty source; commit changes or move stale inputs first.");
        }
      }
      const start = performance.now();
      const { scanProject } = await import("@topo/languages");
      const result = await scanProject({
        root, repositoryId: config.repositoryId, revision: state.revision,
        quality: { allowPartial: values["allow-partial"] ?? false },
        ...(values.responsibilities ? { responsibilityFile: resolve(values.responsibilities) } : {}),
      }, config.analysis);
      await assertCatalogueCurrent(root, catalogue);
      const artifacts = await generateArtifacts(
        root,
        result.graph,
        assets,
        result.logicalArchitecture,
        catalogue,
      );
      for (const diagnostic of result.diagnostics) console.warn(`${diagnostic.severity}: ${diagnostic.code}: ${diagnostic.message}`);
      for (const warning of artifacts.layout.warnings) console.warn(`layout: ${warning.code}: ${warning.message}`);
      for (const warning of artifacts.warnings) console.warn(warning);
      console.log(`${result.authoritative ? "Scanned" : "PARTIAL PREVIEW:"} ${result.metrics.sourceFileCount} files, ${result.graph.edges.length} edges, ${result.metrics.linesOfCode} lines in ${((performance.now() - start) / 1000).toFixed(2)}s`);
      console.log(`Site generated in ${root}/.topo/cache/site; run topo serve "${root}"`);
      return result.authoritative ? 0 : 2;
    }
    
    export function describeError(error: unknown): string {
      const message = error instanceof Error ? error.message : String(error);
      if (typeof error !== "object" || error === null) return message;
      const details = "diagnostics" in error ? error.diagnostics : "issues" in error ? error.issues : undefined;
      return Array.isArray(details) ? `${message}\n${details.map((item: unknown) => JSON.stringify(item)).join("\n")}` : message;
    }
    
    if (process.argv[1] && pathToFileURL(resolve(process.argv[1])).href === import.meta.url) {
      runCli(process.argv.slice(2)).then((code) => { process.exitCode = code; }).catch((error: unknown) => {
        console.error(`Topocode: ${describeError(error)}`);
        process.exitCode = 1;
      });
    }
    
  • @topo/diagram-core Open @topo/diagram-core: public surfaceOpen @topo/cli: public surface: @topo/diagram-coreOpen Dependency context by role: RenderingOpen Dependency context by role: Archify and GraphvizOpen Dependency context by role: Build, test, docsOpen Dependency context by role: Development tools

    Adapts source-grounded stories to the pinned Archify renderer or explicit Graphviz backend; owns renderer integrity, output adaptation, and viewer theme/export behavior. All declared internal dependencies (not runtime calls): @topo/diagram-core -> @topo/story [dependencies: workspace:*] Referenced by internal modules: @topo/cli -> @topo/diagram-core [dependencies: workspace:*] @topo/site -> @topo/diagram-core [devDependencies: workspace:*] Stable drilldown identity: diagram-core. Open this module's public-surface diagram to inspect its exposed interfaces and references.

    packages/diagram-core/package.json:1-34
    {
      "name": "@topo/diagram-core",
      "version": "0.0.0",
      "private": true,
      "type": "module",
      "files": [
        "dist",
        "archify-pin.json",
        "LICENSE",
        "THIRD_PARTY_NOTICES.md"
      ],
      "exports": {
        ".": {
          "types": "./dist/index.d.ts",
          "default": "./dist/index.js"
        }
      },
      "scripts": {
        "build": "tsc -b",
        "typecheck": "tsc -b --pretty false",
        "test": "tsc -b && node --test test/*.test.mjs"
      },
      "dependencies": {
        "@topo/story": "workspace:*",
        "@viz-js/viz": "3.30.0"
      },
      "peerDependencies": {
        "@jdylanmc/topo-archify": "0.1.0"
      },
      "devDependencies": {
        "@types/node": "^22",
        "typescript": "^7.0.2"
      }
    }
    
    packages/diagram-core/src/index.ts:1-1708
    import { execFileSync } from "node:child_process";
    import { createHash } from "node:crypto";
    import {
      mkdtempSync,
      readFileSync,
      rmSync,
      writeFileSync,
    } from "node:fs";
    import { tmpdir } from "node:os";
    import path from "node:path";
    import { fileURLToPath } from "node:url";
    import type {
      ResolvedStoryDocument,
      StoryArtifact,
      StoryConnection,
      StoryDocument,
    } from "@topo/story";
    import { cliPath as archifyCli } from "@jdylanmc/topo-archify";
    import { verifyArchifyIntegrity } from "./integrity.js";
    import { adaptViewerTheme, outputHash } from "./theme.js";
    import { renderGraphviz } from "./graphviz.js";
    import { componentId } from "./node-ids.js";
    export { CORE_THEME_SCRIPT } from "./theme.js";
    export { storyNodeIds } from "./node-ids.js";
    
    export {
      verifyArchifyIntegrity,
      type ArchifyIntegrity,
    } from "./integrity.js";
    
    interface ArchifySource {
      readonly path: string;
      readonly line?: number;
      readonly end_line?: number;
    }
    
    interface ArchifyComponent {
      readonly id: string;
      readonly type: "backend" | "frontend";
      readonly label: string;
      readonly sublabel: string;
      readonly pos: readonly [number, number];
      readonly size: readonly [number, number];
      readonly sources?: readonly ArchifySource[];
    }
    
    interface ArchifyArchitecture {
      readonly schema_version: 1;
      readonly diagram_type: "architecture";
      readonly meta: {
        readonly title: string;
        readonly quality_profile: "standard";
        readonly locale: "en";
        readonly viewBox: readonly [number, number];
        readonly legend: { readonly mode: "hidden" };
        readonly repository?: {
          readonly url: string;
          readonly revision: string;
          readonly link_mode?: "local-only";
        };
      };
      readonly components: readonly ArchifyComponent[];
      readonly connections: readonly {
        readonly id: string;
        readonly from: string;
        readonly to: string;
        readonly label?: string;
        readonly labelAt?: readonly [number, number];
        readonly labelDx?: number;
        readonly labelDy?: number;
        readonly labelSegment?: number;
        readonly fromSide?: "left" | "right" | "top" | "bottom";
        readonly toSide?: "left" | "right" | "top" | "bottom";
        readonly via?: readonly (readonly [number, number])[];
      }[];
    }
    
    interface ArchifyWorkflow {
      readonly schema_version: 2;
      readonly diagram_type: "workflow";
      readonly meta: {
        readonly title: string;
        readonly quality_profile: "standard";
        readonly locale: "en";
        readonly legend: { readonly mode: "hidden" };
      };
      readonly lanes: readonly {
        readonly id: string;
        readonly label: string;
      }[];
      readonly nodes: readonly {
        readonly id: string;
        readonly lane: string;
        readonly col: number;
        readonly type: "backend" | "frontend";
        readonly label: string;
        readonly sublabel: string;
        readonly width: number;
        readonly height: number;
        readonly yOffset: number;
      }[];
      readonly edges: readonly {
        readonly id: string;
        readonly from: string;
        readonly to: string;
        readonly label?: string;
        readonly labelDx?: number;
        readonly labelDy?: number;
        readonly role: "main";
      }[];
    }
    
    interface ArchifySequence {
      readonly schema_version: 1;
      readonly diagram_type: "sequence";
      readonly meta: {
        readonly title: string;
        readonly quality_profile: "standard";
        readonly locale: "en";
        readonly legend: { readonly mode: "hidden" };
        readonly column_fit: "spread";
        readonly viewBox: readonly [number, number];
      };
      readonly participants: readonly {
        readonly id: string;
        readonly type: "backend" | "frontend";
        readonly label: string;
        readonly sublabel: string;
      }[];
      readonly messages: readonly {
        readonly id: string;
        readonly from: string;
        readonly to: string;
        readonly y: number;
        readonly label: string;
        readonly variant?: "return";
      }[];
    }
    
    interface ArchifyDataflow {
      readonly schema_version: 1;
      readonly diagram_type: "dataflow";
      readonly meta: {
        readonly title: string;
        readonly quality_profile: "standard";
        readonly locale: "en";
        readonly viewBox: readonly [number, number];
        readonly legend: { readonly mode: "hidden" };
      };
      readonly stages: readonly {
        readonly label: string;
      }[];
      readonly nodes: readonly {
        readonly id: string;
        readonly type: "backend" | "frontend";
        readonly label: string;
        readonly sublabel: string;
        readonly stage: number;
        readonly row: number;
        readonly width: number;
      }[];
      readonly flows: readonly {
        readonly id: string;
        readonly from: string;
        readonly to: string;
        readonly label: string;
        readonly labelDy?: number;
      }[];
    }
    
    interface ArchifyLifecycle {
      readonly schema_version: 1;
      readonly diagram_type: "lifecycle";
      readonly meta: {
        readonly title: string;
        readonly quality_profile: "standard";
        readonly locale: "en";
        readonly legend: { readonly mode: "hidden" };
      };
      readonly lanes: readonly {
        readonly id: string;
        readonly label: string;
      }[];
      readonly states: readonly {
        readonly id: string;
        readonly type: "start" | "active" | "success";
        readonly label: string;
        readonly lane: "main" | "event" | "terminal";
        readonly col: number;
        readonly width: number;
      }[];
      readonly transitions: readonly {
        readonly id: string;
        readonly from: string;
        readonly to: string;
        readonly label?: string;
        readonly labelDy?: number;
        readonly route?: "right-channel";
      }[];
    }
    
    const architectureFontSize = 24;
    // The pinned renderer measures 8px monospace labels at 0.6em per text unit;
    // authored Architecture CSS scales the same glyphs to 24px.
    const architectureLabelAscent = 25;
    const architectureLabelDescent = 7;
    
    function architectureLabelUnits(label: string): number {
      return Array.from(label).reduce(
        (units, character) =>
          units + ((character.codePointAt(0) ?? 0) > 0xff ? 2 : 1),
        0,
      );
    }
    
    function architectureLabelWidth(label: string): number {
      const units = architectureLabelUnits(label);
      return Math.max(
        30,
        units * 4.8 + 10,
        units * architectureFontSize * 0.6,
      );
    }
    
    const sequenceReadability = {
      minimumViewBoxWidth: 480,
      minimumViewBoxHeight: 480,
      messageStartY: 180,
      minimumMessageSpacing: 28,
      timelineBottomPadding: 83,
      sideMargin: 62,
      participantGapAllowance: 24,
      minimumParticipantGap: 108,
      rightMargin: 40,
      maximumParticipantWidth: 190,
      minimumParticipantWidth: 86,
      nativeLabelWidthFactor: 6.8,
      nativeLabelTolerance: 6,
      textHorizontalPadding: 8,
      textWidthFactor: 0.6,
      targetEffectiveFontSize: 12,
      maximumNativeFontSize: 13,
      viewerBodyHorizontalPadding: 64,
      compactViewerDiagramPadding: 32,
      regularViewerDiagramPadding: 48,
      compactViewerMaximumHeight: 920,
      maximumReaderWidth: 1440,
      supportedViewports: [
        [1024, 768],
        [1280, 720],
        [1440, 900],
        [1600, 1000],
        [1920, 1080],
      ],
    } as const;
    
    interface SequenceLayout {
      readonly viewBox: readonly [number, number];
      readonly fontSize: number;
      readonly participantWidth: number;
      readonly inlineBodyIds: ReadonlySet<string>;
      readonly messageYs: readonly number[];
    }
    
    function stableId(prefix: string, value: string): string {
      const hash = createHash("sha256").update(value).digest("hex").slice(0, 16);
      return `${prefix}_${hash}`;
    }
    
    // Match the pinned renderer's text-unit model before deciding whether prose
    // can remain inline at the final readable font size.
    const fullwidthCharacter =
      /[\u1100-\u115F\u231A-\u231B\u2329-\u232A\u23E9-\u23EC\u23F0\u23F3\u25FD-\u25FE\u2614-\u2615\u2630-\u2637\u2648-\u2653\u267F\u268A-\u268F\u2693\u26A1\u26AA-\u26AB\u26BD-\u26BE\u26C4-\u26C5\u26CE\u26D4\u26EA\u26F2-\u26F3\u26F5\u26FA\u26FD\u2705\u270A-\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B-\u2B1C\u2B50\u2B55\u2E80-\uA4CF\uA960-\uA97C\uAC00-\uD7A3\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE6F\uFF01-\uFF60\uFFE0-\uFFE6\u{16FE0}-\u{18DFF}\u{1AFF0}-\u{1AFFF}\u{1B000}-\u{1B2FF}\u{1F000}-\u{1FAFF}\u{20000}-\u{3FFFD}]/u;
    
    function sequenceTextUnits(text: string): number {
      const characters = Array.from(text);
      let units = 0;
      for (let index = 0; index < characters.length; index += 1) {
        const codePoint = characters[index]!.codePointAt(0)!;
        if (codePoint >= 0xfe00 && codePoint <= 0xfe0f) continue;
        const next = characters[index + 1]?.codePointAt(0) ?? -1;
        if (next === 0xfe0f) units += 2;
        else if (next === 0xfe0e) units += 1;
        else units += fullwidthCharacter.test(characters[index]!) ? 2 : 1;
      }
      return units;
    }
    
    function requiredSequenceParticipantWidth(text: string): number {
      return Math.ceil(
        sequenceTextUnits(text) * sequenceReadability.nativeLabelWidthFactor -
          sequenceReadability.nativeLabelTolerance,
      );
    }
    
    function fittedSequenceFontSize(text: string, width: number): number {
      const units = Math.max(1, sequenceTextUnits(text));
      const available = Math.max(
        1,
        width - sequenceReadability.textHorizontalPadding,
      );
      return Math.floor(
        Math.min(
            sequenceReadability.maximumNativeFontSize,
            available / (units * sequenceReadability.textWidthFactor),
          ) * 10,
      ) / 10;
    }
    
    function sequenceLayout(story: ResolvedStoryDocument): SequenceLayout {
      const participantCount = Math.max(1, story.document.sections.length);
      const requiredParticipantWidth = Math.min(
        sequenceReadability.maximumParticipantWidth,
        Math.max(
          sequenceReadability.minimumParticipantWidth,
          ...story.document.sections.map(({ title }) =>
            requiredSequenceParticipantWidth(title)
          ),
        ),
      );
      const viewBoxWidth = Math.max(
        sequenceReadability.minimumViewBoxWidth,
        participantCount *
            (requiredParticipantWidth +
              sequenceReadability.participantGapAllowance) +
          sequenceReadability.sideMargin * 2,
        sequenceReadability.sideMargin +
          requiredParticipantWidth +
          (participantCount - 1) * (story.document.sequenceLayout?.minimumParticipantGap ?? sequenceReadability.minimumParticipantGap) +
          sequenceReadability.rightMargin,
      );
      const messageYs = story.document.connections.map((_, index) =>
        sequenceReadability.messageStartY +
        index * sequenceReadability.minimumMessageSpacing
      );
      const lastMessageY = messageYs.at(-1) ??
        sequenceReadability.messageStartY;
      const viewBox = [
        viewBoxWidth,
        Math.max(
          sequenceReadability.minimumViewBoxHeight,
          lastMessageY + sequenceReadability.timelineBottomPadding,
        ),
      ] as const;
      const minimumScale = Math.min(
        ...sequenceReadability.supportedViewports.map(([width, height]) => {
          const readerWidth = Math.min(
            width - sequenceReadability.viewerBodyHorizontalPadding,
            sequenceReadability.maximumReaderWidth,
          );
          const diagramPadding =
            height <= sequenceReadability.compactViewerMaximumHeight
              ? sequenceReadability.compactViewerDiagramPadding
              : sequenceReadability.regularViewerDiagramPadding;
          return Math.min(
            (readerWidth - diagramPadding) / viewBox[0],
            height / viewBox[1],
          );
        }),
      );
      const fontSize = Math.ceil(
        sequenceReadability.targetEffectiveFontSize / minimumScale * 10,
      ) / 10;
      if (fontSize > sequenceReadability.maximumNativeFontSize) {
        throw new Error(
          `Sequence story requires ${fontSize}px native text to remain ` +
            `${sequenceReadability.targetEffectiveFontSize}px effective across ` +
            "supported viewports; reduce the message count or split the story",
        );
      }
    
      const participantWidth = Math.max(
        sequenceReadability.minimumParticipantWidth,
        Math.min(
          sequenceReadability.maximumParticipantWidth,
          Math.round(
              (viewBox[0] - sequenceReadability.sideMargin * 2) /
                participantCount,
            ) - sequenceReadability.participantGapAllowance,
        ),
      );
      const inlineBodyIds = new Set<string>();
      for (const section of story.document.sections) {
        if (fittedSequenceFontSize(section.title, participantWidth) < fontSize) {
          throw new Error(
            `Sequence participant "${section.title}" cannot fit inside its ` +
              `${participantWidth}px box at the ${fontSize}px native font ` +
              `required for ${sequenceReadability.targetEffectiveFontSize}px ` +
              "effective text",
          );
        }
        if (fittedSequenceFontSize(section.body, participantWidth) >= fontSize) {
          inlineBodyIds.add(section.id);
        }
      }
    
      return {
        viewBox,
        fontSize,
        participantWidth,
        inlineBodyIds,
        messageYs,
      };
    }
    
    function escapeHtml(value: string): string {
      return value
        .replaceAll("&", "&amp;")
        .replaceAll("<", "&lt;")
        .replaceAll(">", "&gt;")
        .replaceAll('"', "&quot;");
    }
    
    function addSequenceNarrativeDetails(
      contents: string,
      story: ResolvedStoryDocument,
      layout: SequenceLayout,
    ): string {
      let result = contents;
      for (const section of story.document.sections) {
        if (layout.inlineBodyIds.has(section.id)) continue;
        const id = componentId(section.id);
        const marker = `data-node-id="${id}"`;
        const markerIndex = result.indexOf(marker);
        const tagStart = result.lastIndexOf("<g ", markerIndex);
        const tagEnd = result.indexOf(">", markerIndex);
        if (markerIndex < 0 || tagStart < 0 || tagEnd < 0) {
          throw new Error(
            `Archify sequence output is missing participant "${section.id}"`,
          );
        }
    
        const body = escapeHtml(section.body);
        const openTag = result.slice(tagStart, tagEnd);
        const labelledTag = openTag.replace(
          / aria-label="([^"]*)"/,
          (_, label: string) => ` aria-label="${label}, ${body}"`,
        );
        if (labelledTag === openTag) {
          throw new Error(
            `Archify sequence output is missing participant label "${section.id}"`,
          );
        }
        result = result.slice(0, tagStart) +
          `${labelledTag} data-node-sublabel="${body}"` +
          result.slice(tagEnd);
    
        const titleStart = result.indexOf("<title>", tagEnd);
        const titleEnd = result.indexOf("</title>", titleStart);
        if (titleStart < 0 || titleEnd < 0) {
          throw new Error(
            `Archify sequence output is missing participant title "${section.id}"`,
          );
        }
        const titleContentsStart = titleStart + "<title>".length;
        result = result.slice(0, titleContentsStart) +
          `${result.slice(titleContentsStart, titleEnd)} · ${body}` +
          result.slice(titleEnd);
      }
      return result;
    }
    
    function repositoryMetadata(repositoryRoot: string): {
      readonly url: string;
      readonly link_mode?: "local-only";
    } {
      try {
        const url = execFileSync(
          "git",
          ["-C", repositoryRoot, "remote", "get-url", "origin"],
          { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] },
        ).trim();
        if (url) return { url };
      } catch {
        // Let Archify report its repository-evidence requirement consistently.
      }
      return {
        url: "https://localhost.invalid/repository",
        link_mode: "local-only",
      };
    }
    
    export function architectureComponentWidth(
      title: string,
      sublabel = "",
      finalTypography = false,
    ): number {
      const units = Array.from(title).reduce(
        (total, character) => total + (character.codePointAt(0)! > 127 ? 2 : 1), 0,
      );
      const titleWidth = finalTypography ? units * 24 * 0.6 : title.length * 11;
      return Math.max(280, titleWidth + 80, sublabel.length * 9 + 80);
    }
    
    function archifySpec(
      story: ResolvedStoryDocument,
      nativeSourceEvidence = true,
    ): ArchifyArchitecture {
      const anchors = new Map(story.anchors.map((anchor) => [anchor.id, anchor]));
      const componentIds = new Map(
        story.document.sections.map((section) => [
          section.id,
          componentId(section.id),
        ]),
      );
      const sections = story.document.sections;
      const resolved = sections.map((section) => {
        const sectionAnchors = section.anchorIds
          .map((anchorId) => anchors.get(anchorId))
          .filter((anchor): anchor is NonNullable<typeof anchor> => anchor !== undefined);
        const primary = sectionAnchors[0];
        // Short, legible sublabel (a code reference), never the full narrative body:
        // Archify enforces a per-component minimum-legibility width.
        const sublabel = section.summary ?? (primary === undefined || !nativeSourceEvidence
          ? ""
          : primary.symbol ?? primary.path.split("/").pop() ?? primary.path);
        const width = architectureComponentWidth(section.title, sublabel, !nativeSourceEvidence);
        return { section, sectionAnchors, sublabel, width };
      });
      // Balance components across rows of at most four, then snake each row so
      // consecutive sections stay adjacent without producing a tall column.
      const maxRowSize = sections.length >= 10 ? 4 : 3;
      const rowCount = Math.max(1, Math.ceil(sections.length / maxRowSize));
      const shortRowSize = Math.floor(sections.length / rowCount);
      const longRowCount = sections.length % rowCount;
      const rowSizes = Array.from(
        { length: rowCount },
        (_, row) => shortRowSize + (row < longRowCount ? 1 : 0),
      );
      const baseBoxWidth = Math.max(280, ...resolved.map((entry) => entry.width));
      const boxHeight = 130;
      const columnGap = 90;
      const cellOf = (index: number) => {
        let row = 0;
        let rowStart = 0;
        while (index >= rowStart + rowSizes[row]!) {
          rowStart += rowSizes[row]!;
          row += 1;
        }
        const rowSize = rowSizes[row]!;
        const positionInRow = index - rowStart;
        // Reverse odd rows so the sequence snakes and stays adjacent at the wrap.
        const column = row % 2 === 0 ? positionInRow : rowSize - 1 - positionInRow;
        return { row, column };
      };
      const sectionIndexById = new Map(
        sections.map((section, index) => [section.id, index]),
      );
      // Plan label and route corridors before placing rows so shared gaps reserve
      // only the space their realized content and detours require.
      const sharedGapConnections = new Map<number, number[]>();
      const crossRowRouteGaps = new Set<number>();
      const detourLaneByConnection = new Map<number, number>();
      let detourLaneCount = 0;
      let hasBottomOuterLabels = false;
      for (
        const [connectionIndex, connection] of
          story.document.connections.entries()
      ) {
        const fromIndex = sectionIndexById.get(connection.from)!;
        const toIndex = sectionIndexById.get(connection.to)!;
        const from = cellOf(fromIndex);
        const to = cellOf(toIndex);
        const neighbouringDiagonal = Math.abs(to.row - from.row) === 1 &&
          Math.abs(to.column - from.column) === 1;
        if (
          Math.abs(to.row - from.row) +
              Math.abs(to.column - from.column) !==
            1 && !neighbouringDiagonal
        ) {
          detourLaneByConnection.set(connectionIndex, detourLaneCount);
          detourLaneCount += 1;
        }
        for (
          let gap = Math.min(from.row, to.row);
          gap < Math.max(from.row, to.row);
          gap += 1
        ) {
          crossRowRouteGaps.add(gap);
        }
        if (connection.label === undefined) continue;
        const deltaColumn = to.column - from.column;
        if (from.row !== to.row || Math.abs(deltaColumn) !== 1) continue;
        const gap = deltaColumn > 0 ? from.row : from.row - 1;
        if (gap === rowCount - 1) {
          hasBottomOuterLabels = true;
        }
        if (gap < 0 || gap >= rowCount - 1) continue;
        const connections = sharedGapConnections.get(gap) ?? [];
        connections.push(connectionIndex);
        sharedGapConnections.set(gap, connections);
      }
      const sharedGapLaneByConnection = new Map(
        [...sharedGapConnections.entries()].flatMap(([gap, connections]) =>
          connections.map((connectionIndex, lane) => [
            connectionIndex,
            { gap, lane },
          ] as const)
        ),
      );
      const labelLaneStep =
        architectureLabelAscent + architectureLabelDescent + 1;
      const labelCorridorPadding = 2;
      const routeCorridorBand = 8;
      const requiredRowGap = Math.max(
        0,
        ...[...sharedGapConnections.entries()].map(([gap, connections]) =>
          labelCorridorPadding * 2 +
          architectureLabelAscent +
          architectureLabelDescent +
          (connections.length - 1) * labelLaneStep +
          (crossRowRouteGaps.has(gap) ? routeCorridorBand : 0)
        ),
      );
      const rowGap = Math.max(
        80,
        requiredRowGap,
      );
      const maxSharedLabelWidth = Math.max(
        0,
        ...[...sharedGapLaneByConnection.keys()].map((connectionIndex) =>
          architectureLabelWidth(
            story.document.connections[connectionIndex]!.label!,
          )
        ),
      );
      const maxConnectionLabelWidth = Math.max(
        0,
        ...story.document.connections.flatMap((connection) =>
          connection.label === undefined
            ? []
            : [architectureLabelWidth(connection.label)]
        ),
      );
      const boxWidth = Math.max(
        baseBoxWidth,
        Math.ceil(maxSharedLabelWidth + labelCorridorPadding * 2),
      );
      const margin = Math.max(
        80,
        Math.ceil(maxConnectionLabelWidth / 2 + labelCorridorPadding),
      );
      const components = resolved.map(({ section, sectionAnchors, sublabel }, index) => {
        const { row, column } = cellOf(index);
        return {
          id: componentIds.get(section.id)!,
          type: "backend" as const,
          label: section.title,
          sublabel,
          pos: [
            margin + column * (boxWidth + columnGap),
            margin + row * (boxHeight + rowGap),
          ] as const,
          size: [boxWidth, boxHeight] as const,
          ...(sectionAnchors.length === 0 || !nativeSourceEvidence
            ? {}
            : {
                // Native cards allow three links; the story wrapper retains every
                // validated anchor and its excerpt in the full evidence panel.
                sources: sectionAnchors.slice(0, 3).map((anchor) => ({
                  path: anchor.path,
                  line: anchor.location.startLine,
                  end_line: anchor.location.endLine,
                })),
              }),
        };
      });
      const gridBottom = margin + rowCount * boxHeight + (rowCount - 1) * rowGap;
      const laneBase = gridBottom +
        (hasBottomOuterLabels
          ? rowGap / 2 +
            architectureLabelAscent +
            architectureLabelDescent +
            4
          : 60);
      const laneGap = 40;
      const widestRow = Math.max(...rowSizes);
      const gridRight =
        margin + widestRow * boxWidth + (widestRow - 1) * columnGap;
      const gapRouteCorridors = new Map<number, Set<number>>();
      for (const connection of story.document.connections) {
        const fromIndex = sectionIndexById.get(connection.from)!;
        const toIndex = sectionIndexById.get(connection.to)!;
        const from = cellOf(fromIndex);
        const to = cellOf(toIndex);
        if (from.row === to.row) continue;
        const fromX = components[fromIndex]!.pos[0] + boxWidth / 2;
        const toX = components[toIndex]!.pos[0] + boxWidth / 2;
        for (
          let gap = Math.min(from.row, to.row);
          gap < Math.max(from.row, to.row);
          gap += 1
        ) {
          const corridors = gapRouteCorridors.get(gap) ?? new Set<number>();
          corridors.add(fromX);
          corridors.add(toX);
          gapRouteCorridors.set(gap, corridors);
        }
      }
      const sharedGapLabelX = (
        connectionIndex: number,
        gap: number,
      ): number => {
        const connection = story.document.connections[connectionIndex]!;
        const fromIndex = sectionIndexById.get(connection.from)!;
        const sourceX = components[fromIndex]!.pos[0] + boxWidth / 2;
        const width = architectureLabelWidth(connection.label!);
        const routeClearance = 12;
        const corridorXs = [...(gapRouteCorridors.get(gap) ?? [])]
          .sort((left, right) => left - right);
        const intervals: [number, number][] = [];
        let left = margin / 2;
        for (const corridorX of corridorXs) {
          intervals.push([left, corridorX - routeClearance]);
          left = corridorX + routeClearance;
        }
        intervals.push([left, gridRight + margin / 2]);
        const candidates = intervals.flatMap(([intervalLeft, intervalRight]) => {
          const minCenter = intervalLeft + width / 2;
          const maxCenter = intervalRight - width / 2;
          if (minCenter > maxCenter) return [];
          return [Math.min(maxCenter, Math.max(minCenter, sourceX))];
        });
        if (candidates.length === 0) {
          throw new Error(
            `Architecture label "${connection.label}" cannot fit a clear row-gap corridor.`,
          );
        }
        return candidates.reduce((best, candidate) =>
          Math.abs(candidate - sourceX) < Math.abs(best - sourceX)
            ? candidate
            : best
        );
      };
      const viewBoxWidth = Math.max(
        800,
        gridRight + margin,
      );
      const viewBoxHeight = Math.max(
        500,
        gridBottom + margin,
        laneBase + Math.max(0, detourLaneCount - 1) * laneGap + margin,
      );
      return {
        schema_version: 1,
        diagram_type: "architecture",
        meta: {
          title: story.document.title,
          quality_profile: "standard",
          locale: "en",
          viewBox: [viewBoxWidth, viewBoxHeight],
          legend: { mode: "hidden" },
          ...(story.document.classification === "capability-demo" || !nativeSourceEvidence
            ? {}
            : {
                repository: {
                  ...repositoryMetadata(story.repositoryRoot),
                  revision: story.source.revision,
                },
              }),
        },
        components,
        // Neighbouring cells use native routing and port spreading. Distant
        // endpoints retain outside lanes to avoid unrelated nodes.
        connections: story.document.connections.map((connection, index) => {
          const fromIndex = sections.findIndex((s) => s.id === connection.from);
          const toIndex = sections.findIndex((s) => s.id === connection.to);
          const from = cellOf(fromIndex);
          const to = cellOf(toIndex);
          const deltaRow = to.row - from.row;
          const deltaColumn = to.column - from.column;
          const base = {
            id: stableId(
              "connection",
              `${index}\0${connection.from}\0${connection.to}`,
            ),
            from: componentIds.get(connection.from)!,
            to: componentIds.get(connection.to)!,
            ...(connection.label === undefined ? {} : { label: connection.label }),
          };
          const adjacent = Math.abs(deltaRow) + Math.abs(deltaColumn) === 1;
          if (Math.abs(deltaRow) === 1 && Math.abs(deltaColumn) === 1) {
            return base;
          }
          if (adjacent) {
            const vertical = deltaRow !== 0;
            const horizontalLabelBelow = deltaColumn > 0;
            const sharedGapLane = sharedGapLaneByConnection.get(index);
            return {
              ...base,
              ...(vertical
                ? { labelDy: deltaRow > 0 ? 40 : -24 }
                : sharedGapLane === undefined
                ? {
                    labelDy: horizontalLabelBelow
                      ? boxHeight / 2 + rowGap / 2
                      : -(boxHeight / 2 + rowGap / 2),
                  }
                : {
                    labelAt: [
                      sharedGapLabelX(index, sharedGapLane.gap),
                      margin +
                        sharedGapLane.gap * (boxHeight + rowGap) +
                        boxHeight +
                        (crossRowRouteGaps.has(sharedGapLane.gap)
                          ? routeCorridorBand
                          : 0) +
                        labelCorridorPadding +
                        architectureLabelAscent +
                        sharedGapLane.lane * labelLaneStep,
                    ] as const,
                  }),
              fromSide: vertical
                ? (deltaRow > 0 ? "bottom" as const : "top" as const)
                : (deltaColumn > 0 ? "right" as const : "left" as const),
              toSide: vertical
                ? (deltaRow > 0 ? "top" as const : "bottom" as const)
                : (deltaColumn > 0 ? "left" as const : "right" as const),
            };
          }
          const fromX = components[fromIndex]!.pos[0] + boxWidth / 2;
          const toX = components[toIndex]!.pos[0] + boxWidth / 2;
          const lane =
            laneBase + detourLaneByConnection.get(index)! * laneGap;
          const blockedBelow = (endpointIndex: number) => {
            const endpoint = cellOf(endpointIndex);
            return sections.some((_, candidateIndex) => {
              if (candidateIndex === endpointIndex) return false;
              const candidate = cellOf(candidateIndex);
              return candidate.column === endpoint.column &&
                candidate.row > endpoint.row;
            });
          };
          const outside = (column: number) =>
            column < widestRow / 2 ? margin / 2 : gridRight + margin / 2;
          const upperCorridor = (endpointIndex: number) => {
            const endpoint = cellOf(endpointIndex);
            if (endpoint.row === 0) return margin / 2;
            return margin +
              endpoint.row * (boxHeight + rowGap) -
              rowGap +
              routeCorridorBand / 2;
          };
          const fromBlocked = blockedBelow(fromIndex);
          const toBlocked = blockedBelow(toIndex);
          const fromOutside = outside(from.column);
          const toOutside = outside(to.column);
          const fromUpperCorridor = upperCorridor(fromIndex);
          const toUpperCorridor = upperCorridor(toIndex);
          return {
            ...base,
            fromSide: fromBlocked
              ? "top" as const
              : "bottom" as const,
            toSide: toBlocked
              ? "top" as const
              : "bottom" as const,
            via: [
              ...(fromBlocked
                ? [
                    [fromX, fromUpperCorridor],
                    [fromOutside, fromUpperCorridor],
                    [fromOutside, lane],
                  ] as const
                : [[fromX, lane]] as const),
              ...(toBlocked
                ? [
                    [toOutside, lane],
                    [toOutside, toUpperCorridor],
                    [toX, toUpperCorridor],
                  ] as const
                : [[toX, lane]] as const),
            ],
            labelSegment: fromBlocked ? 3 : 1,
          };
        }),
      };
    }
    
    function workflowSpec(story: ResolvedStoryDocument): ArchifyWorkflow {
      const laneId = "story-flow";
      const columns = 2;
      const rows = Math.ceil(story.document.sections.length / columns);
      const cellOf = (index: number) => {
        const row = Math.floor(index / columns);
        const position = index % columns;
        return {
          row,
          col: row % 2 === 0 ? position : columns - 1 - position,
        };
      };
      const nodeIds = new Map(
        story.document.sections.map((section) => [
          section.id,
          componentId(section.id),
        ]),
      );
      return {
        schema_version: 2,
        diagram_type: "workflow",
        meta: {
          title: story.document.title,
          quality_profile: "standard",
          locale: "en",
          legend: { mode: "hidden" },
        },
        lanes: [{ id: laneId, label: story.document.title }],
        nodes: story.document.sections.map((section, index) => {
          const { row, col } = cellOf(index);
          return {
            id: nodeIds.get(section.id)!,
            lane: laneId,
            col,
            type: index === story.document.sections.length - 1
              ? "frontend"
              : "backend",
            label: section.title,
            sublabel: "",
            width: Math.max(
              128,
              section.title.length * 7 + 24,
            ),
            height: 96,
            yOffset: (row - (rows - 1) / 2) * 160,
          };
        }),
        edges: story.document.connections.map((connection, index) => {
          const fromIndex = story.document.sections.findIndex(
            (section) => section.id === connection.from,
          );
          const toIndex = story.document.sections.findIndex(
            (section) => section.id === connection.to,
          );
          const from = cellOf(fromIndex);
          const to = cellOf(toIndex);
          return {
            id: stableId(
              "edge",
              `${index}\0${connection.from}\0${connection.to}`,
            ),
            from: nodeIds.get(connection.from)!,
            to: nodeIds.get(connection.to)!,
            ...(connection.label === undefined ? {} : { label: connection.label }),
            ...(from.col === to.col
              ? { labelDx: from.col === 0 ? -180 : 180 }
              : { labelDy: 72 }),
            role: "main",
          };
        }),
      };
    }
    
    function requiredConnectionLabel(
      connection: StoryConnection,
      family: "sequence" | "dataflow",
    ): string {
      if (connection.label === undefined) {
        throw new Error(`${family} connections require a nonempty label`);
      }
      return connection.label;
    }
    
    function sequenceSpec(
      story: ResolvedStoryDocument,
      layout: SequenceLayout,
    ): ArchifySequence {
      const participantIds = new Map(
        story.document.sections.map((section) => [
          section.id,
          componentId(section.id),
        ]),
      );
      return {
        schema_version: 1,
        diagram_type: "sequence",
        meta: {
          title: story.document.title,
          quality_profile: "standard",
          locale: "en",
          legend: { mode: "hidden" },
          column_fit: "spread",
          viewBox: layout.viewBox,
        },
        participants: story.document.sections.map((section) => ({
          id: participantIds.get(section.id)!,
          type: "backend",
          label: section.title,
          sublabel: layout.inlineBodyIds.has(section.id) ? section.body : "",
        })),
        messages: story.document.connections.map((connection, index) => ({
          id: stableId(
            "message",
            `${index}\0${connection.from}\0${connection.to}`,
          ),
          from: participantIds.get(connection.from)!,
          to: participantIds.get(connection.to)!,
          y: layout.messageYs[index]!,
          label: requiredConnectionLabel(connection, "sequence"),
          ...(connection.variant === undefined
            ? {}
            : { variant: connection.variant }),
        })),
      };
    }
    
    const dataflowReadability = {
      maximumFontSize: 15,
      minimumFontSize: 6,
      fontSizePrecision: 10,
      widthFactor: 0.6,
      horizontalPadding: 8,
      defaultNodeWidth: 112,
      firstNodeMaximumWidth: 152,
      stageCenterGap: 215,
      minimumNodeGap: 10,
      firstStageCenterX: 100,
      stageWidth: 168,
      viewBoxMargin: 24,
      minimumViewBoxWidth: 360,
      viewBoxHeight: 360,
      flowLabelHorizontalPadding: 12,
      minimumFlowLabelWidth: 34,
      nativeFlowLabelWidthFactor: 4.9,
      flowLabelMaskBaselineTop: 11,
      flowLabelMaskBaselineBottom: 5,
      flowLabelFontAscentPadding: 1,
      flowLabelClearanceDy: 53,
    } as const;
    
    function dataflowTextUnits(value: string): number {
      return Array.from(value).reduce(
        (total, character) =>
          total + (character.codePointAt(0)! > 0xff ? 2 : 1),
        0,
      );
    }
    
    function dataflowNodeWidth(
      label: string,
      sublabel: string,
      fontSize: number,
    ): number {
      const units = Math.max(
        dataflowTextUnits(label),
        dataflowTextUnits(sublabel),
      );
      return Math.max(
        dataflowReadability.defaultNodeWidth,
        Math.ceil(
          units * fontSize *
            dataflowReadability.widthFactor +
            dataflowReadability.horizontalPadding,
        ),
      );
    }
    
    interface DataflowLayout {
      readonly fontSize: number;
      readonly nodeWidths: readonly number[];
      readonly flowLabelWidths: readonly number[];
      readonly viewBox: readonly [number, number];
    }
    
    function dataflowFlowLabelWidth(label: string, fontSize: number): number {
      return Math.max(
        dataflowReadability.minimumFlowLabelWidth,
        Math.ceil(
          (
            dataflowTextUnits(label) *
              fontSize *
              dataflowReadability.widthFactor +
            dataflowReadability.flowLabelHorizontalPadding
          ) * dataflowReadability.fontSizePrecision,
        ) / dataflowReadability.fontSizePrecision,
      );
    }
    
    function dataflowNativeFlowLabelWidth(label: string): number {
      return Math.round(
        Math.max(
          dataflowReadability.minimumFlowLabelWidth,
          dataflowTextUnits(label) *
              dataflowReadability.nativeFlowLabelWidthFactor +
            dataflowReadability.flowLabelHorizontalPadding,
        ) * dataflowReadability.fontSizePrecision,
      ) / dataflowReadability.fontSizePrecision;
    }
    
    function dataflowFlowLabelMaskTop(fontSize: number): number {
      return Math.max(
        dataflowReadability.flowLabelMaskBaselineTop,
        Math.ceil(
          fontSize + dataflowReadability.flowLabelFontAscentPadding,
        ),
      );
    }
    
    function dataflowLayout(story: ResolvedStoryDocument): DataflowLayout {
      const sections = story.document.sections;
      const minimumTenths = dataflowReadability.minimumFontSize *
        dataflowReadability.fontSizePrecision;
      const maximumTenths = dataflowReadability.maximumFontSize *
        dataflowReadability.fontSizePrecision;
      let selected:
        | { readonly fontSize: number; readonly nodeWidths: readonly number[] }
        | undefined;
    
      for (let tenths = maximumTenths; tenths >= minimumTenths; tenths -= 1) {
        const fontSize = tenths / dataflowReadability.fontSizePrecision;
        const nodeWidths = sections.map((section) =>
          dataflowNodeWidth(section.title, section.body, fontSize)
        );
        const firstNodeFits =
          (nodeWidths[0] ?? dataflowReadability.defaultNodeWidth) <=
            dataflowReadability.firstNodeMaximumWidth;
        const adjacentNodesFit = nodeWidths.every((width, index) =>
          index === 0 ||
          (nodeWidths[index - 1]! + width) / 2 <=
            dataflowReadability.stageCenterGap -
              dataflowReadability.minimumNodeGap
        );
        if (firstNodeFits && adjacentNodesFit) {
          selected = { fontSize, nodeWidths };
          break;
        }
      }
    
      const fallbackFontSize = dataflowReadability.minimumFontSize;
      const fontSize = selected?.fontSize ?? fallbackFontSize;
      const nodeWidths = selected?.nodeWidths ?? sections.map((section) =>
        dataflowNodeWidth(section.title, section.body, fallbackFontSize)
      );
      const lastStageX = dataflowReadability.firstStageCenterX +
        Math.max(0, sections.length - 1) * dataflowReadability.stageCenterGap;
      const lastNodeWidth = nodeWidths.at(-1) ??
        dataflowReadability.defaultNodeWidth;
      const viewBoxWidth = Math.max(
        dataflowReadability.minimumViewBoxWidth,
        lastStageX + dataflowReadability.stageWidth / 2 +
          dataflowReadability.viewBoxMargin,
        lastStageX + lastNodeWidth / 2 + dataflowReadability.viewBoxMargin,
      );
    
      return {
        fontSize,
        nodeWidths,
        flowLabelWidths: story.document.connections.map((connection) =>
          dataflowFlowLabelWidth(
            requiredConnectionLabel(connection, "dataflow"),
            fontSize,
          )
        ),
        viewBox: [Math.ceil(viewBoxWidth), dataflowReadability.viewBoxHeight],
      };
    }
    
    function dataflowSpec(
      story: ResolvedStoryDocument,
      layout: DataflowLayout,
    ): ArchifyDataflow {
      const nodeIds = new Map(
        story.document.sections.map((section) => [
          section.id,
          componentId(section.id),
        ]),
      );
      return {
        schema_version: 1,
        diagram_type: "dataflow",
        meta: {
          title: story.document.title,
          quality_profile: "standard",
          locale: "en",
          viewBox: layout.viewBox,
          legend: { mode: "hidden" },
        },
        stages: story.document.sections.map((section) => ({
          label: section.title,
        })),
        nodes: story.document.sections.map((section, index) => ({
          id: nodeIds.get(section.id)!,
          type: index === story.document.sections.length - 1
            ? "frontend"
            : "backend",
          label: section.title,
          sublabel: section.body,
          stage: index,
          row: 0,
          width: layout.nodeWidths[index]!,
        })),
        flows: story.document.connections.map((connection, index) => {
          const fromIndex = story.document.sections.findIndex(
            (section) => section.id === connection.from,
          );
          const toIndex = story.document.sections.findIndex(
            (section) => section.id === connection.to,
          );
          const label = requiredConnectionLabel(connection, "dataflow");
          const endpointGap = Math.abs(toIndex - fromIndex) *
              dataflowReadability.stageCenterGap -
            (layout.nodeWidths[fromIndex]! + layout.nodeWidths[toIndex]!) / 2;
          const labelWidth = Math.max(
            layout.flowLabelWidths[index]!,
            dataflowNativeFlowLabelWidth(label),
          );
          return {
            id: stableId(
              "flow",
              `${index}\0${connection.from}\0${connection.to}`,
            ),
            from: nodeIds.get(connection.from)!,
            to: nodeIds.get(connection.to)!,
            label,
            ...(labelWidth > endpointGap
              ? {
                  labelDy: dataflowReadability.flowLabelClearanceDy +
                    dataflowFlowLabelMaskTop(layout.fontSize) -
                    dataflowReadability.flowLabelMaskBaselineTop,
                }
              : {}),
          };
        }),
      };
    }
    
    const lifecycleFontSize = 14.5;
    const lifecycleMinimumRouteLength = 32;
    
    function lifecycleSpec(story: ResolvedStoryDocument): ArchifyLifecycle {
      const stateDrafts = story.document.sections.map((section, index) => {
        const last = index === story.document.sections.length - 1;
        const event = story.document.sections.length >= 5 &&
          index >= 2 &&
          index < story.document.sections.length - 2;
        const lane = last ? "terminal" as const : event ? "event" as const : "main" as const;
        const defaultCol = last ? 2 : event ? index - 2 : index - Math.max(0, index - 2);
        return {
          section,
          index,
          lane,
          defaultCol,
          width: Math.max(
            118,
            Math.ceil(Array.from(section.title).reduce(
              (total, character) =>
                total + (character.codePointAt(0)! > 0xff ? 2 : 1),
              0,
            ) * lifecycleFontSize * 0.5 + 28),
          ),
        };
      });
      const placements = new Map<string, {
        lane: "main" | "event" | "terminal";
        col: number;
      }>();
      for (const lane of ["main", "event", "terminal"] as const) {
        const drafts = stateDrafts.filter((draft) => draft.lane === lane);
        const centers = lane === "main"
          ? [94, 248, 402, 556, 710]
          : [402, 556, 710];
        let best: { cols: number[]; score: number } | undefined;
        const search = (position: number, cols: number[], score: number) => {
          if (position === drafts.length) {
            if (
              best === undefined ||
              score < best.score ||
              (score === best.score && cols.join(",") < best.cols.join(","))
            ) {
              best = { cols: [...cols], score };
            }
            return;
          }
          const draft = drafts[position]!;
          for (let col = 0; col < centers.length; col += 1) {
            if (position > 0 && col <= cols[position - 1]!) continue;
            const center = centers[col]!;
            const left = center - draft.width / 2;
            const right = center + draft.width / 2;
            if (left < 32 || right > 948) continue;
            const overlaps = drafts.slice(0, position).some((other, otherIndex) => {
              const otherCenter = centers[cols[otherIndex]!]!;
              const otherRight = otherCenter + other.width / 2;
              return left - otherRight < lifecycleMinimumRouteLength;
            });
            if (overlaps) continue;
            search(
              position + 1,
              [...cols, col],
              score + Math.abs(col - draft.defaultCol),
            );
          }
        };
        search(0, [], 0);
        if (best === undefined) {
          throw new Error(
            `Lifecycle ${lane} states cannot fit the native columns without overlap`,
          );
        }
        drafts.forEach((draft, index) => {
          placements.set(draft.section.id, {
            lane,
            col: best!.cols[index]!,
          });
        });
      }
      const stateIds = new Map(
        story.document.sections.map((section) => [
          section.id,
          componentId(section.id),
        ]),
      );
      return {
        schema_version: 1,
        diagram_type: "lifecycle",
        meta: {
          title: story.document.title,
          quality_profile: "standard",
          locale: "en",
          legend: { mode: "hidden" },
        },
        lanes: [
          { id: "main", label: story.document.title },
          { id: "event", label: "Interruptions + recovery" },
          { id: "terminal", label: "Outcomes" },
        ],
        states: stateDrafts.map(({ section, index, width }) => {
          const last = index === story.document.sections.length - 1;
          return {
            id: stateIds.get(section.id)!,
            type: index === 0
              ? "start"
              : last
                ? "success"
                : "active",
            label: section.title,
            ...placements.get(section.id)!,
            width,
          };
        }),
        transitions: story.document.connections.map((connection, index) => {
          const fromIndex = story.document.sections.findIndex(
            (section) => section.id === connection.from,
          );
          const toIndex = story.document.sections.findIndex(
            (section) => section.id === connection.to,
          );
          return {
            id: stableId(
              "transition",
              `${index}\0${connection.from}\0${connection.to}`,
            ),
            from: stateIds.get(connection.from)!,
            to: stateIds.get(connection.to)!,
            ...(connection.label === undefined ? {} : { label: connection.label }),
            ...(placements.get(story.document.sections[fromIndex]!.id)!.lane ===
                placements.get(story.document.sections[toIndex]!.id)!.lane
              ? { labelDy: 55 }
              : {}),
            ...(index === story.document.connections.length - 1
              ? { route: "right-channel" as const }
              : {}),
          };
        }),
      };
    }
    
    function commandError(error: unknown): Error {
      if (
        typeof error === "object" &&
        error !== null &&
        "stdout" in error &&
        "stderr" in error
      ) {
        const stdout = String(error.stdout ?? "").trim();
        const stderr = String(error.stderr ?? "").trim();
        return new Error(
          ["Archify rendering failed", stderr, stdout].filter(Boolean).join(": "),
          { cause: error },
        );
      }
      return error instanceof Error
        ? error
        : new Error(`Archify rendering failed: ${String(error)}`);
    }
    
    function serializeRendererInput(spec: { readonly meta: object }): string {
      return `${JSON.stringify({
        ...spec,
        meta: { ...spec.meta, output: "story.html" },
      }, null, 2)}\n`;
    }
    
    function adaptStorySemantics(contents: string, document: StoryDocument): string {
      const fallback = document.diagramFamily === "sequence" ? "participant" : "component";
      const roles = new Map(document.sections.map(section => [componentId(section.id), section.semanticRole ?? fallback]));
      const summaries = new Set(document.sections
        .filter(section => section.summary !== undefined)
        .map(section => componentId(section.id)));
      const seen = new Set<string>();
      const adapted = contents.replace(/<g\b[^>]*\bdata-node-id="([^"]+)"[^>]*>/g, (tag, id: string) => {
        const role = roles.get(id);
        if (role === undefined) return tag;
        if (!/^(?!constructor$)[a-z][a-z0-9-]{0,63}$/.test(role)) throw new Error(`Invalid semantic role for ${id}`);
        if (!/\bdata-node-kind="[^"]*"/.test(tag)) throw new Error(`Story node ${id} has no semantic metadata`);
        seen.add(id);
        const annotated = tag.replace(/\bdata-node-kind="[^"]*"/, `data-node-kind="${role}"`);
        return summaries.has(id) ? annotated.replace("<g", '<g data-topo-caption="summary"') : annotated;
      });
      if (seen.size !== roles.size) throw new Error("Story semantic adaptation omitted an authored node");
      const replacements: readonly [RegExp, string][] = [
        [/(<strong\b[^>]*id="semantic-lens-title"[^>]*>)[^<]*(<\/strong>)/,
          "$1Compare responsibilities$2"],
        [/(<p\b[^>]*class="semantic-lens-instruction"[^>]*>)[^<]*(<\/p>)/,
          "$1Choose up to two authored roles. Highlight only the relationships drawn in this story: not runtime traffic, transitive impact, or the complete dependency graph. One role includes connected peers; two compare direct cross-role arrows.$2"],
      ];
      return replacements.reduce((html, [pattern, replacement]) => {
        if (!pattern.test(html)) throw new Error("Pinned semantic lens presentation seam is missing");
        return html.replace(pattern, replacement);
      }, adapted);
    }
    
    function improveStoryReadability(
      contents: string,
      family:
        | "architecture"
        | "workflow"
        | "sequence"
        | "dataflow"
        | "lifecycle",
      dataflowLayout?: DataflowLayout,
      sequence?: SequenceLayout,
    ): string {
      const headEnd = "</head>";
      if (!contents.includes(headEnd)) {
        throw new Error(`Archify ${family} output is missing its closing head element`);
      }
      if (family === "sequence" && sequence === undefined) throw new Error("Missing sequence readability layout");
      const sequenceRatio = sequence === undefined ? undefined : sequence.viewBox[0] / sequence.viewBox[1];
      const semanticControls = family === "architecture" || family === "sequence" ? `
    html[data-topo-app] .semantic-lens { width: min(34rem, calc(100% - 24px)); max-height: calc(100% - 16px); overflow: auto; }
    #semantic-lens-title { font-size: 1rem; }
    #semantic-lens .semantic-lens-instruction,
    #semantic-lens .semantic-lens-status,
    #semantic-lens .semantic-lens-actions button,
    #semantic-lens-kinds .semantic-lens-kind em { font-size: 0.8rem; line-height: 1.5; }
    #semantic-lens-kinds .semantic-lens-kind strong { font-size: 0.85rem; line-height: 1.4; white-space: normal; overflow: visible; overflow-wrap: anywhere; text-overflow: clip; }` : "";
      const rules = family === "architecture"
        ? `
    svg { max-height: 100vh; }
    /* The story shell supplies the node index and full source details. */
    .reader-rail { display: none !important; }
    svg [data-source-evidence-beacon] { display: none; }
    svg text[data-node-label],
    svg text[data-detail="context"],
    svg g[data-edge-from] > text { font-size: ${architectureFontSize}px; }
    /* Native caption baselines are only 16 units below titles. */
    svg text[data-detail="context"] { transform: translateY(20px); }
    svg [data-topo-caption="summary"] text[data-detail="context"] { font-size: 17px; transform: translateY(12px); }`
        : family === "workflow"
          ? `
    svg text[data-node-label],
    svg text[font-size="10"][font-weight="600"],
    svg g[data-edge-from] > text {
      font-family: ui-sans-serif, system-ui, sans-serif;
      font-size: 14px;
      font-weight: 600;
    }`
          : family === "sequence"
            ? `
    svg { max-height: 100vh; }
    .reader-rail { display: none !important; }
    @media (min-width: 1400px) and (min-height: 900px) {
      html[data-topo-app] .container {
        min-width: min(calc(100vw - 64px), ${sequence === undefined ? 0 : sequence.viewBox[0] * sequenceReadability.targetEffectiveFontSize / sequence.fontSize + 50}px);
        max-width: min(calc(100vw - 64px), calc((100dvh - 260px) * ${sequenceRatio} + 30px));
      }
    }
    @media (min-width: 1400px) and (min-height: 900px) and (max-height: 920px) {
      html[data-topo-app] .container { max-width: min(calc(100vw - 64px), calc((100dvh - 156px) * ${sequenceRatio} + 32px)); }
      html[data-topo-app] .diagram-container { padding-bottom: 56px; }
    }
    svg text {
      font-size: ${sequence?.fontSize}px;
    }
    .semantic-passport-detail {
      font-size: 0.875rem;
    }`
            : family === "dataflow"
              ? `
    svg text[data-node-label],
    svg text[data-detail="context"],
    svg text[font-size="9"][font-weight="600"],
    svg g[data-edge-from] > text {
      font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, 'DejaVu Sans Mono', 'Liberation Mono', 'Noto Sans Mono CJK SC', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', monospace;
      font-size: ${dataflowLayout?.fontSize ?? dataflowReadability.maximumFontSize}px;
      font-weight: 600;
    }`
              : `
    svg text[data-node-label],
    svg text[font-size="10"][font-weight="600"],
    svg g[data-edge-from] > text {
      font-family: Arial, Helvetica, sans-serif;
      font-size: ${lifecycleFontSize}px;
    }`;
      const style = `<style data-topo-story-readability>${rules}${semanticControls}
    </style>`;
      const adjustedContents = family === "dataflow" && dataflowLayout
        ? dataflowLayout.flowLabelWidths.reduce((html, width, index) => {
            const pattern = new RegExp(
              `(<g data-detail="context"[^>]*data-edge-key="${index}"[^>]*>\\s*<rect x=")(-?\\d+(?:\\.\\d+)?)(" y=")(-?\\d+(?:\\.\\d+)?)(" width=")(\\d+(?:\\.\\d+)?)(" height=")(\\d+(?:\\.\\d+)?)(" rx="4" class="c-mask"/>)`,
            );
            let replaced = false;
            const next = html.replace(
              pattern,
              (
                _match,
                prefix: string,
                xValue: string,
                yPrefix: string,
                yValue: string,
                widthPrefix: string,
                nativeWidthValue: string,
                heightPrefix: string,
                _nativeHeightValue: string,
                suffix: string,
              ) => {
                replaced = true;
                const nativeWidth = Number(nativeWidthValue);
                const center = Number(xValue) + nativeWidth / 2;
                const x = Math.round(
                  (center - width / 2) * dataflowReadability.fontSizePrecision,
                ) / dataflowReadability.fontSizePrecision;
                const baseline = Number(yValue) +
                  dataflowReadability.flowLabelMaskBaselineTop;
                const top = dataflowFlowLabelMaskTop(dataflowLayout.fontSize);
                const y = baseline - top;
                const height = top +
                  dataflowReadability.flowLabelMaskBaselineBottom;
                const [viewBoxWidth, viewBoxHeight] = dataflowLayout.viewBox;
                if (
                  ![x, y, width, height].every(Number.isFinite) ||
                  x < 0 ||
                  y < 0 ||
                  x + width > viewBoxWidth ||
                  y + height > viewBoxHeight
                ) {
                  throw new Error(
                    `Archify dataflow final flow label mask ${index} exceeds the ${viewBoxWidth}x${viewBoxHeight} viewBox`,
                  );
                }
                return `${prefix}${x}${yPrefix}${y}${widthPrefix}${width}${heightPrefix}${height}${suffix}`;
              },
            );
            if (!replaced) {
              throw new Error(
                `Archify dataflow output is missing flow label mask ${index}`,
              );
            }
            return next;
          }, contents)
        : contents;
      const accessibleContents = family === "architecture" || family === "sequence"
        ? adjustedContents.replace(/<svg\b[^>]*\brole="img"[^>]*>/, tag =>
            tag.replace('role="img"', 'role="group"').replace("<svg", `<svg data-topo-family="${family}"`))
        : adjustedContents;
      return accessibleContents.replace(headEnd, `${style}\n${headEnd}`);
    }
    
    export function renderArchitectureStories(
      stories: readonly ResolvedStoryDocument[],
      options: { readonly sourceEvidence?: "native" | "wrapper" } = {},
    ): StoryArtifact[] {
      return [...renderArchitectureStoryBatch(stories, options)];
    }
    
    export function* renderArchitectureStoryBatch(
      stories: readonly ResolvedStoryDocument[],
      options: { readonly sourceEvidence?: "native" | "wrapper" } = {},
    ): Generator<StoryArtifact> {
      const integrity = verifyArchifyIntegrity();
      if (stories.length === 0) return;
      const directory = mkdtempSync(path.join(tmpdir(), "topo-architecture-batch-"));
      try {
        const jobs = stories.map((story, index) => {
          if ((story.document.diagramFamily ?? "architecture") !== "architecture") {
            throw new Error("Architecture batch only accepts Architecture stories");
          }
          const input = path.join(directory, `${index}.json`);
          const output = path.join(directory, `${index}.html`);
          writeFileSync(input, serializeRendererInput(archifySpec(story, options.sourceEvidence !== "wrapper")));
          return { input, output, repository: story.repositoryRoot };
        });
        const manifest = path.join(directory, "batch.json");
        // Native entrypoints are ES modules: cache-busted evaluations retain their
        // HTML and compiled code until process exit. Bound that lifetime per chunk.
        for (let offset = 0; offset < jobs.length; offset += 32) {
          writeFileSync(manifest, JSON.stringify(jobs.slice(offset, offset + 32)));
          execFileSync(process.execPath, [
            fileURLToPath(new URL("./architecture-batch.js", import.meta.url)),
            manifest,
          ], { cwd: directory, encoding: "utf8", maxBuffer: 64 * 1024 * 1024, stdio: ["ignore", "pipe", "pipe"] });
        }
        for (const [index, { output }] of jobs.entries()) {
          const sourceContents = readFileSync(output, "utf8");
          const contents = adaptViewerTheme(adaptStorySemantics(
            improveStoryReadability(sourceContents, "architecture"), stories[index]!.document,
          ), stories[index]!.document, "archify");
          yield {
            kind: "html",
            mediaType: "text/html",
            contents,
            renderer: {
              name: "archify",
              pin: integrity.version,
              sha256: integrity.archiveSha256,
              sourceOutputSha256: outputHash(sourceContents),
              outputSha256: outputHash(contents),
              adaptation: "topocode-story-semantics-v2",
            },
          };
        }
      } catch (error) {
        throw commandError(error);
      } finally {
        rmSync(directory, { recursive: true, force: true });
      }
    }
    
    export function renderStory(story: ResolvedStoryDocument): StoryArtifact | Promise<StoryArtifact> {
      if (story.document.renderer === "graphviz") return renderGraphviz(story);
      const integrity = verifyArchifyIntegrity();
      const family = story.document.diagramFamily ?? "architecture";
      const adaptiveSequenceLayout = family === "sequence"
        ? sequenceLayout(story)
        : undefined;
      const adaptiveDataflowLayout = family === "dataflow"
        ? dataflowLayout(story)
        : undefined;
      const spec = family === "workflow"
        ? workflowSpec(story)
        : family === "sequence"
          ? sequenceSpec(story, adaptiveSequenceLayout!)
          : family === "dataflow"
            ? dataflowSpec(story, adaptiveDataflowLayout!)
            : family === "lifecycle"
              ? lifecycleSpec(story)
              : archifySpec(story);
      const temporaryDirectory = mkdtempSync(
        path.join(tmpdir(), "topo-archify-render-"),
      );
      const inputPath = path.join(temporaryDirectory, "story.json");
      const outputPath = path.join(temporaryDirectory, "story.html");
      try {
        writeFileSync(inputPath, serializeRendererInput(spec));
        const args = [
          archifyCli,
          "deliver",
          family,
          inputPath,
          outputPath,
          "--quality",
          "standard",
          "--json",
        ];
        if (
          family === "architecture" &&
          story.document.classification !== "capability-demo"
        ) {
          args.splice(5, 0, "--repo-root", story.repositoryRoot);
        }
        execFileSync(process.execPath, args, {
          cwd: temporaryDirectory,
          encoding: "utf8",
          maxBuffer: 32 * 1024 * 1024,
          stdio: ["ignore", "pipe", "pipe"],
        });
        const contents = family === "sequence"
          ? addSequenceNarrativeDetails(
            readFileSync(outputPath, "utf8"),
            story,
            adaptiveSequenceLayout!,
          )
          : readFileSync(outputPath, "utf8");
        const readable = improveStoryReadability(
          contents, family, adaptiveDataflowLayout, adaptiveSequenceLayout,
        );
        const adapted = adaptViewerTheme(family === "architecture" || family === "sequence"
          ? adaptStorySemantics(readable, story.document)
          : readable, story.document);
        return {
          kind: "html",
          mediaType: "text/html",
          contents: adapted,
          renderer: {
            name: "archify",
            pin: integrity.version,
            sha256: integrity.archiveSha256,
            sourceOutputSha256: outputHash(readFileSync(outputPath, "utf8")),
            outputSha256: outputHash(adapted),
            adaptation: family === "architecture" || family === "sequence" ? "topocode-story-semantics-v2" : "topocode-readability-and-theme-v1",
          },
        };
      } catch (error) {
        throw commandError(error);
      } finally {
        rmSync(temporaryDirectory, { recursive: true, force: true });
      }
    }
    
  • @topo/views Open Dependency context by role: Path selectionOpen Dependency context by role: Ignore matchingOpen Dependency context by role: Build, test, docsOpen Dependency context by role: Development tools

    Resolves authored path-based views, review baselines, overrides and layout pins against graph evidence. All declared internal dependencies (not runtime calls): @topo/views -> @topo/graph [dependencies: workspace:*] @topo/views -> @topo/schema [dependencies: workspace:*] Referenced by internal modules: @topo/cli -> @topo/views [dependencies: workspace:*] @topo/site -> @topo/views [dependencies: workspace:*] Stable drilldown identity: views. Module-specific detail maps will be curated later; there is no placeholder target.

    packages/views/package.json:1-30
    {
      "name": "@topo/views",
      "version": "0.0.0",
      "private": true,
      "type": "module",
      "files": [
        "dist"
      ],
      "exports": {
        ".": {
          "types": "./dist/index.d.ts",
          "default": "./dist/index.js"
        }
      },
      "scripts": {
        "build": "tsc -b",
        "typecheck": "tsc -b --pretty false",
        "test": "vitest run"
      },
      "dependencies": {
        "@topo/graph": "workspace:*",
        "@topo/schema": "workspace:*",
        "ignore": "^7.0.0"
      },
      "devDependencies": {
        "typescript": "^7.0.2",
        "vite": "8.2.2",
        "vitest": "^5.0.0"
      }
    }
    
    packages/views/src/core.ts:1-867
    import ignore from "ignore";
    import {
      assertGraphDocument,
      serializeJson,
      type GraphDocument,
      type GraphNode,
      type JsonValue,
    } from "@topo/schema";
    import type { ArchitectureDocument, LayoutPin } from "@topo/graph";
    import type {
      CuratedViewDefinition,
      CuratedViewEvaluation,
      CuratedViewsSnapshot,
      ViewAnchor,
      ViewMember,
      ViewPin,
    } from "./model.js";
    
    const MAX_STRING = 1024;
    const MAX_NAME = 256;
    const MAX_ARRAY = 10_000;
    const VIEW_KEYS = new Set([
      "schemaVersion",
      "id",
      "name",
      "provenance",
      "pathRules",
      "includes",
      "excludes",
      "pins",
      "expandedPaths",
      "reviewed",
    ]);
    
    export interface CuratedViewValidationIssue {
      path: string;
      message: string;
    }
    
    export class CuratedViewValidationError extends Error {
      readonly issues: CuratedViewValidationIssue[];
    
      constructor(issues: CuratedViewValidationIssue[]) {
        super(
          `Curated view validation failed with ${issues.length} issue${issues.length === 1 ? "" : "s"}: ${issues
            .map((issue) => `${issue.path} ${issue.message}`)
            .join("; ")}`,
        );
        this.name = "CuratedViewValidationError";
        this.issues = issues;
      }
    }
    
    function isRecord(value: unknown): value is Record<string, unknown> {
      return (
        typeof value === "object" &&
        value !== null &&
        !Array.isArray(value) &&
        (Object.getPrototypeOf(value) === Object.prototype ||
          Object.getPrototypeOf(value) === null)
      );
    }
    
    function compareText(left: string, right: string): number {
      return left < right ? -1 : left > right ? 1 : 0;
    }
    
    function anchorKey(anchor: ViewAnchor): string {
      return `${anchor.kind}\0${anchor.path}`;
    }
    
    function compareAnchors(left: ViewAnchor, right: ViewAnchor): number {
      return (
        compareText(left.path, right.path) || compareText(left.kind, right.kind)
      );
    }
    
    function assertKnownKeys(
      value: Record<string, unknown>,
      allowed: ReadonlySet<string>,
      path: string,
      issues: CuratedViewValidationIssue[],
    ): void {
      for (const key of Object.keys(value)) {
        if (!allowed.has(key)) {
          issues.push({ path: `${path}.${key}`, message: "Unknown property." });
        }
      }
    }
    
    function readString(
      value: unknown,
      path: string,
      issues: CuratedViewValidationIssue[],
      maximum = MAX_STRING,
    ): string | undefined {
      if (
        typeof value !== "string" ||
        value.length === 0 ||
        value.length > maximum
      ) {
        issues.push({
          path,
          message: `Expected a non-empty string no longer than ${maximum} characters.`,
        });
        return undefined;
      }
      return value;
    }
    
    function readPath(
      value: unknown,
      path: string,
      issues: CuratedViewValidationIssue[],
      allowRoot: boolean,
    ): string | undefined {
      const result = readString(value, path, issues);
      if (result === undefined) return undefined;
      if (result === "." && allowRoot) return result;
      if (
        result.includes("\\") ||
        /[\u0000-\u001f\u007f]/u.test(result) ||
        result.startsWith("/") ||
        result.endsWith("/") ||
        result.includes("//") ||
        result
          .split("/")
          .some((segment) => segment === "" || segment === "." || segment === "..") ||
        result.startsWith("./")
      ) {
        issues.push({
          path,
          message: "Expected a canonical repository-relative POSIX path.",
        });
        return undefined;
      }
      if (result === "." && !allowRoot) {
        issues.push({ path, message: 'The repository root "." is directory-only.' });
        return undefined;
      }
      return result;
    }
    
    function readArray(
      value: unknown,
      path: string,
      issues: CuratedViewValidationIssue[],
    ): unknown[] {
      if (!Array.isArray(value)) {
        issues.push({ path, message: "Expected an array." });
        return [];
      }
      if (value.length > MAX_ARRAY) {
        issues.push({
          path,
          message: `Expected no more than ${MAX_ARRAY} entries.`,
        });
        return value.slice(0, MAX_ARRAY);
      }
      return value;
    }
    
    function parseAnchor(
      value: unknown,
      path: string,
      issues: CuratedViewValidationIssue[],
    ): ViewAnchor | undefined {
      if (!isRecord(value)) {
        issues.push({ path, message: "Expected an anchor object." });
        return undefined;
      }
      assertKnownKeys(value, new Set(["kind", "path"]), path, issues);
      if (value.kind !== "node" && value.kind !== "directory") {
        issues.push({
          path: `${path}.kind`,
          message: 'Expected "node" or "directory".',
        });
        return undefined;
      }
      const anchorPath = readPath(
        value.path,
        `${path}.path`,
        issues,
        value.kind === "directory",
      );
      return anchorPath === undefined ? undefined : { kind: value.kind, path: anchorPath };
    }
    
    function parseAnchors(
      value: unknown,
      path: string,
      issues: CuratedViewValidationIssue[],
    ): ViewAnchor[] {
      const anchors: ViewAnchor[] = [];
      const seen = new Set<string>();
      readArray(value, path, issues).forEach((entry, index) => {
        const anchor = parseAnchor(entry, `${path}[${index}]`, issues);
        if (!anchor) return;
        const key = anchorKey(anchor);
        if (seen.has(key)) {
          issues.push({
            path: `${path}[${index}]`,
            message: `Duplicate anchor "${anchor.kind}:${anchor.path}".`,
          });
          return;
        }
        seen.add(key);
        anchors.push(anchor);
      });
      return anchors;
    }
    
    function parseRules(
      value: unknown,
      path: string,
      issues: CuratedViewValidationIssue[],
    ): string[] {
      const rules: string[] = [];
      const seen = new Set<string>();
      readArray(value, path, issues).forEach((entry, index) => {
        const rulePath = `${path}[${index}]`;
        const rule = readString(entry, rulePath, issues);
        if (rule === undefined) return;
        if (
          rule.trim() !== rule ||
          rule.startsWith("!") ||
          rule.startsWith("#") ||
          rule.includes("\n") ||
          rule.includes("\r") ||
          rule.includes("\0") ||
          rule.includes("\\") ||
          rule.startsWith("/") ||
          rule === "." ||
          rule.startsWith("../") ||
          rule.includes("/../") ||
          rule.includes("//")
        ) {
          issues.push({
            path: rulePath,
            message:
              "Expected one positive, root-relative gitignore-style pattern without comments, negation, escapes, or traversal.",
          });
          return;
        }
        if (seen.has(rule)) {
          issues.push({ path: rulePath, message: `Duplicate path rule "${rule}".` });
          return;
        }
        seen.add(rule);
        rules.push(rule);
      });
      return rules;
    }
    
    function parsePins(
      value: unknown,
      path: string,
      issues: CuratedViewValidationIssue[],
    ): ViewPin[] {
      const pins: ViewPin[] = [];
      const seen = new Set<string>();
      readArray(value, path, issues).forEach((entry, index) => {
        const pinPath = `${path}[${index}]`;
        if (!isRecord(entry)) {
          issues.push({ path: pinPath, message: "Expected a pin object." });
          return;
        }
        assertKnownKeys(entry, new Set(["anchor", "position"]), pinPath, issues);
        const anchor = parseAnchor(entry.anchor, `${pinPath}.anchor`, issues);
        if (!isRecord(entry.position)) {
          issues.push({
            path: `${pinPath}.position`,
            message: "Expected a position object.",
          });
          return;
        }
        assertKnownKeys(
          entry.position,
          new Set(["x", "y"]),
          `${pinPath}.position`,
          issues,
        );
        const { x, y } = entry.position;
        if (
          typeof x !== "number" ||
          typeof y !== "number" ||
          !Number.isSafeInteger(x) ||
          !Number.isSafeInteger(y)
        ) {
          issues.push({
            path: `${pinPath}.position`,
            message: "Pin coordinates must be safe finite integers.",
          });
          return;
        }
        if (!anchor) return;
        const key = anchorKey(anchor);
        if (seen.has(key)) {
          issues.push({
            path: `${pinPath}.anchor`,
            message: `Multiple pins target "${anchor.kind}:${anchor.path}".`,
          });
          return;
        }
        seen.add(key);
        pins.push({ anchor, position: { x, y } });
      });
      return pins;
    }
    
    function parseMembers(
      value: unknown,
      path: string,
      issues: CuratedViewValidationIssue[],
    ): ViewMember[] {
      const members: ViewMember[] = [];
      const seen = new Set<string>();
      readArray(value, path, issues).forEach((entry, index) => {
        const memberPath = `${path}[${index}]`;
        if (!isRecord(entry)) {
          issues.push({ path: memberPath, message: "Expected a member object." });
          return;
        }
        assertKnownKeys(entry, new Set(["path", "fingerprint"]), memberPath, issues);
        const repositoryPath = readPath(
          entry.path,
          `${memberPath}.path`,
          issues,
          false,
        );
        let fingerprint: string | undefined;
        if (entry.fingerprint !== undefined) {
          fingerprint = readString(
            entry.fingerprint,
            `${memberPath}.fingerprint`,
            issues,
          );
        }
        if (repositoryPath === undefined) return;
        if (seen.has(repositoryPath)) {
          issues.push({
            path: `${memberPath}.path`,
            message: `Duplicate reviewed member "${repositoryPath}".`,
          });
          return;
        }
        seen.add(repositoryPath);
        members.push({
          path: repositoryPath,
          ...(fingerprint === undefined ? {} : { fingerprint }),
        });
      });
      return members;
    }
    
    function parseDefinition(
      value: unknown,
      path: string,
      issues: CuratedViewValidationIssue[],
    ): CuratedViewDefinition | undefined {
      if (!isRecord(value)) {
        issues.push({ path, message: "Expected a curated view object." });
        return undefined;
      }
      assertKnownKeys(value, VIEW_KEYS, path, issues);
      if (value.schemaVersion !== "1.0") {
        issues.push({
          path: `${path}.schemaVersion`,
          message: 'Expected schema version "1.0".',
        });
      }
      if (value.provenance !== "human") {
        issues.push({
          path: `${path}.provenance`,
          message: 'Expected provenance "human".',
        });
      }
      const id = readString(value.id, `${path}.id`, issues, 128);
      if (id !== undefined && !/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(id)) {
        issues.push({
          path: `${path}.id`,
          message: "Expected a lowercase slug using letters, digits, and single hyphens.",
        });
      }
      const name = readString(value.name, `${path}.name`, issues, MAX_NAME);
      const pathRules = parseRules(value.pathRules, `${path}.pathRules`, issues);
      const includes = parseAnchors(value.includes, `${path}.includes`, issues);
      const excludes = parseAnchors(value.excludes, `${path}.excludes`, issues);
      const pins = parsePins(value.pins, `${path}.pins`, issues);
      const expandedPaths = readArray(
        value.expandedPaths,
        `${path}.expandedPaths`,
        issues,
      ).flatMap((entry, index) => {
        const expandedPath = readPath(
          entry,
          `${path}.expandedPaths[${index}]`,
          issues,
          true,
        );
        return expandedPath === undefined ? [] : [expandedPath];
      });
      if (new Set(expandedPaths).size !== expandedPaths.length) {
        issues.push({
          path: `${path}.expandedPaths`,
          message: "Expanded paths must be unique.",
        });
      }
    
      let reviewed: CuratedViewDefinition["reviewed"];
      if (value.reviewed !== undefined) {
        if (!isRecord(value.reviewed)) {
          issues.push({
            path: `${path}.reviewed`,
            message: "Expected a reviewed snapshot object.",
          });
        } else {
          assertKnownKeys(
            value.reviewed,
            new Set(["graphHash", "members"]),
            `${path}.reviewed`,
            issues,
          );
          const graphHash = readString(
            value.reviewed.graphHash,
            `${path}.reviewed.graphHash`,
            issues,
          );
          const members = parseMembers(
            value.reviewed.members,
            `${path}.reviewed.members`,
            issues,
          );
          if (graphHash !== undefined) reviewed = { graphHash, members };
        }
      }
    
      if (
        id === undefined ||
        name === undefined ||
        value.schemaVersion !== "1.0" ||
        value.provenance !== "human"
      ) {
        return undefined;
      }
      return {
        schemaVersion: "1.0",
        id,
        name,
        provenance: "human",
        pathRules,
        includes,
        excludes,
        pins,
        expandedPaths,
        ...(reviewed === undefined ? {} : { reviewed }),
      };
    }
    
    export function parseCuratedView(value: unknown): CuratedViewDefinition {
      const issues: CuratedViewValidationIssue[] = [];
      const definition = parseDefinition(value, "$", issues);
      if (issues.length > 0 || definition === undefined) {
        throw new CuratedViewValidationError(issues);
      }
      return definition;
    }
    
    function canonicalDefinition(
      definitionValue: unknown,
    ): CuratedViewDefinition {
      const definition = parseCuratedView(definitionValue);
      return {
        ...definition,
        pathRules: [...definition.pathRules].sort(compareText),
        includes: [...definition.includes].sort(compareAnchors),
        excludes: [...definition.excludes].sort(compareAnchors),
        pins: [...definition.pins].sort((left, right) =>
          compareAnchors(left.anchor, right.anchor),
        ),
        expandedPaths: [...definition.expandedPaths].sort(compareText),
        ...(definition.reviewed === undefined
          ? {}
          : {
              reviewed: {
                graphHash: definition.reviewed.graphHash,
                members: [...definition.reviewed.members].sort((left, right) =>
                  compareText(left.path, right.path),
                ),
              },
            }),
      };
    }
    
    export function serializeCuratedView(
      definition: CuratedViewDefinition,
    ): string {
      return serializeJson(canonicalDefinition(definition) as unknown as JsonValue);
    }
    
    export function parseCuratedViewsSnapshot(
      value: unknown,
    ): CuratedViewsSnapshot {
      const issues: CuratedViewValidationIssue[] = [];
      if (!isRecord(value)) {
        throw new CuratedViewValidationError([
          { path: "$", message: "Expected a curated views snapshot object." },
        ]);
      }
      assertKnownKeys(
        value,
        new Set(["schemaVersion", "graphHash", "views"]),
        "$",
        issues,
      );
      if (value.schemaVersion !== "1.0") {
        issues.push({
          path: "$.schemaVersion",
          message: 'Expected schema version "1.0".',
        });
      }
      const graphHash = readString(value.graphHash, "$.graphHash", issues);
      const records = readArray(value.views, "$.views", issues);
      const views: CuratedViewsSnapshot["views"] = [];
      const ids = new Set<string>();
      records.forEach((entry, index) => {
        const path = `$.views[${index}]`;
        if (!isRecord(entry)) {
          issues.push({ path, message: "Expected a view record object." });
          return;
        }
        assertKnownKeys(entry, new Set(["definition", "revision"]), path, issues);
        const definition = parseDefinition(
          entry.definition,
          `${path}.definition`,
          issues,
        );
        const revision = readString(
          entry.revision,
          `${path}.revision`,
          issues,
        );
        if (!definition || revision === undefined) return;
        if (ids.has(definition.id)) {
          issues.push({
            path: `${path}.definition.id`,
            message: `Duplicate view identifier "${definition.id}".`,
          });
          return;
        }
        ids.add(definition.id);
        views.push({ definition, revision });
      });
      if (
        issues.length > 0 ||
        graphHash === undefined ||
        value.schemaVersion !== "1.0"
      ) {
        throw new CuratedViewValidationError(issues);
      }
      return {
        schemaVersion: "1.0",
        graphHash,
        views,
      };
    }
    
    interface PathIndex {
      nodesByPath: Map<string, GraphNode>;
      sortedPaths: string[];
    }
    
    function graphPathIndex(graphValue: unknown): {
      graph: GraphDocument;
      index: PathIndex;
    } {
      if (isRecord(graphValue) && Array.isArray(graphValue.nodes)) {
        const nodeIdByPath = new Map<string, string>();
        const issues: CuratedViewValidationIssue[] = [];
        graphValue.nodes.forEach((candidate, index) => {
          if (
            !isRecord(candidate) ||
            typeof candidate.id !== "string" ||
            !isRecord(candidate.identity) ||
            candidate.identity.kind !== "path" ||
            typeof candidate.identity.value !== "string"
          ) {
            return;
          }
          readPath(
            candidate.identity.value,
            `$.graph.nodes[${index}].identity.value`,
            issues,
            false,
          );
          const existingId = nodeIdByPath.get(candidate.identity.value);
          if (existingId !== undefined) {
            issues.push({
              path: "$.graph.nodes",
              message: `Ambiguous path identity "${candidate.identity.value}" is used by "${existingId}" and "${candidate.id}".`,
            });
          }
          nodeIdByPath.set(candidate.identity.value, candidate.id);
        });
        if (issues.length > 0) throw new CuratedViewValidationError(issues);
      }
      assertGraphDocument(graphValue);
      const nodesByPath = new Map<string, GraphNode>();
      for (const node of graphValue.nodes) {
        if (node.identity.kind !== "path") continue;
        const existing = nodesByPath.get(node.identity.value);
        if (existing) {
          throw new CuratedViewValidationError([
            {
              path: "$.graph.nodes",
              message: `Ambiguous path identity "${node.identity.value}" is used by "${existing.id}" and "${node.id}".`,
            },
          ]);
        }
        nodesByPath.set(node.identity.value, node);
      }
      return {
        graph: graphValue,
        index: {
          nodesByPath,
          sortedPaths: [...nodesByPath.keys()].sort(compareText),
        },
      };
    }
    
    function pathsForAnchor(index: PathIndex, anchor: ViewAnchor): string[] {
      if (anchor.kind === "node") {
        return index.nodesByPath.has(anchor.path) ? [anchor.path] : [];
      }
      if (anchor.path === ".") return index.sortedPaths;
      const prefix = `${anchor.path}/`;
      return index.sortedPaths.filter((path) => path.startsWith(prefix));
    }
    
    function selectedPathState(
      index: PathIndex,
      definition: CuratedViewDefinition,
    ): {
      selectedPaths: Set<string>;
      unresolvedIncludes: ViewAnchor[];
      unresolvedExcludes: ViewAnchor[];
      missingPins: ViewAnchor[];
      excludedPins: ViewAnchor[];
      retainedPins: ViewAnchor[];
    } {
      const matcher = ignore({ ignorecase: false }).add(definition.pathRules);
      const selectedPaths = new Set(
        index.sortedPaths.filter((path) => matcher.ignores(path)),
      );
      const unresolvedIncludes: ViewAnchor[] = [];
      for (const anchor of definition.includes) {
        const paths = pathsForAnchor(index, anchor);
        if (paths.length === 0) unresolvedIncludes.push(anchor);
        for (const path of paths) selectedPaths.add(path);
      }
      const excludedPaths = new Set<string>();
      const unresolvedExcludes: ViewAnchor[] = [];
      for (const anchor of definition.excludes) {
        const paths = pathsForAnchor(index, anchor);
        if (paths.length === 0) unresolvedExcludes.push(anchor);
        for (const path of paths) excludedPaths.add(path);
      }
      const missingPins: ViewAnchor[] = [];
      const excludedPins: ViewAnchor[] = [];
      const retainedPins: ViewAnchor[] = [];
      for (const pin of definition.pins) {
        const paths = pathsForAnchor(index, pin.anchor);
        if (paths.length === 0) {
          missingPins.push(pin.anchor);
          continue;
        }
        const remaining = paths.filter((path) => !excludedPaths.has(path));
        if (remaining.length === 0) {
          excludedPins.push(pin.anchor);
          continue;
        }
        const retained = remaining.some((path) => !selectedPaths.has(path));
        for (const path of remaining) selectedPaths.add(path);
        if (retained) retainedPins.push(pin.anchor);
      }
      for (const path of excludedPaths) selectedPaths.delete(path);
      return {
        selectedPaths,
        unresolvedIncludes,
        unresolvedExcludes,
        missingPins,
        excludedPins,
        retainedPins,
      };
    }
    
    function memberForNode(node: GraphNode): ViewMember {
      return {
        path: node.identity.value,
        ...(node.fingerprint === undefined ? {} : { fingerprint: node.fingerprint }),
      };
    }
    
    function memberChanged(left: ViewMember, right: ViewMember): boolean {
      return left.fingerprint !== right.fingerprint;
    }
    
    export function evaluateCuratedView(
      graphValue: unknown,
      definitionValue: CuratedViewDefinition,
    ): CuratedViewEvaluation {
      const definition = parseCuratedView(definitionValue);
      const { index } = graphPathIndex(graphValue);
      const state = selectedPathState(index, definition);
      const members = [...state.selectedPaths]
        .sort(compareText)
        .map((path) => memberForNode(index.nodesByPath.get(path)!));
      const reviewedByPath = new Map(
        (definition.reviewed?.members ?? []).map((member) => [member.path, member]),
      );
      const currentByPath = new Map(members.map((member) => [member.path, member]));
      const added = members.filter((member) => !reviewedByPath.has(member.path));
      const removed = [...reviewedByPath.values()]
        .filter((member) => !currentByPath.has(member.path))
        .sort((left, right) => compareText(left.path, right.path));
      const changed = members.filter((member) => {
        const reviewed = reviewedByPath.get(member.path);
        return reviewed !== undefined && memberChanged(member, reviewed);
      });
      const pinnedPaths = new Set(
        definition.pins.flatMap((pin) => pathsForAnchor(index, pin.anchor)),
      );
      return {
        nodeIds: members.map((member) => index.nodesByPath.get(member.path)!.id),
        members,
        delta: {
          added,
          removed,
          changed,
          unplaced: added.filter((member) => !pinnedPaths.has(member.path)),
          missingPins: [...state.missingPins].sort(compareAnchors),
          excludedPins: [...state.excludedPins].sort(compareAnchors),
          retainedPins: [...state.retainedPins].sort(compareAnchors),
          unresolvedIncludes: [...state.unresolvedIncludes].sort(compareAnchors),
          unresolvedExcludes: [...state.unresolvedExcludes].sort(compareAnchors),
        },
      };
    }
    
    export function reviewCuratedView(
      graph: unknown,
      definitionValue: CuratedViewDefinition,
      graphHashValue: string,
    ): CuratedViewDefinition {
      const graphHashIssues: CuratedViewValidationIssue[] = [];
      const graphHash = readString(graphHashValue, "$.graphHash", graphHashIssues);
      if (graphHash === undefined) {
        throw new CuratedViewValidationError(graphHashIssues);
      }
      const definition = parseCuratedView(definitionValue);
      const evaluation = evaluateCuratedView(graph, definition);
      return {
        ...definition,
        pathRules: [...definition.pathRules],
        includes: definition.includes.map((anchor) => ({ ...anchor })),
        excludes: definition.excludes.map((anchor) => ({ ...anchor })),
        pins: definition.pins.map((pin) => ({
          anchor: { ...pin.anchor },
          position: { ...pin.position },
        })),
        expandedPaths: [...definition.expandedPaths],
        reviewed: {
          graphHash,
          members: evaluation.members.map((member) => ({ ...member })),
        },
      };
    }
    
    function directoryPath(path: string): string {
      return path === "." ? "" : path;
    }
    
    export function resolveViewPins(
      graphValue: unknown,
      architecture: ArchitectureDocument,
      definitionValue: CuratedViewDefinition,
    ): LayoutPin[] {
      const definition = parseCuratedView(definitionValue);
      const { graph, index } = graphPathIndex(graphValue);
      if (architecture.graphId !== graph.graphId || architecture.version !== "1.0") {
        throw new CuratedViewValidationError([
          {
            path: "$.architecture",
            message: "Architecture must be a version 1.0 derivation of this graph.",
          },
        ]);
      }
      const selected = new Set(evaluateCuratedView(graph, definition).nodeIds);
      const containerByPath = new Map(
        architecture.directoryContainers.map((container) => [
          container.path,
          container,
        ]),
      );
      const pins: LayoutPin[] = [];
      for (const pin of definition.pins) {
        const paths = pathsForAnchor(index, pin.anchor);
        const selectedPaths = paths.filter((path) =>
          selected.has(index.nodesByPath.get(path)!.id),
        );
        if (selectedPaths.length === 0) continue;
        if (pin.anchor.kind === "node") {
          const node = index.nodesByPath.get(pin.anchor.path)!;
          pins.push({
            id: `view:${definition.id}:pin:node:${pin.anchor.path}`,
            subject: { kind: "node" as const, id: node.id },
            anchor: { path: pin.anchor.path },
            position: { ...pin.position },
          });
          continue;
        }
        const container = containerByPath.get(directoryPath(pin.anchor.path));
        if (!container) {
          throw new CuratedViewValidationError([
            {
              path: "$.architecture.directoryContainers",
              message: `Missing directory container for "${pin.anchor.path}".`,
            },
          ]);
        }
        pins.push({
          id: `view:${definition.id}:pin:directory:${pin.anchor.path}`,
          subject: { kind: "container" as const, id: container.id },
          anchor: { path: pin.anchor.path },
          position: { ...pin.position },
        });
      }
      return pins;
    }
    
    export function anchorForEntity(
      graphValue: unknown,
      architecture: ArchitectureDocument,
      entityId: string,
    ): ViewAnchor | undefined {
      const { graph } = graphPathIndex(graphValue);
      if (architecture.graphId !== graph.graphId || architecture.version !== "1.0") {
        throw new CuratedViewValidationError([
          {
            path: "$.architecture",
            message: "Architecture must be a version 1.0 derivation of this graph.",
          },
        ]);
      }
      const node = graph.nodes.find((candidate) => candidate.id === entityId);
      if (node) {
        return node.identity.kind === "path"
          ? { kind: "node", path: node.identity.value }
          : undefined;
      }
      const directory = architecture.directoryContainers.find(
        (candidate) => candidate.id === entityId,
      );
      return directory
        ? { kind: "directory", path: directory.path.length === 0 ? "." : directory.path }
        : undefined;
    }
    
  • @topo/site Open Dependency context by role: Build, test, docsOpen Dependency context by role: Development tools

    Owns the site-data contract, artifact loading checks, notices, and browser regressions. It is not the marketing website or the generated shell implementation. All declared internal dependencies (not runtime calls): @topo/site -> @topo/enrichment [dependencies: workspace:*] @topo/site -> @topo/graph [dependencies: workspace:*] @topo/site -> @topo/modules [dependencies: workspace:*] @topo/site -> @topo/schema [dependencies: workspace:*] @topo/site -> @topo/views [dependencies: workspace:*] @topo/site -> @topo/diagram-core [devDependencies: workspace:*] Referenced by internal modules: @topo/cli -> @topo/site [dependencies: workspace:*] Stable drilldown identity: site. Module-specific detail maps will be curated later; there is no placeholder target.

    packages/site/package.json:1-38
    {
      "name": "@topo/site",
      "version": "0.0.0",
      "private": true,
      "type": "module",
      "files": [
        "dist"
      ],
      "exports": {
        "./notices": "./dist/THIRD_PARTY_NOTICES.txt",
        "./data": {
          "types": "./src/data.ts",
          "default": "./dist/data-contract/data.js"
        }
      },
      "scripts": {
        "build": "node scripts/clean-dist.mjs && tsc -p tsconfig.json --noEmit && tsc -p tsconfig.data.json",
        "typecheck": "tsc -p tsconfig.json --noEmit --pretty false && yarn typecheck:browser",
        "typecheck:browser": "tsc -p tsconfig.browser-tests.json --noEmit --pretty false",
        "test": "vitest run --config vitest.config.ts",
        "test:browser": "playwright test --config playwright.config.mjs"
      },
      "dependencies": {
        "@topo/enrichment": "workspace:*",
        "@topo/graph": "workspace:*",
        "@topo/modules": "workspace:*",
        "@topo/schema": "workspace:*",
        "@topo/views": "workspace:*"
      },
      "devDependencies": {
        "@playwright/test": "^1.55.0",
        "@topo/diagram-core": "workspace:*",
        "@types/node": "^22.18.0",
        "typescript": "^7.0.2",
        "vite": "8.2.2",
        "vitest": "^5.0.0"
      }
    }
    
    packages/site/src/data.ts:1-276
    import { hashAnalysis, parseEnrichmentDocument, validateEnrichmentReferences } from "@topo/enrichment";
    import {
      deriveArchitecture,
      type ArchitectureDocument,
    } from "@topo/graph";
    import {
      validateModuleContributions,
      type StaticModuleManifest,
    } from "@topo/modules";
    import {
      assertLayoutDocument,
      parseGraphDocument,
      parseLogicalArchitecture,
      validateLayoutAgainstGraph,
      type GraphDocument,
      type LayoutDocument,
    } from "@topo/schema";
    import { parseCuratedViewsSnapshot } from "@topo/views";
    import type {
      DashboardArtifact,
      LoadedArtifacts,
    } from "./contracts.js";
    import { supportedSiteModules } from "./module-support.js";
    
    export class ArtifactLoadError extends Error {
      readonly artifact: string;
      readonly causeMessage: string;
    
      constructor(artifact: string, cause: unknown) {
        const causeMessage = cause instanceof Error ? cause.message : String(cause);
        super(`Could not load ${artifact}: ${causeMessage}`);
        this.name = "ArtifactLoadError";
        this.artifact = artifact;
        this.causeMessage = causeMessage;
      }
    }
    
    interface SiteDataEnvelope {
      schemaVersion: "1.0";
      graph: unknown;
      layout: unknown;
      architecture?: unknown;
      dashboard: unknown | null;
      curatedViews?: unknown;
      enrichment?: unknown;
      logicalArchitecture?: unknown;
    }
    
    function isEmptyJson(value: unknown): boolean {
      if (value === null) return true;
      if (Array.isArray(value)) return value.length === 0;
      return (
        typeof value === "object" &&
        value !== null &&
        Object.keys(value).length === 0
      );
    }
    
    function scannerQuality(graph: GraphDocument): {
      authoritative: boolean;
      status: string;
      warnings: string[];
    } {
      const value = graph.extensions["dev.topo.scanner"];
      if (value === undefined) {
        return { authoritative: true, status: "complete", warnings: [] };
      }
      if (
        typeof value !== "object" ||
        value === null ||
        Array.isArray(value) ||
        typeof value.authoritative !== "boolean" ||
        typeof value.status !== "string" ||
        value.status.length === 0 ||
        !Array.isArray(value.diagnostics)
      ) {
        throw new ArtifactLoadError(
          "data.json graph.extensions.dev.topo.scanner",
          "Expected authoritative:boolean, status:string, and diagnostics:array.",
        );
      }
      const diagnostics = value.diagnostics.map((diagnostic, index) => {
        if (typeof diagnostic === "string" && diagnostic.length > 0) {
          return diagnostic;
        }
        if (
          typeof diagnostic === "object" &&
          diagnostic !== null &&
          !Array.isArray(diagnostic) &&
          "message" in diagnostic &&
          typeof diagnostic.message === "string" &&
          diagnostic.message.length > 0
        ) {
          return diagnostic.message;
        }
        throw new ArtifactLoadError(
          "data.json graph.extensions.dev.topo.scanner",
          `Diagnostic ${index} must be a string or an object with a message.`,
        );
      });
      return {
        authoritative: value.authoritative,
        status: value.status,
        warnings: value.authoritative
          ? []
          : [
              `Scanner output is ${value.status} and is not authoritative.`,
              ...diagnostics,
            ],
      };
    }
    
    function validateArchitecture(
      value: unknown,
      graph: GraphDocument,
    ): ArchitectureDocument {
      if (
        typeof value !== "object" ||
        value === null ||
        !("version" in value) ||
        value.version !== "1.0" ||
        !("graphId" in value) ||
        value.graphId !== graph.graphId ||
        !("directoryContainers" in value) ||
        !Array.isArray(value.directoryContainers) ||
        !("stronglyConnectedComponents" in value) ||
        !Array.isArray(value.stronglyConnectedComponents)
      ) {
        throw new ArtifactLoadError(
          "architecture.json",
          "Artifact is not a version 1.0 architecture for this graph.",
        );
      }
      return value as ArchitectureDocument;
    }
    
    function validateEnvelope(value: unknown): SiteDataEnvelope {
      if (
        typeof value !== "object" ||
        value === null ||
        !("schemaVersion" in value) ||
        value.schemaVersion !== "1.0" ||
        !("graph" in value) ||
        !("layout" in value) ||
        !("dashboard" in value)
      ) {
        throw new ArtifactLoadError(
          "data.json",
          "Expected schemaVersion 1.0 with graph, layout, and dashboard fields.",
        );
      }
      return value as SiteDataEnvelope;
    }
    
    function validateLayout(value: unknown, graph: GraphDocument): LayoutDocument {
      try {
        assertLayoutDocument(value);
      } catch (error) {
        throw new ArtifactLoadError("data.json layout", error);
      }
      const layout = value;
      const issues = validateLayoutAgainstGraph(layout, graph);
      if (issues.length > 0) {
        throw new ArtifactLoadError(
          "data.json layout",
          issues.map((issue) => `${issue.path} ${issue.message}`).join("; "),
        );
      }
      return layout;
    }
    
    export async function parseSiteData(
      value: unknown,
      compiledModules: readonly StaticModuleManifest[],
      editingToken?: string,
    ): Promise<LoadedArtifacts> {
      const envelope = validateEnvelope(value);
      let parsedGraph: ReturnType<typeof parseGraphDocument>;
      try {
        parsedGraph = parseGraphDocument(
          JSON.stringify(envelope.graph),
          supportedSiteModules(compiledModules),
        );
      } catch (error) {
        throw new ArtifactLoadError("data.json graph", error);
      }
      try {
        validateModuleContributions(parsedGraph.document, compiledModules);
      } catch (error) {
        throw new ArtifactLoadError("data.json module contributions", error);
      }
    
      const layout = validateLayout(envelope.layout, parsedGraph.document);
      const hasArchitecture =
        envelope.architecture !== undefined && envelope.architecture !== null;
      const architecture = hasArchitecture
        ? validateArchitecture(envelope.architecture, parsedGraph.document)
        : deriveArchitecture(parsedGraph.document);
      const scanner = scannerQuality(parsedGraph.document);
      let curatedViews: LoadedArtifacts["curatedViews"];
      if (envelope.curatedViews !== undefined) {
        try {
          curatedViews = parseCuratedViewsSnapshot(envelope.curatedViews);
        } catch (error) {
          throw new ArtifactLoadError("data.json curatedViews", error);
        }
      }
    
      let dashboard: DashboardArtifact;
      if (envelope.dashboard === null) {
        dashboard = { availability: "unavailable" };
      } else if (isEmptyJson(envelope.dashboard)) {
        dashboard = { availability: "empty", value: envelope.dashboard };
      } else {
        dashboard = {
          availability: "available",
          value: envelope.dashboard,
        };
      }
    
      let enrichment: LoadedArtifacts["enrichment"];
      let enrichmentError: string | undefined;
      if (envelope.enrichment !== undefined) {
        try {
          const document = parseEnrichmentDocument(envelope.enrichment);
          if (
            document.analysisHash ===
            await hashAnalysis(parsedGraph.document, envelope.dashboard)
          ) {
            validateEnrichmentReferences(document, parsedGraph.document);
            enrichment = document;
          }
        } catch (error) {
          enrichmentError = new ArtifactLoadError("AI commentary", error).message;
        }
      }
      let logicalArchitecture: LoadedArtifacts["logicalArchitecture"];
      if (envelope.logicalArchitecture !== undefined) {
        try {
          logicalArchitecture = parseLogicalArchitecture(
            envelope.logicalArchitecture,
          );
          if (
            logicalArchitecture.graphId !== parsedGraph.document.graphId ||
            logicalArchitecture.revision !==
              parsedGraph.document.repository.revision
          ) {
            throw new Error(
              "Artifact graph or revision does not match the loaded graph.",
            );
          }
        } catch (error) {
          throw new ArtifactLoadError("data.json logicalArchitecture", error);
        }
      }
    
      return {
        graph: parsedGraph.document,
        compatibility: parsedGraph.compatibility,
        layout,
        architecture,
        architectureSource: hasArchitecture ? "artifact" : "derived",
        dashboard,
        ...(enrichment === undefined ? {} : { enrichment }),
        ...(enrichmentError === undefined ? {} : { enrichmentError }),
        ...(logicalArchitecture === undefined ? {} : { logicalArchitecture }),
        ...(curatedViews === undefined ? {} : { curatedViews }),
        ...(curatedViews && editingToken ? { viewEditingToken: editingToken } : {}),
        quality: {
          authoritative:
            parsedGraph.compatibility.authoritative && scanner.authoritative,
          scannerStatus: scanner.status,
          warnings: [...parsedGraph.compatibility.warnings, ...scanner.warnings],
        },
      };
    }
    
  • @topo/workspace Open Dependency context by role: Build, test, docsOpen Dependency context by role: Development tools

    Owns .topo configuration, safe authored/generated file access, workspace locking, and publication transactions. All declared internal dependencies (not runtime calls): @topo/workspace -> @topo/schema [dependencies: workspace:*] Referenced by internal modules: @topo/cli -> @topo/workspace [dependencies: workspace:*] Stable drilldown identity: workspace. Module-specific detail maps will be curated later; there is no placeholder target.

    packages/workspace/package.json:1-26
    {
      "name": "@topo/workspace",
      "version": "0.0.0",
      "private": true,
      "type": "module",
      "exports": {
        ".": {
          "types": "./dist/index.d.ts",
          "default": "./dist/index.js"
        }
      },
      "scripts": {
        "build": "tsc -b",
        "typecheck": "tsc -b --pretty false",
        "test": "vitest run"
      },
      "dependencies": {
        "@topo/schema": "workspace:*"
      },
      "devDependencies": {
        "@types/node": "^22.20.1",
        "typescript": "^7.0.2",
        "vite": "8.2.2",
        "vitest": "^5.0.0"
      }
    }
    
    packages/workspace/src/index.ts:1-460
    import { createHash, randomUUID } from "node:crypto";
    import { lstat, mkdir, readFile, readdir, realpath, rename, rmdir, unlink, writeFile } from "node:fs/promises";
    import { AsyncLocalStorage } from "node:async_hooks";
    import { basename, dirname, isAbsolute, relative, resolve, sep } from "node:path";
    import { serializeJson, type JsonValue } from "@topo/schema";
    
    export const WORKSPACE_VERSION = "1.0";
    export const DEFAULT_ENRICHMENT_TIMEOUT_MS = 10 * 60 * 1000;
    
    export interface WorkspaceEnrichmentConfig {
      command: string[];
      promptFile?: string;
      timeoutMs?: number;
    }
    
    export interface WorkspaceCatalogueConfig {
      title?: string;
      description?: string;
      accentColor?: string;
      categoryOrder?: string[];
      storyCategories?: Record<string, string>;
      storyIds?: string[];
    }
    
    export interface WorkspaceConfig {
      schemaVersion: "1.0";
      repositoryId: string;
      modules: string[];
      analysis?: { languages: ("typescript" | "rust")[]; frameworks: "tauri"[] };
      enrichment?: WorkspaceEnrichmentConfig;
      catalogue?: WorkspaceCatalogueConfig;
    }
    
    export function isMissing(error: unknown): boolean {
      return error instanceof Error && "code" in error && error.code === "ENOENT";
    }
    
    function isExists(error: unknown): boolean {
      return error instanceof Error && "code" in error && error.code === "EEXIST";
    }
    
    function optionalNonemptyString(
      value: unknown,
      name: string,
    ): string | undefined {
      if (value === undefined) return undefined;
      if (typeof value !== "string" || value.trim().length === 0) {
        throw new Error(`Workspace catalogue ${name} must be a nonempty string`);
      }
      return value;
    }
    
    function parseCatalogueConfig(input: unknown): WorkspaceCatalogueConfig {
      if (typeof input !== "object" || input === null || Array.isArray(input)) {
        throw new Error("Workspace catalogue must be an object");
      }
      const value = input as Record<string, unknown>;
      const title = optionalNonemptyString(value.title, "title");
      const description = optionalNonemptyString(value.description, "description");
      const accentColor = optionalNonemptyString(value.accentColor, "accentColor");
      if (accentColor !== undefined && !/^#[0-9a-fA-F]{6}$/.test(accentColor)) {
        throw new Error("Workspace catalogue accentColor must be a six-digit hex color");
      }
      let categoryOrder: string[] | undefined;
      if (value.categoryOrder !== undefined) {
        if (
          !Array.isArray(value.categoryOrder) ||
          !value.categoryOrder.every(
            (item): item is string =>
              typeof item === "string" && item.trim().length > 0,
          ) ||
          new Set(value.categoryOrder).size !== value.categoryOrder.length
        ) {
          throw new Error(
            "Workspace catalogue categoryOrder must contain distinct nonempty strings",
          );
        }
        categoryOrder = [...value.categoryOrder];
      }
      let storyCategories: Record<string, string> | undefined;
      let storyIds: string[] | undefined;
      if (value.storyIds !== undefined) {
        if (!Array.isArray(value.storyIds) ||
            !value.storyIds.every((id): id is string => typeof id === "string" && /^[a-z0-9][a-z0-9-]*$/.test(id)) ||
            new Set(value.storyIds).size !== value.storyIds.length) {
          throw new Error("Workspace catalogue storyIds must contain distinct valid story ids");
        }
        storyIds = [...value.storyIds];
      }
      if (value.storyCategories !== undefined) {
        if (
          typeof value.storyCategories !== "object" ||
          value.storyCategories === null ||
          Array.isArray(value.storyCategories)
        ) {
          throw new Error("Workspace catalogue storyCategories must be an object");
        }
        const entries = Object.entries(value.storyCategories);
        if (
          entries.some(
            ([id, category]) =>
              !/^[a-z0-9][a-z0-9-]*$/.test(id) ||
              typeof category !== "string" ||
              category.trim().length === 0,
          )
        ) {
          throw new Error(
            "Workspace catalogue storyCategories must map story ids to nonempty strings",
          );
        }
        storyCategories = Object.fromEntries(entries);
      }
      const unknown = Object.keys(value).filter(
        (key) =>
          ![
            "title",
            "description",
            "accentColor",
            "categoryOrder",
            "storyCategories",
            "storyIds",
          ].includes(key),
      );
      if (unknown.length) {
        throw new Error(`Unknown workspace catalogue keys: ${unknown.join(", ")}`);
      }
      return {
        ...(title === undefined ? {} : { title }),
        ...(description === undefined ? {} : { description }),
        ...(accentColor === undefined ? {} : { accentColor }),
        ...(categoryOrder === undefined ? {} : { categoryOrder }),
        ...(storyCategories === undefined ? {} : { storyCategories }),
        ...(storyIds === undefined ? {} : { storyIds }),
      };
    }
    
    export function parseConfig(input: unknown): WorkspaceConfig {
      if (typeof input !== "object" || input === null || Array.isArray(input)) {
        throw new Error("Workspace config must be an object");
      }
      const value = input as Record<string, unknown>;
      if (value.schemaVersion !== WORKSPACE_VERSION) {
        throw new Error(`Unsupported workspace version: ${String(value.schemaVersion)}`);
      }
      if (typeof value.repositoryId !== "string" || !value.repositoryId.trim()) {
        throw new Error("Workspace repositoryId must be a nonempty string");
      }
      if (!Array.isArray(value.modules) ||
          !value.modules.every((item): item is string => typeof item === "string" && item.length > 0) ||
          new Set(value.modules).size !== value.modules.length) {
        throw new Error("Workspace modules must be distinct nonempty strings");
      }
      let enrichment: WorkspaceEnrichmentConfig | undefined;
      if (value.enrichment !== undefined) {
        if (typeof value.enrichment !== "object" || value.enrichment === null || Array.isArray(value.enrichment)) {
          throw new Error("Workspace enrichment must be an object");
        }
        const configured = value.enrichment as Record<string, unknown>;
        if (!Array.isArray(configured.command) ||
            configured.command.length === 0 ||
            !configured.command.every((item): item is string => typeof item === "string" && item.length > 0)) {
          throw new Error("Workspace enrichment command must be a nonempty argv array");
        }
        if (configured.promptFile !== undefined &&
            (typeof configured.promptFile !== "string" || configured.promptFile.length === 0)) {
          throw new Error("Workspace enrichment promptFile must be a nonempty string");
        }
        if (configured.timeoutMs !== undefined &&
            (typeof configured.timeoutMs !== "number" ||
             !Number.isSafeInteger(configured.timeoutMs) ||
             configured.timeoutMs <= 0 ||
             configured.timeoutMs > 2_147_483_647)) {
          throw new Error("Workspace enrichment timeoutMs must be a positive safe timer integer");
        }
        const enrichmentUnknown = Object.keys(configured).filter(
          (key) => !["command", "promptFile", "timeoutMs"].includes(key),
        );
        if (enrichmentUnknown.length) {
          throw new Error(`Unknown workspace enrichment keys: ${enrichmentUnknown.join(", ")}`);
        }
        enrichment = {
          command: [...configured.command],
          ...(configured.promptFile === undefined ? {} : { promptFile: configured.promptFile }),
          ...(configured.timeoutMs === undefined ? {} : { timeoutMs: configured.timeoutMs }),
        };
      }
      const catalogue =
        value.catalogue === undefined
          ? undefined
          : parseCatalogueConfig(value.catalogue);
      let analysis: WorkspaceConfig["analysis"];
      if (value.analysis !== undefined) {
        const configured = value.analysis;
        if (typeof configured !== "object" || configured === null || Array.isArray(configured) ||
            !("languages" in configured) || !Array.isArray(configured.languages) || !configured.languages.length ||
            !configured.languages.every((id): id is "typescript" | "rust" => id === "typescript" || id === "rust") ||
            !("frameworks" in configured) || !Array.isArray(configured.frameworks) ||
            !configured.frameworks.every((id): id is "tauri" => id === "tauri") ||
            new Set(configured.languages).size !== configured.languages.length ||
            new Set(configured.frameworks).size !== configured.frameworks.length ||
            Object.keys(configured).some((key) => key !== "languages" && key !== "frameworks")) {
          throw new Error("Workspace analysis requires distinct first-party languages [typescript, rust] and frameworks [tauri]");
        }
        if (configured.frameworks.includes("tauri") && (!configured.languages.includes("typescript") || !configured.languages.includes("rust"))) {
          throw new Error("Tauri requires explicitly selected typescript and rust languages");
        }
        analysis = { languages: [...configured.languages], frameworks: [...configured.frameworks] };
      }
      const unknown = Object.keys(value).filter(
        (key) =>
          ![
            "schemaVersion",
            "repositoryId",
            "modules",
            "enrichment",
            "catalogue",
            "analysis",
          ].includes(key),
      );
      if (unknown.length) throw new Error(`Unknown workspace config keys: ${unknown.join(", ")}`);
      return {
        schemaVersion: WORKSPACE_VERSION,
        repositoryId: value.repositoryId,
        modules: [...value.modules],
        ...(enrichment === undefined ? {} : { enrichment }),
        ...(catalogue === undefined ? {} : { catalogue }),
        ...(analysis === undefined ? {} : { analysis }),
      };
    }
    
    export async function workspacePath(root: string, name: string): Promise<string> {
      if (isAbsolute(name) || name.includes("\\") || name.split("/").some((part) => part === ".." || part === "." || !part)) {
        throw new Error(`Invalid workspace-relative path: ${name}`);
      }
      const repository = await realpath(root);
      const base = resolve(repository, ".topo");
      const path = resolve(base, name);
      const rel = relative(base, path);
      if (rel.startsWith(`..${sep}`) || rel === ".." || isAbsolute(rel)) {
        throw new Error(`Path escapes .topo: ${name}`);
      }
      for (const part of [base, ...name.split("/").map((_, index, parts) => resolve(base, ...parts.slice(0, index + 1)))]) {
        try {
          if ((await lstat(part)).isSymbolicLink()) throw new Error(`Refusing workspace symlink: ${part}`);
        } catch (error) {
          if (!isMissing(error)) throw error;
        }
      }
      return path;
    }
    
    async function createAuthoredFile(path: string, content: string): Promise<boolean> {
      try {
        await writeFile(path, content, { flag: "wx" });
        return true;
      } catch (error) {
        if (!isExists(error)) throw error;
        return false;
      }
    }
    
    export async function loadConfig(root: string): Promise<WorkspaceConfig> {
      const path = await workspacePath(root, "config.json");
      return parseConfig(JSON.parse(await readFile(path, "utf8")) as unknown);
    }
    
    export async function initializeWorkspace(root: string): Promise<{ config: WorkspaceConfig; created: boolean }> {
      const path = await workspacePath(root, "config.json");
      await mkdir(dirname(path), { recursive: true });
      const created = await createAuthoredFile(path, `${JSON.stringify({
        schemaVersion: WORKSPACE_VERSION,
        repositoryId: basename(await realpath(root)),
        modules: [],
      } satisfies WorkspaceConfig, null, 2)}\n`);
      const config = await loadConfig(root);
      for (const directory of ["graph", "reports/inputs", "reports/outputs", "cache", "metadata"]) {
        const sentinel = await workspacePath(root, `${directory}/.directory-check`);
        await mkdir(dirname(sentinel), { recursive: true });
      }
      await createAuthoredFile(await workspacePath(root, ".gitignore"), "# Local caches only; other artifacts are independently reviewable.\n/cache/\n");
      return { config, created };
    }
    
    export async function readArtifact(root: string, name: string): Promise<unknown> {
      return JSON.parse(await readFile(await workspacePath(root, name), "utf8")) as unknown;
    }
    
    export async function readOptionalArtifact(root: string, name: string): Promise<unknown | undefined> {
      try {
        return await readArtifact(root, name);
      } catch (error) {
        if (!isMissing(error)) throw error;
        return undefined;
      }
    }
    
    export async function writeGenerated(root: string, name: string, content: string | Uint8Array): Promise<void> {
      if (!["graph/", "reports/outputs/", "cache/"].some((prefix) => name.startsWith(prefix))) {
        throw new Error(`Refusing to overwrite authored workspace artifact: ${name}`);
      }
      const target = await workspacePath(root, name);
      const transaction = generation.getStore();
      if (transaction) {
        if (transaction.root !== await realpath(root)) throw new Error("A generated transaction cannot write another repository");
        transaction.files.set(name, Buffer.from(content));
        return;
      }
      await mkdir(dirname(target), { recursive: true });
      const temporary = `${target}.${randomUUID()}.tmp`;
      try {
        await writeFile(temporary, content, { flag: "wx" });
        await rename(temporary, target);
      } finally {
        try {
          await unlink(temporary);
        } catch (error) {
          if (!isMissing(error)) throw error;
        }
    
      }
    }
    
        interface Generation {
          root: string;
          files: Map<string, Buffer | null>;
          directories: Set<string>;
        }
        const generation = new AsyncLocalStorage<Generation>();
    
        export async function removeGenerated(root: string, name: string): Promise<void> {
          if (!["graph/", "reports/outputs/", "cache/"].some((prefix) => name.startsWith(prefix))) {
            throw new Error(`Refusing to remove authored workspace artifact: ${name}`);
          }
          const target = await workspacePath(root, name);
          let info;
          try { info = await lstat(target); }
          catch (error) { if (isMissing(error)) return; throw error; }
          if (info.isSymbolicLink()) throw new Error(`Refusing generated symlink: ${name}`);
          if (info.isDirectory()) {
            for (const entry of await readdir(target)) await removeGenerated(root, `${name}/${entry}`);
            const transaction = generation.getStore();
            if (transaction) transaction.directories.add(name);
            else await rmdir(target);
          } else if (info.isFile()) {
            const transaction = generation.getStore();
            if (transaction) transaction.files.set(name, null);
            else await unlink(target);
          } else throw new Error(`Unsupported generated artifact: ${name}`);
        }
    
        /** Prepare all output before replacement; reported publication errors restore the old generation.
         * This is rollback-capable, not crash-atomic. Callers hold the workspace write lock. */
        export async function withGeneratedTransaction<T>(
          root: string,
          action: () => Promise<T>,
          operations: { rename?: typeof rename } = {},
        ): Promise<T> {
          const repository = await realpath(root);
          const parent = generation.getStore();
          if (parent) {
            if (parent.root !== repository) throw new Error("Cannot nest transactions across repositories");
            return action();
          }
          const transaction: Generation = { root: repository, files: new Map(), directories: new Set() };
          const result = await generation.run(transaction, action);
          const id = randomUUID();
          const prepared: { target: string; staged?: string; backup?: string; previous?: Buffer }[] = [];
          const committed: typeof prepared = [];
          let preserveBackups = false;
          async function current(target: string): Promise<Buffer | undefined> {
            try {
              if (!(await lstat(target)).isFile()) throw new Error(`Generated destination is not a regular file: ${target}`);
              return await readFile(target);
            } catch (error) { if (isMissing(error)) return undefined; throw error; }
          }
          try {
            for (const [name, contents] of transaction.files) {
              const target = await workspacePath(root, name);
              const previous = await current(target);
              await mkdir(dirname(target), { recursive: true });
              const staged = contents === null ? undefined : `${target}.${id}.stage`;
              const backup = previous === undefined ? undefined : `${target}.${id}.rollback`;
              const entry = { target, ...(staged ? { staged } : {}), ...(backup ? { backup } : {}), ...(previous ? { previous } : {}) };
              prepared.push(entry);
              if (staged) await writeFile(staged, contents!, { flag: "wx" });
              if (backup) await writeFile(backup, previous!, { flag: "wx" });
            }
            for (const file of prepared) {
              const actual = await current(file.target);
              if (actual === undefined ? file.previous !== undefined : file.previous === undefined || !actual.equals(file.previous)) {
                throw new Error(`Generated artifact changed during staging: ${file.target}`);
              }
            }
            for (const file of prepared) {
              if (file.staged) await (operations.rename ?? rename)(file.staged, file.target);
              else if (file.previous !== undefined) await unlink(file.target);
              committed.push(file);
            }
          } catch (error) {
            const failures: unknown[] = [error];
            for (const file of committed.reverse()) {
              try {
                if (file.backup) await rename(file.backup, file.target);
                else if (file.staged) await unlink(file.target);
              } catch (rollbackError) { failures.push(rollbackError); }
            }
            preserveBackups = failures.length > 1;
            if (preserveBackups) throw new AggregateError(failures, `Generated rollback incomplete; preserve .${id}.rollback files for repair`);
            throw error;
          } finally {
            for (const file of prepared) {
              for (const path of [file.staged, ...(preserveBackups ? [] : [file.backup])]) {
                if (!path) continue;
                try { await unlink(path); } catch (error) { if (!isMissing(error)) throw error; }
              }
            }
          }
          for (const name of [...transaction.directories].sort((a, b) => b.length - a.length)) {
            const path = await workspacePath(root, name);
            if (!(await readdir(path)).length) await rmdir(path);
          }
          return result;
        }
    
    export async function writeAuthoredAtomic(root: string, name: string, content: string | Uint8Array): Promise<void> {
      let target = await workspacePath(root, name);
      await mkdir(dirname(target), { recursive: true });
      target = await workspacePath(root, name);
      const temporary = `${target}.${randomUUID()}.tmp`;
      try {
        await writeFile(temporary, content, { flag: "wx" });
        await rename(temporary, target);
      } finally {
        try {
          await unlink(temporary);
        } catch (error) {
          if (!isMissing(error)) throw error;
        }
      }
    }
    
    export async function withWorkspaceLock<T>(root: string, action: () => Promise<T>): Promise<T> {
      await initializeWorkspace(root);
      const lock = await workspacePath(root, "cache/write.lock");
      try {
        await writeFile(lock, JSON.stringify({ pid: process.pid }), { flag: "wx" });
      } catch (error) {
        if (!isExists(error)) throw error;
        throw new Error(`Workspace is locked: ${lock}. Wait for the running command; remove a stale lock only after verifying its process has stopped.`);
      }
      try {
        return await action();
      } finally {
        await unlink(lock);
      }
    }
    
    export function cacheKey(input: JsonValue): string {
      return createHash("sha256").update(serializeJson(input)).digest("hex");
    }
    
  • @topo/modules Open Dependency context by role: Build, test, docsOpen Dependency context by role: Development tools

    Composes the built-in degree and cycle contributions. These are graph overlays, not language plugins. All declared internal dependencies (not runtime calls): @topo/modules -> @topo/graph [dependencies: workspace:*] @topo/modules -> @topo/schema [dependencies: workspace:*] Referenced by internal modules: @topo/cli -> @topo/modules [dependencies: workspace:*] @topo/site -> @topo/modules [dependencies: workspace:*] Stable drilldown identity: modules. Module-specific detail maps will be curated later; there is no placeholder target.

    packages/modules/package.json:1-29
    {
      "name": "@topo/modules",
      "version": "0.0.0",
      "private": true,
      "type": "module",
      "files": [
        "dist"
      ],
      "exports": {
        ".": {
          "types": "./dist/index.d.ts",
          "default": "./dist/index.js"
        }
      },
      "scripts": {
        "build": "tsc -b",
        "typecheck": "tsc -b --pretty false",
        "test": "vitest run"
      },
      "dependencies": {
        "@topo/graph": "workspace:*",
        "@topo/schema": "workspace:*"
      },
      "devDependencies": {
        "typescript": "^7.0.2",
        "vite": "8.2.2",
        "vitest": "^5.0.0"
      }
    }
    
    packages/modules/src/modules.ts:1-613
    import { deriveArchitecture } from "@topo/graph";
    import {
      assessModuleCompatibility,
      assertGraphDocument,
      canonicalizeGraphDocument,
      createAttributeId,
      serializeJson,
      type Evidence,
      type GraphAttribute,
      type GraphDocument,
      type JsonValue,
      type ModuleManifestEntry,
      type SupportedModules,
    } from "@topo/schema";
    import type { StaticModuleManifest } from "./model.js";
    
    const MODULE_VERSION = "0.0.0";
    const MODULE_SCHEMA_VERSION = "1.0";
    const DEGREE_MODULE_ID = "@topo/module-degree";
    const CYCLES_MODULE_ID = "@topo/module-cycles";
    const DEGREE_INCOMING_KEY = `${DEGREE_MODULE_ID}/incoming-edge-count`;
    const DEGREE_OUTGOING_KEY = `${DEGREE_MODULE_ID}/outgoing-edge-count`;
    const CYCLE_SIZE_KEY = `${CYCLES_MODULE_ID}/membership-size`;
    const SEMANTIC_VERSION_PATTERN =
      /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
    const SCHEMA_VERSION_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
    
    export const BUILTIN_MODULE_MANIFESTS: readonly StaticModuleManifest[] = [
      {
        id: DEGREE_MODULE_ID,
        version: MODULE_VERSION,
        schemaVersion: MODULE_SCHEMA_VERSION,
        label: "Dependency edge degree",
        dependencies: [],
        attributes: [
          {
            key: DEGREE_INCOMING_KEY,
            label: "Incoming dependency edge count",
            subjectKind: "node",
            schema: { type: "integer", minimum: 0 },
          },
          {
            key: DEGREE_OUTGOING_KEY,
            label: "Outgoing dependency edge count",
            subjectKind: "node",
            schema: { type: "integer", minimum: 0 },
          },
        ],
        views: [
          {
            id: `${DEGREE_MODULE_ID}/dependency-degree`,
            label: "Dependency edge degree",
            attributeKeys: [DEGREE_INCOMING_KEY, DEGREE_OUTGOING_KEY],
          },
        ],
      },
      {
        id: CYCLES_MODULE_ID,
        version: MODULE_VERSION,
        schemaVersion: MODULE_SCHEMA_VERSION,
        label: "Dependency cycle membership",
        dependencies: [],
        attributes: [
          {
            key: CYCLE_SIZE_KEY,
            label: "Dependency cycle membership size",
            subjectKind: "node",
            schema: { type: "integer", minimum: 0 },
          },
        ],
        views: [
          {
            id: `${CYCLES_MODULE_ID}/cycle-membership`,
            label: "Dependency cycle membership",
            attributeKeys: [CYCLE_SIZE_KEY],
          },
        ],
      },
    ] as const;
    
    interface ModuleContribution {
      attributes: GraphAttribute[];
      evidence: Evidence[];
    }
    
    function fail(message: string): never {
      throw new Error(`Module composition validation failed: ${message}`);
    }
    
    function requireNonEmpty(value: string, label: string): void {
      if (value.trim().length === 0) {
        fail(`${label} must not be empty.`);
      }
    }
    
    function ownedPrefix(moduleId: string): string {
      return `${moduleId}/`;
    }
    
    function evidencePrefix(moduleId: string): string {
      return `evidence:${ownedPrefix(moduleId)}`;
    }
    
    function attributeEvidenceId(moduleId: string, nodeId: string): string {
      return `${evidencePrefix(moduleId)}${nodeId}`;
    }
    
    function sorted(values: Iterable<string>): string[] {
      return [...values].sort();
    }
    
    function derivationLocator(
      moduleId: string,
      nodeId: string,
      inputs: Readonly<Record<string, readonly string[]>>,
    ): string {
      const parameters = Object.keys(inputs)
        .sort()
        .map(
          (key) =>
            `${encodeURIComponent(key)}=${encodeURIComponent(
              serializeJson([...(inputs[key] ?? [])]).trim(),
            )}`,
        )
        .join("&");
      return `topo:derivation/${encodeURIComponent(moduleId)}/${encodeURIComponent(nodeId)}?${parameters}`;
    }
    
    function derivedAttribute(
      moduleId: string,
      nodeId: string,
      key: string,
      value: number,
      method: string,
      evidenceId: string,
    ): GraphAttribute {
      return {
        id: createAttributeId(nodeId, key),
        subject: { kind: "node", id: nodeId },
        key,
        value,
        provenance: {
          kind: "derived",
          moduleId,
          method,
          evidenceIds: [evidenceId],
        },
        evidenceIds: [evidenceId],
        confidence: 1,
      };
    }
    
    function degreeContribution(graph: GraphDocument): ModuleContribution {
      const incoming = new Map(graph.nodes.map((node) => [node.id, [] as string[]]));
      const outgoing = new Map(graph.nodes.map((node) => [node.id, [] as string[]]));
      for (const edge of graph.edges) {
        incoming.get(edge.targetId)?.push(edge.id);
        outgoing.get(edge.sourceId)?.push(edge.id);
      }
    
      const attributes: GraphAttribute[] = [];
      const evidence: Evidence[] = [];
      for (const node of graph.nodes) {
        const incomingEdgeIds = sorted(incoming.get(node.id) ?? []);
        const outgoingEdgeIds = sorted(outgoing.get(node.id) ?? []);
        const evidenceId = attributeEvidenceId(DEGREE_MODULE_ID, node.id);
        evidence.push({
          id: evidenceId,
          kind: "annotation",
          label: `Dependency edge inputs for ${node.id}`,
          locator: derivationLocator(DEGREE_MODULE_ID, node.id, {
            incomingEdgeIds,
            outgoingEdgeIds,
          }),
        });
        attributes.push(
          derivedAttribute(
            DEGREE_MODULE_ID,
            node.id,
            DEGREE_INCOMING_KEY,
            incomingEdgeIds.length,
            "count-incoming-dependency-edges",
            evidenceId,
          ),
          derivedAttribute(
            DEGREE_MODULE_ID,
            node.id,
            DEGREE_OUTGOING_KEY,
            outgoingEdgeIds.length,
            "count-outgoing-dependency-edges",
            evidenceId,
          ),
        );
      }
      return { attributes, evidence };
    }
    
    function cyclesContribution(graph: GraphDocument): ModuleContribution {
      const membership = new Map<
        string,
        { memberNodeIds: string[]; internalEdgeIds: string[] }
      >();
      for (const component of deriveArchitecture(graph).stronglyConnectedComponents) {
        const inputs = {
          memberNodeIds: sorted(component.memberNodeIds),
          internalEdgeIds: sorted(component.internalEdgeIds),
        };
        for (const nodeId of component.memberNodeIds) {
          membership.set(nodeId, inputs);
        }
      }
    
      const evidenceId = `${evidencePrefix(CYCLES_MODULE_ID)}graph-inputs`;
      const evidence: Evidence[] = [
        {
          id: evidenceId,
          kind: "annotation",
          label: "Directed graph inputs for strongly connected components",
          locator: derivationLocator(CYCLES_MODULE_ID, graph.graphId, {
            nodeIds: sorted(graph.nodes.map((node) => node.id)),
            edges: sorted(
              graph.edges.map(
                (edge) => `${edge.id}\u0000${edge.sourceId}\u0000${edge.targetId}`,
              ),
            ),
          }),
        },
      ];
      const attributes: GraphAttribute[] = [];
      for (const node of graph.nodes) {
        const inputs = membership.get(node.id) ?? {
          memberNodeIds: [],
          internalEdgeIds: [],
        };
        attributes.push(
          derivedAttribute(
            CYCLES_MODULE_ID,
            node.id,
            CYCLE_SIZE_KEY,
            inputs.memberNodeIds.length,
            "strongly-connected-cycle-membership-size",
            evidenceId,
          ),
        );
      }
      return { attributes, evidence };
    }
    
    function generateContribution(
      moduleId: string,
      graph: GraphDocument,
    ): ModuleContribution {
      switch (moduleId) {
        case DEGREE_MODULE_ID:
          return degreeContribution(graph);
        case CYCLES_MODULE_ID:
          return cyclesContribution(graph);
        default:
          return fail(`No generator is compiled for module "${moduleId}".`);
      }
    }
    
    function moduleEntry(manifest: StaticModuleManifest): ModuleManifestEntry {
      return {
        id: manifest.id,
        version: manifest.version,
        schemaVersion: manifest.schemaVersion,
      };
    }
    
    function isCompatibleEntry(
      entry: ModuleManifestEntry,
      manifest: StaticModuleManifest,
    ): boolean {
      return assessModuleCompatibility([entry], moduleSupport([manifest]))
        .authoritative;
    }
    
    function equalCanonical(left: unknown, right: unknown): boolean {
      return serializeJson(left as JsonValue) === serializeJson(right as JsonValue);
    }
    
    function equalAttributes(
      left: readonly GraphAttribute[],
      right: readonly GraphAttribute[],
    ): boolean {
      const byId = (values: readonly GraphAttribute[]) =>
        [...values].sort((first, second) =>
          first.id < second.id ? -1 : first.id > second.id ? 1 : 0
        );
      return equalCanonical(byId(left), byId(right));
    }
    
    function referencedEvidenceIds(graph: GraphDocument): Set<string> {
      const references = new Set<string>();
      for (const edge of graph.edges) {
        edge.provenance.evidenceIds.forEach((id) => references.add(id));
      }
      for (const attribute of graph.attributes) {
        attribute.provenance.evidenceIds.forEach((id) => references.add(id));
        attribute.evidenceIds.forEach((id) => references.add(id));
      }
      return references;
    }
    
    export function validateModuleCatalog(
      manifests: readonly StaticModuleManifest[],
    ): void {
      const moduleIds = new Set<string>();
      const attributeOwners = new Map<string, string>();
      const viewOwners = new Map<string, string>();
    
      for (const manifest of manifests) {
        requireNonEmpty(manifest.id, "Module identifier");
        if (moduleIds.has(manifest.id)) {
          fail(`Duplicate module identifier "${manifest.id}".`);
        }
        moduleIds.add(manifest.id);
        requireNonEmpty(manifest.label, `Module "${manifest.id}" label`);
        if (!SEMANTIC_VERSION_PATTERN.test(manifest.version)) {
          fail(
            `Module "${manifest.id}" has invalid implementation version "${manifest.version}".`,
          );
        }
        if (!SCHEMA_VERSION_PATTERN.test(manifest.schemaVersion)) {
          fail(
            `Module "${manifest.id}" has invalid schema version "${manifest.schemaVersion}".`,
          );
        }
        if (manifest.dependencies.length > 0) {
          fail(`Module "${manifest.id}" must depend only on core.`);
        }
    
        const localAttributes = new Set<string>();
        for (const attribute of manifest.attributes) {
          requireNonEmpty(attribute.key, `Module "${manifest.id}" attribute key`);
          requireNonEmpty(
            attribute.label,
            `Module "${manifest.id}" attribute "${attribute.key}" label`,
          );
          if (!attribute.key.startsWith(ownedPrefix(manifest.id))) {
            fail(
              `Attribute "${attribute.key}" must be namespaced to module "${manifest.id}".`,
            );
          }
          if (localAttributes.has(attribute.key)) {
            fail(
              `Module "${manifest.id}" declares attribute "${attribute.key}" more than once.`,
            );
          }
          const owner = attributeOwners.get(attribute.key);
          if (owner !== undefined) {
            fail(
              `Attribute "${attribute.key}" is declared by both "${owner}" and "${manifest.id}".`,
            );
          }
          localAttributes.add(attribute.key);
          attributeOwners.set(attribute.key, manifest.id);
          if (
            attribute.subjectKind !== "node" ||
            attribute.schema.type !== "integer" ||
            attribute.schema.minimum !== 0
          ) {
            fail(
              `Attribute "${attribute.key}" must be a node integer with minimum 0.`,
            );
          }
        }
    
        for (const view of manifest.views) {
          requireNonEmpty(view.id, `Module "${manifest.id}" view identifier`);
          requireNonEmpty(view.label, `Module "${manifest.id}" view "${view.id}" label`);
          if (!view.id.startsWith(ownedPrefix(manifest.id))) {
            fail(`View "${view.id}" must be namespaced to module "${manifest.id}".`);
          }
          const owner = viewOwners.get(view.id);
          if (owner !== undefined) {
            fail(
              `View "${view.id}" is registered by both "${owner}" and "${manifest.id}".`,
            );
          }
          viewOwners.set(view.id, manifest.id);
          const keys = new Set<string>();
          for (const key of view.attributeKeys) {
            if (!localAttributes.has(key)) {
              fail(
                `View "${view.id}" references undeclared attribute "${key}".`,
              );
            }
            if (keys.has(key)) {
              fail(`View "${view.id}" references attribute "${key}" more than once.`);
            }
            keys.add(key);
          }
        }
      }
    }
    
    export function moduleSupport(
      manifests: readonly StaticModuleManifest[] = BUILTIN_MODULE_MANIFESTS,
    ): SupportedModules {
      validateModuleCatalog(manifests);
      return Object.fromEntries(
        [...manifests]
          .sort((left, right) => (left.id < right.id ? -1 : left.id > right.id ? 1 : 0))
          .map((manifest) => [
            manifest.id,
            {
              version: manifest.version,
              schemaVersion: manifest.schemaVersion,
            },
          ]),
      );
    }
    
    export function validateModuleContributions(
      graph: GraphDocument,
      manifests: readonly StaticModuleManifest[] = BUILTIN_MODULE_MANIFESTS,
    ): void {
      validateModuleCatalog(manifests);
      assertGraphDocument(graph);
    
      const manifestById = new Map(manifests.map((manifest) => [manifest.id, manifest]));
      const entryById = new Map(graph.modules.map((entry) => [entry.id, entry]));
      const attributeOwner = new Map(
        manifests.flatMap((manifest) =>
          manifest.attributes.map((attribute) => [attribute.key, manifest.id] as const),
        ),
      );
      const compatibleIds = new Set(
        manifests
          .filter((manifest) => {
            const entry = entryById.get(manifest.id);
            return entry !== undefined && isCompatibleEntry(entry, manifest);
          })
          .map((manifest) => manifest.id),
      );
      const allEvidenceReferences = referencedEvidenceIds(graph);
    
      for (const attribute of graph.attributes) {
        const owner = attributeOwner.get(attribute.key);
        if (owner !== undefined) {
          if (!entryById.has(owner)) {
            fail(
              `Attribute "${attribute.id}" uses owned key "${attribute.key}" without module "${owner}".`,
            );
          }
          if (compatibleIds.has(owner) && attribute.provenance.moduleId !== owner) {
            fail(
              `Attribute "${attribute.id}" shadows module-owned key "${attribute.key}".`,
            );
          }
        }
        if (
          compatibleIds.has(attribute.provenance.moduleId) &&
          owner !== attribute.provenance.moduleId
        ) {
          fail(
            `Module "${attribute.provenance.moduleId}" contributed undeclared attribute "${attribute.key}".`,
          );
        }
      }
    
      for (const moduleId of compatibleIds) {
        const expected = generateContribution(moduleId, graph);
        const actualAttributes = graph.attributes.filter(
          (attribute) => attribute.provenance.moduleId === moduleId,
        );
        if (!equalAttributes(actualAttributes, expected.attributes)) {
          fail(`Module "${moduleId}" attributes do not match their derivation inputs.`);
        }
    
        const expectedEvidenceById = new Map(
          expected.evidence.map((evidence) => [evidence.id, evidence]),
        );
        for (const [evidenceId, expectedEvidence] of expectedEvidenceById) {
          const actualEvidence = graph.evidence.find(
            (evidence) => evidence.id === evidenceId,
          );
          if (
            actualEvidence === undefined ||
            !equalCanonical(actualEvidence, expectedEvidence)
          ) {
            fail(
              `Module "${moduleId}" evidence "${evidenceId}" does not match its derivation inputs.`,
            );
          }
        }
      }
    
      for (const evidence of graph.evidence) {
        for (const manifest of manifests) {
          if (
            evidence.id.startsWith(evidencePrefix(manifest.id)) &&
            !entryById.has(manifest.id) &&
            !allEvidenceReferences.has(evidence.id)
          ) {
            fail(
              `Module-owned evidence "${evidence.id}" is present without module "${manifest.id}".`,
            );
          }
        }
        for (const moduleId of compatibleIds) {
          if (
            evidence.id.startsWith(evidencePrefix(moduleId)) &&
            !graph.attributes.some(
              (attribute) =>
                attribute.provenance.moduleId === moduleId &&
                (attribute.evidenceIds.includes(evidence.id) ||
                  attribute.provenance.evidenceIds.includes(evidence.id)),
            ) &&
            !graph.edges.some((edge) =>
              edge.provenance.evidenceIds.includes(evidence.id),
            ) &&
            !graph.attributes.some(
              (attribute) =>
                attribute.provenance.moduleId !== moduleId &&
                (attribute.evidenceIds.includes(evidence.id) ||
                  attribute.provenance.evidenceIds.includes(evidence.id)),
            )
          ) {
            fail(`Module "${moduleId}" has unreferenced evidence "${evidence.id}".`);
          }
        }
      }
    }
    
    export function composeModules(
      graph: GraphDocument,
      enabledModuleIds: readonly string[],
    ): GraphDocument {
      validateModuleCatalog(BUILTIN_MODULE_MANIFESTS);
      assertGraphDocument(graph);
      validateModuleContributions(graph);
    
      const manifestById = new Map<string, StaticModuleManifest>(
        BUILTIN_MODULE_MANIFESTS.map((manifest) => [manifest.id, manifest]),
      );
      const enabled = new Set<string>();
      for (const moduleId of enabledModuleIds) {
        if (enabled.has(moduleId)) {
          fail(`Configured module "${moduleId}" is duplicated.`);
        }
        if (!manifestById.has(moduleId)) {
          fail(`Configured module "${moduleId}" is not compiled into this generator.`);
        }
        enabled.add(moduleId);
      }
    
      for (const entry of graph.modules) {
        const manifest = manifestById.get(entry.id);
        if (
          manifest !== undefined &&
          (entry.version !== manifest.version ||
            entry.schemaVersion !== manifest.schemaVersion)
        ) {
          fail(
            `Module "${entry.id}" version ${entry.version} / schema ${entry.schemaVersion} is unsupported by this generator.`,
          );
        }
      }
    
      const knownIds = new Set<string>(manifestById.keys());
      const baseAttributes = graph.attributes.filter(
        (attribute) => !knownIds.has(attribute.provenance.moduleId),
      );
      const base: GraphDocument = {
        ...graph,
        modules: graph.modules.filter((entry) => !knownIds.has(entry.id)),
        attributes: baseAttributes,
        evidence: graph.evidence,
      };
      const retainedEvidenceIds = referencedEvidenceIds(base);
      base.evidence = graph.evidence.filter(
        (evidence) =>
          ![...knownIds].some((moduleId) =>
            evidence.id.startsWith(evidencePrefix(moduleId)),
          ) || retainedEvidenceIds.has(evidence.id),
      );
    
      const attributes = [...base.attributes];
      const evidence = [...base.evidence];
      const evidenceById = new Map(evidence.map((item) => [item.id, item]));
      const modules = [...base.modules];
    
      for (const moduleId of sorted(enabled)) {
        const manifest = manifestById.get(moduleId)!;
        const contribution = generateContribution(moduleId, base);
        modules.push(moduleEntry(manifest));
        attributes.push(...contribution.attributes);
        for (const item of contribution.evidence) {
          const existing = evidenceById.get(item.id);
          if (existing !== undefined) {
            if (!equalCanonical(existing, item)) {
              fail(`Evidence identifier "${item.id}" conflicts with module "${moduleId}".`);
            }
            continue;
          }
          evidence.push(item);
          evidenceById.set(item.id, item);
        }
      }
    
      const composed = canonicalizeGraphDocument({
        ...base,
        modules,
        attributes,
        evidence,
      });
      assertGraphDocument(composed);
      validateModuleContributions(composed);
      return composed;
    }
    
  • @topo/enrichment Open Dependency context by role: Build, test, docsOpen Dependency context by role: Development tools

    Parses and validates enrichment documents, reference membership and analysis hashes. The CLI, not this data package, executes the configured enrichment command. All declared internal dependencies (not runtime calls): @topo/enrichment -> @topo/schema [dependencies: workspace:*] Referenced by internal modules: @topo/cli -> @topo/enrichment [dependencies: workspace:*] @topo/site -> @topo/enrichment [dependencies: workspace:*] Stable drilldown identity: enrichment. Module-specific detail maps will be curated later; there is no placeholder target.

    packages/enrichment/package.json:1-28
    {
      "name": "@topo/enrichment",
      "version": "0.0.0",
      "private": true,
      "type": "module",
      "files": [
        "dist"
      ],
      "exports": {
        ".": {
          "types": "./dist/index.d.ts",
          "default": "./dist/index.js"
        }
      },
      "scripts": {
        "build": "tsc -b",
        "typecheck": "tsc -b --pretty false",
        "test": "vitest run"
      },
      "dependencies": {
        "@topo/schema": "workspace:*"
      },
      "devDependencies": {
        "typescript": "^7.0.2",
        "vite": "8.2.2",
        "vitest": "^5.0.0"
      }
    }
    
    packages/enrichment/src/enrichment.ts:1-130
    import {
      compareCodeUnits,
      serializeGraphDocument,
      serializeJson,
      type GraphDocument,
      type JsonValue,
    } from "@topo/schema";
    import type { AnalysisInput, EnrichmentDocument } from "./model.js";
    
    export const MAX_ENRICHMENT_BYTES = 4 * 1024 * 1024;
    
    export class EnrichmentValidationError extends Error {
      constructor(message: string) {
        super(message);
        this.name = "EnrichmentValidationError";
      }
    }
    
    function fail(path: string, message: string): never {
      throw new EnrichmentValidationError(`${path}: ${message}`);
    }
    
    function record(value: unknown, path: string, keys: string[]): Record<string, unknown> {
      if (value === null || typeof value !== "object" || Array.isArray(value) ||
          ![Object.prototype, null].includes(Object.getPrototypeOf(value))) {
        fail(path, "Expected a JSON object.");
      }
      for (const key of Object.keys(value)) {
        if (!keys.includes(key)) fail(`${path}.${key}`, "Unknown field.");
      }
      return value as Record<string, unknown>;
    }
    
    function references(value: unknown, path: string): string[] {
      if (!Array.isArray(value) || value.length > 10_000) fail(path, "Expected at most 10000 reference IDs.");
      const ids: string[] = [];
      for (const id of value) {
        if (typeof id !== "string" || !id.length) fail(path, "Reference IDs must be nonempty strings.");
        ids.push(id);
      }
      if (new Set(ids).size !== ids.length) fail(path, "Duplicate reference IDs.");
      return ids.sort(compareCodeUnits);
    }
    
    function serializeUnchecked(document: EnrichmentDocument): string {
      return serializeJson({
        schemaVersion: document.schemaVersion,
        analysisHash: document.analysisHash,
        provenance: document.provenance,
        comments: document.comments.map((comment) => ({
          text: comment.text, nodeIds: comment.nodeIds, evidenceIds: comment.evidenceIds,
        })),
      });
    }
    
    export function parseEnrichmentDocument(value: unknown): EnrichmentDocument {
      const input = record(value, "$", ["schemaVersion", "analysisHash", "provenance", "comments"]);
      if (input.schemaVersion !== "1.0") fail("$.schemaVersion", "Expected enrichment version 1.0.");
      if (typeof input.analysisHash !== "string" || !/^[a-f0-9]{64}$/.test(input.analysisHash)) {
        fail("$.analysisHash", "Expected a lowercase SHA-256 hash.");
      }
      if (input.provenance !== "inferred") fail("$.provenance", 'AI commentary must remain "inferred".');
      if (!Array.isArray(input.comments) || input.comments.length > 10_000) {
        fail("$.comments", "Expected at most 10000 comments.");
      }
      const comments = input.comments.map((value: unknown, index: number) => {
        const path = `$.comments[${index}]`;
        const comment = record(value, path, ["text", "nodeIds", "evidenceIds"]);
        if (typeof comment.text !== "string" || !comment.text.trim() || comment.text.length > 32_000) {
          fail(`${path}.text`, "Expected nonblank commentary of at most 32000 characters.");
        }
        const nodeIds = references(comment.nodeIds, `${path}.nodeIds`);
        const evidenceIds = references(comment.evidenceIds, `${path}.evidenceIds`);
        if (!nodeIds.length && !evidenceIds.length) fail(path, "Commentary needs a node or evidence reference.");
        return { text: comment.text, nodeIds, evidenceIds };
      });
      const document: EnrichmentDocument = {
        schemaVersion: "1.0", analysisHash: input.analysisHash, provenance: "inferred", comments,
      };
      if (new TextEncoder().encode(serializeUnchecked(document)).byteLength > MAX_ENRICHMENT_BYTES) {
        fail("$", "Canonical enrichment exceeds 4 MiB.");
      }
      return document;
    }
    
    export function validateEnrichmentReferences(document: EnrichmentDocument, graph: GraphDocument): void {
      const nodes = new Set(graph.nodes.map((node) => node.id));
      const evidence = new Set(graph.evidence.map((item) => item.id));
      for (const [index, comment] of document.comments.entries()) {
        for (const id of comment.nodeIds) {
          if (!nodes.has(id)) fail(`$.comments[${index}].nodeIds`, `Unknown node "${id}".`);
        }
        for (const id of comment.evidenceIds) {
          if (!evidence.has(id)) fail(`$.comments[${index}].evidenceIds`, `Unknown evidence "${id}".`);
        }
      }
    }
    
    export function serializeEnrichmentDocument(document: EnrichmentDocument): string {
      return serializeUnchecked(parseEnrichmentDocument(document));
    }
    
    function assertJson(value: unknown, ancestors = new Set<object>()): asserts value is JsonValue {
      if (value === null || typeof value === "string" || typeof value === "boolean") return;
      if (typeof value === "number" && Number.isFinite(value)) return;
      if (typeof value !== "object" || ancestors.has(value) ||
          (!Array.isArray(value) && ![Object.prototype, null].includes(Object.getPrototypeOf(value)))) {
        fail("$.dashboard", "Expected finite, acyclic JSON data.");
      }
      ancestors.add(value);
      try {
        for (const child of Array.isArray(value) ? value : Object.values(value)) assertJson(child, ancestors);
      } finally {
        ancestors.delete(value);
      }
    }
    
    export async function hashAnalysis(graph: GraphDocument, dashboard: unknown): Promise<string> {
      assertJson(dashboard);
      // Layout, authored views and AI output are not inputs to the static analysis.
      const content = `{"schemaVersion":"1.0","graph":${serializeGraphDocument(graph).trim()},"dashboard":${serializeJson(dashboard).trim()}}\n`;
      if (!globalThis.crypto?.subtle) throw new EnrichmentValidationError("Analysis hashing requires Web Crypto (localhost or HTTPS in a browser).");
      const digest = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(content));
      return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
    }
    
    export async function createAnalysisInput(graph: GraphDocument, dashboard: unknown): Promise<AnalysisInput> {
      assertJson(dashboard);
      return { schemaVersion: "1.0", analysisHash: await hashAnalysis(graph, dashboard), graph, dashboard };
    }
    
  • @topo/graph Open Graph projection and edge aggregationOpen Dependency context by role: Build, test, docsOpen Dependency context by role: Development tools

    Derives architecture, graph projections, aggregation, deterministic layout and layout deltas from validated source evidence. All declared internal dependencies (not runtime calls): @topo/graph -> @topo/schema [dependencies: workspace:*] Referenced by internal modules: @topo/cli -> @topo/graph [dependencies: workspace:*] @topo/views -> @topo/graph [dependencies: workspace:*] @topo/site -> @topo/graph [dependencies: workspace:*] @topo/modules -> @topo/graph [dependencies: workspace:*] Stable drilldown identity: graph. Open the source-backed sequence for this module's core algorithm.

    packages/graph/package.json:1-28
    {
      "name": "@topo/graph",
      "version": "0.0.0",
      "private": true,
      "type": "module",
      "files": [
        "dist"
      ],
      "exports": {
        ".": {
          "types": "./dist/index.d.ts",
          "default": "./dist/index.js"
        }
      },
      "scripts": {
        "build": "tsc -b",
        "typecheck": "tsc -b --pretty false",
        "test": "vitest run"
      },
      "dependencies": {
        "@topo/schema": "workspace:*"
      },
      "devDependencies": {
        "typescript": "^7.0.2",
        "vite": "8.2.2",
        "vitest": "^5.0.0"
      }
    }
    
    packages/graph/src/index.ts:1-5
    export * from "./canonical.js";
    export * from "./derive.js";
    export * from "./layout.js";
    export * from "./project.js";
    export * from "./types.js";
    

source-traced: cli to languages

Direct dependencies declaration; not a runtime call. See node details for the complete manifest relationship set.

packages/cli/package.json:1-40
{
  "name": "@topo/cli",
  "version": "0.0.0",
  "private": true,
  "type": "module",
  "bin": {
    "topo": "./dist/main.js"
  },
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "default": "./dist/index.js"
    }
  },
  "scripts": {
    "build": "tsc -b && node ../../scripts/package-skills.mjs",
    "typecheck": "tsc -b --pretty false",
    "test": "vitest run --no-file-parallelism"
  },
  "dependencies": {
    "@topo/diagram-core": "workspace:*",
    "@topo/enrichment": "workspace:*",
    "@topo/graph": "workspace:*",
    "@topo/languages": "workspace:*",
    "@topo/modules": "workspace:*",
    "@topo/reports": "workspace:*",
    "@topo/scanner": "workspace:*",
    "@topo/schema": "workspace:*",
    "@topo/site": "workspace:*",
    "@topo/story": "workspace:*",
    "@topo/views": "workspace:*",
    "@topo/workspace": "workspace:*"
  },
  "devDependencies": {
    "@types/node": "^22.20.1",
    "typescript": "^7.0.2",
    "vite": "8.2.2",
    "vitest": "^5.0.0"
  }
}

source-traced: languages to scanner

Direct dependencies declaration; not a runtime call. See node details for the complete manifest relationship set.

packages/languages/package.json:1-31
{
  "name": "@topo/languages",
  "version": "0.0.0",
  "private": true,
  "type": "module",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "default": "./dist/index.js"
    }
  },
  "scripts": {
    "build": "tsc -b",
    "typecheck": "tsc -b --pretty false",
    "test": "node --test test/*.test.mjs"
  },
  "dependencies": {
    "@topo/scanner": "workspace:*",
    "@topo/schema": "workspace:*",
    "typescript-compiler-api": "npm:typescript@6.0.3"
  },
  "optionalDependencies": {
    "@ast-grep/lang-rust": "0.0.7",
    "@ast-grep/napi": "0.45.3",
    "@iarna/toml": "2.2.5"
  },
  "devDependencies": {
    "@types/node": "^22",
    "typescript": "^7.0.2"
  }
}

source-traced: scanner to schema

Direct dependencies declaration; not a runtime call. See node details for the complete manifest relationship set.

packages/scanner/package.json:1-32
{
  "name": "@topo/scanner",
  "version": "0.0.0",
  "private": true,
  "type": "module",
  "files": [
    "dist"
  ],
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "default": "./dist/index.js"
    }
  },
  "scripts": {
    "build": "tsc -b",
    "fixture": "node dist/fixture.js",
    "typecheck": "tsc -b --pretty false",
    "test": "vitest run src"
  },
  "dependencies": {
    "@topo/schema": "workspace:*",
    "ignore": "^7.0.0",
    "typescript-compiler-api": "npm:typescript@6.0.3"
  },
  "devDependencies": {
    "@types/node": "^22.0.0",
    "typescript": "^7.0.2",
    "vite": "8.2.2",
    "vitest": "^5.0.0"
  }
}

source-traced: cli to diagram-core

Direct dependencies declaration; not a runtime call. See node details for the complete manifest relationship set.

packages/cli/package.json:1-40
{
  "name": "@topo/cli",
  "version": "0.0.0",
  "private": true,
  "type": "module",
  "bin": {
    "topo": "./dist/main.js"
  },
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "default": "./dist/index.js"
    }
  },
  "scripts": {
    "build": "tsc -b && node ../../scripts/package-skills.mjs",
    "typecheck": "tsc -b --pretty false",
    "test": "vitest run --no-file-parallelism"
  },
  "dependencies": {
    "@topo/diagram-core": "workspace:*",
    "@topo/enrichment": "workspace:*",
    "@topo/graph": "workspace:*",
    "@topo/languages": "workspace:*",
    "@topo/modules": "workspace:*",
    "@topo/reports": "workspace:*",
    "@topo/scanner": "workspace:*",
    "@topo/schema": "workspace:*",
    "@topo/site": "workspace:*",
    "@topo/story": "workspace:*",
    "@topo/views": "workspace:*",
    "@topo/workspace": "workspace:*"
  },
  "devDependencies": {
    "@types/node": "^22.20.1",
    "typescript": "^7.0.2",
    "vite": "8.2.2",
    "vitest": "^5.0.0"
  }
}

source-traced: diagram-core to story

Direct dependencies declaration; not a runtime call. See node details for the complete manifest relationship set.

packages/diagram-core/package.json:1-34
{
  "name": "@topo/diagram-core",
  "version": "0.0.0",
  "private": true,
  "type": "module",
  "files": [
    "dist",
    "archify-pin.json",
    "LICENSE",
    "THIRD_PARTY_NOTICES.md"
  ],
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "default": "./dist/index.js"
    }
  },
  "scripts": {
    "build": "tsc -b",
    "typecheck": "tsc -b --pretty false",
    "test": "tsc -b && node --test test/*.test.mjs"
  },
  "dependencies": {
    "@topo/story": "workspace:*",
    "@viz-js/viz": "3.30.0"
  },
  "peerDependencies": {
    "@jdylanmc/topo-archify": "0.1.0"
  },
  "devDependencies": {
    "@types/node": "^22",
    "typescript": "^7.0.2"
  }
}

source-traced: cli to workspace

Direct dependencies declaration; not a runtime call. See node details for the complete manifest relationship set.

packages/cli/package.json:1-40
{
  "name": "@topo/cli",
  "version": "0.0.0",
  "private": true,
  "type": "module",
  "bin": {
    "topo": "./dist/main.js"
  },
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "default": "./dist/index.js"
    }
  },
  "scripts": {
    "build": "tsc -b && node ../../scripts/package-skills.mjs",
    "typecheck": "tsc -b --pretty false",
    "test": "vitest run --no-file-parallelism"
  },
  "dependencies": {
    "@topo/diagram-core": "workspace:*",
    "@topo/enrichment": "workspace:*",
    "@topo/graph": "workspace:*",
    "@topo/languages": "workspace:*",
    "@topo/modules": "workspace:*",
    "@topo/reports": "workspace:*",
    "@topo/scanner": "workspace:*",
    "@topo/schema": "workspace:*",
    "@topo/site": "workspace:*",
    "@topo/story": "workspace:*",
    "@topo/views": "workspace:*",
    "@topo/workspace": "workspace:*"
  },
  "devDependencies": {
    "@types/node": "^22.20.1",
    "typescript": "^7.0.2",
    "vite": "8.2.2",
    "vitest": "^5.0.0"
  }
}

source-traced: cli to reports

Direct dependencies declaration; not a runtime call. See node details for the complete manifest relationship set.

packages/cli/package.json:1-40
{
  "name": "@topo/cli",
  "version": "0.0.0",
  "private": true,
  "type": "module",
  "bin": {
    "topo": "./dist/main.js"
  },
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "default": "./dist/index.js"
    }
  },
  "scripts": {
    "build": "tsc -b && node ../../scripts/package-skills.mjs",
    "typecheck": "tsc -b --pretty false",
    "test": "vitest run --no-file-parallelism"
  },
  "dependencies": {
    "@topo/diagram-core": "workspace:*",
    "@topo/enrichment": "workspace:*",
    "@topo/graph": "workspace:*",
    "@topo/languages": "workspace:*",
    "@topo/modules": "workspace:*",
    "@topo/reports": "workspace:*",
    "@topo/scanner": "workspace:*",
    "@topo/schema": "workspace:*",
    "@topo/site": "workspace:*",
    "@topo/story": "workspace:*",
    "@topo/views": "workspace:*",
    "@topo/workspace": "workspace:*"
  },
  "devDependencies": {
    "@types/node": "^22.20.1",
    "typescript": "^7.0.2",
    "vite": "8.2.2",
    "vitest": "^5.0.0"
  }
}

source-traced: cli to site

Direct dependencies declaration; not a runtime call. See node details for the complete manifest relationship set.

packages/cli/package.json:1-40
{
  "name": "@topo/cli",
  "version": "0.0.0",
  "private": true,
  "type": "module",
  "bin": {
    "topo": "./dist/main.js"
  },
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "default": "./dist/index.js"
    }
  },
  "scripts": {
    "build": "tsc -b && node ../../scripts/package-skills.mjs",
    "typecheck": "tsc -b --pretty false",
    "test": "vitest run --no-file-parallelism"
  },
  "dependencies": {
    "@topo/diagram-core": "workspace:*",
    "@topo/enrichment": "workspace:*",
    "@topo/graph": "workspace:*",
    "@topo/languages": "workspace:*",
    "@topo/modules": "workspace:*",
    "@topo/reports": "workspace:*",
    "@topo/scanner": "workspace:*",
    "@topo/schema": "workspace:*",
    "@topo/site": "workspace:*",
    "@topo/story": "workspace:*",
    "@topo/views": "workspace:*",
    "@topo/workspace": "workspace:*"
  },
  "devDependencies": {
    "@types/node": "^22.20.1",
    "typescript": "^7.0.2",
    "vite": "8.2.2",
    "vitest": "^5.0.0"
  }
}

source-traced: site to views

Direct dependencies declaration; not a runtime call. See node details for the complete manifest relationship set.

packages/site/package.json:1-38
{
  "name": "@topo/site",
  "version": "0.0.0",
  "private": true,
  "type": "module",
  "files": [
    "dist"
  ],
  "exports": {
    "./notices": "./dist/THIRD_PARTY_NOTICES.txt",
    "./data": {
      "types": "./src/data.ts",
      "default": "./dist/data-contract/data.js"
    }
  },
  "scripts": {
    "build": "node scripts/clean-dist.mjs && tsc -p tsconfig.json --noEmit && tsc -p tsconfig.data.json",
    "typecheck": "tsc -p tsconfig.json --noEmit --pretty false && yarn typecheck:browser",
    "typecheck:browser": "tsc -p tsconfig.browser-tests.json --noEmit --pretty false",
    "test": "vitest run --config vitest.config.ts",
    "test:browser": "playwright test --config playwright.config.mjs"
  },
  "dependencies": {
    "@topo/enrichment": "workspace:*",
    "@topo/graph": "workspace:*",
    "@topo/modules": "workspace:*",
    "@topo/schema": "workspace:*",
    "@topo/views": "workspace:*"
  },
  "devDependencies": {
    "@playwright/test": "^1.55.0",
    "@topo/diagram-core": "workspace:*",
    "@types/node": "^22.18.0",
    "typescript": "^7.0.2",
    "vite": "8.2.2",
    "vitest": "^5.0.0"
  }
}

source-traced: views to graph

Direct dependencies declaration; not a runtime call. See node details for the complete manifest relationship set.

packages/views/package.json:1-30
{
  "name": "@topo/views",
  "version": "0.0.0",
  "private": true,
  "type": "module",
  "files": [
    "dist"
  ],
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "default": "./dist/index.js"
    }
  },
  "scripts": {
    "build": "tsc -b",
    "typecheck": "tsc -b --pretty false",
    "test": "vitest run"
  },
  "dependencies": {
    "@topo/graph": "workspace:*",
    "@topo/schema": "workspace:*",
    "ignore": "^7.0.0"
  },
  "devDependencies": {
    "typescript": "^7.0.2",
    "vite": "8.2.2",
    "vitest": "^5.0.0"
  }
}

source-traced: site to enrichment

Direct dependencies declaration; not a runtime call. See node details for the complete manifest relationship set.

packages/site/package.json:1-38
{
  "name": "@topo/site",
  "version": "0.0.0",
  "private": true,
  "type": "module",
  "files": [
    "dist"
  ],
  "exports": {
    "./notices": "./dist/THIRD_PARTY_NOTICES.txt",
    "./data": {
      "types": "./src/data.ts",
      "default": "./dist/data-contract/data.js"
    }
  },
  "scripts": {
    "build": "node scripts/clean-dist.mjs && tsc -p tsconfig.json --noEmit && tsc -p tsconfig.data.json",
    "typecheck": "tsc -p tsconfig.json --noEmit --pretty false && yarn typecheck:browser",
    "typecheck:browser": "tsc -p tsconfig.browser-tests.json --noEmit --pretty false",
    "test": "vitest run --config vitest.config.ts",
    "test:browser": "playwright test --config playwright.config.mjs"
  },
  "dependencies": {
    "@topo/enrichment": "workspace:*",
    "@topo/graph": "workspace:*",
    "@topo/modules": "workspace:*",
    "@topo/schema": "workspace:*",
    "@topo/views": "workspace:*"
  },
  "devDependencies": {
    "@playwright/test": "^1.55.0",
    "@topo/diagram-core": "workspace:*",
    "@types/node": "^22.18.0",
    "typescript": "^7.0.2",
    "vite": "8.2.2",
    "vitest": "^5.0.0"
  }
}

source-traced: site to modules

Direct dependencies declaration; not a runtime call. See node details for the complete manifest relationship set.

packages/site/package.json:1-38
{
  "name": "@topo/site",
  "version": "0.0.0",
  "private": true,
  "type": "module",
  "files": [
    "dist"
  ],
  "exports": {
    "./notices": "./dist/THIRD_PARTY_NOTICES.txt",
    "./data": {
      "types": "./src/data.ts",
      "default": "./dist/data-contract/data.js"
    }
  },
  "scripts": {
    "build": "node scripts/clean-dist.mjs && tsc -p tsconfig.json --noEmit && tsc -p tsconfig.data.json",
    "typecheck": "tsc -p tsconfig.json --noEmit --pretty false && yarn typecheck:browser",
    "typecheck:browser": "tsc -p tsconfig.browser-tests.json --noEmit --pretty false",
    "test": "vitest run --config vitest.config.ts",
    "test:browser": "playwright test --config playwright.config.mjs"
  },
  "dependencies": {
    "@topo/enrichment": "workspace:*",
    "@topo/graph": "workspace:*",
    "@topo/modules": "workspace:*",
    "@topo/schema": "workspace:*",
    "@topo/views": "workspace:*"
  },
  "devDependencies": {
    "@playwright/test": "^1.55.0",
    "@topo/diagram-core": "workspace:*",
    "@types/node": "^22.18.0",
    "typescript": "^7.0.2",
    "vite": "8.2.2",
    "vitest": "^5.0.0"
  }
}