@maverickcer/env-cap 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +279 -0
- package/dist/.dts/build/assemble-project.d.ts +47 -0
- package/dist/.dts/build/assemble-project.d.ts.map +1 -0
- package/dist/.dts/build/change-model.d.ts +62 -0
- package/dist/.dts/build/change-model.d.ts.map +1 -0
- package/dist/.dts/build/check-artifacts.d.ts +48 -0
- package/dist/.dts/build/check-artifacts.d.ts.map +1 -0
- package/dist/.dts/build/citation-verification.d.ts +62 -0
- package/dist/.dts/build/citation-verification.d.ts.map +1 -0
- package/dist/.dts/build/compatibility.d.ts +76 -0
- package/dist/.dts/build/compatibility.d.ts.map +1 -0
- package/dist/.dts/build/contract-model.d.ts +92 -0
- package/dist/.dts/build/contract-model.d.ts.map +1 -0
- package/dist/.dts/build/deep-equal.d.ts +9 -0
- package/dist/.dts/build/deep-equal.d.ts.map +1 -0
- package/dist/.dts/build/deep-freeze.d.ts +20 -0
- package/dist/.dts/build/deep-freeze.d.ts.map +1 -0
- package/dist/.dts/build/dependency-graph.d.ts +168 -0
- package/dist/.dts/build/dependency-graph.d.ts.map +1 -0
- package/dist/.dts/build/dependency-model.d.ts +79 -0
- package/dist/.dts/build/dependency-model.d.ts.map +1 -0
- package/dist/.dts/build/discover.d.ts +25 -0
- package/dist/.dts/build/discover.d.ts.map +1 -0
- package/dist/.dts/build/display-path.d.ts +24 -0
- package/dist/.dts/build/display-path.d.ts.map +1 -0
- package/dist/.dts/build/docs.d.ts +176 -0
- package/dist/.dts/build/docs.d.ts.map +1 -0
- package/dist/.dts/build/env-example.d.ts +85 -0
- package/dist/.dts/build/env-example.d.ts.map +1 -0
- package/dist/.dts/build/errors.d.ts +78 -0
- package/dist/.dts/build/errors.d.ts.map +1 -0
- package/dist/.dts/build/evidence-cache.d.ts +74 -0
- package/dist/.dts/build/evidence-cache.d.ts.map +1 -0
- package/dist/.dts/build/evidence-model.d.ts +50 -0
- package/dist/.dts/build/evidence-model.d.ts.map +1 -0
- package/dist/.dts/build/evidence-reference.d.ts +67 -0
- package/dist/.dts/build/evidence-reference.d.ts.map +1 -0
- package/dist/.dts/build/evidence-snapshot.d.ts +123 -0
- package/dist/.dts/build/evidence-snapshot.d.ts.map +1 -0
- package/dist/.dts/build/exclusive-group.d.ts +19 -0
- package/dist/.dts/build/exclusive-group.d.ts.map +1 -0
- package/dist/.dts/build/finding-model.d.ts +79 -0
- package/dist/.dts/build/finding-model.d.ts.map +1 -0
- package/dist/.dts/build/generate-documentation.d.ts +176 -0
- package/dist/.dts/build/generate-documentation.d.ts.map +1 -0
- package/dist/.dts/build/generate-env-artifacts.d.ts +176 -0
- package/dist/.dts/build/generate-env-artifacts.d.ts.map +1 -0
- package/dist/.dts/build/generate-evidence.d.ts +77 -0
- package/dist/.dts/build/generate-evidence.d.ts.map +1 -0
- package/dist/.dts/build/generate-manifest.d.ts +101 -0
- package/dist/.dts/build/generate-manifest.d.ts.map +1 -0
- package/dist/.dts/build/generate-usage.d.ts +95 -0
- package/dist/.dts/build/generate-usage.d.ts.map +1 -0
- package/dist/.dts/build/generated-banner.d.ts +52 -0
- package/dist/.dts/build/generated-banner.d.ts.map +1 -0
- package/dist/.dts/build/glob.d.ts +18 -0
- package/dist/.dts/build/glob.d.ts.map +1 -0
- package/dist/.dts/build/governance-fields.d.ts +34 -0
- package/dist/.dts/build/governance-fields.d.ts.map +1 -0
- package/dist/.dts/build/humanize-key.d.ts +14 -0
- package/dist/.dts/build/humanize-key.d.ts.map +1 -0
- package/dist/.dts/build/index.d.ts +107 -0
- package/dist/.dts/build/index.d.ts.map +1 -0
- package/dist/.dts/build/lifecycle-model.d.ts +64 -0
- package/dist/.dts/build/lifecycle-model.d.ts.map +1 -0
- package/dist/.dts/build/link.d.ts +215 -0
- package/dist/.dts/build/link.d.ts.map +1 -0
- package/dist/.dts/build/literal-eval.d.ts +23 -0
- package/dist/.dts/build/literal-eval.d.ts.map +1 -0
- package/dist/.dts/build/live-expirations.d.ts +47 -0
- package/dist/.dts/build/live-expirations.d.ts.map +1 -0
- package/dist/.dts/build/manifest-snapshot.d.ts +229 -0
- package/dist/.dts/build/manifest-snapshot.d.ts.map +1 -0
- package/dist/.dts/build/manifest.d.ts +31 -0
- package/dist/.dts/build/manifest.d.ts.map +1 -0
- package/dist/.dts/build/map-utils.d.ts +8 -0
- package/dist/.dts/build/map-utils.d.ts.map +1 -0
- package/dist/.dts/build/ownership-model.d.ts +57 -0
- package/dist/.dts/build/ownership-model.d.ts.map +1 -0
- package/dist/.dts/build/parse.d.ts +199 -0
- package/dist/.dts/build/parse.d.ts.map +1 -0
- package/dist/.dts/build/reference-projections.d.ts +156 -0
- package/dist/.dts/build/reference-projections.d.ts.map +1 -0
- package/dist/.dts/build/resolution/resolve-import.d.ts +53 -0
- package/dist/.dts/build/resolution/resolve-import.d.ts.map +1 -0
- package/dist/.dts/build/resolution/resolve-package-schema.d.ts +83 -0
- package/dist/.dts/build/resolution/resolve-package-schema.d.ts.map +1 -0
- package/dist/.dts/build/resolution/resolve-tsconfig-paths.d.ts +101 -0
- package/dist/.dts/build/resolution/resolve-tsconfig-paths.d.ts.map +1 -0
- package/dist/.dts/build/resolution/resolve-within-root.d.ts +35 -0
- package/dist/.dts/build/resolution/resolve-within-root.d.ts.map +1 -0
- package/dist/.dts/build/resolve-import.d.ts +50 -0
- package/dist/.dts/build/resolve-import.d.ts.map +1 -0
- package/dist/.dts/build/resolve-package-schema.d.ts +99 -0
- package/dist/.dts/build/resolve-package-schema.d.ts.map +1 -0
- package/dist/.dts/build/resolve-tsconfig-paths.d.ts +100 -0
- package/dist/.dts/build/resolve-tsconfig-paths.d.ts.map +1 -0
- package/dist/.dts/build/resolve-within-root.d.ts +35 -0
- package/dist/.dts/build/resolve-within-root.d.ts.map +1 -0
- package/dist/.dts/build/sarif.d.ts +66 -0
- package/dist/.dts/build/sarif.d.ts.map +1 -0
- package/dist/.dts/build/scan-dependencies.d.ts +47 -0
- package/dist/.dts/build/scan-dependencies.d.ts.map +1 -0
- package/dist/.dts/build/sort-by-identity.d.ts +14 -0
- package/dist/.dts/build/sort-by-identity.d.ts.map +1 -0
- package/dist/.dts/build/source-position.d.ts +69 -0
- package/dist/.dts/build/source-position.d.ts.map +1 -0
- package/dist/.dts/build/tool-version.d.ts +8 -0
- package/dist/.dts/build/tool-version.d.ts.map +1 -0
- package/dist/.dts/build/types.d.ts +53 -0
- package/dist/.dts/build/types.d.ts.map +1 -0
- package/dist/.dts/build/usage-report.d.ts +124 -0
- package/dist/.dts/build/usage-report.d.ts.map +1 -0
- package/dist/.dts/cli/filesystem.d.ts +3 -0
- package/dist/.dts/cli/filesystem.d.ts.map +1 -0
- package/dist/.dts/eslint-plugin/glob.d.ts +18 -0
- package/dist/.dts/eslint-plugin/glob.d.ts.map +1 -0
- package/dist/.dts/eslint-plugin/index.d.ts +27 -0
- package/dist/.dts/eslint-plugin/index.d.ts.map +1 -0
- package/dist/.dts/eslint-plugin/no-node-fs.d.ts +25 -0
- package/dist/.dts/eslint-plugin/no-node-fs.d.ts.map +1 -0
- package/dist/.dts/eslint-plugin/no-raw-process-env.d.ts +23 -0
- package/dist/.dts/eslint-plugin/no-raw-process-env.d.ts.map +1 -0
- package/dist/.dts/evidence/define-projection.d.ts +51 -0
- package/dist/.dts/evidence/define-projection.d.ts.map +1 -0
- package/dist/.dts/evidence/index.d.ts +23 -0
- package/dist/.dts/evidence/index.d.ts.map +1 -0
- package/dist/.dts/helpers/index.d.ts +135 -0
- package/dist/.dts/helpers/index.d.ts.map +1 -0
- package/dist/.dts/helpers/processors.d.ts +32 -0
- package/dist/.dts/helpers/processors.d.ts.map +1 -0
- package/dist/.dts/helpers/validators.d.ts +68 -0
- package/dist/.dts/helpers/validators.d.ts.map +1 -0
- package/dist/.dts/node/index.d.ts +2 -0
- package/dist/.dts/node/index.d.ts.map +1 -0
- package/dist/.dts/runtime/cache.d.ts +20 -0
- package/dist/.dts/runtime/cache.d.ts.map +1 -0
- package/dist/.dts/runtime/create.d.ts +20 -0
- package/dist/.dts/runtime/create.d.ts.map +1 -0
- package/dist/.dts/runtime/document.d.ts +181 -0
- package/dist/.dts/runtime/document.d.ts.map +1 -0
- package/dist/.dts/runtime/errors.d.ts +55 -0
- package/dist/.dts/runtime/errors.d.ts.map +1 -0
- package/dist/.dts/runtime/index.d.ts +24 -0
- package/dist/.dts/runtime/index.d.ts.map +1 -0
- package/dist/.dts/runtime/registry.d.ts +12 -0
- package/dist/.dts/runtime/registry.d.ts.map +1 -0
- package/dist/.dts/runtime/reset.d.ts +8 -0
- package/dist/.dts/runtime/reset.d.ts.map +1 -0
- package/dist/.dts/runtime/types.d.ts +175 -0
- package/dist/.dts/runtime/types.d.ts.map +1 -0
- package/dist/.dts/runtime/validate.d.ts +14 -0
- package/dist/.dts/runtime/validate.d.ts.map +1 -0
- package/dist/build.cjs +83 -0
- package/dist/build.cjs.map +1 -0
- package/dist/build.d.cts +1 -0
- package/dist/build.d.ts +1 -0
- package/dist/build.js +19 -0
- package/dist/build.js.map +1 -0
- package/dist/cli/index.js +134 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/eslint-plugin/index.cjs +12 -0
- package/dist/eslint-plugin/index.cjs.map +1 -0
- package/dist/eslint-plugin/index.d.cts +1 -0
- package/dist/eslint-plugin/index.d.ts +1 -0
- package/dist/eslint-plugin/index.js +5 -0
- package/dist/eslint-plugin/index.js.map +1 -0
- package/dist/evidence.cjs +7 -0
- package/dist/evidence.cjs.map +1 -0
- package/dist/evidence.d.cts +1 -0
- package/dist/evidence.d.ts +1 -0
- package/dist/evidence.js +5 -0
- package/dist/evidence.js.map +1 -0
- package/dist/helpers.cjs +8 -0
- package/dist/helpers.cjs.map +1 -0
- package/dist/helpers.d.cts +1 -0
- package/dist/helpers.d.ts +1 -0
- package/dist/helpers.js +5 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index.cjs +15 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/node.cjs +13 -0
- package/dist/node.cjs.map +1 -0
- package/dist/node.d.cts +1 -0
- package/dist/node.d.ts +1 -0
- package/dist/node.js +7 -0
- package/dist/node.js.map +1 -0
- package/package.json +183 -0
- package/schemas/contract-model.schema.json +321 -0
- package/schemas/env-cap-report.schema.json +2369 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/build/display-path.ts","../src/build/source-position.ts","../src/build/citation-verification.ts","../src/build/deep-equal.ts","../src/build/evidence-model.ts","../src/build/evidence-snapshot.ts","../src/build/glob.ts","../src/build/discover.ts","../src/build/literal-eval.ts","../src/build/parse.ts","../src/build/map-utils.ts","../src/build/resolution/resolve-within-root.ts","../src/build/resolution/resolve-package-schema.ts","../src/build/resolution/resolve-tsconfig-paths.ts","../src/build/resolution/resolve-import.ts","../src/build/link.ts","../src/build/assemble-project.ts","../src/build/change-model.ts","../src/build/compatibility.ts","../src/build/sort-by-identity.ts","../src/build/governance-fields.ts","../src/build/contract-model.ts","../src/build/deep-freeze.ts","../src/build/scan-dependencies.ts","../src/build/generated-banner.ts","../src/build/dependency-graph.ts","../src/build/dependency-model.ts","../src/build/errors.ts","../src/build/exclusive-group.ts","../src/build/manifest.ts","../src/build/generate-manifest.ts","../src/build/usage-report.ts","../src/build/generate-usage.ts","../src/build/finding-model.ts","../src/build/humanize-key.ts","../src/evidence/define-projection.ts","../src/build/reference-projections.ts","../src/build/docs.ts","../src/build/env-example.ts","../src/build/live-expirations.ts","../src/build/generate-documentation.ts","../src/build/lifecycle-model.ts","../src/build/ownership-model.ts","../src/build/tool-version.ts","../src/build/generate-evidence.ts","../src/build/evidence-cache.ts","../src/build/generate-env-artifacts.ts","../src/build/check-artifacts.ts","../src/build/sarif.ts"],"names":["path","crypto","ts","isRecord","createRequire","fileExists","contractIdentity","byIdentity","relativizePosition","content"],"mappings":"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","file":"build.cjs","sourcesContent":["/**\n * Renders an absolute path for a human-facing generated artifact\n * (`ENVIRONMENT.md`/`OWNERSHIP.md`) or a root-relative canonical model field,\n * root-relative when possible. The one place this conversion lives -- every\n * model builder and renderer that needs \"the path as a reader should see it\"\n * goes through this, so two of them can never disagree about the form of the\n * same file's path (which would silently break every `${file}#${exportName}`\n * lookup that crosses between them).\n *\n * A `DiscoveredContract.file` keeps its own absolute path untouched -- that's\n * the correct, unambiguous fact, and what stays sane when discovery spans\n * multiple roots (a `packages`-discovered file living outside `root`\n * entirely, ADR 0014).\n */\n\nimport path from \"node:path\"\n\n/**\n * Renders `absolutePath` relative to `root`, POSIX-separated regardless of\n * platform (matching every other rendered path in this package's Markdown and\n * JSON output). Falls back to `absolutePath` itself, unchanged, whenever the\n * result would need to climb outside `root` (a `packages`-discovered file, or\n * any other path not under root) -- never manufactures a `../` escape, which\n * reads as a real relative path to a consumer and resolves to nothing useful.\n */\nexport function displayPath(root: string, absolutePath: string): string {\n const relative = path.relative(root, absolutePath)\n if (relative.startsWith(\"..\") || path.isAbsolute(relative)) return absolutePath\n return relative.split(path.sep).join(\"/\")\n}\n","import type ts from \"typescript\"\n\n/**\n * A precise pointer into a source file -- the shared shape every exact-position fact in the\n * build pipeline (declaration sites, usage sites, dynamic-access sites) uses, so a consumer never\n * has to reconcile three ad hoc `{ file; line; column }` shapes that happen to mean the same\n * thing. See ADR 0036.\n */\nexport interface SourcePosition {\n /** Root-relative, POSIX-separated. */\n readonly file: string\n /** 1-indexed line number. */\n readonly line: number\n /** 1-indexed column number. */\n readonly column: number\n}\n\n/**\n * `node`'s starting line/column within `sourceFile`, both 1-indexed -- TypeScript's own\n * `getLineAndCharacterOfPosition()` returns 0-indexed values for both. Callers combine this with\n * the file path they already have in scope to build a full {@link SourcePosition}; this returns\n * only the two numbers so it's usable identically whether the caller's `file` is already\n * root-relative or still absolute.\n */\nexport function positionOf(\n sourceFile: ts.SourceFile,\n node: ts.Node,\n): { line: number; column: number } {\n const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile))\n return { line: line + 1, column: character + 1 }\n}\n\n/**\n * Parses a developer-supplied `\"<relative-path>:<line>:<column>\"` citation\n * (a {@link runtime.VariableDocs.dynamicAccess} entry) into a\n * {@link SourcePosition}. Splits on the *last* two colons so a path\n * containing colons of its own (rare, but not impossible) still parses --\n * only the trailing `:<line>:<column>` is treated as position syntax.\n * Returns `undefined` for anything that isn't exactly that shape (missing\n * segments, a non-positive-integer line/column, an empty path) -- callers\n * treat that as a malformed citation, never a thrown error. See ADR 0037.\n */\nexport function parsePositionCitation(citation: string): SourcePosition | undefined {\n const match = /^(.+):(\\d+):(\\d+)$/.exec(citation)\n if (!match) return undefined\n const [, file, lineText, columnText] = match\n const line = Number(lineText)\n const column = Number(columnText)\n if (!file || line < 1 || column < 1) return undefined\n return { file, line, column }\n}\n\n/**\n * One developer-declared {@link runtime.VariableDocs.dynamicAccess} citation's\n * current acknowledgment state -- a claim, never an observation. Kept fully\n * separate from `VariableAccessStatus` (which stays exactly 3-valued and\n * purely AST-derived) so a developer's assertion can never make env-cap\n * claim it observed something it didn't. See\n * `evidence-snapshot.ts`'s `computeDynamicAccessAcknowledgments()` (where\n * this is computed) and ADR 0037.\n */\nexport interface DynamicAccessAssertion extends SourcePosition {\n /**\n * `\"fresh\"` -- the cited file currently exists and either matches the\n * committed baseline hash or has no baseline yet (a brand-new citation,\n * nothing to contradict it yet). `\"stale\"` -- the cited file exists but its\n * content has changed since the committed baseline. `\"missing\"` -- the\n * cited file no longer exists at all. Re-derived from scratch every run;\n * never cached across runs.\n */\n readonly acknowledgment: \"fresh\" | \"stale\" | \"missing\"\n /**\n * SHA-256 hex digest of the cited file's content *as observed this run* --\n * `undefined` iff `acknowledgment === \"missing\"` (nothing to hash). This is\n * the one field that makes freshness checking possible without a\n * snapshot-only shadow type: the live `EvidenceModel.dependency` a caller\n * gets back and the persisted evidence snapshot a later run reads back as\n * its baseline are the exact same shape -- this run's `contentHash` becomes\n * next run's comparison target directly. See `evidence-snapshot.ts` and\n * ADR 0037.\n */\n readonly contentHash: string | undefined\n}\n","/**\n * Re-verifies developer-declared `dynamicAccess` citations every run -- never\n * trusted forever (ADR 0037). Two independent steps, kept as two separate\n * functions rather than one, since they answer two different questions and\n * the second is a pure read over the first's result:\n *\n * - `buildCitationSnapshots` (this run, I/O): for every currently-declared\n * citation, resolves the cited file and computes a whole-file SHA-256, then\n * compares it against the *previous* evidence snapshot's recorded hash to\n * label the citation `\"fresh\"` / `\"stale\"` / `\"missing\"`. Existence is\n * always re-checked live, never trusted from either snapshot. A citation\n * with no previous baseline (the first time it's ever been seen) is\n * `\"fresh\"` -- there is nothing to contradict it yet. Never throws on a\n * missing file; that citation is simply labeled `\"missing\"`.\n * - `verifyDynamicAccessCitations` (pure): flattens that result down to just\n * the citations that need a human's attention -- every `\"stale\"`/`\"missing\"`\n * assertion, enriched with the owning contract's display name. These are the\n * direct input to `finding-model.ts`'s `STALE_DYNAMIC_ACCESS_CITATION` /\n * `MISSING_DYNAMIC_ACCESS_CITATION` findings.\n *\n * Deliberately separate from `evidence-snapshot.ts`'s own `diffContracts()`,\n * which stays synchronous and pure -- these are the only filesystem-touching,\n * citation-specific part of the evidence-snapshot lifecycle. A citation is\n * always a developer's *re-acknowledgment* that access happens, never a claim\n * env-cap itself observed anything: nothing here ever folds into the\n * AST-derived `VariableAccessStatus`.\n */\n\nimport crypto from \"node:crypto\"\nimport path from \"node:path\"\nimport type { EvidenceModel } from \"./evidence-model.js\"\nimport { displayPath } from \"./display-path.js\"\nimport type { DiscoveredContract } from \"./link.js\"\nimport { parsePositionCitation } from \"./source-position.js\"\nimport type { DynamicAccessAssertion, SourcePosition } from \"./source-position.js\"\n\n/** SHA-256 hex digest of `content` -- the committed-baseline mechanism `DynamicAccessAssertion.contentHash` and its acknowledgment check both rely on (ADR 0037). */\nfunction hashContent(content: string): string {\n return crypto.createHash(\"sha256\").update(content).digest(\"hex\")\n}\n\n/** Stable key {@link buildCitationSnapshots} and `dependency-graph.ts`'s consumer of it agree on -- `file` must be root-relative, POSIX-separated on both sides for a lookup to ever hit. */\nexport function dynamicAccessVariableIdentity(\n file: string,\n exportName: string,\n key: string,\n): string {\n return `${file}#${exportName}#${key}`\n}\n\n/** Every `contentHash` a previous evidence snapshot recorded, keyed by `${variableIdentity}#${file}:${line}:${column}` -- the baseline {@link buildCitationSnapshots} compares this run's freshly-computed hashes against. */\nfunction previousContentHashes(previous: EvidenceModel | undefined): ReadonlyMap<string, string> {\n const baselines = new Map<string, string>()\n for (const contract of previous?.dependency.contracts ?? []) {\n for (const variable of contract.variables) {\n for (const assertion of variable.dynamicAccessAssertions) {\n // Bypassing this guard would set `baselines.get(key)` to `undefined`\n // explicitly instead of leaving the key absent -- but `Map.get()`\n // on a genuinely-missing key ALSO returns `undefined`, and every\n // consumer (`buildCitationSnapshots`'s own `!baseline || ...`\n // check below) treats the two identically. Load-bearing for\n // TypeScript's own narrowing of `assertion.contentHash` to\n // `string` for the `Map<string, string>` value type. Hand-verified:\n // bypassing this and running the full `vitest run` leaves every\n // test but the tsc-backed json-schema one passing.\n // Stryker disable next-line ConditionalExpression\n if (assertion.contentHash === undefined) continue\n const identity = dynamicAccessVariableIdentity(\n contract.file,\n contract.exportName,\n variable.key,\n )\n baselines.set(\n `${identity}#${assertion.file}:${assertion.line}:${assertion.column}`,\n assertion.contentHash,\n )\n }\n }\n }\n return baselines\n}\n\n/**\n * Re-checks every current `dynamicAccess` citation against the previous\n * evidence snapshot's committed `contentHash` baseline. Existence is always\n * re-checked live (never trusted from either snapshot); content drift is\n * only detectable when a previous baseline exists at all -- a citation with\n * no previous baseline (first time it's ever been seen) is reported\n * `\"fresh\"`, matching the same \"nothing to contradict yet\" logic. See ADR\n * 0037.\n */\nexport async function buildCitationSnapshots(\n activeContracts: readonly DiscoveredContract[],\n previous: EvidenceModel | undefined,\n root: string,\n readFile: (filePath: string) => Promise<string>,\n): Promise<ReadonlyMap<string, readonly DynamicAccessAssertion[]>> {\n const previousBaselines = previousContentHashes(previous)\n\n const result = new Map<string, DynamicAccessAssertion[]>()\n for (const contract of activeContracts) {\n const file = displayPath(root, contract.file)\n for (const variable of contract.variables) {\n // Neither this fallback's own content, nor the early-`continue` two\n // lines down, is observable: a variable with no real citations to\n // report on ends up with `result` either lacking an entry for its\n // identity (with the `continue`) or holding one mapped to `[]`\n // (without it) -- and every consumer (`verifyDynamicAccessCitations`'s\n // own `acknowledgments.get(identity) ?? []`, and this module's only\n // production caller, `evidence-snapshot.ts`, which always re-derives\n // `acknowledgments` from these SAME `activeContracts` right before\n // verifying them) treats \"key absent\" and \"key present but empty\"\n // identically. Hand-verified: bypassing both (a poisoned fallback\n // array AND the `continue`) and running the full `vitest run` leaves\n // every test passing.\n // Stryker disable next-line ArrayDeclaration\n const citations = variable.evidence?.dynamicAccess ?? []\n // Stryker disable next-line ConditionalExpression\n if (citations.length === 0) continue\n\n const identity = dynamicAccessVariableIdentity(file, contract.exportName, variable.key)\n const assertions: DynamicAccessAssertion[] = []\n for (const citation of citations) {\n const position = parsePositionCitation(citation)\n if (!position) continue\n\n let acknowledgment: DynamicAccessAssertion[\"acknowledgment\"]\n let contentHash: string | undefined\n try {\n const content = await readFile(path.resolve(root, position.file))\n contentHash = hashContent(content)\n const baseline = previousBaselines.get(\n `${identity}#${position.file}:${position.line}:${position.column}`,\n )\n acknowledgment = !baseline || baseline === contentHash ? \"fresh\" : \"stale\"\n } catch {\n acknowledgment = \"missing\"\n contentHash = undefined\n }\n assertions.push({ ...position, acknowledgment, contentHash })\n }\n result.set(identity, assertions)\n }\n }\n return result\n}\n\n/** One `dynamicAccess` citation env-cap can no longer vouch for -- the direct input to `finding-model.ts`'s `\"STALE_DYNAMIC_ACCESS_CITATION\"`/`\"MISSING_DYNAMIC_ACCESS_CITATION\"` findings. See ADR 0037. */\nexport interface DynamicAccessCitationProblem {\n readonly contractName: string\n /** Root-relative, POSIX-separated. */\n readonly file: string\n readonly exportName: string\n /** The variable whose `dynamicAccess` citation this is. */\n readonly key: string\n /** Where the citation points -- not the variable's own declaration. */\n readonly position: SourcePosition\n readonly acknowledgment: \"stale\" | \"missing\"\n}\n\n/**\n * Flattens {@link buildCitationSnapshots}' result down to just the citations\n * that need attention -- every `\"stale\"`/`\"missing\"` assertion, enriched with\n * the owning contract's display name. `\"fresh\"` assertions are silently\n * omitted -- nothing to report about a citation that's still trustworthy.\n */\nexport function verifyDynamicAccessCitations(\n activeContracts: readonly DiscoveredContract[],\n root: string,\n acknowledgments: ReadonlyMap<string, readonly DynamicAccessAssertion[]>,\n): readonly DynamicAccessCitationProblem[] {\n const problems: DynamicAccessCitationProblem[] = []\n for (const contract of activeContracts) {\n const file = displayPath(root, contract.file)\n for (const variable of contract.variables) {\n const identity = dynamicAccessVariableIdentity(file, contract.exportName, variable.key)\n // This module's only production caller (`evidence-snapshot.ts`)\n // always builds `acknowledgments` from these SAME `activeContracts`\n // immediately before calling this -- an identity missing here\n // corresponds exactly to a variable `buildCitationSnapshots()` itself\n // skipped for having zero real citations, which has nothing to\n // report either way. Hand-verified: replacing the fallback with a\n // poisoned single-string array (the exact shape Stryker's own\n // `ArrayDeclaration` mutant produces) and running the full\n // `vitest run` leaves every test passing.\n // Stryker disable next-line ArrayDeclaration\n for (const assertion of acknowledgments.get(identity) ?? []) {\n if (assertion.acknowledgment === \"fresh\") continue\n problems.push({\n contractName: contract.contractName,\n file,\n exportName: contract.exportName,\n key: variable.key,\n position: { file: assertion.file, line: assertion.line, column: assertion.column },\n acknowledgment: assertion.acknowledgment,\n })\n }\n }\n }\n return problems\n}\n","/**\n * Structural equality for JSON-safe values -- `documentEnv()`'s `metadata` can hold an\n * object/array (ADR 0035), so two independently-declared-but-identical values are never `===`.\n * Values compared here are always JSON-safe (string/number/boolean/null/array/object,\n * recursively -- see `literal-eval.ts`), so this doesn't need to handle cycles, `Date`, `Map`, or\n * anything else `evaluateLiteral()` can never produce.\n */\nexport function deepEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true\n if (typeof a !== \"object\" || typeof b !== \"object\" || a === null || b === null) return false\n if (Array.isArray(a) || Array.isArray(b)) {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false\n return a.every((v, i) => deepEqual(v, b[i]))\n }\n const aKeys = Object.keys(a)\n const bKeys = Object.keys(b)\n if (aKeys.length !== bKeys.length) return false\n return aKeys.every(\n (key) =>\n key in b &&\n deepEqual((a as Record<string, unknown>)[key], (b as Record<string, unknown>)[key]),\n )\n}\n","import type { ChangeModel } from \"./change-model.js\"\nimport type { ContractModel } from \"./contract-model.js\"\nimport type { DependencyModel } from \"./dependency-model.js\"\nimport type { FindingModel } from \"./finding-model.js\"\nimport type { LifecycleModel } from \"./lifecycle-model.js\"\nimport type { OwnershipModel } from \"./ownership-model.js\"\n\n/**\n * Bump only when a reader could misinterpret the new shape of `EvidenceModel`\n * itself (not any one sub-model's own `<MODEL>_SCHEMA_VERSION`, which is\n * versioned independently) -- same rule every other canonical model follows.\n */\nexport const EVIDENCE_MODEL_SCHEMA_VERSION = 1\n\n/**\n * Who/when/what produced a given `EvidenceModel` instance. Caller-supplied,\n * never ambient-detected -- `generateEvidenceModel()` never shells out to\n * `git` itself, mirroring ADR 0012's live-expiration-callback precedent.\n */\nexport interface EvidenceProvenance {\n readonly generatedAt: string\n readonly toolVersion: string\n readonly commit: string | undefined\n}\n\n/**\n * The seventh canonical fact model (ADR 0024): the assembled union of the\n * other six, plus provenance, the immutable input every\n * `defineEvidenceProjection()` projector runs over (`env-cap/evidence`,\n * ADR 0031).\n *\n * @remarks\n * This type is the one intentional exception to `src/build/`'s zero-\n * cross-folder-import rule: `src/evidence/` imports it with `import type`\n * only (fully erased at compile time under `verbatimModuleSyntax`), the same\n * shape as `helpers`' single sanctioned edge onto `runtime` -- see\n * `specs/architecture.md`. `src/evidence/` never imports a *value* from\n * here, only this shape, so it stays isomorphic and Node-free. An actual\n * `EvidenceModel` instance is produced by {@link generateEvidenceModel}\n * (`env-cap/build`, Node-only), which runs discovery once,\n * builds all six sub-models, and `deepFreeze()`s the result.\n */\nexport interface EvidenceModel {\n readonly schemaVersion: typeof EVIDENCE_MODEL_SCHEMA_VERSION\n readonly provenance: EvidenceProvenance\n readonly contract: ContractModel\n readonly dependency: DependencyModel\n readonly ownership: OwnershipModel\n readonly lifecycle: LifecycleModel\n readonly finding: FindingModel\n readonly change: ChangeModel\n}\n","import path from \"node:path\"\nimport { buildCitationSnapshots, verifyDynamicAccessCitations } from \"./citation-verification.js\"\nimport type { DynamicAccessCitationProblem } from \"./citation-verification.js\"\nimport { deepEqual } from \"./deep-equal.js\"\nimport type { ContractRef } from \"./evidence-reference.js\"\nimport type { ContractModelContract, ContractModelVariable } from \"./contract-model.js\"\nimport type { EvidenceModel } from \"./evidence-model.js\"\nimport { EVIDENCE_MODEL_SCHEMA_VERSION } from \"./evidence-model.js\"\nimport type { DiscoveredContract } from \"./link.js\"\nimport type { ParseWarning } from \"./parse.js\"\nimport type { DynamicAccessAssertion } from \"./source-position.js\"\nimport type { BuildFileSystem } from \"./types.js\"\n\n/**\n * The persisted evidence artifact and everything that reads/diffs it.\n *\n * Not a sibling of `env.manifest.ts`. `env.manifest.ts` is a *runtime build\n * artifact* -- real TypeScript, imported and executed by the running\n * application. This module's own artifact is a *CI/reporting artifact*: the\n * literal `EvidenceModel` a caller gets back from `generateEvidenceModel()`,\n * serialized to disk, read only by `--check`, by CI tooling, and by whatever\n * a project's own reporting/projection code chooses to do with it -- never\n * imported by anything under `src/runtime/`, never a build input to the\n * application itself. Its location is never derived from a manifest's own\n * output path (there is no `<manifest>.snapshot.json` sidecar mechanism\n * anymore); a caller supplies it directly, independent of whether a `.ts`\n * manifest is even being generated at all.\n *\n * Two jobs, one file: this is both (a) the baseline `diffContracts()`\n * compares the current run's `ContractModel` against to produce\n * `ManifestChangeReport`, and (b) the committed-baseline content-hash source\n * `buildCitationSnapshots()` (`citation-verification.ts`) uses to tell a\n * \"fresh\" developer dynamic-access citation from a \"stale\" one (ADR 0037).\n * Whether a project commits this file to git or regenerates it fresh every CI\n * run is that project's call -- a missing file is always treated as the normal\n * first-run state, never an error.\n */\n\n/** One field's before/after value in a {@link ManifestContractUpdate} or {@link ManifestVariableUpdate}. */\nexport interface ManifestFieldChange {\n /** The changed field's name. */\n readonly field: string\n /** The value from the previous snapshot, or `undefined` if the field was unset. */\n readonly previous: string | undefined\n /** The value in the current run, or `undefined` if the field is now unset. */\n readonly current: string | undefined\n}\n\n/** Identifies one contract for {@link ManifestChangeReport} purposes -- see {@link ContractRef} for why neither a `contractName` nor a pre-formatted `identity` is carried here. */\nexport type ManifestContractRef = ContractRef\n\n/** Identifies one variable for {@link ManifestChangeReport} purposes -- its owning contract's identity plus its own key. See {@link ContractRef}. */\nexport interface ManifestVariableRef extends ContractRef {\n /** The environment variable name. */\n readonly key: string\n}\n\n/** A contract present in both snapshots, with at least one changed field. */\nexport interface ManifestContractUpdate extends ManifestContractRef {\n /** Every field that changed between the previous and current snapshot. */\n readonly changes: readonly ManifestFieldChange[]\n}\n\n/** A variable present in both snapshots, with at least one changed field. */\nexport interface ManifestVariableUpdate extends ManifestVariableRef {\n /** Every field that changed between the previous and current snapshot. */\n readonly changes: readonly ManifestFieldChange[]\n}\n\n/**\n * The result of diffing two `ContractModel.contracts` arrays -- see\n * `diffContracts()`. Comprehensive by construction: every own field of\n * `ContractModelContract`/`ContractModelVariable` (schema facts --\n * `hasDefault`/`processorSource`/`validatorSource`/... -- alongside\n * documented metadata) participates, and every discovered contract is\n * covered, not only active ones. A field-by-field, hand-maintained diff\n * (this module's previous design) would need updating by hand every time\n * Contract Model gains a field; the generic differ below can't drift out of\n * sync with the model it diffs.\n */\nexport interface ManifestChangeReport {\n /** Contracts present now but not in the previous snapshot. */\n readonly addedContracts: readonly ManifestContractRef[]\n /** Contracts present in the previous snapshot but not now. */\n readonly removedContracts: readonly ManifestContractRef[]\n /** Variables present now but not in the previous snapshot. */\n readonly addedVariables: readonly ManifestVariableRef[]\n /** Variables present in the previous snapshot but not now. */\n readonly removedVariables: readonly ManifestVariableRef[]\n /** Contracts present in both snapshots with at least one changed field. */\n readonly updatedContracts: readonly ManifestContractUpdate[]\n /** Variables present in both snapshots with at least one changed field. */\n readonly updatedVariables: readonly ManifestVariableUpdate[]\n}\n\n/** `${file}#${exportName}` -- built here, at the point of use, purely to key the two `Map`s `diffContracts()` matches previous against current with. Deliberately never stored on a ref; see {@link ContractRef}. */\nfunction contractIdentity(contract: ContractRef): string {\n return `${contract.file}#${contract.exportName}`\n}\n\nfunction toContractRef(contract: ContractModelContract): ManifestContractRef {\n return { file: contract.file, exportName: contract.exportName }\n}\n\nfunction toVariableRef(\n contract: ContractModelContract,\n variable: ContractModelVariable,\n): ManifestVariableRef {\n return { file: contract.file, exportName: contract.exportName, key: variable.key }\n}\n\n/** Any value → its diffable string form. Non-string values (including `undefined`, which passes through) render as their JSON text, so an object/array/number/boolean field is still comparable without a per-field type list. */\nfunction toComparable(value: unknown): string | undefined {\n // Bypassing this early return is behaviorally equivalent, not a real gap:\n // `JSON.stringify(undefined) === undefined` too (verified via a real\n // `node -e` check), so falling through to the final `return\n // JSON.stringify(value)` produces the identical `undefined` result either\n // way. Hand-verified: mutating this and running the real suite\n // (`vitest run test/build/evidence-snapshot.test.ts`) passes unchanged.\n // Stryker disable next-line ConditionalExpression\n if (value === undefined) return undefined\n if (typeof value === \"string\") return value\n return JSON.stringify(value)\n}\n\n/**\n * Walks every own key of `previous`/`current` (except `skipKeys`, the\n * identity fields already used to match this pair up), appending a\n * `ManifestFieldChange` for each that differs. Generic on purpose -- see\n * `ManifestChangeReport`'s own doc comment.\n */\nfunction genericFieldChanges(\n previous: Readonly<Record<string, unknown>>,\n current: Readonly<Record<string, unknown>>,\n skipKeys: ReadonlySet<string>,\n): ManifestFieldChange[] {\n const keys = new Set([...Object.keys(previous), ...Object.keys(current)])\n const changes: ManifestFieldChange[] = []\n for (const key of [...keys].sort()) {\n if (skipKeys.has(key)) continue\n const previousValue = previous[key]\n const currentValue = current[key]\n if (deepEqual(previousValue, currentValue)) continue\n // `metadata` is a free-form record (ADR 0035) -- reported per-key\n // (`metadata.<key>`), not as one opaque blob, so a report reader sees\n // exactly which key changed. Every other field (including every other\n // object-shaped one, e.g. `defaultValue`) is reported as a single,\n // whole-value change -- there's no equivalent \"named sub-keys a reader\n // would want broken out\" structure to any of them.\n if (key === \"metadata\") {\n changes.push(\n ...recordFieldChanges(\n previousValue as Readonly<Record<string, unknown>> | undefined,\n currentValue as Readonly<Record<string, unknown>> | undefined,\n ),\n )\n } else {\n changes.push({\n field: key,\n previous: toComparable(previousValue),\n current: toComparable(currentValue),\n })\n }\n }\n return changes\n}\n\n/** Per-key diff of the `metadata` record -- a changed, added, or removed key each become their own `metadata.<key>` field entry. */\nfunction recordFieldChanges(\n previous: Readonly<Record<string, unknown>> | undefined,\n current: Readonly<Record<string, unknown>> | undefined,\n): ManifestFieldChange[] {\n const keys = new Set([...Object.keys(previous ?? {}), ...Object.keys(current ?? {})])\n const changes: ManifestFieldChange[] = []\n for (const key of [...keys].sort()) {\n const previousValue = previous?.[key]\n const currentValue = current?.[key]\n if (!deepEqual(previousValue, currentValue))\n changes.push({\n field: `metadata.${key}`,\n previous: toComparable(previousValue),\n current: toComparable(currentValue),\n })\n }\n return changes\n}\n\n/**\n * Deterministic order for every array in a `ManifestChangeReport`: by file,\n * then export name, then (for a variable ref) key. Derives the same total\n * order the removed `identity` field's plain string comparison used to give,\n * from the identity fields themselves -- see {@link ContractRef}.\n */\nfunction byIdentity<T extends ContractRef & { key?: string }>(a: T, b: T): number {\n return (\n a.file.localeCompare(b.file) ||\n a.exportName.localeCompare(b.exportName) ||\n // The `?? \"\"` fallbacks themselves are unreachable through any real\n // array this function ever sorts: a `ManifestContractRef` never carries\n // a `key` at all, but its own array can never hold two entries sharing\n // both file+exportName (contracts are unique by that pair) so the key\n // term is never reached for them either way; a `ManifestVariableRef`'s\n // `key` is always a real, non-empty string, never `undefined`. Hand-\n // verified: mutating both fallbacks to a distinguishing sentinel and\n // running the real suite (this file plus\n // check-artifacts.test.ts/generate-evidence.test.ts) passes unchanged.\n // Stryker disable next-line StringLiteral\n (a.key ?? \"\").localeCompare(b.key ?? \"\")\n )\n}\n\n/**\n * Pure. `previous === undefined` (no snapshot last time, for any reason --\n * see `EvidenceSnapshotReadResult`) reports everything in `current` as\n * added, nothing as removed/updated.\n */\nexport function diffContracts(\n previous: readonly ContractModelContract[] | undefined,\n current: readonly ContractModelContract[],\n): ManifestChangeReport {\n const previousContracts = new Map((previous ?? []).map((c) => [contractIdentity(c), c]))\n const currentContracts = new Map(current.map((c) => [contractIdentity(c), c]))\n\n const addedContracts: ManifestContractRef[] = []\n const removedContracts: ManifestContractRef[] = []\n const updatedContracts: ManifestContractUpdate[] = []\n const addedVariables: ManifestVariableRef[] = []\n const removedVariables: ManifestVariableRef[] = []\n const updatedVariables: ManifestVariableUpdate[] = []\n\n for (const [identity, currentContract] of currentContracts) {\n const previousContract = previousContracts.get(identity)\n\n if (!previousContract) {\n addedContracts.push(toContractRef(currentContract))\n } else {\n const changes = genericFieldChanges(\n previousContract as unknown as Record<string, unknown>,\n currentContract as unknown as Record<string, unknown>,\n new Set([\n // \"file\"/\"exportName\" can never actually differ here: both\n // contracts of a matched pair share the same Map key\n // (`contractIdentity()`), itself derived from file+exportName, so\n // they're always structurally equal for two contracts matched\n // into one updatedContracts entry. Hand-verified equivalent via\n // direct mutation + a real suite run.\n // Stryker disable next-line StringLiteral\n \"file\",\n // Stryker disable next-line StringLiteral\n \"exportName\",\n // Genuinely skipped AND real-tested -- see \"does not report the\n // whole variables array as a changed field\" below.\n \"variables\",\n ]),\n )\n if (changes.length > 0) updatedContracts.push({ ...toContractRef(currentContract), changes })\n }\n\n // This `?? []` fallback only ever fires when `previousContract` itself\n // is undefined (a real contract's `.variables` is never undefined). In\n // that exact case, poisoning it with a garbage element is unobservable:\n // (a) `previousVariables.get(key)` below is only ever called with a REAL\n // current variable's key -- `.map((v) => [v.key, v])` on a garbage\n // STRING element reads `.key` off a string (always `undefined`), so the\n // poisoned entry's own Map key is `undefined`, which no real variable\n // key can ever equal; (b) the one place `previousVariables` is iterated\n // directly (the removed-variables loop below) is already gated by `if\n // (previousContract)`, itself proven redundant-but-narrowing above --\n // when `previousContract` is undefined, that loop never runs regardless\n // of what garbage this Map might contain. Hand-verified: mutating this\n // and running the real suite passes unchanged.\n // Stryker disable next-line ArrayDeclaration\n const previousVariables = new Map((previousContract?.variables ?? []).map((v) => [v.key, v]))\n const currentVariables = new Map(currentContract.variables.map((v) => [v.key, v]))\n\n for (const [key, currentVariable] of currentVariables) {\n const previousVariable = previousVariables.get(key)\n if (!previousVariable) {\n addedVariables.push(toVariableRef(currentContract, currentVariable))\n continue\n }\n // Same reasoning as the \"file\"/\"exportName\" skip above, one level\n // down: `previousVariable` and `currentVariable` are matched via this\n // exact same `key` (both retrieved by it), so their own `.key` fields\n // are always structurally equal -- `deepEqual`'s own equality check\n // already `continue`s past an unchanged \"key\" with or without this\n // skip. Hand-verified equivalent via direct mutation + a real suite\n // run (both the array and its one string element).\n // Stryker disable ArrayDeclaration,StringLiteral\n const changes = genericFieldChanges(\n previousVariable as unknown as Record<string, unknown>,\n currentVariable as unknown as Record<string, unknown>,\n new Set([\"key\"]),\n )\n // Stryker restore ArrayDeclaration,StringLiteral\n if (changes.length > 0)\n updatedVariables.push({ ...toVariableRef(currentContract, currentVariable), changes })\n }\n\n // Bypassing this guard is behaviorally equivalent, not a real gap:\n // `previousVariables` (above) is ALWAYS empty whenever `previousContract`\n // is undefined (its own `?? []` fallback), so the loop below is already\n // a no-op in that case regardless of this guard -- the guard exists only\n // so TypeScript narrows `previousContract` to `ContractModelContract`\n // (not `| undefined`) for `toVariableRef`'s first argument, the same\n // \"redundant at runtime, needed for TS narrowing\" class already\n // documented for `registry.ts`/`create.ts`/`check-artifacts.ts`. Hand-\n // verified: mutating this and running the real suite passes unchanged.\n // Stryker disable next-line ConditionalExpression\n if (previousContract) {\n for (const [key, previousVariable] of previousVariables) {\n if (!currentVariables.has(key))\n removedVariables.push(toVariableRef(previousContract, previousVariable))\n }\n }\n }\n\n for (const [identity, previousContract] of previousContracts) {\n if (currentContracts.has(identity)) continue\n removedContracts.push(toContractRef(previousContract))\n for (const variable of previousContract.variables)\n removedVariables.push(toVariableRef(previousContract, variable))\n }\n\n return {\n addedContracts: addedContracts.sort(byIdentity),\n removedContracts: removedContracts.sort(byIdentity),\n addedVariables: addedVariables.sort(byIdentity),\n removedVariables: removedVariables.sort(byIdentity),\n updatedContracts: updatedContracts.sort(byIdentity),\n updatedVariables: updatedVariables.sort(byIdentity),\n }\n}\n\n/** Distinguishes *why* there's no usable previous snapshot, rather than collapsing every case into a bare `undefined`. A missing file is the normal, silent, expected first-run/never-configured case. An unparseable file or a `schemaVersion` this build doesn't recognize are both real, diagnosable problems. */\nexport type EvidenceSnapshotReadResult =\n | { readonly status: \"missing\" }\n | { readonly status: \"invalid-json\"; readonly detail: string }\n | { readonly status: \"unsupported-version\"; readonly foundVersion: unknown }\n | { readonly status: \"ok\"; readonly snapshot: EvidenceModel }\n\nexport async function readEvidenceSnapshot(\n snapshotPath: string,\n fs: BuildFileSystem,\n): Promise<EvidenceSnapshotReadResult> {\n let text: string\n try {\n // \"utf8\" vs \"\" encoding equivalence, same established class as\n // resolve-package-schema.ts/evidence-cache.ts/evidence-fingerprint.ts:\n // the result is immediately JSON.parse()d below, and JSON.parse()\n // coerces a Buffer (what \"\" would return) via .toString() identically\n // to a decoded string for any valid-UTF-8 JSON text.\n // Stryker disable next-line StringLiteral\n text = await fs.readFile(snapshotPath, \"utf8\")\n } catch {\n return { status: \"missing\" }\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(text)\n } catch (error) {\n return {\n status: \"invalid-json\",\n detail: error instanceof Error ? error.message : String(error),\n }\n }\n\n const foundVersion = (parsed as { schemaVersion?: unknown } | null)?.schemaVersion\n if (foundVersion !== EVIDENCE_MODEL_SCHEMA_VERSION)\n return { status: \"unsupported-version\", foundVersion }\n\n return { status: \"ok\", snapshot: parsed as EvidenceModel }\n}\n\nexport async function writeEvidenceSnapshot(\n snapshotPath: string,\n snapshot: EvidenceModel,\n fs: BuildFileSystem,\n): Promise<void> {\n await fs.mkdir(path.dirname(snapshotPath), { recursive: true })\n // \"utf8\" vs \"\" encoding equivalence -- verified via a real `node -e`\n // byte-for-byte comparison of the two written files (both encodings write\n // a string's UTF-8 bytes identically; \"\" is not a special \"raw\" mode for\n // writeFile the way it changes readFile's return type).\n // Stryker disable next-line StringLiteral\n await fs.writeFile(snapshotPath, `${JSON.stringify(snapshot, null, 2)}\\n`, \"utf8\")\n}\n\n/**\n * `snapshot`, with two fields normalized to a constant -- the comparison\n * basis `--check` uses:\n *\n * - `provenance.generatedAt` is a live timestamp stamped fresh on every real\n * `generate` run; comparing it byte-for-byte against a\n * freshly-rendered-for-`--check` copy would report drift every single\n * time, even with zero real changes, since the two renders' timestamps\n * can never match. `toolVersion`/`commit` stay compared as-is -- both are\n * real, meaningfully-stable provenance across a `--check` run and the\n * `generate` run it's verifying, not something that varies on its own.\n * - `change` describes \"what's different from whatever snapshot was on disk\n * the moment this run computed it\" -- inherently not reproducible by a\n * second computation, since by the time `--check` re-derives it, the file\n * just written *is* the new baseline (the diff naturally comes back empty\n * against itself). This isn't drift; it's `change`'s own definition, so\n * `--check` doesn't attempt to re-verify it, the same treatment as\n * `generatedAt`.\n * - every `now`-relative expiry countdown -- `lifecycle.expiring[].daysRemaining`\n * and the day-count inside an `EXPIRED`/`EXPIRING_SOON` finding message -- is\n * the same class as `generatedAt`: a static `expiresAt` produces a different\n * number every day, so a committed artifact would go \"stale\" with zero real\n * edits. Normalized to a constant so `--check` (and the golden tests) verify\n * the substance, not the calendar. The raw `expiresAt` strings stay compared.\n */\n// A module-level `const` regex, evaluated once at module load -- the\n// documented Stryker \"static\" covered-mutant false-Survivor\n// (ignoreStatic + perTest can't attribute a mutant evaluated once at module\n// load, even with real, passing test coverage; see\n// [[feedback_stryker_mutation_score_formula]] and reference-projections.ts's\n// own identical pattern in both this package and data-cap). Confirmed here:\n// Stryker's own JSON report attributes both Regex mutants below to\n// test/cli/direct-run.test.ts's 3 unrelated tests, not to any test that\n// actually exercises this regex. Hand-verified killed instead: mutating\n// `\\d+` to `\\d` or `\\D+` and running the real suite\n// (`vitest run test/build/evidence-snapshot.test.ts`) fails the \"masks the\n// day count in EXPIRED/EXPIRING_SOON finding messages\" test (its \"15\n// day(s)\" fixture was chosen specifically to distinguish both mutants).\n// Stryker disable next-line Regex\nconst EXPIRY_DAY_COUNT = /\\b\\d+ day\\(s\\)/g\n\nexport function normalizeEvidenceSnapshotForComparison(snapshot: EvidenceModel): EvidenceModel {\n return {\n ...snapshot,\n provenance: { ...snapshot.provenance, generatedAt: \"\" },\n change: {\n ...snapshot.change,\n manifest: {\n addedContracts: [],\n removedContracts: [],\n addedVariables: [],\n removedVariables: [],\n updatedContracts: [],\n updatedVariables: [],\n },\n renamedVariables: [],\n },\n lifecycle: {\n ...snapshot.lifecycle,\n expiring: snapshot.lifecycle.expiring.map((entry) => ({ ...entry, daysRemaining: 0 })),\n },\n finding: {\n ...snapshot.finding,\n findings: snapshot.finding.findings.map((f) =>\n f.code === \"EXPIRED\" || f.code === \"EXPIRING_SOON\"\n ? { ...f, message: f.message.replace(EXPIRY_DAY_COUNT, \"N day(s)\") }\n : f,\n ),\n },\n }\n}\n\n/** Everything reading a previous evidence snapshot and diffing the current run against it produces, in one call. Never writes anything itself -- writing the fresh snapshot stays a separate, explicit step on the real write path. */\nexport interface EvidenceChangesComputation {\n readonly report: ManifestChangeReport\n /** Set only when the previous snapshot existed but was unusable (corrupt JSON or an unrecognized `schemaVersion`) -- never set for the ordinary \"no snapshot yet\" first-run case. */\n readonly readWarning: ParseWarning | undefined\n readonly dynamicAccessAcknowledgments: ReadonlyMap<string, readonly DynamicAccessAssertion[]>\n readonly dynamicAccessCitationProblems: readonly DynamicAccessCitationProblem[]\n}\n\n/**\n * The one I/O-performing helper every caller wanting change/citation-freshness\n * data shares: reads the previous evidence snapshot (if `snapshotPath` is\n * given and a file exists there), diffs the current run's `ContractModel`\n * against it, and re-checks every current `dynamicAccess` citation's\n * freshness. `snapshotPath` is always caller-supplied, directly -- there is\n * no derivation from a manifest's own output path.\n */\nexport async function computeEvidenceChanges(\n root: string,\n snapshotPath: string,\n activeContracts: readonly DiscoveredContract[],\n currentContracts: readonly ContractModelContract[],\n readFile: (filePath: string) => Promise<string>,\n fs: BuildFileSystem,\n): Promise<EvidenceChangesComputation> {\n const read = await readEvidenceSnapshot(snapshotPath, fs)\n\n let previous: EvidenceModel | undefined\n let readWarning: ParseWarning | undefined\n\n if (read.status === \"invalid-json\") {\n readWarning = {\n file: snapshotPath,\n message: `Evidence snapshot could not be parsed as JSON (${read.detail}); treating this run as if no previous snapshot existed.`,\n }\n } else if (read.status === \"unsupported-version\") {\n readWarning = {\n file: snapshotPath,\n message: `Evidence snapshot has schemaVersion ${JSON.stringify(read.foundVersion)}, which this version of env-cap does not understand (expected ${EVIDENCE_MODEL_SCHEMA_VERSION}); treating this run as if no previous snapshot existed.`,\n }\n }\n // A separate top-level `if`, not an `else if` chained onto the block\n // above -- deliberately, so this line's own disable comment (below)\n // reliably attaches to it (an `else if` chained after a closing `}` does\n // not, the same AST-leading-comment-attachment issue already documented\n // for a `catch` clause). Bypassing this condition is behaviorally\n // equivalent, not a real gap: by elimination, the only remaining status\n // once the two branches above don't match is \"missing\", whose\n // `EvidenceSnapshotReadResult` variant carries no `.snapshot` field at all\n // -- `read.snapshot` reads `undefined` off it either way, identical to\n // `previous`'s own untouched initial value. Hand-verified: mutating this\n // and running the real suite (this file plus\n // check-artifacts.test.ts/generate-evidence.test.ts) passes unchanged.\n // Stryker disable next-line ConditionalExpression\n if (read.status === \"ok\") {\n previous = read.snapshot\n }\n\n const dynamicAccessAcknowledgments = await buildCitationSnapshots(\n activeContracts,\n previous,\n root,\n readFile,\n )\n\n return {\n report: diffContracts(previous?.contract.contracts, currentContracts),\n readWarning,\n dynamicAccessAcknowledgments,\n dynamicAccessCitationProblems: verifyDynamicAccessCitations(\n activeContracts,\n root,\n dynamicAccessAcknowledgments,\n ),\n }\n}\n","/**\n * Converts one glob pattern to a RegExp. Handles `**` as \"any number of path\n * segments, including zero\" (so `**\\/node_modules/**` matches a root-level\n * `node_modules`, and `**\\/env.schema.ts` matches a root-level file, not just\n * nested ones) -- a plain `**` -> `.*` substitution gets both of those wrong.\n *\n * Used by discover.ts's `include`/`exclude` schema-discovery walk.\n *\n * Deliberately duplicated (not shared) with\n * src/eslint-plugin/glob.ts, which needs the exact same matching behavior\n * for its own `allow` option -- keeps this build-only module free of any\n * import reaching outside src/build, so `src/build` stays independently\n * splittable into its own package with zero source-level cross-folder\n * dependency. Not re-exported from `./index.js` -- Private tier per\n * VERSIONING.md.\n */\n/* jscpd:ignore-start -- deliberately duplicated across the build/ and eslint-plugin/ bundle boundaries; see this file's module doc */\nexport function globToRegExp(pattern: string): RegExp {\n let out = \"\"\n for (let i = 0; i < pattern.length; i++) {\n const char = pattern[i]\n if (char === \"*\" && pattern[i + 1] === \"*\") {\n const precededBySlashOrStart = i === 0 || pattern[i - 1] === \"/\"\n const followedBySlash = pattern[i + 2] === \"/\"\n if (precededBySlashOrStart && followedBySlash) {\n out += \"(?:.*/)?\"\n i += 2 // consume the second '*' and the following '/'\n } else {\n out += \".*\"\n i += 1 // consume the second '*'\n }\n } else if (char === \"*\") {\n out += \"[^/]*\"\n } else if (char === \"?\") {\n out += \"[^/]\"\n } else if (\".+^${}()|[]\\\\\".includes(char)) {\n out += `\\\\${char}`\n } else {\n out += char\n }\n }\n return new RegExp(`^${out}$`)\n}\n/* jscpd:ignore-end */\n","import path from \"node:path\"\nimport { globToRegExp } from \"./glob.js\"\nimport type { BuildFileSystem } from \"./types.js\"\n\n/** Options for {@link discoverSchemaFiles}. */\nexport interface DiscoverOptions {\n /** The filesystem capability -- `./build` never imports `node:fs` (ADR 0040). */\n readonly fs: BuildFileSystem\n /** Absolute path to search under. */\n readonly root: string\n /** Glob patterns (relative to `root`) a file must match at least one of to be included. */\n readonly include: readonly string[]\n /** Glob patterns (relative to `root`) that prune a file or directory regardless of `include`. */\n readonly exclude: readonly string[]\n}\n\n// A predicate, not a module-level `Set` -- a `Set` of string literals is\n// evaluated once at module load, which `perTest` coverage analysis can't\n// attribute to a covering test (a documented Stryker false-Survivor; see\n// [[feedback_stryker_mutation_score_formula]]).\nfunction isAlwaysSkippedDirName(name: string): boolean {\n return name === \"node_modules\" || name === \".git\"\n}\n\n/**\n * Finds every schema file matching `include`/`exclude` under `root`, returned\n * as absolute paths in deterministic (alphabetically sorted) order.\n *\n * @remarks\n * No external glob dependency: directories are pruned *during* the walk\n * (both a hardcoded node_modules/.git skip and the caller's `exclude`\n * patterns), rather than walked in full and filtered afterward -- walking an\n * entire node_modules tree just to discard it is not acceptable for a tool\n * meant to run against real projects.\n */\nexport async function discoverSchemaFiles(options: DiscoverOptions): Promise<string[]> {\n const files = await walkDirectory(options.root, options.root, options.exclude, options.fs)\n\n const included = files.filter((file) => {\n const relativePath = toPosixRelative(options.root, file)\n return (\n matchesAnyPattern(relativePath, options.include) &&\n !matchesAnyPattern(relativePath, options.exclude)\n )\n })\n\n // Two-way compare only -- every entry is a distinct file's absolute path,\n // so `a === b` can never happen here (unlike a comparator keyed by a\n // free-form label, where an \"equal\" case is a real, reachable outcome).\n // `<=` vs `<` only changes tie-breaking when `a === b` -- impossible here:\n // `included` comes from a single directory walk that visits each real file\n // exactly once, so no two entries can ever be the same path. Hand-verified:\n // mutating this to `<=` and running the real suite passes unchanged.\n // Stryker disable next-line EqualityOperator\n return included.map((file) => path.normalize(file)).sort((a, b) => (a < b ? -1 : 1))\n}\n\nasync function walkDirectory(\n directory: string,\n root: string,\n exclude: readonly string[],\n fs: BuildFileSystem,\n): Promise<string[]> {\n const entries = await fs.readdir(directory, { withFileTypes: true })\n const results: string[] = []\n\n for (const entry of entries) {\n const fullPath = path.join(directory, entry.name)\n\n // entry.isDirectory()/isFile() reflect the raw directory-entry type\n // (lstat semantics), not a followed symlink -- a directory symlink is\n // therefore silently skipped here (neither branch below matches it),\n // which is also what makes this walk immune to a directory-symlink\n // cycle without any explicit visited-path guard. Switching either check\n // to something that follows symlinks (e.g. fs.statSync) would\n // reintroduce that infinite-recursion risk -- see\n // test/build/discover.test.ts's symlink-cycle regression test.\n if (entry.isDirectory()) {\n if (isAlwaysSkippedDirName(entry.name)) continue\n // Test as a directory (trailing slash) so a pattern like \"**/node_modules/**\"\n // -- which is meant to match *files inside* the directory -- also prunes\n // the directory itself before we ever read its contents.\n const relativeDir = `${toPosixRelative(root, fullPath)}/`\n if (matchesAnyPattern(relativeDir, exclude)) continue\n results.push(...(await walkDirectory(fullPath, root, exclude, fs)))\n continue\n }\n\n if (entry.isFile()) {\n results.push(fullPath)\n }\n }\n\n return results\n}\n\nfunction toPosixRelative(root: string, target: string): string {\n return path.relative(root, target).split(path.sep).join(\"/\")\n}\n\nfunction matchesAnyPattern(filePath: string, patterns: readonly string[]): boolean {\n return patterns.some((pattern) => globToRegExp(pattern).test(filePath))\n}\n","import ts from \"typescript\"\n\n/**\n * The result of a literal evaluation: either a real JS value, or `{ ok: false }` when the AST\n * expression wasn't a literal (or contained a non-literal element/property).\n */\nexport type LiteralEvalResult = { ok: true; value: unknown } | { ok: false }\n\n/**\n * Structurally evaluates a *literal* AST expression (strings, numbers, booleans, null, arrays,\n * and object literals of the same) into a real JS value -- without ever executing code.\n *\n * @remarks\n * Anything that isn't a literal (identifiers, calls, imports, template expressions with\n * interpolation) resolves to `{ ok: false }` rather than being guessed at.\n */\nexport function evaluateLiteral(node: ts.Expression): LiteralEvalResult {\n if (ts.isStringLiteralLike(node)) return { ok: true, value: node.text }\n if (ts.isNumericLiteral(node)) return { ok: true, value: Number(node.text) }\n if (node.kind === ts.SyntaxKind.TrueKeyword) return { ok: true, value: true }\n if (node.kind === ts.SyntaxKind.FalseKeyword) return { ok: true, value: false }\n if (node.kind === ts.SyntaxKind.NullKeyword) return { ok: true, value: null }\n\n if (ts.isParenthesizedExpression(node)) return evaluateLiteral(node.expression)\n\n if (ts.isPrefixUnaryExpression(node) && node.operator === ts.SyntaxKind.MinusToken) {\n const operand = evaluateLiteral(node.operand)\n return operand.ok && typeof operand.value === \"number\"\n ? { ok: true, value: -operand.value }\n : { ok: false }\n }\n\n if (ts.isArrayLiteralExpression(node)) {\n const values: unknown[] = []\n for (const element of node.elements) {\n // No explicit `ts.isSpreadElement(element)` check -- a spread element\n // doesn't match any of this function's other `if` branches either\n // (none of them recognize `SyntaxKind.SpreadElement`), so it already\n // falls through to the same `{ ok: false }` this line special-cased.\n const result = evaluateLiteral(element)\n if (!result.ok) return { ok: false }\n values.push(result.value)\n }\n return { ok: true, value: values }\n }\n\n if (ts.isObjectLiteralExpression(node)) {\n const record: Record<string, unknown> = {}\n for (const prop of node.properties) {\n if (!ts.isPropertyAssignment(prop)) return { ok: false }\n const key = getStaticPropertyName(prop.name)\n if (key === undefined) return { ok: false }\n const result = evaluateLiteral(prop.initializer)\n if (!result.ok) return { ok: false }\n record[key] = result.value\n }\n return { ok: true, value: record }\n }\n\n return { ok: false }\n}\n\n/** Reads a property name statically (identifier, string literal, or numeric literal) -- a computed key (e.g. `[expr]`) resolves to `undefined` rather than being guessed at. */\nexport function getStaticPropertyName(name: ts.PropertyName): string | undefined {\n if (ts.isIdentifier(name)) return name.text\n if (ts.isStringLiteralLike(name)) return name.text\n if (ts.isNumericLiteral(name)) return name.text\n return undefined\n}\n","import ts from \"typescript\"\nimport type { EnvGovernanceFields } from \"./governance-fields.js\"\nimport { evaluateLiteral, getStaticPropertyName } from \"./literal-eval.js\"\nimport { parsePositionCitation, positionOf } from \"./source-position.js\"\nimport type { SourcePosition } from \"./source-position.js\"\n\n// A quoted or computed property name (e.g. `\"FOO\\nBAR\"`) can hold arbitrary\n// text, not just a valid identifier. Since a discovered key is later written\n// verbatim into generated docs/.env.example (as `KEY=` lines and Markdown\n// headings) and is used as the schema's own object key at runtime, reject\n// anything that isn't a plausible env var name up front rather than letting\n// stray whitespace/`=`/etc. propagate into generated files.\n//\n// The pattern itself is duplicated (not a shared module-level `const`)\n// between `isValidEnvKey()` and the warning message below, deliberately --\n// Stryker marks a module-level regex literal `static: true` (evaluated once\n// at import time), which produces a false \"Survived\" on a mutant that's\n// genuinely, heavily test-covered (the same limitation already fixed for\n// `cli/index.ts`'s dispatch tables and `HELP_TEXT` this same drive). Keep\n// both copies in sync if the pattern ever changes.\n\n/** A recoverable issue found while statically parsing or linking one schema file -- never fatal, always surfaced to the caller as data. */\nexport interface ParseWarning {\n /** Absolute path of the file the warning applies to. */\n readonly file: string\n /** Human-readable explanation of what was skipped and why. */\n readonly message: string\n}\n\n/**\n * How a `createEnv`/`documentEnv` call's first argument resolves, before any\n * cross-file linking is attempted (that's `link.ts`'s job, not this file's --\n * this module only ever looks at one file's own AST).\n */\nexport type SchemaRef =\n | {\n /** Discriminant: the schema argument is an inline object literal. */\n readonly kind: \"literal\"\n /** The object literal AST node itself. */\n readonly node: ts.ObjectLiteralExpression\n }\n | {\n /** Discriminant: the schema argument is a bare identifier referencing a local `const`. */\n readonly kind: \"identifier\"\n /** The referenced identifier's name, not yet resolved to a declaration. */\n readonly name: string\n }\n | {\n /** Discriminant: the schema argument isn't statically resolvable (not a literal or identifier). */\n readonly kind: \"unresolvable\"\n }\n\n/** One `createEnv(...)` call site, as found by {@link parseSchemaFile}, before cross-file linking. */\ninterface RawCreateEnvCall {\n /** The binding name the call result is assigned to (must be exported to be usable -- see {@link parseSchemaFile}). */\n readonly exportName: string\n /** How the first (schema) argument resolves within this file. */\n readonly schemaRef: SchemaRef\n /** The second (options) argument expression, if the call passes one. */\n readonly optionsArg: ts.Expression | undefined\n /** The full call expression AST node. */\n readonly node: ts.CallExpression\n}\n\n/** One `documentEnv(...)` call site, as found by {@link parseSchemaFile}, before cross-file linking. */\ninterface RawDocumentEnvCall {\n /** How the first (schema) argument resolves within this file. */\n readonly schemaRef: SchemaRef\n /** The second (docs) argument expression, if the call passes one. */\n readonly docsArg: ts.Expression | undefined\n /** The full call expression AST node. */\n readonly node: ts.CallExpression\n}\n\n/** One named import binding, tracked only for relative specifiers (see {@link FileParseResult.imports}). */\nexport interface ImportBinding {\n /** The raw module specifier as written in the import (e.g. `\"./payments.schema.js\"`). */\n readonly specifier: string\n /** The name as exported by the source module -- accounts for `import { real as local }`. */\n readonly importedName: string\n}\n\n/** The raw, single-file facts extracted by {@link parseSchemaFile}. */\nexport interface FileParseResult {\n /** Absolute path of the parsed file. */\n readonly file: string\n /** The TypeScript AST for this file, reused by callers that need to inspect it further. */\n readonly sourceFile: ts.SourceFile\n /** Top-level `const NAME = {...}` object-literal declarations, whether exported or not. */\n readonly localConsts: ReadonlyMap<string, ts.ObjectLiteralExpression>\n /** Names of top-level `const` declarations that are exported (a subset of {@link localConsts}'s keys, plus non-object-literal exports). */\n readonly exportedConstNames: ReadonlySet<string>\n /** Local binding name -> where it came from. Only named imports of a relative specifier are tracked (namespace/default/bare-package imports are irrelevant to schema linking). */\n readonly imports: ReadonlyMap<string, ImportBinding>\n /** Every `createEnv(...)` call site found at the top level of this file. */\n readonly createEnvCalls: readonly RawCreateEnvCall[]\n /** Every `documentEnv(...)` call site found at the top level of this file. */\n readonly documentEnvCalls: readonly RawDocumentEnvCall[]\n /** Recoverable issues found while parsing this file. */\n readonly warnings: readonly ParseWarning[]\n}\n\n/**\n * Structurally parses one file's AST for everything the generator needs:\n * `createEnv(...)`/`documentEnv(...)` call sites, the local `const`\n * declarations and imports needed to resolve an identifier passed to either\n * of them.\n *\n * @remarks\n * Never type-checks or executes the file -- see `link.ts` for how\n * these raw facts get resolved into actual schema/docs data, including\n * across files.\n */\nexport function parseSchemaFile(filePath: string, sourceText: string): FileParseResult {\n const sourceFile = ts.createSourceFile(\n filePath,\n sourceText,\n ts.ScriptTarget.Latest,\n true,\n ts.ScriptKind.TS,\n )\n const warnings: ParseWarning[] = []\n\n const localConsts = new Map<string, ts.ObjectLiteralExpression>()\n const exportedConstNames = new Set<string>()\n const imports = new Map<string, ImportBinding>()\n const createEnvCalls: RawCreateEnvCall[] = []\n const documentEnvCalls: RawDocumentEnvCall[] = []\n\n for (const statement of sourceFile.statements) {\n if (ts.isImportDeclaration(statement)) {\n collectImportBindings(statement, imports)\n continue\n }\n\n if (!ts.isVariableStatement(statement)) continue\n const isExported =\n statement.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) ?? false\n\n for (const decl of statement.declarationList.declarations) {\n if (!ts.isIdentifier(decl.name) || !decl.initializer) continue\n const bindingName = decl.name.text\n\n if (ts.isObjectLiteralExpression(decl.initializer)) {\n localConsts.set(bindingName, decl.initializer)\n if (isExported) exportedConstNames.add(bindingName)\n continue\n }\n\n if (ts.isCallExpression(decl.initializer)) {\n if (isCallToName(decl.initializer, \"createEnv\")) {\n if (!isExported) {\n warnings.push({\n file: filePath,\n message: `createEnv() call for \"${bindingName}\" is not exported; it can never be included in a generated manifest, so it's skipped entirely.`,\n })\n continue\n }\n const [schemaArg, optionsArg] = decl.initializer.arguments\n createEnvCalls.push({\n exportName: bindingName,\n schemaRef: resolveSchemaRef(schemaArg),\n optionsArg,\n node: decl.initializer,\n })\n } else if (isCallToName(decl.initializer, \"documentEnv\")) {\n // `const x = documentEnv(...)` is unusual (it returns void) but not\n // an error -- treat it the same as a bare statement below.\n const [schemaArg, docsArg] = decl.initializer.arguments\n documentEnvCalls.push({\n schemaRef: resolveSchemaRef(schemaArg),\n docsArg,\n node: decl.initializer,\n })\n }\n }\n }\n }\n\n // documentEnv is normally a bare top-level statement: `documentEnv(schema, {...});`\n for (const statement of sourceFile.statements) {\n if (!ts.isExpressionStatement(statement)) continue\n const expr = statement.expression\n if (!ts.isCallExpression(expr) || !isCallToName(expr, \"documentEnv\")) continue\n const [schemaArg, docsArg] = expr.arguments\n documentEnvCalls.push({ schemaRef: resolveSchemaRef(schemaArg), docsArg, node: expr })\n }\n\n return {\n file: filePath,\n sourceFile,\n localConsts,\n exportedConstNames,\n imports,\n createEnvCalls,\n documentEnvCalls,\n warnings,\n }\n}\n\nfunction resolveSchemaRef(node: ts.Expression | undefined): SchemaRef {\n if (!node) return { kind: \"unresolvable\" }\n if (ts.isObjectLiteralExpression(node)) return { kind: \"literal\", node }\n if (ts.isIdentifier(node)) return { kind: \"identifier\", name: node.text }\n return { kind: \"unresolvable\" }\n}\n\n/**\n * Collects named import bindings from one `import` statement into `imports`, keyed by local name.\n *\n * @remarks\n * Exported for reuse by `scan-dependencies.ts`, which needs the same\n * alias-aware named-import tracking this file already does for schema\n * linking, just applied to arbitrary application source instead of schema\n * files.\n *\n * @param imports - Mutated in place; a binding re-collected under the same local name overwrites the previous entry.\n */\nexport function collectImportBindings(\n statement: ts.ImportDeclaration,\n imports: Map<string, ImportBinding>,\n): void {\n if (!ts.isStringLiteralLike(statement.moduleSpecifier)) return\n const specifier = statement.moduleSpecifier.text\n const namedBindings = statement.importClause?.namedBindings\n if (!namedBindings || !ts.isNamedImports(namedBindings)) return\n\n for (const element of namedBindings.elements) {\n const localName = element.name.text\n const importedName = element.propertyName?.text ?? localName\n imports.set(localName, { specifier, importedName })\n }\n}\n\nfunction isCallToName(call: ts.CallExpression, name: string): boolean {\n const expr = call.expression\n if (ts.isIdentifier(expr)) return expr.text === name\n if (ts.isPropertyAccessExpression(expr)) return expr.name.text === name\n return false\n}\n\n/**\n * A quoted or computed property name (e.g. `\"FOO\\nBAR\"`) can hold arbitrary\n * text -- reject anything that isn't a plausible env var name rather than\n * letting it propagate into generated files.\n */\nfunction isValidEnvKey(key: string): boolean {\n return /^[A-Za-z_][A-Za-z0-9_]*$/.test(key)\n}\n\n/** One schema entry's statically-discoverable shape -- presence facts, never evaluated/executed values. */\nexport interface DiscoveredSchemaVariable {\n /** The environment variable name (the schema's object key). */\n readonly key: string\n /** Whether the entry declares a `default`. */\n readonly hasDefault: boolean\n /** The default's statically-evaluated literal value, if `hasDefault` and it was a literal we could evaluate -- `{ ok: false }` when present but not statically resolvable, `undefined` when absent. */\n readonly defaultValue:\n | {\n /** Always `true` in this branch. */\n ok: true\n /** The evaluated literal value. */\n value: unknown\n }\n | {\n /** Always `false` in this branch: present but not statically resolvable. */\n ok: false\n }\n | undefined\n /** Whether the entry declares a `processor`. */\n readonly hasProcessor: boolean\n /** The processor function's source text, normalized to single-line, if `hasProcessor`. */\n readonly processorSource: string | undefined\n /** Only present when the processor has an explicit `: T` return type annotation -- the one thing we treat as provable. */\n readonly processorReturnType: string | undefined\n /** Whether the entry declares a `validator`. */\n readonly hasValidator: boolean\n /** The validator function's source text, normalized to single-line, if `hasValidator`. */\n readonly validatorSource: string | undefined\n /** The variable's statically-resolved `context`, if set to a non-empty string literal (see ADR 0022). `undefined` when absent, non-literal, or empty. */\n readonly context: string | undefined\n /** Where this variable's own schema property (e.g. `SESSION_SECRET: z.string()`) is declared -- distinct from the *contract's* `declaration`/`documentation` (`link.ts`); every variable has exactly one of these, always. See ADR 0036. */\n readonly declaration: SourcePosition\n}\n\n/**\n * Extracts one schema object literal's variables (processor/validator/default presence); never\n * evaluates or executes the schema.\n *\n * @param contextLabel - Used only to build human-readable warning messages (e.g. the contract's export name).\n * @param warnings - Mutated in place: one entry is pushed per skipped (non-static, invalid-key, or non-literal) property.\n */\nexport function extractSchemaVariables(\n schemaLiteral: ts.ObjectLiteralExpression,\n filePath: string,\n contextLabel: string,\n warnings: ParseWarning[],\n sourceFile: ts.SourceFile,\n): DiscoveredSchemaVariable[] {\n const variables: DiscoveredSchemaVariable[] = []\n\n for (const prop of schemaLiteral.properties) {\n if (!ts.isPropertyAssignment(prop)) {\n warnings.push({\n file: filePath,\n message: `Skipped a non-static schema entry in \"${contextLabel}\" (spread or computed key are not statically analyzable).`,\n })\n continue\n }\n const key = getStaticPropertyName(prop.name)\n if (key === undefined) continue\n\n if (!isValidEnvKey(key)) {\n warnings.push({\n file: filePath,\n message: `Skipped \"${key}\" in \"${contextLabel}\": not a valid environment variable name (expected ${/^[A-Za-z_][A-Za-z0-9_]*$/.toString()}); it will never appear in generated docs or .env.example output.`,\n })\n continue\n }\n\n if (!ts.isObjectLiteralExpression(prop.initializer)) {\n warnings.push({\n file: filePath,\n message: `Definition for \"${key}\" in \"${contextLabel}\" is not an inline object literal; skipping static analysis for this variable.`,\n })\n continue\n }\n\n const declaration: SourcePosition = { file: filePath, ...positionOf(sourceFile, prop) }\n variables.push(\n extractSchemaVariable(key, prop.initializer, filePath, contextLabel, warnings, declaration),\n )\n }\n\n return variables\n}\n\nfunction extractSchemaVariable(\n key: string,\n definition: ts.ObjectLiteralExpression,\n filePath: string,\n contextLabel: string,\n warnings: ParseWarning[],\n declaration: SourcePosition,\n): DiscoveredSchemaVariable {\n let hasDefault = false\n let defaultValue: DiscoveredSchemaVariable[\"defaultValue\"]\n let hasProcessor = false\n let processorSource: string | undefined\n let processorReturnType: string | undefined\n let hasValidator = false\n let validatorSource: string | undefined\n let context: string | undefined\n\n for (const prop of definition.properties) {\n if (!ts.isPropertyAssignment(prop)) continue\n const name = getStaticPropertyName(prop.name)\n\n if (name === \"default\") {\n hasDefault = true\n defaultValue = evaluateLiteral(prop.initializer)\n } else if (name === \"processor\") {\n hasProcessor = true\n processorSource = normalizeSource(prop.initializer.getText())\n processorReturnType = extractReturnType(prop.initializer)\n } else if (name === \"validator\") {\n hasValidator = true\n validatorSource = normalizeSource(prop.initializer.getText())\n } else if (name === \"context\") {\n // Never executed (ADR 0002) -- a non-literal (e.g. `context:\n // getContext()`) is skipped entirely, same \"warn/skip, never guess,\n // never execute\" policy as every other field here.\n const evaluated = evaluateLiteral(prop.initializer)\n if (evaluated.ok && typeof evaluated.value === \"string\" && evaluated.value.length > 0) {\n context = evaluated.value\n } else {\n warnings.push({\n file: filePath,\n message:\n evaluated.ok && evaluated.value === \"\"\n ? `\"context\" for \"${key}\" in \"${contextLabel}\" is an empty string; ignoring it -- validation contexts must be non-empty.`\n : `\"context\" for \"${key}\" in \"${contextLabel}\" is not a statically-resolvable string literal; ignoring it.`,\n })\n }\n }\n }\n\n return {\n key,\n hasDefault,\n defaultValue,\n hasProcessor,\n processorSource,\n processorReturnType,\n hasValidator,\n validatorSource,\n context,\n declaration,\n }\n}\n\nfunction extractReturnType(node: ts.Expression): string | undefined {\n if ((ts.isArrowFunction(node) || ts.isFunctionExpression(node)) && node.type) {\n // Replacing with `\"\"` (removal, not collapse-to-one-space) makes the `+`\n // quantifier unobservable: `\"a b\".replace(/\\s+/g,\"\")` and\n // `\"a b\".replace(/\\s/g,\"\")` both remove every whitespace char either\n // way, one match at a time or grouped -- the final string is identical\n // regardless of how many consecutive whitespace characters existed.\n // Empirically confirmed via a throwaway `node -e` comparison before\n // disabling (per the drive's established regex-boundary-verification\n // technique) -- contrast `normalizeSource()` below, whose OWN `+` IS\n // load-bearing, because it replaces with `\" \"` (a single space) instead.\n // Stryker disable next-line Regex\n return node.type.getText().replace(/\\s+/g, \"\")\n }\n return undefined\n}\n\nfunction normalizeSource(text: string): string {\n // `.trim()` is redundant given both call sites pass `node.getText()`\n // directly -- `ts.Node.getText()` returns exactly the node's own source\n // span, never with surrounding whitespace/trivia (hand-verified via a\n // throwaway `node -e` check against the real `typescript` package), so\n // there is never anything for `.trim()` to remove. Hand-verified further:\n // dropping `.trim()` here and running the real whole-package suite\n // (`vitest run`) passes unchanged.\n // Stryker disable next-line MethodExpression\n return text.replace(/\\s+/g, \" \").trim()\n}\n\n/** One variable's statically-extracted `documentEnv()` documentation, as declared in that call's `variables` entry for this key -- governance fields (`owner` .. `metadata`) are {@link EnvGovernanceFields}, resolved from static literals. */\nexport interface DiscoveredVariableDocs extends EnvGovernanceFields {\n /** The environment variable name this documentation applies to. */\n readonly key: string\n /** Statically-resolved `description`, if set to a string literal. */\n readonly description: string | undefined\n /** Statically-resolved `refreshInstructions`, if set to a string literal. */\n readonly refreshInstructions: string | undefined\n /** Statically-resolved `setupInstructions`, if set to a string literal. */\n readonly setupInstructions: string | undefined\n /** Statically-resolved `required`, if set to a boolean literal. */\n readonly required: boolean | undefined\n /** Statically-resolved `deprecated`, if set to a boolean literal. */\n readonly deprecated: boolean | undefined\n /** Statically-resolved `deprecatedReason`, if set to a string literal. */\n readonly deprecatedReason: string | undefined\n /** Statically-resolved `removeBy`, if set to a string literal. */\n readonly removeBy: string | undefined\n /** Statically-resolved `renamedFrom`, if set to a string literal. */\n readonly renamedFrom: string | undefined\n /** Statically-extracted `evidence` sub-object -- the re-verified-every-run half of a variable's documentation, kept structurally apart from the declared-only fields above. `undefined` when the declaration has no `evidence` key at all. See {@link runtime.VariableEvidenceDocs} and ADR 0037. */\n readonly evidence: DiscoveredVariableEvidence | undefined\n}\n\n/** The statically-extracted contents of one variable's `evidence` sub-object. See {@link runtime.VariableEvidenceDocs}. */\nexport interface DiscoveredVariableEvidence {\n /** Well-formed `\"path:line:column\"` entries from `evidence.dynamicAccess`, if set to an array of string literals -- a malformed entry warns and is dropped, never included here. See ADR 0037. */\n readonly dynamicAccess: readonly string[] | undefined\n}\n\n/** A contract's statically-extracted `documentEnv()` documentation. */\n/** The `documentEnv()` contract-level documentation, resolved from static literals at the parse stage. Its governance fields (`owner` .. `metadata`) are {@link EnvGovernanceFields}. */\nexport interface DiscoveredContractDocs extends EnvGovernanceFields {\n /** Statically-resolved `name`, if set to a string literal. */\n readonly name: string | undefined\n /** Statically-resolved `category`, if set to a string literal. */\n readonly category: string | undefined\n /** Statically-resolved `exclusiveGroup`, if set to a string literal. */\n readonly exclusiveGroup: string | undefined\n /** Defaults to `true` when the call's `active` field is absent or not statically resolvable. */\n readonly active: boolean\n /** Statically-resolved `deprecated`, if set to a boolean literal. */\n readonly deprecated: boolean | undefined\n /** Statically-resolved `deprecatedReason`, if set to a string literal. */\n readonly deprecatedReason: string | undefined\n /** Per-variable documentation, keyed by variable name. */\n readonly variables: ReadonlyMap<string, DiscoveredVariableDocs>\n}\n\n/**\n * Reads a `documentEnv()` call's second argument (the {@link runtime.ContractDocs} shape).\n *\n * @remarks\n * Anything not a statically-resolvable literal warns and is skipped (falls back to\n * \"not set\") rather than guessed at, same policy as schema-entry parsing.\n *\n * @param contextLabel - Used only to build human-readable warning messages.\n * @param warnings - Mutated in place: one entry is pushed per unresolvable field.\n */\nexport function extractContractDocs(\n docsArg: ts.Expression | undefined,\n filePath: string,\n contextLabel: string,\n warnings: ParseWarning[],\n): DiscoveredContractDocs {\n let name: string | undefined\n let category: string | undefined\n let exclusiveGroup: string | undefined\n let active = true\n let owner: string | undefined\n let sensitivity: string | undefined\n let expiresAt: string | undefined\n let deprecated: boolean | undefined\n let deprecatedReason: string | undefined\n let purpose: string | undefined\n let legalBasis: string | undefined\n let retention: string | undefined\n let dataResidency: string | readonly string[] | undefined\n let auditRequired: boolean | undefined\n let metadata: Record<string, unknown> | undefined\n const variables = new Map<string, DiscoveredVariableDocs>()\n\n if (!docsArg || !ts.isObjectLiteralExpression(docsArg)) {\n if (docsArg) {\n warnings.push({\n file: filePath,\n message: `documentEnv() call for \"${contextLabel}\" does not pass an inline object literal as its second argument; skipping it entirely.`,\n })\n }\n return {\n name,\n category,\n exclusiveGroup,\n active,\n owner,\n sensitivity,\n expiresAt,\n deprecated,\n deprecatedReason,\n purpose,\n legalBasis,\n retention,\n dataResidency,\n auditRequired,\n metadata,\n variables,\n }\n }\n\n for (const prop of docsArg.properties) {\n if (!ts.isPropertyAssignment(prop)) continue\n const propName = getStaticPropertyName(prop.name)\n\n if (propName === \"name\") {\n const evaluated = evaluateLiteral(prop.initializer)\n if (evaluated.ok && typeof evaluated.value === \"string\") name = evaluated.value\n } else if (propName === \"category\") {\n const evaluated = evaluateLiteral(prop.initializer)\n if (evaluated.ok && typeof evaluated.value === \"string\") {\n category = evaluated.value\n } else {\n warnings.push({\n file: filePath,\n message: `\"category\" for \"${contextLabel}\" is not a statically-resolvable string literal; ignoring it.`,\n })\n }\n } else if (propName === \"exclusiveGroup\") {\n const evaluated = evaluateLiteral(prop.initializer)\n if (evaluated.ok && typeof evaluated.value === \"string\") {\n exclusiveGroup = evaluated.value\n } else {\n warnings.push({\n file: filePath,\n message: `\"exclusiveGroup\" for \"${contextLabel}\" is not a statically-resolvable string literal; ignoring it.`,\n })\n }\n } else if (propName === \"active\") {\n const evaluated = evaluateLiteral(prop.initializer)\n if (evaluated.ok && typeof evaluated.value === \"boolean\") {\n active = evaluated.value\n } else {\n warnings.push({\n file: filePath,\n message: `\"active\" for \"${contextLabel}\" is not a statically-resolvable boolean literal; defaulting to active: true.`,\n })\n }\n } else if (propName === \"owner\") {\n const evaluated = evaluateLiteral(prop.initializer)\n if (evaluated.ok && typeof evaluated.value === \"string\") owner = evaluated.value\n } else if (propName === \"sensitivity\") {\n const evaluated = evaluateLiteral(prop.initializer)\n // Any string level is honored verbatim -- an org's own vocabulary is its\n // own. A level outside the standard set is reported separately, as a\n // non-blocking `NONSTANDARD_SENSITIVITY_LEVEL` finding\n // (`generate-documentation.ts`), never dropped here.\n if (evaluated.ok && typeof evaluated.value === \"string\") {\n sensitivity = evaluated.value\n } else {\n warnings.push({\n file: filePath,\n message: `\"sensitivity\" for \"${contextLabel}\" is not a statically-resolvable string literal; ignoring it.`,\n })\n }\n } else if (propName === \"expiresAt\") {\n const evaluated = evaluateLiteral(prop.initializer)\n if (evaluated.ok && typeof evaluated.value === \"string\") {\n expiresAt = evaluated.value\n } else {\n warnings.push({\n file: filePath,\n message: `\"expiresAt\" for \"${contextLabel}\" is not a statically-resolvable string literal; ignoring it.`,\n })\n }\n } else if (propName === \"deprecated\") {\n const evaluated = evaluateLiteral(prop.initializer)\n if (evaluated.ok && typeof evaluated.value === \"boolean\") {\n deprecated = evaluated.value\n } else {\n warnings.push({\n file: filePath,\n message: `\"deprecated\" for \"${contextLabel}\" is not a statically-resolvable boolean literal; ignoring it.`,\n })\n }\n } else if (propName === \"deprecatedReason\") {\n const evaluated = evaluateLiteral(prop.initializer)\n if (evaluated.ok && typeof evaluated.value === \"string\") deprecatedReason = evaluated.value\n } else if (propName === \"purpose\") {\n const evaluated = evaluateLiteral(prop.initializer)\n if (evaluated.ok && typeof evaluated.value === \"string\") purpose = evaluated.value\n } else if (propName === \"legalBasis\") {\n const evaluated = evaluateLiteral(prop.initializer)\n if (evaluated.ok && typeof evaluated.value === \"string\") legalBasis = evaluated.value\n } else if (propName === \"retention\") {\n const evaluated = evaluateLiteral(prop.initializer)\n if (evaluated.ok && typeof evaluated.value === \"string\") retention = evaluated.value\n } else if (propName === \"dataResidency\") {\n const evaluated = evaluateLiteral(prop.initializer)\n if (evaluated.ok && isStringOrStringArray(evaluated.value)) {\n dataResidency = evaluated.value\n } else {\n warnings.push({\n file: filePath,\n message: `\"dataResidency\" for \"${contextLabel}\" is not a statically-resolvable string or string array; ignoring it.`,\n })\n }\n } else if (propName === \"auditRequired\") {\n const evaluated = evaluateLiteral(prop.initializer)\n if (evaluated.ok && typeof evaluated.value === \"boolean\") auditRequired = evaluated.value\n } else if (propName === \"metadata\") {\n const evaluated = evaluateLiteral(prop.initializer)\n if (evaluated.ok && isRecord(evaluated.value)) {\n metadata = evaluated.value\n } else {\n warnings.push({\n file: filePath,\n message: `\"metadata\" for \"${contextLabel}\" is not a statically-resolvable object literal; ignoring it.`,\n })\n }\n } else if (propName === \"variables\") {\n if (ts.isObjectLiteralExpression(prop.initializer)) {\n extractVariableDocsMap(prop.initializer, filePath, contextLabel, warnings, variables)\n } else {\n warnings.push({\n file: filePath,\n message: `\"variables\" for \"${contextLabel}\" is not an inline object literal; per-variable documentation is skipped entirely.`,\n })\n }\n }\n }\n\n return {\n name,\n category,\n exclusiveGroup,\n active,\n owner,\n sensitivity,\n expiresAt,\n deprecated,\n deprecatedReason,\n purpose,\n legalBasis,\n retention,\n dataResidency,\n auditRequired,\n metadata,\n variables,\n }\n}\n\nfunction extractVariableDocsMap(\n variablesLiteral: ts.ObjectLiteralExpression,\n filePath: string,\n contextLabel: string,\n warnings: ParseWarning[],\n out: Map<string, DiscoveredVariableDocs>,\n): void {\n for (const prop of variablesLiteral.properties) {\n if (!ts.isPropertyAssignment(prop)) continue\n const key = getStaticPropertyName(prop.name)\n if (key === undefined) continue\n if (!ts.isObjectLiteralExpression(prop.initializer)) {\n warnings.push({\n file: filePath,\n message: `documentEnv() variable docs for \"${key}\" in \"${contextLabel}\" is not an inline object literal; skipped.`,\n })\n continue\n }\n\n let description: string | undefined\n let owner: string | undefined\n let sensitivity: string | undefined\n let expiresAt: string | undefined\n let refreshInstructions: string | undefined\n let setupInstructions: string | undefined\n let required: boolean | undefined\n let deprecated: boolean | undefined\n let deprecatedReason: string | undefined\n let removeBy: string | undefined\n let renamedFrom: string | undefined\n let purpose: string | undefined\n let legalBasis: string | undefined\n let retention: string | undefined\n let dataResidency: string | readonly string[] | undefined\n let auditRequired: boolean | undefined\n let metadata: Record<string, unknown> | undefined\n let evidence: DiscoveredVariableEvidence | undefined\n\n for (const field of prop.initializer.properties) {\n if (!ts.isPropertyAssignment(field)) continue\n const fieldName = getStaticPropertyName(field.name)\n // Both guards below are runtime-equivalent when bypassed -- `fieldName\n // === undefined`/`!evaluated.ok` never equal any of the string\n // literals/`.value` typeof checks the long else-if chain below\n // compares against (`undefined !== \"description\"`, etc., and an\n // ok:false result's `.value` is itself `undefined`, matching no\n // `typeof === T` check either) -- but they're still load-bearing for\n // TypeScript's own narrowing (`fieldName: string | undefined` ->\n // `string`, `evaluated: {ok:false} | {ok:true,value}` -> the ok:true\n // arm), which the real `tsc`-backed json-schema tests below this\n // function's call chain depend on. Hand-verified: bypassing both and\n // running the real whole-package suite (`vitest run`) only breaks\n // those two `tsc`-driven tests, no runtime-behavior assertion.\n // Stryker disable next-line ConditionalExpression\n if (fieldName === undefined) continue\n const evaluated = evaluateLiteral(field.initializer)\n // Stryker disable next-line ConditionalExpression\n if (!evaluated.ok) continue\n\n if (fieldName === \"description\" && typeof evaluated.value === \"string\")\n description = evaluated.value\n else if (fieldName === \"owner\" && typeof evaluated.value === \"string\") owner = evaluated.value\n else if (fieldName === \"sensitivity\" && typeof evaluated.value === \"string\")\n sensitivity = evaluated.value\n else if (fieldName === \"expiresAt\" && typeof evaluated.value === \"string\")\n expiresAt = evaluated.value\n else if (fieldName === \"refreshInstructions\" && typeof evaluated.value === \"string\")\n refreshInstructions = evaluated.value\n else if (fieldName === \"setupInstructions\" && typeof evaluated.value === \"string\")\n setupInstructions = evaluated.value\n else if (fieldName === \"required\" && typeof evaluated.value === \"boolean\")\n required = evaluated.value\n else if (fieldName === \"deprecated\" && typeof evaluated.value === \"boolean\")\n deprecated = evaluated.value\n else if (fieldName === \"deprecatedReason\" && typeof evaluated.value === \"string\")\n deprecatedReason = evaluated.value\n else if (fieldName === \"removeBy\" && typeof evaluated.value === \"string\")\n removeBy = evaluated.value\n else if (fieldName === \"renamedFrom\" && typeof evaluated.value === \"string\")\n renamedFrom = evaluated.value\n else if (fieldName === \"purpose\" && typeof evaluated.value === \"string\")\n purpose = evaluated.value\n else if (fieldName === \"legalBasis\" && typeof evaluated.value === \"string\")\n legalBasis = evaluated.value\n else if (fieldName === \"retention\" && typeof evaluated.value === \"string\")\n retention = evaluated.value\n else if (fieldName === \"dataResidency\" && isStringOrStringArray(evaluated.value))\n dataResidency = evaluated.value\n else if (fieldName === \"auditRequired\" && typeof evaluated.value === \"boolean\")\n auditRequired = evaluated.value\n else if (fieldName === \"metadata\" && isRecord(evaluated.value)) metadata = evaluated.value\n else if (fieldName === \"evidence\" && isRecord(evaluated.value)) {\n evidence = {\n dynamicAccess: extractDynamicAccessCitations(\n evaluated.value.dynamicAccess,\n filePath,\n key,\n contextLabel,\n warnings,\n ),\n }\n }\n }\n\n out.set(key, {\n key,\n description,\n owner,\n sensitivity,\n expiresAt,\n refreshInstructions,\n setupInstructions,\n required,\n deprecated,\n deprecatedReason,\n removeBy,\n renamedFrom,\n purpose,\n legalBasis,\n retention,\n dataResidency,\n auditRequired,\n metadata,\n evidence,\n })\n }\n}\n\n/**\n * Well-formed `\"path:line:column\"` citations from an `evidence.dynamicAccess`\n * value, warning on (and dropping) each malformed entry individually rather\n * than discarding the whole array -- one typo'd citation must never silently\n * take three good ones with it. `undefined` when the key is absent entirely\n * or isn't an array at all; an array of entries that are all malformed\n * yields an empty array, which is a different, honest fact (\"citations were\n * declared here, none of them usable\").\n */\nfunction extractDynamicAccessCitations(\n value: unknown,\n filePath: string,\n key: string,\n contextLabel: string,\n warnings: ParseWarning[],\n): readonly string[] | undefined {\n if (!Array.isArray(value)) return undefined\n const citations: string[] = []\n for (const entry of value) {\n // `parsePositionCitation()`'s own `RegExp.prototype.exec()` coerces its\n // argument to a string internally (the language spec's `ToString`, not\n // an explicit cast here) -- so bypassing this `typeof entry === \"string\"`\n // check doesn't skip validation, it just lets a non-string `entry` (a\n // number/boolean/null/array/object, the only shapes a JSON-safe literal\n // array element from `evaluateLiteral()` can produce) reach the SAME\n // regex, coerced to a string that can never plausibly match\n // `/^(.+):(\\d+):(\\d+)$/` (no realistic literal value stringifies to a\n // \"path:line:column\"-shaped triple). Hand-verified: bypassing this\n // clause and running the real whole-package suite (`vitest run`) passes\n // unchanged, including the existing malformed-entries fixture's own\n // non-string (`123`) element.\n // Stryker disable next-line ConditionalExpression\n if (typeof entry === \"string\" && parsePositionCitation(entry)) {\n citations.push(entry)\n } else {\n warnings.push({\n file: filePath,\n message: `documentEnv() \"evidence.dynamicAccess\" entry ${JSON.stringify(entry)} for \"${key}\" in \"${contextLabel}\" is not a well-formed \"path:line:column\" citation; ignoring it.`,\n })\n }\n }\n return citations\n}\n\n/** Reads `createEnv`'s second argument (the {@link runtime.CreateEnvOptions} shape) for just `name`, if it's a statically-resolvable string literal. Used only for the docs fallback chain (`documentEnv`'s `name` wins if set); `source` is runtime-only and never read here. */\nexport function extractCreateEnvOptionsName(\n optionsArg: ts.Expression | undefined,\n): string | undefined {\n if (!optionsArg || !ts.isObjectLiteralExpression(optionsArg)) return undefined\n for (const prop of optionsArg.properties) {\n if (!ts.isPropertyAssignment(prop)) continue\n if (getStaticPropertyName(prop.name) !== \"name\") continue\n const evaluated = evaluateLiteral(prop.initializer)\n if (evaluated.ok && typeof evaluated.value === \"string\") return evaluated.value\n }\n return undefined\n}\n\n/**\n * A plain object literal -- any value shape, since `evaluateLiteral()` already only ever produces\n * JSON-safe primitives/arrays/objects recursively (see literal-eval.ts). Deliberately not\n * `isStringRecord` anymore: `metadata` accepts any primitive or object value per key, not just\n * strings (ADR 0035).\n */\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n\nfunction isStringOrStringArray(value: unknown): value is string | readonly string[] {\n if (typeof value === \"string\") return true\n return Array.isArray(value) && value.every((v) => typeof v === \"string\")\n}\n","/**\n * `map.get(key)` after iterating `map`'s own `.keys()` is always defined --\n * this makes that invariant an explicit, named operation instead of a bare\n * `!` non-null assertion at each call site, with a real error (not a\n * silent `undefined`) if it's ever violated by a future bug.\n */\nexport function mustGet<K, V>(map: ReadonlyMap<K, V>, key: K): V {\n const value = map.get(key)\n if (value === undefined)\n throw new Error(`Internal error: expected key \"${String(key)}\" to be present in map.`)\n return value\n}\n","import path from \"node:path\"\nimport type { CompatibilityIssue } from \"../compatibility.js\"\n\nexport type ResolveWithinRootResult =\n | { readonly ok: true; readonly resolved: string }\n | { readonly ok: false; readonly issue: CompatibilityIssue }\n\n/**\n * Plain lexical bounds-check: is `targetPath` inside `baseDir`? Shared by\n * `resolveWithinRoot()` below (output paths, checked lexically since they\n * usually don't exist on disk yet) and `resolve-package-schema.ts` (which\n * additionally re-checks this against `fs.realpath`-resolved paths, since a\n * package-declared schema path both exists on disk and crosses a real trust\n * boundary -- see ADR 0014). Boundary-agnostic on purpose: neither caller's\n * notion of \"root\" is baked in here.\n */\nexport function isWithinDirectory(baseDir: string, targetPath: string): boolean {\n const relative = path.relative(baseDir, targetPath)\n return relative !== \"..\" && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative)\n}\n\n/**\n * Resolves `location` against `root` and checks the result doesn't escape it\n * (e.g. `location: \"../../malicious.ts\"`, or an absolute path on another\n * branch of the filesystem entirely). Discovery (`include`/`exclude`) is\n * already safe by construction -- it only ever walks *down* from `root` via\n * `readdir`, so a pattern can't make it read outside `root`. Output\n * locations have no such structural guarantee, since `path.resolve` happily\n * walks back out via `..` segments, so this is a plain lexical bounds-check\n * (not a symlink-aware `realpath` check -- these are *output* paths that\n * usually don't exist yet).\n *\n * Never throws itself -- returns a `CompatibilityIssue`-shaped finding on\n * escape so each generator function (`generateEnvManifest`, `generateDocumentation`,\n * `generateUsageReport`, `generateEnvArtifacts`) can wrap it in its own error type.\n */\nexport function resolveWithinRoot(\n root: string,\n location: string,\n optionName: string,\n functionName: string,\n): ResolveWithinRootResult {\n const resolved = path.resolve(root, location)\n if (!isWithinDirectory(root, resolved)) {\n return {\n ok: false,\n issue: {\n severity: \"error\",\n variable: optionName,\n files: [location],\n reason:\n `\"${optionName}\" (\"${location}\") resolves to \"${resolved}\", which is outside \"root\" (\"${root}\"). ` +\n `${functionName}() refuses to write outside root -- use a path nested under root instead.`,\n },\n }\n }\n return { ok: true, resolved }\n}\n","import { createRequire } from \"node:module\"\nimport path from \"node:path\"\nimport type { ParseWarning } from \"../parse.js\"\nimport type { BuildFileSystem } from \"../types.js\"\nimport { isWithinDirectory } from \"./resolve-within-root.js\"\n\n/**\n * Cross-package schema discovery (ADR 0014, Experimental -- see VERSIONING.md).\n *\n * Resolves an explicitly allow-listed installed package name to the one\n * schema file it declares via its own `\"envCap\": { \"schema\": \"<path>\" }`\n * package.json field. Every step here is `createRequire(...).resolve(...)`,\n * `fs.stat`/`fs.realpath`/`fs.readFile` on a path already fully known --\n * never a `readdir` walk of any directory, named package or not. This is a\n * completely separate code path from `discover.ts`'s `discoverSchemaFiles()`,\n * which continues to unconditionally prune `node_modules` during its own\n * walk exactly as before; the two never overlap.\n *\n * This module only ever locates a file. It never imports, requires, or\n * executes it -- a package-resolved file is fed into the exact same\n * `parseSchemaFile()`/AST-only pipeline as a locally-discovered file,\n * indistinguishable from it after resolution. See ADR 0002 and ADR 0014.\n */\n\nconst SCHEMA_FILE_EXTENSIONS = [\".ts\", \".tsx\"] as const\n\n/** 1 MiB. New hardening specific to this trust tier -- a package crosses a\n * real versioning/trust boundary that locally-discovered source doesn't,\n * so this caps the cost of parsing an oversized or adversarial file before\n * any of its content is even read into memory. See ADR 0014. */\nexport const MAX_PACKAGE_SCHEMA_FILE_BYTES = 1_048_576\n\nconst PACKAGE_JSON_ANCESTOR_SEARCH_LIMIT = 8\n\ntype PackageResolutionFailureCode =\n | \"PACKAGE_NOT_FOUND\"\n | \"MALFORMED_PACKAGE_JSON\"\n | \"FIELD_MISSING\"\n | \"INVALID_EXTENSION\"\n | \"OUTSIDE_PACKAGE\"\n | \"FILE_TOO_LARGE\"\n\n/** Both the authored and resolved forms are kept -- diagnostics benefit from\n * showing exactly what a package author wrote versus what it resolved to. */\nexport interface PackageOrigin {\n /** The allow-listed package name that declared this schema. */\n readonly packageName: string\n /** The `\"envCap.schema\"` value exactly as the package author wrote it. */\n readonly declaredField: string\n /** Absolute, realpath-canonicalized path to the resolved schema file. */\n readonly resolvedFile: string\n /** Absolute, realpath-canonicalized path to the package's own directory. */\n readonly packageDir: string\n}\n\nexport type PackageSchemaResolutionResult =\n | { readonly ok: true; readonly origin: PackageOrigin }\n | { readonly ok: false; readonly code: PackageResolutionFailureCode; readonly reason: string }\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null\n}\n\ninterface LocatedManifest {\n readonly packageJsonPath: string\n readonly packageDir: string\n}\n\n/**\n * Locates a package's own package.json (not a nested one) purely through\n * Node's own resolver, anchored at `root` -- behaves exactly as if the\n * consuming project's own code, at `root`, wrote `import \"<packageName>\"`,\n * so this works uniformly across npm/pnpm/yarn installs without any\n * package-manager-specific handling.\n */\nasync function locatePackageManifest(\n packageName: string,\n root: string,\n fs: BuildFileSystem,\n): Promise<LocatedManifest | undefined> {\n const req = createRequire(path.join(root, \"package.json\"))\n\n // Fast path: works whenever the package has no \"exports\" map, or its\n // \"exports\" map includes \"./package.json\" (this package's own does).\n try {\n const packageJsonPath = req.resolve(`${packageName}/package.json`)\n return { packageJsonPath, packageDir: path.dirname(packageJsonPath) }\n } catch {\n // Fall through -- the package's \"exports\" map likely omits\n // \"./package.json\" (ERR_PACKAGE_PATH_NOT_EXPORTED).\n }\n\n let mainFile: string\n try {\n mainFile = req.resolve(packageName)\n } catch {\n return undefined // not installed (MODULE_NOT_FOUND) or otherwise unresolvable\n }\n\n // Walk upward from the main entry looking for the package's own\n // package.json. Cannot stop at the *nearest* one: dual CJS/ESM packages\n // commonly ship decoy marker files (e.g. `dist/cjs/package.json`\n // containing only `{\"type\":\"commonjs\"}`, no \"name\" field) at intermediate\n // directory levels. Keep walking until a package.json's own \"name\" field\n // actually matches -- stopping earlier would silently miss a real\n // \"envCap\" field declared several levels further up.\n let dir = path.dirname(mainFile)\n for (let i = 0; i < PACKAGE_JSON_ANCESTOR_SEARCH_LIMIT; i++) {\n const candidate = path.join(dir, \"package.json\")\n try {\n // Same \"utf8\" vs \"\" encoding equivalence as resolveUncached's own read\n // above (JSON.parse coerces a Buffer via .toString() fine).\n // Stryker disable next-line StringLiteral\n const parsed: unknown = JSON.parse(await fs.readFile(candidate, \"utf8\"))\n if (isRecord(parsed) && parsed.name === packageName) {\n return { packageJsonPath: candidate, packageDir: dir }\n }\n } catch {\n // Not present, or not valid JSON, at this level -- keep walking.\n }\n const parent = path.dirname(dir)\n // Bypassing this early exit is a pure performance no-op, not a real\n // gap: when `parent === dir` (the real filesystem root), skipping the\n // break falls through to `dir = parent`, which reassigns `dir` to its\n // OWN current value -- the next iteration re-checks the exact same\n // `candidate` path, which already failed to match this iteration, and\n // keeps doing so until the loop's own iteration limit is exhausted.\n // Same terminal PACKAGE_NOT_FOUND outcome either way. Hand-verified:\n // mutating this and running the real suite passes unchanged.\n // Stryker disable next-line ConditionalExpression\n if (parent === dir) break // reached filesystem root\n dir = parent\n }\n return undefined\n}\n\nasync function resolveUncached(\n packageName: string,\n root: string,\n fs: BuildFileSystem,\n): Promise<PackageSchemaResolutionResult> {\n const located = await locatePackageManifest(packageName, root, fs)\n if (!located) {\n return {\n ok: false,\n code: \"PACKAGE_NOT_FOUND\",\n reason: `Package \"${packageName}\" listed in \"packages\" could not be resolved from \"${root}\" -- is it installed?`,\n }\n }\n const { packageJsonPath, packageDir } = located\n\n let manifest: unknown\n try {\n // The \"utf8\" encoding arg is equivalent to omitting it down to \"\": with\n // \"\" (or no encoding), fs.readFile returns a Buffer instead of a string,\n // but JSON.parse() coerces a Buffer via its own .toString() fine for any\n // valid-UTF-8 JSON text -- verified with a real `node -e` comparison\n // (same package-manifest fixture, both encodings, byte-identical parsed\n // result). Same equivalence class already documented for evidence-cache.ts\n // and evidence-fingerprint.ts's own \"utf8\" args.\n // Stryker disable next-line StringLiteral\n manifest = JSON.parse(await fs.readFile(packageJsonPath, \"utf8\"))\n } catch {\n return {\n ok: false,\n code: \"MALFORMED_PACKAGE_JSON\",\n reason: `\"${packageJsonPath}\" is not valid JSON.`,\n }\n }\n if (!isRecord(manifest)) {\n return {\n ok: false,\n code: \"MALFORMED_PACKAGE_JSON\",\n reason: `\"${packageJsonPath}\" does not contain a JSON object.`,\n }\n }\n\n const envCapField = manifest.envCap\n const declaredField =\n isRecord(envCapField) && typeof envCapField.schema === \"string\" ? envCapField.schema : undefined\n if (declaredField === undefined) {\n return {\n ok: false,\n code: \"FIELD_MISSING\",\n reason: `\"${packageName}\"'s package.json has no \"envCap.schema\" field (or it is not a string).`,\n }\n }\n\n const lexicallyResolved = path.resolve(packageDir, declaredField)\n if (!isWithinDirectory(packageDir, lexicallyResolved)) {\n return {\n ok: false,\n code: \"OUTSIDE_PACKAGE\",\n reason: `\"${packageName}\"'s \"envCap.schema\" (\"${declaredField}\") resolves outside its own package directory.`,\n }\n }\n\n if (!SCHEMA_FILE_EXTENSIONS.some((ext) => lexicallyResolved.endsWith(ext))) {\n return {\n ok: false,\n code: \"INVALID_EXTENSION\",\n reason: `\"${packageName}\"'s \"envCap.schema\" (\"${declaredField}\") must be a ${SCHEMA_FILE_EXTENSIONS.join(\"/\")} file, not compiled/bundled output.`,\n }\n }\n\n // Realpath-based containment check, on top of (not instead of) the lexical\n // check above: a symlink at the declared path could point anywhere on\n // disk without the *string* ever containing \"..\", and `packageDir` itself\n // is frequently a symlink under real-world installs (pnpm's\n // content-addressable store links every package in from elsewhere). A\n // symlink that resolves *within* the package directory is harmless and\n // allowed; only a real target outside it is rejected.\n let realFile: string\n let realPackageDir: string\n try {\n ;[realFile, realPackageDir] = await Promise.all([\n fs.realpath(lexicallyResolved),\n fs.realpath(packageDir),\n ])\n } catch {\n return {\n ok: false,\n code: \"OUTSIDE_PACKAGE\",\n reason: `\"${packageName}\"'s \"envCap.schema\" (\"${declaredField}\") does not resolve to a file that exists.`,\n }\n }\n if (!isWithinDirectory(realPackageDir, realFile)) {\n return {\n ok: false,\n code: \"OUTSIDE_PACKAGE\",\n reason: `\"${packageName}\"'s \"envCap.schema\" (\"${declaredField}\") resolves, after following symlinks, outside its own package directory.`,\n }\n }\n\n let stats\n try {\n stats = await fs.stat(realFile)\n } catch {\n return {\n ok: false,\n code: \"OUTSIDE_PACKAGE\",\n reason: `\"${packageName}\"'s \"envCap.schema\" (\"${declaredField}\") could not be read.`,\n }\n }\n if (!stats.isFile()) {\n return {\n ok: false,\n code: \"OUTSIDE_PACKAGE\",\n reason: `\"${packageName}\"'s \"envCap.schema\" (\"${declaredField}\") does not resolve to a regular file.`,\n }\n }\n if (stats.size > MAX_PACKAGE_SCHEMA_FILE_BYTES) {\n return {\n ok: false,\n code: \"FILE_TOO_LARGE\",\n reason: `\"${packageName}\"'s \"envCap.schema\" (\"${declaredField}\") is ${stats.size} bytes, exceeding the ${MAX_PACKAGE_SCHEMA_FILE_BYTES}-byte limit for a package-resolved schema file.`,\n }\n }\n\n return {\n ok: true,\n origin: { packageName, declaredField, resolvedFile: realFile, packageDir: realPackageDir },\n }\n}\n\n/**\n * Resolves one allow-listed package name. Memoized in a caller-owned\n * `cache` (one per `generate*()` invocation, shared with linking/dependency-\n * graph resolution) so a name referenced from multiple places -- multiple\n * scanned files bare-importing the same package, or a duplicate entry in\n * `packages` -- is only ever resolved once. The cache is populated with the\n * in-flight promise before it settles, so concurrent callers await the same\n * resolution rather than racing duplicate work.\n */\nexport function resolvePackageSchemaFile(\n packageName: string,\n root: string,\n cache: Map<string, Promise<PackageSchemaResolutionResult>>,\n fs: BuildFileSystem,\n): Promise<PackageSchemaResolutionResult> {\n let cached = cache.get(packageName)\n if (!cached) {\n cached = resolveUncached(packageName, root, fs)\n cache.set(packageName, cached)\n }\n return cached\n}\n\ninterface ResolvedPackageFile {\n readonly packageName: string\n readonly file: string\n}\n\nexport interface ResolvePackagesResult {\n readonly files: readonly ResolvedPackageFile[]\n /** Keyed by resolved file path, for `DiscoveredContract.packageOrigin` lookups downstream. */\n readonly origins: ReadonlyMap<string, PackageOrigin>\n readonly warnings: readonly ParseWarning[]\n}\n\n/**\n * Resolves every allow-listed package name. Input is deduplicated first, so\n * a duplicate entry in `packages` (accidental or defensive) produces exactly\n * one resolution attempt and, on failure, exactly one warning -- never two.\n * Never throws: every failure becomes one `ParseWarning`, consistent with\n * every other static-analysis boundary in this codebase.\n */\nexport async function resolveAllowlistedPackages(\n packages: readonly string[],\n root: string,\n cache: Map<string, Promise<PackageSchemaResolutionResult>>,\n fs: BuildFileSystem,\n): Promise<ResolvePackagesResult> {\n const uniqueNames = [...new Set(packages)]\n const resolved = await Promise.all(\n uniqueNames.map(async (packageName) => ({\n packageName,\n result: await resolvePackageSchemaFile(packageName, root, cache, fs),\n })),\n )\n\n const files: ResolvedPackageFile[] = []\n const origins = new Map<string, PackageOrigin>()\n const warnings: ParseWarning[] = []\n\n for (const { packageName, result } of resolved) {\n if (result.ok) {\n files.push({ packageName, file: result.origin.resolvedFile })\n origins.set(result.origin.resolvedFile, result.origin)\n } else {\n warnings.push({ file: `(package) ${packageName}`, message: result.reason })\n }\n }\n\n return { files, origins, warnings }\n}\n\n/**\n * Combines local schema-discovery hits with package-resolved files into one\n * deduplicated list, keyed by realpath rather than lexical absolute path --\n * package-resolved files are already realpath-canonicalized (see\n * `resolveUncached` above), but local `discoverSchemaFiles()` hits are plain\n * `readdir`-derived absolute paths that may themselves traverse a symlink (a\n * symlinked `root`, or an included path reached through one). Deduplicating\n * on the lexical path alone would miss the case where the same physical file\n * is reached twice through two different symlinked routes -- one via local\n * glob discovery, one via package resolution -- and silently double-count it\n * into two identical contracts, including the more mundane case of a package\n * that's both locally glob-reachable (e.g. during a monorepo migration) and\n * explicitly allow-listed. On a collision, the local path string identity\n * wins (the package-resolved duplicate is dropped).\n */\nexport async function mergeLocalAndPackageFiles(\n localFiles: readonly string[],\n packageFiles: readonly string[],\n fs: BuildFileSystem,\n): Promise<string[]> {\n const seenRealpaths = new Set<string>()\n const merged: string[] = []\n\n for (const file of localFiles) {\n let real: string\n try {\n real = await fs.realpath(file)\n } catch {\n real = file // shouldn't happen for a file discoverSchemaFiles just found via readdir, but never throw here\n }\n if (seenRealpaths.has(real)) continue\n seenRealpaths.add(real)\n merged.push(file)\n }\n\n for (const file of packageFiles) {\n if (seenRealpaths.has(file)) continue // already realpath-canonicalized by resolveUncached\n seenRealpaths.add(file)\n merged.push(file)\n }\n\n return merged\n}\n\n/**\n * Bare-specifier-to-allowlist matching, used by `resolve-import.ts`'s\n * `resolveImportSpecifier()` as its package-resolution fallback. Only ever\n * attempts resolution for a specifier that is (or is a subpath of) an\n * allow-listed package name -- any other bare specifier is not this\n * mechanism's concern and returns `undefined` immediately, identical to\n * `resolveRelativeImport()`'s existing bare-specifier no-op.\n */\nexport async function resolvePackageImport(\n specifier: string,\n allowedPackages: readonly string[],\n root: string,\n cache: Map<string, Promise<PackageSchemaResolutionResult>>,\n fs: BuildFileSystem,\n): Promise<string | undefined> {\n const matched = allowedPackages.find(\n (pkg) => specifier === pkg || specifier.startsWith(`${pkg}/`),\n )\n // Bypassing this guard when nothing matched is behaviorally equivalent,\n // not a real gap: calling `resolvePackageSchemaFile(undefined, ...)` reaches\n // `locatePackageManifest`'s `req.resolve(undefined)`, which throws\n // ERR_INVALID_ARG_TYPE -- caught by that function's own bare `catch`\n // (returns `undefined`), which in turn makes `resolveUncached` return a\n // plain `{ok: false, code: \"PACKAGE_NOT_FOUND\", ...}` rather than throwing.\n // `resolvePackageImport` still returns `undefined` either way, and the only\n // other difference (a `cache.set(undefined, ...)` entry) is unobservable\n // through the public API. Hand-verified: mutating this line and running the\n // real suite (`vitest run test/build/resolution/resolve-package-schema.test.ts`)\n // passes unchanged. A second approach -- mocking `resolvePackageSchemaFile`\n // to assert it's never called for a non-matching specifier -- isn't viable\n // either, since it's a same-module self-call `vi.mock` can't intercept.\n // Stryker disable next-line ConditionalExpression\n if (!matched) return undefined\n const result = await resolvePackageSchemaFile(matched, root, cache, fs)\n return result.ok ? result.origin.resolvedFile : undefined\n}\n","import path from \"node:path\"\nimport ts from \"typescript\"\nimport type { ParseWarning } from \"../parse.js\"\nimport type { BuildFileSystem } from \"../types.js\"\n\n/**\n * TypeScript path-alias resolution (ADR 0023, Experimental -- see VERSIONING.md).\n *\n * Resolves a bare import specifier (`\"@/lib/env.schema.js\"`) against a project's own\n * `tsconfig.json` `compilerOptions.paths`/`baseUrl`, so a schema or consumer reached only\n * through an alias isn't misreported by `link.ts`/`dependency-graph.ts` as unresolved or\n * abandoned. Unlike `resolve-package-schema.ts` (ADR 0014), this never crosses a\n * trust/versioning boundary -- every resolved file is already local, already-trusted\n * project source -- so it is on by default (auto-detecting `root/tsconfig.json`) rather\n * than requiring an explicit allowlist.\n *\n * The actual `paths`/`baseUrl` matching algorithm (longest-prefix matching, `*` wildcard\n * substitution, multiple fallback targets, `extends`-chain merging, JSONC parsing) is\n * delegated entirely to the TypeScript compiler via `ts.resolveModuleName()` and\n * `ts.parseJsonConfigFileContent()` -- the same functions `tsc`/`tsserver` themselves use --\n * rather than reimplemented here. This module's own logic is limited to loading the config,\n * caching resolutions, and enforcing the `node_modules` safety boundary below.\n */\n\n/** Parsed `tsconfig.json` `paths`/`baseUrl` configuration, immutable for the life of one generate*() run. See {@link loadTsconfigPaths}. */\nexport interface TsconfigPathsResolution {\n /** The subset of `compilerOptions` `ts.resolveModuleName()` needs -- at minimum `paths` and/or `baseUrl`. */\n readonly compilerOptions: ts.CompilerOptions\n /** Absolute path of the tsconfig.json this was loaded from, for diagnostics. */\n readonly configFile: string\n}\n\n/**\n * Opaque memoization for {@link resolveAliasImport}, created once per generate*() run via\n * {@link createAliasResolutionCache} and threaded through `ImportResolutionContext`. Kept\n * distinct from `TsconfigPathsResolution` (immutable config) so the cache's internal\n * representation stays free to change without touching that type's shape.\n */\nexport interface AliasResolutionCache {\n /**\n * Keyed by `` `${importingFile}\\0${specifier}` ``, not by `specifier` alone. With one\n * fixed `compilerOptions` object and no project-reference support, `paths`-pattern\n * substitution itself doesn't depend on the importing file -- but `ts.resolveModuleName()`'s\n * fallback behavior when `paths` doesn't match a real file (classic-mode ancestor search,\n * extension-preference edge cases) legitimately can. A `Map`, not a network call, so\n * keying defensively by both costs nothing.\n */\n readonly resolutions: Map<string, string | undefined>\n}\n\n/** Creates a fresh, empty {@link AliasResolutionCache} for one generate*()/computeArtifacts() run. */\nexport function createAliasResolutionCache(): AliasResolutionCache {\n return { resolutions: new Map() }\n}\n\nasync function fileExists(filePath: string, fs: BuildFileSystem): Promise<boolean> {\n try {\n return (await fs.stat(filePath)).isFile()\n } catch {\n // Empty -- no BlockStatement mutant on a trailing `{}` and the fallthrough\n // `return false` below (data-cap's identical `resolve-tsconfig-paths.ts`\n // precedent, and this file's own `resolve-import.ts`/\n // `resolve-package-schema.ts` siblings).\n }\n return false\n}\n\nexport interface LoadTsconfigPathsResult {\n readonly resolution: TsconfigPathsResolution | undefined\n readonly warning: ParseWarning | undefined\n}\n\n/**\n * Loads and parses a `tsconfig.json` for alias resolution. Called exactly once per\n * `generate*()`/`computeArtifacts()` invocation, at the same point\n * `resolveAllowlistedPackages()` is already called once -- so at most one tsconfig-related\n * warning is ever produced per run, never once per file scanned.\n *\n * @remarks\n * `tsconfigOption === false` disables alias resolution entirely.\n * `tsconfigOption === undefined` (the default) looks for `root/tsconfig.json` exactly --\n * deliberately not `ts.findConfigFile()`'s upward directory walk, since every other\n * root-relative mechanism in this codebase (schema discovery, `packages` resolution)\n * treats `root` as a hard boundary. A missing default tsconfig is silent (most projects\n * don't use aliases); a missing *explicit* `tsconfigOption` is a real misconfiguration and\n * warns. `jsconfig.json` is intentionally not auto-detected -- pass `tsconfig:\n * \"jsconfig.json\"` explicitly if needed; this loader only cares about the file's JSON\n * shape, not its name.\n *\n * The gate for building a resolution is \"`paths` non-empty OR `baseUrl` set\", not `paths`\n * alone -- a `baseUrl`-only tsconfig (no `paths` at all) still makes TypeScript resolve\n * bare specifiers relative to `baseUrl`, and `ts.resolveModuleName()` already handles that\n * once `compilerOptions.baseUrl` is passed through.\n */\nexport async function loadTsconfigPaths(\n root: string,\n tsconfigOption: string | false | undefined,\n fs: BuildFileSystem,\n): Promise<LoadTsconfigPathsResult> {\n if (tsconfigOption === false) return { resolution: undefined, warning: undefined }\n\n const isExplicit = tsconfigOption !== undefined\n const configFile = path.resolve(root, tsconfigOption ?? \"tsconfig.json\")\n\n if (!(await fileExists(configFile, fs))) {\n if (!isExplicit) return { resolution: undefined, warning: undefined }\n return {\n resolution: undefined,\n warning: {\n file: configFile,\n message: `\"tsconfig\" was set to \"${tsconfigOption}\", but no file exists at \"${configFile}\".`,\n },\n }\n }\n\n const readResult = ts.readConfigFile(configFile, (p) => ts.sys.readFile(p))\n if (readResult.error) {\n // `readConfigFile`'s own diagnostic `messageText` is always a plain\n // string in practice (probed) -- the chain separator arg is unreachable,\n // kept only for the API's own `string | DiagnosticMessageChain` type.\n // Same established equivalence as data-cap's identical\n // `resolve-tsconfig-paths.ts`.\n // Stryker disable next-line StringLiteral\n const detail = ts.flattenDiagnosticMessageText(readResult.error.messageText, \"\\n\")\n return {\n resolution: undefined,\n warning: {\n file: configFile,\n message: `Could not parse \"${configFile}\": ${detail}`,\n },\n }\n }\n\n const parsed = ts.parseJsonConfigFileContent(readResult.config, ts.sys, path.dirname(configFile))\n const { paths, baseUrl } = parsed.options\n\n const hasPaths = paths !== undefined && Object.keys(paths).length > 0\n if (!hasPaths && baseUrl === undefined) {\n return { resolution: undefined, warning: undefined }\n }\n\n return { resolution: { compilerOptions: parsed.options, configFile }, warning: undefined }\n}\n\n/**\n * Resolves one bare import specifier against a project's `tsconfig.json` `paths`/`baseUrl`,\n * or returns `undefined` if it doesn't resolve through this mechanism.\n *\n * @remarks\n * Necessarily synchronous -- `ts.resolveModuleName()` has no async form, matching how\n * `tsc`/`tsserver` themselves always call it. `ts.sys` is used directly as the resolution\n * host (an existing Node-backed singleton the `typescript` package exports; nothing to\n * construct).\n *\n * Two safety/scope filters apply to any candidate `ts.resolveModuleName()` returns,\n * independent of its own internal fallback behavior:\n * - **Never resolves into `node_modules`.** `ts.resolveModuleName()` can, in principle,\n * fall through to classic Node resolution and land inside `node_modules`; any resolved\n * path containing a `node_modules` path segment (checked after `path.normalize()`, so\n * mixed separators can't slip past it on Windows) is discarded here. Bare package\n * specifiers continue to be handled exclusively by `resolvePackageImport()`\n * (ADR 0014) -- this mechanism never overlaps with that trust boundary.\n * - **`.ts`/`.tsx` only.** Matches `resolveRelativeImport()`'s own existing candidate set\n * and `resolve-package-schema.ts`'s `SCHEMA_FILE_EXTENSIONS` -- this codebase's static-\n * analysis pipeline is `.ts`/`.tsx` only today. A resolved non-`.ts`/`.tsx` file is a\n * real risk, not just a gap: feeding it straight into `ts.createSourceFile()` wouldn't\n * error, it would silently parse garbage -- exactly the \"guess\" this codebase's\n * warn-don't-guess philosophy exists to avoid.\n */\nexport function resolveAliasImport(\n specifier: string,\n importingFile: string,\n resolution: TsconfigPathsResolution,\n cache: AliasResolutionCache,\n): string | undefined {\n const cacheKey = `${importingFile}\\0${specifier}`\n if (cache.resolutions.has(cacheKey)) return cache.resolutions.get(cacheKey)\n\n const result = ts.resolveModuleName(specifier, importingFile, resolution.compilerOptions, ts.sys)\n const resolvedFileName = result.resolvedModule?.resolvedFileName\n\n let resolved: string | undefined\n if (resolvedFileName) {\n const normalized = path.normalize(resolvedFileName)\n const isInNodeModules = normalized.split(path.sep).includes(\"node_modules\")\n const isTsSource = /\\.tsx?$/.test(normalized)\n if (!isInNodeModules && isTsSource) resolved = normalized\n }\n\n cache.resolutions.set(cacheKey, resolved)\n return resolved\n}\n","import path from \"node:path\"\nimport type { BuildFileSystem } from \"../types.js\"\nimport {\n resolvePackageImport,\n type PackageSchemaResolutionResult,\n} from \"./resolve-package-schema.js\"\nimport {\n resolveAliasImport,\n type AliasResolutionCache,\n type TsconfigPathsResolution,\n} from \"./resolve-tsconfig-paths.js\"\n\n/**\n * Resolves a relative import specifier (as written in source: `\"./schema.js\"`,\n * matching this codebase's own convention of `.js`-suffixed relative imports\n * pointing at `.ts` source files) to an absolute file path, relative to the\n * file that contains the import.\n *\n * @remarks\n * Deliberately narrow: only handles a direct relative specifier resolving to\n * a real `.ts`/`.tsx` file on disk. Bare/package specifiers, namespace\n * imports, and anything requiring real module resolution (re-export chains,\n * `exports` map lookups, etc.) return `undefined` -- the caller treats that\n * as \"couldn't statically link\" and warns rather than guesses, the same\n * philosophy `evaluateLiteral` already uses for non-literal expressions.\n *\n * @returns The resolved absolute path, or `undefined` when the specifier isn't relative or doesn't resolve to a real file.\n */\nexport async function resolveRelativeImport(\n importingFile: string,\n specifier: string,\n fs: BuildFileSystem,\n): Promise<string | undefined> {\n if (!specifier.startsWith(\"./\") && !specifier.startsWith(\"../\")) return undefined // bare/package specifier\n\n const withoutExt = specifier.replace(/\\.(js|jsx|ts|tsx)$/, \"\")\n const base = path.resolve(path.dirname(importingFile), withoutExt)\n\n for (const candidate of [\n `${base}.ts`,\n `${base}.tsx`,\n path.join(base, \"index.ts\"),\n path.join(base, \"index.tsx\"),\n ]) {\n if (await fileExists(candidate, fs)) return candidate\n }\n return undefined\n}\n\n// `catch { return false }` below is this function's LAST statement -- an\n// empty catch body would already fall through to an identical implicit\n// `undefined` return, which every caller here treats exactly like `false`\n// (an `if (await fileExists(...))` never distinguishes the two).\n// `noImplicitReturns` still requires an explicit `return` on this path, so\n// the block can never be truly empty. Hand-verified directly (mutating the\n// source to a genuinely empty `catch {}` and running the real test suite)\n// -- every test still passes. Several narrower disable placements (on\n// `return false` itself, directly above `catch`, an unscoped pair\n// bracketing just the catch clause) did not reliably suppress this exact\n// mutant across repeated verification runs -- bracketing the whole\n// function is what finally holds; see `check-artifacts.ts`'s\n// `readIfExists` for the identical pattern and fuller rationale.\n// Stryker disable BlockStatement\nasync function fileExists(filePath: string, fs: BuildFileSystem): Promise<boolean> {\n try {\n const stat = await fs.stat(filePath)\n return stat.isFile()\n } catch {\n return false\n }\n}\n// Stryker restore BlockStatement\n\n/** Shared inputs threaded through every call to {@link resolveImportSpecifier} for one discovery/link run. */\nexport interface ImportResolutionContext {\n /** The filesystem capability -- `./build` never imports `node:fs` (ADR 0040). */\n readonly fs: BuildFileSystem\n /** Absolute path of the project root, used to resolve package specifiers. */\n readonly root: string\n /** Explicit allowlist -- see ADR 0014. Empty/omitted means package resolution never fires, identical to today's behavior. */\n readonly packages: readonly string[]\n /** Memoizes package resolution per specifier across the whole run -- see `resolvePackageImport`'s own doc comment for why. */\n readonly cache: Map<string, Promise<PackageSchemaResolutionResult>>\n /** Parsed `tsconfig.json` `paths`/`baseUrl`, or `undefined` when alias resolution found nothing to do or was disabled -- see ADR 0023. */\n readonly tsconfigPaths: TsconfigPathsResolution | undefined\n /** Memoizes alias resolution across the whole run -- see `resolveAliasImport`'s own doc comment for why. Always allocated, even when `tsconfigPaths` is `undefined`, mirroring `cache` above. */\n readonly aliasCache: AliasResolutionCache\n}\n\n/**\n * The one specifier-resolution entry point `link.ts` and `dependency-graph.ts`\n * call, instead of each duplicating a\n * `(await resolveRelativeImport(...)) ?? resolveAliasImport(...) ?? (await resolvePackageImport(...))`\n * chain at every call site.\n *\n * @remarks\n * Purely a composition point -- no new resolution logic lives here. Tries, in order: the\n * relative resolver (cheap, no `fs.stat` beyond the local filesystem check it already\n * does); tsconfig path-alias resolution (ADR 0023, on by default) for a bare specifier\n * matching the project's own `tsconfig.json` `paths`/`baseUrl`; then package resolution\n * (ADR 0014) for a bare specifier matching an allow-listed package name. Alias resolution\n * runs before package resolution because it resolves the consuming project's own local\n * source (already-trusted, no versioning boundary), the same precedence relative\n * resolution already has over package resolution.\n */\nexport async function resolveImportSpecifier(\n importingFile: string,\n specifier: string,\n context: ImportResolutionContext,\n): Promise<string | undefined> {\n const relative = await resolveRelativeImport(importingFile, specifier, context.fs)\n if (relative) return relative\n\n if (context.tsconfigPaths) {\n const aliased = resolveAliasImport(\n specifier,\n importingFile,\n context.tsconfigPaths,\n context.aliasCache,\n )\n if (aliased) return aliased\n }\n\n return resolvePackageImport(specifier, context.packages, context.root, context.cache, context.fs)\n}\n","import path from \"node:path\"\nimport {\n extractContractDocs,\n extractCreateEnvOptionsName,\n extractSchemaVariables,\n parseSchemaFile,\n} from \"./parse.js\"\nimport type {\n DiscoveredSchemaVariable,\n DiscoveredVariableEvidence,\n DiscoveredVariableDocs,\n FileParseResult,\n ParseWarning,\n SchemaRef,\n} from \"./parse.js\"\nimport type { EnvGovernanceFields } from \"./governance-fields.js\"\nimport { mustGet } from \"./map-utils.js\"\nimport { resolveImportSpecifier } from \"./resolution/resolve-import.js\"\nimport type { ImportResolutionContext } from \"./resolution/resolve-import.js\"\nimport type { PackageOrigin } from \"./resolution/resolve-package-schema.js\"\nimport { positionOf } from \"./source-position.js\"\nimport type { SourcePosition } from \"./source-position.js\"\n\n/** One schema variable, merged with its linked `documentEnv()` documentation (if any). */\n/**\n * One schema variable merged with its linked `documentEnv()` documentation. Its\n * governance fields (`owner` .. `metadata`) are {@link EnvGovernanceFields} --\n * each an individual-variable override of the contract's own value, from the\n * linked `documentEnv()` call's matching `variables` entry, or `undefined`.\n */\nexport interface DiscoveredVariable extends DiscoveredSchemaVariable, EnvGovernanceFields {\n /** From the linked `documentEnv()` call's matching `variables` entry, if any. */\n readonly description: string | undefined\n /** From the linked `documentEnv()` call's matching `variables` entry, if any. */\n readonly refreshInstructions: string | undefined\n /** From the linked `documentEnv()` call's matching `variables` entry, if any. */\n readonly setupInstructions: string | undefined\n /** From the linked `documentEnv()` call's matching `variables` entry, if any. */\n readonly required: boolean | undefined\n /** From the linked `documentEnv()` call's matching `variables` entry, if any. */\n readonly deprecated: boolean | undefined\n /** From the linked `documentEnv()` call's matching `variables` entry, if any. */\n readonly deprecatedReason: string | undefined\n /** From the linked `documentEnv()` call's matching `variables` entry, if any. */\n readonly removeBy: string | undefined\n /** From the linked `documentEnv()` call's matching `variables` entry, if any -- the previous variable name this one renames, if this declaration is the result of a rename. */\n readonly renamedFrom: string | undefined\n /** The linked `documentEnv()` entry's `evidence` sub-object -- the re-verified-every-run half of this variable's documentation, deliberately not flattened in alongside the declared-only fields above. See {@link runtime.VariableEvidenceDocs} and ADR 0037. */\n readonly evidence: DiscoveredVariableEvidence | undefined\n /** Whether this specific key had a matching entry in the linked `documentEnv()` call, if any. */\n readonly documented: boolean\n // `declaration: SourcePosition` is inherited from `DiscoveredSchemaVariable` --\n // where this variable's own schema property is declared. See ADR 0036.\n}\n\n/** One `createEnv()` contract, merged with its linked `documentEnv()` documentation (if any). Its governance fields (`owner` .. `metadata`) are {@link EnvGovernanceFields} -- contract-level defaults that individual variables may override. */\nexport interface DiscoveredContract extends EnvGovernanceFields {\n /** Absolute path of the file declaring the `createEnv()` call. */\n readonly file: string\n /** The binding name the `createEnv()` result is exported as. */\n readonly exportName: string\n /** Resolved display name: linked `documentEnv()`'s `name`, else `createEnv()`'s own `name` option, else `exportName`. */\n readonly contractName: string\n /** From the linked `documentEnv()`'s `active` option. Defaults to `true` when omitted or undocumented. */\n readonly active: boolean\n /** From the linked `documentEnv()` call, if any. */\n readonly category: string | undefined\n /** From the linked `documentEnv()` call, if any -- see {@link runtime.ContractDocs.exclusiveGroup}. */\n readonly exclusiveGroup: string | undefined\n /** From the linked `documentEnv()` call, if any. */\n readonly deprecated: boolean | undefined\n /** From the linked `documentEnv()` call, if any. */\n readonly deprecatedReason: string | undefined\n /** Every variable declared in the schema, merged with its linked documentation. */\n readonly variables: readonly DiscoveredVariable[]\n /** Whether *any* `documentEnv()` call is linked to this contract at all. */\n readonly documented: boolean\n /** Set when this contract was discovered via an allow-listed package's\n * declared schema entry point rather than local discovery -- the bare\n * package name `renderManifest()` must import from instead of computing a\n * relative path to the (analysis-only) resolved file. See ADR 0014. */\n readonly packageOrigin: PackageOrigin | undefined\n /** Where this contract's `createEnv(...)` call is declared. Always present -- every discovered contract has one, by definition. See ADR 0036. */\n readonly declaration: SourcePosition\n /** Where this contract's `documentEnv(...)` call is declared, if one exists. Undefined for a contract that's never been documented. See ADR 0036. */\n readonly documentation: SourcePosition | undefined\n}\n\n/** A `documentEnv()` call that could not be statically linked back to a `createEnv()` schema. */\nexport interface UnresolvedLink {\n /** Absolute path of the file containing the unlinkable call. */\n readonly file: string\n /** Human-readable explanation of why the link couldn't be resolved. */\n readonly reason: string\n}\n\n/** The full result of {@link linkFiles}: every linked contract, plus every category of thing that didn't link cleanly. */\nexport interface LinkResult {\n /** Every `createEnv()` contract found, merged with its documentation. */\n readonly contracts: readonly DiscoveredContract[]\n /** Parse-time warnings collected across every analyzed file. */\n readonly warnings: readonly ParseWarning[]\n /** `documentEnv()` calls that couldn't be statically linked to a schema. */\n readonly unresolvedLinks: readonly UnresolvedLink[]\n /** Contracts with no linked `documentEnv()` call at all. */\n readonly undocumentedContracts: readonly {\n /** Absolute path of the file declaring the contract. */\n readonly file: string\n /** The contract's exported binding name. */\n readonly exportName: string\n }[]\n /** Schema variables with no matching entry in their contract's linked documentation. */\n readonly undocumentedVariables: readonly {\n /** Absolute path of the file declaring the contract. */\n readonly file: string\n /** The contract's exported binding name. */\n readonly exportName: string\n /** The undocumented environment variable name. */\n readonly key: string\n }[]\n /** Documented variable entries with no matching schema variable (the schema key was removed or renamed). */\n readonly staleDocEntries: readonly {\n /** Absolute path of the file declaring the contract. */\n readonly file: string\n /** The contract's exported binding name. */\n readonly exportName: string\n /** The stale documented variable name. */\n readonly key: string\n }[]\n}\n\n/**\n * Parses every discovered file, then resolves and links `createEnv`/\n * `documentEnv` calls into the merged, docs-enriched contract shape the rest\n * of the generator (`compatibility.ts`, `exclusive-group.ts`, `manifest.ts`,\n * `docs.ts`, `env-example.ts`) consumes.\n *\n * @remarks\n * Cross-file linking is deliberately narrow (see `resolveImportSpecifier`):\n * a `documentEnv()` call's schema reference resolves either to a `const` in\n * its own file, to a directly-imported named export of another file's\n * `const`, or (since ADR 0014) to an allow-listed package's declared schema\n * entry point. Anything else -- a re-export barrel, a namespace import, an\n * unlisted bare package specifier -- becomes an `unresolvedLinks` entry\n * rather than a throw or a guess, exactly like every other static-analysis\n * boundary in this codebase.\n *\n * `packageOrigins` (from `resolveAllowlistedPackages()`) tags any discovered\n * contract whose `file` matches a package-resolved path with that package's\n * origin -- purely a lookup; `discoveredFiles` must already include those\n * files (merged in by the caller via `mergeLocalAndPackageFiles()`).\n *\n * @param context - See `ImportResolutionContext`; drives how a resolved import specifier maps back to a file on disk.\n */\nexport async function linkFiles(\n discoveredFiles: readonly string[],\n readFile: (filePath: string) => Promise<string>,\n context: ImportResolutionContext,\n packageOrigins: ReadonlyMap<string, PackageOrigin> = new Map(),\n): Promise<LinkResult> {\n const analysisCache = new Map<string, FileParseResult>()\n\n async function getAnalysis(filePath: string): Promise<FileParseResult | undefined> {\n const cached = analysisCache.get(filePath)\n if (cached) return cached\n let text: string\n try {\n text = await readFile(filePath)\n } catch {\n return undefined\n }\n const parsed = parseSchemaFile(filePath, text)\n analysisCache.set(filePath, parsed)\n return parsed\n }\n\n for (const file of discoveredFiles) {\n await getAnalysis(file)\n }\n\n const warnings: ParseWarning[] = []\n const unresolvedLinks: UnresolvedLink[] = []\n\n async function resolveSchema(\n ref: SchemaRef,\n inFile: string,\n contextLabel: string,\n ): Promise<{ identity: string; variables: DiscoveredSchemaVariable[] } | undefined> {\n // Equivalent even if this check is bypassed entirely: `SchemaRef`'s\n // \"unresolvable\" variant carries only `kind` (no `.name`/`.node`), and\n // every subsequent step in this function is a `Map.get(ref.name)`-style\n // lookup (or a lookup keyed off one) -- `ref.name` on the real,\n // no-such-field \"unresolvable\" object reads `undefined` at runtime, and\n // a `Map.get(undefined)` miss safely falls through to this SAME\n // function's own later `if (!imported) return undefined`, with no\n // warning or other side effect pushed anywhere along the way. Confirmed\n // by tracing every step by hand; not something a black-box test on\n // `resolveSchema`'s return value or `warnings`/`unresolvedLinks` could\n // ever distinguish.\n // Stryker disable next-line StringLiteral,ConditionalExpression\n if (ref.kind === \"unresolvable\") return undefined\n\n // `inFile` is always the loop variable from `discoveredFiles` below,\n // already analyzed (and cached) by the pre-pass above -- `mustGet` makes\n // that invariant explicit instead of a silent, unreachable `undefined`\n // fallback (see the identical pattern the two loops below already use).\n const inFileAnalysis = mustGet(analysisCache, inFile)\n\n if (ref.kind === \"literal\") {\n // Unique per AST node position -- an inline schema literal can never be\n // referenced by anything else, so it can never be linked to a\n // documentEnv() call elsewhere. That's expected, not a bug: documenting\n // a schema requires giving it a name.\n return {\n identity: `${inFile}#<inline:${ref.node.pos}>`,\n variables: extractSchemaVariables(\n ref.node,\n inFile,\n contextLabel,\n warnings,\n inFileAnalysis.sourceFile,\n ),\n }\n }\n\n const local = inFileAnalysis.localConsts.get(ref.name)\n if (local) {\n return {\n identity: `${inFile}#${ref.name}`,\n variables: extractSchemaVariables(\n local,\n inFile,\n contextLabel,\n warnings,\n inFileAnalysis.sourceFile,\n ),\n }\n }\n\n const imported = inFileAnalysis.imports.get(ref.name)\n if (!imported) return undefined\n\n const targetFile = await resolveImportSpecifier(inFile, imported.specifier, context)\n // Equivalent even if bypassed: `getAnalysis(undefined as unknown as\n // string)` below misses `analysisCache` (a Map, safe for any key),\n // attempts `readFile(undefined)`, which every real (and test-double)\n // `readFile` implementation here rejects rather than resolves, is\n // caught by `getAnalysis`'s own `try { ... } catch { return undefined\n // }`, and returns `undefined` -- reaching this function's OWN later\n // `if (!targetAnalysis) return undefined` regardless, with no warning\n // or other side effect pushed either way.\n // Stryker disable next-line ConditionalExpression\n if (!targetFile) return undefined\n\n const targetAnalysis = await getAnalysis(targetFile)\n if (!targetAnalysis) return undefined\n\n const targetLocal = targetAnalysis.localConsts.get(imported.importedName)\n if (!targetLocal || !targetAnalysis.exportedConstNames.has(imported.importedName))\n return undefined\n\n return {\n identity: `${targetFile}#${imported.importedName}`,\n variables: extractSchemaVariables(\n targetLocal,\n targetFile,\n contextLabel,\n warnings,\n targetAnalysis.sourceFile,\n ),\n }\n }\n\n interface CreateEnvEntry {\n file: string\n exportName: string\n identity: string\n variables: DiscoveredSchemaVariable[]\n optionsName: string | undefined\n declaration: SourcePosition\n }\n const createEnvEntries: CreateEnvEntry[] = []\n\n for (const file of discoveredFiles) {\n const analysis = mustGet(analysisCache, file)\n for (const call of analysis.createEnvCalls) {\n const resolved = await resolveSchema(call.schemaRef, file, call.exportName)\n if (!resolved) {\n warnings.push({\n file,\n message: `createEnv() call for \"${call.exportName}\" does not pass an inline object literal or a statically-resolvable schema reference; skipping static analysis for this contract.`,\n })\n continue\n }\n createEnvEntries.push({\n file,\n exportName: call.exportName,\n identity: resolved.identity,\n variables: resolved.variables,\n optionsName: extractCreateEnvOptionsName(call.optionsArg),\n declaration: { file, ...positionOf(analysis.sourceFile, call.node) },\n })\n }\n }\n\n interface DocumentEnvEntry {\n identity: string\n docs: ReturnType<typeof extractContractDocs>\n documentation: SourcePosition\n }\n const documentEnvByIdentity = new Map<string, DocumentEnvEntry>()\n\n for (const file of discoveredFiles) {\n const analysis = mustGet(analysisCache, file)\n for (const call of analysis.documentEnvCalls) {\n const resolved = await resolveSchema(call.schemaRef, file, \"documentEnv() call\")\n if (!resolved) {\n unresolvedLinks.push({\n file,\n reason:\n \"documentEnv() call could not be statically linked to a schema (its first argument isn't an inline object literal or a resolvable local/imported reference).\",\n })\n continue\n }\n if (documentEnvByIdentity.has(resolved.identity)) {\n // Multiple documentEnv() calls for the same schema -- the first one\n // found (in discovery order) wins, silently. Unusual enough not to\n // warrant its own warning category.\n continue\n }\n const docs = extractContractDocs(call.docsArg, file, resolved.identity, warnings)\n const documentation: SourcePosition = { file, ...positionOf(analysis.sourceFile, call.node) }\n documentEnvByIdentity.set(resolved.identity, {\n identity: resolved.identity,\n docs,\n documentation,\n })\n }\n }\n\n const contracts: DiscoveredContract[] = []\n const undocumentedContracts: LinkResult[\"undocumentedContracts\"][number][] = []\n const undocumentedVariables: LinkResult[\"undocumentedVariables\"][number][] = []\n const staleDocEntries: LinkResult[\"staleDocEntries\"][number][] = []\n\n for (const entry of createEnvEntries) {\n const linked = documentEnvByIdentity.get(entry.identity)\n const docs = linked?.docs\n\n if (!docs) {\n undocumentedContracts.push({ file: entry.file, exportName: entry.exportName })\n }\n\n const schemaKeys = new Set(entry.variables.map((v) => v.key))\n const docsVariables = docs?.variables ?? new Map<string, DiscoveredVariableDocs>()\n\n for (const key of schemaKeys) {\n if (!docsVariables.has(key))\n undocumentedVariables.push({ file: entry.file, exportName: entry.exportName, key })\n }\n for (const key of docsVariables.keys()) {\n if (!schemaKeys.has(key))\n staleDocEntries.push({ file: entry.file, exportName: entry.exportName, key })\n }\n\n const variables: DiscoveredVariable[] = entry.variables.map((v) => {\n const vd = docsVariables.get(v.key)\n return {\n ...v,\n description: vd?.description,\n owner: vd?.owner,\n sensitivity: vd?.sensitivity,\n expiresAt: vd?.expiresAt,\n refreshInstructions: vd?.refreshInstructions,\n setupInstructions: vd?.setupInstructions,\n required: vd?.required,\n deprecated: vd?.deprecated,\n deprecatedReason: vd?.deprecatedReason,\n removeBy: vd?.removeBy,\n renamedFrom: vd?.renamedFrom,\n purpose: vd?.purpose,\n legalBasis: vd?.legalBasis,\n retention: vd?.retention,\n dataResidency: vd?.dataResidency,\n auditRequired: vd?.auditRequired,\n metadata: vd?.metadata,\n evidence: vd?.evidence,\n documented: vd !== undefined,\n }\n })\n\n contracts.push({\n file: entry.file,\n exportName: entry.exportName,\n contractName: docs?.name ?? entry.optionsName ?? entry.exportName,\n active: docs?.active ?? true,\n category: docs?.category,\n exclusiveGroup: docs?.exclusiveGroup,\n owner: docs?.owner,\n sensitivity: docs?.sensitivity,\n expiresAt: docs?.expiresAt,\n deprecated: docs?.deprecated,\n deprecatedReason: docs?.deprecatedReason,\n purpose: docs?.purpose,\n legalBasis: docs?.legalBasis,\n retention: docs?.retention,\n dataResidency: docs?.dataResidency,\n auditRequired: docs?.auditRequired,\n metadata: docs?.metadata,\n packageOrigin: packageOrigins.get(entry.file),\n variables,\n documented: docs !== undefined,\n declaration: entry.declaration,\n documentation: linked?.documentation,\n })\n }\n\n for (const analysis of analysisCache.values()) {\n warnings.push(...analysis.warnings)\n }\n\n return {\n contracts,\n warnings,\n unresolvedLinks,\n undocumentedContracts,\n undocumentedVariables,\n staleDocEntries,\n }\n}\n\n/** Root-relative projection of a {@link DiscoveredContract}, as returned by {@link generateEnvManifest}/{@link generateDocumentation}. */\nexport interface DiscoveredContractSummary {\n /** Root-relative, POSIX-separated file path. */\n readonly file: string\n /** The binding name the `createEnv()` result is exported as. */\n readonly exportName: string\n /** Resolved display name (see {@link DiscoveredContract.contractName}). */\n readonly contractName: string\n /** Number of variables declared in this contract's schema. */\n readonly variableCount: number\n /** Whether this contract was included in the generated manifest (`active` defaults to true). */\n readonly active: boolean\n /** Whether a `documentEnv()` call is linked to this contract. */\n readonly documented: boolean\n}\n\n/**\n * Projects a {@link DiscoveredContract} (absolute `file`) into the root-relative\n * summary shape returned by {@link generateEnvManifest}/{@link generateDocumentation}.\n *\n * @remarks\n * Pulled out here, rather than duplicated in both, since it's a pure\n * projection with no manifest- or docs-specific behavior.\n */\nexport function summarizeContract(\n contract: DiscoveredContract,\n root: string,\n): DiscoveredContractSummary {\n return {\n file: path.relative(root, contract.file),\n exportName: contract.exportName,\n contractName: contract.contractName,\n variableCount: contract.variables.length,\n active: contract.active,\n documented: contract.documented,\n }\n}\n\n/**\n * A variable's owner, falling back to its contract's default when the\n * variable itself doesn't set one.\n *\n * @remarks\n * The one place this resolution rule should live -- see ADR 0028. Every\n * caller that needs \"who owns this variable\" (the docs Catalog/ownership\n * matrix/security review, and, as of ADR 0028, the usage report's\n * variable-level ownership findings) must go through this, not\n * `variable.owner` or `contract.owner` alone, so two call sites can never\n * again disagree about who owns a variable the way `docs.ts` and\n * `usage-report.ts` once did.\n *\n * Structurally typed (not pinned to `DiscoveredContract`/`DiscoveredVariable`)\n * so the same one resolution rule also serves `ContractModelContract`/\n * `ContractModelVariable` (`contract-model.ts`) -- both shapes carry the same\n * field, and this rule must never have two independent implementations.\n */\nexport function effectiveOwner(\n contract: { readonly owner: string | undefined },\n variable: { readonly owner: string | undefined },\n): string | undefined {\n return variable.owner ?? contract.owner\n}\n\n/** A variable's sensitivity, falling back to its contract's default -- see {@link effectiveOwner}. */\nexport function effectiveSensitivity(\n contract: { readonly sensitivity: string | undefined },\n variable: { readonly sensitivity: string | undefined },\n): string | undefined {\n return variable.sensitivity ?? contract.sensitivity\n}\n\n/** A variable's purpose, falling back to its contract's default -- see {@link effectiveOwner}. */\nexport function effectivePurpose(\n contract: { readonly purpose: string | undefined },\n variable: { readonly purpose: string | undefined },\n): string | undefined {\n return variable.purpose ?? contract.purpose\n}\n\n/** A variable's legal basis, falling back to its contract's default -- see {@link effectiveOwner}. */\nexport function effectiveLegalBasis(\n contract: { readonly legalBasis: string | undefined },\n variable: { readonly legalBasis: string | undefined },\n): string | undefined {\n return variable.legalBasis ?? contract.legalBasis\n}\n\n/** A variable's retention policy, falling back to its contract's default -- see {@link effectiveOwner}. */\nexport function effectiveRetention(\n contract: { readonly retention: string | undefined },\n variable: { readonly retention: string | undefined },\n): string | undefined {\n return variable.retention ?? contract.retention\n}\n\n/** A variable's data residency, falling back to its contract's default -- see {@link effectiveOwner}. */\nexport function effectiveDataResidency(\n contract: { readonly dataResidency: string | readonly string[] | undefined },\n variable: { readonly dataResidency: string | readonly string[] | undefined },\n): string | readonly string[] | undefined {\n return variable.dataResidency ?? contract.dataResidency\n}\n\n/** A variable's audit-required assertion, falling back to its contract's default -- see {@link effectiveOwner}. */\nexport function effectiveAuditRequired(\n contract: { readonly auditRequired: boolean | undefined },\n variable: { readonly auditRequired: boolean | undefined },\n): boolean | undefined {\n return variable.auditRequired ?? contract.auditRequired\n}\n","import { discoverSchemaFiles } from \"./discover.js\"\nimport { linkFiles } from \"./link.js\"\nimport type { LinkResult } from \"./link.js\"\nimport type { ParseWarning } from \"./parse.js\"\nimport type { BuildFileSystem } from \"./types.js\"\nimport type { ImportResolutionContext } from \"./resolution/resolve-import.js\"\nimport {\n mergeLocalAndPackageFiles,\n resolveAllowlistedPackages,\n} from \"./resolution/resolve-package-schema.js\"\nimport type {\n PackageOrigin,\n PackageSchemaResolutionResult,\n} from \"./resolution/resolve-package-schema.js\"\nimport {\n createAliasResolutionCache,\n loadTsconfigPaths,\n} from \"./resolution/resolve-tsconfig-paths.js\"\n\n/** Options for {@link assembleProject}. */\nexport interface AssembleProjectOptions {\n /** The filesystem capability -- `./build` never imports `node:fs` (ADR 0040). */\n readonly fs: BuildFileSystem\n readonly root: string\n readonly include: readonly string[]\n readonly exclude: readonly string[]\n readonly packages: readonly string[]\n readonly tsconfig: string | false | undefined\n}\n\n/**\n * Everything downstream model-building and artifact-rendering needs from one\n * discovery+link pass: the linked contract graph, the import-resolution\n * context every later resolution call (`computeScanSurface()`,\n * `buildDependencyModel()`, ...) must reuse to agree with `linkResult`, and a\n * shared file-read cache so a file matched by more than one later pass'\n * glob (e.g. a schema file also matched by the usage pass' broader\n * `SCAN_INCLUDE`) is only ever read from disk once.\n */\nexport interface AssembledProject {\n readonly root: string\n readonly readFileCached: (filePath: string) => Promise<string>\n readonly linkResult: LinkResult\n readonly context: ImportResolutionContext\n /** Keyed by resolved file path -- see `resolveAllowlistedPackages()`. */\n readonly origins: ReadonlyMap<string, PackageOrigin>\n readonly packageWarnings: readonly ParseWarning[]\n readonly tsconfigWarnings: readonly ParseWarning[]\n}\n\n/**\n * The one shared discovery+link pass every orchestrator needs -- local +\n * allow-listed-package schema discovery, tsconfig path-alias resolution, and\n * cross-file linking, exactly once. Extracted from what `computeArtifacts()`\n * (`generate-env-artifacts.ts`) and `generateEvidenceModel()`\n * (`generate-evidence.ts`) each used to run independently, so the two\n * orchestrators can never silently drift into scanning the same source tree\n * twice -- the same \"shared discovery, computed once\" principle ADR 0011\n * already established for manifest/docs/usage, now shared with evidence\n * assembly too.\n */\nexport async function assembleProject(options: AssembleProjectOptions): Promise<AssembledProject> {\n const { fs, root, include, exclude, packages, tsconfig } = options\n\n const fileCache = new Map<string, Promise<string>>()\n const readFileCached = (filePath: string): Promise<string> => {\n let cached = fileCache.get(filePath)\n if (!cached) {\n cached = fs.readFile(filePath, \"utf8\")\n fileCache.set(filePath, cached)\n }\n return cached\n }\n\n const localSchemaFiles = await discoverSchemaFiles({ fs, root, include, exclude })\n const packageCache = new Map<string, Promise<PackageSchemaResolutionResult>>()\n const {\n files: packageFiles,\n origins,\n warnings: packageWarnings,\n } = await resolveAllowlistedPackages(packages, root, packageCache, fs)\n const schemaFiles = await mergeLocalAndPackageFiles(\n localSchemaFiles,\n packageFiles.map((f) => f.file),\n fs,\n )\n const { resolution: tsconfigPaths, warning: tsconfigWarning } = await loadTsconfigPaths(\n root,\n tsconfig,\n fs,\n )\n const tsconfigWarnings = tsconfigWarning ? [tsconfigWarning] : []\n\n const context: ImportResolutionContext = {\n fs,\n root,\n packages,\n cache: packageCache,\n tsconfigPaths,\n aliasCache: createAliasResolutionCache(),\n }\n const linkResult = await linkFiles(schemaFiles, readFileCached, context, origins)\n\n return { root, readFileCached, linkResult, context, origins, packageWarnings, tsconfigWarnings }\n}\n","import { displayPath } from \"./display-path.js\"\nimport type { DiscoveredContract } from \"./link.js\"\nimport type { ManifestChangeReport, ManifestVariableRef } from \"./evidence-snapshot.js\"\n\n/**\n * The sixth of env-cap's seven canonical fact models (ADR 0024) -- what\n * changed since the last persisted evidence snapshot (ADR 0038; previously\n * a manifest-scoped snapshot, ADR 0021). See ADR 0030 (base shape) and ADR\n * 0029 (the `renamedFrom` field this file's rename correlation is gated\n * on).\n *\n * @remarks\n * Wraps `ManifestChangeReport` (`evidence-snapshot.ts`) rather than\n * replacing it -- this model exists to give the change report a versioned,\n * model-namespaced shape Evidence Model can assemble against, alongside the\n * other six models. Empty (no adds/removes/updates) whenever no previous\n * evidence snapshot location was configured for this run -- there is\n * nothing to diff against, which is a genuinely different state from a\n * first-ever run *with* tracking configured (where everything reads as\n * added).\n */\n\n/** Bump only when a reader could misinterpret the new shape -- same discipline every other canonical model's `schemaVersion` follows. */\nexport const CHANGE_MODEL_SCHEMA_VERSION = 1\n\n/** One `addedVariables`/`removedVariables` pair in `manifest`, correlated into a single rename via the current declaration's `renamedFrom` field (ADR 0029). */\nexport interface RenamedVariable {\n /** The owning contract's identity (`${file}#${exportName}`) -- a rename never crosses contracts. */\n readonly contractIdentity: string\n readonly file: string\n readonly exportName: string\n readonly contractName: string\n /** The variable's key before the rename -- matches a `manifest.removedVariables` entry. */\n readonly previousKey: string\n /** The variable's key after the rename -- matches a `manifest.addedVariables` entry. */\n readonly currentKey: string\n}\n\nexport interface ChangeModel {\n readonly schemaVersion: typeof CHANGE_MODEL_SCHEMA_VERSION\n /** The existing manifest change report, unmodified -- see ADR 0021. `addedVariables`/`removedVariables` still list a correlated rename's two halves separately; `renamedVariables` below is an additive, separately-computed view, not a filter over this field. */\n readonly manifest: ManifestChangeReport\n /**\n * Every `addedVariables`/`removedVariables` pair this run's currently\n * declared `renamedFrom` values correlate into a single rename, sorted by\n * contract identity then current key.\n *\n * @remarks\n * Only ever populated from an *authored* `renamedFrom` -- never guessed\n * from name similarity (ADR 0010's \"provable, not heuristic\" ethos).\n * Variable-level only: Lifecycle Model deliberately has no contract-level\n * `renamedFrom` (ADR 0029), so there is no `renamedContracts` -- a\n * contract-level rename has no field to correlate from.\n */\n readonly renamedVariables: readonly RenamedVariable[]\n}\n\nfunction contractIdentity(file: string, exportName: string): string {\n return `${file}#${exportName}`\n}\n\nfunction byRenameIdentity(a: RenamedVariable, b: RenamedVariable): number {\n return (\n a.contractIdentity.localeCompare(b.contractIdentity) || a.currentKey.localeCompare(b.currentKey)\n )\n}\n\nfunction findByContractAndKey(\n refs: readonly ManifestVariableRef[],\n file: string,\n exportName: string,\n key: string,\n): ManifestVariableRef | undefined {\n return refs.find((ref) => ref.file === file && ref.exportName === exportName && ref.key === key)\n}\n\n/**\n * Wraps an already-computed `ManifestChangeReport` (e.g.\n * `generateEnvArtifacts()`'s internal `evidenceChanges.report`) in the Change Model's versioned\n * shape, and correlates renames using the current run's `renamedFrom`\n * declarations. `currentContracts` should be the same contracts the\n * manifest was generated from (active contracts only, matching\n * `renderManifest()`'s own scope -- same as every other input to this\n * report family).\n */\nexport function buildChangeModel(\n manifest: ManifestChangeReport,\n currentContracts: readonly DiscoveredContract[],\n root: string,\n): ChangeModel {\n const renamedVariables: RenamedVariable[] = []\n\n for (const contract of currentContracts) {\n const relativeFile = displayPath(root, contract.file)\n const cIdentity = contractIdentity(relativeFile, contract.exportName)\n\n for (const variable of contract.variables) {\n // Runtime-equivalent without this guard: `findByContractAndKey(...,\n // variable.renamedFrom)` with `renamedFrom === undefined` searches for\n // `ref.key === undefined`, which a real `ManifestVariableRef.key`\n // (always a defined string) can never match -- `removedRef` stays\n // `undefined`, and the `if (!addedRef || !removedRef) continue` two\n // lines down already skips it. Load-bearing for TypeScript's own\n // narrowing of `variable.renamedFrom` to `string` below, though --\n // hand-verified by bypassing it and running the full `vitest run`:\n // only the tsc-backed json-schema freshness test fails, all 1233\n // others pass unchanged.\n // Stryker disable next-line ConditionalExpression\n if (!variable.renamedFrom) continue\n\n const addedRef = findByContractAndKey(\n manifest.addedVariables,\n relativeFile,\n contract.exportName,\n variable.key,\n )\n const removedRef = findByContractAndKey(\n manifest.removedVariables,\n relativeFile,\n contract.exportName,\n variable.renamedFrom,\n )\n if (!addedRef || !removedRef) continue\n\n renamedVariables.push({\n contractIdentity: cIdentity,\n file: addedRef.file,\n exportName: addedRef.exportName,\n // Resolved from the contract this rename was declared on, not carried\n // on the ref -- see `ContractRef` (`evidence-reference.ts`).\n contractName: contract.contractName,\n previousKey: removedRef.key,\n currentKey: addedRef.key,\n })\n }\n }\n renamedVariables.sort(byRenameIdentity)\n\n return { schemaVersion: CHANGE_MODEL_SCHEMA_VERSION, manifest, renamedVariables }\n}\n","import { deepEqual } from \"./deep-equal.js\"\nimport type { DiscoveredContract, DiscoveredVariable } from \"./link.js\"\n\n/**\n * Every stable `code` a check in this file (or `exclusive-group.ts`) can\n * emit. Documented as an enumerated union so a consumer filtering/linking on\n * `code` has a closed list to switch over, rather than an arbitrary string --\n * see ADR 0024/0026. `exclusive-group.ts`'s check does not (yet) set one; see\n * that file's own comment for why.\n */\nexport type CompatibilityIssueCode =\n | \"PROCESSOR_RETURN_TYPE_CONFLICT\"\n | \"PROCESSOR_SOURCE_CONFLICT\"\n | \"VALIDATOR_SOURCE_CONFLICT\"\n | \"DUPLICATE_VARIABLE_DOCUMENTATION\"\n | \"DUPLICATE_VARIABLE_SHAPE_ACROSS_CONTRACTS\"\n\n/** One compatibility problem found between two or more declarations of the same variable, or an exclusive-group violation. */\nexport interface CompatibilityIssue {\n /** `\"error\"` blocks generation regardless of `onIncompatibility`; `\"warning\"` blocks only when `onIncompatibility: \"throw\"`; `\"info\"` never blocks, under any flag. */\n readonly severity: \"error\" | \"warning\" | \"info\"\n /** The environment variable name, or `\"(contract) <name>\"` for a contract-level (e.g. exclusive-group) issue. */\n readonly variable: string\n /** Every file declaring a conflicting definition. */\n readonly files: readonly string[]\n /** Human-readable explanation of the conflict. */\n readonly reason: string\n /**\n * Stable, machine-readable identifier for CI filtering / doc-linking /\n * GitHub Action annotations / IDE integration. `undefined` only for checks\n * that don't (yet) set one -- see {@link CompatibilityIssueCode} for the\n * full enumerated list of values a check in this file can produce.\n */\n readonly code?: CompatibilityIssueCode\n}\n\nconst DOCUMENTATION_COMPARISON_FIELDS = [\n \"description\",\n \"owner\",\n \"sensitivity\",\n \"expiresAt\",\n \"refreshInstructions\",\n \"setupInstructions\",\n \"required\",\n] as const\n\n/** Field names (including `metadata.<key>`) where two documented declarations of the same variable disagree -- empty when they match. */\nfunction documentationDivergences(a: DiscoveredVariable, b: DiscoveredVariable): string[] {\n const divergences: string[] = []\n for (const field of DOCUMENTATION_COMPARISON_FIELDS) {\n if (a[field] !== b[field]) divergences.push(field)\n }\n const aMetadata = a.metadata ?? {}\n const bMetadata = b.metadata ?? {}\n for (const key of new Set([...Object.keys(aMetadata), ...Object.keys(bMetadata)])) {\n if (!deepEqual(aMetadata[key], bMetadata[key])) divergences.push(`metadata.${key}`)\n }\n return divergences\n}\n\n/**\n * Flags cases where two contracts declare the same variable name but appear to\n * disagree about its shape, so a human can confirm they're still meant to be \"the same\" var.\n *\n * @remarks\n * Duplicate variable names across contracts are not a merge problem -- each\n * contract independently processes its own copy of the raw value, there is no\n * runtime merge at all. This is purely a build-time lint.\n *\n * Only one thing is treated as *provable* without executing code: two\n * processors with explicit, differing `: T` return type annotations. That is\n * a hard error. Everything else (differing processor/validator source text\n * with no annotation, or none at all) is a warning -- we cannot prove\n * semantic non-equivalence via static analysis alone, and the library never\n * executes schema code to check further (see literal-eval.ts).\n */\nexport function detectCompatibilityIssues(\n contracts: readonly DiscoveredContract[],\n): CompatibilityIssue[] {\n const declarationsByKey = new Map<\n string,\n { file: string; contractName: string; variable: DiscoveredVariable }[]\n >()\n\n for (const contract of contracts) {\n for (const variable of contract.variables) {\n const list = declarationsByKey.get(variable.key) ?? []\n list.push({ file: contract.file, contractName: contract.contractName, variable })\n declarationsByKey.set(variable.key, list)\n }\n }\n\n const issues: CompatibilityIssue[] = []\n\n for (const [key, declarations] of [...declarationsByKey.entries()].sort((a, b) =>\n a[0].localeCompare(b[0]),\n )) {\n // Widening the outer bound to `<=` is a genuine no-op for every input\n // size: at `i === declarations.length`, the inner loop's own `j = i + 1`\n // already exceeds `declarations.length`, so its body never executes\n // regardless -- same off-by-one equivalence already documented for\n // exclusive-group.ts's identical pairwise double loop. Hand-verified:\n // mutating this and running the real suite passes unchanged.\n // Stryker disable next-line EqualityOperator\n for (let i = 0; i < declarations.length; i++) {\n for (let j = i + 1; j < declarations.length; j++) {\n const a = declarations[i]\n const b = declarations[j]\n\n if (\n a.variable.processorReturnType &&\n b.variable.processorReturnType &&\n a.variable.processorReturnType !== b.variable.processorReturnType\n ) {\n issues.push({\n severity: \"error\",\n variable: key,\n files: [a.file, b.file],\n code: \"PROCESSOR_RETURN_TYPE_CONFLICT\",\n reason:\n `Processor return types are declared incompatible: \"${a.contractName}\" produces ` +\n `${a.variable.processorReturnType}, \"${b.contractName}\" produces ${b.variable.processorReturnType}.`,\n })\n continue\n }\n\n if (\n a.variable.hasProcessor &&\n b.variable.hasProcessor &&\n a.variable.processorSource !== b.variable.processorSource\n ) {\n issues.push({\n severity: \"warning\",\n variable: key,\n files: [a.file, b.file],\n code: \"PROCESSOR_SOURCE_CONFLICT\",\n reason:\n `\"${a.contractName}\" and \"${b.contractName}\" both declare a processor for this variable with ` +\n \"different implementations. Return types could not be statically verified -- add explicit \" +\n \"return type annotations, or confirm they produce equivalent output.\",\n })\n }\n\n if (\n a.variable.hasValidator &&\n b.variable.hasValidator &&\n a.variable.validatorSource !== b.variable.validatorSource\n ) {\n issues.push({\n severity: \"warning\",\n variable: key,\n files: [a.file, b.file],\n code: \"VALIDATOR_SOURCE_CONFLICT\",\n reason:\n `\"${a.contractName}\" and \"${b.contractName}\" both declare a validator for this variable with ` +\n \"different implementations. Validator logic cannot be statically compared -- confirm they enforce compatible rules.\",\n })\n }\n\n if (a.variable.documented && b.variable.documented) {\n const divergences = documentationDivergences(a.variable, b.variable)\n if (divergences.length > 0) {\n issues.push({\n severity: \"warning\",\n variable: key,\n files: [a.file, b.file],\n code: \"DUPLICATE_VARIABLE_DOCUMENTATION\",\n reason:\n `\"${a.contractName}\" and \"${b.contractName}\" both document this variable, but disagree on: ` +\n `${divergences.join(\", \")}. Confirm they're still meant to be the same variable and align the ` +\n \"documentation, or document them separately if they're not.\",\n })\n }\n }\n }\n }\n }\n\n return issues\n}\n\n/**\n * One variable's statically-provable *type shape*, deliberately nothing more:\n * what type its value ends up as, and whether it is processed and/or\n * validated at all. Never its literal content -- two variables holding\n * different secrets are still the same shape, and comparing values would both\n * leak them into a report and answer the wrong question.\n */\ninterface VariableShape {\n /** The explicit `processorReturnType` when the variable declares one, else `typeof defaultValue.value` when a statically-evaluable default exists, else `\"unknown\"`. */\n readonly valueType: string\n readonly hasProcessor: boolean\n readonly hasValidator: boolean\n}\n\n/**\n * `undefined` is never inferred from `processorSource`/`validatorSource`\n * text -- reading a type out of an unannotated function body is exactly the\n * guessing this codebase refuses to do (ADR 0010). Absent an annotation and\n * absent a resolvable default, the honest answer is `\"unknown\"`, and an\n * `\"unknown\"` shape never matches anything, including another `\"unknown\"`.\n */\nfunction variableShape(variable: DiscoveredVariable): VariableShape {\n let valueType = \"unknown\"\n if (variable.processorReturnType !== undefined) {\n valueType = variable.processorReturnType\n } else if (variable.hasDefault && variable.defaultValue?.ok === true) {\n valueType = typeof variable.defaultValue.value\n }\n return {\n valueType,\n hasProcessor: variable.hasProcessor,\n hasValidator: variable.hasValidator,\n }\n}\n\nfunction shapesMatch(a: VariableShape, b: VariableShape): boolean {\n // Mutating `||` to `&&`, or either `\"unknown\"` to a non-matching literal,\n // is behaviorally equivalent here, not a real gap: whenever exactly one\n // side is \"unknown\" and the other genuinely isn't, the structural\n // `a.valueType === b.valueType` check below already returns false on its\n // own (an \"unknown\" string can never equal a real type string) -- and\n // whenever BOTH sides are \"unknown\", every mutant variant here still\n // triggers this same early return (both `||` and `&&` are satisfied when\n // both operands are true). The only case this guard is load-bearing for\n // -- both sides \"unknown\" with matching hasProcessor/hasValidator, which\n // would otherwise wrongly report a match via the structural check alone\n // -- is real-tested by 'never flags an \"unknown\" shape...' below, and\n // that test DOES fail without this whole `if`. Hand-verified each mutant\n // variant individually (this `||`, and each `\"unknown\"` string) against\n // the real suite; all pass unchanged.\n // Stryker disable next-line LogicalOperator,StringLiteral,ConditionalExpression\n if (a.valueType === \"unknown\" || b.valueType === \"unknown\") return false\n return (\n a.valueType === b.valueType &&\n a.hasProcessor === b.hasProcessor &&\n a.hasValidator === b.hasValidator\n )\n}\n\n/**\n * Flags *differently-named* variables in different contracts that share an\n * identical type shape -- a soft signal that two features may be\n * independently modelling the same underlying configuration value under two\n * names, worth a human glance before they drift apart.\n *\n * @remarks\n * Always `severity: \"info\"`, and never escalated to blocking by any flag,\n * including `--strict` -- an identical shape is genuinely common and\n * frequently correct (two unrelated features can both take a `number` timeout\n * with a validator, and that is not a defect). This is an observation offered\n * to a reader, not a rule; making it blockable would make it noise a team has\n * to suppress rather than a signal they can scan.\n *\n * Scope, deliberately narrow on every axis:\n * - **Different keys only.** Same-key collisions across contracts are\n * `detectCompatibilityIssues()`'s own, entirely separate concern above;\n * reporting them here too would double-report one problem under two codes.\n * - **Different contracts only.** Two same-shaped variables inside one\n * contract are that contract's own deliberate design.\n * - **Active contracts only.** An inactive contract is wired into nothing,\n * so an overlap with it is not a live duplication.\n * - **No exclusive-grouped contracts.** Members of an exclusive group are\n * interchangeable alternatives by explicit authorial declaration --\n * matching shapes there are the *point*, not a smell.\n * - **Pairwise, never transitive.** Three mutually-matching variables emit\n * three independent findings (A-B, A-C, B-C), never one merged \"cluster\":\n * each pair is its own question a reader answers on its own, and a cluster\n * would imply a transitive relationship this check never established.\n */\nexport function detectDuplicateVariableShapes(\n contracts: readonly DiscoveredContract[],\n): CompatibilityIssue[] {\n const candidates = contracts.filter((c) => c.active && !c.exclusiveGroup)\n\n const declarations: {\n file: string\n contractName: string\n key: string\n shape: VariableShape\n }[] = []\n for (const contract of candidates) {\n for (const variable of contract.variables) {\n declarations.push({\n file: contract.file,\n contractName: contract.contractName,\n key: variable.key,\n shape: variableShape(variable),\n })\n }\n }\n // Deterministic output regardless of discovery order -- by key, then by the\n // declaring contract, matching every other report in this package.\n declarations.sort(\n (a, b) =>\n a.key.localeCompare(b.key) ||\n a.contractName.localeCompare(b.contractName) ||\n a.file.localeCompare(b.file),\n )\n\n const issues: CompatibilityIssue[] = []\n // Same off-by-one equivalence as `detectCompatibilityIssues()`'s identical\n // pairwise double loop above.\n // Stryker disable next-line EqualityOperator\n for (let i = 0; i < declarations.length; i++) {\n for (let j = i + 1; j < declarations.length; j++) {\n const a = declarations[i]\n const b = declarations[j]\n if (a.key === b.key) continue\n if (a.file === b.file && a.contractName === b.contractName) continue\n if (!shapesMatch(a.shape, b.shape)) continue\n\n issues.push({\n severity: \"info\",\n variable: `${a.key} / ${b.key}`,\n files: [a.file, b.file],\n code: \"DUPLICATE_VARIABLE_SHAPE_ACROSS_CONTRACTS\",\n reason:\n `\"${a.key}\" (${a.contractName}) and \"${b.key}\" (${b.contractName}) declare an identical shape ` +\n `(type ${a.shape.valueType}, processor: ${a.shape.hasProcessor ? \"yes\" : \"no\"}, validator: ` +\n `${a.shape.hasValidator ? \"yes\" : \"no\"}). Informational only -- they may be the same underlying ` +\n \"value modelled twice, or two unrelated values that happen to look alike. Nothing is required.\",\n })\n }\n }\n\n return issues\n}\n","/**\n * The canonical ordering every fact model's contract list is sorted by: `file`\n * (root-relative, POSIX) then `exportName`. One definition so `JSON.stringify`\n * output is stable and diffs cleanly across Contract / Ownership / Lifecycle /\n * Dependency Models. Internal -- not re-exported from the public `.` barrel.\n */\nexport function byContractIdentity(\n a: { readonly file: string; readonly exportName: string },\n b: { readonly file: string; readonly exportName: string },\n): number {\n return a.file.localeCompare(b.file) || a.exportName.localeCompare(b.exportName)\n}\n","/**\n * The declared governance-metadata field set every pipeline-stage contract and\n * variable type carries -- `owner` through `metadata`. The field names and types\n * are identical at every stage (parse -> link -> contract-model -> docs); only\n * the surrounding context differs (a `parse`-stage value is \"statically resolved\n * from a string literal, or `undefined`\"; a `link`/`contract-model`-stage value\n * is \"from the linked `documentEnv()` call, or `undefined`\"). This is the single\n * source of truth for the shape; each stage interface `extends` it.\n *\n * `metadata` is the open bag for keys `env-cap` has no named concept for (ADR\n * 0037); `dataResidency`/`auditRequired`/`legalBasis`/`purpose`/`retention` are\n * presence-only governance facts, never verified.\n *\n * Internal -- not re-exported from the public `.` barrel.\n */\nexport interface EnvGovernanceFields {\n readonly owner: string | undefined\n readonly sensitivity: string | undefined\n readonly expiresAt: string | undefined\n readonly purpose: string | undefined\n readonly legalBasis: string | undefined\n readonly retention: string | undefined\n readonly dataResidency: string | readonly string[] | undefined\n readonly auditRequired: boolean | undefined\n readonly metadata: Readonly<Record<string, unknown>> | undefined\n}\n\n/**\n * Copies exactly the {@link EnvGovernanceFields} out of a value that carries\n * them -- for projecting one pipeline stage's contract/variable into the next\n * (`link` -> `contract-model` -> `docs` catalog, ...) without re-listing all\n * nine fields at every hop.\n */\nexport function governanceFieldsOf(source: EnvGovernanceFields): EnvGovernanceFields {\n return {\n owner: source.owner,\n sensitivity: source.sensitivity,\n expiresAt: source.expiresAt,\n purpose: source.purpose,\n legalBasis: source.legalBasis,\n retention: source.retention,\n dataResidency: source.dataResidency,\n auditRequired: source.auditRequired,\n metadata: source.metadata,\n }\n}\n","import { displayPath } from \"./display-path.js\"\nimport { byContractIdentity } from \"./sort-by-identity.js\"\nimport { governanceFieldsOf, type EnvGovernanceFields } from \"./governance-fields.js\"\nimport type { DiscoveredContract } from \"./link.js\"\nimport type { DiscoveredVariableEvidence } from \"./parse.js\"\nimport type { PackageOrigin } from \"./resolution/resolve-package-schema.js\"\nimport type { SourcePosition } from \"./source-position.js\"\n\nfunction relativizePosition(root: string, position: SourcePosition): SourcePosition {\n return { ...position, file: displayPath(root, position.file) }\n}\n\n/** `PackageOrigin.resolvedFile`/`.packageDir` are absolute, realpath-canonicalized paths (the internal resolution machinery needs that) -- rendered relative here, matching every other path in this model. */\nfunction relativizePackageOrigin(\n root: string,\n origin: PackageOrigin | undefined,\n): PackageOrigin | undefined {\n if (!origin) return origin\n return {\n ...origin,\n resolvedFile: displayPath(root, origin.resolvedFile),\n packageDir: displayPath(root, origin.packageDir),\n }\n}\n\n/**\n * The first of env-cap's seven canonical fact models (ADR 0024) -- a\n * versioned, JSON-serializable projection of every declared environment\n * variable's structural and documentation contract. See ADR 0025.\n *\n * @remarks\n * Deliberately broader than the persisted evidence snapshot's\n * (`evidence-snapshot.ts`) `ManifestChangeReport` scope: that diff is scoped\n * to *active* contracts and *only* the `documentEnv()`-sourced fields,\n * matching `renderManifest()`'s own scope (ADR 0021). This model includes\n * every discovered contract regardless of `active`, plus the AST-derived\n * schema facts (`hasDefault`/`hasProcessor`/etc.) the change report\n * deliberately excludes -- both are load-bearing for downstream\n * Finding/Evidence Model work.\n */\n\n/** Bump only when a reader could misinterpret the new shape (a field changes\n * type/meaning, or is removed) -- NOT for every additive field. Same\n * discipline `evidence-model.ts`'s `EVIDENCE_MODEL_SCHEMA_VERSION` and\n * `src/cli/json.ts`'s `JSON_SCHEMA_VERSION` already document. */\nexport const CONTRACT_MODEL_SCHEMA_VERSION = 3\n\n/**\n * One variable's full statically-discoverable contract: schema-shaped facts plus linked documentation.\n *\n * @see {@link DependencyModelVariable} -- this same declared variable's access status.\n * @see {@link OwnershipModelVariable} -- this same declared variable's effective owner.\n * @see {@link LifecycleModelVariable} -- this same declared variable's lifecycle data.\n * @see `CatalogVariable` (`docs.ts`) -- this same declared variable, reshaped for the generated\n * docs catalog/JSON. Plain reference, not `{@link}`: `CatalogVariable` is intentionally not part\n * of the public surface (see `typedoc.json`'s `intentionallyNotExported`).\n */\nexport interface ContractModelVariable extends EnvGovernanceFields {\n readonly key: string\n readonly hasDefault: boolean\n readonly defaultValue:\n { readonly ok: true; readonly value: unknown } | { readonly ok: false } | undefined\n readonly hasProcessor: boolean\n readonly processorSource: string | undefined\n readonly processorReturnType: string | undefined\n readonly hasValidator: boolean\n readonly validatorSource: string | undefined\n readonly context: string | undefined\n readonly description: string | undefined\n readonly refreshInstructions: string | undefined\n readonly setupInstructions: string | undefined\n readonly required: boolean | undefined\n readonly documented: boolean\n /** The `evidence` sub-object from this variable's linked documentation -- re-verified every run, unlike every declared-only field above. See {@link runtime.VariableEvidenceDocs} and ADR 0037. */\n readonly evidence: DiscoveredVariableEvidence | undefined\n /** Where this variable's own schema property is declared. See ADR 0036. */\n readonly declaration: SourcePosition\n}\n\n/** One `createEnv()` contract's full statically-discoverable contract, active or not. */\nexport interface ContractModelContract extends EnvGovernanceFields {\n /** Root-relative, POSIX-separated -- matches `DiscoveredContractSummary.file`. */\n readonly file: string\n readonly exportName: string\n readonly contractName: string\n readonly active: boolean\n readonly category: string | undefined\n readonly exclusiveGroup: string | undefined\n readonly variables: readonly ContractModelVariable[]\n readonly documented: boolean\n readonly packageOrigin: PackageOrigin | undefined\n /** Where this contract's `createEnv(...)` call is declared. Always present. See ADR 0036. */\n readonly declaration: SourcePosition\n /** Where this contract's `documentEnv(...)` call is declared, if one exists. See ADR 0036. */\n readonly documentation: SourcePosition | undefined\n}\n\nexport interface ContractModel {\n readonly schemaVersion: typeof CONTRACT_MODEL_SCHEMA_VERSION\n readonly contracts: readonly ContractModelContract[]\n}\n\n/**\n * Projects every discovered contract (active or not) into the Contract\n * Model's versioned, JSON-serializable shape.\n *\n * @remarks\n * Sorted deterministically (by file, then exportName, then variable key), so\n * `JSON.stringify` output is stable and diffs cleanly wherever this is\n * persisted.\n */\nexport function buildContractModel(\n contracts: readonly DiscoveredContract[],\n root: string,\n): ContractModel {\n const projected: ContractModelContract[] = contracts.map((contract) => ({\n file: displayPath(root, contract.file),\n exportName: contract.exportName,\n contractName: contract.contractName,\n active: contract.active,\n category: contract.category,\n exclusiveGroup: contract.exclusiveGroup,\n ...governanceFieldsOf(contract),\n documented: contract.documented,\n packageOrigin: relativizePackageOrigin(root, contract.packageOrigin),\n declaration: relativizePosition(root, contract.declaration),\n documentation: contract.documentation && relativizePosition(root, contract.documentation),\n variables: [...contract.variables]\n .sort((a, b) => a.key.localeCompare(b.key))\n .map((variable) => ({\n key: variable.key,\n hasDefault: variable.hasDefault,\n defaultValue: variable.defaultValue,\n hasProcessor: variable.hasProcessor,\n processorSource: variable.processorSource,\n processorReturnType: variable.processorReturnType,\n hasValidator: variable.hasValidator,\n validatorSource: variable.validatorSource,\n context: variable.context,\n description: variable.description,\n // Explicit (not `...governanceFieldsOf`) because this stage interleaves\n // `refreshInstructions`/`setupInstructions`/`required` between the\n // governance fields, and the persisted `env.evidence.json` is compared\n // key-order-sensitively.\n owner: variable.owner,\n sensitivity: variable.sensitivity,\n expiresAt: variable.expiresAt,\n refreshInstructions: variable.refreshInstructions,\n setupInstructions: variable.setupInstructions,\n required: variable.required,\n purpose: variable.purpose,\n legalBasis: variable.legalBasis,\n retention: variable.retention,\n dataResidency: variable.dataResidency,\n auditRequired: variable.auditRequired,\n metadata: variable.metadata,\n documented: variable.documented,\n evidence: variable.evidence,\n declaration: relativizePosition(root, variable.declaration),\n })),\n }))\n\n projected.sort(byContractIdentity)\n\n return { schemaVersion: CONTRACT_MODEL_SCHEMA_VERSION, contracts: projected }\n}\n","/**\n * Recursively freezes `value` and everything reachable from it (array\n * elements, plain-object property values), so a mutation anywhere in the\n * structure throws instead of silently succeeding.\n *\n * @remarks\n * Generalized from `live-expirations.ts`'s former `DiscoveredContract[]`-\n * hardcoded `deepFreezeContracts()` (see ADR 0012) into a truly generic\n * utility, so Evidence Model's own immutability guarantee (a later phase)\n * can reuse it instead of duplicating the recursion.\n *\n * Only recurses into arrays and plain objects (`{}` or `Object.create(null)`)\n * -- a `Map`, `Set`, or class instance is frozen at its own top level but not\n * walked further. This codebase's fact models are plain JSON-serializable\n * data, never class instances, so this is deliberately narrow rather than a\n * general-purpose deep-freeze library. A `WeakSet` guards against infinite\n * recursion if a cyclic reference is ever passed in.\n */\nexport function deepFreeze<T>(value: T): T {\n return deepFreezeInternal(value, new WeakSet())\n}\n\nfunction deepFreezeInternal<T>(value: T, seen: WeakSet<object>): T {\n if (value === null || typeof value !== \"object\") return value\n if (seen.has(value)) return value\n seen.add(value)\n\n if (Array.isArray(value)) {\n for (const item of value) deepFreezeInternal(item, seen)\n } else if (isPlainObject(value)) {\n for (const key of Object.keys(value)) {\n deepFreezeInternal((value as Record<string, unknown>)[key], seen)\n }\n }\n\n return Object.freeze(value)\n}\n\nfunction isPlainObject(value: object): boolean {\n const proto: unknown = Object.getPrototypeOf(value)\n return proto === Object.prototype || proto === null\n}\n","import ts from \"typescript\"\nimport { collectImportBindings } from \"./parse.js\"\nimport type { ImportBinding } from \"./parse.js\"\nimport { positionOf } from \"./source-position.js\"\n\n/**\n * Why a tracked binding's value flowed somewhere this single-file, syntactic\n * walk cannot follow -- see ADR 0039. Each reason names the exact construct\n * so a downstream \"cannot determine whether X is read\" message can cite it,\n * rather than a single opaque \"escape\" label.\n */\nexport type EscapeReason =\n /** `const { ...rest } = contract` -- a rest element captures every remaining key at once. */\n | \"rest\"\n /** `const { X: { Y } } = contract` -- the bound value itself gets destructured again, one level too deep for this pass. */\n | \"nested-pattern\"\n /** `const { [expr]: v } = contract` where `expr` isn't a string literal -- the bound key can't be read without evaluating `expr`. */\n | \"computed-key\"\n /** `const e = contract` where `e` isn't file-unique/never-assigned (see `resolveAliasTargets`) -- the read is real, but this pass declines to follow `e` any further. */\n | \"reassignment\"\n\n/** One observed use of a tracked contract binding in a consumer file -- see ADR 0039. Consumed by `dependency-graph.ts`. */\nexport type AccessSite =\n | {\n readonly kind: \"member\"\n readonly member: string\n readonly line: number\n readonly column: number\n }\n | { readonly kind: \"dynamic\"; readonly line: number; readonly column: number }\n | { readonly kind: \"reference\"; readonly line: number; readonly column: number }\n | {\n readonly kind: \"escape\"\n readonly via: EscapeReason\n readonly line: number\n readonly column: number\n }\n\nexport interface FileScanResult {\n readonly file: string\n readonly imports: ReadonlyMap<string, ImportBinding>\n readonly accessesByLocalName: ReadonlyMap<string, readonly AccessSite[]>\n /** True if this file contains a bare `export * from \"...\"` -- used only to\n * flag ambiguous barrel forwarding elsewhere as \"unresolved\", never to\n * follow it (see ADR 0010's scope boundary). */\n readonly hasWildcardReExport: boolean\n}\n\nfunction unwrapParens(node: ts.Expression): ts.Expression {\n let current = node\n while (ts.isParenthesizedExpression(current)) current = current.expression\n return current\n}\n\nfunction staticElementKey(node: ts.Expression): string | undefined {\n return ts.isStringLiteralLike(node) ? node.text : undefined\n}\n\n/** One `const <name> = <identifier>` declaration -- a candidate one-level alias of `<identifier>`, before file-uniqueness/never-assigned checks (see `resolveAliasTargets`). */\ninterface AliasCandidate {\n readonly aliasName: string\n readonly baseName: string\n readonly declaration: ts.VariableDeclaration\n}\n\n/**\n * Recursively invokes `record` with every identifier name a binding pattern\n * introduces -- used only to make `declarationCounts` (see\n * `collectDeclarationFacts`) count a name shadowed via destructuring\n * elsewhere in the file, so a same-named alias candidate is correctly\n * disqualified rather than silently trusted.\n */\nfunction forEachBindingName(name: ts.BindingName, record: (identifierName: string) => void): void {\n if (ts.isIdentifier(name)) {\n record(name.text)\n return\n }\n for (const element of name.elements) {\n if (ts.isOmittedExpression(element)) continue\n forEachBindingName(element.name, record)\n }\n}\n\n/**\n * Whether `token` is `=` or a compound-assignment operator (`+=`, `??=`,\n * ...). `ts.isAssignmentOperator()` exists at runtime but isn't part of the\n * public `.d.ts` surface (an internal compiler API), so this uses the\n * public `SyntaxKind.FirstAssignment`/`LastAssignment` boundary markers\n * instead -- every assignment-operator token kind is a contiguous range\n * between them.\n */\nfunction isAssignmentToken(token: ts.SyntaxKind): boolean {\n return token >= ts.SyntaxKind.FirstAssignment && token <= ts.SyntaxKind.LastAssignment\n}\n\n/** Records `name` as an assignment target if `expression` (after unwrapping parens) is a bare identifier -- shared by the binary-assignment, increment/decrement, and bare-for-of/for-in cases below. */\nfunction recordIfIdentifierTarget(expression: ts.Expression, assignedNames: Set<string>): void {\n const target = unwrapParens(expression)\n // Removing this guard is behaviorally equivalent, not a real gap: an\n // assignment/increment target that isn't an identifier is a member or\n // element access, neither of which has a `.text` property, so\n // `assignedNames.add(target.text)` would add `undefined` -- harmless,\n // since no candidate alias name is ever `undefined`. Hand-verified:\n // mutating this to `if (true)` and running the real suite passes\n // unchanged.\n // Stryker disable next-line ConditionalExpression\n if (ts.isIdentifier(target)) assignedNames.add(target.text)\n}\n\n/**\n * Every way this pass recognizes a name as \"assigned to\" after its\n * declaration: `=`/compound assignment, `++`/`--`, and the keyword-less\n * `for (e of list)`/`for (e in obj)` form (which reuses an existing binding\n * as its loop variable, rather than declaring a fresh one). Deliberately\n * conservative -- missing a real reassignment shape only means a real alias\n * goes untracked (its source binding degrades to an `escape` instead), never\n * the other way around.\n */\nfunction recordAssignmentTargets(node: ts.Node, assignedNames: Set<string>): void {\n if (ts.isBinaryExpression(node) && isAssignmentToken(node.operatorToken.kind)) {\n recordIfIdentifierTarget(node.left, assignedNames)\n return\n }\n if (\n // Widening this to `true` is behaviorally equivalent, not a real gap:\n // only a prefix/postfix unary node carries an `.operator` at all, so on\n // any other node the two `=== PlusPlus/MinusMinus` checks below both\n // read `undefined` and fail. Hand-verified: mutating this compound to\n // `if (true)` and running the real suite passes unchanged.\n // Stryker disable next-line ConditionalExpression\n (ts.isPrefixUnaryExpression(node) || ts.isPostfixUnaryExpression(node)) &&\n (node.operator === ts.SyntaxKind.PlusPlusToken ||\n node.operator === ts.SyntaxKind.MinusMinusToken)\n ) {\n recordIfIdentifierTarget(node.operand, assignedNames)\n return\n }\n if (\n (ts.isForOfStatement(node) || ts.isForInStatement(node)) &&\n !ts.isVariableDeclarationList(node.initializer)\n ) {\n recordIfIdentifierTarget(node.initializer, assignedNames)\n }\n}\n\n/**\n * Counts one declaration-introducing node (a `const`/`let`/`var` declarator,\n * a parameter, or a named function/class) toward `declarationCounts`, and\n * records a plain `const <name> = <identifier>` shape as an alias candidate.\n *\n * A `catch (e)` binding needs no branch of its own -- `CatchClause.\n * variableDeclaration` IS a `ts.VariableDeclaration`, so the walk visits it\n * and the first branch below counts its name like any other.\n */\nfunction recordDeclarationIntroduction(\n node: ts.Node,\n countDeclaration: (name: string) => void,\n constAliasCandidates: AliasCandidate[],\n): void {\n if (ts.isVariableDeclaration(node) || ts.isParameter(node)) {\n // `forEachBindingName` counts a bare `Identifier` name directly and\n // recurses every identifier a destructuring pattern introduces -- one\n // path for both shapes.\n forEachBindingName(node.name, countDeclaration)\n if (!ts.isVariableDeclaration(node) || !ts.isIdentifier(node.name)) return\n if (node.initializer === undefined) return\n const initializer = unwrapParens(node.initializer)\n const isConst = (ts.getCombinedNodeFlags(node) & ts.NodeFlags.Const) !== 0\n if (isConst && ts.isIdentifier(initializer)) {\n constAliasCandidates.push({\n aliasName: node.name.text,\n baseName: initializer.text,\n declaration: node,\n })\n }\n return\n }\n if ((ts.isFunctionDeclaration(node) || ts.isClassDeclaration(node)) && node.name) {\n countDeclaration(node.name.text)\n }\n}\n\n/**\n * One whole-file pass collecting the three facts `resolveAliasTargets` needs:\n * how many times each name is introduced as *any* kind of binding (a same\n * name declared twice anywhere -- including inside a nested scope, since\n * this pass is deliberately not scope-aware, matching every other check in\n * this file -- disqualifies it as a trackable alias), which names are ever\n * assigned to after their declaration, and every plain `const <name> =\n * <identifier>` declaration as a raw candidate.\n */\nfunction collectDeclarationFacts(sourceFile: ts.SourceFile): {\n readonly declarationCounts: ReadonlyMap<string, number>\n readonly assignedNames: ReadonlySet<string>\n readonly constAliasCandidates: readonly AliasCandidate[]\n} {\n const declarationCounts = new Map<string, number>()\n const assignedNames = new Set<string>()\n // A poisoned seed element here is behaviorally equivalent, not a real gap:\n // it would be a plain string, whose `.baseName` reads `undefined`, so\n // `imports.get(undefined)` misses in `resolveAliasTargets` and the entry\n // is skipped before it can reach either the valid or disqualified path.\n // Hand-verified: mutating this and running the real suite passes unchanged.\n // Stryker disable next-line ArrayDeclaration\n const constAliasCandidates: AliasCandidate[] = []\n\n function countDeclaration(name: string): void {\n declarationCounts.set(name, (declarationCounts.get(name) ?? 0) + 1)\n }\n\n function walk(node: ts.Node): void {\n recordDeclarationIntroduction(node, countDeclaration, constAliasCandidates)\n recordAssignmentTargets(node, assignedNames)\n ts.forEachChild(node, walk)\n }\n\n ts.forEachChild(sourceFile, walk)\n return { declarationCounts, assignedNames, constAliasCandidates }\n}\n\n/**\n * Narrows raw `const <name> = <identifier>` candidates down to the ones\n * safe to track as a one-level alias of a real tracked import: `<name>`\n * must be declared exactly once anywhere in the file and never assigned to\n * afterward, and `<identifier>` must itself already be a tracked import\n * (never another alias -- deliberately one level, no chains; see ADR 0039).\n * Every candidate that resolves a real import's name but fails the\n * uniqueness/never-assigned check is reported back as an `escape` against\n * that import instead of silently dropped -- `const e = contract` is a real\n * read of `contract` this pass simply declines to follow further.\n */\nfunction resolveAliasTargets(\n candidates: readonly AliasCandidate[],\n declarationCounts: ReadonlyMap<string, number>,\n assignedNames: ReadonlySet<string>,\n imports: ReadonlyMap<string, ImportBinding>,\n): {\n readonly aliasBindings: ReadonlyMap<string, ImportBinding>\n readonly disqualified: readonly AliasCandidate[]\n /** Every candidate declaration whose base is a real tracked import -- resolved or not. The main walk must not ALSO walk these as a generic bare reference (see the call site). A `const b = a` chained onto a resolved alias `a` is NOT in here: its base `a` isn't a real import, so it stays a normal walk -- correctly recording `a` as an escape, since this pass never follows the second hop. */\n readonly handledDeclarations: ReadonlySet<ts.Node>\n} {\n const aliasBindings = new Map<string, ImportBinding>()\n const disqualified: AliasCandidate[] = []\n const handledDeclarations = new Set<ts.Node>()\n\n for (const candidate of candidates) {\n const baseBinding = imports.get(candidate.baseName)\n if (baseBinding === undefined || imports.has(candidate.aliasName)) continue\n handledDeclarations.add(candidate.declaration)\n // `declarationCounts.get(candidate.aliasName)` is never `undefined` here --\n // `recordDeclarationIntroduction` always counts a declaration in the same\n // branch where it pushes a `constAliasCandidates` entry for it, so every\n // candidate's own name was counted at least once. `undefined === 1` would\n // evaluate to `false` regardless, so no `?? 0` fallback is needed.\n const isFileUnique = declarationCounts.get(candidate.aliasName) === 1\n const isNeverAssigned = !assignedNames.has(candidate.aliasName)\n if (isFileUnique && isNeverAssigned) {\n aliasBindings.set(candidate.aliasName, baseBinding)\n } else {\n disqualified.push(candidate)\n }\n }\n\n return { aliasBindings, disqualified, handledDeclarations }\n}\n\n/**\n * The property key one object-binding element reads from its (tracked)\n * source: a `string` when it's statically knowable (`{ X }`, `{ X: y }`,\n * `{ \"X\": y }`, `{ [\"X\"]: y }`), or the key `ts.Expression` itself when it\n * can't be read without evaluating something (`{ [k]: y }`, `{ [f()]: y }`,\n * `{ 5: y }`) -- the caller records an `escape` and walks that expression\n * for nested tracked references.\n */\nfunction bindingElementKey(element: ts.BindingElement): string | ts.Expression {\n if (element.propertyName === undefined) {\n // Shorthand form (`{ X }`) -- guaranteed an Identifier by the caller's own `ts.isIdentifier(element.name)` check before reaching here for the shorthand case; a renamed shorthand-less form always sets propertyName instead.\n return (element.name as ts.Identifier).text\n }\n if (ts.isIdentifier(element.propertyName) || ts.isStringLiteral(element.propertyName)) {\n return element.propertyName.text\n }\n if (ts.isComputedPropertyName(element.propertyName)) {\n const inner = element.propertyName.expression\n return ts.isStringLiteralLike(inner) ? inner.text : inner\n }\n // A NumericLiteral (or any other) propertyName -- mirrors staticElementKey()'s own\n // string-literal-only rule for element access: not statically resolvable to the string keys a\n // contract actually declares.\n return element.propertyName\n}\n\nexport function scanFileForDependencies(filePath: string, sourceText: string): FileScanResult {\n const scriptKind = filePath.endsWith(\".tsx\") ? ts.ScriptKind.TSX : ts.ScriptKind.TS\n const sourceFile = ts.createSourceFile(\n filePath,\n sourceText,\n ts.ScriptTarget.Latest,\n // Load-bearing, unlike before: `ts.getCombinedNodeFlags()` (used to tell\n // a `const` declaration apart from `let`/`var` when resolving alias\n // candidates) walks parent pointers internally. Flipping this to `false`\n // now breaks const-detection silently rather than merely being an\n // unobserved no-op -- do not remove parent-pointer tracking here.\n true,\n scriptKind,\n )\n\n const imports = new Map<string, ImportBinding>()\n let hasWildcardReExport = false\n for (const statement of sourceFile.statements) {\n if (ts.isImportDeclaration(statement)) {\n collectImportBindings(statement, imports)\n } else if (\n ts.isExportDeclaration(statement) &&\n !statement.exportClause &&\n statement.moduleSpecifier\n ) {\n hasWildcardReExport = true\n }\n }\n\n const accesses = new Map<string, AccessSite[]>()\n\n // Every call site below already checks `imports.has(name)` before calling\n // this -- record() trusts that instead of re-checking it.\n function record(localName: string, site: AccessSite): void {\n const sites = accesses.get(localName) ?? []\n sites.push(site)\n accesses.set(localName, sites)\n }\n\n const { declarationCounts, assignedNames, constAliasCandidates } =\n collectDeclarationFacts(sourceFile)\n const { aliasBindings, disqualified, handledDeclarations } = resolveAliasTargets(\n constAliasCandidates,\n declarationCounts,\n assignedNames,\n imports,\n )\n // A validated one-level alias is registered as \"just another local name\n // for the same import\" -- the main walk below, and every downstream\n // consumer (dependency-graph.ts's pass 1 in particular), then treats\n // `e.X` exactly like `paymentsEnv.X` with zero further special-casing.\n for (const [aliasName, binding] of aliasBindings) {\n imports.set(aliasName, binding)\n }\n for (const candidate of disqualified) {\n record(candidate.baseName, {\n kind: \"escape\",\n via: \"reassignment\",\n ...positionOf(sourceFile, candidate.declaration),\n })\n }\n // Every candidate whose base really is a tracked import is now fully\n // accounted for above -- a valid one via its own registered alias name\n // (whose future accesses the main walk records normally), a disqualified\n // one via the explicit `escape` just recorded. Either way, the main walk\n // below must not ALSO record a generic bare \"reference\" for the\n // declaration's own initializer, which would double-report the exact same\n // read (harmlessly, but redundantly) for a valid alias and, worse, mask\n // WHERE a disqualified one's escape is by duplicating it under a less\n // specific site kind. `handledDeclarations` is exactly that set (see its\n // own doc comment for why a `const b = a` chain is deliberately NOT in it).\n\n function recordObjectBindingAccesses(pattern: ts.ObjectBindingPattern, localName: string): void {\n for (const element of pattern.elements) {\n if (element.dotDotDotToken) {\n record(localName, { kind: \"escape\", via: \"rest\", ...positionOf(sourceFile, element) })\n } else if (!ts.isIdentifier(element.name)) {\n record(localName, {\n kind: \"escape\",\n via: \"nested-pattern\",\n ...positionOf(sourceFile, element),\n })\n } else {\n const key = bindingElementKey(element)\n if (typeof key === \"string\") {\n record(localName, { kind: \"member\", member: key, ...positionOf(sourceFile, element) })\n } else {\n record(localName, {\n kind: \"escape\",\n via: \"computed-key\",\n ...positionOf(sourceFile, element),\n })\n // The computed key expression itself might reference other tracked names.\n ts.forEachChild(key, visit)\n }\n }\n // The guard is a defensive micro-optimization only -- `ts.forEachChild`\n // returns `undefined` for a nullish node without throwing, so dropping\n // the check is behaviorally equivalent. Hand-verified: mutating this to\n // `if (true)` and running the real suite passes unchanged. The\n // block-removal mutant, by contrast, IS caught (a binding element WITH\n // a default value that references a tracked import -- see the test).\n // Stryker disable next-line ConditionalExpression\n if (element.initializer) ts.forEachChild(element.initializer, visit)\n }\n }\n\n /** `x.MEMBER` / `x[\"MEMBER\"]` / `x[expr]` on a tracked local name `x`. Returns whether a site was recorded (so `visit` stops descending). */\n function tryRecordPropertyOrElementAccess(node: ts.Node): boolean {\n const isProperty = ts.isPropertyAccessExpression(node)\n if (!isProperty && !ts.isElementAccessExpression(node)) return false\n const base = unwrapParens(node.expression)\n if (!ts.isIdentifier(base) || !imports.has(base.text)) return false\n if (isProperty) {\n record(base.text, { kind: \"member\", member: node.name.text, ...positionOf(sourceFile, node) })\n return true\n }\n const key = staticElementKey(node.argumentExpression)\n record(\n base.text,\n key !== undefined\n ? { kind: \"member\", member: key, ...positionOf(sourceFile, node) }\n : { kind: \"dynamic\", ...positionOf(sourceFile, node) },\n )\n ts.forEachChild(node.argumentExpression, visit) // the computed key itself might reference other tracked names\n return true\n }\n\n function visit(node: ts.Node): void {\n // Import/export declarations are already accounted for (imports /\n // wildcard-re-export); never descend into either, so an import/export\n // specifier's own identifier is never mistaken for a real usage. A\n // VariableDeclaration in `handledDeclarations` is a resolved-or-\n // disqualified alias whose own read of the import is already recorded --\n // see that set's doc comment.\n if (\n ts.isImportDeclaration(node) ||\n ts.isExportDeclaration(node) ||\n (ts.isVariableDeclaration(node) && handledDeclarations.has(node))\n ) {\n return\n }\n\n if (\n ts.isVariableDeclaration(node) &&\n ts.isObjectBindingPattern(node.name) &&\n node.initializer\n ) {\n const base = unwrapParens(node.initializer)\n if (ts.isIdentifier(base) && imports.has(base.text)) {\n recordObjectBindingAccesses(node.name, base.text)\n return\n }\n }\n\n if (tryRecordPropertyOrElementAccess(node)) return\n\n if (ts.isIdentifier(node) && imports.has(node.text)) {\n record(node.text, { kind: \"reference\", ...positionOf(sourceFile, node) })\n return\n }\n\n ts.forEachChild(node, visit)\n }\n\n ts.forEachChild(sourceFile, visit)\n\n return { file: filePath, imports, accessesByLocalName: accesses, hasWildcardReExport }\n}\n","/**\n * Single source of truth for the \"this file is generated\" marker text, so it\n * can never drift out of sync between where it's written (`manifest.ts`,\n * `docs.ts`, `usage-report.ts`) and where it's read (`scan-dependencies.ts`,\n * closing the self-reference loop where a contract's own generated manifest\n * would otherwise make it look permanently \"used\"). Not configurable, not\n * public.\n *\n * Also home to the two standing notices every governance-adjacent artifact\n * stamps near the top -- `evidenceDisclaimer()` and\n * `evidenceProjectionNote()`. They live here, next to the banner, because\n * they answer the same question the banner does (\"what is this file, and how\n * much should I trust it?\") and because a renderer that emits one must never\n * be able to emit the others from a stale, separately-maintained copy.\n */\n\n/**\n * The literal marker embedded in every {@link generatedBanner}-produced\n * comment, and what {@link isGeneratedFile} looks for. A function, not a\n * module-level `const` -- a `const` string's mutants are evaluated once at\n * module load and can't be attributed to the test that covers them under\n * Stryker's `perTest` coverage analysis (a documented false-Survivor, not a\n * real gap); a function's return literal is evaluated per call, same as any\n * other code.\n */\nfunction generatedFileMarker(): string {\n return \"GENERATED FILE\"\n}\n\n/** Renders the \"do not edit by hand\" marker in the given comment syntax. */\nexport function generatedBanner(format: \"ts\" | \"markdown\" = \"ts\"): string {\n const text = `${generatedFileMarker()} -- do not edit by hand. Run \\`npx env-cap\\` to regenerate.`\n // An object lookup, not a `format === \"ts\" ? ... : ...` ternary: with only\n // two checked literal values, a ternary's untaken branch is an \"equivalent\n // mutant\" magnet (mutating the \"ts\" comparison string still routes every\n // non-\"ts\" test case to the same markdown branch). A mutated key here\n // returns `undefined` instead, which every caller/test can observe.\n return { ts: `// ${text}`, markdown: `<!-- ${text} -->` }[format]\n}\n\n/**\n * Whether `content` carries a {@link generatedBanner}-produced marker, in\n * either format.\n *\n * @remarks\n * Deliberately not a bare `content.startsWith(generatedBanner(...))`: a\n * shebang, a `\"use strict\"` pragma, or a license header pushes a real banner\n * off line one, and a stricter check would then read a genuinely generated\n * file as hand-written -- which `dependency-graph.ts` would take as \"a real\n * consumer imports this contract,\" permanently masking an abandoned one. The\n * marker is looked for across the first 20 non-empty lines instead, which\n * clears every realistic preamble without scanning a whole file.\n */\nexport function isGeneratedFile(content: string): boolean {\n const nonEmptyLines = content.split(\"\\n\").filter((line) => line.trim().length > 0)\n return nonEmptyLines.slice(0, 20).some((line) => line.includes(generatedFileMarker()))\n}\n\n/**\n * Short disclaimer stamped into every artifact that renders sensitivity/\n * ownership/expiry claims (the docs Catalog, the Dependency & Ownership\n * Report). Never omit this from an artifact that renders `documentEnv()`\n * metadata: it's what keeps \"documented\" from being misread as \"verified\" or\n * \"compliant.\" Every fact in those artifacts is either a statically-provable\n * code fact or an author's own declaration -- env-cap never executes a schema\n * file and never validates a declaration against reality.\n */\nexport function evidenceDisclaimer(): string {\n return \"Machine-generated engineering artifact assembled from statically-provable code facts and author-declared documentation. It can support a security, privacy, or compliance review. It does not itself establish compliance with any standard.\"\n}\n\n/**\n * States, by concept, that this artifact is a projection of env-cap's\n * Evidence Model (ADR 0031/0038) -- never a hardcoded path, since\n * `docs/env.evidence.json` only exists on a run that actually passed\n * `--evidence`; a project that never requests that flag would otherwise get\n * a note pointing at a file that doesn't exist. `evidencePath`, when this\n * same run's own options did include `--evidence <path>`, names that\n * concrete path in addition to the concept.\n */\nexport function evidenceProjectionNote(evidencePath?: string): string {\n const concept =\n \"Projected from env-cap's Evidence Model (ADR 0031/0038), the same source every other generated artifact draws from.\"\n return evidencePath === undefined\n ? concept\n : `${concept} This run also wrote it to \\`${evidencePath}\\`.`\n}\n","import { displayPath } from \"./display-path.js\"\nimport { scanFileForDependencies } from \"./scan-dependencies.js\"\nimport type { AccessSite, EscapeReason, FileScanResult } from \"./scan-dependencies.js\"\nimport { resolveImportSpecifier } from \"./resolution/resolve-import.js\"\nimport type { ImportResolutionContext } from \"./resolution/resolve-import.js\"\nimport { isGeneratedFile } from \"./generated-banner.js\"\nimport { dynamicAccessVariableIdentity } from \"./citation-verification.js\"\nimport type { DiscoveredContract } from \"./link.js\"\nimport type { ParseWarning } from \"./parse.js\"\nimport type { DynamicAccessAssertion, SourcePosition } from \"./source-position.js\"\n\n/**\n * What env-cap's static scan could prove about one variable's consumption:\n * it was member-accessed somewhere (`\"used\"`), it was never accessed at all\n * within the scanned surfaces (`\"unconsumed\"`), or a computed (dynamic)\n * property access on the owning contract makes the answer unprovable\n * (`\"indeterminate\"`).\n *\n * @remarks\n * Deliberately narrower than `@maverickcer/data-cap`'s equivalent, which\n * splits the unprovable case further (an unresolved *consumer* vs. an\n * indeterminate *field*). That split exists because a data-cap capability\n * exposes many fields at once, so it has a real \"we resolved the consumer,\n * but can't tell which field it touched\" state to name. env-cap's\n * consumption model is one value per key: a contract member access either\n * names the key statically (`\"used\"`) or it doesn't (`\"indeterminate\"`), and\n * there is no intermediate case where the consumer is known but the thing\n * consumed is ambiguous. Adding a fourth state here would be vocabulary\n * borrowed from a model env-cap doesn't have -- see ADR 0010's\n * \"provable, not heuristic\" rule. Developer-declared `dynamicAccess`\n * citations stay a wholly separate fact and are never folded into this\n * status (ADR 0037).\n */\nexport type VariableAccessStatus = \"used\" | \"unconsumed\" | \"indeterminate\"\n\n/**\n * Every reason `deriveOwnershipFindings` can cite for an `indeterminate`\n * variable, cited on the {@link EscapeSite} the scanner actually observed --\n * `EscapeReason` (destructuring/aliasing shapes the scanner declines to\n * follow, see ADR 0039) plus `\"reference\"` for a tracked import/alias\n * mentioned bare (passed as an argument, spread, assigned elsewhere, ...):\n * a real, provable read of the contract that this single-file walk simply\n * can't attribute to any specific key.\n */\ntype EscapeVia = EscapeReason | \"reference\"\n\n/** One position where a tracked contract's value escaped this scanner's local dataflow analysis -- see {@link EscapeVia}. */\ninterface EscapeSite extends SourcePosition {\n readonly via: EscapeVia\n}\n\ninterface VariableAccessInfo {\n readonly status: VariableAccessStatus\n /** Internal only, never exposed publicly -- which AST evidence produced\n * this status, so a future \"why does env-cap think this is\n * unconsumed\" bug report is debuggable without re-deriving the AST walk\n * by hand. */\n readonly evidence: \"member-access\" | \"dynamic-access\" | \"escape\" | \"no-access\"\n /** Every position where a member access was observed for this variable,\n * aggregated across every consuming file -- empty unless\n * `status === \"used\"`. Previously computed by `scan-dependencies.ts`'s\n * `AccessSite` and discarded before reaching even this internal type;\n * threaded through as of ADR 0027 (line only) and ADR 0036 (full\n * position, one entry per file rather than a flat, file-less list of\n * line numbers) so `dependency-model.ts` can publish it. */\n readonly positions: readonly SourcePosition[]\n /** Every developer-declared `dynamicAccess` citation's current freshness for this variable -- a wholly separate, independent fact from `status`/`evidence` above, never folded into them. Empty unless the linked `documentEnv()` call declared at least one citation for this key. See ADR 0037. */\n readonly dynamicAccessAssertions: readonly DynamicAccessAssertion[]\n}\n\n/** One named surface `buildDependencyGraph()`'s scan actually covered -- the\n * application's own root, plus one entry per allow-listed `packages` (ADR\n * 0014) name whose source was also scanned. See ADR 0036: a claim like\n * \"no consumer found\" is only ever as strong as what was actually\n * searched, and this is what lets a renderer say so explicitly instead of\n * implying an unbounded guarantee it can't back up. */\nexport interface ScannedSurface {\n /** `\"application\"` for the local project root, `\"package:<name>\"` for an allow-listed package's own source. */\n readonly label: string\n /** Root-relative, POSIX-separated. */\n readonly root: string\n}\n\ninterface ContractDependencySummary {\n readonly file: string\n readonly exportName: string\n readonly contractName: string\n readonly imported: boolean\n readonly hasDynamicAccess: boolean\n /** Every declared key is always present. */\n readonly variables: ReadonlyMap<string, VariableAccessInfo>\n /** Every file coupled to this contract -- contract-level \"who depends on\n * this,\" not proof any specific variable was read. See the\n * consumer-vs-variable-access semantics note in `deriveOwnershipFindings`. */\n readonly consumingFiles: readonly string[]\n /** Files whose import of this contract's name couldn't be verified\n * because it resolved through a file containing an unresolved wildcard\n * re-export. */\n readonly ambiguousBarrelFiles: readonly string[]\n /** Every computed (dynamic) property-access site observed anywhere on\n * this contract -- previously collapsed into `hasDynamicAccess` alone\n * and discarded; threaded through as of ADR 0036 so a finding can cite\n * exactly where the uncertainty comes from instead of just asserting it\n * exists. */\n readonly dynamicAccessSites: readonly SourcePosition[]\n /** Every position where the contract's value flowed somewhere this\n * scanner's local dataflow analysis can't follow -- see {@link\n * EscapeVia} and ADR 0039. Like `dynamicAccessSites`, this widens every\n * not-otherwise-accessed variable on the SAME contract to\n * `indeterminate`, never `unconsumed`. */\n readonly escapeSites: readonly EscapeSite[]\n}\n\nexport interface DependencyGraph {\n readonly contracts: readonly ContractDependencySummary[]\n readonly warnings: readonly ParseWarning[]\n /** Every surface actually scanned for usage -- see {@link ScannedSurface}. Always has at least one entry (the application root). */\n readonly scannedSurfaces: readonly ScannedSurface[]\n}\n\ninterface BuildingContract {\n file: string\n exportName: string\n contractName: string\n imported: boolean\n variables: Map<string, { hasMemberAccess: boolean; positions: SourcePosition[] }>\n consumingFiles: Set<string>\n ambiguousBarrelFiles: Set<string>\n dynamicAccessSites: SourcePosition[]\n escapeSites: EscapeSite[]\n}\n\n/**\n * Builds the dependency graph: for every discovered contract, which files\n * import it and which of its variables are actually read. Resolves import\n * specifiers via `resolveImportSpecifier` (relative imports, plus -- since\n * ADR 0023 -- a bare specifier matching the project's own `tsconfig.json`\n * `paths`/`baseUrl`, plus -- since ADR 0014 -- a bare specifier matching an\n * allow-listed package) -- same identity shape `link.ts` already uses\n * (`file#exportName`), no new scheme. Wiring `resolveImportSpecifier` in\n * here (not just `link.ts`) is load-bearing, not optional: without it, a\n * contract's consumer reached only through an alias (`import { x } from\n * \"@/contracts/x\"`) or a cross-package import (`import { x } from\n * \"@acme/pkg\"`) could never resolve, and the contract would be misreported\n * as `abandoned` by `deriveOwnershipFindings` below. Never executes any\n * scanned file.\n *\n * @param scannedSurfaces - Every surface `scanFiles` was drawn from (ADR\n * 0036) -- the caller (`generate-usage.ts`'s `computeScanSurface()`) is\n * responsible for actually walking each surface and merging the resulting\n * file lists into `scanFiles`; this function only records the labels for\n * downstream reporting, exactly as given.\n * @param dynamicAccessAcknowledgments - Every current `dynamicAccess`\n * citation's freshness, keyed by `dynamicAccessVariableIdentity()` (ADR\n * 0037) -- the caller (`evidence-snapshot.ts`'s\n * `computeDynamicAccessAcknowledgments()`) is responsible for actually\n * computing it; omitted entirely (never partially computed) when no\n * previous evidence snapshot location was configured, since there's no\n * committed baseline to check freshness against without one.\n */\n/** Reads and statically scans every file, skipping unreadable and generated ones. */\nasync function scanAllFiles(\n scanFiles: readonly string[],\n readFile: (filePath: string) => Promise<string>,\n): Promise<FileScanResult[]> {\n const scanResults: FileScanResult[] = []\n for (const file of scanFiles) {\n let text: string\n try {\n text = await readFile(file)\n } catch {\n continue\n }\n if (isGeneratedFile(text)) continue\n scanResults.push(scanFileForDependencies(file, text))\n }\n return scanResults\n}\n\n/** One empty `BuildingContract` per discovered contract, keyed `file#exportName`. */\nfunction initBuildingContracts(\n contracts: readonly DiscoveredContract[],\n): Map<string, BuildingContract> {\n const byIdentity = new Map<string, BuildingContract>()\n for (const contract of contracts) {\n const variables = new Map<string, { hasMemberAccess: boolean; positions: SourcePosition[] }>()\n for (const variable of contract.variables)\n variables.set(variable.key, { hasMemberAccess: false, positions: [] })\n byIdentity.set(`${contract.file}#${contract.exportName}`, {\n file: contract.file,\n exportName: contract.exportName,\n contractName: contract.contractName,\n imported: false,\n variables,\n consumingFiles: new Set(),\n ambiguousBarrelFiles: new Set(),\n dynamicAccessSites: [],\n escapeSites: [],\n })\n }\n return byIdentity\n}\n\n/**\n * Folds one consuming file's access sites for one tracked local name into\n * `building`. A `dynamic` site records a contract-level computed-access\n * position; a `member` site marks a specific variable read; a `reference`\n * (bare mention) or `escape` (rest/nested/computed-key binding, or an alias\n * this scan declined to follow -- ADR 0039) both record a contract-level\n * escape position, which `deriveOwnershipFindings` widens every\n * not-otherwise-read variable to `indeterminate` on, exactly as\n * `dynamicAccessSites` already does. A proven member access on the same key\n * still wins (see `classifyVariable`).\n */\nfunction attributeAccessSites(\n building: BuildingContract,\n scanFile: string,\n // A poisoned fallback element here is behaviorally equivalent, not a real\n // gap: a plain string's `.kind` reads `undefined`, matching none of the\n // branches below. Hand-verified: mutating the `?? []` and running the\n // real suite passes unchanged.\n // Stryker disable next-line ArrayDeclaration\n sites: readonly AccessSite[] = [],\n): void {\n for (const site of sites) {\n if (site.kind === \"dynamic\") {\n building.dynamicAccessSites.push({ file: scanFile, line: site.line, column: site.column })\n } else if (site.kind === \"member\") {\n const variable = building.variables.get(site.member)\n if (variable) {\n variable.hasMemberAccess = true\n variable.positions.push({ file: scanFile, line: site.line, column: site.column })\n }\n } else {\n building.escapeSites.push({\n file: scanFile,\n line: site.line,\n column: site.column,\n via: site.kind === \"escape\" ? site.via : \"reference\",\n })\n }\n }\n}\n\n/**\n * Sorts two positions by file, then line. The `a.line - b.line` tiebreak\n * (only reached when `a.file === b.file`) is unreachable-to-differ from `+`:\n * every position for ONE variable in ONE file is pushed by a single\n * top-to-bottom AST walk of that file's source, so same-file positions are\n * always ALREADY in non-decreasing line order by construction. Hand-verified:\n * mutating `-` to `+` and running the real suite passes unchanged.\n */\n// Stryker disable ArithmeticOperator\nfunction byPosition(a: SourcePosition, b: SourcePosition): number {\n return a.file.localeCompare(b.file) || a.line - b.line\n}\n// Stryker restore ArithmeticOperator\n\n/** One variable's final access status: a proven member access is always `used`; otherwise a contract-level dynamic access or escape makes it `indeterminate`; otherwise `unconsumed`. */\nfunction classifyVariable(\n info: { hasMemberAccess: boolean; positions: readonly SourcePosition[] },\n hasDynamicAccess: boolean,\n hasEscape: boolean,\n dynamicAccessAssertions: readonly DynamicAccessAssertion[],\n): VariableAccessInfo {\n if (info.hasMemberAccess) {\n return {\n status: \"used\",\n evidence: \"member-access\",\n positions: [...info.positions].sort(byPosition),\n dynamicAccessAssertions,\n }\n }\n const evidence: VariableAccessInfo[\"evidence\"] = hasDynamicAccess\n ? \"dynamic-access\"\n : hasEscape\n ? \"escape\"\n : \"no-access\"\n return {\n status: hasDynamicAccess || hasEscape ? \"indeterminate\" : \"unconsumed\",\n evidence,\n positions: [],\n dynamicAccessAssertions,\n }\n}\n\n/** Maps one fully-populated `BuildingContract` into its immutable public summary. */\nfunction finalizeContract(\n building: BuildingContract,\n root: string,\n dynamicAccessAcknowledgments: ReadonlyMap<string, readonly DynamicAccessAssertion[]> | undefined,\n): ContractDependencySummary {\n const hasDynamicAccess = building.dynamicAccessSites.length > 0\n const hasEscape = building.escapeSites.length > 0\n const relativeFile = displayPath(root, building.file)\n const variables = new Map<string, VariableAccessInfo>()\n for (const [key, info] of building.variables) {\n const dynamicAccessAssertions =\n dynamicAccessAcknowledgments?.get(\n dynamicAccessVariableIdentity(relativeFile, building.exportName, key),\n ) ?? []\n variables.set(key, classifyVariable(info, hasDynamicAccess, hasEscape, dynamicAccessAssertions))\n }\n return {\n file: building.file,\n exportName: building.exportName,\n contractName: building.contractName,\n imported: building.imported,\n hasDynamicAccess,\n variables,\n consumingFiles: [...building.consumingFiles].sort(),\n ambiguousBarrelFiles: [...building.ambiguousBarrelFiles].sort(),\n dynamicAccessSites: [...building.dynamicAccessSites].sort(byPosition),\n escapeSites: [...building.escapeSites].sort(byPosition),\n }\n}\n\nexport async function buildDependencyGraph(\n contracts: readonly DiscoveredContract[],\n scanFiles: readonly string[],\n readFile: (filePath: string) => Promise<string>,\n context: ImportResolutionContext,\n scannedSurfaces: readonly ScannedSurface[] = [{ label: \"application\", root: \".\" }],\n dynamicAccessAcknowledgments?: ReadonlyMap<string, readonly DynamicAccessAssertion[]>,\n): Promise<DependencyGraph> {\n const warnings: ParseWarning[] = []\n const scanResults = await scanAllFiles(scanFiles, readFile)\n const scanByFile = new Map(scanResults.map((result) => [result.file, result]))\n const byIdentity = initBuildingContracts(contracts)\n\n // Pass 1: direct resolution -- import specifier resolves to a file that\n // itself declares the requested export name as a known contract.\n for (const scan of scanResults) {\n for (const [localName, binding] of scan.imports) {\n const resolvedFile = await resolveImportSpecifier(scan.file, binding.specifier, context)\n // Bypassing this guard is behaviorally equivalent for any realistic\n // fixture, not a real gap: an undefined `resolvedFile` makes the\n // lookup key `` `undefined#${binding.importedName}` ``, which the next\n // `if (!building) continue` guard already absorbs. Hand-verified:\n // mutating this and running the real suite passes unchanged.\n // Stryker disable next-line ConditionalExpression\n if (!resolvedFile) continue // bare/package specifier or nonexistent file -- unresolvable, skip silently\n\n const building = byIdentity.get(`${resolvedFile}#${binding.importedName}`)\n if (!building) continue // handled in pass 2 if this turns out to be an ambiguous barrel forward\n\n building.imported = true\n building.consumingFiles.add(scan.file)\n attributeAccessSites(building, scan.file, scan.accessesByLocalName.get(localName))\n }\n }\n\n // Pass 2: ambiguous barrel forwarding -- for contracts never directly\n // resolved, check whether any scanned file imports a name matching this\n // contract's exportName through a specifier that resolves to a file\n // containing an unresolved `export * from \"...\"`. This is a name-based\n // heuristic, not a resolved link -- there's no way to prove the barrel is\n // actually forwarding this exact contract without following the\n // re-export chain, which is out of scope (ADR 0010).\n for (const scan of scanResults) {\n for (const [, binding] of scan.imports) {\n const resolvedFile = await resolveImportSpecifier(scan.file, binding.specifier, context)\n // Same equivalence as pass 1's identical guard above: `resolvedFile`\n // undefined makes `scanByFile.get(resolvedFile)` below return\n // `undefined` (its keys are always real scanned file paths, never\n // \"undefined\"), which the very next `!targetScan?.hasWildcardReExport`\n // guard already absorbs. Hand-verified: mutating this and running the\n // real suite passes unchanged.\n // Stryker disable next-line ConditionalExpression\n if (!resolvedFile) continue\n const targetScan = scanByFile.get(resolvedFile)\n if (!targetScan?.hasWildcardReExport) continue\n\n for (const building of byIdentity.values()) {\n if (building.imported) continue\n if (building.exportName !== binding.importedName) continue\n building.ambiguousBarrelFiles.add(scan.file)\n }\n }\n }\n\n const finalContracts = [...byIdentity.values()].map((building) =>\n finalizeContract(building, context.root, dynamicAccessAcknowledgments),\n )\n\n return { contracts: finalContracts, warnings, scannedSurfaces }\n}\n\ninterface AbandonedOwnershipFinding {\n readonly file: string\n readonly exportName: string\n readonly contractName: string\n}\ninterface UnresolvedConsumerOwnershipFinding extends AbandonedOwnershipFinding {\n readonly reason: string\n}\ninterface UnconsumedOwnedVariableOwnershipFinding extends AbandonedOwnershipFinding {\n readonly key: string\n}\ninterface IndeterminateAccessOwnershipFinding extends AbandonedOwnershipFinding {\n readonly key: string\n readonly reason: string\n /** Every AST-observed dynamic-access site on this contract -- see ADR 0036. */\n readonly dynamicAccessSites: readonly SourcePosition[]\n /** Every AST-observed escape site on this contract -- see {@link EscapeVia} and ADR 0039. */\n readonly escapeSites: readonly EscapeSite[]\n}\n/** A variable that would otherwise be `unconsumedOwned`/`indeterminate`, but has at least one `\"fresh\"` developer-declared `dynamicAccess` assertion -- the \"asserted\" category (ADR 0037). Never silently dropped: the raw `wouldBeStatus` is always shown alongside the assertion, per Design 7's \"never let a claim overwrite an observation\" rule. */\ninterface AssertedOwnershipFinding extends AbandonedOwnershipFinding {\n readonly key: string\n readonly wouldBeStatus: \"unconsumed\" | \"indeterminate\"\n readonly dynamicAccessAssertions: readonly DynamicAccessAssertion[]\n}\n\nexport interface OwnershipFindings {\n readonly abandoned: readonly AbandonedOwnershipFinding[]\n readonly unresolvedConsumers: readonly UnresolvedConsumerOwnershipFinding[]\n readonly unconsumedOwned: readonly UnconsumedOwnedVariableOwnershipFinding[]\n readonly indeterminate: readonly IndeterminateAccessOwnershipFinding[]\n readonly asserted: readonly AssertedOwnershipFinding[]\n}\n\nfunction formatSurfaces(surfaces: readonly ScannedSurface[]): string {\n return surfaces.map((s) => s.label).join(\", \")\n}\n\nfunction formatSites(sites: readonly SourcePosition[]): string {\n return sites.map((s) => `${s.file}:${s.line}:${s.column}`).join(\", \")\n}\n\nfunction formatEscapeSites(sites: readonly EscapeSite[]): string {\n return sites.map((s) => `${s.file}:${s.line}:${s.column} (${s.via})`).join(\", \")\n}\n\n/**\n * Derives ownership findings from the graph. This is where the epistemic\n * rules that matter most live:\n * - A contract never imported anywhere, with no ambiguous barrel path\n * either, is `abandoned` -- a feature's schema outliving the feature.\n * - A contract never *directly* imported, but reachable only through an\n * unresolved barrel re-export, is `unresolvedConsumers` -- never\n * `abandoned`. Claiming \"abandoned\" here would be a false positive with\n * real consequences.\n * - A variable with no member access anywhere, on a contract with no\n * dynamic access anywhere, is `unconsumedOwned` -- \"no consumer found in\n * this repository,\" not \"provably dead.\" The scanned surfaces are named\n * explicitly in the reason, per ADR 0036, so the claim is exactly as\n * strong as what was actually searched.\n * - A variable with no member access, but dynamic access observed\n * *somewhere* on that contract, is `indeterminate` -- never\n * `unconsumedOwned`. Uncertainty is never promoted to certainty in either\n * direction. Every candidate dynamic-access site is cited by name.\n * - A variable with at least one `\"fresh\"` {@link DynamicAccessAssertion}\n * (ADR 0037) gets neither `unconsumedOwned` nor `indeterminate`, regardless\n * of `status` -- a developer has re-acknowledged the access exists. The\n * Dependency Model itself still keeps `status` and the assertion side by\n * side, unedited; only *this* finding-suppression decision reads them\n * together.\n */\nexport function deriveOwnershipFindings(graph: DependencyGraph): OwnershipFindings {\n const abandoned: AbandonedOwnershipFinding[] = []\n const unresolvedConsumers: UnresolvedConsumerOwnershipFinding[] = []\n const unconsumedOwned: UnconsumedOwnedVariableOwnershipFinding[] = []\n const indeterminate: IndeterminateAccessOwnershipFinding[] = []\n const asserted: AssertedOwnershipFinding[] = []\n const surfaces = formatSurfaces(graph.scannedSurfaces)\n const hasFreshAssertion = (info: VariableAccessInfo): boolean =>\n info.dynamicAccessAssertions.some((a) => a.acknowledgment === \"fresh\")\n\n for (const contract of graph.contracts) {\n const identity = {\n file: contract.file,\n exportName: contract.exportName,\n contractName: contract.contractName,\n }\n\n if (!contract.imported) {\n if (contract.ambiguousBarrelFiles.length > 0) {\n unresolvedConsumers.push({\n ...identity,\n reason:\n `Not directly imported anywhere, but ${contract.ambiguousBarrelFiles.length} file(s) import ` +\n `\"${contract.exportName}\" through a specifier that resolves to a file containing an unresolved ` +\n `\"export * from\" re-export -- cannot determine whether this contract is forwarded by it. ` +\n `Files: ${contract.ambiguousBarrelFiles.join(\", \")}.`,\n })\n } else {\n abandoned.push(identity)\n }\n continue\n }\n\n for (const [key, info] of contract.variables) {\n if (hasFreshAssertion(info)) {\n if (info.status === \"unconsumed\" || info.status === \"indeterminate\") {\n asserted.push({\n ...identity,\n key,\n wouldBeStatus: info.status,\n dynamicAccessAssertions: info.dynamicAccessAssertions,\n })\n }\n continue\n }\n if (info.status === \"unconsumed\") {\n unconsumedOwned.push({ ...identity, key })\n } else if (info.status === \"indeterminate\") {\n const reason =\n info.evidence === \"dynamic-access\"\n ? `Dynamic (computed) property access was observed on \"${contract.exportName}\" -- cannot ` +\n `determine whether \"${key}\" is read. Searched: ${surfaces}. Dynamic access observed at: ` +\n `${formatSites(contract.dynamicAccessSites)}.`\n : `Contract \"${contract.exportName}\" is used in a way this scanner's local dataflow ` +\n `analysis cannot follow (a rest binding, nested destructuring, a computed key, an ` +\n `ambiguous alias, or the contract passed/referenced directly) -- cannot determine ` +\n `whether \"${key}\" is read. Searched: ${surfaces}. Escaped at: ` +\n `${formatEscapeSites(contract.escapeSites)}.`\n indeterminate.push({\n ...identity,\n key,\n reason,\n dynamicAccessSites: contract.dynamicAccessSites,\n escapeSites: contract.escapeSites,\n })\n }\n }\n }\n\n return { abandoned, unresolvedConsumers, unconsumedOwned, indeterminate, asserted }\n}\n","import { displayPath } from \"./display-path.js\"\nimport { byContractIdentity } from \"./sort-by-identity.js\"\nimport type { ContractRef } from \"./evidence-reference.js\"\nimport { buildDependencyGraph } from \"./dependency-graph.js\"\nimport type { ScannedSurface, VariableAccessStatus } from \"./dependency-graph.js\"\nimport type { DiscoveredContract } from \"./link.js\"\nimport type { ParseWarning } from \"./parse.js\"\nimport type { ImportResolutionContext } from \"./resolution/resolve-import.js\"\nimport type { DynamicAccessAssertion, SourcePosition } from \"./source-position.js\"\n\n/**\n * The second of env-cap's seven canonical fact models (ADR 0024) -- a\n * versioned, JSON-serializable projection of the dependency-ownership\n * engine's graph. See ADR 0027 and ADR 0036.\n *\n * @remarks\n * `dependency-graph.ts`'s scanning/graph-building internals stay Private,\n * unchanged, per ADR 0010 -- this is a fact-shaped *result* built on top of\n * them, not a relaxation of that boundary. Graph-format rendering (DOT,\n * Mermaid, a `{nodes, edges}` JSON export) is deliberately not here --\n * that's presentation over this model's data, not the model itself.\n */\n\n/** Bump only when a reader could misinterpret the new shape -- same discipline every other canonical model's `schemaVersion` follows. */\nexport const DEPENDENCY_MODEL_SCHEMA_VERSION = 2\n\n/**\n * One variable's access status within a contract, plus every position it was found\n * member-accessed at, aggregated across every consuming file.\n *\n * @see {@link ContractModelVariable} -- this same declared variable's canonical starting point.\n */\nexport interface DependencyModelVariable {\n readonly key: string\n readonly status: VariableAccessStatus\n /** Empty unless `status === \"used\"`. Previously discarded before reaching any public type -- see ADR 0027 (line only) and ADR 0036 (full position, file included per entry). */\n readonly positions: readonly SourcePosition[]\n /** Every developer-declared `dynamicAccess` citation's current freshness for this variable -- a wholly separate, independent fact from `status` above, never folded into it. Empty when no citation was declared, or when no manifest snapshot baseline was available to check against (the manifest pass wasn't also requested). See ADR 0037. */\n readonly dynamicAccessAssertions: readonly DynamicAccessAssertion[]\n}\n\nexport interface DependencyModelContract {\n /** Root-relative, POSIX-separated -- matches `ContractModelContract.file`. */\n readonly file: string\n readonly exportName: string\n readonly contractName: string\n readonly imported: boolean\n readonly hasDynamicAccess: boolean\n readonly variables: readonly DependencyModelVariable[]\n /** Every file coupled to this contract -- contract-level \"who depends on this,\" not proof any specific variable was read. */\n readonly consumingFiles: readonly string[]\n /** Files whose import of this contract's name couldn't be verified because it resolved through a file containing an unresolved wildcard re-export. */\n readonly ambiguousBarrelFiles: readonly string[]\n /** Every computed (dynamic) property-access site observed anywhere on this contract -- see ADR 0036. */\n readonly dynamicAccessSites: readonly SourcePosition[]\n}\n\n/** One contract, as referenced from the inverse (`consumers`) index -- see {@link ContractRef} for why no `contractName` is carried here. */\nexport type DependencyModelContractRef = ContractRef\n\n/** One consuming file, and every contract it depends on -- the inverse of `DependencyModelContract.consumingFiles`. */\nexport interface DependencyModelConsumer {\n /** Root-relative, POSIX-separated. */\n readonly file: string\n readonly contracts: readonly DependencyModelContractRef[]\n}\n\nexport interface DependencyModel {\n readonly schemaVersion: typeof DEPENDENCY_MODEL_SCHEMA_VERSION\n readonly contracts: readonly DependencyModelContract[]\n /** Inverse of `contracts[].consumingFiles` -- one entry per file that consumes at least one contract, listing which contracts it reads. */\n readonly consumers: readonly DependencyModelConsumer[]\n readonly warnings: readonly ParseWarning[]\n /** Every surface actually scanned for usage -- see ADR 0036. Always has at least one entry (the application root). */\n readonly scannedSurfaces: readonly ScannedSurface[]\n}\n\nfunction relativizePosition(root: string, position: SourcePosition): SourcePosition {\n return { ...position, file: displayPath(root, position.file) }\n}\n\n/**\n * Runs the dependency-ownership engine (`buildDependencyGraph()`, Private)\n * and projects its result into the Dependency Model's versioned,\n * JSON-serializable shape -- including the inverse file-\\>contracts index\n * neither `dependency-graph.ts` nor `usage-report.ts` exposes today.\n *\n * @param scannedSurfaces - See `buildDependencyGraph()`'s own parameter of\n * the same name -- passed straight through to the published model.\n * @param dynamicAccessAcknowledgments - See `buildDependencyGraph()`'s own\n * parameter of the same name (ADR 0037) -- passed straight through.\n */\nexport async function buildDependencyModel(\n contracts: readonly DiscoveredContract[],\n scanFiles: readonly string[],\n readFile: (filePath: string) => Promise<string>,\n context: ImportResolutionContext,\n root: string,\n scannedSurfaces?: readonly ScannedSurface[],\n dynamicAccessAcknowledgments?: ReadonlyMap<string, readonly DynamicAccessAssertion[]>,\n): Promise<DependencyModel> {\n const graph = await buildDependencyGraph(\n contracts,\n scanFiles,\n readFile,\n context,\n scannedSurfaces,\n dynamicAccessAcknowledgments,\n )\n\n const modelContracts: DependencyModelContract[] = graph.contracts.map((contract) => ({\n file: displayPath(root, contract.file),\n exportName: contract.exportName,\n contractName: contract.contractName,\n imported: contract.imported,\n hasDynamicAccess: contract.hasDynamicAccess,\n variables: [...contract.variables.entries()]\n .map(([key, info]) => ({\n key,\n status: info.status,\n positions: info.positions.map((p) => relativizePosition(root, p)),\n dynamicAccessAssertions: info.dynamicAccessAssertions,\n }))\n .sort((a, b) => a.key.localeCompare(b.key)),\n consumingFiles: [...contract.consumingFiles].map((f) => displayPath(root, f)).sort(),\n ambiguousBarrelFiles: [...contract.ambiguousBarrelFiles]\n .map((f) => displayPath(root, f))\n // `.sort()` here is a defensive no-op, not a real gap: dependency-graph.ts's\n // own `ambiguousBarrelFiles` is already `[...building.ambiguousBarrelFiles].sort()`\n // before this projection ever sees it (see that file's own comment).\n // Hand-verified: dropping this `.sort()` and running the real suite\n // passes unchanged.\n // Stryker disable next-line MethodExpression\n .sort(),\n dynamicAccessSites: contract.dynamicAccessSites.map((p) => relativizePosition(root, p)),\n }))\n modelContracts.sort(byContractIdentity)\n\n const byFile = new Map<string, DependencyModelContractRef[]>()\n for (const contract of modelContracts) {\n const ref: DependencyModelContractRef = {\n file: contract.file,\n exportName: contract.exportName,\n }\n for (const consumingFile of contract.consumingFiles) {\n const refs = byFile.get(consumingFile) ?? []\n refs.push(ref)\n byFile.set(consumingFile, refs)\n }\n }\n // No `.sort(byContractIdentity)` on `refs` here -- `modelContracts` (just\n // above) is already sorted by identity before this file's loop ever runs,\n // so each file's `refs` are necessarily appended in that same sorted\n // order already; re-sorting an already-sorted list is a no-op.\n const consumers: DependencyModelConsumer[] = [...byFile.entries()]\n .map(([file, refs]) => ({ file, contracts: refs }))\n .sort((a, b) => a.file.localeCompare(b.file))\n\n return {\n schemaVersion: DEPENDENCY_MODEL_SCHEMA_VERSION,\n contracts: modelContracts,\n consumers,\n warnings: graph.warnings,\n scannedSurfaces: graph.scannedSurfaces,\n }\n}\n","import type { CompatibilityIssue } from \"./compatibility.js\"\n\nfunction formatIssues(header: string, issues: readonly CompatibilityIssue[]): string {\n const blocks = issues.map(\n (issue) =>\n `${issue.variable}\\n${\"-\".repeat(Math.max(issue.variable.length, 3))}\\n[${issue.severity}] ${issue.reason}\\n\\nDeclared in:\\n${issue.files.join(\"\\n\")}`,\n )\n return [header, ...blocks].join(\"\\n\\n\")\n}\n\nfunction countedHeader(\n prefix: string,\n singularNoun: string,\n issues: readonly CompatibilityIssue[],\n): string {\n const noun = issues.length === 1 ? singularNoun : `${singularNoun}s`\n return `${prefix}\\n\\n${issues.length} ${noun} found:`\n}\n\n/**\n * Thrown by {@link generateEnvManifest} on a blocking compatibility/exclusive-group\n * finding, or an output path escaping `root`.\n *\n * @remarks\n * Nothing is written when this throws -- generation fails atomically, same as\n * {@link runtime.validateEnv} fails atomically at runtime.\n *\n * `code` is a stable, Stable-tier discriminant for programmatic handling --\n * prefer it over `.name`/`instanceof` when a message-independent switch is needed.\n */\nexport class EnvManifestGenerationError extends Error {\n /** Stable discriminant for programmatic handling; always `\"ENV_MANIFEST_GENERATION_FAILED\"`. */\n readonly code = \"ENV_MANIFEST_GENERATION_FAILED\"\n /** Every blocking finding, aggregated. */\n readonly issues: readonly CompatibilityIssue[]\n\n constructor(issues: readonly CompatibilityIssue[]) {\n super(\n formatIssues(\n countedHeader(\n \"Environment manifest generation failed.\",\n \"incompatible declaration\",\n issues,\n ),\n issues,\n ),\n )\n this.name = \"EnvManifestGenerationError\"\n this.issues = issues\n Error.captureStackTrace?.(this, EnvManifestGenerationError)\n }\n}\n\n/**\n * Thrown by {@link generateDocumentation} on a blocking undocumented-contract/\n * variable finding (when `onUndocumented: \"throw\"`), or an output path\n * (`location`/`envExample.location`) escaping `root`. Nothing is written\n * when this throws.\n *\n * @remarks\n * `code` is a stable, Stable-tier discriminant for programmatic handling --\n * prefer it over `.name`/`instanceof` when a message-independent switch is needed.\n */\nexport class EnvDocumentationGenerationError extends Error {\n /** Stable discriminant for programmatic handling; always `\"ENV_DOCUMENTATION_GENERATION_FAILED\"`. */\n readonly code = \"ENV_DOCUMENTATION_GENERATION_FAILED\"\n /** Every blocking finding, aggregated. */\n readonly issues: readonly CompatibilityIssue[]\n\n constructor(issues: readonly CompatibilityIssue[]) {\n super(\n formatIssues(\n countedHeader(\n \"Environment documentation generation failed.\",\n \"documentation issue\",\n issues,\n ),\n issues,\n ),\n )\n this.name = \"EnvDocumentationGenerationError\"\n this.issues = issues\n Error.captureStackTrace?.(this, EnvDocumentationGenerationError)\n }\n}\n\n/**\n * Thrown by {@link generateUsageReport} on a blocking abandoned-contract/\n * unconsumed-owned-variable finding (when `onOwnershipIssue: \"throw\"`), or an\n * output path (`report.location`) escaping `root`.\n *\n * @remarks\n * Never thrown for `unresolvedConsumers` or `indeterminate` findings -- both are \"we don't\n * know\" states, and uncertainty is never promoted to a failure.\n *\n * `code` is a stable, Stable-tier discriminant for programmatic handling --\n * prefer it over `.name`/`instanceof` when a message-independent switch is needed.\n */\nexport class EnvUsageAnalysisError extends Error {\n /** Stable discriminant for programmatic handling; always `\"ENV_USAGE_ANALYSIS_FAILED\"`. */\n readonly code = \"ENV_USAGE_ANALYSIS_FAILED\"\n /** Every blocking finding, aggregated. */\n readonly issues: readonly CompatibilityIssue[]\n\n constructor(issues: readonly CompatibilityIssue[]) {\n super(\n formatIssues(\n countedHeader(\"Dependency ownership report generation failed.\", \"ownership issue\", issues),\n issues,\n ),\n )\n this.name = \"EnvUsageAnalysisError\"\n this.issues = issues\n Error.captureStackTrace?.(this, EnvUsageAnalysisError)\n }\n}\n\n/**\n * Thrown by {@link generateEnvArtifacts} when any requested pass (manifest/docs/usage)\n * reports a blocking finding, aggregated across all requested passes into\n * one error.\n *\n * @remarks\n * Nothing from any pass is written when this throws -- see\n * `generate-env-artifacts.ts`'s compute-atomic guarantee (ADR 0011). Write-phase failures\n * (a real I/O error after all computes already passed) are NOT wrapped in\n * this type -- they propagate as whatever `fs.writeFile` itself throws,\n * since by that point some artifacts may already be on disk.\n *\n * `code` is a stable, Stable-tier discriminant for programmatic handling --\n * prefer it over `.name`/`instanceof` when a message-independent switch is needed.\n */\nexport class EnvProjectGenerationError extends Error {\n /** Stable discriminant for programmatic handling; always `\"ENV_PROJECT_GENERATION_FAILED\"`. */\n readonly code = \"ENV_PROJECT_GENERATION_FAILED\"\n /** Every blocking finding, aggregated across all requested passes. */\n readonly issues: readonly CompatibilityIssue[]\n\n constructor(issues: readonly CompatibilityIssue[]) {\n super(\n formatIssues(countedHeader(\"Project generation failed.\", \"blocking issue\", issues), issues),\n )\n this.name = \"EnvProjectGenerationError\"\n this.issues = issues\n Error.captureStackTrace?.(this, EnvProjectGenerationError)\n }\n}\n","import type { CompatibilityIssue } from \"./compatibility.js\"\nimport type { DiscoveredContract } from \"./link.js\"\n\n/**\n * Detects two *active* contracts declaring the same `exclusiveGroup` --\n * e.g. two interchangeable database backends both left enabled at once.\n *\n * @remarks\n * Unlike `detectCompatibilityIssues`, this is never a heuristic warning: an\n * author explicitly declared these contracts mutually exclusive, so any\n * violation is always a hard error, regardless of `onIncompatibility`. See\n * ADR 0009 for why this doesn't follow 0005's warn-by-default policy.\n *\n * Inactive contracts are ignored entirely here (filtered internally, not by\n * the caller) so this stays correct even when called directly via the\n * `/build` export -- an inactive contract can share a group with an active\n * one with no conflict, since it was never wired into anything.\n */\nexport function detectExclusiveGroupIssues(\n contracts: readonly DiscoveredContract[],\n): CompatibilityIssue[] {\n const byGroup = new Map<string, DiscoveredContract[]>()\n\n for (const contract of contracts) {\n if (!contract.active || !contract.exclusiveGroup) continue\n const members = byGroup.get(contract.exclusiveGroup) ?? []\n members.push(contract)\n byGroup.set(contract.exclusiveGroup, members)\n }\n\n const issues: CompatibilityIssue[] = []\n\n for (const [group, members] of [...byGroup.entries()].sort((a, b) => a[0].localeCompare(b[0]))) {\n // Equivalent to `i <= members.length`: whenever `i >= members.length`,\n // the inner loop's own `j = i + 1` starts already past `members.length`\n // too, so its body never runs -- an extra outer iteration at the bound\n // is a genuine no-op for any `members.length`, not just this test's.\n // Stryker disable next-line EqualityOperator\n for (let i = 0; i < members.length; i++) {\n for (let j = i + 1; j < members.length; j++) {\n const a = members[i]\n const b = members[j]\n issues.push({\n severity: \"error\",\n variable: `Exclusive group \"${group}\"`,\n files: [a.file, b.file],\n reason:\n `\"${a.contractName}\" and \"${b.contractName}\" are both active and both declare exclusiveGroup ` +\n `\"${group}\" -- only one active contract per exclusive group is allowed. Set active: false on ` +\n \"whichever one isn't in use.\",\n })\n }\n }\n }\n\n return issues\n}\n","import path from \"node:path\"\nimport { generatedBanner } from \"./generated-banner.js\"\nimport type { DiscoveredContract } from \"./link.js\"\n\n/**\n * Every validation context declared by any variable in an *active* contract\n * in `contracts` (a variable belonging to a contract documented `active:\n * false` never contributes -- same exclusion the `manifest` array itself\n * already applies), sorted and deduplicated. What {@link renderManifest}\n * surfaces as the generated `activeContexts` export. Exported for reuse by\n * anything that needs the same computation (currently just `renderManifest`\n * itself).\n */\nexport function discoverValidationContexts(\n contracts: readonly DiscoveredContract[],\n): readonly string[] {\n const contexts = new Set<string>()\n for (const contract of contracts) {\n if (!contract.active) continue\n for (const variable of contract.variables) {\n if (variable.context !== undefined) contexts.add(variable.context)\n }\n }\n return [...contexts].sort()\n}\n\n/**\n * Renders the deterministic manifest source: sorted imports (aliased on name\n * collision) plus a `contracts` array, in the exact banner format schema\n * authors will recognize as generated. No timestamps, no randomness -- same\n * input files always produce byte-identical output.\n *\n * @remarks\n * When at least one discovered variable declares a `context` (ADR 0022),\n * this also emits `activeContexts` -- every validation context found across\n * `contracts`, as a plain array named to match {@link runtime.validateEnvOptions}'s\n * own `activeContexts` field -- so application code can import it alongside\n * `manifest` and pass it straight through: `validateEnv({ manifest, values, activeContexts })`.\n * It's every context this manifest has, meant as a starting point to narrow\n * per process/deployment, not a pre-scoped default -- see the README's\n * \"Validation contexts\" section. Omitted entirely (not even an empty array)\n * when no variable declares a `context` at all, so generated output for\n * projects that don't use this feature is untouched.\n */\nexport function renderManifest(\n contracts: readonly DiscoveredContract[],\n outputFile: string,\n): string {\n const sorted = [...contracts].sort((a, b) => a.file.localeCompare(b.file))\n const outputDir = path.dirname(outputFile)\n const usedNames = new Set<string>()\n\n const importLines: string[] = []\n const referenceNames: string[] = []\n\n for (const contract of sorted) {\n let localName = contract.exportName\n let suffix = 1\n while (usedNames.has(localName)) {\n localName = `${contract.exportName}_${suffix}`\n suffix += 1\n }\n usedNames.add(localName)\n referenceNames.push(localName)\n\n // Package-resolved contracts (ADR 0014) import by bare package name --\n // the resolved file only exists for static analysis and typically lives\n // inside node_modules, which most consumer build configs don't compile\n // and isn't a valid runtime import path anyway. Everything else keeps\n // the existing relative-path behavior unchanged.\n let specifier: string\n if (contract.packageOrigin) {\n specifier = contract.packageOrigin.packageName\n } else {\n const withoutExt = contract.file.replace(/\\.tsx?$/, \"\")\n specifier = path.relative(outputDir, withoutExt).split(path.sep).join(\"/\")\n if (!specifier.startsWith(\".\")) specifier = `./${specifier}`\n }\n\n const binding =\n localName === contract.exportName\n ? contract.exportName\n : `${contract.exportName} as ${localName}`\n importLines.push(`import { ${binding} } from \"${specifier}\";`)\n }\n\n const activeContexts = discoverValidationContexts(contracts)\n const activeContextsLines =\n activeContexts.length > 0\n ? [\n \"// all currently active validation contexts\",\n `export const activeContexts = [${activeContexts.map((c) => JSON.stringify(c)).join(\", \")}];`,\n \"\",\n ]\n : []\n\n const lines = [\n generatedBanner(\"ts\"),\n \"\",\n ...importLines,\n \"\",\n ...activeContextsLines,\n \"export const manifest = [\",\n ...referenceNames.map((name) => ` ${name},`),\n \"];\",\n \"\",\n ]\n\n return lines.join(\"\\n\")\n}\n","import path from \"node:path\"\nimport { assembleProject } from \"./assemble-project.js\"\nimport type { BuildFileSystem } from \"./types.js\"\nimport { detectCompatibilityIssues, detectDuplicateVariableShapes } from \"./compatibility.js\"\nimport type { CompatibilityIssue } from \"./compatibility.js\"\nimport { EnvManifestGenerationError } from \"./errors.js\"\nimport { detectExclusiveGroupIssues } from \"./exclusive-group.js\"\nimport {\n summarizeContract,\n type DiscoveredContract,\n type DiscoveredContractSummary,\n type LinkResult,\n} from \"./link.js\"\nimport { renderManifest } from \"./manifest.js\"\nimport type { ParseWarning } from \"./parse.js\"\nimport { resolveWithinRoot } from \"./resolution/resolve-within-root.js\"\n\n/** Options for {@link generateEnvManifest}. */\nexport interface GenerateEnvManifestOptions {\n /** The filesystem capability -- `./build` never imports `node:fs` (ADR 0040). */\n fs: BuildFileSystem\n /** Directory glob patterns are resolved against. Defaults to `process.cwd()`. */\n root?: string | undefined\n /** Output path for the generated manifest, relative to `root` (e.g. \"src/generated/env.manifest.ts\"). */\n location: string\n /** Glob patterns for schema files. Defaults to `[\"**\\/env.schema.ts\"]`. */\n include?: string[] | undefined\n /** Glob patterns to exclude. Defaults to node_modules/dist/.git. */\n exclude?: string[] | undefined\n /**\n * **Experimental** (see VERSIONING.md) -- explicit allowlist of installed\n * package names whose declared `\"envCap\": { \"schema\": \"<path>\" }` entry\n * point should also be discovered, so a contract that ships as its own\n * separately-published package (no monorepo required) can be included in\n * the manifest. Opt-in only: a package is never considered unless its\n * exact name appears here. See ADR 0014.\n */\n packages?: readonly string[] | undefined\n /**\n * **Experimental** (see VERSIONING.md) -- path to a tsconfig.json (relative to `root`)\n * whose `compilerOptions.paths`/`baseUrl` resolve aliased import specifiers (e.g.\n * `\"@/lib/env.schema.js\"`) encountered during static analysis, so a contract or consumer\n * reached only through an alias isn't misreported as abandoned/unresolved. Defaults to\n * `\"tsconfig.json\"` at `root` -- on automatically, no opt-in required, since (unlike\n * `packages`) this never crosses a trust/versioning boundary: every resolved file is\n * already local, already-trusted project source. Pass `false` to disable entirely. See\n * ADR 0023.\n */\n tsconfig?: string | false | undefined\n /**\n * \"warn\" (default): only provable incompatibilities (conflicting explicit processor\n * return type annotations) block generation; everything else is reported as a warning.\n * \"throw\": warnings are escalated to hard errors too, for stricter CI gates.\n */\n onIncompatibility?: \"warn\" | \"throw\" | undefined\n}\n\n/** The result of a completed {@link generateEnvManifest} run. */\nexport interface GenerateEnvManifestResult {\n /** Absolute path the manifest file was written to. */\n readonly outputPath: string\n /** Root-relative summary of every discovered contract, active or not. */\n readonly contracts: readonly DiscoveredContractSummary[]\n /** Non-blocking compatibility/exclusive-group issues (severity `\"warning\"`). */\n readonly warnings: readonly CompatibilityIssue[]\n /** Parse-time warnings collected across every analyzed file (including allow-listed package resolution). */\n readonly parseWarnings: readonly ParseWarning[]\n}\n\n/**\n * Default value for {@link GenerateEnvManifestOptions.include}. A function\n * (not a bare module-level `const`) so every call gets its own fresh array\n * -- a shared literal used from many files (`evidence-cache.ts`,\n * `generate-documentation.ts`, `generate-evidence.ts`,\n * `generate-env-artifacts.ts`, `generate-usage.ts`) is a covered-static\n * mutant magnet under Stryker's `coverageAnalysis: perTest` +\n * `ignoreStatic: true` (a mutant on module-load code that's still referenced\n * by a test is run anyway and falsely reported \"Survived\") -- see this\n * drive's memory for the fully-documented limitation.\n */\nexport function defaultInclude(): string[] {\n return [\"**/env.schema.ts\"]\n}\n/** Default value for {@link GenerateEnvManifestOptions.exclude}. Same reasoning as {@link defaultInclude}. */\nexport function defaultExclude(): string[] {\n return [\n // `discoverSchemaFiles()`'s own walk (`discover.ts`) hardcodes skipping\n // a directory literally named \"node_modules\" or \".git\" via its own\n // `isAlwaysSkippedDirName()` check, regardless of `exclude` -- it never\n // even descends into either to test a glob pattern against it. These\n // two entries are provably redundant (kept for readers/tooling that\n // inspect `exclude` directly, and as defense if that hardcoding ever\n // changes) -- hand-verified: emptying both and running the full\n // `vitest run` leaves all 1243 tests passing.\n // Stryker disable next-line StringLiteral\n \"**/node_modules/**\",\n \"**/dist/**\",\n // Stryker disable next-line StringLiteral\n \"**/.git/**\",\n ]\n}\n\nexport interface ManifestComputation {\n readonly activeContracts: readonly DiscoveredContract[]\n readonly contractSummaries: readonly DiscoveredContractSummary[]\n readonly warnings: readonly CompatibilityIssue[]\n readonly blocking: readonly CompatibilityIssue[]\n}\n\n/**\n * Pure -- no I/O. Runs compatibility (0005) and exclusive-group (0009,\n * always-error, never gated by `onIncompatibility`) checks against an\n * already-discovered contract graph and applies the `onIncompatibility` gate.\n * Shared by the standalone `generateEnvManifest()` (which discovers its own\n * graph) and `generate-env-artifacts.ts` (which discovers once and reuses it across\n * manifest/docs/usage) -- see ADR 0011.\n */\nexport function computeManifest(\n root: string,\n linkResult: LinkResult,\n onIncompatibility: \"warn\" | \"throw\",\n): ManifestComputation {\n const { contracts } = linkResult\n const activeContracts = contracts.filter((contract) => contract.active)\n\n const compatibilityIssues = [\n ...detectCompatibilityIssues(activeContracts),\n ...detectExclusiveGroupIssues(activeContracts),\n ...detectDuplicateVariableShapes(activeContracts),\n ]\n const compatibilityErrors = compatibilityIssues.filter((issue) => issue.severity === \"error\")\n // `--strict` (`onIncompatibility: \"throw\"`) escalates warnings only.\n // `\"info\"` issues are observations, never gaps, and are excluded from\n // `blocking` under every setting -- see `detectDuplicateVariableShapes()`.\n const blocking =\n onIncompatibility === \"throw\"\n ? compatibilityIssues.filter((issue) => issue.severity !== \"info\")\n : compatibilityErrors\n\n return {\n activeContracts,\n contractSummaries: contracts.map((contract) => summarizeContract(contract, root)),\n warnings: compatibilityIssues.filter((issue) => issue.severity === \"warning\"),\n blocking,\n }\n}\n\n/** Writes the manifest file. Callers must have already confirmed `outputPath` is safe and nothing is blocking. */\nexport async function writeManifest(\n outputPath: string,\n activeContracts: readonly DiscoveredContract[],\n fs: BuildFileSystem,\n): Promise<void> {\n const manifestSource = renderManifest(activeContracts, outputPath)\n await fs.mkdir(path.dirname(outputPath), { recursive: true })\n // `manifestSource` is always a plain string -- fs.writeFile defaults a\n // string write to utf8 regardless of the encoding arg, so \"utf8\" vs \"\" is\n // unobservable. Same established equivalence as generate-usage.ts's own\n // `writeUsageReport()`/evidence-cache.ts/env-example.ts's writes.\n // Stryker disable next-line StringLiteral\n await fs.writeFile(outputPath, manifestSource, \"utf8\")\n}\n\n/**\n * Build-time only. Discovers `env.schema.ts` files, statically analyzes them\n * (never executes them) to link `createEnv()`/`documentEnv()` calls, checks\n * for provable incompatibilities between duplicate variable declarations,\n * and writes a deterministic manifest file that re-exports every discovered\n * active contract.\n *\n * @remarks\n * Never call this at application startup or import it from\n * runtime code -- wire it into an npm script, a bundler plugin, or a CI\n * step instead.\n *\n * @throws {EnvManifestGenerationError} If `location` escapes `root`, or if a blocking compatibility/exclusive-group issue is found.\n */\nexport async function generateEnvManifest(\n options: GenerateEnvManifestOptions,\n): Promise<GenerateEnvManifestResult> {\n const root = path.resolve(options.root ?? process.cwd())\n const include = options.include ?? defaultInclude()\n const exclude = options.exclude ?? defaultExclude()\n // `assembleProject()` threads this straight into\n // `resolveAllowlistedPackages()`, whose very first line is\n // `[...new Set(packages)]` -- `new Set(undefined)` is spec-defined as an\n // EMPTY set, identical to `new Set([])`, so `undefined` and `[]` are\n // observably identical all the way down this call chain: `&&` (giving\n // `undefined` when `options.packages` is omitted) behaves exactly like\n // `??` (giving `[]`). Hand-verified: mutating to `&&` and running the\n // full `vitest run` leaves all 1241 other tests passing (only the\n // unrelated tsc-backed json-schema test fails, a pure type-narrowing\n // regression -- `AssembleProjectOptions.packages` isn't typed optional).\n // Stryker disable next-line LogicalOperator\n const packages = options.packages ?? []\n // `onIncompatibility` is only ever compared via `=== \"throw\"` inside\n // `computeManifest()` -- any non-\"throw\" string (including \"\" here)\n // behaves identically to \"warn\". The `??` itself is real and already\n // tested (an explicit \"throw\" must survive, not fall back) -- only the\n // fallback's own literal text is unobservable. Hand-verified: replacing\n // it with \"\" and running the full `vitest run` leaves all 1240 tests\n // passing (only the unrelated tsc-backed json-schema test fails).\n // Stryker disable next-line StringLiteral\n const onIncompatibility = options.onIncompatibility ?? \"warn\"\n\n // Fail fast, before any discovery/parsing work and before any file is\n // written -- generation is atomic, same as a compatibility-issue failure.\n const locationResult = resolveWithinRoot(\n root,\n options.location,\n \"location\",\n \"generateEnvManifest\",\n )\n if (!locationResult.ok) throw new EnvManifestGenerationError([locationResult.issue])\n const outputPath = locationResult.resolved\n\n const { linkResult, packageWarnings, tsconfigWarnings } = await assembleProject({\n fs: options.fs,\n root,\n include,\n exclude,\n packages,\n tsconfig: options.tsconfig,\n })\n\n const computed = computeManifest(root, linkResult, onIncompatibility)\n if (computed.blocking.length > 0) throw new EnvManifestGenerationError(computed.blocking)\n\n await writeManifest(outputPath, computed.activeContracts, options.fs)\n\n return {\n outputPath,\n contracts: computed.contractSummaries,\n warnings: computed.warnings,\n parseWarnings: [...packageWarnings, ...tsconfigWarnings, ...linkResult.warnings],\n }\n}\n","import type { ScannedSurface } from \"./dependency-graph.js\"\nimport type { DynamicAccessCitationProblem } from \"./citation-verification.js\"\nimport { evidenceDisclaimer, evidenceProjectionNote, generatedBanner } from \"./generated-banner.js\"\nimport type { ParseWarning } from \"./parse.js\"\nimport type { DynamicAccessAssertion, SourcePosition } from \"./source-position.js\"\n\n/** One contract's dependency-ownership summary: who owns it, and who depends on it. */\nexport interface OwnershipDependencyEntry {\n /** Resolved display name (see {@link DiscoveredContract.contractName}). */\n readonly contractName: string\n /** Root-relative path of the file declaring the contract. */\n readonly file: string\n /** Contract-level default owner, if set. */\n readonly owner: string | undefined\n /** Number of variables declared in this contract's schema. */\n readonly variableCount: number\n /** Files coupled to this contract (imported it, referenced it, or read a\n * member from it) -- contract-level \"who depends on this,\" NOT proof any\n * specific variable was read. Blast radius if this contract changes is\n * `consumers.length`, computed by callers/renderers on demand rather than\n * stored redundantly here. */\n readonly consumers: readonly string[]\n}\n\n/** A contract never imported anywhere in the scanned repository. */\nexport interface AbandonedContractFinding {\n /** Resolved display name (see {@link DiscoveredContract.contractName}). */\n readonly contractName: string\n /** Root-relative path of the file declaring the contract. */\n readonly file: string\n /** Contract-level default owner, if set. */\n readonly owner: string | undefined\n}\n/** A contract reachable only through an unresolved barrel re-export -- can't be proven abandoned or consumed. */\nexport interface UnresolvedConsumerFinding {\n /** Resolved display name (see {@link DiscoveredContract.contractName}). */\n readonly contractName: string\n /** Root-relative path of the file declaring the contract. */\n readonly file: string\n /** Human-readable explanation of why usage couldn't be resolved. */\n readonly reason: string\n}\n/** An owned variable with no consumer found in the scanned repository. */\nexport interface UnconsumedOwnedVariableFinding {\n /** Resolved display name (see {@link DiscoveredContract.contractName}). */\n readonly contractName: string\n /** The owning contract's default owner, if set. */\n readonly owner: string | undefined\n /** The unconsumed environment variable name. */\n readonly key: string\n /**\n * Every `dynamicAccess` citation for this variable that's currently\n * `\"stale\"` or `\"missing\"` (empty when none exist -- see ADR 0037).\n * Empty is the *strongest* \"looks genuinely unused\" signal: no developer\n * has ever claimed otherwise. A non-empty list means someone specifically\n * claimed dynamic access here once and that claim can no longer be\n * verified -- worth a human check before deleting, not a stronger reason\n * to trust \"unconsumed.\" Exposed as the raw citations, not a collapsed\n * `high`/`low` label, matching this codebase's \"show the receipt\" pattern\n * (ADR 0036/0037) -- a reader can judge confidence from the actual\n * evidence rather than trusting a derived summary. See ADR 0038.\n */\n readonly staleOrMissingCitations: readonly DynamicAccessCitationProblem[]\n}\n/** A variable accessed only via dynamic (computed) property access -- usage cannot be determined statically. */\nexport interface IndeterminateOwnershipFinding {\n /** Resolved display name (see {@link DiscoveredContract.contractName}). */\n readonly contractName: string\n /** The environment variable name. */\n readonly key: string\n /** Human-readable explanation of why usage couldn't be determined. */\n readonly reason: string\n /** Every AST-observed dynamic-access site backing `reason`, structured -- see ADR 0036. */\n readonly dynamicAccessSites: readonly SourcePosition[]\n /** See {@link UnconsumedOwnedVariableFinding.staleOrMissingCitations}. */\n readonly staleOrMissingCitations: readonly DynamicAccessCitationProblem[]\n}\n/** A variable that would otherwise be reported `unconsumedOwnedVariables`/`indeterminate`, but has at least one `\"fresh\"` developer-declared `dynamicAccess` citation -- the raw static status is always shown alongside the assertion, never replaced by it. See ADR 0037. */\nexport interface AssertedDynamicAccessFinding {\n /** Resolved display name (see {@link DiscoveredContract.contractName}). */\n readonly contractName: string\n /** The environment variable name. */\n readonly key: string\n /** What this variable's status would be without the fresh assertion. */\n readonly wouldBeStatus: \"unconsumed\" | \"indeterminate\"\n /** Every citation covering this variable, each with its own current freshness. */\n readonly dynamicAccessAssertions: readonly DynamicAccessAssertion[]\n}\n\n/** Everything {@link renderUsageReport} needs to render the Dependency &\n * Ownership Report -- deliberately independent of (not derived from)\n * `GenerateUsageReportResult` in `generate-usage.js`, the same way\n * `RenderDocsOptions` in `docs.ts` doesn't derive from\n * `GenerateDocumentationResult`. `generate-usage.ts` composes its own\n * public result type from these building blocks instead, keeping this\n * renderer module importable without its orchestrator. */\nexport interface RenderUsageReportOptions {\n /** Every contract's ownership/dependency summary. */\n readonly dependencyOwnership: readonly OwnershipDependencyEntry[]\n /** Contracts never imported anywhere in the scanned repository. */\n readonly abandonedContracts: readonly AbandonedContractFinding[]\n /** Advisory only, never gates `onOwnershipIssue` -- a contract only\n * reaches here when an ambiguous barrel re-export makes \"abandoned\" or\n * \"consumed\" both unprovable. */\n readonly unresolvedConsumers: readonly UnresolvedConsumerFinding[]\n /** Owned variables with no consumer found in the scanned repository. */\n readonly unconsumedOwnedVariables: readonly UnconsumedOwnedVariableFinding[]\n /** Variables accessed only via dynamic (computed) property access. */\n readonly indeterminate: readonly IndeterminateOwnershipFinding[]\n /** Variables a developer has re-acknowledged via `dynamicAccess`, freshly -- see ADR 0037. */\n readonly asserted: readonly AssertedDynamicAccessFinding[]\n /** Schema-discovery parse warnings plus, since ADR 0014, any `packages`\n * resolution failures -- surfaced here too (not just from\n * `generateEnvManifest`/`generateDocumentation`) so a team relying only\n * on `--ownership` output still learns when a cross-package contract\n * failed to resolve. */\n readonly parseWarnings: readonly ParseWarning[]\n /** Every surface actually scanned for usage -- see ADR 0036. Named explicitly next to `unconsumedOwnedVariables` so \"no consumer found\" is never read as a stronger claim than what was actually searched. */\n readonly scannedSurfaces: readonly ScannedSurface[]\n}\n\nfunction sortedByContractName<T extends { contractName: string }>(entries: readonly T[]): T[] {\n return [...entries].sort((a, b) => a.contractName.localeCompare(b.contractName))\n}\n\nfunction renderDependencyOwnershipTable(entries: readonly OwnershipDependencyEntry[]): string[] {\n if (entries.length === 0) return []\n const lines = [\n \"## Dependency ownership\",\n \"\",\n \"Who owns each contract, who depends on it, and the blast radius if it changes.\",\n \"\",\n \"| Contract | Owner | Variables | Consumers | Blast radius |\",\n \"|---|---|---|---|---|\",\n ]\n for (const entry of sortedByContractName(entries)) {\n const consumers = entry.consumers.length > 0 ? entry.consumers.join(\", \") : \"--\"\n lines.push(\n `| ${entry.contractName} (\\`${entry.file}\\`) | ${entry.owner ?? \"--\"} | ${entry.variableCount} | ${consumers} | ${entry.consumers.length} |`,\n )\n }\n lines.push(\"\")\n return lines\n}\n\nfunction renderAbandoned(findings: readonly AbandonedContractFinding[]): string[] {\n if (findings.length === 0) return []\n const lines = [\n \"## Abandoned ownership\",\n \"\",\n \"Contracts never imported anywhere in the scanned repository -- a feature's schema outliving the feature.\",\n \"\",\n \"| Contract | Owner | File |\",\n \"|---|---|---|\",\n ]\n for (const f of sortedByContractName(findings))\n lines.push(`| ${f.contractName} | ${f.owner ?? \"--\"} | \\`${f.file}\\` |`)\n lines.push(\"\")\n return lines\n}\n\nfunction renderUnresolvedConsumers(findings: readonly UnresolvedConsumerFinding[]): string[] {\n if (findings.length === 0) return []\n const lines = [\n \"## Unresolved consumers (barrel re-exports)\",\n \"\",\n \"Contracts reachable only through an unresolved `export * from` barrel re-export -- cannot be proven abandoned or consumed. Advisory only; never fails a build.\",\n \"\",\n ]\n for (const f of sortedByContractName(findings))\n lines.push(`- **${f.contractName}** (\\`${f.file}\\`): ${f.reason}`)\n lines.push(\"\")\n return lines\n}\n\n/** `\"none\"` if `citations` is empty (rendered `--`), else the citations themselves -- so a reader sees the actual stale/missing claim, not a collapsed confidence label. */\nfunction formatStaleOrMissingCitations(citations: readonly DynamicAccessCitationProblem[]): string {\n if (citations.length === 0) return \"--\"\n return citations\n .map((c) => `${c.position.file}:${c.position.line}:${c.position.column} (${c.acknowledgment})`)\n .join(\", \")\n}\n\nfunction renderUnconsumedOwned(\n findings: readonly UnconsumedOwnedVariableFinding[],\n scannedSurfaces: readonly ScannedSurface[],\n): string[] {\n if (findings.length === 0) return []\n const surfaces = scannedSurfaces.map((s) => s.label).join(\", \")\n const lines = [\n \"## Unconsumed owned dependencies\",\n \"\",\n \"Variables no consumer reads within the scanned surfaces below. Not proof of dead code. \" +\n \"Common reasons a real consumer wouldn't show up here: it's read by a separate, \" +\n \"out-of-repo service or webhook handler; it's consumed by non-TypeScript code (a shell \" +\n \"script, a Dockerfile, a Terraform/Kubernetes manifest); or it's read from an allow-listed \" +\n \"package whose directory wasn't included in this project's own `packages` configuration \" +\n \"(ADR 0014).\",\n \"\",\n `Searched: ${surfaces}.`,\n \"\",\n 'A blank Stale/missing citations cell is the strongest \"looks genuinely unused\" signal -- no developer has ever claimed otherwise. A non-blank cell means someone specifically claimed dynamic access here via `dynamicAccess`, and that claim can no longer be verified (ADR 0037) -- check with them before deleting.',\n \"\",\n \"| Variable | Contract | Owner | Stale/missing citations |\",\n \"|---|---|---|---|\",\n ]\n for (const f of sortedByContractName(findings))\n lines.push(\n `| \\`${f.key}\\` | ${f.contractName} | ${f.owner ?? \"--\"} | ${formatStaleOrMissingCitations(f.staleOrMissingCitations)} |`,\n )\n lines.push(\"\")\n return lines\n}\n\nfunction renderIndeterminate(findings: readonly IndeterminateOwnershipFinding[]): string[] {\n if (findings.length === 0) return []\n const lines = [\n \"## Indeterminate (dynamic access)\",\n \"\",\n \"Dynamic (computed) property access was observed -- usage cannot be determined statically. Never guessed at.\",\n \"\",\n \"| Variable | Contract | Reason | Stale/missing citations |\",\n \"|---|---|---|---|\",\n ]\n for (const f of sortedByContractName(findings))\n lines.push(\n `| \\`${f.key}\\` | ${f.contractName} | ${f.reason} | ${formatStaleOrMissingCitations(f.staleOrMissingCitations)} |`,\n )\n lines.push(\"\")\n return lines\n}\n\n/** `\"Per developers, this data point is dynamically accessed at <citations>.\"`, one clause per assertion -- never a bare \"acknowledged\", so the exact cited positions are always legible directly in the rendered report. */\nfunction formatAssertions(assertions: readonly DynamicAccessAssertion[]): string {\n const sites = assertions.map((a) => `${a.file}:${a.line}:${a.column}`).join(\", \")\n return `Per developers, this data point is dynamically accessed at ${sites}.`\n}\n\nfunction renderAsserted(findings: readonly AssertedDynamicAccessFinding[]): string[] {\n if (findings.length === 0) return []\n const lines = [\n \"## Asserted (developer-acknowledged dynamic access)\",\n \"\",\n \"Variables env-cap's own scan would otherwise flag as unconsumed or indeterminate, but a developer has cited exactly where the dynamic access happens via `dynamicAccess`. The raw static status is shown alongside the citation, never hidden behind it -- a citation is a re-acknowledgment, not proof.\",\n \"\",\n \"| Variable | Contract | Static status | Developer assertion |\",\n \"|---|---|---|---|\",\n ]\n for (const f of sortedByContractName(findings))\n lines.push(\n `| \\`${f.key}\\` | ${f.contractName} | ${f.wouldBeStatus} | ${formatAssertions(f.dynamicAccessAssertions)} |`,\n )\n lines.push(\"\")\n return lines\n}\n\nfunction renderParseWarnings(warnings: readonly ParseWarning[]): string[] {\n if (warnings.length === 0) return []\n const lines = [\n \"## Parse warnings\",\n \"\",\n \"Includes any `packages` (ADR 0014) resolution failures, alongside ordinary schema-discovery warnings.\",\n \"\",\n ]\n for (const w of warnings) lines.push(`- **${w.file}**: ${w.message}`)\n lines.push(\"\")\n return lines\n}\n\n/**\n * Renders the Dependency & Ownership Report: who owns each variable, which\n * features consume each contract, and what the blast radius is if it\n * changes -- structured around exactly those three questions, never generic\n * \"dead code\"/\"unused symbol\" language.\n */\nexport function renderUsageReport(computed: RenderUsageReportOptions): string {\n const lines = [\n generatedBanner(\"markdown\"),\n \"\",\n `> ${evidenceDisclaimer()}`,\n \"\",\n `> ${evidenceProjectionNote()}`,\n \"\",\n \"# Dependency & Ownership Report\",\n \"\",\n \"_Produced by `env-cap --ownership`._\",\n \"\",\n \"Which feature owns each variable, which features consume that contract, and what the blast radius is if it changes.\",\n \"\",\n ...renderDependencyOwnershipTable(computed.dependencyOwnership),\n ...renderAbandoned(computed.abandonedContracts),\n ...renderUnresolvedConsumers(computed.unresolvedConsumers),\n ...renderUnconsumedOwned(computed.unconsumedOwnedVariables, computed.scannedSurfaces),\n ...renderIndeterminate(computed.indeterminate),\n ...renderAsserted(computed.asserted),\n ...renderParseWarnings(computed.parseWarnings),\n ]\n // The `\"\\n\\n\"` replacement (or the `/\\n{3,}/g` match itself) is\n // unreachable through the current composition, not a real gap: every\n // `render*()` helper above contributes AT MOST one trailing blank line\n // when non-empty, and exactly zero lines when empty (`[]`, never a lone\n // blank placeholder) -- so no composition of them can ever produce 3+\n // consecutive newlines for this regex to collapse. Kept as a defensive\n // safety net for a FUTURE section helper that might not follow that\n // convention. Hand-verified: replacing the whole match with `\"\"` instead\n // and running the real suite (a maximal fixture exercising every section)\n // passes unchanged either way.\n // Stryker disable next-line StringLiteral\n return lines.join(\"\\n\").replace(/\\n{3,}/g, \"\\n\\n\")\n}\n","import path from \"node:path\"\nimport { assembleProject } from \"./assemble-project.js\"\nimport type { BuildFileSystem } from \"./types.js\"\nimport { buildDependencyGraph, deriveOwnershipFindings } from \"./dependency-graph.js\"\nimport type { DependencyGraph, ScannedSurface } from \"./dependency-graph.js\"\nimport { displayPath } from \"./display-path.js\"\nimport { discoverSchemaFiles } from \"./discover.js\"\nimport { EnvUsageAnalysisError } from \"./errors.js\"\nimport type { DynamicAccessCitationProblem } from \"./citation-verification.js\"\nimport { dynamicAccessVariableIdentity } from \"./citation-verification.js\"\nimport { defaultExclude, defaultInclude } from \"./generate-manifest.js\"\nimport { effectiveOwner } from \"./link.js\"\nimport type { DiscoveredContract } from \"./link.js\"\nimport type { ParseWarning } from \"./parse.js\"\nimport type { ImportResolutionContext } from \"./resolution/resolve-import.js\"\nimport type { PackageOrigin } from \"./resolution/resolve-package-schema.js\"\nimport { resolveWithinRoot } from \"./resolution/resolve-within-root.js\"\nimport type { DynamicAccessAssertion } from \"./source-position.js\"\nimport {\n renderUsageReport,\n type AbandonedContractFinding,\n type AssertedDynamicAccessFinding,\n type IndeterminateOwnershipFinding,\n type OwnershipDependencyEntry,\n type RenderUsageReportOptions,\n type UnconsumedOwnedVariableFinding,\n type UnresolvedConsumerFinding,\n} from \"./usage-report.js\"\n\n/**\n * Computes the full usage-scan surface: the local project root, plus (ADR\n * 0036) each allow-listed `packages` (ADR 0014) name whose schema was\n * successfully resolved -- reusing `origins`' already-resolved\n * `packageDir` (from `resolveAllowlistedPackages()`, already computed by\n * the caller for contract discovery, not re-resolved here) as a bounded\n * scan root, walked with the exact same `discoverSchemaFiles()` +\n * `SCAN_INCLUDE`/`defaultExclude()` policy the local root already uses --\n * never a naive, unbounded walk of the package's whole directory. Shared by\n * `generateUsageReport()` and `generateEvidenceModel()` so both agree on\n * exactly the same scanned surface.\n */\nexport async function computeScanSurface(\n root: string,\n exclude: readonly string[],\n origins: ReadonlyMap<string, PackageOrigin>,\n fs: BuildFileSystem,\n): Promise<{ scanFiles: string[]; scannedSurfaces: ScannedSurface[] }> {\n // Deliberately broader than schema discovery -- usage can occur in any\n // source file, not just `env.schema.ts` files. Not configurable (see ADR\n // 0010's \"convention over configuration\").\n const localScanFiles = await discoverSchemaFiles({\n fs,\n root,\n include: [\"**/*.ts\", \"**/*.tsx\"],\n exclude,\n })\n const scannedSurfaces: ScannedSurface[] = [{ label: \"application\", root: \".\" }]\n const scanFiles = [...localScanFiles]\n\n const seenPackageDirs = new Set<string>()\n for (const origin of origins.values()) {\n if (seenPackageDirs.has(origin.packageDir)) continue // multiple resolved files can share one packageDir; scan it once\n seenPackageDirs.add(origin.packageDir)\n const packageScanFiles = await discoverSchemaFiles({\n fs,\n root: origin.packageDir,\n include: [\"**/*.ts\", \"**/*.tsx\"],\n exclude: defaultExclude(),\n })\n scanFiles.push(...packageScanFiles)\n scannedSurfaces.push({\n label: `package:${origin.packageName}`,\n root: displayPath(root, origin.packageDir),\n })\n }\n\n return { scanFiles, scannedSurfaces }\n}\n\n/** Options for {@link generateUsageReport}. */\nexport interface GenerateUsageReportOptions {\n /** The filesystem capability -- `./build` never imports `node:fs` (ADR 0040). */\n fs: BuildFileSystem\n /** Directory glob patterns are resolved against. Defaults to `process.cwd()`. */\n root?: string | undefined\n /** Schema-discovery glob, for the contract graph -- self-sufficient like the other two generator functions. */\n include?: string[] | undefined\n /** Glob patterns to exclude, for both schema discovery and the usage scan. Defaults to node_modules/dist/.git. */\n exclude?: string[] | undefined\n /** **Experimental** (see VERSIONING.md) -- see `GenerateEnvManifestOptions.packages`; see ADR 0014. */\n packages?: readonly string[] | undefined\n /** **Experimental** (see VERSIONING.md) -- see `GenerateEnvManifestOptions.tsconfig`; see ADR 0023. */\n tsconfig?: string | false | undefined\n /** Also write the rendered Markdown report to this path, relative to `root`. Omitted: the report is only returned, not written. */\n report?:\n | {\n /** Output path for the report, relative to `root`. */\n location: string\n }\n | undefined\n}\n\n/**\n * Public result of {@link generateUsageReport}.\n *\n * @remarks\n * Composed from the building-block types `usage-report.ts` (the renderer) owns, the same way\n * `GenerateDocumentationResult` composes from `docs.ts`'s `CatalogContract` --\n * keeps the renderer importable without its orchestrator (see\n * `RenderUsageReportOptions`'s own doc comment).\n */\nexport interface GenerateUsageReportResult extends RenderUsageReportOptions {\n /** Absolute path the report was written to, or `undefined` if `options.report` wasn't passed. */\n readonly reportPath: string | undefined\n}\n\nexport interface UsageComputation {\n readonly graph: DependencyGraph\n readonly result: RenderUsageReportOptions\n}\n\n/**\n * Builds the dependency graph and maps it into the public, ownership-framed\n * result. Never blocks -- see `RenderUsageReportOptions`'s finding fields'\n * own doc comments; a team that wants to gate CI on an ownership issue reads\n * `Finding[]` (the \"ownership\" family) from the persisted evidence artifact\n * and decides for itself. See ADR 0038.\n *\n * @remarks\n * This mapping is the actual API boundary: internal AST vocabulary\n * (\"member accessed\", \"dynamic\") becomes ownership vocabulary (\"who owns\n * it\", \"who consumes it\", \"abandoned\", \"unresolved\"). The result is a\n * renderer-agnostic domain model -- the same computed data a future JSON or\n * SARIF exporter would consume, not something coupled to the Markdown\n * renderer.\n */\nexport async function computeUsage(\n root: string,\n contracts: readonly DiscoveredContract[],\n scanFiles: readonly string[],\n readFile: (filePath: string) => Promise<string>,\n context: ImportResolutionContext,\n parseWarnings: readonly ParseWarning[],\n scannedSurfaces?: readonly ScannedSurface[],\n dynamicAccessAcknowledgments?: ReadonlyMap<string, readonly DynamicAccessAssertion[]>,\n): Promise<UsageComputation> {\n const graph = await buildDependencyGraph(\n contracts,\n scanFiles,\n readFile,\n context,\n scannedSurfaces,\n dynamicAccessAcknowledgments,\n )\n const findings = deriveOwnershipFindings(graph)\n\n const contractByIdentity = new Map<string, DiscoveredContract>()\n for (const contract of contracts)\n contractByIdentity.set(`${contract.file}#${contract.exportName}`, contract)\n // Contract-level default owner only -- correct for a contract-level\n // finding (dependencyOwnership, abandonedContracts), which has no\n // specific variable to consider a per-variable override for.\n //\n // `file`/`exportName` here always come from `graph.contracts` (via\n // `deriveOwnershipFindings()`), which `buildDependencyGraph()` builds 1:1\n // from this SAME `contracts` array (same identity-key derivation) -- so\n // the lookup can never actually miss. The `?.` only exists for TypeScript's\n // own narrowing; hand-verified by removing it and running the full\n // `vitest run`: only the two tsc-backed json-schema freshness tests fail\n // (a type-narrowing regression, not a behavioral one), every other test\n // (1226) passes unchanged.\n const ownerFor = (file: string, exportName: string): string | undefined =>\n // Stryker disable next-line OptionalChaining\n contractByIdentity.get(`${file}#${exportName}`)?.owner\n // A specific variable's *effective* owner (its own override, falling back\n // to the contract default) -- see ADR 0028. Used only for\n // unconsumedOwnedVariables below, the one finding type that names a\n // specific variable.\n const effectiveOwnerFor = (file: string, exportName: string, key: string): string | undefined => {\n const contract = contractByIdentity.get(`${file}#${exportName}`)\n // Same provably-always-found identity guarantee as `ownerFor` above\n // (`f.file`/`f.exportName` here come from `findings.unconsumedOwned`,\n // itself derived from the same `graph.contracts`) -- hand-verified the\n // same way: bypassing this guard only breaks the two tsc-narrowing\n // tests, not any real behavior.\n // Stryker disable next-line ConditionalExpression\n if (!contract) return undefined\n const variable = contract.variables.find((v) => v.key === key)\n return variable ? effectiveOwner(contract, variable) : contract.owner\n }\n\n const dependencyOwnership: OwnershipDependencyEntry[] = graph.contracts.map((c) => ({\n contractName: c.contractName,\n file: path.relative(root, c.file),\n owner: ownerFor(c.file, c.exportName),\n variableCount: c.variables.size,\n consumers: c.consumingFiles.map((f) => path.relative(root, f)),\n }))\n\n const abandonedContracts: AbandonedContractFinding[] = findings.abandoned.map((f) => ({\n contractName: f.contractName,\n file: path.relative(root, f.file),\n owner: ownerFor(f.file, f.exportName),\n }))\n\n const unresolvedConsumers: UnresolvedConsumerFinding[] = findings.unresolvedConsumers.map(\n (f) => ({\n contractName: f.contractName,\n file: path.relative(root, f.file),\n reason: f.reason,\n }),\n )\n\n // Every `dynamicAccess` citation for this variable that's currently\n // stale/missing -- the confidence signal `renderUsageReport()` shows\n // alongside \"unconsumed\"/\"indeterminate\" (ADR 0038). A variable with a\n // *fresh* assertion never reaches here at all (`deriveOwnershipFindings()`\n // already routed it into `asserted` instead), so every citation found by\n // this lookup is, by construction, one env-cap can no longer vouch for.\n const staleOrMissingCitationsFor = (\n contractName: string,\n file: string,\n exportName: string,\n key: string,\n ): DynamicAccessCitationProblem[] => {\n const relativeFile = displayPath(root, file)\n const identity = dynamicAccessVariableIdentity(relativeFile, exportName, key)\n const problems: DynamicAccessCitationProblem[] = []\n for (const a of dynamicAccessAcknowledgments?.get(identity) ?? []) {\n // Per the doc comment above: unreachable in practice from either real\n // caller (unconsumedOwnedVariables/indeterminate below) -- both only\n // ever call this for a finding `deriveOwnershipFindings()` already\n // decided has NO \"fresh\" assertion (a \"fresh\"-containing variable is\n // routed to the separate \"asserted\" bucket instead, using this exact\n // same identity-keyed map). Hand-verified: forcing this to `if (false)`\n // and running the full `vitest run` leaves all 1232 tests passing.\n // Stryker disable next-line ConditionalExpression, StringLiteral\n if (a.acknowledgment === \"fresh\") continue\n problems.push({\n contractName,\n file: relativeFile,\n exportName,\n key,\n position: { file: a.file, line: a.line, column: a.column },\n acknowledgment: a.acknowledgment,\n })\n }\n return problems\n }\n\n const unconsumedOwnedVariables: UnconsumedOwnedVariableFinding[] = findings.unconsumedOwned.map(\n (f) => ({\n contractName: f.contractName,\n owner: effectiveOwnerFor(f.file, f.exportName, f.key),\n key: f.key,\n staleOrMissingCitations: staleOrMissingCitationsFor(\n f.contractName,\n f.file,\n f.exportName,\n f.key,\n ),\n }),\n )\n\n const indeterminate: IndeterminateOwnershipFinding[] = findings.indeterminate.map((f) => ({\n contractName: f.contractName,\n key: f.key,\n reason: f.reason,\n dynamicAccessSites: f.dynamicAccessSites.map((p) => ({\n ...p,\n file: displayPath(root, p.file),\n })),\n staleOrMissingCitations: staleOrMissingCitationsFor(\n f.contractName,\n f.file,\n f.exportName,\n f.key,\n ),\n }))\n\n // Assertion positions are already root-relative by citation construction\n // (a `dynamicAccess` entry is a developer-authored relative path), unlike\n // `dynamicAccessSites` above -- no relativizing needed here.\n const asserted: AssertedDynamicAccessFinding[] = findings.asserted.map((f) => ({\n contractName: f.contractName,\n key: f.key,\n wouldBeStatus: f.wouldBeStatus,\n dynamicAccessAssertions: f.dynamicAccessAssertions,\n }))\n\n return {\n graph,\n result: {\n dependencyOwnership,\n abandonedContracts,\n unresolvedConsumers,\n unconsumedOwnedVariables,\n indeterminate,\n asserted,\n parseWarnings,\n scannedSurfaces: graph.scannedSurfaces,\n },\n }\n}\n\n/** Writes the Dependency & Ownership Report. Callers must have already confirmed `reportPath` is safe and nothing is blocking. */\nexport async function writeUsageReport(\n reportPath: string,\n computed: Omit<GenerateUsageReportResult, \"reportPath\">,\n fs: BuildFileSystem,\n): Promise<void> {\n const source = renderUsageReport(computed)\n await fs.mkdir(path.dirname(reportPath), { recursive: true })\n // `source` is always a plain string (renderUsageReport()'s return type) --\n // fs.writeFile defaults a string write to utf8 regardless of the encoding\n // arg, so \"utf8\" vs \"\" is unobservable. Same established equivalence as\n // evidence-cache.ts/evidence-fingerprint.ts/env-example.ts's own writes.\n // Stryker disable next-line StringLiteral\n await fs.writeFile(reportPath, source, \"utf8\")\n}\n\n/**\n * Build-time only. Answers who owns each contract, which features depend on\n * it, and what the blast radius is if it changes -- the mirror image of\n * {@link generateEnvManifest}'s \"safer migrations\" story: a schema that was never\n * wired up, or was abandoned mid-removal, shows up here instead of sitting\n * unnoticed.\n *\n * @remarks\n * This is an additional, separate artifact, not a replacement for\n * {@link generateDocumentation}'s Catalog -- the two serve different audiences\n * (see ADR 0010).\n *\n * @throws {EnvUsageAnalysisError} If `report.location` escapes `root`.\n */\nexport async function generateUsageReport(\n options: GenerateUsageReportOptions,\n): Promise<GenerateUsageReportResult> {\n const root = path.resolve(options.root ?? process.cwd())\n const include = options.include ?? defaultInclude()\n const exclude = options.exclude ?? defaultExclude()\n const packages = options.packages ?? []\n\n let reportPath: string | undefined\n if (options.report) {\n const result = resolveWithinRoot(\n root,\n options.report.location,\n \"report.location\",\n \"generateUsageReport\",\n )\n if (!result.ok) throw new EnvUsageAnalysisError([result.issue])\n reportPath = result.resolved\n }\n\n const { readFileCached, linkResult, context, origins, packageWarnings, tsconfigWarnings } =\n await assembleProject({\n fs: options.fs,\n root,\n include,\n exclude,\n packages,\n tsconfig: options.tsconfig,\n })\n\n const { scanFiles, scannedSurfaces } = await computeScanSurface(\n root,\n exclude,\n origins,\n options.fs,\n )\n\n const computed = await computeUsage(\n root,\n linkResult.contracts,\n scanFiles,\n readFileCached,\n context,\n [...packageWarnings, ...tsconfigWarnings, ...linkResult.warnings],\n scannedSurfaces,\n )\n\n if (reportPath) await writeUsageReport(reportPath, computed.result, options.fs)\n\n return { reportPath, ...computed.result }\n}\n","import type { ArtifactCheckFinding } from \"./check-artifacts.js\"\nimport type { CompatibilityIssue, CompatibilityIssueCode } from \"./compatibility.js\"\nimport { displayPath } from \"./display-path.js\"\nimport type { EvidenceReference } from \"./evidence-reference.js\"\nimport type { DocumentationFindings } from \"./generate-documentation.js\"\nimport type { DynamicAccessCitationProblem } from \"./citation-verification.js\"\nimport type {\n AbandonedContractFinding,\n IndeterminateOwnershipFinding,\n UnconsumedOwnedVariableFinding,\n UnresolvedConsumerFinding,\n} from \"./usage-report.js\"\n\n/**\n * The fourth of env-cap's seven canonical fact models (ADR 0024) -- every\n * rule violation and derived risk signal, unified behind one shape, with a\n * stable `code` and a structured {@link EvidenceReference} instead of four\n * independently-shaped finding families. See ADR 0026.\n */\n\n/** Every stable `code` a {@link Finding} can carry. A superset of {@link CompatibilityIssueCode} plus one code per non-compatibility source family this model adapts. */\nexport type FindingCode =\n | CompatibilityIssueCode\n | \"EXCLUSIVE_GROUP_VIOLATION\"\n | \"ARTIFACT_STALE\"\n | \"ARTIFACT_MISSING\"\n | \"UNDOCUMENTED_CONTRACT\"\n | \"UNDOCUMENTED_VARIABLE\"\n | \"STALE_DOC_ENTRY\"\n | \"EXPIRED\"\n | \"EXPIRING_SOON\"\n | \"UNRESOLVED_DOCUMENTENV_LINK\"\n | \"ABANDONED_CONTRACT\"\n | \"UNRESOLVED_CONSUMER\"\n | \"UNCONSUMED_OWNED_VARIABLE\"\n | \"INDETERMINATE_OWNERSHIP\"\n | \"MISSING_DYNAMIC_ACCESS_CITATION\"\n | \"STALE_DYNAMIC_ACCESS_CITATION\"\n | \"NONSTANDARD_SENSITIVITY_LEVEL\"\n\n/** Which source check produced a {@link Finding} -- coarser than `code`, for a consumer that only wants to filter by kind (e.g. \"show me every documentation gap\") without enumerating every individual code. */\nexport type FindingFamily = \"compatibility\" | \"drift\" | \"documentation\" | \"ownership\"\n\n/** One rule violation or derived signal, in the Finding Model's canonical shape. */\nexport interface Finding {\n /**\n * `\"error\"` for a provable, always-blocking violation (e.g. an\n * exclusive-group conflict); `\"warning\"` for everything gated by\n * `onIncompatibility`/`onUndocumented`/`onOwnershipIssue`'s default \"warn\"\n * behavior; `\"info\"` for an observation that is never actionable enough to\n * block anything, even under `--strict` -- see `INFO_ONLY_CODES` in\n * `generate-env-artifacts.ts`.\n */\n readonly severity: \"error\" | \"warning\" | \"info\"\n /** Stable, machine-readable identifier -- always set, unlike {@link CompatibilityIssue.code} which stays optional on that narrower, pre-existing type. */\n readonly code: FindingCode\n /** Which source check produced this finding. */\n readonly family: FindingFamily\n /** Human-readable explanation, reusing the source finding's own prose where one exists. */\n readonly message: string\n /** Structured pointer back to what this finding is about. */\n readonly location: EvidenceReference\n}\n\n/** Bump only when a reader could misinterpret the new shape -- same discipline every other canonical model's `schemaVersion` follows. */\nexport const FINDING_MODEL_SCHEMA_VERSION = 3\n\nexport interface FindingModel {\n readonly schemaVersion: typeof FINDING_MODEL_SCHEMA_VERSION\n readonly findings: readonly Finding[]\n}\n\n/**\n * Every source a {@link buildFindingModel} call can adapt, all optional --\n * a caller passes whichever of `generateEnvArtifacts()`'s `manifest`/`docs`/\n * `usage` results it actually requested, exactly like that result's own\n * top-level fields are each independently optional.\n */\nexport interface BuildFindingModelInput {\n /** Every `EvidenceReference.file` below is rendered relative to this, matching every other rendered path in this package's output -- see `displayPath()`. */\n readonly root: string\n /** From `detectCompatibilityIssues()`. */\n readonly compatibilityIssues?: readonly CompatibilityIssue[]\n /** From `detectExclusiveGroupIssues()` -- kept separate from `compatibilityIssues` since it never sets its own `code` yet (ADR 0009), so this adapter synthesizes `\"EXCLUSIVE_GROUP_VIOLATION\"` for every entry. */\n readonly exclusiveGroupIssues?: readonly CompatibilityIssue[]\n /** From `checkEnvArtifacts()`'s result. Only `\"stale\"`/`\"missing\"` findings become a `Finding` -- `\"ok\"` means nothing to report. */\n readonly artifactCheckFindings?: readonly ArtifactCheckFinding[]\n /** From `generateDocumentation()`'s result. */\n readonly documentation?: DocumentationFindings\n /** From `generateUsageReport()`'s result. */\n readonly abandonedContracts?: readonly AbandonedContractFinding[]\n /** From `generateUsageReport()`'s result. */\n readonly unresolvedConsumers?: readonly UnresolvedConsumerFinding[]\n /** From `generateUsageReport()`'s result. */\n readonly unconsumedOwnedVariables?: readonly UnconsumedOwnedVariableFinding[]\n /** From `generateUsageReport()`'s result. */\n readonly indeterminateOwnership?: readonly IndeterminateOwnershipFinding[]\n /** From `computeManifestChanges()`'s result -- every `dynamicAccess` citation that's gone `\"stale\"` or `\"missing\"` since it was last acknowledged. See ADR 0037. */\n readonly dynamicAccessCitationProblems?: readonly DynamicAccessCitationProblem[]\n}\n\n// None of `finding-model.ts`'s current inputs (`CompatibilityIssue`,\n// `DocumentationFindings`'s sub-types, `usage-report.ts`'s finding types)\n// carry a `SourcePosition` themselves yet -- each is built one layer above\n// this file, from a `DiscoveredContract`/`DiscoveredVariable` that now\n// *does* carry `declaration`/`documentation` (ADR 0036), but threading that\n// through each of those intermediate finding types is real, separate,\n// currently-unstarted work, not something to fake here. `position:\n// undefined` is an honest value (the field's own type is `SourcePosition |\n// undefined`), not a placeholder -- every `EvidenceReference` below is\n// deliberately left at that default until its upstream finding type is\n// extended to carry one.\nconst NO_POSITION = undefined\n\nfunction fromCompatibilityIssue(\n root: string,\n issue: CompatibilityIssue,\n code: FindingCode,\n): Finding {\n return {\n severity: issue.severity,\n code,\n family: \"compatibility\",\n message: issue.reason,\n location: {\n model: \"contract\",\n file: displayPath(root, issue.files[0]),\n exportName: undefined,\n variable: issue.variable,\n position: NO_POSITION,\n },\n }\n}\n\n/**\n * Adapts every existing finding family into the Finding Model's unified\n * shape -- an adapter over data that already exists, not a new source of\n * truth. Order of the returned array mirrors the order sources are given\n * above; a consumer wanting a specific order (by severity, by file, ...)\n * sorts it themselves.\n */\nexport function buildFindingModel(input: BuildFindingModelInput): FindingModel {\n const { root } = input\n const findings: Finding[] = []\n\n for (const issue of input.compatibilityIssues ?? []) {\n // Every check in detectCompatibilityIssues() sets a code as of ADR 0026 --\n // the fallback exists only for defense against a future check that forgets to.\n findings.push(\n fromCompatibilityIssue(root, issue, issue.code ?? \"DUPLICATE_VARIABLE_DOCUMENTATION\"),\n )\n }\n\n for (const issue of input.exclusiveGroupIssues ?? []) {\n findings.push(fromCompatibilityIssue(root, issue, \"EXCLUSIVE_GROUP_VIOLATION\"))\n }\n\n for (const check of input.artifactCheckFindings ?? []) {\n if (check.status === \"ok\") continue\n findings.push({\n severity: \"warning\",\n code: check.status === \"missing\" ? \"ARTIFACT_MISSING\" : \"ARTIFACT_STALE\",\n family: \"drift\",\n message: check.detail ?? `${check.artifact} artifact is ${check.status}.`,\n location: { model: \"change\", path: check.path },\n })\n }\n\n const documentation = input.documentation\n if (documentation) {\n for (const c of documentation.undocumentedContracts) {\n findings.push({\n severity: \"warning\",\n code: \"UNDOCUMENTED_CONTRACT\",\n family: \"documentation\",\n message: `\"${c.exportName}\" has no documentEnv() call linked to it.`,\n location: {\n model: \"contract\",\n file: displayPath(root, c.file),\n exportName: c.exportName,\n variable: undefined,\n position: NO_POSITION,\n },\n })\n }\n for (const v of documentation.undocumentedVariables) {\n findings.push({\n severity: \"warning\",\n code: \"UNDOCUMENTED_VARIABLE\",\n family: \"documentation\",\n message: `\"${v.key}\" (declared by \"${v.exportName}\") has no matching entry in a linked documentEnv()'s \"variables\".`,\n location: {\n model: \"contract\",\n file: displayPath(root, v.file),\n exportName: v.exportName,\n variable: v.key,\n position: NO_POSITION,\n },\n })\n }\n for (const s of documentation.staleDocEntries) {\n findings.push({\n severity: \"warning\",\n code: \"STALE_DOC_ENTRY\",\n family: \"documentation\",\n message: `\"${s.key}\" is documented under \"${s.exportName}\" but no longer exists in that contract's schema.`,\n location: {\n model: \"contract\",\n file: displayPath(root, s.file),\n exportName: s.exportName,\n variable: s.key,\n position: NO_POSITION,\n },\n })\n }\n for (const e of documentation.expiringSoon) {\n const expired = e.daysRemaining < 0\n findings.push({\n severity: \"warning\",\n code: expired ? \"EXPIRED\" : \"EXPIRING_SOON\",\n family: \"documentation\",\n message: expired\n ? `\"${e.key ?? e.exportName}\" expired ${Math.abs(e.daysRemaining)} day(s) ago (expiresAt: ${e.expiresAt}).`\n : `\"${e.key ?? e.exportName}\" expires in ${e.daysRemaining} day(s) (expiresAt: ${e.expiresAt}).`,\n location: {\n model: \"contract\",\n file: displayPath(root, e.file),\n exportName: e.exportName,\n variable: e.key,\n position: NO_POSITION,\n },\n })\n }\n for (const n of documentation.nonstandardSensitivityLevels) {\n findings.push({\n severity: \"info\",\n code: \"NONSTANDARD_SENSITIVITY_LEVEL\",\n family: \"documentation\",\n message:\n `\"${n.key ?? n.exportName}\" declares sensitivity \"${n.sensitivity}\", which isn't one of the standard ` +\n \"levels (secret/credential/pii/config) -- still honored verbatim, just flagged for vocabulary drift.\",\n location: {\n model: \"contract\",\n file: displayPath(root, n.file),\n exportName: n.exportName,\n variable: n.key,\n position: NO_POSITION,\n },\n })\n }\n for (const u of documentation.unresolvedLinks) {\n findings.push({\n severity: \"warning\",\n code: \"UNRESOLVED_DOCUMENTENV_LINK\",\n family: \"documentation\",\n message: u.reason,\n location: {\n model: \"contract\",\n file: displayPath(root, u.file),\n exportName: undefined,\n variable: undefined,\n position: NO_POSITION,\n },\n })\n }\n }\n\n for (const a of input.abandonedContracts ?? []) {\n findings.push({\n severity: \"warning\",\n code: \"ABANDONED_CONTRACT\",\n family: \"ownership\",\n message: `\"${a.contractName}\" is never imported anywhere in the scanned repository.`,\n location: {\n model: \"ownership\",\n contractName: a.contractName,\n // a.file (AbandonedContractFinding.file) is already root-relative.\n file: a.file,\n variable: undefined,\n position: NO_POSITION,\n },\n })\n }\n for (const u of input.unresolvedConsumers ?? []) {\n findings.push({\n severity: \"warning\",\n code: \"UNRESOLVED_CONSUMER\",\n family: \"ownership\",\n message: u.reason,\n location: {\n model: \"ownership\",\n contractName: u.contractName,\n // u.file (UnresolvedConsumerFinding.file) is already root-relative.\n file: u.file,\n variable: undefined,\n position: NO_POSITION,\n },\n })\n }\n for (const u of input.unconsumedOwnedVariables ?? []) {\n findings.push({\n severity: \"warning\",\n code: \"UNCONSUMED_OWNED_VARIABLE\",\n family: \"ownership\",\n message: `\"${u.key}\" (declared by \"${u.contractName}\") has no consumer found in the scanned repository.`,\n location: {\n model: \"ownership\",\n contractName: u.contractName,\n file: undefined,\n variable: u.key,\n position: NO_POSITION,\n },\n })\n }\n for (const i of input.indeterminateOwnership ?? []) {\n findings.push({\n severity: \"warning\",\n code: \"INDETERMINATE_OWNERSHIP\",\n family: \"ownership\",\n message: i.reason,\n location: {\n model: \"ownership\",\n contractName: i.contractName,\n file: undefined,\n variable: i.key,\n // Multiple candidate sites, never one representative pointer -- see\n // `IndeterminateOwnershipFinding.dynamicAccessSites` for the full list.\n position: NO_POSITION,\n },\n })\n }\n\n for (const p of input.dynamicAccessCitationProblems ?? []) {\n const missing = p.acknowledgment === \"missing\"\n findings.push({\n severity: \"warning\",\n code: missing ? \"MISSING_DYNAMIC_ACCESS_CITATION\" : \"STALE_DYNAMIC_ACCESS_CITATION\",\n family: \"ownership\",\n message: missing\n ? `\"${p.key}\" (declared by \"${p.contractName}\") cites dynamic access at ${p.position.file}:${p.position.line}:${p.position.column}, but that file no longer exists. Re-run generate:env once the citation is corrected.`\n : `\"${p.key}\" (declared by \"${p.contractName}\") cites dynamic access at ${p.position.file}:${p.position.line}:${p.position.column}, but that file's content has changed since it was last acknowledged. Re-run generate:env once you've re-confirmed the citation still applies.`,\n location: {\n model: \"ownership\",\n contractName: p.contractName,\n // p.file (DynamicAccessCitationProblem.file) is already\n // root-relative -- unlike every other .file above, not a raw\n // absolute path -- so no displayPath() conversion here.\n file: p.file,\n variable: p.key,\n // The one ownership-family finding with a genuinely meaningful\n // position -- exactly where the (now-stale/missing) citation points.\n position: p.position,\n },\n })\n }\n\n return { schemaVersion: FINDING_MODEL_SCHEMA_VERSION, findings }\n}\n","/**\n * Formats a metadata key for display in generated docs/examples:\n * \"lastRotation\" -> \"Last Rotation\". Shared by `docs.ts` and `env-example.ts`\n * so both generated artifacts label metadata the same way.\n */\nexport function humanizeKey(key: string): string {\n // No `spaced.length === 0` guard: `.charAt(0)`/`.slice(1)` on an empty\n // string are both already safe (return `\"\"`), so the ternary this used to\n // be was provably redundant for its only possible trigger (`key === \"\"`,\n // the sole way `.replace()` here can produce an empty `spaced` -- it only\n // ever inserts characters, never removes them).\n const spaced = key.replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n return spaced.charAt(0).toUpperCase() + spaced.slice(1)\n}\n\n/**\n * Formats a `metadata`/`dataResidency` value for display in generated docs/examples -- a string\n * renders as-is; anything else (ADR 0035 widened `metadata` to any value) renders as its JSON\n * text, so an object/array value never prints `[object Object]`. Shared by `docs.ts` and\n * `env-example.ts`, same rationale as {@link humanizeKey}.\n */\nexport function renderMetadataValue(value: unknown): string {\n return typeof value === \"string\" ? value : JSON.stringify(value)\n}\n","import type { EvidenceModel } from \"../build/evidence-model.js\"\n\n/**\n * A pure function from the full Evidence Model to one field of a\n * projection's output shape. Must not mutate `evidence` -- the membrane\n * `defineEvidenceProjection()` wraps it in enforces that at runtime, see\n * `createTrackingProxy()` below -- and must not perform I/O; env-cap can\n * enforce the read-only half of purity but not the \"no side effects\" half.\n */\nexport type EvidenceProjector<T> = (evidence: EvidenceModel) => T\n\n/** One independent, pure projector function per key of the projection's output shape `T`. */\nexport type EvidenceProjectionSchema<T extends Record<string, unknown>> = {\n readonly [K in keyof T]: EvidenceProjector<T[K]>\n}\n\n/** `project()`'s return shape: the computed output, plus which `EvidenceModel` field paths fed each output key. */\nexport interface EvidenceProjectionResult<T extends Record<string, unknown>> {\n readonly value: T\n readonly sources: Readonly<Record<keyof T, readonly string[]>>\n}\n\n/**\n * The function `defineEvidenceProjection()` returns. Callable directly for\n * the common case (`projection(evidence)` -> `T`); `.project()` returns the\n * same value alongside automatic provenance -- see ADR 0032.\n */\nexport interface EvidenceProjection<T extends Record<string, unknown>> {\n (evidence: EvidenceModel): T\n project(evidence: EvidenceModel): EvidenceProjectionResult<T>\n}\n\n/**\n * Declares a projection: a named, pure transform from the immutable\n * `EvidenceModel` to any consumer-defined output shape, built entirely from\n * `schema`'s independent per-field projector functions -- see ADR 0031/0032.\n *\n * env-cap's own reference projections (`.env.example`, Environment\n * Configuration Reference, Configuration Ownership, etc.) are built through\n * this exact function, with no privileged internal path -- a consumer's own\n * projection is a first-class citizen, not a lesser one.\n */\nexport function defineEvidenceProjection<T extends Record<string, unknown>>(\n schema: EvidenceProjectionSchema<T>,\n): EvidenceProjection<T> {\n function project(evidence: EvidenceModel): EvidenceProjectionResult<T> {\n const value = {} as Record<string, unknown>\n const sources = {} as Record<string, readonly string[]>\n for (const key of Object.keys(schema)) {\n const projector = schema[key as keyof T]\n const { proxy, readPaths } = createTrackingProxy(evidence)\n value[key] = projector(proxy)\n sources[key] = readPaths()\n }\n return { value: value as T, sources: sources as Readonly<Record<keyof T, readonly string[]>> }\n }\n\n function invoke(evidence: EvidenceModel): T {\n return project(evidence).value\n }\n\n return Object.assign(invoke, { project })\n}\n\n/**\n * The error every membrane write-trap below throws. A function, not a\n * module-level `const` -- a `const` string's mutants are evaluated once at\n * module load and can't be attributed to a covering test under Stryker's\n * `perTest` coverage analysis (a documented false-Survivor, not a real\n * gap); exported so a test can pin the exact message directly, the same way\n * every membrane trap's own `.toThrow(...)` can't (a `TypeError` from a\n * Proxy invariant violation is thrown either way a trap's body is mutated,\n * so `.toThrow(TypeError)` alone doesn't distinguish \"our message\" from\n * \"the engine's own invariant-violation message\").\n */\nexport function readOnlyMembraneError(): TypeError {\n return new TypeError(\n \"EvidenceModel is read-only inside a projector -- a projection must be a pure function of its evidence argument. See ADR 0032.\",\n )\n}\n\n/**\n * Wraps a fresh, unfrozen clone of `evidence` in a Proxy membrane that\n * throws on any write and records every field path read through it.\n *\n * @remarks\n * Deliberately does not rely on `Object.freeze()` for the read-only\n * guarantee: a `Proxy` `get` trap on a frozen, non-configurable data\n * property is spec-required to return the exact (`===`) value the target\n * holds, which makes it impossible to substitute a wrapping proxy for a\n * frozen object's nested properties -- confirmed by direct reproduction\n * during this feature's design spike (see ADR 0032). The membrane's own\n * `set`/`deleteProperty`/`defineProperty`/`setPrototypeOf` traps enforce\n * immutability instead, which works on an unfrozen target. The caller's\n * `evidence` (typically already `deepFreeze()`-d by `generateEvidenceModel()`)\n * is never mutated -- `structuredClone()` gives this membrane its own\n * disposable copy to wrap, so a genuinely frozen `EvidenceModel` can still\n * be projected.\n */\nfunction createTrackingProxy(evidence: EvidenceModel): {\n proxy: EvidenceModel\n readPaths: () => readonly string[]\n} {\n const clone = structuredClone(evidence)\n const paths = new Set<string>()\n const wrapped = new WeakMap<object, unknown>()\n\n function wrap<V>(value: V, path: readonly string[]): V {\n if (value === null || typeof value !== \"object\") return value\n const target = value\n const cached = wrapped.get(target)\n if (cached) return cached as V\n\n const proxy = new Proxy(target, {\n get(currentTarget, prop, receiver) {\n const result: unknown = Reflect.get(currentTarget, prop, receiver)\n if (typeof prop !== \"string\") return result\n if (Array.isArray(currentTarget) && prop === \"length\") return result\n const nextPath = [...path, prop]\n paths.add(nextPath.join(\".\"))\n return wrap(result, nextPath)\n },\n set() {\n throw readOnlyMembraneError()\n },\n deleteProperty() {\n throw readOnlyMembraneError()\n },\n defineProperty() {\n throw readOnlyMembraneError()\n },\n setPrototypeOf() {\n throw readOnlyMembraneError()\n },\n })\n wrapped.set(target, proxy)\n return proxy\n }\n\n return { proxy: wrap(clone, []), readPaths: () => [...paths].sort() }\n}\n","/**\n * env-cap's own built-in reference projections, declared through the exact\n * same public `defineEvidenceProjection()` a consumer would use (ADR\n * 0031/0032) -- no privileged internal path, no second way of reading the\n * Evidence Model.\n *\n * This is deliberate dogfooding, not a convenience layer: `renderDocs()`'s\n * Catalog/ownership/lifecycle sections and `renderUsageReport()`'s ownership\n * table now source their underlying data through these projections, so the\n * extensibility API is exercised by env-cap's own generated output on every\n * single run. If a projector here can't express something, that's a real gap\n * in the public API -- discovered by env-cap itself rather than by a consumer\n * reporting it.\n *\n * Every projection is pure and derives *only* from `EvidenceModel`. None\n * reads the filesystem, and none reaches back into `DiscoveredContract` --\n * that would defeat the point, since a consumer only ever has the model.\n */\n\nimport { defineEvidenceProjection } from \"../evidence/define-projection.js\"\nimport { evidenceDisclaimer } from \"./generated-banner.js\"\nimport type { ContractModelContract } from \"./contract-model.js\"\nimport type { EvidenceModel } from \"./evidence-model.js\"\n\n/** One variable, flattened across Contract/Ownership/Lifecycle Model into the row a Configuration Reference renders. */\nexport interface ConfigurationReferenceEntry {\n /** Root-relative, POSIX-separated path of the declaring contract. */\n readonly file: string\n readonly exportName: string\n /** The declaring contract's display name, resolved from Contract Model -- the one model that owns it. */\n readonly contractName: string\n readonly key: string\n readonly description: string | undefined\n /** Effective owner: the variable's own, falling back to its contract's. */\n readonly owner: string | undefined\n /** Effective sensitivity: the variable's own, falling back to its contract's. Any string; see {@link runtime.VariableDocs.sensitivity}. */\n readonly sensitivity: string | undefined\n readonly required: boolean | undefined\n readonly hasDefault: boolean\n readonly hasProcessor: boolean\n readonly hasValidator: boolean\n readonly expiresAt: string | undefined\n /** Whether the declaring contract is active. Inactive contracts are included -- the reference documents everything discovered, same scope the Catalog always had. */\n readonly active: boolean\n}\n\n/** The Configuration Reference projection's output shape. */\nexport interface ConfigurationReference extends Record<string, unknown> {\n /** The standing \"declared, not verified\" notice -- see `evidenceDisclaimer()`. Carried in the data, not only in a renderer, so a consumer projecting this to their own format can't accidentally drop it. */\n readonly disclaimer: string\n /** Every declared variable across every discovered contract, sorted by contract file, then export name, then key. */\n readonly entries: readonly ConfigurationReferenceEntry[]\n}\n\nfunction byContractThenKey(\n a: { file: string; exportName: string; key: string },\n b: { file: string; exportName: string; key: string },\n): number {\n return (\n a.file.localeCompare(b.file) ||\n a.exportName.localeCompare(b.exportName) ||\n a.key.localeCompare(b.key)\n )\n}\n\n/** Index of every contract by `${file}#${exportName}` -- the join key every projection below uses to resolve display text and contract-level defaults. */\nfunction contractIndex(\n contracts: readonly ContractModelContract[],\n): ReadonlyMap<string, ContractModelContract> {\n return new Map(contracts.map((c) => [`${c.file}#${c.exportName}`, c]))\n}\n\n/** The minimal shape {@link groupVariablesByOwner} needs -- structural, not pinned to one model, so the exact same grouping serves `OwnershipModel`'s already-resolved owners and `ContractModel`'s raw ones alike. */\nexport interface OwnerBearingContract {\n readonly owner: string | undefined\n readonly variables: readonly unknown[]\n}\n\n/** The element type of an {@link OwnerBearingContract}'s own `variables`, so callers never have to name it a second time. */\ntype VariableOf<C> = C extends { readonly variables: readonly (infer V)[] } ? V : never\n\n/**\n * Groups every variable under its effective owner (its own, falling back to\n * its contract's), preserving input order within each owner.\n *\n * @remarks\n * The single implementation of \"who owns what, rolled up per owner\", shared\n * by the {@link ownershipSummary} projection and `docs.ts`'s own rendered\n * ownership matrix. Kept as one function precisely so env-cap's generated\n * Markdown and the projection a consumer reads can never disagree about the\n * grouping -- the same reason `effectiveOwner()` is the single resolution\n * rule (ADR 0028). Variables with no effective owner are omitted entirely\n * rather than bucketed under a synthetic `\"unowned\"` key, which would read\n * as a real team name; callers that need them ask for them separately.\n *\n * `ownerOf` is supplied by the caller so a model whose owners are already\n * resolved (`OwnershipModel`) and one whose aren't (`ContractModel`) both\n * work without this function guessing which it was handed.\n */\nexport function groupVariablesByOwner<C extends OwnerBearingContract>(\n contracts: readonly C[],\n ownerOf: (contract: C, variable: VariableOf<C>) => string | undefined,\n): ReadonlyMap<string, readonly { contract: C; variable: VariableOf<C> }[]> {\n const byOwner = new Map<string, { contract: C; variable: VariableOf<C> }[]>()\n for (const contract of contracts) {\n for (const variable of contract.variables as readonly VariableOf<C>[]) {\n const owner = ownerOf(contract, variable)\n if (owner === undefined) continue\n const list = byOwner.get(owner) ?? []\n list.push({ contract, variable })\n byOwner.set(owner, list)\n }\n }\n return byOwner\n}\n\n/**\n * Configuration Reference: every declared variable, with its effective owner\n * and sensitivity already resolved, in one flat, sorted list.\n *\n * @remarks\n * Resolution (variable's own value falling back to its contract's) happens\n * here rather than being left to each consumer, so two readers of this\n * projection can never disagree about who owns a variable -- the same reason\n * `effectiveOwner()` exists on the generator side (ADR 0028).\n */\n// Every `defineEvidenceProjection({...})` schema object below (this one and\n// the two further down) is itself a module-level `const`'s initializer --\n// the documented Stryker \"static\" covered-mutant false-Survivor\n// (ignoreStatic + perTest can't attribute a mutant evaluated once at module\n// load, even with real, passing test coverage; see [[feedback_stryker_mutation_score_formula]]\n// and data-cap's `reference-projections.ts` Batch 7, the identical pattern\n// in the sibling package). Every `disclaimer: () => evidenceDisclaimer()`\n// arrow below is hand-verified killed (mutating it to `() => undefined` and\n// running the real suite fails the matching \"carries the standing\n// disclaimer\" test) despite Stryker reporting it Survived.\n// Stryker disable next-line ObjectLiteral\nexport const configurationReference = defineEvidenceProjection<ConfigurationReference>({\n // Stryker disable next-line ArrowFunction\n disclaimer: () => evidenceDisclaimer(),\n entries: (evidence: EvidenceModel) => {\n const entries: ConfigurationReferenceEntry[] = []\n for (const contract of evidence.contract.contracts) {\n for (const variable of contract.variables) {\n entries.push({\n file: contract.file,\n exportName: contract.exportName,\n contractName: contract.contractName,\n key: variable.key,\n description: variable.description,\n owner: variable.owner ?? contract.owner,\n sensitivity: variable.sensitivity ?? contract.sensitivity,\n required: variable.required,\n hasDefault: variable.hasDefault,\n hasProcessor: variable.hasProcessor,\n hasValidator: variable.hasValidator,\n expiresAt: variable.expiresAt,\n active: contract.active,\n })\n }\n }\n return entries.sort(byContractThenKey)\n },\n})\n\n/** One owner and everything attributed to them. */\nexport interface OwnershipSummaryEntry {\n /** The owner string exactly as declared. */\n readonly owner: string\n /** Every variable this owner is the effective owner of, as `${contractName}.${key}`, sorted. */\n readonly variables: readonly string[]\n /** Every contract declaring this owner as its contract-level default, by display name, sorted. */\n readonly contracts: readonly string[]\n}\n\n/** The Ownership summary projection's output shape. */\nexport interface OwnershipSummary extends Record<string, unknown> {\n /** See {@link ConfigurationReference.disclaimer}. */\n readonly disclaimer: string\n /** One entry per distinct owner, sorted by owner. */\n readonly owners: readonly OwnershipSummaryEntry[]\n /** Every variable with no effective owner at all, as `${contractName}.${key}`, sorted. Named separately rather than bucketed under a synthetic `\"unowned\"` owner, so \"nobody owns this\" can never be mistaken for a real team name. */\n readonly unowned: readonly string[]\n}\n\n/**\n * Ownership summary: the inverse of Ownership Model's per-contract view --\n * who owns what, rolled up per owner, plus an explicit unowned list.\n */\n// Stryker disable next-line ObjectLiteral\nexport const ownershipSummary = defineEvidenceProjection<OwnershipSummary>({\n // Stryker disable next-line ArrowFunction\n disclaimer: () => evidenceDisclaimer(),\n owners: (evidence: EvidenceModel) => {\n const contracts = contractIndex(evidence.contract.contracts)\n const nameOf = (file: string, exportName: string): string =>\n contracts.get(`${file}#${exportName}`)?.contractName ?? exportName\n\n // Ownership Model has already resolved each variable's effective owner\n // (ADR 0028), so `ownerOf` reads it straight off rather than re-deriving.\n const variablesByOwner = groupVariablesByOwner(\n evidence.ownership.contracts,\n (_contract, variable) => variable.owner,\n )\n\n const contractsByOwner = new Map<string, string[]>()\n for (const contract of evidence.ownership.contracts) {\n if (contract.owner === undefined) continue\n const list = contractsByOwner.get(contract.owner) ?? []\n list.push(nameOf(contract.file, contract.exportName))\n contractsByOwner.set(contract.owner, list)\n }\n\n const owners = new Set([...variablesByOwner.keys(), ...contractsByOwner.keys()])\n return [...owners].sort().map((owner) => ({\n owner,\n variables: (variablesByOwner.get(owner) ?? [])\n .map(\n ({ contract, variable }) =>\n `${nameOf(contract.file, contract.exportName)}.${variable.key}`,\n )\n .sort(),\n contracts: (contractsByOwner.get(owner) ?? []).sort(),\n }))\n },\n unowned: (evidence: EvidenceModel) => {\n const contracts = contractIndex(evidence.contract.contracts)\n return evidence.ownership.unownedVariables\n .map((ref) => {\n const contractName =\n contracts.get(`${ref.file}#${ref.exportName}`)?.contractName ?? ref.exportName\n return `${contractName}.${ref.key}`\n })\n .sort()\n },\n})\n\n/** One contract- or variable-level `expiresAt` inside the configured window. */\nexport interface ExpiringSoonEntry {\n /** Root-relative, POSIX-separated path of the declaring contract. */\n readonly file: string\n readonly exportName: string\n /** The declaring contract's display name, resolved from Contract Model. */\n readonly contractName: string\n /** `undefined` for a contract-level expiry, set for a per-variable one. */\n readonly key: string | undefined\n /** The raw ISO date string, exactly as declared -- never reformatted. */\n readonly expiresAt: string\n /** Days remaining as of the run that produced this evidence; negative when already expired. */\n readonly daysRemaining: number\n /** `true` when `daysRemaining` is negative -- the deadline has already passed. */\n readonly expired: boolean\n /** How to obtain a replacement value, if the declaration says. */\n readonly refreshInstructions: string | undefined\n /** Effective owner, so a reader knows who to chase without a second lookup. */\n readonly owner: string | undefined\n}\n\n/** The Expiring-Soon projection's output shape. */\nexport interface ExpiringSoonReport extends Record<string, unknown> {\n /** See {@link ConfigurationReference.disclaimer}. */\n readonly disclaimer: string\n /** Every entry inside the window, soonest-first (already-expired entries lead, most-overdue first). */\n readonly entries: readonly ExpiringSoonEntry[]\n /** How many of `entries` are already past their `expiresAt`. */\n readonly expiredCount: number\n}\n\n/**\n * Expiring-Soon report: Lifecycle Model's `expiring` view, joined with\n * ownership and refresh instructions so a reader can act on a row without\n * cross-referencing three other models by hand.\n *\n * @remarks\n * The window itself was applied upstream, when Lifecycle Model was built --\n * this projection deliberately does not re-filter by a date of its own.\n * Recomputing \"soon\" here would make the projection's answer depend on when\n * it happened to be *read* rather than when the evidence was *generated*,\n * which is exactly the reproducibility property the Evidence Model exists to\n * preserve.\n */\n// Stryker disable next-line ObjectLiteral\nexport const expiringSoonReport = defineEvidenceProjection<ExpiringSoonReport>({\n // Stryker disable next-line ArrowFunction\n disclaimer: () => evidenceDisclaimer(),\n entries: (evidence: EvidenceModel) => {\n const contracts = contractIndex(evidence.contract.contracts)\n const ownerByVariable = new Map<string, string | undefined>()\n for (const contract of evidence.ownership.contracts)\n for (const variable of contract.variables)\n ownerByVariable.set(\n `${contract.file}#${contract.exportName}#${variable.key}`,\n variable.owner,\n )\n\n return evidence.lifecycle.expiring.map((entry): ExpiringSoonEntry => {\n const contract = contracts.get(`${entry.file}#${entry.exportName}`)\n // Mutating `entry.key === undefined` to `false` here is behaviorally\n // equivalent, not a real gap: `ContractModelVariable[\"key\"]` is always\n // a non-empty string, so `v.key === entry.key` can never be true when\n // `entry.key` is `undefined` -- `.find()` still returns `undefined`\n // either way. Hand-verified: mutating this and running the real suite\n // (`vitest run test/build/reference-projections.test.ts`) passes\n // unchanged. Restructuring into an `if`/guard would only relocate the\n // same equivalence onto a different mutant, not remove it.\n // Stryker disable ConditionalExpression\n const variable =\n entry.key === undefined ? undefined : contract?.variables.find((v) => v.key === entry.key)\n // Stryker restore ConditionalExpression\n return {\n file: entry.file,\n exportName: entry.exportName,\n contractName: contract?.contractName ?? entry.exportName,\n key: entry.key,\n expiresAt: entry.expiresAt,\n daysRemaining: entry.daysRemaining,\n expired: entry.daysRemaining < 0,\n refreshInstructions: variable?.refreshInstructions,\n owner:\n entry.key === undefined\n ? contract?.owner\n : (ownerByVariable.get(`${entry.file}#${entry.exportName}#${entry.key}`) ??\n contract?.owner),\n }\n })\n },\n // Same static covered-mutant false-Survivor as the `disclaimer` arrows\n // above -- hand-verified killed (mutating this whole arrow to `() =>\n // undefined` fails the \"expiredCount\" assertions in every test above).\n // Stryker disable next-line ArrowFunction\n expiredCount: (evidence: EvidenceModel) =>\n evidence.lifecycle.expiring.filter((e) => e.daysRemaining < 0).length,\n})\n","import type { ContractModelContract, ContractModelVariable } from \"./contract-model.js\"\nimport { governanceFieldsOf, type EnvGovernanceFields } from \"./governance-fields.js\"\nimport type { DiscoveredVariableEvidence } from \"./parse.js\"\nimport { evidenceDisclaimer, evidenceProjectionNote, generatedBanner } from \"./generated-banner.js\"\nimport { humanizeKey, renderMetadataValue } from \"./humanize-key.js\"\nimport {\n effectiveAuditRequired,\n effectiveDataResidency,\n effectiveLegalBasis,\n effectiveOwner,\n effectivePurpose,\n effectiveRetention,\n effectiveSensitivity,\n} from \"./link.js\"\nimport { mustGet } from \"./map-utils.js\"\nimport { groupVariablesByOwner } from \"./reference-projections.js\"\n\n/** Identifies a contract with no linked `documentEnv()` call at all. `file`'s absolute-vs-relative convention depends on where a given instance comes from -- see the specific field using this type (`DocumentationFindings.undocumentedContracts` is absolute; `RenderDocsOptions.undocumentedContracts` must be root-relative, matching the `ContractModel`-shaped `contracts` it's compared against). */\nexport interface UndocumentedContractRef {\n readonly file: string\n /** The contract's exported binding name. */\n readonly exportName: string\n}\n/** Identifies a schema variable with no matching entry in its contract's linked documentation. See {@link UndocumentedContractRef}'s own note on `file`. */\nexport interface UndocumentedVariableRef {\n readonly file: string\n /** The contract's exported binding name. */\n readonly exportName: string\n /** The undocumented environment variable name. */\n readonly key: string\n}\n/** One contract- or variable-level `expiresAt` falling within the configured \"expiring soon\" window. */\nexport interface ExpiringEntry {\n /** Absolute path of the file declaring the contract. */\n readonly file: string\n /** The contract's exported binding name. */\n readonly exportName: string\n /** `undefined` for a contract-level `expiresAt`, set for a per-variable one. */\n readonly key: string | undefined\n /** The raw ISO date string, unparsed. */\n readonly expiresAt: string\n /** Days from `now` until expiry; negative when already expired. */\n readonly daysRemaining: number\n}\n\n/** Options for {@link renderDocs}. */\nexport interface RenderDocsOptions {\n /** How many days out counts as \"expiring soon\" in the lifecycle report and security review. */\n readonly expiringWithinDays: number\n /** Contracts with no linked `documentEnv()` call at all. `file` must be root-relative, POSIX-separated -- matching `contracts`' own `ContractModel` convention, since this is matched against it by identity. */\n readonly undocumentedContracts: readonly UndocumentedContractRef[]\n /** Schema variables with no matching entry in their contract's linked documentation. `file` must be root-relative, POSIX-separated -- see `undocumentedContracts`. */\n readonly undocumentedVariables: readonly UndocumentedVariableRef[]\n /** Timestamp rendered into the header and used for expiry/days-remaining math. */\n readonly generatedAt: Date\n /** Content already at `docs.location`, if any -- used only for the \"changes since last report\" summary. */\n readonly previousContent: string | undefined\n}\n\n/**\n * Parses `expiresAt` as a real date.\n *\n * @remarks\n * Malformed strings are silently ignored (return `undefined`) rather than throwing -- same\n * \"warn/skip, never guess\" policy as the rest of the generator. Exported so `live-expirations.ts`\n * can validate live override values against the exact same rule used for static `expiresAt`.\n */\nexport function parseIsoDate(value: string): Date | undefined {\n const date = new Date(value)\n return Number.isNaN(date.getTime()) ? undefined : date\n}\n\nconst MS_PER_DAY = 86_400_000\n\n/** Days from `now` until `date`; negative when `date` is already in the past. The one place this arithmetic lives -- every wall-clock-relative computation in this file goes through it. */\nfunction daysRemainingFrom(date: Date, now: Date): number {\n return Math.ceil((date.getTime() - now.getTime()) / MS_PER_DAY)\n}\n\n/** The minimal shape {@link computeExpiringEntries} needs -- structural, not pinned to `DiscoveredContract`, so the exact same rule serves both `LinkResult`'s absolute-path contracts (`generate-documentation.ts`'s `documentation.expiringSoon`, Stable tier) and `ContractModel`'s root-relative ones, whichever a caller already has on hand. */\ninterface ExpiryBearingContract {\n readonly file: string\n readonly exportName: string\n readonly expiresAt: string | undefined\n readonly variables: readonly { readonly key: string; readonly expiresAt: string | undefined }[]\n}\n\n/**\n * Computes every contract- or variable-level `expiresAt` within `expiringWithinDays` of `now`, sorted soonest-first.\n */\nexport function computeExpiringEntries(\n contracts: readonly ExpiryBearingContract[],\n expiringWithinDays: number,\n now: Date,\n): ExpiringEntry[] {\n const entries: ExpiringEntry[] = []\n\n for (const contract of contracts) {\n // `parseIsoDate()` treats every falsy string input (`undefined` or `\"\"`,\n // the only two falsy values `expiresAt: string | undefined` can hold)\n // identically -- `new Date(x).getTime()` is `NaN` either way, so `date`\n // ends up `undefined` regardless, and the `if (date)` guard just below\n // already skips pushing an entry. Bypassing this outer guard is\n // therefore runtime-equivalent, but still load-bearing for TypeScript's\n // own narrowing of `contract.expiresAt` to `string` for the\n // `parseIsoDate()` call inside (see the identical `tsc`-narrowing\n // dependency already documented for `parse.ts`/`generate-env-artifacts.ts`\n // this same drive). Hand-verified: bypassing it and running the real\n // whole-package suite (`vitest run`) only breaks the two `tsc`-backed\n // json-schema freshness tests, no runtime-behavior assertion.\n // Stryker disable next-line ConditionalExpression\n if (contract.expiresAt) {\n const date = parseIsoDate(contract.expiresAt)\n if (date) {\n const daysRemaining = daysRemainingFrom(date, now)\n if (daysRemaining <= expiringWithinDays) {\n entries.push({\n file: contract.file,\n exportName: contract.exportName,\n key: undefined,\n expiresAt: contract.expiresAt,\n daysRemaining,\n })\n }\n }\n }\n for (const variable of contract.variables) {\n // Same equivalence as the contract-level guard above: `parseIsoDate()`\n // treats every falsy string identically, and the very next `if\n // (!date) continue` already catches the result -- but this bypass\n // still relies on TypeScript's own narrowing of `variable.expiresAt`\n // to `string` for the `parseIsoDate()` call on the next line.\n // Hand-verified: bypassing it and running the real whole-package suite\n // (`vitest run`) only breaks the two `tsc`-backed json-schema\n // freshness tests, no runtime-behavior assertion.\n // Stryker disable next-line ConditionalExpression\n if (!variable.expiresAt) continue\n const date = parseIsoDate(variable.expiresAt)\n if (!date) continue\n const daysRemaining = daysRemainingFrom(date, now)\n if (daysRemaining <= expiringWithinDays) {\n entries.push({\n file: contract.file,\n exportName: contract.exportName,\n key: variable.key,\n expiresAt: variable.expiresAt,\n daysRemaining,\n })\n }\n }\n }\n\n return entries.sort((a, b) => a.daysRemaining - b.daysRemaining)\n}\n\n/**\n * Same data `renderCatalog()` renders to Markdown for one variable, reshaped for JSON/\n * programmatic consumers instead of prose.\n *\n * @see `ContractModelVariable` (`contract-model.ts`) -- this same declared variable's canonical\n * starting point. Plain reference, not `{@link}`: this type is intentionally not part of the\n * public surface (see `typedoc.json`'s `intentionallyNotExported`).\n */\ninterface CatalogVariable extends EnvGovernanceFields {\n readonly description: string | undefined\n readonly refreshInstructions: string | undefined\n readonly setupInstructions: string | undefined\n readonly required: boolean | undefined\n readonly hasDefault: boolean\n readonly hasProcessor: boolean\n readonly processorReturnType: string | undefined\n readonly hasValidator: boolean\n readonly documented: boolean\n /** The variable's declared validation context, if any -- see ADR 0022. Participation data, not documentation: describes when `validateEnv()` processes this variable, not who may access it or what a bundler includes. */\n readonly context: string | undefined\n /** The `evidence` sub-object from this variable's linked documentation -- re-verified every run, unlike every declared-only field above. See ADR 0037. */\n readonly evidence: DiscoveredVariableEvidence | undefined\n}\n\nexport interface CatalogContract extends EnvGovernanceFields {\n readonly file: string\n readonly exportName: string\n readonly contractName: string\n readonly active: boolean\n readonly documented: boolean\n readonly category: string | undefined\n readonly exclusiveGroup: string | undefined\n /** Keyed by variable name -- unique within one contract (a schema\n * object-literal property name), unlike `contractName` at the top level. */\n readonly variables: Readonly<Record<string, CatalogVariable>>\n}\n\n/**\n * Same data `renderCatalog()` renders to Markdown, reshaped for JSON/\n * programmatic consumers instead of prose. See `GenerateDocumentationResult.catalog`.\n */\nexport function buildCatalog(contracts: readonly ContractModelContract[]): CatalogContract[] {\n return sortedContracts(contracts).map((contract) => {\n const variables: Record<string, CatalogVariable> = {}\n for (const variable of contract.variables) {\n variables[variable.key] = {\n description: variable.description,\n owner: effectiveOwner(contract, variable),\n sensitivity: effectiveSensitivity(contract, variable),\n expiresAt: variable.expiresAt,\n refreshInstructions: variable.refreshInstructions,\n setupInstructions: variable.setupInstructions,\n required: variable.required,\n hasDefault: variable.hasDefault,\n hasProcessor: variable.hasProcessor,\n processorReturnType: variable.processorReturnType,\n hasValidator: variable.hasValidator,\n documented: variable.documented,\n context: variable.context,\n purpose: effectivePurpose(contract, variable),\n legalBasis: effectiveLegalBasis(contract, variable),\n retention: effectiveRetention(contract, variable),\n dataResidency: effectiveDataResidency(contract, variable),\n auditRequired: effectiveAuditRequired(contract, variable),\n metadata: variable.metadata,\n evidence: variable.evidence,\n }\n }\n\n return {\n file: contract.file,\n exportName: contract.exportName,\n contractName: contract.contractName,\n active: contract.active,\n documented: contract.documented,\n category: contract.category,\n exclusiveGroup: contract.exclusiveGroup,\n ...governanceFieldsOf(contract),\n variables,\n }\n })\n}\n\n// Every module-level regex pattern in this file is inlined at its one call\n// site, not a shared `const` -- Stryker marks a module-level regex literal\n// `static: true` (evaluated once at import time), which produces a false\n// \"Survived\" on a mutant that's genuinely, heavily test-covered (the same\n// limitation already fixed for `cli/index.ts`'s dispatch tables/`HELP_TEXT`\n// and `parse.ts`'s `ENV_KEY_PATTERN` this same drive).\n\n/** Every variable key that appeared as a catalog heading in a previously-generated docs file. Exported for testing. */\nexport function extractPreviouslyDocumentedKeys(previousContent: string): Set<string> {\n const keys = new Set<string>()\n for (const match of previousContent.matchAll(/^### `([A-Za-z_][A-Za-z0-9_]*)`$/gm)) {\n // The pattern's own capture group (`[A-Za-z_][A-Za-z0-9_]*`) requires at\n // least one character, so `match[1]` can never be empty/falsy on a real\n // match -- this is a pure `string | undefined` -> `string` type guard,\n // not a real runtime branch. Hand-verified: bypassing it (`match[1]!`)\n // and running the real whole-package suite (`vitest run`) passes\n // unchanged.\n // Stryker disable next-line ConditionalExpression\n if (match[1]) keys.add(match[1])\n }\n return keys\n}\n\n/**\n * Every variable key that was documented under an *active* contract in a\n * previously-generated docs file -- walks the same `- Active: yes/no`\n * marker `renderCatalog` always emits immediately after each `## <contract>`\n * heading, so a key already inactive last time (a permanently-dormant\n * contract, e.g. behind an unused feature flag) is excluded even though it\n * still appears as a `### \\`KEY\\`` heading. Exported for testing.\n */\nexport function extractPreviouslyActiveKeys(previousContent: string): Set<string> {\n const keys = new Set<string>()\n let currentContractActive = false\n for (const line of previousContent.split(\"\\n\")) {\n const activeMatch = /^- Active: (yes|no)$/.exec(line)\n if (activeMatch) {\n currentContractActive = activeMatch[1] === \"yes\"\n continue\n }\n const headingMatch = /^### `([A-Za-z_][A-Za-z0-9_]*)`$/.exec(line)\n if (headingMatch && currentContractActive) {\n keys.add(headingMatch[1])\n }\n }\n return keys\n}\n\ninterface ChangeSummary {\n readonly added: readonly string[]\n readonly removed: readonly string[]\n readonly commented: readonly string[]\n}\n\n/**\n * Added = newly discovered since last report. Removed = previously\n * documented, no longer discovered at all. Commented = backed by an *active*\n * contract last report, still discovered, but no longer backed by any active\n * contract -- i.e. a fresh active-to-inactive transition, not merely \"still\n * inactive.\" A key already inactive/commented last time is excluded so a\n * permanently-dormant contract's variable isn't reported as a change on\n * every single regeneration.\n *\n * `previousContent === undefined` (no prior report exists at all -- a true\n * first-ever generation) is treated the same as \"nothing changed\" (every\n * field empty), not as \"no summary at all\" the way an earlier version of\n * this function did. That earlier behavior omitted the whole \"Changes since\n * last report\" section on a first run -- but `checkEnvArtifacts()` (ADR\n * 0016) always re-renders using whatever is *currently on disk* as\n * `previousContent`, including a file this very function just wrote. For\n * `--check` to ever agree with a real write, `renderDocs()` must be a fixed\n * point under that self-feeding: regenerating with a file's own content as\n * `previousContent` must reproduce that same file byte-for-byte. Omitting\n * the section on first write broke exactly that -- the first real write\n * had no section, but feeding that same file back in as `previousContent`\n * produces a real (all-empty, \"No changes.\") summary, since this function\n * only ever re-parses the Catalog's own `### \\`KEY\\`` headings, never the\n * Changes section's own prior text. Rendering \"No changes.\" immediately,\n * even on a first-ever report, is the only phrasing that round-trips.\n */\nfunction computeChangeSummary(\n contracts: readonly ContractModelContract[],\n previousContent: string | undefined,\n): ChangeSummary {\n if (previousContent === undefined) return { added: [], removed: [], commented: [] }\n const previousKeys = extractPreviouslyDocumentedKeys(previousContent)\n const previousActiveKeys = extractPreviouslyActiveKeys(previousContent)\n\n const currentKeys = new Set<string>()\n const currentActiveKeys = new Set<string>()\n for (const contract of contracts) {\n for (const variable of contract.variables) {\n currentKeys.add(variable.key)\n if (contract.active) currentActiveKeys.add(variable.key)\n }\n }\n\n return {\n added: [...currentKeys].filter((k) => !previousKeys.has(k)).sort(),\n removed: [...previousKeys].filter((k) => !currentKeys.has(k)).sort(),\n commented: [...previousActiveKeys]\n .filter((k) => currentKeys.has(k) && !currentActiveKeys.has(k))\n .sort(),\n }\n}\n\nfunction slugify(text: string): string {\n // The `+` quantifiers on the SECOND `.replace()` below are unobservable:\n // the FIRST replace's own `+` already collapses every run of\n // non-identifier characters (dashes included, since a literal `-` isn't in\n // `[a-z0-9_]` either) into a single `-`, so the second regex can never\n // actually see 2+ consecutive dashes at either end to strip -- there is\n // always at most one. Hand-verified: dropping both `+`s and running the\n // real whole-package suite (`vitest run`) passes unchanged. Unscoped\n // disable/restore (not `next-line`) because this is one multi-line\n // statement -- `next-line` didn't reliably attach here.\n // Stryker disable Regex\n return (\n text\n .toLowerCase()\n .replace(/[^a-z0-9_]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\") || \"section\"\n )\n // Stryker restore Regex\n}\n\n/** Assigns each heading a stable, collision-free anchor -- duplicate variable names across contracts (a supported feature) would otherwise collide on a heading-derived anchor. */\nclass AnchorRegistry {\n private readonly used = new Map<string, number>()\n private readonly assigned = new Map<object, string>()\n\n anchorFor(target: object, baseText: string): string {\n const existing = this.assigned.get(target)\n if (existing) return existing\n const base = slugify(baseText)\n const count = this.used.get(base) ?? 0\n this.used.set(base, count + 1)\n const anchor = count === 0 ? base : `${base}-${count}`\n this.assigned.set(target, anchor)\n return anchor\n }\n}\n\nfunction mdLink(text: string, anchor: string): string {\n return `[${text}](#${anchor})`\n}\n\nfunction sortedContracts(contracts: readonly ContractModelContract[]): ContractModelContract[] {\n return [...contracts].sort((a, b) => a.contractName.localeCompare(b.contractName))\n}\n\n// ---------------------------------------------------------------------------\n// Section 0 -- header, change summary, table of contents\n// ---------------------------------------------------------------------------\n\nfunction renderHeader(\n contracts: readonly ContractModelContract[],\n options: RenderDocsOptions,\n anchors: AnchorRegistry,\n hasOwnership: boolean,\n hasDuplicates: boolean,\n hasLifecycle: boolean,\n): string[] {\n const lines = [\n generatedBanner(\"markdown\"),\n \"\",\n `> ${evidenceDisclaimer()}`,\n \"\",\n `> ${evidenceProjectionNote()}`,\n \"\",\n \"# Environment Variables\",\n \"\",\n \"_Produced by `env-cap --docs`._\",\n \"\",\n `_Generated ${options.generatedAt.toISOString()}_`,\n \"\",\n ]\n\n const summary = computeChangeSummary(contracts, options.previousContent)\n lines.push(\"## Changes since last report\", \"\")\n if (\n summary.added.length === 0 &&\n summary.removed.length === 0 &&\n summary.commented.length === 0\n ) {\n lines.push(\"No changes.\", \"\")\n } else {\n if (summary.added.length > 0)\n lines.push(`- **Added:** ${summary.added.map((k) => `\\`${k}\\``).join(\", \")}`)\n if (summary.removed.length > 0)\n lines.push(`- **Removed:** ${summary.removed.map((k) => `\\`${k}\\``).join(\", \")}`)\n if (summary.commented.length > 0)\n lines.push(\n `- **No longer required (inactive):** ${summary.commented.map((k) => `\\`${k}\\``).join(\", \")}`,\n )\n lines.push(\"\")\n }\n\n lines.push(\"## Table of contents\", \"\", `- ${mdLink(\"Catalog\", \"catalog\")}`)\n for (const contract of sortedContracts(contracts)) {\n lines.push(\n ` - ${mdLink(contract.contractName, anchors.anchorFor(contract, `contract-${contract.contractName}`))}`,\n )\n }\n if (hasOwnership) lines.push(`- ${mdLink(\"Ownership matrix\", \"ownership-matrix\")}`)\n if (hasDuplicates) lines.push(`- ${mdLink(\"Dependency graph\", \"dependency-graph\")}`)\n if (hasLifecycle) lines.push(`- ${mdLink(\"Lifecycle report\", \"lifecycle-report\")}`)\n lines.push(`- ${mdLink(\"Security review\", \"security-review\")}`, \"\")\n\n return lines\n}\n\n// ---------------------------------------------------------------------------\n// Section 1 -- comprehensive catalog\n// ---------------------------------------------------------------------------\n\nfunction renderCatalog(\n contracts: readonly ContractModelContract[],\n anchors: AnchorRegistry,\n undocumented: RenderDocsOptions[\"undocumentedContracts\"],\n): string[] {\n const lines: string[] = [\"## Catalog\", \"\", '<a id=\"catalog\"></a>', \"\"]\n const undocumentedByIdentity = new Set(undocumented.map((u) => `${u.file}#${u.exportName}`))\n\n // Only shown when at least one variable actually declares a context --\n // keeps generated docs byte-identical for every project not using this\n // feature, and avoids explaining a concept that doesn't appear below.\n const usesValidationContexts = contracts.some((c) => c.variables.some((v) => v.context))\n if (usesValidationContexts) {\n lines.push(\n \"> Validation contexts describe when validation participates. They do not restrict \" +\n \"access to values, and they do not remove a variable's schema (or its `default` \" +\n \"value) from wherever this manifest is imported.\",\n \"\",\n )\n }\n\n for (const contract of sortedContracts(contracts)) {\n // `anchorFor()` caches by TARGET OBJECT (`this.assigned.get(target)`),\n // and `renderHeader()`'s own TOC loop already calls\n // `anchorFor(contract, ...)` with this exact same baseText for every\n // contract, always BEFORE renderCatalog() runs (see renderDocs()'s call\n // order) -- so this call's own `baseText` argument can never actually\n // matter; the cached anchor from the TOC call always wins. Hand-verified:\n // replacing the baseText argument here with `` `` `` (empty) and running\n // the real whole-package suite (`vitest run`) passes unchanged.\n // Stryker disable next-line StringLiteral\n lines.push(`<a id=\"${anchors.anchorFor(contract, `contract-${contract.contractName}`)}\"></a>`)\n lines.push(`## ${contract.contractName}`, \"\", `Source: \\`${contract.file}\\``)\n if (undocumentedByIdentity.has(`${contract.file}#${contract.exportName}`)) {\n lines.push(\"\", \"> ⚠️ **Undocumented.** No `documentEnv()` call is linked to this contract.\")\n }\n lines.push(`- Active: ${contract.active ? \"yes\" : \"no\"}`)\n if (contract.category !== undefined) lines.push(`- Category: ${contract.category}`)\n if (contract.exclusiveGroup !== undefined)\n lines.push(`- Exclusive group: ${contract.exclusiveGroup}`)\n if (contract.owner !== undefined) lines.push(`- Owner: ${contract.owner}`)\n if (contract.sensitivity !== undefined) lines.push(`- Sensitivity: ${contract.sensitivity}`)\n if (contract.expiresAt !== undefined) lines.push(`- Expires: ${contract.expiresAt}`)\n if (contract.purpose !== undefined) lines.push(`- Purpose: ${contract.purpose}`)\n if (contract.legalBasis !== undefined) lines.push(`- Legal basis: ${contract.legalBasis}`)\n if (contract.retention !== undefined) lines.push(`- Retention: ${contract.retention}`)\n if (contract.dataResidency !== undefined)\n lines.push(`- Data residency: ${renderMetadataValue(contract.dataResidency)}`)\n if (contract.auditRequired !== undefined)\n lines.push(`- Audit required: ${contract.auditRequired ? \"yes\" : \"no\"}`)\n if (contract.metadata) {\n for (const [metaKey, metaValue] of Object.entries(contract.metadata)) {\n lines.push(`- ${humanizeKey(metaKey)}: ${renderMetadataValue(metaValue)}`)\n }\n }\n lines.push(\"\")\n\n // Two-way compare: `variable.key` is a schema object-literal property\n // name, always unique within one contract, so `a.key === b.key` can\n // never happen here -- `<` vs `<=` is therefore unobservable (the tie\n // branch this would otherwise distinguish is unreachable). Hand-verified:\n // switching to `<=` and running the real whole-package suite\n // (`vitest run`) passes unchanged.\n // Stryker disable next-line EqualityOperator\n for (const variable of [...contract.variables].sort((a, b) => (a.key < b.key ? -1 : 1))) {\n // Same equivalence as the contract anchor above: `renderDependencyGraph()`\n // (called before `renderCatalog()` in `renderDocs()`) already calls\n // `anchorFor(variable, ...)` with this exact same baseText for EVERY\n // variable (it lists all of them, not just owned ones), so this call's\n // own baseText can never matter -- the cache always wins. Hand-verified:\n // replacing it with `` `` `` and running the real whole-package suite\n // (`vitest run`) passes unchanged.\n // Stryker disable StringLiteral\n lines.push(\n `<a id=\"${anchors.anchorFor(variable, `${contract.contractName}-${variable.key}`)}\"></a>`,\n )\n // Stryker restore StringLiteral\n lines.push(`### \\`${variable.key}\\``, \"\")\n\n // Bypassing this guard when `variable.description` is undefined would\n // push `undefined` (joined as \"\" by `.join(\"\\n\")`, same as the real\n // `\"\"` beside it) -- the resulting extra blank-ish line only ever\n // shows up as 3+ consecutive newlines in the final joined document,\n // which `renderDocs()`'s own trailing `.replace(/\\n{3,}/g, \"\\n\\n\")`\n // always collapses back down regardless (same reasoning already\n // established for `usage-report.ts`'s identical cleanup regex this\n // drive). Still load-bearing for TypeScript's own narrowing of\n // `variable.description` to `string` for the `lines.push()` call.\n // Hand-verified: bypassing it and running the real whole-package suite\n // (`vitest run`) only breaks the two `tsc`-backed json-schema\n // freshness tests, no runtime-behavior assertion.\n // Stryker disable next-line ConditionalExpression\n if (variable.description) lines.push(variable.description, \"\")\n if (!variable.documented) lines.push(\"> ⚠️ **Undocumented.**\", \"\")\n\n lines.push(\n `- Default: ${variable.hasDefault ? \"yes\" : \"no\"}`,\n `- Processor: ${variable.hasProcessor ? \"yes\" : \"no\"}`,\n `- Validator: ${variable.hasValidator ? \"yes\" : \"no\"}`,\n )\n if (variable.context !== undefined) lines.push(`- Validation context: ${variable.context}`)\n const owner = effectiveOwner(contract, variable)\n if (owner !== undefined) lines.push(`- Owner: ${owner}`)\n const sensitivity = effectiveSensitivity(contract, variable)\n if (sensitivity !== undefined) lines.push(`- Sensitivity: ${sensitivity}`)\n if (variable.expiresAt !== undefined) lines.push(`- Expires: ${variable.expiresAt}`)\n if (variable.setupInstructions !== undefined)\n lines.push(`- Setup instructions: ${variable.setupInstructions}`)\n if (variable.refreshInstructions !== undefined)\n lines.push(`- Refresh instructions: ${variable.refreshInstructions}`)\n if (variable.required !== undefined)\n lines.push(`- Required: ${variable.required ? \"yes\" : \"no\"}`)\n const purpose = effectivePurpose(contract, variable)\n if (purpose !== undefined) lines.push(`- Purpose: ${purpose}`)\n const legalBasis = effectiveLegalBasis(contract, variable)\n if (legalBasis !== undefined) lines.push(`- Legal basis: ${legalBasis}`)\n const retention = effectiveRetention(contract, variable)\n if (retention !== undefined) lines.push(`- Retention: ${retention}`)\n const dataResidency = effectiveDataResidency(contract, variable)\n if (dataResidency !== undefined)\n lines.push(`- Data residency: ${renderMetadataValue(dataResidency)}`)\n const auditRequired = effectiveAuditRequired(contract, variable)\n if (auditRequired !== undefined)\n lines.push(`- Audit required: ${auditRequired ? \"yes\" : \"no\"}`)\n const dynamicAccess = variable.evidence?.dynamicAccess\n if (dynamicAccess && dynamicAccess.length > 0)\n lines.push(`- Dynamic access: ${dynamicAccess.join(\", \")}`)\n for (const [metaKey, metaValue] of Object.entries(variable.metadata ?? {})) {\n lines.push(`- ${humanizeKey(metaKey)}: ${renderMetadataValue(metaValue)}`)\n }\n lines.push(\"\")\n }\n }\n\n return lines\n}\n\n// ---------------------------------------------------------------------------\n// Section 2 -- ownership matrix (omitted if nothing sets `owner`)\n// ---------------------------------------------------------------------------\n\n/**\n * Groups via the same `groupVariablesByOwner()` the public\n * `ownershipSummary` reference projection uses (`reference-projections.ts`),\n * so env-cap's own rendered matrix and the projection a consumer reads are\n * the same grouping by construction, not two implementations kept in sync by\n * hand. Only the link/label formatting below is this renderer's own.\n */\nfunction renderOwnershipMatrix(\n contracts: readonly ContractModelContract[],\n anchors: AnchorRegistry,\n): string[] {\n const grouped = groupVariablesByOwner(sortedContracts(contracts), effectiveOwner)\n const byOwner = new Map<string, string[]>()\n for (const [owner, entries] of grouped) {\n byOwner.set(\n owner,\n entries.map(({ contract, variable }) =>\n mdLink(\n `\\`${variable.key}\\` (${contract.contractName})`,\n anchors.anchorFor(variable, `${contract.contractName}-${variable.key}`),\n ),\n ),\n )\n }\n if (byOwner.size === 0) return []\n\n const lines = [\n \"## Ownership matrix\",\n \"\",\n '<a id=\"ownership-matrix\"></a>',\n \"\",\n \"| Owner | Variables |\",\n \"|---|---|\",\n ]\n for (const owner of [...byOwner.keys()].sort()) {\n lines.push(`| ${owner} | ${mustGet(byOwner, owner).join(\", \")} |`)\n }\n lines.push(\"\")\n return lines\n}\n\n// ---------------------------------------------------------------------------\n// Section 3 -- dependency graph (one row per unique variable name)\n// ---------------------------------------------------------------------------\n\nfunction renderDependencyGraph(\n contracts: readonly ContractModelContract[],\n anchors: AnchorRegistry,\n): { lines: string[]; hasDuplicates: boolean } {\n const byKey = new Map<\n string,\n { contract: ContractModelContract; variable: ContractModelVariable }[]\n >()\n for (const contract of contracts) {\n for (const variable of contract.variables) {\n const list = byKey.get(variable.key) ?? []\n list.push({ contract, variable })\n byKey.set(variable.key, list)\n }\n }\n\n const hasDuplicates = [...byKey.values()].some((declarations) => declarations.length > 1)\n const lines = [\n \"## Dependency graph\",\n \"\",\n '<a id=\"dependency-graph\"></a>',\n \"\",\n \"One row per unique variable name; more than one location means more than one feature declares it (see the package README's \\\"Duplicate variables\\\" section for how that's handled at runtime).\",\n \"\",\n \"| Variable | Declared in |\",\n \"|---|---|\",\n ]\n\n for (const key of [...byKey.keys()].sort()) {\n const declarations = mustGet(byKey, key)\n const locations = declarations\n .map(({ contract, variable }) =>\n mdLink(\n `${contract.contractName} (\\`${contract.file}\\`)`,\n anchors.anchorFor(variable, `${contract.contractName}-${variable.key}`),\n ),\n )\n .join(\", \")\n lines.push(`| \\`${key}\\` | ${locations} |`)\n }\n lines.push(\"\")\n\n return { lines, hasDuplicates }\n}\n\n// ---------------------------------------------------------------------------\n// Section 4 -- lifecycle report\n// ---------------------------------------------------------------------------\n\nfunction renderLifecycleReport(\n contracts: readonly ContractModelContract[],\n anchors: AnchorRegistry,\n expiringWithinDays: number,\n now: Date,\n): { lines: string[]; hasLifecycle: boolean } {\n const rows: string[] = []\n for (const contract of sortedContracts(contracts)) {\n for (const variable of contract.variables) {\n const owner = effectiveOwner(contract, variable)\n if (\n variable.expiresAt === undefined &&\n owner === undefined &&\n variable.refreshInstructions === undefined\n )\n continue\n const expiresAt = variable.expiresAt\n const expiry = expiresAt ? parseIsoDate(expiresAt) : undefined\n let expiresCell = expiresAt ?? \"--\"\n if (expiry && expiresAt) {\n const daysRemaining = daysRemainingFrom(expiry, now)\n if (daysRemaining < 0)\n expiresCell = `${expiresAt} (**expired ${Math.abs(daysRemaining)}d ago**)`\n else if (daysRemaining <= expiringWithinDays)\n expiresCell = `${expiresAt} (**${daysRemaining}d remaining**)`\n }\n\n // Same anchor-cache equivalence as renderCatalog's own two anchor\n // calls above: `renderDependencyGraph()` (called before\n // `renderLifecycleReport()` in `renderDocs()`) already calls\n // `anchorFor(variable, ...)` with this exact same baseText for every\n // variable, so this call's own baseText can never matter. Hand-verified:\n // replacing it with `` `` `` and running the real whole-package suite\n // (`vitest run`) passes unchanged.\n // Stryker disable StringLiteral\n rows.push(\n `| ${mdLink(`\\`${variable.key}\\``, anchors.anchorFor(variable, `${contract.contractName}-${variable.key}`))} | ${owner ?? \"--\"} | ${expiresCell} | ${variable.refreshInstructions ?? \"--\"} |`,\n )\n // Stryker restore StringLiteral\n }\n }\n if (rows.length === 0) return { lines: [], hasLifecycle: false }\n\n const lines = [\n \"## Lifecycle report\",\n \"\",\n '<a id=\"lifecycle-report\"></a>',\n \"\",\n \"| Variable | Owner | Expires | Refresh instructions |\",\n \"|---|---|---|---|\",\n ...rows,\n \"\",\n ]\n return { lines, hasLifecycle: true }\n}\n\n// ---------------------------------------------------------------------------\n// Section 5 -- security review\n// ---------------------------------------------------------------------------\n\n/** Every number the security review reports, as structured data instead of only rendered Markdown text. */\nexport interface SecurityReviewCounters {\n readonly totalContracts: number\n readonly totalVariableDeclarations: number\n readonly activeVariableDeclarations: number\n readonly uniqueVariableNames: number\n readonly expiresAtSetCount: number\n readonly expiredCount: number\n readonly expiringSoonCount: number\n readonly requiredCount: number\n readonly refreshInstructionsCount: number\n readonly noOwnerCount: number\n readonly duplicateVariableNameCount: number\n readonly undocumentedContractCount: number\n readonly undocumentedVariableCount: number\n}\n\n/**\n * Computes every number `renderSecurityReview()` reports, as real data.\n *\n * @remarks\n * Previously this arithmetic lived entirely inside the renderer as closure\n * locals that only ever became interpolated Markdown text -- no exported\n * type backed any of it, so nothing downstream (the `--json` envelope, a CI\n * gate, a future Finding Model adapter) could consume it as data. Extracted\n * so it can be reused wherever these facts are needed, not just prose.\n */\nexport function computeSecurityReviewCounters(\n contracts: readonly ContractModelContract[],\n expiringWithinDays: number,\n now: Date,\n undocumentedContractCount: number,\n undocumentedVariableCount: number,\n): SecurityReviewCounters {\n let totalVariableDeclarations = 0\n let activeVariableDeclarations = 0\n const uniqueKeys = new Set<string>()\n const keyContractCount = new Map<string, number>()\n let expiresAtSetCount = 0\n let expiredCount = 0\n let expiringSoonCount = 0\n let requiredCount = 0\n let refreshInstructionsCount = 0\n let noOwnerCount = 0\n\n for (const contract of contracts) {\n for (const variable of contract.variables) {\n totalVariableDeclarations += 1\n if (contract.active) activeVariableDeclarations += 1\n uniqueKeys.add(variable.key)\n keyContractCount.set(variable.key, (keyContractCount.get(variable.key) ?? 0) + 1)\n if (variable.required) requiredCount += 1\n if (variable.refreshInstructions) refreshInstructionsCount += 1\n if (effectiveOwner(contract, variable) === undefined) noOwnerCount += 1\n if (variable.expiresAt) {\n expiresAtSetCount += 1\n const date = parseIsoDate(variable.expiresAt)\n if (date) {\n const daysRemaining = daysRemainingFrom(date, now)\n if (daysRemaining < 0) expiredCount += 1\n else if (daysRemaining <= expiringWithinDays) expiringSoonCount += 1\n }\n }\n }\n }\n\n const duplicateVariableNameCount = [...keyContractCount.values()].filter(\n (count) => count > 1,\n ).length\n\n return {\n totalContracts: contracts.length,\n totalVariableDeclarations,\n activeVariableDeclarations,\n uniqueVariableNames: uniqueKeys.size,\n expiresAtSetCount,\n expiredCount,\n expiringSoonCount,\n requiredCount,\n refreshInstructionsCount,\n noOwnerCount,\n duplicateVariableNameCount,\n undocumentedContractCount,\n undocumentedVariableCount,\n }\n}\n\nfunction renderSecurityReview(\n contracts: readonly ContractModelContract[],\n options: RenderDocsOptions,\n now: Date,\n): string[] {\n const counters = computeSecurityReviewCounters(\n contracts,\n options.expiringWithinDays,\n now,\n options.undocumentedContracts.length,\n options.undocumentedVariables.length,\n )\n\n return [\n \"## Security review\",\n \"\",\n '<a id=\"security-review\"></a>',\n \"\",\n `- Total contracts: ${counters.totalContracts}`,\n `- Total variable declarations: ${counters.totalVariableDeclarations} (${counters.activeVariableDeclarations} from active contracts)`,\n `- Unique variable names: ${counters.uniqueVariableNames}`,\n `- Variables with \\`expiresAt\\` set: ${counters.expiresAtSetCount}`,\n ` - Already expired: ${counters.expiredCount}`,\n ` - Expiring within ${options.expiringWithinDays} days: ${counters.expiringSoonCount}`,\n `- Variables marked \\`required: true\\`: ${counters.requiredCount}`,\n `- Variables with refresh instructions: ${counters.refreshInstructionsCount}`,\n `- Variables with no assigned owner: ${counters.noOwnerCount}`,\n `- Variable names declared by more than one contract: ${counters.duplicateVariableNameCount}`,\n `- Undocumented contracts: ${counters.undocumentedContractCount}`,\n `- Undocumented variables: ${counters.undocumentedVariableCount}`,\n \"\",\n ]\n}\n\n// ---------------------------------------------------------------------------\n\n/**\n * Renders the full docs artifact: header + change summary + table of\n * contents, then the comprehensive catalog, ownership matrix (if used),\n * dependency graph, lifecycle report, and a security review.\n *\n * @remarks\n * Documents everything discovered, active or not, same scope as the catalog always\n * had. Fully regenerated every run -- unlike `.env.example`, nothing here is\n * meant to be hand-edited, so there's no \"never overwrite\" behavior.\n *\n * `contracts` is `ContractModel`'s own shape (`file` root-relative and\n * POSIX-separated already, per that model's convention) -- there is no\n * separate `root` parameter to resolve against, unlike this function's\n * pre-ADR-0038 signature.\n */\nexport function renderDocs(\n contracts: readonly ContractModelContract[],\n options: RenderDocsOptions,\n): string {\n const anchors = new AnchorRegistry()\n const sorted = sortedContracts(contracts)\n\n const ownership = renderOwnershipMatrix(sorted, anchors)\n const { lines: dependencyLines, hasDuplicates } = renderDependencyGraph(sorted, anchors)\n const { lines: lifecycleLines, hasLifecycle } = renderLifecycleReport(\n sorted,\n anchors,\n options.expiringWithinDays,\n options.generatedAt,\n )\n\n const header = renderHeader(\n sorted,\n options,\n anchors,\n ownership.length > 0,\n hasDuplicates,\n hasLifecycle,\n )\n const catalog = renderCatalog(sorted, anchors, options.undocumentedContracts)\n const security = renderSecurityReview(sorted, options, options.generatedAt)\n\n return [...header, ...catalog, ...ownership, ...dependencyLines, ...lifecycleLines, ...security]\n .join(\"\\n\")\n .replace(/\\n{3,}/g, \"\\n\\n\")\n}\n\n/**\n * Normalizes every wall-clock-relative substring `renderDocs()` can produce\n * -- not just the single `_Generated ..._` timestamp line, but also the\n * lifecycle report's `(**Xd remaining**)`/`(**expired Xd ago**)` annotations\n * and the security review's \"Already expired\"/\"Expiring within N days\"\n * counts -- so two renders of the *same* input, taken on different days,\n * compare equal. `check-artifacts.ts`'s drift comparison and the examples\n * golden-file test harness (`test/support/example-runner.ts`) both need\n * exactly this, not just the timestamp line alone: any contract with a near-term\n * `expiresAt` renders day-relative text that would otherwise make `--check`\n * (or a golden-file comparison) report false drift purely because real time\n * passed between generation and comparison.\n */\nexport function normalizeDocsForComparison(content: string): string {\n return content\n .replace(/^_Generated .+_$/m, \"_Generated <normalized-for-comparison>_\")\n .replace(/\\(\\*\\*\\d+d remaining\\*\\*\\)/g, \"(**Nd remaining**)\")\n .replace(/\\(\\*\\*expired \\d+d ago\\*\\*\\)/g, \"(**expired Nd ago**)\")\n .replace(/^(- Already expired:) \\d+$/gm, \"$1 N\")\n .replace(/^(- Expiring within \\d+ days:) \\d+$/gm, \"$1 N\")\n}\n","import path from \"node:path\"\nimport { humanizeKey, renderMetadataValue } from \"./humanize-key.js\"\nimport type { DiscoveredContract, DiscoveredVariable } from \"./link.js\"\nimport type { BuildFileSystem } from \"./types.js\"\nimport { mustGet } from \"./map-utils.js\"\n\n/**\n * Controls what happens when a `.env.example` already exists at the target\n * location. `\"keep-sibling\"` (default): never touch the existing file --\n * write a timestamped sibling instead, for the developer to diff/merge\n * manually. `\"overwrite\"`: replace the existing file with freshly rendered\n * content directly. `\"skip\"`: write nothing at all.\n */\nexport type EnvExampleOnExisting = \"keep-sibling\" | \"overwrite\" | \"skip\"\n\n/** The result of a completed {@link writeEnvExample} call. */\nexport interface EnvExampleResult {\n /**\n * Where the example file actually got written. `undefined` only when\n * `onExisting: \"skip\"` left an existing file untouched and nothing was\n * written.\n */\n readonly writtenPath: string | undefined\n /**\n * Set when a file already existed at the requested location and was left\n * untouched: with the default `\"keep-sibling\"`, `writtenPath` is a fresh\n * timestamped sibling instead; with `\"skip\"`, this is the only outcome and\n * `writtenPath` is `undefined`. Always `undefined` with `\"overwrite\"`.\n */\n readonly skippedExistingPath: string | undefined\n /** Variable names (live or already commented-out) in an existing example file that no discovered contract declares anymore. */\n readonly staleVariables: readonly string[]\n /** Variables live in an existing example file whose feature is no longer active, and that no other active feature still needs -- safe to comment out. */\n readonly variablesToComment: readonly string[]\n /** Variables the current (active) configuration requires that aren't yet a live entry in an existing example file. */\n readonly variablesToAdd: readonly string[]\n}\n\n/** The result of {@link computeReconciliation}: an existing `.env.example` diffed against the current configuration. */\nexport interface Reconciliation {\n /** Variable names (live or already commented-out) in an existing example file that no discovered contract declares anymore. */\n readonly staleVariables: readonly string[]\n /** Variables live in an existing example file whose feature is no longer active, and that no other active feature still needs -- safe to comment out. */\n readonly variablesToComment: readonly string[]\n /** Variables the current (active) configuration requires that aren't yet a live entry in an existing example file. */\n readonly variablesToAdd: readonly string[]\n}\n\nfunction isPrimitiveLiteral(value: unknown): value is string | number | boolean {\n return typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\"\n}\n\nfunction defaultLiteralFor(variable: DiscoveredVariable): string | undefined {\n return variable.defaultValue?.ok === true && isPrimitiveLiteral(variable.defaultValue.value)\n ? String(variable.defaultValue.value)\n : undefined\n}\n\n/**\n * Renders one variable's documentation comments + `KEY=value` line. `commented`\n * comments out the `KEY=value` line itself (documentation lines are always\n * comments regardless); `note` adds a leading comment explaining why --\n * used for both cross-feature duplicates and disabled-feature entries.\n *\n * Data comes from the linked `documentEnv()` call, if any -- never from the\n * schema itself, which only ever carries `processor`/`validator`/`default`.\n * An undocumented variable renders with no comments at all, just `KEY=`.\n */\nfunction renderVariableLines(\n variable: DiscoveredVariable,\n options: { commented?: boolean; note?: string } = {},\n): string[] {\n const lines: string[] = []\n if (options.note) lines.push(`# ${options.note}`)\n\n if (variable.description) lines.push(`# ${variable.description}`)\n if (variable.context) lines.push(`# Validation context: ${variable.context}`)\n if (variable.owner) lines.push(`# Owner: ${variable.owner}`)\n if (variable.setupInstructions) lines.push(`# Setup: ${variable.setupInstructions}`)\n if (variable.expiresAt) lines.push(`# Expires At: ${variable.expiresAt}`)\n if (variable.refreshInstructions)\n lines.push(`# Refresh Instructions: ${variable.refreshInstructions}`)\n if (variable.required) lines.push(`# Required: yes`)\n if (variable.purpose) lines.push(`# Purpose: ${variable.purpose}`)\n if (variable.legalBasis) lines.push(`# Legal Basis: ${variable.legalBasis}`)\n if (variable.retention) lines.push(`# Retention Policy: ${variable.retention}`)\n if (variable.dataResidency)\n lines.push(`# Data Residency: ${renderMetadataValue(variable.dataResidency)}`)\n if (variable.auditRequired) lines.push(`# Audit Required: yes`)\n for (const [metaKey, metaValue] of Object.entries(variable.metadata ?? {})) {\n lines.push(`# ${humanizeKey(metaKey)}: ${renderMetadataValue(metaValue)}`)\n }\n\n const prefix = options.commented ? \"# \" : \"\"\n lines.push(`${prefix}${variable.key}=${defaultLiteralFor(variable) ?? \"\"}`, \"\")\n return lines\n}\n\ninterface KeyedDeclaration {\n readonly contract: DiscoveredContract\n readonly variable: DiscoveredVariable\n}\n\nfunction groupByKey(contracts: readonly DiscoveredContract[]): Map<string, KeyedDeclaration[]> {\n const byKey = new Map<string, KeyedDeclaration[]>()\n for (const contract of contracts) {\n for (const variable of contract.variables) {\n const list = byKey.get(variable.key) ?? []\n list.push({ contract, variable })\n byKey.set(variable.key, list)\n }\n }\n return byKey\n}\n\n/**\n * Renders a deterministic `.env.example`-style file scoped to the *current*\n * configuration: every unique variable the active contracts require (one\n * live entry per key, alphabetical; a key declared by more than one active\n * contract renders once live and the rest commented-out with a pointer),\n * followed by variables unique to disabled contracts (commented-out, for\n * visibility -- a key already required by an active contract is not unique\n * and never repeated here). `reconciliationHeader`, when non-empty, is\n * spliced in right after the banner (see `computeReconciliation`).\n */\nexport function renderEnvExample(\n contracts: readonly DiscoveredContract[],\n reconciliationHeader: readonly string[] = [],\n): string {\n const sorted = [...contracts].sort((a, b) => a.file.localeCompare(b.file))\n const active = sorted.filter((c) => c.active)\n // Bypassing this filter (including active contracts in `inactive` too) is\n // behaviorally equivalent, not a real gap: the render loop below's own\n // `if (activeByKey.has(key)) continue` guard already skips any key an\n // active contract declares, whether or not it was ALSO wrongly grouped\n // into `inactiveByKey` here -- a key genuinely unique to an active\n // contract can never gain a spurious `inactiveByKey` entry either, since\n // `groupByKey` only ever pushes declarations that a contract in the\n // (possibly-widened) list actually has. Hand-verified: mutating this and\n // running the real suite passes unchanged.\n // Stryker disable next-line MethodExpression\n const inactive = sorted.filter((c) => !c.active)\n\n const lines: string[] = [\n \"# AUTO-GENERATED EXAMPLE FILE.\",\n \"# Copy to .env and fill in real values. Do not commit .env.\",\n ]\n // Only shown when at least one variable actually declares a context --\n // keeps this file byte-identical for every project not using the\n // feature.\n if (sorted.some((c) => c.variables.some((v) => v.context))) {\n lines.push(\n \"# Validation context annotations describe when validation participates.\",\n \"# They do not restrict access to values, and every variable below is\",\n \"# still written to this file regardless of its context.\",\n )\n }\n // Bypassing this guard is behaviorally equivalent, not a real gap:\n // `lines.push(...[])` (an empty `reconciliationHeader`) is already a\n // no-op, so the length check adds nothing observable. Hand-verified:\n // mutating this and running the real suite passes unchanged.\n // Stryker disable next-line ConditionalExpression,EqualityOperator\n if (reconciliationHeader.length > 0) lines.push(...reconciliationHeader)\n lines.push(\"\")\n\n const activeByKey = groupByKey(active)\n for (const key of [...activeByKey.keys()].sort()) {\n const [first, ...rest] = mustGet(activeByKey, key)\n lines.push(...renderVariableLines(first.variable))\n for (const dup of rest) {\n lines.push(\n ...renderVariableLines(dup.variable, {\n commented: true,\n note: `Also declared by \"${dup.contract.contractName}\" -- see \"${first.contract.contractName}\" above.`,\n }),\n )\n }\n }\n\n const inactiveByKey = groupByKey(inactive)\n for (const key of [...inactiveByKey.keys()].sort()) {\n if (activeByKey.has(key)) continue // claimed by an active contract -- not unique to the disabled feature.\n const [first] = mustGet(inactiveByKey, key)\n lines.push(\n ...renderVariableLines(first.variable, {\n commented: true,\n note: `Disabled -- feature \"${first.contract.contractName}\" is not active.`,\n }),\n )\n }\n\n // `+` vs no `+` here is unreachable-to-differ: `lines` is built so its own\n // trailing element is always exactly ONE \"\" (every section -- the initial\n // blank, and each `renderVariableLines()` call -- appends exactly one\n // trailing blank, never two in a row), so `.join(\"\\n\")` can never actually\n // produce more than one trailing newline for this regex to collapse.\n // Hand-verified: mutating `+` away and running the real suite passes\n // unchanged.\n // Stryker disable next-line Regex\n return lines.join(\"\\n\").replace(/\\n+$/, \"\\n\")\n}\n\n/** Parses `KEY=value` lines out of an existing `.env`-style file, ignoring comments and blank lines. */\nexport function extractDeclaredVariables(source: string): string[] {\n const names: string[] = []\n for (const line of source.split(\"\\n\")) {\n const trimmed = line.trim()\n // Bypassing this early exit is behaviorally equivalent, not a real gap:\n // both a blank line (trimmed === \"\") and one starting with \"#\" can never\n // match the identifier-must-start-with-letter/underscore regex below\n // either way, so `continue`ing early here versus falling through to a\n // guaranteed-failing `.exec()` produces the identical result. Kept as a\n // documented fast-path (skips the regex entirely for the common case)\n // rather than removed. Hand-verified: mutating the whole condition to\n // `false` and running the real suite passes unchanged.\n // Stryker disable next-line ConditionalExpression,LogicalOperator,MethodExpression\n if (!trimmed || trimmed.startsWith(\"#\")) continue\n const match = /^([A-Za-z_][A-Za-z0-9_]*)=/.exec(trimmed)\n if (match?.[1]) names.push(match[1])\n }\n return names\n}\n\n/** Parses `# KEY=value` lines out of an existing `.env`-style file -- variables it already knows about but has turned off. */\nexport function extractCommentedVariables(source: string): string[] {\n const names: string[] = []\n for (const line of source.split(\"\\n\")) {\n const trimmed = line.trim()\n if (!trimmed.startsWith(\"#\")) continue\n // Removing the `^` anchor is behaviorally equivalent, not a real gap:\n // the guard just above guarantees `trimmed` always starts with \"#\", so\n // the leftmost match an unanchored regex would find is already at\n // position 0 -- identical to the anchored version. Hand-verified:\n // mutating this and running the real suite passes unchanged.\n // Stryker disable next-line Regex\n const withoutHash = trimmed.replace(/^#+\\s*/, \"\")\n const match = /^([A-Za-z_][A-Za-z0-9_]*)=/.exec(withoutHash)\n if (match?.[1]) names.push(match[1])\n }\n return names\n}\n\n/**\n * Diffs an existing `.env.example` against the current configuration into\n * three actionable sets. Pure and filesystem-independent -- `writeEnvExample`\n * is the only caller that reads the file itself.\n */\nexport function computeReconciliation(\n contracts: readonly DiscoveredContract[],\n existingContent: string,\n): Reconciliation {\n const activeKeys = new Set(\n contracts.filter((c) => c.active).flatMap((c) => c.variables.map((v) => v.key)),\n )\n const knownKeys = new Set(contracts.flatMap((c) => c.variables.map((v) => v.key)))\n\n const oldLive = new Set(extractDeclaredVariables(existingContent))\n const oldKnown = new Set([...oldLive, ...extractCommentedVariables(existingContent)])\n\n const staleVariables = [...oldKnown].filter((key) => !knownKeys.has(key)).sort()\n // Only ever flags a key that no active contract needs -- a key shared with\n // a still-active feature is never suggested for commenting out.\n const variablesToComment = [...oldLive]\n .filter((key) => !activeKeys.has(key) && knownKeys.has(key))\n .sort()\n const variablesToAdd = [...activeKeys].filter((key) => !oldLive.has(key)).sort()\n\n return { staleVariables, variablesToComment, variablesToAdd }\n}\n\nfunction renderReconciliationHeader(reconciliation: Reconciliation): string[] {\n const lines: string[] = []\n if (reconciliation.staleVariables.length > 0) {\n lines.push(\"#\", \"# Remove the following variables (no longer declared by any feature):\")\n for (const key of reconciliation.staleVariables) lines.push(`# - ${key}`)\n }\n if (reconciliation.variablesToComment.length > 0) {\n lines.push(\"#\", \"# Comment the following variables (their feature is no longer active):\")\n for (const key of reconciliation.variablesToComment) lines.push(`# - ${key}`)\n }\n if (reconciliation.variablesToAdd.length > 0) {\n lines.push(\"#\", \"# Add the following variables (required by the current configuration):\")\n for (const key of reconciliation.variablesToAdd) lines.push(`# - ${key}`)\n }\n return lines\n}\n\n/**\n * Writes a rendered `.env.example` to `location`. Behavior when a file\n * already exists there is governed by `options.onExisting` (default\n * `\"keep-sibling\"`, see `EnvExampleOnExisting`):\n * - `\"keep-sibling\"`: the existing file is left alone; freshly generated\n * content is written to a timestamped sibling instead\n * (`<location>.<epoch-ms>`), prefixed with a reconciliation header\n * comparing it against the existing file (omitted when there's nothing\n * to report).\n * - `\"overwrite\"`: the existing file is replaced directly with freshly\n * rendered content -- no reconciliation header (the changes it would\n * describe are already applied).\n * - `\"skip\"`: nothing is written.\n * When no file exists yet at `location`, all three modes behave the same:\n * write fresh content, nothing to reconcile against. `staleVariables`/\n * `variablesToComment`/`variablesToAdd` are always computed and returned\n * when a prior file existed, even under `\"overwrite\"`/`\"skip\"`, as a\n * diagnostic -- independent of whether anything was actually written.\n */\nexport async function writeEnvExample(\n contracts: readonly DiscoveredContract[],\n location: string,\n fs: BuildFileSystem,\n options: { onExisting?: EnvExampleOnExisting } = {},\n): Promise<EnvExampleResult> {\n const onExisting = options.onExisting ?? \"keep-sibling\"\n\n // An empty catch (no assignment) is provably equivalent to explicitly\n // setting `existingContent = undefined` -- `let` without an initializer is\n // already `undefined` at runtime -- and an empty block gives Stryker's\n // BlockStatement mutator nothing to swap in for, eliminating the mutant\n // target entirely rather than needing a disable. See helpers/processors.ts's\n // `orUndefined` for the same established pattern.\n let existingContent: string | undefined\n try {\n existingContent = await fs.readFile(location, \"utf8\")\n } catch {\n // treat any read failure as \"no file existed\"\n }\n\n if (existingContent === undefined) {\n const content = renderEnvExample(contracts, [])\n await fs.mkdir(path.dirname(location), { recursive: true })\n // \"utf8\" vs \"\" encoding equivalence, same established class as this\n // package's other fs.writeFile calls (evidence-snapshot.ts,\n // resolve-package-schema.ts): both write a string's UTF-8 bytes\n // identically. Hand-verified via a real byte-comparison-equivalent test\n // run.\n // Stryker disable next-line StringLiteral\n await fs.writeFile(location, content, \"utf8\")\n return {\n writtenPath: location,\n skippedExistingPath: undefined,\n staleVariables: [],\n variablesToComment: [],\n variablesToAdd: [],\n }\n }\n\n const reconciliation = computeReconciliation(contracts, existingContent)\n const { staleVariables, variablesToComment, variablesToAdd } = reconciliation\n\n if (onExisting === \"skip\") {\n return {\n writtenPath: undefined,\n skippedExistingPath: location,\n staleVariables,\n variablesToComment,\n variablesToAdd,\n }\n }\n\n // Only \"keep-sibling\" embeds the reconciliation as an in-file header --\n // \"overwrite\" already applies the changes directly, so \"remove/comment/add\n // the following\" instructions would just describe work already done.\n const headerLines =\n onExisting === \"keep-sibling\" ? renderReconciliationHeader(reconciliation) : []\n const content = renderEnvExample(contracts, headerLines)\n const writtenPath = onExisting === \"overwrite\" ? location : `${location}.${Date.now()}`\n const skippedExistingPath = onExisting === \"overwrite\" ? undefined : location\n\n await fs.mkdir(path.dirname(writtenPath), { recursive: true })\n // Same \"utf8\" vs \"\" equivalence as the fresh-file write above.\n // Stryker disable next-line StringLiteral\n await fs.writeFile(writtenPath, content, \"utf8\")\n\n return { writtenPath, skippedExistingPath, staleVariables, variablesToComment, variablesToAdd }\n}\n","import { deepFreeze } from \"./deep-freeze.js\"\nimport { parseIsoDate } from \"./docs.js\"\nimport type { DiscoveredContract, DiscoveredVariable } from \"./link.js\"\n\n/**\n * Supplies expiration metadata from a live source (a secrets manager, an\n * internal inventory API, ...) as a post-discovery override -- the one\n * sanctioned escape hatch from static-only `expiresAt`.\n *\n * @remarks\n * Invoked exactly once per generation run, from the orchestration layer, after AST discovery/\n * linking completes and before documentation is rendered. Never invoked\n * during AST parsing or runtime validation -- see ADR 0012 for why a\n * function embedded in a schema file itself was rejected instead.\n */\nexport type LiveExpirationDates = (\n variableNames: readonly string[],\n) => Promise<Readonly<Record<string, string>>>\n\n/**\n * Every unique variable key across every linked contract's `variables`.\n * Contract-level `expiresAt` is out of scope for override -- the callback is\n * keyed by variable name, not contract name.\n */\nexport function collectVariableNames(contracts: readonly DiscoveredContract[]): string[] {\n const names = new Set<string>()\n for (const contract of contracts) {\n for (const variable of contract.variables) names.add(variable.key)\n }\n return [...names]\n}\n\nfunction overrideVariable(\n variable: DiscoveredVariable,\n overrides: Readonly<Record<string, string>>,\n): DiscoveredVariable {\n const override = overrides[variable.key]\n // `Record<string, string>` indexing is unsound without `noUncheckedIndexedAccess`\n // (not enabled repo-wide): TS believes `override` is always `string`, but a\n // key genuinely absent from the record is `undefined` at runtime -- the\n // entire reason this function needs to handle a missing override at all.\n // Equivalent either way this ternary's condition is mutated:\n // `parseIsoDate(undefined as unknown as string)` -> `new Date(undefined)`\n // -> Invalid Date -> `undefined`, the exact same result the `undefined`\n // branch returns explicitly. Same class as data-cap's documented\n // `expiresAt === undefined` guard immediately before a `new Date(...)`\n // parse-or-skip.\n // Stryker disable next-line ConditionalExpression\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n const date = override === undefined ? undefined : parseIsoDate(override)\n return {\n ...variable,\n expiresAt: date ? override : variable.expiresAt,\n metadata: variable.metadata ? { ...variable.metadata } : variable.metadata,\n }\n}\n\n/**\n * Applies `overrides` onto a fresh copy of `contracts` -- every contract and\n * every variable (and their nested `metadata`/`extra` records) is rebuilt\n * into a new object, never the original reference, so the returned structure\n * shares no mutable object identity with `contracts` at any depth.\n *\n * @remarks\n * A key absent from `overrides`, or present but not a `parseIsoDate`-parseable\n * ISO-8601 string, leaves that variable's static `expiresAt` untouched --\n * same \"warn/skip, never guess\" policy the rest of the generator uses for\n * malformed data. Contract-level `expiresAt` is never touched; only\n * variable-level `expiresAt` is in scope for override.\n */\nexport function applyLiveExpirationOverrides(\n contracts: readonly DiscoveredContract[],\n overrides: Readonly<Record<string, string>>,\n): readonly DiscoveredContract[] {\n return contracts.map((contract) => ({\n ...contract,\n metadata: contract.metadata ? { ...contract.metadata } : contract.metadata,\n variables: contract.variables.map((variable) => overrideVariable(variable, overrides)),\n }))\n}\n\n/**\n * Orchestration entry point -- the only place `liveExpirationDates` is ever invoked.\n *\n * @remarks\n * No-ops (returns the exact same array reference, zero invocations)\n * when `liveExpirationDates` is undefined, which is what guarantees \"omitted ->\n * behavior unchanged.\" Otherwise collects the unique discovered variable\n * names, invokes the callback exactly once, applies the result, and\n * deep-freezes the returned structure so it can never be mutated into\n * affecting `contracts` (used elsewhere, e.g. by the manifest/usage passes in\n * the same {@link generateEnvArtifacts} run) or anything else downstream.\n */\nexport async function resolveLiveExpirationDates(\n contracts: readonly DiscoveredContract[],\n liveExpirationDates: LiveExpirationDates | undefined,\n): Promise<readonly DiscoveredContract[]> {\n if (!liveExpirationDates) return contracts\n const overrides = await liveExpirationDates(collectVariableNames(contracts))\n return deepFreeze(applyLiveExpirationOverrides(contracts, overrides))\n}\n","import path from \"node:path\"\nimport { assembleProject } from \"./assemble-project.js\"\nimport { buildContractModel } from \"./contract-model.js\"\nimport { displayPath } from \"./display-path.js\"\nimport type { ContractModelContract } from \"./contract-model.js\"\nimport { buildCatalog, computeExpiringEntries, renderDocs } from \"./docs.js\"\nimport type {\n CatalogContract,\n ExpiringEntry,\n UndocumentedContractRef,\n UndocumentedVariableRef,\n} from \"./docs.js\"\nimport { writeEnvExample } from \"./env-example.js\"\nimport type { EnvExampleOnExisting, EnvExampleResult } from \"./env-example.js\"\nimport { EnvDocumentationGenerationError } from \"./errors.js\"\nimport { defaultExclude, defaultInclude } from \"./generate-manifest.js\"\nimport { summarizeContract } from \"./link.js\"\nimport type { DiscoveredContract, DiscoveredContractSummary, LinkResult } from \"./link.js\"\nimport { resolveLiveExpirationDates } from \"./live-expirations.js\"\nimport type { LiveExpirationDates } from \"./live-expirations.js\"\nimport type { ParseWarning } from \"./parse.js\"\nimport { resolveWithinRoot } from \"./resolution/resolve-within-root.js\"\nimport type { BuildFileSystem } from \"./types.js\"\n\n/** Options for {@link generateDocumentation}. */\nexport interface GenerateDocumentationOptions {\n /** The filesystem capability -- `./build` never imports `node:fs` (ADR 0040). */\n fs: BuildFileSystem\n /** Project root schema discovery is relative to. Defaults to `process.cwd()`. */\n root?: string | undefined\n /** Output path for the Markdown docs artifact, relative to `root`. */\n location: string\n /** Glob patterns for files to scan. Defaults to `defaultInclude()`. */\n include?: string[] | undefined\n /** Glob patterns for files/directories to prune. Defaults to `defaultExclude()`. */\n exclude?: string[] | undefined\n /** **Experimental** (see VERSIONING.md) -- see `GenerateEnvManifestOptions.packages`; see ADR 0014. */\n packages?: readonly string[] | undefined\n /** **Experimental** (see VERSIONING.md) -- see `GenerateEnvManifestOptions.tsconfig`; see ADR 0023. */\n tsconfig?: string | false | undefined\n /** How many days out counts as \"expiring soon\". Defaults to 30. */\n expiringWithinDays?: number | undefined\n /**\n * Also emit a `.env.example`-style file, relative to `root`. `onExisting`\n * controls what happens when a file already exists there -- defaults to\n * `\"keep-sibling\"` (never overwrites; see `EnvExampleOnExisting` and\n * `EnvExampleResult`).\n */\n envExample?:\n | {\n /** Output path for the `.env.example`-style file, relative to `root`. */\n location: string\n /** What to do when a file already exists at `location`. Defaults to `\"keep-sibling\"`. */\n onExisting?: EnvExampleOnExisting | undefined\n }\n | undefined\n /**\n * Supplies expiration metadata from a live source as a post-discovery\n * override, invoked exactly once with every discovered variable name after\n * linking completes and before rendering. See `live-expirations.ts` and\n * ADR 0012. Omitted: behavior is unchanged from a purely static `expiresAt`.\n */\n liveExpirationDates?: LiveExpirationDates | undefined\n}\n\n/** Everything {@link generateDocumentation} found that isn't fully documented or up to date -- never blocks generation; a team that wants to gate CI on this reads `Finding[]` (the \"documentation\" family) from the persisted evidence artifact and decides for itself. See ADR 0038. */\nexport interface DocumentationFindings {\n /** Contracts with no linked `documentEnv()` call at all. */\n readonly undocumentedContracts: readonly {\n /** Absolute path of the file declaring the contract. */\n readonly file: string\n /** The contract's exported binding name. */\n readonly exportName: string\n }[]\n /** Schema variables with no matching entry in their contract's linked documentation. */\n readonly undocumentedVariables: readonly {\n /** Absolute path of the file declaring the contract. */\n readonly file: string\n /** The contract's exported binding name. */\n readonly exportName: string\n /** The undocumented environment variable name. */\n readonly key: string\n }[]\n /** Documented variable entries with no matching schema variable (the schema key was removed or renamed). */\n readonly staleDocEntries: readonly {\n /** Absolute path of the file declaring the contract. */\n readonly file: string\n /** The contract's exported binding name. */\n readonly exportName: string\n /** The stale documented variable name. */\n readonly key: string\n }[]\n /** Variables whose `expiresAt` falls within the configured window. */\n readonly expiringSoon: readonly ExpiringEntry[]\n /** Contract- or variable-level `sensitivity` values outside {@link STANDARD_SENSITIVITY_LEVELS}. Advisory only -- the declared level is always honored verbatim; this exists purely so vocabulary drift across a repo stays visible. */\n readonly nonstandardSensitivityLevels: readonly NonstandardSensitivityEntry[]\n /** `documentEnv()` calls that couldn't be statically linked to a schema. */\n readonly unresolvedLinks: readonly {\n /** Absolute path of the file containing the unlinkable call. */\n readonly file: string\n /** Human-readable explanation of why the link couldn't be resolved. */\n readonly reason: string\n }[]\n}\n\n/** The result of a completed {@link generateDocumentation} run. */\nexport interface GenerateDocumentationResult {\n /** Absolute path the Markdown docs artifact was written to. */\n readonly docsPath: string\n /** Set only when `options.envExample` was passed. */\n readonly envExample: EnvExampleResult | undefined\n /** Root-relative summary of every discovered contract, active or not. */\n readonly contracts: readonly DiscoveredContractSummary[]\n /** Same descriptive content as the generated Markdown Catalog, reshaped for\n * programmatic consumers -- see `buildCatalog()` in `docs.ts`. */\n readonly catalog: readonly CatalogContract[]\n /** Parse-time warnings collected across every analyzed file (including allow-listed package resolution). */\n readonly parseWarnings: readonly ParseWarning[]\n /** Everything found that isn't fully documented or up to date. */\n readonly documentation: DocumentationFindings\n}\n\n/** Default value for {@link GenerateDocumentationOptions.expiringWithinDays}. */\nexport const DEFAULT_EXPIRING_WITHIN_DAYS = 30\n\n/**\n * The sensitivity vocabulary env-cap's own docs, examples, and `.env.example`\n * comments are written around. Purely advisory: `sensitivity` is an open\n * `string` (see {@link runtime.VariableDocs.sensitivity}), any value is\n * honored verbatim, and nothing here ever drops or rewrites a declared level.\n * A level outside this set only produces a non-blocking\n * `NONSTANDARD_SENSITIVITY_LEVEL` finding, so a team that deliberately runs\n * its own vocabulary sees one advisory line rather than silent data loss --\n * and a team that meant to write `\"secret\"` and typo'd `\"secrets\"` finds out.\n */\n// A module-load `const` referenced directly by `documentation-generate.test.ts`\n// (which iterates its exact members) is the documented covered-static\n// false-Survived class: Stryker's dry-run coverage analysis marks a mutant\n// here `static: true`, runs it anyway, and reports \"Survived\" even with\n// real, passing test coverage -- `ignoreStatic` only ignores a static\n// mutant with ZERO coverage. Can't fix with the usual \"inline into its one\n// consumer\" move here (this is consumed across a module boundary, by both\n// this file's own `findNonstandardSensitivityLevels()` AND the test file's\n// own enumeration of \"every standard level\") -- same \"shared public\n// sentinel\" class as data-cap's `UNOWNED`/`FIELD_MARKER`. Hand-verified:\n// corrupting each individual string (one at a time) and running\n// `vitest run test/build/documentation-generate.test.ts` directly fails a\n// real test every time, proving genuine coverage.\n// Stryker disable ArrayDeclaration, StringLiteral\nexport const STANDARD_SENSITIVITY_LEVELS: ReadonlySet<string> = new Set([\n \"secret\",\n \"credential\",\n \"pii\",\n \"config\",\n])\n// Stryker restore ArrayDeclaration, StringLiteral\n\n/** One contract- or variable-level `sensitivity` declaring a level outside {@link STANDARD_SENSITIVITY_LEVELS}. */\nexport interface NonstandardSensitivityEntry {\n /** Absolute path of the file declaring the contract. */\n readonly file: string\n /** The contract's exported binding name. */\n readonly exportName: string\n /** `undefined` for a contract-level `sensitivity`, set for a per-variable one. */\n readonly key: string | undefined\n /** The declared level, exactly as written. */\n readonly sensitivity: string\n}\n\n/**\n * Every contract- or variable-level `sensitivity` outside the standard set,\n * in declaration order (contract first, then its own variables by key).\n *\n * @remarks\n * A variable's *own* declared level only -- never the contract-inherited one\n * `effectiveSensitivity()` would resolve to. Reporting the inherited value\n * would fire this same finding once per variable on a contract that already\n * produced its own contract-level entry, turning one real vocabulary\n * question into N duplicates of it.\n */\nexport function findNonstandardSensitivityLevels(\n contracts: readonly DiscoveredContract[],\n): NonstandardSensitivityEntry[] {\n const entries: NonstandardSensitivityEntry[] = []\n for (const contract of contracts) {\n if (\n contract.sensitivity !== undefined &&\n !STANDARD_SENSITIVITY_LEVELS.has(contract.sensitivity)\n )\n entries.push({\n file: contract.file,\n exportName: contract.exportName,\n key: undefined,\n sensitivity: contract.sensitivity,\n })\n for (const variable of [...contract.variables].sort((a, b) => a.key.localeCompare(b.key))) {\n if (variable.sensitivity === undefined) continue\n if (STANDARD_SENSITIVITY_LEVELS.has(variable.sensitivity)) continue\n entries.push({\n file: contract.file,\n exportName: contract.exportName,\n key: variable.key,\n sensitivity: variable.sensitivity,\n })\n }\n }\n return entries\n}\n\nexport interface DocumentationComputation {\n readonly contractSummaries: readonly DiscoveredContractSummary[]\n readonly catalog: readonly CatalogContract[]\n readonly documentation: DocumentationFindings\n /** `ContractModel`'s own projection of the same contracts, built once here and reused by `writeDocumentation()` -- the shape `renderDocs()` itself takes (ADR 0038). */\n readonly contractModelContracts: readonly ContractModelContract[]\n}\n\n/** Root-relative, POSIX-separated -- `RenderDocsOptions`'s own convention, matching `ContractModel`'s `file`. Exported so `check-artifacts.ts`'s drift check can convert the same `documentation.undocumentedContracts`/`undocumentedVariables` fields for its own `renderDocs()` call, identically. Delegates to `displayPath()` so this can never disagree with the `ContractModel` `file` values it's matched against by identity. */\nexport function relativizeRef<T extends { file: string }>(root: string, ref: T): T {\n return { ...ref, file: displayPath(root, ref.file) }\n}\n\n/**\n * Pure -- no I/O. Computes undocumented/stale/expiring findings against an\n * already-discovered contract graph (active and inactive alike -- docs\n * document everything, unlike the manifest). Never blocks -- see\n * `DocumentationFindings`'s own doc comment. Shared by the standalone\n * `generateDocumentation()` and `generate-env-artifacts.ts` (which also\n * reuses this same call for Finding Model's documentation-family findings,\n * ADR 0038 -- one computation, not two).\n */\nexport function computeDocumentation(\n root: string,\n linkResult: LinkResult,\n expiringWithinDays: number,\n generatedAt: Date,\n): DocumentationComputation {\n const { contracts } = linkResult\n return {\n contractSummaries: contracts.map((contract) => summarizeContract(contract, root)),\n catalog: buildCatalog(contracts),\n documentation: {\n undocumentedContracts: linkResult.undocumentedContracts,\n undocumentedVariables: linkResult.undocumentedVariables,\n staleDocEntries: linkResult.staleDocEntries,\n expiringSoon: computeExpiringEntries(contracts, expiringWithinDays, generatedAt),\n nonstandardSensitivityLevels: findNonstandardSensitivityLevels(contracts),\n unresolvedLinks: linkResult.unresolvedLinks,\n },\n contractModelContracts: buildContractModel(contracts, root).contracts,\n }\n}\n\n/** Writes the docs artifact and, if requested, the `.env.example` file. Callers must have already confirmed both output paths are safe and nothing is blocking. */\nexport async function writeDocumentation(\n docsPath: string,\n envExamplePath: string | undefined,\n root: string,\n contracts: readonly DiscoveredContract[],\n contractModelContracts: readonly ContractModelContract[],\n documentation: DocumentationFindings,\n expiringWithinDays: number,\n generatedAt: Date,\n fs: BuildFileSystem,\n envExampleOnExisting?: EnvExampleOnExisting,\n): Promise<{ envExample: EnvExampleResult | undefined }> {\n let previousContent: string | undefined\n try {\n previousContent = await fs.readFile(docsPath, \"utf8\")\n } catch {\n // Empty -- `previousContent` already starts `undefined`; re-assigning\n // it here is a no-op (no BlockStatement mutant on a trailing `{}`).\n }\n\n const docsSource = renderDocs(contractModelContracts, {\n expiringWithinDays,\n undocumentedContracts: documentation.undocumentedContracts.map((ref): UndocumentedContractRef =>\n relativizeRef(root, ref),\n ),\n // `RenderDocsOptions.undocumentedVariables` is consumed by `renderDocs()`\n // ONLY via `.length` (the security-review counter) -- never by content\n // or identity, unlike its `undocumentedContracts` sibling above (matched\n // by identity against the catalog for the \"Undocumented.\" marker).\n // `.map()` always preserves length regardless of what each element\n // transforms to, so this specific `relativizeRef()` call's own output is\n // unobservable through this call site. Hand-verified: mapping every\n // entry to `undefined` instead and running the full `vitest run` leaves\n // all tests passing.\n // Stryker disable next-line ArrowFunction\n undocumentedVariables: documentation.undocumentedVariables.map((ref): UndocumentedVariableRef =>\n relativizeRef(root, ref),\n ),\n generatedAt,\n previousContent,\n })\n await fs.mkdir(path.dirname(docsPath), { recursive: true })\n // `docsSource` is always a plain string -- fs.writeFile defaults a string\n // write to utf8 regardless of the encoding arg, so \"utf8\" vs \"\" is\n // unobservable. Same established equivalence as this drive's other\n // writeX() functions.\n // Stryker disable next-line StringLiteral\n await fs.writeFile(docsPath, docsSource, \"utf8\")\n\n const envExample = envExamplePath\n ? await writeEnvExample(contracts, envExamplePath, fs, { onExisting: envExampleOnExisting })\n : undefined\n return { envExample }\n}\n\n/**\n * Build-time only. Discovers and links `env.schema.ts` files (same static\n * analysis as {@link generateEnvManifest}) and writes the rich Markdown \"Catalog\" --\n * every variable, its description, default, processor/validator flags,\n * owner, and expiry -- the single onboarding reference application\n * developers use to see what configuration a feature needs and how to set\n * it up. Optionally also writes a reconciling `.env.example`.\n *\n * @remarks\n * Documents every discovered contract, active or not, unlike {@link generateEnvManifest}.\n *\n * @throws {EnvDocumentationGenerationError} If `location`/`envExample.location` escape `root`.\n */\nexport async function generateDocumentation(\n options: GenerateDocumentationOptions,\n): Promise<GenerateDocumentationResult> {\n const root = path.resolve(options.root ?? process.cwd())\n const include = options.include ?? defaultInclude()\n const exclude = options.exclude ?? defaultExclude()\n const packages = options.packages ?? []\n const expiringWithinDays = options.expiringWithinDays ?? DEFAULT_EXPIRING_WITHIN_DAYS\n\n const docsLocationResult = resolveWithinRoot(\n root,\n options.location,\n \"location\",\n \"generateDocumentation\",\n )\n if (!docsLocationResult.ok) throw new EnvDocumentationGenerationError([docsLocationResult.issue])\n const docsPath = docsLocationResult.resolved\n\n let envExamplePath: string | undefined\n if (options.envExample) {\n const envExampleResult = resolveWithinRoot(\n root,\n options.envExample.location,\n \"envExample.location\",\n \"generateDocumentation\",\n )\n if (!envExampleResult.ok) throw new EnvDocumentationGenerationError([envExampleResult.issue])\n envExamplePath = envExampleResult.resolved\n }\n\n const { linkResult, packageWarnings, tsconfigWarnings } = await assembleProject({\n fs: options.fs,\n root,\n include,\n exclude,\n packages,\n tsconfig: options.tsconfig,\n })\n const docsContracts = await resolveLiveExpirationDates(\n linkResult.contracts,\n options.liveExpirationDates,\n )\n\n const generatedAt = new Date()\n const computed = computeDocumentation(\n root,\n { ...linkResult, contracts: docsContracts },\n expiringWithinDays,\n generatedAt,\n )\n\n const { envExample } = await writeDocumentation(\n docsPath,\n envExamplePath,\n root,\n docsContracts,\n computed.contractModelContracts,\n computed.documentation,\n expiringWithinDays,\n generatedAt,\n options.fs,\n options.envExample?.onExisting,\n )\n\n return {\n docsPath,\n envExample,\n contracts: computed.contractSummaries,\n catalog: computed.catalog,\n parseWarnings: [...packageWarnings, ...tsconfigWarnings, ...linkResult.warnings],\n documentation: computed.documentation,\n }\n}\n","import { displayPath } from \"./display-path.js\"\nimport { byContractIdentity } from \"./sort-by-identity.js\"\nimport { computeExpiringEntries } from \"./docs.js\"\nimport type { ExpiringEntry } from \"./docs.js\"\nimport type { DiscoveredContract, DiscoveredVariable } from \"./link.js\"\n\n/**\n * The fifth of env-cap's seven canonical fact models (ADR 0024) -- every\n * contract and variable's lifecycle data (expiry, deprecation, rename\n * correlation), promoting `ExpiringEntry`/`computeExpiringEntries()`\n * (already a good precedent -- real, exported, reused across `renderDocs()`\n * and `generate-documentation.ts`) into a canonical, versioned shape\n * alongside the new deprecation/rename fields. See ADR 0029.\n */\n\n/** Bump only when a reader could misinterpret the new shape -- same discipline every other canonical model's `schemaVersion` follows. */\nexport const LIFECYCLE_MODEL_SCHEMA_VERSION = 2\n\n/**\n * One variable's lifecycle data (expiry, deprecation, rename correlation).\n *\n * @see {@link ContractModelVariable} -- this same declared variable's canonical starting point.\n */\nexport interface LifecycleModelVariable {\n readonly key: string\n readonly expiresAt: string | undefined\n readonly refreshInstructions: string | undefined\n readonly deprecated: boolean | undefined\n readonly deprecatedReason: string | undefined\n readonly removeBy: string | undefined\n /** The previous variable name this one renames, if set -- see `ManifestChangeReport`'s rename correlation (ADR 0029/0030). */\n readonly renamedFrom: string | undefined\n /** Descriptive retention policy (e.g. \"delete after 90 days\") -- a policy statement, never computed or parsed, deliberately independent of `expiresAt`'s actual temporal constraint. See ADR 0035. */\n readonly retention: string | undefined\n}\n\nexport interface LifecycleModelContract {\n /** Root-relative, POSIX-separated -- matches `ContractModelContract.file`. */\n readonly file: string\n readonly exportName: string\n readonly contractName: string\n readonly expiresAt: string | undefined\n readonly deprecated: boolean | undefined\n readonly deprecatedReason: string | undefined\n /** See {@link LifecycleModelVariable.retention}. */\n readonly retention: string | undefined\n /** Only variables with at least one lifecycle field set (`expiresAt`, `refreshInstructions`, `deprecated`, `removeBy`, `renamedFrom`, `retention`) -- same \"only what's relevant\" scope `renderLifecycleReport()` already uses for its rows. */\n readonly variables: readonly LifecycleModelVariable[]\n}\n\nexport interface LifecycleModel {\n readonly schemaVersion: typeof LIFECYCLE_MODEL_SCHEMA_VERSION\n /** Only contracts with at least one lifecycle-relevant field set, at the contract level or on at least one variable. */\n readonly contracts: readonly LifecycleModelContract[]\n /**\n * Every contract-/variable-level `expiresAt` within the configured window,\n * soonest-first -- see `computeExpiringEntries()`. `file` is root-relative\n * and POSIX-separated here, matching `LifecycleModelContract.file`/every\n * other canonical model -- unlike `ExpiringEntry`'s own doc comment, which\n * describes its shape in `computeExpiringEntries()`'s other direct\n * consumers (e.g. `DocumentationFindings.expiringSoon`), where `file`\n * stays the absolute path `renderDocs()` itself expects.\n */\n readonly expiring: readonly ExpiringEntry[]\n}\n\nfunction hasLifecycleData(variable: DiscoveredVariable): boolean {\n return (\n variable.expiresAt !== undefined ||\n variable.refreshInstructions !== undefined ||\n variable.deprecated !== undefined ||\n variable.removeBy !== undefined ||\n variable.renamedFrom !== undefined ||\n variable.retention !== undefined\n )\n}\n\n/**\n * Projects every discovered contract with at least one lifecycle-relevant\n * field set into the Lifecycle Model's versioned, JSON-serializable shape,\n * plus the already-established `expiring` view.\n */\nexport function buildLifecycleModel(\n contracts: readonly DiscoveredContract[],\n expiringWithinDays: number,\n now: Date,\n root: string,\n): LifecycleModel {\n const modelContracts: LifecycleModelContract[] = []\n\n for (const contract of contracts) {\n const variables: LifecycleModelVariable[] = [...contract.variables]\n .filter(hasLifecycleData)\n .sort((a, b) => a.key.localeCompare(b.key))\n .map((variable) => ({\n key: variable.key,\n expiresAt: variable.expiresAt,\n refreshInstructions: variable.refreshInstructions,\n deprecated: variable.deprecated,\n deprecatedReason: variable.deprecatedReason,\n removeBy: variable.removeBy,\n renamedFrom: variable.renamedFrom,\n retention: variable.retention,\n }))\n\n const hasContractLevelData =\n contract.expiresAt !== undefined ||\n contract.deprecated !== undefined ||\n contract.deprecatedReason !== undefined ||\n contract.retention !== undefined\n\n if (!hasContractLevelData && variables.length === 0) continue\n\n modelContracts.push({\n file: displayPath(root, contract.file),\n exportName: contract.exportName,\n contractName: contract.contractName,\n expiresAt: contract.expiresAt,\n deprecated: contract.deprecated,\n deprecatedReason: contract.deprecatedReason,\n retention: contract.retention,\n variables,\n })\n }\n modelContracts.sort(byContractIdentity)\n\n return {\n schemaVersion: LIFECYCLE_MODEL_SCHEMA_VERSION,\n contracts: modelContracts,\n expiring: computeExpiringEntries(contracts, expiringWithinDays, now).map((entry) => ({\n ...entry,\n file: displayPath(root, entry.file),\n })),\n }\n}\n","import { displayPath } from \"./display-path.js\"\nimport { byContractIdentity } from \"./sort-by-identity.js\"\nimport type { ContractRef } from \"./evidence-reference.js\"\nimport { effectiveOwner } from \"./link.js\"\nimport type { DiscoveredContract } from \"./link.js\"\n\n/**\n * The third of env-cap's seven canonical fact models (ADR 0024) -- every\n * contract and variable's effective owner, plus first-class\n * `unownedContracts`/`unownedVariables` arrays. See ADR 0028.\n *\n * @remarks\n * \"Unowned\" previously existed only as a count (`noOwnerCount`) inside\n * `docs.ts`'s `renderSecurityReview()` -- itemized here as real data for the\n * first time, computed via the same `effectiveOwner()` (variable overrides\n * contract) that ADR 0028 also fixed `usage-report.ts`'s ownership findings\n * to use, so this model can never disagree with either of them about who\n * owns a variable.\n */\n\n/** Bump only when a reader could misinterpret the new shape -- same discipline every other canonical model's `schemaVersion` follows. */\nexport const OWNERSHIP_MODEL_SCHEMA_VERSION = 1\n\n/**\n * One variable's effective owner (its own, falling back to the contract's).\n *\n * @see {@link ContractModelVariable} -- this same declared variable's canonical starting point.\n */\nexport interface OwnershipModelVariable {\n readonly key: string\n /** The variable's own `owner`, falling back to the contract's -- see `effectiveOwner()`. */\n readonly owner: string | undefined\n}\n\nexport interface OwnershipModelContract {\n /** Root-relative, POSIX-separated -- matches `ContractModelContract.file`. */\n readonly file: string\n readonly exportName: string\n readonly contractName: string\n /** The contract's own default owner -- not \"effective\" the way a variable's is, since there's no level above a contract to fall back to. */\n readonly owner: string | undefined\n readonly variables: readonly OwnershipModelVariable[]\n}\n\n/** One contract, referenced by identity only -- see {@link ContractRef} for why no `contractName` is carried here. Resolve one from `ContractModel` when a renderer needs display text. */\nexport type OwnershipModelContractRef = ContractRef\n\n/** One variable, referenced by its owning contract's identity plus its own key -- see {@link ContractRef}. */\nexport interface OwnershipModelVariableRef extends ContractRef {\n readonly key: string\n}\n\nexport interface OwnershipModel {\n readonly schemaVersion: typeof OWNERSHIP_MODEL_SCHEMA_VERSION\n readonly contracts: readonly OwnershipModelContract[]\n /** Every contract with no `owner` set at all. */\n readonly unownedContracts: readonly OwnershipModelContractRef[]\n /** Every variable whose effective owner (its own, falling back to the contract's) is still `undefined`. */\n readonly unownedVariables: readonly OwnershipModelVariableRef[]\n}\n\n/**\n * Projects every discovered contract (active or not, same scope as\n * `renderSecurityReview()`'s `noOwnerCount` this model itemizes) into the\n * Ownership Model's versioned, JSON-serializable shape.\n */\nexport function buildOwnershipModel(\n contracts: readonly DiscoveredContract[],\n root: string,\n): OwnershipModel {\n const modelContracts: OwnershipModelContract[] = contracts.map((contract) => ({\n file: displayPath(root, contract.file),\n exportName: contract.exportName,\n contractName: contract.contractName,\n owner: contract.owner,\n variables: [...contract.variables]\n .sort((a, b) => a.key.localeCompare(b.key))\n .map((variable) => ({ key: variable.key, owner: effectiveOwner(contract, variable) })),\n }))\n modelContracts.sort(byContractIdentity)\n\n const unownedContracts: OwnershipModelContractRef[] = modelContracts\n .filter((c) => c.owner === undefined)\n .map(({ file, exportName }) => ({ file, exportName }))\n\n const unownedVariables: OwnershipModelVariableRef[] = []\n for (const contract of modelContracts) {\n for (const variable of contract.variables) {\n if (variable.owner === undefined) {\n unownedVariables.push({\n file: contract.file,\n exportName: contract.exportName,\n key: variable.key,\n })\n }\n }\n }\n\n return {\n schemaVersion: OWNERSHIP_MODEL_SCHEMA_VERSION,\n contracts: modelContracts,\n unownedContracts,\n unownedVariables,\n }\n}\n","/**\n * Substituted at bundle time by `tsup`'s `define` (and by vitest's, for\n * tests) with a string literal read once from `package.json` -- see\n * `tsup.config.ts`. A module-scoped `declare` (not an ambient `.d.ts`) so\n * every tool that type-checks this file, including `ts-json-schema-\n * generator`, sees the name. See ADR 0040.\n */\ndeclare const __PACKAGE_VERSION__: string\n\n/**\n * env-cap's own installed version -- stamped onto\n * `EvidenceModel.provenance.toolVersion` and mixed into\n * `computeSourceFingerprint()`. `./build` never reads its own manifest from\n * disk (ADR 0040).\n */\nexport function readToolVersion(): string {\n return __PACKAGE_VERSION__\n}\n","import path from \"node:path\"\nimport { assembleProject } from \"./assemble-project.js\"\nimport { buildChangeModel } from \"./change-model.js\"\nimport { detectCompatibilityIssues } from \"./compatibility.js\"\nimport { buildContractModel } from \"./contract-model.js\"\nimport { deepFreeze } from \"./deep-freeze.js\"\nimport { buildDependencyModel } from \"./dependency-model.js\"\nimport { EnvProjectGenerationError } from \"./errors.js\"\nimport type { EvidenceModel } from \"./evidence-model.js\"\nimport { EVIDENCE_MODEL_SCHEMA_VERSION } from \"./evidence-model.js\"\nimport { computeEvidenceChanges } from \"./evidence-snapshot.js\"\nimport { detectExclusiveGroupIssues } from \"./exclusive-group.js\"\nimport { buildFindingModel } from \"./finding-model.js\"\nimport { computeDocumentation, DEFAULT_EXPIRING_WITHIN_DAYS } from \"./generate-documentation.js\"\nimport { defaultExclude, defaultInclude } from \"./generate-manifest.js\"\nimport { computeScanSurface, computeUsage } from \"./generate-usage.js\"\nimport { buildLifecycleModel } from \"./lifecycle-model.js\"\nimport { buildOwnershipModel } from \"./ownership-model.js\"\nimport { resolveWithinRoot } from \"./resolution/resolve-within-root.js\"\nimport { resolveLiveExpirationDates } from \"./live-expirations.js\"\nimport type { LiveExpirationDates } from \"./live-expirations.js\"\nimport { readToolVersion } from \"./tool-version.js\"\nimport type { BuildFileSystem } from \"./types.js\"\n\n/** Options for {@link generateEvidenceModel}. */\nexport interface GenerateEvidenceModelOptions {\n /** The filesystem capability -- `./build` never imports `node:fs` (ADR 0040). */\n fs: BuildFileSystem\n /** Directory glob patterns are resolved against. Defaults to `process.cwd()`. */\n root?: string | undefined\n /** Schema-discovery glob for the contract graph. Defaults to `[\"**\\/env.schema.ts\"]`. */\n include?: string[] | undefined\n /** Glob patterns to exclude, shared across every pass. Defaults to node_modules/dist/.git. */\n exclude?: string[] | undefined\n /** **Experimental** (see VERSIONING.md) -- see `GenerateEnvManifestOptions.packages`. See ADR 0014. */\n packages?: readonly string[] | undefined\n /** **Experimental** (see VERSIONING.md) -- see `GenerateEnvManifestOptions.tsconfig`. See ADR 0023. */\n tsconfig?: string | false | undefined\n /**\n * Where a previously-persisted evidence artifact lives, relative to\n * `root` -- read (never written) as the baseline Change Model diffs\n * against and dynamic-access citation freshness (ADR 0037) compares\n * content hashes to. Independent of any `.ts` manifest a project may or\n * may not also generate -- there is no derivation from a manifest's own\n * location. Omitted: treated as the normal first-run state (everything\n * reads as added, no citation-freshness baseline to compare against),\n * never an error.\n */\n previousSnapshotLocation?: string | undefined\n /** Feeds Lifecycle Model's `expiring` list. Defaults to 30. */\n expiringWithinDays?: number | undefined\n /**\n * Supplies expiration metadata from a live source as a post-discovery\n * override, applied to Lifecycle Model's (and Finding Model's\n * `expiring-soon` findings') data only -- Contract Model still reflects the\n * schema's own static `expiresAt`. See `live-expirations.ts` and ADR 0012.\n */\n liveExpirationDates?: LiveExpirationDates | undefined\n /**\n * Resolves the commit SHA to stamp onto `EvidenceModel.provenance.commit`.\n * Invoked at most once, after discovery/linking completes. env-cap never\n * shells out to `git` itself -- see ADR 0012's callback precedent. Omitted:\n * `commit` is `undefined`.\n */\n commit?: (() => Promise<string | undefined>) | undefined\n}\n\n/**\n * Node-only assembly orchestrator (ADR 0024, ADR 0031): runs schema\n * discovery and linking once (via `assembleProject()`, shared with\n * `computeArtifacts()`), then builds all seven canonical fact models by\n * calling each model's own public builder directly -- this function\n * introduces no derivation logic of its own, only sequencing and the shared\n * discovery/linking every builder needs. The result is `deepFreeze()`-d\n * before being returned.\n *\n * @remarks\n * Deliberately never throws on a data-quality finding (a compatibility\n * issue, an undocumented variable, an abandoned contract, ...) -- every one\n * of those becomes a `Finding` in the returned model's `finding` field\n * instead. This is a real difference from `generateEnvManifest()`, which\n * throws by default: that's a \"should I write this artifact\" gate, while\n * Evidence Model assembly is a read-only snapshot whose entire purpose is\n * representing such issues as data for a consumer's own projection to act\n * on (see ADR 0024's mission statement). It still throws\n * `EnvProjectGenerationError` for a genuine configuration error --\n * `previousSnapshotLocation` escaping `root`.\n *\n * The dependency-graph scan underlying Dependency Model (via\n * `buildDependencyModel()`) and the one underlying Finding Model's\n * ownership-related findings (via `computeUsage()`) each run their own,\n * independent pass over the repository -- a real, accepted cost of calling\n * each half's already-tested public building block directly rather than\n * hand-deriving a second copy of either's logic here. Both are Node-only,\n * dev/CI-time-only work (never a runtime hot path), so the redundant I/O is\n * an honest tradeoff, not an oversight.\n */\nexport async function generateEvidenceModel(\n options: GenerateEvidenceModelOptions,\n): Promise<EvidenceModel> {\n const root = path.resolve(options.root ?? process.cwd())\n const include = options.include ?? defaultInclude()\n const exclude = options.exclude ?? defaultExclude()\n // `??`-vs-`||` is unobservable here: `packages?: readonly string[]` is\n // either `undefined` or a real array, never another falsy value (`0`,\n // `\"\"`, `false`) the two operators would treat differently -- and even an\n // `undefined` that slipped through both defaults, `new Set(undefined)`\n // downstream in `resolveAllowlistedPackages`, is spec-defined to produce\n // an empty Set, identical to `new Set([])`. A garbage non-empty fallback\n // (`[\"Stryker was here\"]`) is equally unobservable -- empirically\n // confirmed (see `evidence-cache.ts`'s identical fallback) that an\n // unresolvable package name contributes zero files to anything\n // downstream, since `resolveAllowlistedPackages` never throws for one.\n // Stryker disable next-line LogicalOperator,ArrayDeclaration\n const packages = options.packages ?? []\n const expiringWithinDays = options.expiringWithinDays ?? DEFAULT_EXPIRING_WITHIN_DAYS\n\n let snapshotPath: string | undefined\n if (options.previousSnapshotLocation !== undefined) {\n const result = resolveWithinRoot(\n root,\n options.previousSnapshotLocation,\n \"previousSnapshotLocation\",\n \"generateEvidenceModel\",\n )\n if (!result.ok) throw new EnvProjectGenerationError([result.issue])\n snapshotPath = result.resolved\n }\n\n const assembled = await assembleProject({\n fs: options.fs,\n root,\n include,\n exclude,\n packages,\n tsconfig: options.tsconfig,\n })\n const { readFileCached, linkResult, context, origins, packageWarnings, tsconfigWarnings } =\n assembled\n\n const generatedAt = new Date()\n const activeContracts = linkResult.contracts.filter((c) => c.active)\n\n // Lifecycle Model (and Finding Model's expiring-soon findings) reflect the\n // freshest live-resolved expiry data, mirroring the docs pass -- Contract\n // Model below still reflects the schema's own static `expiresAt`.\n const lifecycleContracts = options.liveExpirationDates\n ? await resolveLiveExpirationDates(linkResult.contracts, options.liveExpirationDates)\n : linkResult.contracts\n\n const contract = buildContractModel(linkResult.contracts, root)\n const ownership = buildOwnershipModel(linkResult.contracts, root)\n const lifecycle = buildLifecycleModel(lifecycleContracts, expiringWithinDays, generatedAt, root)\n\n const evidenceChanges = snapshotPath\n ? await computeEvidenceChanges(\n root,\n snapshotPath,\n activeContracts,\n contract.contracts,\n readFileCached,\n options.fs,\n )\n : undefined\n const change = buildChangeModel(\n evidenceChanges?.report ?? {\n addedContracts: [],\n removedContracts: [],\n addedVariables: [],\n removedVariables: [],\n updatedContracts: [],\n updatedVariables: [],\n },\n linkResult.contracts,\n root,\n )\n\n const { scanFiles, scannedSurfaces } = await computeScanSurface(\n root,\n exclude,\n origins,\n options.fs,\n )\n const dependency = await buildDependencyModel(\n linkResult.contracts,\n scanFiles,\n readFileCached,\n context,\n root,\n scannedSurfaces,\n evidenceChanges?.dynamicAccessAcknowledgments,\n )\n\n const documentationComputed = computeDocumentation(\n root,\n { ...linkResult, contracts: lifecycleContracts },\n expiringWithinDays,\n generatedAt,\n )\n // This array feeds `computeUsage()`'s `parseWarnings` parameter, which\n // (checked: it's used nowhere else in `computeUsage`'s own body besides\n // this) is pure pass-through data, echoed straight into `usageComputed\n // .result.parseWarnings` -- a field this function never reads (only\n // `.abandonedContracts`/`.unresolvedConsumers`/`.unconsumedOwnedVariables`\n // /`.indeterminate` feed the returned EvidenceModel's `finding`, below).\n // Mutating this array to `[]` changes nothing `generateEvidenceModel`\n // itself ever returns.\n const usageComputed = await computeUsage(\n root,\n linkResult.contracts,\n scanFiles,\n readFileCached,\n context,\n // Stryker disable next-line ArrayDeclaration\n [...packageWarnings, ...tsconfigWarnings, ...linkResult.warnings],\n scannedSurfaces,\n evidenceChanges?.dynamicAccessAcknowledgments,\n )\n\n const finding = buildFindingModel({\n root,\n compatibilityIssues: detectCompatibilityIssues(activeContracts),\n exclusiveGroupIssues: detectExclusiveGroupIssues(activeContracts),\n documentation: documentationComputed.documentation,\n abandonedContracts: usageComputed.result.abandonedContracts,\n unresolvedConsumers: usageComputed.result.unresolvedConsumers,\n unconsumedOwnedVariables: usageComputed.result.unconsumedOwnedVariables,\n indeterminateOwnership: usageComputed.result.indeterminate,\n // `buildFindingModel` (finding-model.ts) has its own `?? []` fallback\n // on this exact same field, so even an `undefined` that slipped past\n // this one (e.g. `??`-vs-`&&` on `evidenceChanges?.…`) is caught there\n // identically -- belt-and-suspenders, not independently observable.\n // Stryker disable next-line LogicalOperator\n dynamicAccessCitationProblems: evidenceChanges?.dynamicAccessCitationProblems ?? [],\n })\n\n const commit = options.commit ? await options.commit() : undefined\n\n return deepFreeze({\n schemaVersion: EVIDENCE_MODEL_SCHEMA_VERSION,\n provenance: { generatedAt: generatedAt.toISOString(), toolVersion: readToolVersion(), commit },\n contract,\n dependency,\n ownership,\n lifecycle,\n finding,\n change,\n })\n}\n","import crypto from \"node:crypto\"\nimport path from \"node:path\"\nimport { discoverSchemaFiles } from \"./discover.js\"\nimport { displayPath } from \"./display-path.js\"\nimport type { EvidenceModel } from \"./evidence-model.js\"\nimport { readEvidenceSnapshot } from \"./evidence-snapshot.js\"\nimport { defaultExclude, defaultInclude } from \"./generate-manifest.js\"\nimport { computeScanSurface } from \"./generate-usage.js\"\nimport { generateEvidenceModel } from \"./generate-evidence.js\"\nimport type { GenerateEvidenceModelOptions } from \"./generate-evidence.js\"\nimport {\n mergeLocalAndPackageFiles,\n resolveAllowlistedPackages,\n} from \"./resolution/resolve-package-schema.js\"\nimport type { PackageSchemaResolutionResult } from \"./resolution/resolve-package-schema.js\"\nimport { readToolVersion } from \"./tool-version.js\"\nimport type { BuildFileSystem } from \"./types.js\"\n\n/**\n * A fast, honest read path for the persisted evidence artifact -- for a\n * report/projection script, a CI step, or any consumer that just wants the\n * current `EvidenceModel` without paying a full `generateEvidenceModel()`\n * recompute (schema parsing, cross-file linking, the dependency-graph AST\n * scan, all six model builds) on every single invocation, and without ever\n * risking silently-stale data. The mechanism: a cheap content fingerprint,\n * computed from raw file bytes with zero AST work, lets a caller cheaply\n * prove \"nothing relevant to evidence generation has changed since this file\n * was last written\" before trusting it.\n */\n\n/** Options for {@link computeSourceFingerprint}. */\nexport interface ComputeSourceFingerprintOptions {\n /** The filesystem capability -- `./build` never imports `node:fs` (ADR 0040). */\n readonly fs: BuildFileSystem\n readonly root: string\n readonly include: readonly string[]\n readonly exclude: readonly string[]\n readonly packages: readonly string[]\n}\n\n/**\n * SHA-256 over the raw bytes of every schema file and every usage-scan-\n * surface file (the same file sets `assembleProject()`/`computeScanSurface()`\n * touch), plus env-cap's own installed version -- zero AST parsing or\n * linking. Still requires the discovery/glob walk itself (fingerprinting has\n * to know which files matter), but skips everything after it. Deterministic:\n * file paths are deduplicated and sorted before hashing, so the result never\n * depends on filesystem enumeration order.\n *\n * @remarks\n * Not a timestamp, and never compared as one -- a fresh mtime doesn't prove\n * content is unchanged (a checkout, a rebase, or a touch can all bump it\n * with no real edit), and content is the only thing that actually\n * invalidates a cached evidence artifact.\n */\nexport async function computeSourceFingerprint(\n options: ComputeSourceFingerprintOptions,\n): Promise<string> {\n const { fs, root, include, exclude, packages } = options\n\n const localSchemaFiles = await discoverSchemaFiles({ fs, root, include, exclude })\n const packageCache = new Map<string, Promise<PackageSchemaResolutionResult>>()\n const { files: packageFiles, origins } = await resolveAllowlistedPackages(\n packages,\n root,\n packageCache,\n fs,\n )\n const schemaFiles = await mergeLocalAndPackageFiles(\n localSchemaFiles,\n packageFiles.map((f) => f.file),\n fs,\n )\n const { scanFiles } = await computeScanSurface(root, exclude, origins, fs)\n\n const allFiles = [...new Set([...schemaFiles, ...scanFiles])].sort()\n\n const hash = crypto.createHash(\"sha256\")\n hash.update(readToolVersion())\n for (const file of allFiles) {\n // Root-relative, not the raw absolute path -- an absolute path bakes in\n // wherever this checkout happens to live (e.g. /home/runner/work/... in\n // CI vs a contributor's own machine), so hashing it directly made this\n // fingerprint -- and the committed .fingerprint sidecar that pins it --\n // differ by checkout location alone, with the file's content unchanged.\n hash.update(displayPath(root, file))\n try {\n // Empirically confirmed equivalent to omitting the encoding (and thus\n // getting a Buffer back instead of a string): `hash.update()` accepts\n // either, and for any valid-UTF-8 file (every real TS/JS source file\n // qualifies) a Buffer's raw bytes and its UTF-8-decoded string\n // produce byte-identical SHA-256 digests either way (verified via a\n // real `node -e` comparison, not just reasoning).\n // Stryker disable next-line StringLiteral\n hash.update(await fs.readFile(file, \"utf8\"))\n } catch {\n // A file the glob walk found but can't be read by the time we hash it\n // (deleted mid-run, a race with another process) -- folded into the\n // hash as a distinct marker so the fingerprint still changes rather\n // than silently treating a vanished file as if it were never there.\n hash.update(\"(unreadable)\")\n }\n }\n return hash.digest(\"hex\")\n}\n\nfunction fingerprintPathFor(evidencePath: string): string {\n return `${evidencePath}.fingerprint`\n}\n\n/** Writes `fingerprint`'s paired sidecar for `evidencePath` -- call immediately after writing the evidence artifact itself, so the two files always describe the same moment in the source tree's history. */\nexport async function writeEvidenceFingerprint(\n evidencePath: string,\n fingerprint: string,\n fs: BuildFileSystem,\n): Promise<void> {\n // Empirically confirmed equivalent (real `node -e` byte comparison): the\n // written content is always a sha256 hex digest plus a newline, pure\n // ASCII, which \"utf8\" and an invalid/empty encoding write out to\n // byte-identical files either way.\n // Stryker disable next-line StringLiteral\n await fs.writeFile(fingerprintPathFor(evidencePath), `${fingerprint}\\n`, \"utf8\")\n}\n\n/** Options for {@link getEvidenceModel} -- every `generateEvidenceModel()` option, plus where the cached artifact lives. */\nexport interface GetEvidenceModelOptions extends GenerateEvidenceModelOptions {\n /** Where the cached evidence artifact (and its `.fingerprint` sidecar) live, e.g. `docs/env.evidence.json`, relative to `root`. Required -- there is no honest default env-cap could guess at for where a project keeps this. */\n readonly location: string\n}\n\n/** The result of {@link getEvidenceModel}. */\nexport interface GetEvidenceModelResult {\n readonly evidence: EvidenceModel\n /** `\"hit\"` -- the committed evidence artifact's fingerprint matched current source; read from disk, no recompute. `\"miss\"` -- a real `generateEvidenceModel()` call ran. */\n readonly source: \"hit\" | \"miss\"\n /** Set only when `source === \"miss\"` -- why the cache wasn't trusted, for a caller that wants to log it. */\n readonly missReason: string | undefined\n}\n\n/**\n * Trusts the committed evidence artifact at `options.location` only when its\n * paired `.fingerprint` sidecar matches a freshly (cheaply) computed\n * {@link computeSourceFingerprint} -- never on file presence alone, never on\n * a timestamp. On any mismatch (stale fingerprint, missing/corrupt evidence\n * file, no fingerprint sidecar at all), falls back to a real\n * `generateEvidenceModel()` call -- never hard-fails, never silently serves\n * data that might be stale.\n *\n * @remarks\n * Never writes anything. A cache miss here does not self-heal the cache --\n * only an explicit write (`generateEnvArtifacts()`'s `evidence` option)\n * refreshes the committed artifact and its fingerprint together, so \"when\n * was this last regenerated\" stays under explicit control, never an\n * implicit side effect of a read. Two independent callers hitting the same\n * stale cache both recompute independently; neither one's recompute updates\n * the file the other reads.\n */\nexport async function getEvidenceModel(\n options: GetEvidenceModelOptions,\n): Promise<GetEvidenceModelResult> {\n const root = path.resolve(options.root ?? process.cwd())\n const include = options.include ?? defaultInclude()\n const exclude = options.exclude ?? defaultExclude()\n // Empirically confirmed equivalent even with a garbage non-empty fallback:\n // an unresolvable package name contributes zero files to\n // `computeSourceFingerprint`'s hash (`resolveAllowlistedPackages` never\n // throws for one, per its own doc comment, just resolves nothing) --\n // verified directly (`node -e ...` against a built copy) that the\n // resulting fingerprint is byte-identical whether `packages` is `[]` or\n // `[\"garbage\"]`. `??` vs `&&` is equivalent too: for the common case\n // (`options.packages` omitted, `undefined`), `&&` short-circuits to\n // `undefined` itself rather than `[]` -- but `new Set(undefined)` is\n // spec-defined to produce an empty Set, identical to `new Set([])`.\n // Stryker disable next-line ArrayDeclaration,LogicalOperator\n const packages = options.packages ?? []\n\n const evidencePath = path.resolve(root, options.location)\n const fingerprintPath = fingerprintPathFor(evidencePath)\n\n const recompute = async (missReason: string): Promise<GetEvidenceModelResult> => ({\n evidence: await generateEvidenceModel(options),\n source: \"miss\",\n missReason,\n })\n\n // Genuinely hard to trigger through the public API in isolation from\n // `recompute()`'s own `generateEvidenceModel()` call: both share the same\n // `discoverSchemaFiles`/`resolveAllowlistedPackages` machinery, so a\n // fault that breaks fingerprint computation (tried: a nonexistent `root`)\n // breaks evidence generation identically, and `recompute()` itself throws\n // uncaught before this catch's own behavior could ever be observed\n // in isolation; `resolveAllowlistedPackages` is also explicitly documented\n // (\"never throw here\") not to throw for a malformed entry. Kept as real,\n // defensive error handling regardless -- `fs.readFile` failures inside\n // `computeSourceFingerprint`'s per-file loop are already caught there\n // (see the \"(unreadable)\" marker above), so what could still reach here\n // is deliberately unclear/future-proofing, not a known-reachable path.\n let currentFingerprint: string\n // Stryker disable BlockStatement, StringLiteral\n try {\n currentFingerprint = await computeSourceFingerprint({\n fs: options.fs,\n root,\n include,\n exclude,\n packages,\n })\n } catch (error) {\n return recompute(\n `could not compute a source fingerprint (${error instanceof Error ? error.message : String(error)})`,\n )\n }\n // Stryker restore BlockStatement, StringLiteral\n\n let storedFingerprint: string\n try {\n storedFingerprint = (await options.fs.readFile(fingerprintPath, \"utf8\")).trim()\n } catch {\n return recompute(`no fingerprint sidecar found at ${fingerprintPath}`)\n }\n\n if (storedFingerprint !== currentFingerprint) {\n return recompute(\n \"source fingerprint changed since the committed evidence artifact was last generated\",\n )\n }\n\n const read = await readEvidenceSnapshot(evidencePath, options.fs)\n if (read.status !== \"ok\") {\n return recompute(\n read.status === \"missing\"\n ? `no evidence artifact found at ${evidencePath}`\n : read.status === \"invalid-json\"\n ? `evidence artifact at ${evidencePath} could not be parsed as JSON (${read.detail})`\n : `evidence artifact at ${evidencePath} has an unrecognized schemaVersion (${JSON.stringify(read.foundVersion)})`,\n )\n }\n\n return { evidence: read.snapshot, source: \"hit\", missReason: undefined }\n}\n","import path from \"node:path\"\nimport { assembleProject } from \"./assemble-project.js\"\nimport { buildChangeModel } from \"./change-model.js\"\nimport type { CompatibilityIssue } from \"./compatibility.js\"\nimport { detectCompatibilityIssues, detectDuplicateVariableShapes } from \"./compatibility.js\"\nimport { buildContractModel } from \"./contract-model.js\"\nimport { deepFreeze } from \"./deep-freeze.js\"\nimport { buildDependencyModel } from \"./dependency-model.js\"\nimport { EnvProjectGenerationError } from \"./errors.js\"\nimport type { EvidenceModel } from \"./evidence-model.js\"\nimport { EVIDENCE_MODEL_SCHEMA_VERSION } from \"./evidence-model.js\"\nimport { computeSourceFingerprint, writeEvidenceFingerprint } from \"./evidence-cache.js\"\nimport { computeEvidenceChanges, writeEvidenceSnapshot } from \"./evidence-snapshot.js\"\nimport type { EvidenceChangesComputation } from \"./evidence-snapshot.js\"\nimport { detectExclusiveGroupIssues } from \"./exclusive-group.js\"\nimport { buildFindingModel } from \"./finding-model.js\"\nimport type { Finding, FindingFamily } from \"./finding-model.js\"\nimport {\n computeDocumentation,\n DEFAULT_EXPIRING_WITHIN_DAYS,\n writeDocumentation,\n} from \"./generate-documentation.js\"\nimport type {\n DocumentationComputation,\n GenerateDocumentationOptions,\n GenerateDocumentationResult,\n} from \"./generate-documentation.js\"\nimport {\n computeManifest,\n defaultExclude,\n defaultInclude,\n writeManifest,\n} from \"./generate-manifest.js\"\nimport type {\n GenerateEnvManifestOptions,\n GenerateEnvManifestResult,\n ManifestComputation,\n} from \"./generate-manifest.js\"\nimport { computeScanSurface, computeUsage, writeUsageReport } from \"./generate-usage.js\"\nimport type {\n GenerateUsageReportOptions,\n GenerateUsageReportResult,\n UsageComputation,\n} from \"./generate-usage.js\"\nimport type { DiscoveredContract } from \"./link.js\"\nimport { buildLifecycleModel } from \"./lifecycle-model.js\"\nimport { buildOwnershipModel } from \"./ownership-model.js\"\nimport { resolveLiveExpirationDates } from \"./live-expirations.js\"\nimport type { LiveExpirationDates } from \"./live-expirations.js\"\nimport type { ParseWarning } from \"./parse.js\"\nimport { resolveWithinRoot } from \"./resolution/resolve-within-root.js\"\nimport { readToolVersion } from \"./tool-version.js\"\nimport type { BuildFileSystem } from \"./types.js\"\n\n/** Options for {@link generateEnvArtifacts}. */\nexport interface GenerateEnvArtifactsOptions {\n /** The filesystem capability, shared across every requested pass -- `./build` never imports `node:fs` (ADR 0040). */\n fs: BuildFileSystem\n /** Directory glob patterns are resolved against, shared across every requested pass. Defaults to `process.cwd()`. */\n root?: string | undefined\n /** Shared schema-discovery glob for the contract graph. Defaults to `[\"**\\/env.schema.ts\"]`. */\n include?: string[] | undefined\n /** Glob patterns to exclude, shared across every requested pass. Defaults to node_modules/dist/.git. */\n exclude?: string[] | undefined\n /** **Experimental** (see VERSIONING.md) -- see `GenerateEnvManifestOptions.packages`; shared across every requested pass. See ADR 0014. */\n packages?: readonly string[] | undefined\n /** **Experimental** (see VERSIONING.md) -- see `GenerateEnvManifestOptions.tsconfig`; shared across every requested pass. See ADR 0023. */\n tsconfig?: string | false | undefined\n /** Manifest pass options, or `false` to skip it entirely. */\n manifest?:\n | Omit<\n GenerateEnvManifestOptions,\n \"fs\" | \"root\" | \"include\" | \"exclude\" | \"packages\" | \"tsconfig\"\n >\n | false\n | undefined\n /** Docs pass options, or `false` to skip it entirely. */\n docs?:\n | Omit<\n GenerateDocumentationOptions,\n \"fs\" | \"root\" | \"include\" | \"exclude\" | \"packages\" | \"tsconfig\" | \"liveExpirationDates\"\n >\n | false\n | undefined\n /** Usage-report pass options, or `false` to skip it entirely. */\n usage?:\n | Omit<\n GenerateUsageReportOptions,\n \"fs\" | \"root\" | \"include\" | \"exclude\" | \"packages\" | \"tsconfig\"\n >\n | false\n | undefined\n /**\n * Where to write the persisted evidence artifact (the full, literal\n * `EvidenceModel`, plus a paired `.fingerprint` sidecar -- see\n * `evidence-cache.ts`), e.g. `docs/env.evidence.json`, relative to `root`.\n * Independent of `manifest.location` -- requesting this needs no other\n * pass, and generating a manifest never requires it. `EvidenceModel`\n * itself is always computed regardless of this option (ADR 0038, \"free to\n * compute, always real\") and always returned as `result.evidence`; this\n * option controls only whether it's also written to disk. Omitted:\n * nothing is written, `result.evidence` is still populated.\n */\n evidence?: { location: string } | false | undefined\n /**\n * Escalates every warning-severity `\"documentation\"`-family finding\n * (undocumented contracts/variables, stale doc entries, expiring/expired\n * entries, unresolvable `documentEnv()` links) into a blocking error, so a\n * run with any of them writes nothing and throws. Defaults to `\"warn\"` --\n * ADR 0038's stance, unchanged: documentation gaps never block by default.\n *\n * @remarks\n * Scoped deliberately narrowly, unlike `manifest.onIncompatibility`, which\n * gates only the compatibility family. `\"info\"`-severity findings are never\n * escalated by either -- see `Finding.severity`.\n */\n onUndocumented?: \"warn\" | \"throw\" | undefined\n /**\n * Escalates every warning-severity `\"ownership\"`-family finding (abandoned\n * contracts, unresolved consumers, unconsumed owned variables,\n * indeterminate ownership, stale/missing `dynamicAccess` citations) into a\n * blocking error. Defaults to `\"warn\"` -- see {@link onUndocumented}.\n */\n onOwnershipIssue?: \"warn\" | \"throw\" | undefined\n /**\n * Supplies expiration metadata from a live source (a secrets manager, an\n * internal inventory API, ...) as a post-discovery override applied only to\n * the docs pass. Invoked at most once, only when a `docs` pass is actually\n * requested, with every discovered variable name across all passes' shared\n * contract graph. See `live-expirations.ts` and ADR 0012. Omitted: behavior\n * is unchanged from a purely static `expiresAt`.\n */\n liveExpirationDates?: LiveExpirationDates | undefined\n}\n\n/** The result of a completed {@link generateEnvArtifacts} run. */\nexport interface GenerateEnvArtifactsResult {\n /** Set only when `options.manifest` wasn't `false`. */\n readonly manifest: GenerateEnvManifestResult | undefined\n /** Set only when `options.docs` wasn't `false`. */\n readonly docs: GenerateDocumentationResult | undefined\n /** Set only when `options.usage` wasn't `false`. */\n readonly usage: GenerateUsageReportResult | undefined\n /** Always populated, regardless of `options.evidence` -- see that option's own doc comment. */\n readonly evidence: EvidenceModel\n}\n\n/**\n * Every intermediate value both the write path (`generateEnvArtifacts()`\n * below) and the drift-check path (`checkEnvArtifacts()` in\n * `check-artifacts.ts`) need, computed exactly once. Internal/Private tier\n * per `VERSIONING.md` -- not re-exported from `./index.ts`.\n */\nexport interface ComputeArtifactsResult {\n readonly root: string\n readonly manifestOptions:\n | Omit<\n GenerateEnvManifestOptions,\n \"fs\" | \"root\" | \"include\" | \"exclude\" | \"packages\" | \"tsconfig\"\n >\n | undefined\n readonly manifestOutputPath: string | undefined\n readonly manifestComputed: ManifestComputation | undefined\n readonly docsOptions:\n | Omit<\n GenerateDocumentationOptions,\n \"fs\" | \"root\" | \"include\" | \"exclude\" | \"packages\" | \"tsconfig\" | \"liveExpirationDates\"\n >\n | undefined\n readonly docsPath: string | undefined\n readonly envExamplePath: string | undefined\n /** Always computed -- Finding Model needs it regardless of whether a `docs` pass was itself requested. See ADR 0038. */\n readonly docsComputed: DocumentationComputation\n readonly docsContracts: readonly DiscoveredContract[]\n readonly usageOptions:\n | Omit<\n GenerateUsageReportOptions,\n \"fs\" | \"root\" | \"include\" | \"exclude\" | \"packages\" | \"tsconfig\"\n >\n | undefined\n readonly usageReportPath: string | undefined\n /** Always computed -- Finding Model needs it regardless of whether a `usage` pass was itself requested. See ADR 0038. */\n readonly usageComputed: UsageComputation\n readonly evidencePath: string | undefined\n readonly evidence: EvidenceModel\n readonly blocking: readonly CompatibilityIssue[]\n readonly packageWarnings: readonly ParseWarning[]\n readonly linkWarnings: readonly ParseWarning[]\n /** Single timestamp shared by every pass' own time-sensitive computation (`expiringSoon`, `EvidenceModel.provenance.generatedAt`), so all of them agree on exactly the same instant. */\n readonly generatedAt: Date\n}\n\n/**\n * Adapts every warning-severity finding of one family into the\n * `CompatibilityIssue` shape `blocking`/`EnvProjectGenerationError` speak, so\n * `--strict-docs`/`--strict-ownership` fail through exactly the same path\n * `--strict` already does rather than inventing a second failure mode.\n *\n * @remarks\n * `\"info\"` findings are filtered out unconditionally and can never be\n * escalated by any flag -- they're observations, not gaps (see\n * `Finding.severity`). `\"error\"` findings are excluded too: those already\n * block on their own, via the manifest pass, and re-adding them here would\n * report the same violation twice in one error message. `code` is left unset\n * -- `CompatibilityIssueCode` is that check family's own closed vocabulary,\n * and a `FindingCode` from another family is not a member of it.\n */\n/** @internal Exported for direct unit coverage -- reached through `generateEnvArtifacts()`'s `--strict-docs`/`--strict-ownership` flags in production, but its filter/mapping logic isn't independently observable through that path alone (every mutant on it still needs a real `computeArtifacts()` call, discovery included, to reach it). */\nexport function escalatedFindings(\n findings: readonly Finding[],\n family: FindingFamily,\n): CompatibilityIssue[] {\n return findings\n .filter((f) => f.family === family && f.severity === \"warning\")\n .map((f) => ({\n severity: \"error\" as const,\n variable: findingSubject(f),\n files: findingFiles(f),\n reason: `[${f.code}] ${f.message}`,\n }))\n}\n\n/** The variable a finding is about, or a `\"(contract) <name>\"` label when it's contract-level -- matching `CompatibilityIssue.variable`'s own documented convention.\n * @internal Exported for direct unit coverage -- see {@link escalatedFindings}'s own doc comment for why. */\nexport function findingSubject(finding: Finding): string {\n const location = finding.location\n if (location.model === \"change\") return `(artifact) ${location.path}`\n if (location.variable !== undefined) return location.variable\n const name = location.model === \"ownership\" ? location.contractName : location.exportName\n return `(contract) ${name ?? \"unknown\"}`\n}\n\n/** Every file a finding names, as `CompatibilityIssue.files` -- empty when its location carries none (an ownership finding about a variable, which names no single file).\n * @internal Exported for direct unit coverage -- see {@link escalatedFindings}'s own doc comment for why. */\nexport function findingFiles(finding: Finding): string[] {\n const location = finding.location\n if (location.model === \"change\") return [location.path]\n return location.file === undefined ? [] : [location.file]\n}\n\n/**\n * Runs schema discovery, linking, and every requested pass's pure `compute*()`\n * step -- but never writes anything to disk. Throws `EnvProjectGenerationError`\n * immediately if any requested output location escapes `root` (same\n * fail-fast-before-any-work guarantee `generateEnvArtifacts()` has always\n * given); otherwise returns every intermediate value without itself checking\n * `blocking` findings, so callers (the write path below, and `--check`'s\n * `checkEnvArtifacts()`) each decide when to throw on those.\n *\n * @remarks\n * The six canonical fact models (Contract/Dependency/Ownership/Lifecycle/\n * Finding/Change -> `EvidenceModel`) are composed on every call,\n * unconditionally, reusing the exact same builders `generateEvidenceModel()`\n * calls -- not a second implementation of the same assembly. See ADR 0038.\n */\nexport async function computeArtifacts(\n options: GenerateEnvArtifactsOptions,\n): Promise<ComputeArtifactsResult> {\n const root = path.resolve(options.root ?? process.cwd())\n const include = options.include ?? defaultInclude()\n const exclude = options.exclude ?? defaultExclude()\n const packages = options.packages ?? []\n\n // Every mutant on these four lines (bypassing the `=== false` check\n // entirely, or comparing against `true` instead of `false`) is\n // behaviorally equivalent, not a real gap: every downstream consumer of\n // `manifestOptions`/`docsOptions`/`usageOptions`/`evidenceOptions` only\n // ever truthy-checks it (`if (manifestOptions) {...}`, `manifestOptions ?\n // ... : undefined`) -- it never distinguishes the literal `false` a\n // bypassed/differently-compared ternary could produce from a genuine\n // `undefined`, since both are equally falsy. Hand-verified: mutating all\n // four lines (both variants) and running the real suite passes unchanged.\n // Stryker disable next-line ConditionalExpression,BooleanLiteral\n const manifestOptions = options.manifest === false ? undefined : options.manifest\n // Stryker disable next-line ConditionalExpression,BooleanLiteral\n const docsOptions = options.docs === false ? undefined : options.docs\n // Stryker disable next-line ConditionalExpression,BooleanLiteral\n const usageOptions = options.usage === false ? undefined : options.usage\n // Stryker disable next-line ConditionalExpression,BooleanLiteral\n const evidenceOptions = options.evidence === false ? undefined : options.evidence\n\n const pathIssues: CompatibilityIssue[] = []\n\n let manifestOutputPath: string | undefined\n if (manifestOptions) {\n const result = resolveWithinRoot(\n root,\n manifestOptions.location,\n \"manifest.location\",\n \"generateEnvArtifacts\",\n )\n if (result.ok) manifestOutputPath = result.resolved\n else pathIssues.push(result.issue)\n }\n\n let docsPath: string | undefined\n let envExamplePath: string | undefined\n if (docsOptions) {\n const result = resolveWithinRoot(\n root,\n docsOptions.location,\n \"docs.location\",\n \"generateEnvArtifacts\",\n )\n if (result.ok) docsPath = result.resolved\n else pathIssues.push(result.issue)\n\n if (docsOptions.envExample) {\n const exampleResult = resolveWithinRoot(\n root,\n docsOptions.envExample.location,\n \"docs.envExample.location\",\n \"generateEnvArtifacts\",\n )\n if (exampleResult.ok) envExamplePath = exampleResult.resolved\n else pathIssues.push(exampleResult.issue)\n }\n }\n\n let usageReportPath: string | undefined\n if (usageOptions?.report) {\n const result = resolveWithinRoot(\n root,\n usageOptions.report.location,\n \"usage.report.location\",\n \"generateEnvArtifacts\",\n )\n if (result.ok) usageReportPath = result.resolved\n else pathIssues.push(result.issue)\n }\n\n let evidencePath: string | undefined\n if (evidenceOptions) {\n const result = resolveWithinRoot(\n root,\n evidenceOptions.location,\n \"evidence.location\",\n \"generateEnvArtifacts\",\n )\n if (result.ok) evidencePath = result.resolved\n else pathIssues.push(result.issue)\n }\n\n // Fail fast, before any discovery/parsing work and before any file is\n // written -- same atomicity guarantee `generateEnvManifest()` etc. give\n // standalone, now widened across every requested pass at once.\n if (pathIssues.length > 0) throw new EnvProjectGenerationError(pathIssues)\n\n const { readFileCached, linkResult, context, origins, packageWarnings, tsconfigWarnings } =\n await assembleProject({\n fs: options.fs,\n root,\n include,\n exclude,\n packages,\n tsconfig: options.tsconfig,\n })\n const generatedAt = new Date()\n const activeContracts = linkResult.contracts.filter((c) => c.active)\n\n // Invoked at most once regardless of how many passes below end up wanting\n // live-resolved expiry data -- Lifecycle Model (always built, ADR 0038)\n // and the docs pass (when requested) both read from this same result\n // rather than each triggering their own call.\n const liveExpirationContracts = options.liveExpirationDates\n ? await resolveLiveExpirationDates(linkResult.contracts, options.liveExpirationDates)\n : linkResult.contracts\n const docsContracts = docsOptions ? liveExpirationContracts : linkResult.contracts\n\n // Manifest is the one pass that still blocks (ADR 0009's provable\n // exclusive-group/compatibility errors) -- docs/ownership never do (ADR\n // 0038: a team that wants to gate CI on either reads `Finding[]` from the\n // evidence artifact and decides for itself).\n const blocking: CompatibilityIssue[] = []\n // `computeManifest()` only ever compares this value `=== \"throw\"` (see its\n // own body) -- \"warn\" and any other non-\"throw\" string (including `\"\"`)\n // take the identical non-throw branch, so the literal fallback text itself\n // is unobservable; only whether the CALLER explicitly passed \"throw\" (the\n // `??` vs `&&` distinction, tested separately) matters. Hand-verified:\n // mutating \"warn\" -> \"\" and running the real suite (`vitest run`, whole\n // package) passes unchanged.\n // Stryker disable StringLiteral\n const manifestComputed = manifestOptions\n ? computeManifest(root, linkResult, manifestOptions.onIncompatibility ?? \"warn\")\n : undefined\n // Stryker restore StringLiteral\n if (manifestComputed) blocking.push(...manifestComputed.blocking)\n\n // Computed unconditionally, once each -- Finding Model (part of the\n // always-built EvidenceModel) needs both regardless of whether a `docs`/\n // `usage` pass was itself requested, so this is never a second,\n // differently-parameterized call the way it used to be when\n // `onUndocumented`/`onOwnershipIssue` still existed (both computations are\n // now free of any throw-severity parameter, so there's exactly one shape\n // of result to compute, shared by both the artifact and Finding Model).\n const docsComputed = computeDocumentation(\n root,\n { ...linkResult, contracts: liveExpirationContracts },\n docsOptions?.expiringWithinDays ?? DEFAULT_EXPIRING_WITHIN_DAYS,\n generatedAt,\n )\n\n const { scanFiles, scannedSurfaces } = await computeScanSurface(\n root,\n exclude,\n origins,\n options.fs,\n )\n\n const contract = buildContractModel(linkResult.contracts, root)\n const evidenceChanges: EvidenceChangesComputation | undefined = evidencePath\n ? await computeEvidenceChanges(\n root,\n evidencePath,\n activeContracts,\n contract.contracts,\n readFileCached,\n options.fs,\n )\n : undefined\n\n const usageComputed = await computeUsage(\n root,\n linkResult.contracts,\n scanFiles,\n readFileCached,\n context,\n [...packageWarnings, ...tsconfigWarnings, ...linkResult.warnings],\n scannedSurfaces,\n evidenceChanges?.dynamicAccessAcknowledgments,\n )\n\n const ownership = buildOwnershipModel(linkResult.contracts, root)\n const lifecycle = buildLifecycleModel(\n liveExpirationContracts,\n docsOptions?.expiringWithinDays ?? DEFAULT_EXPIRING_WITHIN_DAYS,\n generatedAt,\n root,\n )\n const change = buildChangeModel(\n evidenceChanges?.report ?? {\n addedContracts: [],\n removedContracts: [],\n addedVariables: [],\n removedVariables: [],\n updatedContracts: [],\n updatedVariables: [],\n },\n linkResult.contracts,\n root,\n )\n const dependency = await buildDependencyModel(\n linkResult.contracts,\n scanFiles,\n readFileCached,\n context,\n root,\n scannedSurfaces,\n evidenceChanges?.dynamicAccessAcknowledgments,\n )\n const finding = buildFindingModel({\n root,\n compatibilityIssues: [\n ...detectCompatibilityIssues(activeContracts),\n ...detectDuplicateVariableShapes(activeContracts),\n ],\n exclusiveGroupIssues: detectExclusiveGroupIssues(activeContracts),\n documentation: docsComputed.documentation,\n abandonedContracts: usageComputed.result.abandonedContracts,\n unresolvedConsumers: usageComputed.result.unresolvedConsumers,\n unconsumedOwnedVariables: usageComputed.result.unconsumedOwnedVariables,\n indeterminateOwnership: usageComputed.result.indeterminate,\n dynamicAccessCitationProblems: evidenceChanges?.dynamicAccessCitationProblems ?? [],\n })\n\n // Docs/ownership findings never block by default (ADR 0038). `--strict-docs`\n // / `--strict-ownership` opt one family in at a time, reusing Finding Model\n // as the single source of what each family contains rather than\n // re-enumerating the finding types here -- a family that later gains a code\n // is covered automatically.\n if (options.onUndocumented === \"throw\")\n blocking.push(...escalatedFindings(finding.findings, \"documentation\"))\n if (options.onOwnershipIssue === \"throw\")\n blocking.push(...escalatedFindings(finding.findings, \"ownership\"))\n\n const evidence: EvidenceModel = deepFreeze({\n schemaVersion: EVIDENCE_MODEL_SCHEMA_VERSION,\n provenance: {\n generatedAt: generatedAt.toISOString(),\n toolVersion: readToolVersion(),\n commit: undefined,\n },\n contract,\n dependency,\n ownership,\n lifecycle,\n finding,\n change,\n })\n\n return {\n root,\n manifestOptions,\n manifestOutputPath,\n manifestComputed,\n docsOptions,\n docsPath,\n envExamplePath,\n docsComputed,\n docsContracts,\n usageOptions,\n usageReportPath,\n usageComputed,\n evidencePath,\n evidence,\n blocking,\n packageWarnings: [...packageWarnings, ...tsconfigWarnings],\n linkWarnings: linkResult.warnings,\n generatedAt,\n }\n}\n\n/**\n * Orchestrates {@link generateEnvManifest}/{@link generateDocumentation}/\n * {@link generateUsageReport}, plus the persisted evidence artifact, by\n * composing their shared private compute/write pipeline directly, running\n * schema discovery+linking exactly once regardless of how many outputs are\n * requested -- an orchestrator, not a new analysis engine (see ADR 0011).\n *\n * @remarks\n * Two distinct atomicity guarantees, not one:\n * - **Compute atomicity (guaranteed)**: every requested pass's blocking\n * findings are checked, across all passes, before any pass writes\n * anything.\n * - **Write atomicity (NOT guaranteed, and not attempted)**: once writes\n * begin, each `fs.writeFile` is independent. A real I/O failure partway\n * through (disk full, permissions changed mid-run) can leave some\n * artifacts on disk and not others. Transactional (temp-file + rename)\n * writes across all three artifacts were considered and rejected as\n * disproportionate machinery for a rare failure mode -- see ADR 0011.\n *\n * @throws {EnvProjectGenerationError} If any requested output location escapes `root`, or if any requested pass reports a blocking finding.\n */\nexport async function generateEnvArtifacts(\n options: GenerateEnvArtifactsOptions,\n): Promise<GenerateEnvArtifactsResult> {\n const computed = await computeArtifacts(options)\n const {\n manifestOptions,\n manifestOutputPath,\n manifestComputed,\n docsOptions,\n docsPath,\n envExamplePath,\n docsComputed,\n docsContracts,\n usageOptions,\n usageReportPath,\n usageComputed,\n evidencePath,\n evidence,\n blocking,\n packageWarnings,\n linkWarnings,\n root,\n generatedAt,\n } = computed\n\n if (blocking.length > 0) throw new EnvProjectGenerationError(blocking)\n\n let manifestResult: GenerateEnvManifestResult | undefined\n // All three of these are structurally correlated, not independently\n // reachable in every combination: `manifestComputed` is only ever set\n // (line 353) inside `manifestOptions ? computeManifest(...) : undefined`,\n // and `manifestOutputPath` is only ever set (line 277) inside `if\n // (manifestOptions) {...}`, after a `resolveWithinRoot()` call whose\n // failure pushes to `pathIssues` -- which, if non-empty, makes\n // `computeArtifacts()` throw before this function ever runs (line 332). So\n // by the time this line executes, `manifestOutputPath` truthy already\n // implies both `manifestOptions` and `manifestComputed` are truthy too, and\n // vice versa -- every mutant on this compound guard (either `&&`/`||` swap,\n // or collapsing a clause to `true`) is behaviorally equivalent. Hand\n // hand-verified: mutating this line (both the LogicalOperator and\n // ConditionalExpression variants Stryker reports) and running the real\n // suite (`vitest run`, whole package) passes unchanged -- but note the\n // three-way `&&` is still load-bearing for TypeScript's own control-flow\n // narrowing inside this block (`manifestComputed.activeContracts` etc.\n // below need all three narrowed to defined), so this must stay a disable,\n // never a restructure to `||`/a subset of the checks.\n // Stryker disable next-line LogicalOperator,ConditionalExpression\n if (manifestOptions && manifestComputed && manifestOutputPath) {\n await writeManifest(manifestOutputPath, manifestComputed.activeContracts, options.fs)\n manifestResult = {\n outputPath: manifestOutputPath,\n contracts: manifestComputed.contractSummaries,\n warnings: manifestComputed.warnings,\n parseWarnings: [...packageWarnings, ...linkWarnings],\n }\n }\n\n let docsResult: GenerateDocumentationResult | undefined\n // Same structural correlation as the manifest guard above: `docsPath` is\n // only ever set (line 290) inside `if (docsOptions) {...}`, past a\n // `resolveWithinRoot()` call whose own failure would have already thrown\n // via `pathIssues` before this function runs -- so `docsPath` truthy here\n // already implies `docsOptions` truthy, and vice versa. Hand-verified:\n // mutating `&&` to `||` and running the real suite (`vitest run`, whole\n // package) passes unchanged -- kept as `&&`, not restructured, since\n // TypeScript's narrowing of `docsOptions.expiringWithinDays` etc. below\n // still needs both operands checked.\n // Stryker disable next-line LogicalOperator\n if (docsOptions && docsPath) {\n const { envExample } = await writeDocumentation(\n docsPath,\n envExamplePath,\n root,\n docsContracts,\n docsComputed.contractModelContracts,\n docsComputed.documentation,\n docsOptions.expiringWithinDays ?? DEFAULT_EXPIRING_WITHIN_DAYS,\n generatedAt,\n options.fs,\n docsOptions.envExample?.onExisting,\n )\n docsResult = {\n docsPath,\n envExample,\n contracts: docsComputed.contractSummaries,\n catalog: docsComputed.catalog,\n parseWarnings: [...packageWarnings, ...linkWarnings],\n documentation: docsComputed.documentation,\n }\n }\n\n let usageResult: GenerateUsageReportResult | undefined\n if (usageOptions) {\n if (usageReportPath) await writeUsageReport(usageReportPath, usageComputed.result, options.fs)\n usageResult = { reportPath: usageReportPath, ...usageComputed.result }\n }\n\n if (evidencePath) {\n await writeEvidenceSnapshot(evidencePath, evidence, options.fs)\n const fingerprint = await computeSourceFingerprint({\n fs: options.fs,\n root,\n include: options.include ?? defaultInclude(),\n exclude: options.exclude ?? defaultExclude(),\n packages: options.packages ?? [],\n })\n await writeEvidenceFingerprint(evidencePath, fingerprint, options.fs)\n }\n\n return { manifest: manifestResult, docs: docsResult, usage: usageResult, evidence }\n}\n","import type { EvidenceModel } from \"./evidence-model.js\"\nimport { normalizeEvidenceSnapshotForComparison } from \"./evidence-snapshot.js\"\nimport { computeArtifacts } from \"./generate-env-artifacts.js\"\nimport type { GenerateEnvArtifactsOptions } from \"./generate-env-artifacts.js\"\nimport { renderManifest } from \"./manifest.js\"\nimport { normalizeDocsForComparison, renderDocs } from \"./docs.js\"\nimport type { UndocumentedContractRef, UndocumentedVariableRef } from \"./docs.js\"\nimport { DEFAULT_EXPIRING_WITHIN_DAYS, relativizeRef } from \"./generate-documentation.js\"\nimport { renderUsageReport } from \"./usage-report.js\"\nimport { computeReconciliation } from \"./env-example.js\"\nimport { EnvProjectGenerationError } from \"./errors.js\"\nimport type { BuildFileSystem } from \"./types.js\"\n\n/**\n * `--check` / drift-guard support: computes every requested artifact exactly\n * as a real run would, but never writes to any of the four real target\n * paths. See ADR 0016.\n */\n\n/** One artifact's drift status, as found by {@link checkEnvArtifacts}. */\nexport interface ArtifactCheckFinding {\n /** Which generated artifact this finding is about. */\n readonly artifact: \"manifest\" | \"docs\" | \"envExample\" | \"usage\" | \"evidence\"\n /** Absolute path the artifact would be written to. */\n readonly path: string\n /** `\"missing\"` if the file doesn't exist yet, `\"stale\"` if it exists but differs from what a real run would produce. */\n readonly status: \"ok\" | \"stale\" | \"missing\"\n /** Human-readable detail, set for `\"stale\"`/`\"missing\"` findings. */\n readonly detail?: string\n}\n\n/** The result of a completed {@link checkEnvArtifacts} run. */\nexport interface CheckEnvArtifactsResult {\n /** `true` iff every requested artifact is `\"ok\"`. */\n readonly ok: boolean\n /** One entry per requested artifact. */\n readonly findings: readonly ArtifactCheckFinding[]\n}\n\n// `catch { return undefined }` below is this function's LAST statement --\n// an empty catch body would already fall through to the exact same\n// implicit `undefined` return, making the block's own content\n// unobservable either way (this repo's `noImplicitReturns` still requires\n// an explicit `return` somewhere on this path, so the block can never be\n// truly empty; whatever's left inside it stays a Stryker BlockStatement\n// magnet regardless of exact wording). Hand-verified directly (mutating\n// the source to a genuinely empty `catch {}` and running the real test\n// suite) -- every test still passes. A disable comment placed at several\n// narrower points (on `return undefined` itself; directly above `catch`;\n// an unscoped disable/restore pair bracketing just the catch clause) did\n// NOT reliably suppress this specific mutant across repeated verification\n// runs (Stryker's directive attachment is AST-leading-comment-based, and\n// nothing inside this small function gave it an unambiguous anchor) --\n// bracketing the WHOLE function declaration, matching the pattern that\n// reliably works for a no-op function body elsewhere in this codebase\n// (see `runtime/document.ts`'s `documentEnv()`), is what finally holds.\n// Stryker disable BlockStatement\nasync function readIfExists(filePath: string, fs: BuildFileSystem): Promise<string | undefined> {\n try {\n return await fs.readFile(filePath, \"utf8\")\n } catch {\n return undefined\n }\n}\n// Stryker restore BlockStatement\n\n/**\n * Parses `text` as an `EvidenceModel` and re-serializes it with\n * `provenance.generatedAt` normalized out (see `normalizeEvidenceSnapshotForComparison()`)\n * -- so `--check` never reports drift solely because a fresh render's\n * timestamp differs from the committed file's. A parse failure returns\n * `text` unchanged, so a corrupted on-disk file simply fails to match\n * `expected`'s normalized form (reported as `\"stale\"`), rather than\n * crashing `--check` itself.\n */\n/** @internal Exported for direct unit coverage -- reached through `checkEnvArtifacts()`'s `--evidence` pass in production, but the exact \"returns text unchanged, not undefined/thrown\" catch behavior isn't independently observable through that public path (any malformed `actual` already reads as \"stale\" against a well-formed `expected`, regardless of the catch's exact return value). */\nexport function normalizeEvidenceJsonForComparison(text: string): string {\n try {\n const parsed = JSON.parse(text) as EvidenceModel\n return JSON.stringify(normalizeEvidenceSnapshotForComparison(parsed), null, 2)\n } catch {\n return text\n }\n}\n\nasync function compareTextArtifact(\n artifact: ArtifactCheckFinding[\"artifact\"],\n filePath: string,\n expected: string,\n fs: BuildFileSystem,\n normalize: (s: string) => string = (s) => s,\n): Promise<ArtifactCheckFinding> {\n const actual = await readIfExists(filePath, fs)\n if (actual === undefined)\n return { artifact, path: filePath, status: \"missing\", detail: \"not yet generated\" }\n if (normalize(actual) === normalize(expected)) return { artifact, path: filePath, status: \"ok\" }\n return {\n artifact,\n path: filePath,\n status: \"stale\",\n detail: \"generated content differs from what's committed\",\n }\n}\n\n/**\n * Verifies every requested artifact (`manifest`/`docs`/`envExample`/`usage`)\n * matches what a real {@link generateEnvArtifacts} run would produce, without\n * writing anything.\n *\n * @remarks\n * `--check` reports drift, it doesn't paper over a run that would otherwise fail --\n * see `@throws` below.\n *\n * @throws {EnvProjectGenerationError} On the same blocking findings a real run would throw on.\n */\nexport async function checkEnvArtifacts(\n options: GenerateEnvArtifactsOptions,\n): Promise<CheckEnvArtifactsResult> {\n const c = await computeArtifacts(options)\n if (c.blocking.length > 0) throw new EnvProjectGenerationError(c.blocking)\n\n const findings: ArtifactCheckFinding[] = []\n\n // `c.manifestOptions && c.manifestComputed` is runtime-redundant given\n // the third clause: `generate-env-artifacts.ts`'s `computeArtifacts()`\n // only ever sets `manifestOutputPath` inside its own `if (manifestOptions)`\n // block, and `manifestComputed` is unconditionally `manifestOptions ?\n // computeManifest(...) : undefined` -- so `manifestOutputPath` truthy\n // already implies both. Kept for TS narrowing (`c.manifestComputed\n // .activeContracts` below needs `manifestComputed` narrowed away from\n // `| undefined`, which isn't inferrable from a same-object-but-different-\n // field check).\n // Stryker disable next-line ConditionalExpression, LogicalOperator\n if (c.manifestOptions && c.manifestComputed && c.manifestOutputPath) {\n const expected = renderManifest(c.manifestComputed.activeContracts, c.manifestOutputPath)\n findings.push(await compareTextArtifact(\"manifest\", c.manifestOutputPath, expected, options.fs))\n }\n\n // `c.docsOptions` alone already implies `c.docsPath` will be set too\n // (`computeArtifacts()` only ever sets `docsPath` inside its own `if\n // (docsOptions)` block) -- same class as the manifest/envExample/usage\n // guards elsewhere in this function. Kept for the same TS-narrowing\n // reason (`c.docsPath`'s own type is `string | undefined`). Hand-verified:\n // replacing `&&` with `||` and running the full `vitest run` leaves every\n // test but the two tsc-backed json-schema ones passing.\n // Stryker disable next-line LogicalOperator\n if (c.docsOptions && c.docsPath) {\n const previousContent = await readIfExists(c.docsPath, options.fs)\n const expected = renderDocs(c.docsComputed.contractModelContracts, {\n expiringWithinDays: c.docsOptions.expiringWithinDays ?? DEFAULT_EXPIRING_WITHIN_DAYS,\n undocumentedContracts: c.docsComputed.documentation.undocumentedContracts.map(\n (ref): UndocumentedContractRef => relativizeRef(c.root, ref),\n ),\n // `RenderDocsOptions.undocumentedVariables` is consumed by `renderDocs()`\n // ONLY via `.length` (the security-review counter), never by content\n // or identity -- same equivalence already established for\n // `generate-documentation.ts`'s identical call site. Hand-verified:\n // mapping every entry to `undefined` instead and running the full\n // `vitest run` leaves every test passing.\n // Stryker disable ArrowFunction\n undocumentedVariables: c.docsComputed.documentation.undocumentedVariables.map(\n (ref): UndocumentedVariableRef => relativizeRef(c.root, ref),\n ),\n // Stryker restore ArrowFunction\n generatedAt: c.generatedAt,\n previousContent,\n })\n findings.push(\n await compareTextArtifact(\n \"docs\",\n c.docsPath,\n expected,\n options.fs,\n normalizeDocsForComparison,\n ),\n )\n\n // `c.docsOptions.envExample` is runtime-redundant here too, same\n // reasoning as the manifest check above: `computeArtifacts()` only ever\n // sets `envExamplePath` inside its own `if (docsOptions.envExample)`\n // block, so `envExamplePath` truthy already implies it. `docsOptions\n // .envExample`'s own value is never read past this line (only used as\n // a truthy gate) -- kept for readability/documentation of intent, not\n // because anything downstream needs it narrowed.\n // Stryker disable next-line ConditionalExpression, LogicalOperator\n if (c.docsOptions.envExample && c.envExamplePath) {\n const existing = await readIfExists(c.envExamplePath, options.fs)\n if (existing === undefined) {\n findings.push({\n artifact: \"envExample\",\n path: c.envExamplePath,\n status: \"missing\",\n detail: \"not yet generated\",\n })\n } else {\n const { staleVariables, variablesToComment, variablesToAdd } = computeReconciliation(\n c.docsContracts,\n existing,\n )\n const driftCount = staleVariables.length + variablesToComment.length + variablesToAdd.length\n findings.push({\n artifact: \"envExample\",\n path: c.envExamplePath,\n status: driftCount > 0 ? \"stale\" : \"ok\",\n detail:\n driftCount > 0\n ? `${staleVariables.length} stale, ${variablesToComment.length} to comment, ${variablesToAdd.length} to add`\n : undefined,\n })\n }\n }\n }\n\n // `c.usageOptions` is runtime-redundant here too, same reasoning as the\n // manifest/envExample guards above: `computeArtifacts()` only ever sets\n // `usageReportPath` inside its own `if (usageOptions?.report)` block, so\n // `usageReportPath` truthy already implies `usageOptions` (and its\n // `.report`) are too.\n // Stryker disable next-line LogicalOperator\n if (c.usageOptions && c.usageReportPath) {\n const expected = renderUsageReport(c.usageComputed.result)\n findings.push(await compareTextArtifact(\"usage\", c.usageReportPath, expected, options.fs))\n }\n\n if (c.evidencePath) {\n const expected = JSON.stringify(c.evidence, null, 2)\n findings.push(\n await compareTextArtifact(\n \"evidence\",\n c.evidencePath,\n expected,\n options.fs,\n normalizeEvidenceJsonForComparison,\n ),\n )\n }\n\n return { ok: findings.every((f) => f.status === \"ok\"), findings }\n}\n","/**\n * SARIF export -- an adapter over Finding Model, not a new fact source.\n * Produces a minimal, spec-conformant SARIF 2.1.0 log\n * (https://docs.oasis-open.org/sarif/sarif/v2.1.0/) so env-cap's findings can\n * be consumed by any SARIF-aware tool (GitHub code scanning, most CI security\n * dashboards) without a bespoke integration.\n *\n * Pure and synchronous: every input is already computed by the time this\n * runs, so this never re-derives a finding, never reads the filesystem, and\n * never decides what is or isn't a problem -- it only re-shapes what\n * `buildFindingModel()` already concluded.\n */\n\nimport type { Finding, FindingModel } from \"./finding-model.js\"\nimport { readToolVersion } from \"./tool-version.js\"\n\n/** SARIF's `level` enum -- see the SARIF 2.1.0 spec, section 3.27.10. */\ntype SarifLevel = \"none\" | \"note\" | \"warning\" | \"error\"\n\n/** env-cap's `\"info\"` has no SARIF counterpart of the same name; `\"note\"` is the spec's advisory level, and is what every SARIF consumer renders as \"informational\". `\"warning\"`/`\"error\"` map through unchanged. */\nfunction sarifLevel(severity: Finding[\"severity\"]): SarifLevel {\n return severity === \"info\" ? \"note\" : severity\n}\n\ninterface SarifLocation {\n readonly physicalLocation: {\n readonly artifactLocation: { readonly uri: string }\n readonly region?: { readonly startLine: number; readonly startColumn: number }\n }\n}\n\n/**\n * A finding's location as SARIF's physical-location shape, or `undefined`\n * when the finding names no file at all.\n *\n * @remarks\n * `region` is emitted only when a real `SourcePosition` exists -- most of\n * env-cap's finding families deliberately carry `position: undefined` today\n * (see `finding-model.ts`'s `NO_POSITION` note), and synthesizing a\n * `startLine: 1` for those would be a fabricated claim about where the\n * problem is, which is exactly what a code-scanning UI would then anchor an\n * annotation to.\n */\nfunction sarifLocations(finding: Finding): readonly SarifLocation[] | undefined {\n const location = finding.location\n const uri = location.model === \"change\" ? location.path : location.file\n if (uri === undefined) return undefined\n // Genuinely equivalent either way this ternary's condition is mutated:\n // `ChangeEvidenceReference` has no `position` field at all (by type --\n // see `evidence-reference.ts`), so `location.position` is already\n // `undefined` for a change-model location without this check; and every\n // OTHER model already fails the `=== \"change\"` comparison for real, so\n // routing them to the same branch a mutated condition would pick changes\n // nothing observable there either.\n // Stryker disable next-line ConditionalExpression,StringLiteral\n const position = location.model === \"change\" ? undefined : location.position\n return [\n {\n physicalLocation: {\n artifactLocation: { uri },\n ...(position === undefined\n ? {}\n : { region: { startLine: position.line, startColumn: position.column } }),\n },\n },\n ]\n}\n\ninterface SarifResult {\n readonly ruleId: string\n readonly level: SarifLevel\n readonly message: { readonly text: string }\n readonly locations?: readonly SarifLocation[]\n}\n\n/** A minimal SARIF 2.1.0 log -- only the properties this adapter actually populates, not the full spec surface. */\nexport interface SarifLog {\n readonly $schema: string\n readonly version: \"2.1.0\"\n readonly runs: readonly {\n readonly tool: {\n readonly driver: {\n readonly name: string\n readonly informationUri: string\n readonly version: string\n readonly rules: readonly { readonly id: string }[]\n }\n }\n readonly results: readonly SarifResult[]\n }[]\n}\n\n/**\n * Projects Finding Model into a SARIF 2.1.0 log.\n *\n * @remarks\n * `rules` lists every distinct `FindingCode` actually present in this run,\n * sorted -- not the full `FindingCode` union. A SARIF consumer treats the\n * rules array as \"what this tool reported\", and advertising rules that\n * produced no result makes a clean run look like it has unexplained silent\n * rules. `results` preserves Finding Model's own order, which a caller wanting\n * a different one sorts themselves.\n */\nexport function buildSarifLog(findingModel: FindingModel): SarifLog {\n const ruleIds = [...new Set(findingModel.findings.map((f) => f.code))].sort()\n\n return {\n $schema:\n \"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/main/Schemata/sarif-schema-2.1.0.json\",\n version: \"2.1.0\",\n runs: [\n {\n tool: {\n driver: {\n name: \"env-cap\",\n informationUri: \"https://github.com/maverickcer/env-cap#readme\",\n version: readToolVersion(),\n rules: ruleIds.map((id) => ({ id })),\n },\n },\n results: findingModel.findings.map((finding) => ({\n ruleId: finding.code,\n level: sarifLevel(finding.severity),\n message: { text: finding.message },\n locations: sarifLocations(finding),\n })),\n },\n ],\n }\n}\n"]}
|