@moldea.ai/core 7.1.0 → 8.0.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.
Files changed (54) hide show
  1. package/README.md +4 -4
  2. package/dist/analysis-worker.js +10 -22
  3. package/dist/analysis-worker.js.map +1 -1
  4. package/dist/chunks/{core-CMuQrqRI.js → core-BCMf-ig9.js} +84 -141
  5. package/dist/chunks/core-BCMf-ig9.js.map +1 -0
  6. package/dist/chunks/{errors-BhiLG9F0.js → errors-CvWn6gr2.js} +4 -10
  7. package/dist/chunks/errors-CvWn6gr2.js.map +1 -0
  8. package/dist/chunks/{lifecycle-Bdi_ydtH.js → lifecycle-DwuevNoO.js} +2 -2
  9. package/dist/chunks/{lifecycle-Bdi_ydtH.js.map → lifecycle-DwuevNoO.js.map} +1 -1
  10. package/dist/chunks/{options-BVF3DQHm.js → options-l3kVfA-K.js} +4 -4
  11. package/dist/chunks/options-l3kVfA-K.js.map +1 -0
  12. package/dist/chunks/{repository-rpc-CiKFu86B.js → repository-rpc-DgYwMaGv.js} +15 -56
  13. package/dist/chunks/repository-rpc-DgYwMaGv.js.map +1 -0
  14. package/dist/chunks/{scope-DoNl6LhC.js → scope-D9BYchNI.js} +2 -2
  15. package/dist/chunks/{scope-DoNl6LhC.js.map → scope-D9BYchNI.js.map} +1 -1
  16. package/dist/constants/index.d.ts +1 -1
  17. package/dist/constants/index.d.ts.map +1 -1
  18. package/dist/contracts/index.d.ts +2 -6
  19. package/dist/contracts/index.d.ts.map +1 -1
  20. package/dist/diagnostic-utilities/index.d.ts.map +1 -1
  21. package/dist/diagnostics/index.d.ts +2 -2
  22. package/dist/diagnostics/index.d.ts.map +1 -1
  23. package/dist/index.d.ts +1 -1
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +2 -2
  26. package/dist/integration-validation/agents-inspection.d.ts +3 -3
  27. package/dist/integration-validation/agents-inspection.d.ts.map +1 -1
  28. package/dist/integration-validation/claude-inspection.d.ts +3 -2
  29. package/dist/integration-validation/claude-inspection.d.ts.map +1 -1
  30. package/dist/integration-validation/inspection.d.ts +4 -2
  31. package/dist/integration-validation/inspection.d.ts.map +1 -1
  32. package/dist/integration-validation/types.d.ts +3 -3
  33. package/dist/integration-validation/types.d.ts.map +1 -1
  34. package/dist/integration-validation/utilities.d.ts +0 -8
  35. package/dist/integration-validation/utilities.d.ts.map +1 -1
  36. package/dist/node-inspection/client.d.ts.map +1 -1
  37. package/dist/node-inspection/protocol.d.ts.map +1 -1
  38. package/dist/node-inspection/repository-rpc.d.ts +7 -6
  39. package/dist/node-inspection/repository-rpc.d.ts.map +1 -1
  40. package/dist/node-inspection/types.d.ts +7 -12
  41. package/dist/node-inspection/types.d.ts.map +1 -1
  42. package/dist/node-runner.js +2 -2
  43. package/dist/node.js +11 -18
  44. package/dist/node.js.map +1 -1
  45. package/dist/project-validation/index.d.ts +1 -1
  46. package/dist/project-validation/index.d.ts.map +1 -1
  47. package/dist/repository-inspection-session/index.d.ts +5 -8
  48. package/dist/repository-inspection-session/index.d.ts.map +1 -1
  49. package/dist/scope.js +2 -2
  50. package/package.json +2 -2
  51. package/dist/chunks/core-CMuQrqRI.js.map +0 -1
  52. package/dist/chunks/errors-BhiLG9F0.js.map +0 -1
  53. package/dist/chunks/options-BVF3DQHm.js.map +0 -1
  54. package/dist/chunks/repository-rpc-CiKFu86B.js.map +0 -1
package/README.md CHANGED
@@ -4,12 +4,12 @@
4
4
 
5
5
  Source-neutral, deterministic, content-safe interpretation of the `moldea` repository format.
6
6
 
7
- Version 7 accepts caller-supplied text and `@moldea.ai/repository` version 2 readers. The main, format, and scope entry points remain environment-neutral. Repository access belongs to the caller-supplied reader. Project validation returns content-free summaries, diagnostics, binding coverage, agent assignments, and metadata. Canonical document bodies are available only through an explicit path-scoped byte-range operation.
7
+ Version 8 accepts caller-supplied text and `@moldea.ai/repository` version 3 readers. The main, format, and scope entry points remain environment-neutral. Repository access belongs to the caller-supplied reader. Project validation returns content-free summaries, diagnostics, binding coverage, agent assignments, and metadata. Canonical document bodies are available only through an explicit path-scoped byte-range operation.
8
8
 
9
9
  ## Install
10
10
 
11
11
  ```bash
12
- pnpm add @moldea.ai/core@7 @moldea.ai/repository@2
12
+ pnpm add @moldea.ai/core@8 @moldea.ai/repository@3
13
13
  ```
14
14
 
15
15
  ## Public entry points
@@ -78,11 +78,11 @@ Core checks each declared binding's file and, when a symbol is named, its syntax
78
78
 
79
79
  `RECOGNIZED_RUNTIME_IDS` contains 35 runtime labels plus `custom`. Labels select agent guidance. Core applies the same universal checks to every label and does not interpret SDK calls. Use the installed SDK's type definitions and real application tests to establish runtime behavior. Handoffs remain runtime-native behavior.
80
80
 
81
- Every diagnostic has `severity`, `group`, and stable `source: 'core'`. The groups are `discovery`, `manifest`, `references`, `agents`, `mirrors`, and `integration`. The result reports complete `errorCount`, unaccepted `warningCount`, `acceptedWarningCount`, and `diagnosticCount`; warnings do not invalidate a project. Manifest `acceptedWarnings` match a warning's code, subject, and qualifier and require a non-empty reason. Accepted findings remain visible. Unmatched impact patterns are best-effort warnings; a skipped check never makes an acceptance obsolete. Validation and inspection also check the root `/AGENTS.md` managed block against its referenced skill installation, reporting missing blocks, missing installation files, drift, or an unverifiable link as acceptable integration warnings. They also check whether `/CLAUDE.md`, `/.claude/CLAUDE.md`, or, without shared files, `/CLAUDE.local.md` loads AGENTS.md through an import line or a link, reporting `MOLDEA_INTEGRATION_CLAUDE_IMPORT_MISSING` when it does not. An optional `instructions` source `{ reader, linkResolver? }` supplies the instruction files, and its resolver lets Core check a symlinked `/AGENTS.md` on its regular-file target; the skill installation and every other check still read `repository`. `parseIntegrationBlock(text)` extracts the safe relative installation path or a reason it could not be found. Manifest-only operations and `scope` do not read the integration.
81
+ Every diagnostic has `severity`, `group`, and stable `source: 'core'`. The groups are `discovery`, `manifest`, `references`, `agents`, `mirrors`, and `integration`. The result reports complete `errorCount`, unaccepted `warningCount`, `acceptedWarningCount`, and `diagnosticCount`; warnings do not invalidate a project. Manifest `acceptedWarnings` match a warning's code, subject, and qualifier and require a non-empty reason. Accepted findings remain visible. Unmatched impact patterns are best-effort warnings; a skipped check never makes an acceptance obsolete. Validation and inspection also check the root `/AGENTS.md` managed block against its referenced skill installation, reporting missing blocks, missing installation files, drift, or a link that doesn't lead to a file in the repository, with its reason as qualifier, as acceptable integration warnings. They also check whether `/CLAUDE.md`, `/.claude/CLAUDE.md`, or, without shared files, `/CLAUDE.local.md` loads AGENTS.md through an import line or a link, reporting `MOLDEA_INTEGRATION_CLAUDE_IMPORT_MISSING` when it does not. An optional `instructions` reader supplies the four instruction files; links are followed inside the repository with Repository's `resolveRepositoryLink`, and link targets, the skill installation, and every other check read `repository`. `parseIntegrationBlock(text)` extracts the safe relative installation path or a reason it could not be found. Manifest-only operations and `scope` do not read the integration.
82
82
 
83
83
  ## Resource and trust boundaries
84
84
 
85
- Core uses independent limits for distinct entries, total bytes read, per-file bytes, manifest bytes, logical retained bytes, diagnostics, and coverage records. The default logical retained-memory ceiling is 512 MiB. Before reading a supported source for export analysis, Core checks `maxFileBytes`, confirms read-buffer headroom, and reserves `65536 + sourceBytes * (8 + 512)` bytes for text and syntax nodes. An oversized source or reservation miss records `resource-limit` without a source read; a subsequent failed read, cancellation, or operation budget failure rejects the whole operation. Each distinct source is parsed at most once per operation. Source buffers and syntax reservations are released after analysis; only export names remain in the inventory cache. Core executes no repository code, follows only resolver-provided instruction links, receives no host path or source credential, and returns logical paths only.
85
+ Core uses independent limits for distinct entries, total bytes read, per-file bytes, manifest bytes, logical retained bytes, diagnostics, and coverage records. The default logical retained-memory ceiling is 512 MiB. Before reading a supported source for export analysis, Core checks `maxFileBytes`, confirms read-buffer headroom, and reserves `65536 + sourceBytes * (8 + 512)` bytes for text and syntax nodes. An oversized source or reservation miss records `resource-limit` without a source read; a subsequent failed read, cancellation, or operation budget failure rejects the whole operation. Each distinct source is parsed at most once per operation. Source buffers and syntax reservations are released after analysis; only export names remain in the inventory cache. Core executes no repository code, follows instruction links only inside the snapshot, receives no host path or source credential, and returns logical paths only.
86
86
 
87
87
  Logical `RESOURCE_LIMIT_EXCEEDED` exceptions identify the exceeded limit, its configured maximum, the observed or projected usage, and `reduce-input-or-increase-limit`. Verified isolated-worker heap exhaustion uses `review-inspection-capacity` with unknown observed usage. Fixed transport limits have no next action. Core refuses an operation before allocating retained state beyond the applicable ceiling.
88
88
 
@@ -1,7 +1,7 @@
1
- import { n as normalizeCoreOptions } from "./chunks/options-BVF3DQHm.js";
1
+ import { n as normalizeCoreOptions } from "./chunks/options-l3kVfA-K.js";
2
2
  import { n as CoreOperationException } from "./chunks/exceptions-CYf1pCKf.js";
3
- import { a as encodeInspectionMessage, d as NODE_INSPECTION_TRANSPORT_BYTES, i as decodeInspectionMessage, n as serializeInspectionFailure, o as NODE_INSPECTION_FILE_PAGE_BYTES, r as createInspectionProcessFailure, t as deserializeInspectionFailure } from "./chunks/errors-BhiLG9F0.js";
4
- import { a as parseRpcLinkResolution, i as parseRpcFilePage, n as parseRpcEntry, r as parseRpcEntryPage } from "./chunks/repository-rpc-CiKFu86B.js";
3
+ import { a as encodeInspectionMessage, d as NODE_INSPECTION_TRANSPORT_BYTES, i as decodeInspectionMessage, n as serializeInspectionFailure, o as NODE_INSPECTION_FILE_PAGE_BYTES, r as createInspectionProcessFailure, t as deserializeInspectionFailure } from "./chunks/errors-CvWn6gr2.js";
4
+ import { a as parseRpcLinkText, i as parseRpcFilePage, n as parseRpcEntry, r as parseRpcEntryPage } from "./chunks/repository-rpc-DgYwMaGv.js";
5
5
  import { RepositorySourceException } from "@moldea.ai/repository";
6
6
  import { parentPort, workerData } from "node:worker_threads";
7
7
  import { getHeapStatistics } from "node:v8";
@@ -75,6 +75,11 @@ var createProxyReader = (source, snapshot) => ({
75
75
  maxBytes: Math.min(NODE_INSPECTION_FILE_PAGE_BYTES, options.maxBytes),
76
76
  source
77
77
  })),
78
+ readLinkText: async (path) => parseRpcLinkText(await requestReader({
79
+ method: "readLinkText",
80
+ path,
81
+ source
82
+ })),
78
83
  compare: () => Promise.reject(new RepositorySourceException({
79
84
  code: "SOURCE_UNAVAILABLE",
80
85
  operation: "create-comparison",
@@ -82,28 +87,11 @@ var createProxyReader = (source, snapshot) => ({
82
87
  retryable: false
83
88
  }))
84
89
  });
85
- /** Proxies the caller-owned link resolver of the instruction source. */
86
- var createProxyLinkResolver = (snapshot) => ({
87
- snapshot,
88
- resolveLink: async (path) => parseRpcLinkResolution(await requestReader({
89
- method: "resolveLink",
90
- path
91
- })),
92
- readLinkTargetPage: async (path, options) => parseRpcFilePage(await requestReader({
93
- method: "readLinkTargetPage",
94
- path,
95
- offset: options.offset,
96
- maxBytes: Math.min(NODE_INSPECTION_FILE_PAGE_BYTES, options.maxBytes)
97
- }))
98
- });
99
90
  var repository = createProxyReader("repository", start.snapshot);
100
- var instructions = start.instructions === null ? null : {
101
- reader: createProxyReader("instructions", start.instructions.snapshot),
102
- ...start.instructions.hasLinkResolver ? { linkResolver: createProxyLinkResolver(start.instructions.snapshot) } : {}
103
- };
91
+ var instructions = start.instructions === null ? null : createProxyReader("instructions", start.instructions.snapshot);
104
92
  /** Prepares the fixed Core implementation after the parent acknowledges the heap. */
105
93
  var prepare = async () => {
106
- const { createCore } = await import("./chunks/core-CMuQrqRI.js").then((n) => n.t);
94
+ const { createCore } = await import("./chunks/core-BCMf-ig9.js").then((n) => n.t);
107
95
  inspection = await createCore(normalizeCoreOptions({ limits: {
108
96
  ...start.limits,
109
97
  maxRetainedBytes: start.limits.maxRetainedBytes - NODE_INSPECTION_TRANSPORT_BYTES
@@ -1 +1 @@
1
- {"version":3,"file":"analysis-worker.js","names":[],"sources":["../src/node-inspection/analysis-worker.ts"],"sourcesContent":["import { getHeapStatistics } from 'node:v8';\nimport { parentPort, workerData } from 'node:worker_threads';\n\nimport {\n RepositorySourceException,\n type IRepositoryLinkResolver,\n type IRepositoryReader,\n type IRepositorySnapshot,\n} from '@moldea.ai/repository';\n\nimport type { IProjectInspection, IProjectInstructionSource } from '../contracts/index.js';\nimport { CoreOperationException } from '../exceptions/index.js';\nimport { normalizeCoreOptions } from '../options/index.js';\n\nimport {\n NODE_INSPECTION_FILE_PAGE_BYTES,\n NODE_INSPECTION_MAX_REQUESTS,\n NODE_INSPECTION_TRANSPORT_BYTES,\n} from './constants.js';\nimport { deserializeInspectionFailure, serializeInspectionFailure } from './errors.js';\nimport {\n createInspectionProcessFailure,\n decodeInspectionMessage,\n encodeInspectionMessage,\n} from './protocol.js';\nimport {\n parseRpcEntry,\n parseRpcEntryPage,\n parseRpcFilePage,\n parseRpcLinkResolution,\n} from './repository-rpc.js';\nimport type { INodeInspectionMessage, INodeReaderRequest, INodeReaderSource } from './types.js';\n\nconst port = parentPort;\nif (port === null) throw createInspectionProcessFailure();\nconst start = decodeInspectionMessage(workerData);\nif (start.kind !== 'start') throw createInspectionProcessFailure();\nconst attemptId = start.attemptId;\nconst maxAnalysisHeapBytes = getHeapStatistics().heap_size_limit;\nlet inspection: IProjectInspection | undefined;\nlet hasRun = false;\nlet isReadingPage = false;\nlet nextRequestId = 0;\nconst pending = new Map<\n number,\n { resolve: (result: unknown) => void; reject: (cause: unknown) => void }\n>();\nconst send = (message: INodeInspectionMessage): void => {\n port.postMessage(encodeInspectionMessage(message));\n};\n\n/** Admits at most four requests across both bridges; no unbounded transport wait queue exists. */\nconst requestReader = (request: INodeReaderRequest): Promise<unknown> => {\n if (pending.size >= NODE_INSPECTION_MAX_REQUESTS)\n return Promise.reject(\n new CoreOperationException({\n code: 'RESOURCE_LIMIT_EXCEEDED',\n operation: 'create-project-inspection',\n limit: 'maxReaderRequests',\n limitMaximum: NODE_INSPECTION_MAX_REQUESTS,\n observedUsage: pending.size + 1,\n nextAction: null,\n }),\n );\n const requestId = nextRequestId++;\n return new Promise<unknown>((resolve, reject) => {\n pending.set(requestId, { resolve, reject });\n try {\n send({ attemptId, kind: 'reader-request', requestId, request });\n } catch (cause) {\n pending.delete(requestId);\n reject(cause instanceof Error ? cause : createInspectionProcessFailure(cause));\n }\n });\n};\n\n/** Proxies one caller-owned reader; only the repository source lists entries. */\nconst createProxyReader = (\n source: INodeReaderSource,\n snapshot: IRepositorySnapshot,\n): IRepositoryReader => ({\n snapshot,\n getEntry: async (path) =>\n parseRpcEntry(await requestReader({ method: 'getEntry', path, source })),\n listEntriesPage: async (options) =>\n source === 'repository'\n ? parseRpcEntryPage(\n await requestReader({\n method: 'listEntriesPage',\n maxEntries: Math.min(128, options.maxEntries),\n ...(options.cursor === undefined ? {} : { cursor: options.cursor }),\n ...(options.prefix === undefined ? {} : { prefix: options.prefix }),\n }),\n )\n : Promise.reject(\n new RepositorySourceException({\n code: 'SOURCE_UNAVAILABLE',\n operation: 'list-entries-page',\n path: null,\n retryable: false,\n }),\n ),\n readFilePage: async (path, options) =>\n parseRpcFilePage(\n await requestReader({\n method: 'readFilePage',\n path,\n offset: options.offset,\n maxBytes: Math.min(NODE_INSPECTION_FILE_PAGE_BYTES, options.maxBytes),\n source,\n }),\n ),\n compare: () =>\n Promise.reject(\n new RepositorySourceException({\n code: 'SOURCE_UNAVAILABLE',\n operation: 'create-comparison',\n path: null,\n retryable: false,\n }),\n ),\n});\n\n/** Proxies the caller-owned link resolver of the instruction source. */\nconst createProxyLinkResolver = (snapshot: IRepositorySnapshot): IRepositoryLinkResolver => ({\n snapshot,\n resolveLink: async (path) =>\n parseRpcLinkResolution(await requestReader({ method: 'resolveLink', path })),\n readLinkTargetPage: async (path, options) =>\n parseRpcFilePage(\n await requestReader({\n method: 'readLinkTargetPage',\n path,\n offset: options.offset,\n maxBytes: Math.min(NODE_INSPECTION_FILE_PAGE_BYTES, options.maxBytes),\n }),\n ),\n});\n\nconst repository = createProxyReader('repository', start.snapshot);\nconst instructions: IProjectInstructionSource | null =\n start.instructions === null\n ? null\n : {\n reader: createProxyReader('instructions', start.instructions.snapshot),\n ...(start.instructions.hasLinkResolver\n ? { linkResolver: createProxyLinkResolver(start.instructions.snapshot) }\n : {}),\n };\n\n/** Prepares the fixed Core implementation after the parent acknowledges the heap. */\nconst prepare = async (): Promise<void> => {\n const { createCore } = await import('../core/index.js');\n const options = normalizeCoreOptions({\n limits: {\n ...start.limits,\n maxRetainedBytes: start.limits.maxRetainedBytes - NODE_INSPECTION_TRANSPORT_BYTES,\n },\n });\n const core = createCore(options);\n inspection = await core.createProjectInspection({\n repository,\n ...(instructions === null ? {} : { instructions }),\n });\n const metadata = {\n source: inspection.source,\n formatVersion: inspection.formatVersion,\n valid: inspection.valid,\n counts: inspection.counts,\n coverageCounts: inspection.coverageCounts,\n summary: inspection.summary,\n resourceUsage: inspection.resourceUsage,\n inspectionDigest: inspection.inspectionDigest,\n };\n send({\n attemptId,\n kind: 'prepared',\n inspection: {\n ...metadata,\n maxAnalysisHeapBytes,\n resourceUsage: {\n ...metadata.resourceUsage,\n retainedBytes: metadata.resourceUsage.retainedBytes + NODE_INSPECTION_TRANSPORT_BYTES,\n peakRetainedBytes:\n metadata.resourceUsage.peakRetainedBytes + NODE_INSPECTION_TRANSPORT_BYTES,\n },\n },\n });\n};\n\n/** Translates worker failures to safe package contracts while the supervisor stays responsive. */\nconst fail = (cause: unknown): void => {\n try {\n const failure = serializeInspectionFailure(cause);\n if (\n cause instanceof CoreOperationException &&\n cause.code === 'RESOURCE_LIMIT_EXCEEDED' &&\n cause.limit === 'maxRetainedBytes' &&\n cause.observedUsage !== null\n ) {\n failure.options['limitMaximum'] = start.limits.maxRetainedBytes;\n failure.options['observedUsage'] = cause.observedUsage + NODE_INSPECTION_TRANSPORT_BYTES;\n }\n send({ attemptId, kind: 'failure', failure });\n } catch {\n port.close();\n }\n};\n\nport.on('message', (frame: unknown) => {\n try {\n const message = decodeInspectionMessage(frame);\n if (message.attemptId !== attemptId) throw createInspectionProcessFailure();\n if (message.kind === 'run') {\n if (hasRun) throw createInspectionProcessFailure();\n hasRun = true;\n void prepare().catch(fail);\n } else if (message.kind === 'reader-response' || message.kind === 'reader-failure') {\n const request = pending.get(message.requestId);\n if (request === undefined) throw createInspectionProcessFailure();\n pending.delete(message.requestId);\n if (message.kind === 'reader-failure')\n request.reject(deserializeInspectionFailure(message.failure));\n else request.resolve(message.result);\n } else if (message.kind === 'read-page') {\n if (inspection === undefined || isReadingPage) throw createInspectionProcessFailure();\n isReadingPage = true;\n try {\n if (message.input.maxItems > start.limits.maxEntries)\n throw new CoreOperationException({\n code: 'INVALID_ARGUMENT',\n operation: 'create-project-inspection',\n });\n let maxItems = Math.min(256, message.input.maxItems);\n while (true) {\n try {\n const frame = encodeInspectionMessage({\n attemptId,\n kind: 'page',\n requestId: message.requestId,\n result: inspection.readPage({ ...message.input, maxItems }),\n });\n port.postMessage(frame);\n break;\n } catch (cause) {\n if (\n !(cause instanceof CoreOperationException) ||\n cause.code !== 'RESOURCE_LIMIT_EXCEEDED' ||\n cause.limit !== 'maxInspectionMessageBytes' ||\n maxItems === 1\n )\n throw cause;\n maxItems = Math.max(1, Math.floor(maxItems / 2));\n }\n }\n } finally {\n isReadingPage = false;\n }\n } else throw createInspectionProcessFailure();\n } catch (cause) {\n fail(cause);\n }\n});\nport.on('messageerror', fail);\nsend({ attemptId, kind: 'ready', maxAnalysisHeapBytes });\n"],"mappings":"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"}
1
+ {"version":3,"file":"analysis-worker.js","names":[],"sources":["../src/node-inspection/analysis-worker.ts"],"sourcesContent":["import { getHeapStatistics } from 'node:v8';\nimport { parentPort, workerData } from 'node:worker_threads';\n\nimport {\n RepositorySourceException,\n type IRepositoryReader,\n type IRepositorySnapshot,\n} from '@moldea.ai/repository';\n\nimport type { IProjectInspection } from '../contracts/index.js';\nimport { CoreOperationException } from '../exceptions/index.js';\nimport { normalizeCoreOptions } from '../options/index.js';\n\nimport {\n NODE_INSPECTION_FILE_PAGE_BYTES,\n NODE_INSPECTION_MAX_REQUESTS,\n NODE_INSPECTION_TRANSPORT_BYTES,\n} from './constants.js';\nimport { deserializeInspectionFailure, serializeInspectionFailure } from './errors.js';\nimport {\n createInspectionProcessFailure,\n decodeInspectionMessage,\n encodeInspectionMessage,\n} from './protocol.js';\nimport {\n parseRpcEntry,\n parseRpcEntryPage,\n parseRpcFilePage,\n parseRpcLinkText,\n} from './repository-rpc.js';\nimport type { INodeInspectionMessage, INodeReaderRequest, INodeReaderSource } from './types.js';\n\nconst port = parentPort;\nif (port === null) throw createInspectionProcessFailure();\nconst start = decodeInspectionMessage(workerData);\nif (start.kind !== 'start') throw createInspectionProcessFailure();\nconst attemptId = start.attemptId;\nconst maxAnalysisHeapBytes = getHeapStatistics().heap_size_limit;\nlet inspection: IProjectInspection | undefined;\nlet hasRun = false;\nlet isReadingPage = false;\nlet nextRequestId = 0;\nconst pending = new Map<\n number,\n { resolve: (result: unknown) => void; reject: (cause: unknown) => void }\n>();\nconst send = (message: INodeInspectionMessage): void => {\n port.postMessage(encodeInspectionMessage(message));\n};\n\n/** Admits at most four requests across both bridges; no unbounded transport wait queue exists. */\nconst requestReader = (request: INodeReaderRequest): Promise<unknown> => {\n if (pending.size >= NODE_INSPECTION_MAX_REQUESTS)\n return Promise.reject(\n new CoreOperationException({\n code: 'RESOURCE_LIMIT_EXCEEDED',\n operation: 'create-project-inspection',\n limit: 'maxReaderRequests',\n limitMaximum: NODE_INSPECTION_MAX_REQUESTS,\n observedUsage: pending.size + 1,\n nextAction: null,\n }),\n );\n const requestId = nextRequestId++;\n return new Promise<unknown>((resolve, reject) => {\n pending.set(requestId, { resolve, reject });\n try {\n send({ attemptId, kind: 'reader-request', requestId, request });\n } catch (cause) {\n pending.delete(requestId);\n reject(cause instanceof Error ? cause : createInspectionProcessFailure(cause));\n }\n });\n};\n\n/** Proxies one caller-owned reader; only the repository source lists entries. */\nconst createProxyReader = (\n source: INodeReaderSource,\n snapshot: IRepositorySnapshot,\n): IRepositoryReader => ({\n snapshot,\n getEntry: async (path) =>\n parseRpcEntry(await requestReader({ method: 'getEntry', path, source })),\n listEntriesPage: async (options) =>\n source === 'repository'\n ? parseRpcEntryPage(\n await requestReader({\n method: 'listEntriesPage',\n maxEntries: Math.min(128, options.maxEntries),\n ...(options.cursor === undefined ? {} : { cursor: options.cursor }),\n ...(options.prefix === undefined ? {} : { prefix: options.prefix }),\n }),\n )\n : Promise.reject(\n new RepositorySourceException({\n code: 'SOURCE_UNAVAILABLE',\n operation: 'list-entries-page',\n path: null,\n retryable: false,\n }),\n ),\n readFilePage: async (path, options) =>\n parseRpcFilePage(\n await requestReader({\n method: 'readFilePage',\n path,\n offset: options.offset,\n maxBytes: Math.min(NODE_INSPECTION_FILE_PAGE_BYTES, options.maxBytes),\n source,\n }),\n ),\n readLinkText: async (path) =>\n parseRpcLinkText(await requestReader({ method: 'readLinkText', path, source })),\n compare: () =>\n Promise.reject(\n new RepositorySourceException({\n code: 'SOURCE_UNAVAILABLE',\n operation: 'create-comparison',\n path: null,\n retryable: false,\n }),\n ),\n});\n\nconst repository = createProxyReader('repository', start.snapshot);\nconst instructions: IRepositoryReader | null =\n start.instructions === null\n ? null\n : createProxyReader('instructions', start.instructions.snapshot);\n\n/** Prepares the fixed Core implementation after the parent acknowledges the heap. */\nconst prepare = async (): Promise<void> => {\n const { createCore } = await import('../core/index.js');\n const options = normalizeCoreOptions({\n limits: {\n ...start.limits,\n maxRetainedBytes: start.limits.maxRetainedBytes - NODE_INSPECTION_TRANSPORT_BYTES,\n },\n });\n const core = createCore(options);\n inspection = await core.createProjectInspection({\n repository,\n ...(instructions === null ? {} : { instructions }),\n });\n const metadata = {\n source: inspection.source,\n formatVersion: inspection.formatVersion,\n valid: inspection.valid,\n counts: inspection.counts,\n coverageCounts: inspection.coverageCounts,\n summary: inspection.summary,\n resourceUsage: inspection.resourceUsage,\n inspectionDigest: inspection.inspectionDigest,\n };\n send({\n attemptId,\n kind: 'prepared',\n inspection: {\n ...metadata,\n maxAnalysisHeapBytes,\n resourceUsage: {\n ...metadata.resourceUsage,\n retainedBytes: metadata.resourceUsage.retainedBytes + NODE_INSPECTION_TRANSPORT_BYTES,\n peakRetainedBytes:\n metadata.resourceUsage.peakRetainedBytes + NODE_INSPECTION_TRANSPORT_BYTES,\n },\n },\n });\n};\n\n/** Translates worker failures to safe package contracts while the supervisor stays responsive. */\nconst fail = (cause: unknown): void => {\n try {\n const failure = serializeInspectionFailure(cause);\n if (\n cause instanceof CoreOperationException &&\n cause.code === 'RESOURCE_LIMIT_EXCEEDED' &&\n cause.limit === 'maxRetainedBytes' &&\n cause.observedUsage !== null\n ) {\n failure.options['limitMaximum'] = start.limits.maxRetainedBytes;\n failure.options['observedUsage'] = cause.observedUsage + NODE_INSPECTION_TRANSPORT_BYTES;\n }\n send({ attemptId, kind: 'failure', failure });\n } catch {\n port.close();\n }\n};\n\nport.on('message', (frame: unknown) => {\n try {\n const message = decodeInspectionMessage(frame);\n if (message.attemptId !== attemptId) throw createInspectionProcessFailure();\n if (message.kind === 'run') {\n if (hasRun) throw createInspectionProcessFailure();\n hasRun = true;\n void prepare().catch(fail);\n } else if (message.kind === 'reader-response' || message.kind === 'reader-failure') {\n const request = pending.get(message.requestId);\n if (request === undefined) throw createInspectionProcessFailure();\n pending.delete(message.requestId);\n if (message.kind === 'reader-failure')\n request.reject(deserializeInspectionFailure(message.failure));\n else request.resolve(message.result);\n } else if (message.kind === 'read-page') {\n if (inspection === undefined || isReadingPage) throw createInspectionProcessFailure();\n isReadingPage = true;\n try {\n if (message.input.maxItems > start.limits.maxEntries)\n throw new CoreOperationException({\n code: 'INVALID_ARGUMENT',\n operation: 'create-project-inspection',\n });\n let maxItems = Math.min(256, message.input.maxItems);\n while (true) {\n try {\n const frame = encodeInspectionMessage({\n attemptId,\n kind: 'page',\n requestId: message.requestId,\n result: inspection.readPage({ ...message.input, maxItems }),\n });\n port.postMessage(frame);\n break;\n } catch (cause) {\n if (\n !(cause instanceof CoreOperationException) ||\n cause.code !== 'RESOURCE_LIMIT_EXCEEDED' ||\n cause.limit !== 'maxInspectionMessageBytes' ||\n maxItems === 1\n )\n throw cause;\n maxItems = Math.max(1, Math.floor(maxItems / 2));\n }\n }\n } finally {\n isReadingPage = false;\n }\n } else throw createInspectionProcessFailure();\n } catch (cause) {\n fail(cause);\n }\n});\nport.on('messageerror', fail);\nsend({ attemptId, kind: 'ready', maxAnalysisHeapBytes });\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
- import { E as parseDecisionIdFromPath, O as trimRepositoryFormatWhitespace, S as isRuntimeGuidancePath, T as isVariableId, a as escapeJsonPointerSegment, c as freezeRecursively, d as hasNonWhitespace, g as isContextPath, i as createCoreDiagnosticCollector, l as compareExactStrings, n as normalizeCoreOptions, o as normalizeDiagnostics, r as countDiagnosticsBySeverity, s as createNullPrototypeRecord, t as createCoreOperationOptionsSnapshot, u as countUnicodeScalars } from "./options-BVF3DQHm.js";
1
+ import { E as parseDecisionIdFromPath, O as trimRepositoryFormatWhitespace, S as isRuntimeGuidancePath, T as isVariableId, a as escapeJsonPointerSegment, c as freezeRecursively, d as hasNonWhitespace, g as isContextPath, i as createCoreDiagnosticCollector, l as compareExactStrings, n as normalizeCoreOptions, o as normalizeDiagnostics, r as countDiagnosticsBySeverity, s as createNullPrototypeRecord, t as createCoreOperationOptionsSnapshot, u as countUnicodeScalars } from "./options-l3kVfA-K.js";
2
2
  import { n as CoreOperationException } from "./exceptions-CYf1pCKf.js";
3
- import { a as createSourceLocator, c as calculateContentDigest, i as parseStrictYaml, l as calculateNormalizedTextDigest, n as inspectManifestDocument, o as collectManifestScopeDeclarations, r as parseManifestDocument, s as matchesRepositoryGlob, t as matchManifestScope, u as normalizeTextDocument } from "./scope-DoNl6LhC.js";
4
- import { REPOSITORY_ROOT, RepositorySourceException, compareRepositoryPaths, createRepositoryIdentity, isRepositoryPath, parseRepositoryPath } from "@moldea.ai/repository";
3
+ import { a as createSourceLocator, c as calculateContentDigest, i as parseStrictYaml, l as calculateNormalizedTextDigest, n as inspectManifestDocument, o as collectManifestScopeDeclarations, r as parseManifestDocument, s as matchesRepositoryGlob, t as matchManifestScope, u as normalizeTextDocument } from "./scope-D9BYchNI.js";
4
+ import { REPOSITORY_LINK_TEXT_MAX_BYTES, REPOSITORY_ROOT, RepositorySourceException, compareRepositoryPaths, createRepositoryIdentity, isRepositoryPath, parseRepositoryPath, resolveRepositoryLink } from "@moldea.ai/repository";
5
5
  //#region \0rolldown/runtime.js
6
6
  var __defProp = Object.defineProperty;
7
7
  var __exportAll = (all, no_symbols) => {
@@ -534,41 +534,6 @@ var copyReaderEntry$1 = (candidate, operation, fallbackPath, expectedPath) => {
534
534
  type: typeCandidate
535
535
  };
536
536
  };
537
- var REFUSED_LINK_STATES = [
538
- "broken",
539
- "denied",
540
- "loop",
541
- "unsafe"
542
- ];
543
- var LINK_TARGET_TYPES = [
544
- "directory",
545
- "file",
546
- "other"
547
- ];
548
- /** Copies one untrusted link resolution, rejecting any shape outside the closed contract. */
549
- var copyLinkResolution = (candidate, path) => {
550
- if (typeof candidate !== "object" || candidate === null) return invalidSourceData$3("get-entry", path);
551
- const record = candidate;
552
- const keys = Object.keys(record).sort().join();
553
- const refusedState = REFUSED_LINK_STATES.find((state) => state === record["state"]);
554
- if (Reflect.ownKeys(record).length !== Object.keys(record).length) return invalidSourceData$3("get-entry", path);
555
- if (record["state"] === "not-link" || refusedState !== void 0) return keys === "state" ? { state: refusedState ?? "not-link" } : invalidSourceData$3("get-entry", path);
556
- const targetIdentity = record["targetIdentity"];
557
- const targetType = LINK_TARGET_TYPES.find((type) => type === record["targetType"]);
558
- if (typeof targetIdentity !== "string" || targetIdentity.length === 0 || targetType === void 0) return invalidSourceData$3("get-entry", path);
559
- if (record["state"] === "outside" && keys === "state,targetIdentity,targetType") return {
560
- state: "outside",
561
- targetIdentity,
562
- targetType
563
- };
564
- const targetPath = record["targetPath"];
565
- return record["state"] === "inside" && keys === "state,targetIdentity,targetPath,targetType" && typeof targetPath === "string" && isRepositoryPath(targetPath) ? {
566
- state: "inside",
567
- targetIdentity,
568
- targetPath: parseRepositoryPath(targetPath),
569
- targetType
570
- } : invalidSourceData$3("get-entry", path);
571
- };
572
537
  var isStrictDescendant = (path, prefix) => {
573
538
  if (path === prefix) return false;
574
539
  const descendantPrefix = prefix === REPOSITORY_ROOT ? REPOSITORY_ROOT : `${prefix}/`;
@@ -593,7 +558,7 @@ var createSourceOptions = (sessionSignal, operationSignal) => {
593
558
  * @param repository The source-neutral reader bound to one coherent snapshot.
594
559
  * @param limits The immutable resource limits for the inspection.
595
560
  * @param signal Optional cancellation shared by every inspection operation.
596
- * @param instructions Optional instruction source read only through the instruction view.
561
+ * @param instructions Optional reader of the four instruction paths, used only by the instruction view.
597
562
  * @returns A session that pages source metadata and range-reads bounded canonical files.
598
563
  * @throws
599
564
  * - ABORTED: The Core operation was aborted.
@@ -780,36 +745,33 @@ var createRepositoryInspectionSession = (repository, limits, signal, instruction
780
745
  }
781
746
  };
782
747
  };
783
- const instructionReader = instructions?.reader ?? repository;
784
- const instructionPages = instructions === void 0 ? repositoryPages : {
785
- readPage: (path, options) => instructions.reader.readFilePage(path, options),
786
- snapshotId: instructions.reader.snapshot.id
787
- };
788
- const linkResolver = instructions?.linkResolver;
789
- const linkPages = linkResolver === void 0 ? void 0 : {
790
- readPage: (path, options) => linkResolver.readLinkTargetPage(path, options),
791
- snapshotId: linkResolver.snapshot.id
748
+ const readerFor = (path) => instructions !== void 0 && INSTRUCTION_PATHS.has(path) ? instructions : repository;
749
+ const pagesFor = (path) => {
750
+ const source = readerFor(path);
751
+ return source === repository ? repositoryPages : {
752
+ readPage: (pagePath, options) => source.readFilePage(pagePath, options),
753
+ snapshotId: source.snapshot.id
754
+ };
792
755
  };
793
- const requireInstructionPath = (path) => {
756
+ /** Reads one link's stored text from the routed source, rejecting text past the shared limit. */
757
+ const readLinkText = async (path, options) => {
794
758
  const parsedPath = parseRepositoryPath(path);
795
- if (!INSTRUCTION_PATHS.has(parsedPath)) throw new TypeError("The instruction view reads only coding-agent instruction paths.");
796
- return parsedPath;
759
+ throwIfSignalAborted(options?.signal);
760
+ registerPath(parsedPath);
761
+ const text = await awaitWithCancellation(readerFor(parsedPath).readLinkText(parsedPath, createSourceOptions(signal, options?.signal)), options?.signal);
762
+ throwIfSignalAborted(options?.signal);
763
+ if (text !== null && (typeof text !== "string" || encoder$1.encode(text).byteLength > REPOSITORY_LINK_TEXT_MAX_BYTES)) return invalidSourceData$3("read-link-text", parsedPath);
764
+ return text;
797
765
  };
798
766
  const instructionView = Object.freeze({
799
- getEntry: (path) => getEntryFrom(instructionReader, requireInstructionPath(path)),
800
- readLinkedSourceFile: (path) => {
801
- if (linkPages === void 0) throw new TypeError("The instruction view has no link resolver to read through.");
802
- return readRetainedSource(requireInstructionPath(path), linkPages);
767
+ getEntry: (path, options) => {
768
+ const parsedPath = parseRepositoryPath(path);
769
+ return getEntryFrom(readerFor(parsedPath), parsedPath, options);
803
770
  },
804
- readSourceFile: (path) => readRetainedSource(requireInstructionPath(path), instructionPages),
805
- resolveLink: async (path) => {
806
- const parsedPath = requireInstructionPath(path);
807
- if (linkResolver === void 0) return null;
808
- throwIfSignalAborted();
809
- registerPath(parsedPath);
810
- const candidate = await awaitWithCancellation(linkResolver.resolveLink(parsedPath, createSourceOptions(signal, void 0)));
811
- throwIfSignalAborted();
812
- return copyLinkResolution(candidate, parsedPath);
771
+ readLinkText,
772
+ readSourceFile: (path) => {
773
+ const parsedPath = parseRepositoryPath(path);
774
+ return readRetainedSource(parsedPath, pagesFor(parsedPath));
813
775
  }
814
776
  });
815
777
  const reader = Object.freeze({
@@ -2028,19 +1990,14 @@ var readRetainedText = async (ledger, load) => {
2028
1990
  };
2029
1991
  /** Distinguishes missing and non-regular files without an extra entry lookup or following symlinks. */
2030
1992
  var getAbsentKind = (error) => error instanceof RepositorySourceException ? error.code === "ENTRY_NOT_FOUND" ? "missing" : error.code === "ENTRY_NOT_FILE" ? "non-regular" : null : null;
2031
- /**
2032
- * Explains why a linked instruction file cannot be read, or returns null for a readable link.
2033
- * @param resolution The resolver's classification, or null when no resolver is available.
2034
- * @returns The content-free link state, or null when the final target is a regular file.
2035
- */
2036
- var getUnreadableLinkState = (resolution) => {
2037
- if (resolution === null) return "unavailable";
2038
- if (resolution.state === "inside" || resolution.state === "outside") return resolution.targetType === "file" ? null : resolution.targetType;
2039
- return resolution.state;
2040
- };
2041
1993
  //#endregion
2042
1994
  //#region src/integration-validation/agents-inspection.ts
2043
1995
  var AGENTS_PATH$1 = parseRepositoryPath("/AGENTS.md");
1996
+ /** Reports an AGENTS.md link that doesn't lead to a file, with its reason as the qualifier. */
1997
+ var reportUnresolvedLink = (report, reason) => report("MOLDEA_INTEGRATION_LINK_UNRESOLVED", {
1998
+ entryKind: "symlink",
1999
+ reason
2000
+ }, reason);
2044
2001
  /**
2045
2002
  * Checks one readable AGENTS.md text against its referenced skill installation.
2046
2003
  * @returns A promise that settles after at most one integration warning was recorded.
@@ -2062,10 +2019,7 @@ var checkAgentsDocument = async (context, report, load, entryDetails) => {
2062
2019
  } catch (error) {
2063
2020
  const absentKind = getAbsentKind(error);
2064
2021
  if (absentKind === null) throw error;
2065
- return entryDetails["entryKind"] === "symlink" ? report("MOLDEA_INTEGRATION_UNVERIFIED", {
2066
- entryKind: "symlink",
2067
- linkState: "not-file"
2068
- }) : report("MOLDEA_INTEGRATION_BLOCK_MISSING", { entryKind: absentKind });
2022
+ return entryDetails["entryKind"] === "symlink" ? reportUnresolvedLink(report, absentKind === "missing" ? "missing" : "not-file") : report("MOLDEA_INTEGRATION_BLOCK_MISSING", { entryKind: absentKind });
2069
2023
  }
2070
2024
  try {
2071
2025
  if (document.text === null) return report("MOLDEA_INTEGRATION_BLOCK_MISSING", {
@@ -2128,9 +2082,9 @@ var checkAgentsDocument = async (context, report, load, entryDetails) => {
2128
2082
  }
2129
2083
  };
2130
2084
  /**
2131
- * Checks root AGENTS.md against its referenced skill installation. A symlinked AGENTS.md whose
2132
- * final target is a readable regular file, inside or outside the repository, is checked on the
2133
- * target text; any other link is reported as unverifiable without reading it.
2085
+ * Checks root AGENTS.md against its referenced skill installation. A symlinked AGENTS.md that
2086
+ * leads to a regular file in the repository is checked on that file's text; any other link is
2087
+ * reported with its reason, without reading anything outside the repository.
2134
2088
  * @param context The instruction view, repository reader, ledger, and warning recorder.
2135
2089
  * @returns What AGENTS.md is, including its link resolution, for the Claude Code check.
2136
2090
  * @throws
@@ -2145,7 +2099,7 @@ var checkAgentsDocument = async (context, report, load, entryDetails) => {
2145
2099
  */
2146
2100
  var inspectAgentsIntegration = async (context) => {
2147
2101
  const { instructions } = context;
2148
- const report = (code, details) => context.report(code, AGENTS_PATH$1, details);
2102
+ const report = (code, details, qualifier) => context.report(code, AGENTS_PATH$1, details, qualifier);
2149
2103
  const entry = await instructions.getEntry(AGENTS_PATH$1);
2150
2104
  if (entry === null) {
2151
2105
  report("MOLDEA_INTEGRATION_BLOCK_MISSING", { entryKind: "missing" });
@@ -2159,16 +2113,11 @@ var inspectAgentsIntegration = async (context) => {
2159
2113
  await checkAgentsDocument(context, report, () => instructions.readSourceFile(AGENTS_PATH$1), { entryKind: "file" });
2160
2114
  return { kind: "file" };
2161
2115
  }
2162
- const resolution = await instructions.resolveLink(AGENTS_PATH$1);
2163
- const linkState = getUnreadableLinkState(resolution);
2164
- if (linkState !== null || resolution === null) report("MOLDEA_INTEGRATION_UNVERIFIED", {
2165
- entryKind: "symlink",
2166
- linkState: linkState ?? "unavailable"
2167
- });
2168
- else await checkAgentsDocument(context, report, () => instructions.readLinkedSourceFile(AGENTS_PATH$1), {
2169
- entryKind: "symlink",
2170
- linkTarget: resolution.state
2171
- });
2116
+ const resolution = await resolveRepositoryLink(instructions, AGENTS_PATH$1);
2117
+ if (resolution.state === "file") {
2118
+ const { targetPath } = resolution;
2119
+ await checkAgentsDocument(context, report, () => instructions.readSourceFile(targetPath), { entryKind: "symlink" });
2120
+ } else reportUnresolvedLink(report, resolution.state);
2172
2121
  return {
2173
2122
  kind: "link",
2174
2123
  resolution
@@ -2180,13 +2129,16 @@ var AGENTS_PATH = parseRepositoryPath("/AGENTS.md");
2180
2129
  var CLAUDE_PATH = parseRepositoryPath("/CLAUDE.md");
2181
2130
  var NESTED_CLAUDE_PATH = parseRepositoryPath("/.claude/CLAUDE.md");
2182
2131
  var LOCAL_CLAUDE_PATH = parseRepositoryPath("/CLAUDE.local.md");
2183
- /** Recognizes a link between a Claude file and AGENTS.md without reading either file. */
2132
+ /** Returns the regular file AGENTS.md leads to, or null when it leads to none. */
2133
+ var getAgentsTargetPath = (agents) => {
2134
+ if (agents.kind === "file") return AGENTS_PATH;
2135
+ return agents.kind === "link" && agents.resolution.state === "file" ? agents.resolution.targetPath : null;
2136
+ };
2137
+ /** Recognizes a link between a Claude file and AGENTS.md by final target path, without reading. */
2184
2138
  var isLinkedToAgents = (path, resolution, agents) => {
2185
- const agentsResolution = agents.kind === "link" ? agents.resolution : null;
2186
- if (agentsResolution?.state === "inside" && agentsResolution.targetPath === path) return true;
2187
- if (resolution === null || resolution.state !== "inside" && resolution.state !== "outside") return false;
2188
- if (agents.kind === "file") return resolution.state === "inside" && resolution.targetPath === AGENTS_PATH;
2189
- return (agentsResolution?.state === "inside" || agentsResolution?.state === "outside") && agentsResolution.targetIdentity === resolution.targetIdentity;
2139
+ const agentsTargetPath = getAgentsTargetPath(agents);
2140
+ if (agents.kind === "link" && agentsTargetPath === path) return true;
2141
+ return resolution?.state === "file" && resolution.targetPath === agentsTargetPath;
2190
2142
  };
2191
2143
  /**
2192
2144
  * Determines whether one Claude Code file loads AGENTS.md through an import line, a link to the
@@ -2214,24 +2166,26 @@ var assessClaudeFile = async (context, path, agents) => {
2214
2166
  };
2215
2167
  let load = () => instructions.readSourceFile(path);
2216
2168
  if (entry.type === "symlink") {
2217
- const resolution = await instructions.resolveLink(path);
2169
+ const resolution = await resolveRepositoryLink(instructions, path);
2218
2170
  if (isLinkedToAgents(path, resolution, agents)) return { kind: "loads" };
2219
- const linkState = getUnreadableLinkState(resolution);
2220
- if (linkState !== null) return {
2221
- kind: "unverified",
2222
- linkState
2171
+ if (resolution.state !== "file") return {
2172
+ kind: "unresolved",
2173
+ reason: resolution.state
2223
2174
  };
2224
- load = () => instructions.readLinkedSourceFile(path);
2175
+ const { targetPath } = resolution;
2176
+ load = () => instructions.readSourceFile(targetPath);
2225
2177
  }
2226
2178
  let document;
2227
2179
  try {
2228
2180
  document = await readRetainedText(ledger, load);
2229
2181
  } catch (error) {
2230
- if (getAbsentKind(error) === null) throw error;
2231
- return entry.type === "symlink" ? {
2232
- kind: "unverified",
2233
- linkState: "not-file"
2234
- } : { kind: "absent" };
2182
+ const absentKind = getAbsentKind(error);
2183
+ if (absentKind === null) throw error;
2184
+ if (entry.type !== "symlink") return { kind: "absent" };
2185
+ return {
2186
+ kind: "unresolved",
2187
+ reason: absentKind === "missing" ? "missing" : "not-file"
2188
+ };
2235
2189
  }
2236
2190
  try {
2237
2191
  return document.text !== null && hasAgentsImport(document.text, path === NESTED_CLAUDE_PATH) ? { kind: "loads" } : {
@@ -2245,8 +2199,9 @@ var assessClaudeFile = async (context, path, agents) => {
2245
2199
  /**
2246
2200
  * Checks whether Claude Code loads AGENTS.md. When `/CLAUDE.md` or `/.claude/CLAUDE.md` exists,
2247
2201
  * only those shared files count; `/CLAUDE.local.md` counts only when neither exists. At most one
2248
- * Claude warning is recorded: unverifiable for the first unverifiable counted file when none
2249
- * loads AGENTS.md, otherwise a missing import for the governing file.
2202
+ * Claude warning is recorded: an unresolved link for the first counted file whose link doesn't
2203
+ * lead to a file in the repository when none loads AGENTS.md, otherwise a missing import for the
2204
+ * governing file.
2250
2205
  * @param context The instruction view, ledger, and warning recorder.
2251
2206
  * @param agents What root AGENTS.md is, as the AGENTS.md check observed it.
2252
2207
  * @returns A promise that settles after at most one Claude warning was recorded.
@@ -2278,12 +2233,13 @@ var inspectClaudeIntegration = async (context, agents) => {
2278
2233
  path: LOCAL_CLAUDE_PATH
2279
2234
  });
2280
2235
  }
2281
- const unverifiable = counted.find(({ assessment }) => assessment.kind === "unverified");
2282
- if (unverifiable?.assessment.kind === "unverified") {
2283
- context.report("MOLDEA_INTEGRATION_UNVERIFIED", unverifiable.path, {
2236
+ const unresolved = counted.find(({ assessment }) => assessment.kind === "unresolved");
2237
+ if (unresolved?.assessment.kind === "unresolved") {
2238
+ const { reason } = unresolved.assessment;
2239
+ context.report("MOLDEA_INTEGRATION_LINK_UNRESOLVED", unresolved.path, {
2284
2240
  entryKind: "symlink",
2285
- linkState: unverifiable.assessment.linkState
2286
- });
2241
+ reason
2242
+ }, reason);
2287
2243
  return;
2288
2244
  }
2289
2245
  const governing = counted[0];
@@ -2294,9 +2250,11 @@ var inspectClaudeIntegration = async (context, agents) => {
2294
2250
  /**
2295
2251
  * Checks the coding-agent integration: root AGENTS.md and the Claude Code instruction files
2296
2252
  * through the instruction view, and the referenced skill installation through the repository
2297
- * reader, with at most six entry lookups, four link resolutions, and five bounded reads.
2253
+ * reader. It reads at most four instruction files, follows at most 32 links for each with one
2254
+ * lookup and one link-text read per link, and makes at most five bounded reads, all inside the
2255
+ * repository.
2298
2256
  * @param reader The repository inspection reader for skill files and the managed asset.
2299
- * @param instructions The instruction view for the coding-agent instruction paths.
2257
+ * @param instructions The instruction view that routes the four instruction paths and links.
2300
2258
  * @param limits The immutable resource limits for the inspection.
2301
2259
  * @param signal Optional cancellation for repository lookups.
2302
2260
  * @returns Completed content-free integration warnings, never an execution or runtime-wiring claim.
@@ -2316,12 +2274,12 @@ var inspectCodingAgentIntegration = async (reader, instructions, limits, signal)
2316
2274
  instructions,
2317
2275
  ledger: getRetainedMemory(reader),
2318
2276
  reader,
2319
- report: (code, subject, details) => {
2277
+ report: (code, subject, details, qualifier) => {
2320
2278
  collector.add({
2321
2279
  code,
2322
2280
  path: subject,
2323
2281
  subject,
2324
- qualifier: null,
2282
+ qualifier: qualifier ?? null,
2325
2283
  entity: { integrationPath: subject },
2326
2284
  details
2327
2285
  });
@@ -3222,7 +3180,7 @@ var inspectUniversalProject = async (context, options) => {
3222
3180
  "MOLDEA_INTEGRATION_BLOCK_MISSING",
3223
3181
  "MOLDEA_INTEGRATION_SKILL_MISSING",
3224
3182
  "MOLDEA_INTEGRATION_BLOCK_STALE",
3225
- "MOLDEA_INTEGRATION_UNVERIFIED",
3183
+ "MOLDEA_INTEGRATION_LINK_UNRESOLVED",
3226
3184
  "MOLDEA_INTEGRATION_CLAUDE_IMPORT_MISSING"
3227
3185
  ], ...patterns.completed ? ["MOLDEA_IMPACT_PATTERN_UNMATCHED"] : []]), options.limits);
3228
3186
  const project = !diagnostics.some((diagnostic) => diagnostic.severity === "error") && indexedManifest !== null && projectAssets.project !== null ? createProjectIndex({
@@ -3253,22 +3211,7 @@ var invalidArgument$1 = () => {
3253
3211
  });
3254
3212
  };
3255
3213
  var isRepositoryReader = (candidate) => {
3256
- return isRecord(candidate) && isRecord(candidate["snapshot"]) && typeof candidate["snapshot"]["id"] === "string" && typeof candidate["snapshot"]["sourceKind"] === "string" && typeof candidate["compare"] === "function" && typeof candidate["getEntry"] === "function" && typeof candidate["listEntriesPage"] === "function" && typeof candidate["readFilePage"] === "function";
3257
- };
3258
- var isLinkResolver = (candidate) => {
3259
- return isRecord(candidate) && isRecord(candidate["snapshot"]) && typeof candidate["snapshot"]["id"] === "string" && typeof candidate["snapshot"]["sourceKind"] === "string" && typeof candidate["resolveLink"] === "function" && typeof candidate["readLinkTargetPage"] === "function";
3260
- };
3261
- var validateInstructions = (candidate) => {
3262
- if (!isRecord(candidate) || Reflect.ownKeys(candidate).some((key) => key !== "reader" && key !== "linkResolver")) return invalidArgument$1();
3263
- const reader = candidate["reader"];
3264
- const linkResolver = candidate["linkResolver"];
3265
- if (!isRepositoryReader(reader)) return invalidArgument$1();
3266
- if (linkResolver === void 0) return { reader };
3267
- if (!isLinkResolver(linkResolver) || linkResolver.snapshot.id !== reader.snapshot.id) return invalidArgument$1();
3268
- return {
3269
- linkResolver,
3270
- reader
3271
- };
3214
+ return isRecord(candidate) && isRecord(candidate["snapshot"]) && typeof candidate["snapshot"]["id"] === "string" && typeof candidate["snapshot"]["sourceKind"] === "string" && typeof candidate["compare"] === "function" && typeof candidate["getEntry"] === "function" && typeof candidate["listEntriesPage"] === "function" && typeof candidate["readFilePage"] === "function" && typeof candidate["readLinkText"] === "function";
3272
3215
  };
3273
3216
  var isAbortSignal = (candidate) => {
3274
3217
  return isRecord(candidate) && typeof candidate["aborted"] === "boolean" && typeof candidate["addEventListener"] === "function" && typeof candidate["removeEventListener"] === "function";
@@ -3279,9 +3222,9 @@ var validateInput = (candidate) => {
3279
3222
  const repository = candidate["repository"];
3280
3223
  const instructions = candidate["instructions"];
3281
3224
  const signal = candidate["signal"];
3282
- if (Reflect.ownKeys(candidate).some((key) => key !== "repository" && key !== "instructions" && key !== "signal") || !isRepositoryReader(repository) || signal !== void 0 && !isAbortSignal(signal)) return invalidArgument$1();
3225
+ if (Reflect.ownKeys(candidate).some((key) => key !== "repository" && key !== "instructions" && key !== "signal") || !isRepositoryReader(repository) || instructions !== void 0 && !isRepositoryReader(instructions) || signal !== void 0 && !isAbortSignal(signal)) return invalidArgument$1();
3283
3226
  return {
3284
- ...instructions === void 0 ? {} : { instructions: validateInstructions(instructions) },
3227
+ ...instructions === void 0 ? {} : { instructions },
3285
3228
  repository,
3286
3229
  ...signal === void 0 ? {} : { signal }
3287
3230
  };
@@ -3292,7 +3235,7 @@ var validateInput = (candidate) => {
3292
3235
  };
3293
3236
  /**
3294
3237
  * Inspects one coherent repository snapshot through universal file and export validation.
3295
- * @param input The untrusted source-neutral reader, optional instruction source, and signal.
3238
+ * @param input The untrusted source-neutral reader, optional instruction reader, and signal.
3296
3239
  * @param options The immutable Core configuration snapshot.
3297
3240
  * @returns A promise resolving to the frozen all-or-nothing project inspection result.
3298
3241
  * @throws
@@ -3694,4 +3637,4 @@ var createCore = (options) => {
3694
3637
  //#endregion
3695
3638
  export { createCore as n, parseIntegrationBlock as r, core_exports as t };
3696
3639
 
3697
- //# sourceMappingURL=core-CMuQrqRI.js.map
3640
+ //# sourceMappingURL=core-BCMf-ig9.js.map