@moldea.ai/core 4.0.0 → 5.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.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { n as CoreOperationException, t as CoreConfigurationException } from "./chunks/exceptions-C_KfCIjE.js";
1
+ import { n as CoreOperationException, r as registerRuntimeAdapterRetainedByteReservation, t as CoreConfigurationException } from "./chunks/exceptions-HS9ofVy2.js";
2
2
  import { REPOSITORY_ROOT, RepositoryPathException, RepositorySourceException, compareRepositoryPaths, createRepositoryIdentity, isRepositoryPath, parseRepositoryPath } from "@moldea.ai/repository";
3
3
  import { Parser, isAlias, isMap, isScalar, isSeq, parseAllDocuments } from "yaml";
4
4
  //#region src/constants/index.ts
@@ -496,6 +496,7 @@ var serializeDiagnostic = (diagnostic) => {
496
496
  ];
497
497
  return JSON.stringify([
498
498
  diagnostic.code,
499
+ diagnostic.severity,
499
500
  serializeDiagnosticDetails(diagnostic.details),
500
501
  entity,
501
502
  diagnostic.message,
@@ -514,7 +515,7 @@ var readEntityValue = (entity, key) => {
514
515
  return entity?.[key] ?? "";
515
516
  };
516
517
  var compareDiagnostics = (left, right) => {
517
- return compareNullableStrings$2(left.path, right.path) || compareRanges(left.range, right.range) || compareNullableStrings$2(left.pointer, right.pointer) || compareExactStrings(left.source, right.source) || compareExactStrings(left.code, right.code) || compareExactStrings(readEntityValue(left.entity, "agentId"), readEntityValue(right.entity, "agentId")) || compareExactStrings(readEntityValue(left.entity, "capabilityKind"), readEntityValue(right.entity, "capabilityKind")) || compareExactStrings(readEntityValue(left.entity, "capabilityId"), readEntityValue(right.entity, "capabilityId")) || compareExactStrings(readEntityValue(left.entity, "decisionId"), readEntityValue(right.entity, "decisionId")) || compareExactStrings(readEntityValue(left.entity, "variableId"), readEntityValue(right.entity, "variableId")) || compareExactStrings(readEntityValue(left.entity, "adapterId"), readEntityValue(right.entity, "adapterId")) || compareExactStrings(serializeDiagnosticDetails(left.details), serializeDiagnosticDetails(right.details)) || compareExactStrings(left.message, right.message);
518
+ return compareNullableStrings$2(left.path, right.path) || compareRanges(left.range, right.range) || compareNullableStrings$2(left.pointer, right.pointer) || compareExactStrings(left.source, right.source) || compareExactStrings(left.code, right.code) || compareExactStrings(left.severity, right.severity) || compareExactStrings(readEntityValue(left.entity, "agentId"), readEntityValue(right.entity, "agentId")) || compareExactStrings(readEntityValue(left.entity, "capabilityKind"), readEntityValue(right.entity, "capabilityKind")) || compareExactStrings(readEntityValue(left.entity, "capabilityId"), readEntityValue(right.entity, "capabilityId")) || compareExactStrings(readEntityValue(left.entity, "decisionId"), readEntityValue(right.entity, "decisionId")) || compareExactStrings(readEntityValue(left.entity, "variableId"), readEntityValue(right.entity, "variableId")) || compareExactStrings(readEntityValue(left.entity, "adapterId"), readEntityValue(right.entity, "adapterId")) || compareExactStrings(serializeDiagnosticDetails(left.details), serializeDiagnosticDetails(right.details)) || compareExactStrings(left.message, right.message);
518
519
  };
519
520
  /**
520
521
  * Creates one normalized, immutable Core diagnostic.
@@ -532,6 +533,7 @@ var createCoreDiagnostic = (input) => {
532
533
  path: input.path,
533
534
  pointer: input.pointer ?? null,
534
535
  range: input.range ?? null,
536
+ severity: "error",
535
537
  source: "core"
536
538
  });
537
539
  };
@@ -549,6 +551,17 @@ var normalizeDiagnostics = (candidates) => {
549
551
  }
550
552
  return freezeRecursively([...diagnostics.values()].sort(compareDiagnostics));
551
553
  };
554
+ /** Counts the complete normalized diagnostic result by severity once. */
555
+ var countDiagnosticsBySeverity = (diagnostics) => {
556
+ let errorCount = 0;
557
+ let warningCount = 0;
558
+ for (const diagnostic of diagnostics) if (diagnostic.severity === "error") errorCount += 1;
559
+ else warningCount += 1;
560
+ return {
561
+ errorCount,
562
+ warningCount
563
+ };
564
+ };
552
565
  /**
553
566
  * Creates a deterministic, deduplicating diagnostic collector for one operation.
554
567
  * @param limits The Core resource limits governing diagnostic output.
@@ -2312,11 +2325,13 @@ var parseManifestDocument = async (input, options, operation = "parse-manifest")
2312
2325
  };
2313
2326
  //#endregion
2314
2327
  //#region src/project-agent-assignments/index.ts
2315
- /** Collects deterministic content-free agent-to-runtime assignments from a validated project. */
2316
- var collectProjectAgentAssignments = (project) => project.agents.map((agent) => ({
2317
- agentId: agent.id,
2318
- runtimeId: agent.declaration.runtime.id
2319
- })).sort((left, right) => compareExactStrings(left.agentId, right.agentId) || compareExactStrings(left.runtimeId, right.runtimeId));
2328
+ /** Iterates content-free agent-to-runtime assignments without retaining an intermediate array. */
2329
+ var iterateProjectAgentAssignments = function* (project) {
2330
+ for (const agent of project.agents) yield {
2331
+ agentId: agent.id,
2332
+ runtimeId: agent.declaration.runtime.id
2333
+ };
2334
+ };
2320
2335
  //#endregion
2321
2336
  //#region src/project-metadata/index.ts
2322
2337
  var createAssetItem = (asset, kind, agentId = null, decisionId = null) => ({
@@ -2329,18 +2344,18 @@ var createAssetItem = (asset, kind, agentId = null, decisionId = null) => ({
2329
2344
  path: asset.path,
2330
2345
  scalarLength: asset.scalarLength
2331
2346
  });
2332
- var compareMetadataItems = (left, right) => compareExactStrings(left.path, right.path) || compareExactStrings(left.kind, right.kind) || compareExactStrings(left.agentId ?? "", right.agentId ?? "");
2333
- /** Collects deterministic content-free asset metadata from one validated project. */
2334
- var collectProjectMetadata = (project) => {
2335
- const items = [createAssetItem(project.manifest.asset, "manifest"), createAssetItem(project.project, "project")];
2336
- for (const context of project.context) items.push(createAssetItem(context.asset, "context"));
2337
- for (const { decision } of project.decisions) items.push(createAssetItem(decision.asset, "decision", null, decision.id));
2338
- for (const runtime of project.runtimes) items.push(createAssetItem(runtime.asset, "runtime-guidance"));
2347
+ /** Iterates content-free asset metadata without retaining a second project-sized collection. */
2348
+ var iterateProjectMetadata = function* (project) {
2349
+ yield createAssetItem(project.manifest.asset, "manifest");
2350
+ yield createAssetItem(project.project, "project");
2351
+ for (const context of project.context) yield createAssetItem(context.asset, "context");
2352
+ for (const { decision } of project.decisions) yield createAssetItem(decision.asset, "decision", null, decision.id);
2353
+ for (const runtime of project.runtimes) yield createAssetItem(runtime.asset, "runtime-guidance");
2339
2354
  for (const agent of project.agents) {
2340
- items.push(createAssetItem(agent.description.asset, "agent-description", agent.id));
2341
- items.push(createAssetItem(agent.instruction, "agent-instruction", agent.id));
2342
- if (agent.handoffDescription !== null) items.push(createAssetItem(agent.handoffDescription.asset, "agent-handoff-description", agent.id));
2343
- for (const mirror of agent.mirrors) items.push({
2355
+ yield createAssetItem(agent.description.asset, "agent-description", agent.id);
2356
+ yield createAssetItem(agent.instruction, "agent-instruction", agent.id);
2357
+ if (agent.handoffDescription !== null) yield createAssetItem(agent.handoffDescription.asset, "agent-handoff-description", agent.id);
2358
+ for (const mirror of agent.mirrors) yield {
2344
2359
  agentId: agent.id,
2345
2360
  byteLength: mirror.byteLength,
2346
2361
  canonicalDigest: mirror.canonicalDigest,
@@ -2349,9 +2364,8 @@ var collectProjectMetadata = (project) => {
2349
2364
  kind: "mirror",
2350
2365
  path: mirror.path,
2351
2366
  scalarLength: mirror.scalarLength
2352
- });
2367
+ };
2353
2368
  }
2354
- return items.sort(compareMetadataItems);
2355
2369
  };
2356
2370
  /** Creates the content-free summary for one validated project snapshot. */
2357
2371
  var createProjectSummary = (project) => ({
@@ -2452,6 +2466,7 @@ var EVIDENCE_KEYS = /* @__PURE__ */ new Set([
2452
2466
  ]);
2453
2467
  var DIAGNOSTIC_KEYS = /* @__PURE__ */ new Set([
2454
2468
  "source",
2469
+ "severity",
2455
2470
  "code",
2456
2471
  "message",
2457
2472
  "path",
@@ -2462,6 +2477,33 @@ var DIAGNOSTIC_KEYS = /* @__PURE__ */ new Set([
2462
2477
  ]);
2463
2478
  var ADAPTER_RESULT_KEYS = /* @__PURE__ */ new Set(["evidence", "diagnostics"]);
2464
2479
  var ADAPTER_CODE_PATTERN = /^[A-Z][A-Z0-9_]*$/u;
2480
+ var UNVERIFIED_MESSAGE = "The declared runtime relationship could not be verified.";
2481
+ var UNVERIFIED_RELATIONSHIPS = /* @__PURE__ */ new Set([
2482
+ "runtime-agent",
2483
+ "instruction-loader",
2484
+ "agent-input-schema",
2485
+ "agent-output-schema",
2486
+ "tool-implementation",
2487
+ "tool-registration",
2488
+ "tool-input-schema",
2489
+ "tool-output-schema",
2490
+ "skill-implementation",
2491
+ "skill-registration",
2492
+ "handoff-registration",
2493
+ "routing-description",
2494
+ "variable-provider"
2495
+ ]);
2496
+ var SIMPLE_WARNING_KEYS = /* @__PURE__ */ new Set(["relationship", "reason"]);
2497
+ var VERSION_WARNING_KEYS = /* @__PURE__ */ new Set([
2498
+ "relationship",
2499
+ "reason",
2500
+ "packageName",
2501
+ "declaredRange",
2502
+ "boundaryVersion"
2503
+ ]);
2504
+ var PACKAGE_NAME_PATTERN = /^(?:@[a-z0-9][a-z0-9._~-]*\/)?[a-z0-9][a-z0-9._~-]*$/u;
2505
+ var BOUNDARY_VERSION_PATTERN = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)$/u;
2506
+ var RANGE_COMPARATOR_PATTERN = new RegExp(`^(?:<=|>=|<|>|=)?(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$`, "u");
2465
2507
  var isRecord$2 = (candidate) => {
2466
2508
  return typeof candidate === "object" && candidate !== null && !Array.isArray(candidate);
2467
2509
  };
@@ -2491,7 +2533,11 @@ var registerRawOutput = (outputCounts, key, amount, context) => {
2491
2533
  outputCounts[key] += amount;
2492
2534
  };
2493
2535
  var hasOnlyKeys = (candidate, keys) => {
2494
- return Reflect.ownKeys(candidate).every((key) => typeof key === "string" && keys.has(key));
2536
+ return Reflect.ownKeys(candidate).every((key) => {
2537
+ if (typeof key !== "string" || !keys.has(key)) return false;
2538
+ const descriptor = Object.getOwnPropertyDescriptor(candidate, key);
2539
+ return descriptor !== void 0 && descriptor.enumerable && "value" in descriptor;
2540
+ });
2495
2541
  };
2496
2542
  var isSafeString = (candidate) => {
2497
2543
  return typeof candidate === "string" && isUnicodeScalarText(candidate) && !candidate.includes("\0");
@@ -2558,6 +2604,58 @@ var normalizeEntity = (candidate, context) => {
2558
2604
  if (decisionId !== void 0 && !context.decisionIds.has(decisionId)) return invalidAdapterResult(context.adapterId);
2559
2605
  return normalizeDiagnosticEntity(entity);
2560
2606
  };
2607
+ /** Checks only the safe wire grammar; adapters own SemVer meaning and normalization. */
2608
+ var isNormalizedRangeWire = (candidate) => {
2609
+ if (candidate === "*") return true;
2610
+ return candidate.split(" || ").every((set) => {
2611
+ const comparators = set.split(" ");
2612
+ return comparators.length > 0 && comparators.every((part) => RANGE_COMPARATOR_PATTERN.test(part));
2613
+ });
2614
+ };
2615
+ var isValidWarningSubject = (relationship, entity, context) => {
2616
+ if (entity?.agentId === void 0 || entity.decisionId !== void 0) return false;
2617
+ const agent = context.agentsById.get(entity.agentId);
2618
+ if (agent === void 0) return false;
2619
+ if (relationship === "variable-provider") return entity.capabilityKind === void 0 && entity.capabilityId === void 0 && entity.variableId !== void 0 && agent.declaration.bindings?.variableProviders?.[entity.variableId] !== void 0;
2620
+ if (entity.variableId !== void 0) return false;
2621
+ if (relationship.startsWith("tool-")) {
2622
+ if (entity.capabilityKind !== "tool" || entity.capabilityId === void 0) return false;
2623
+ const tool = agent.declaration.tools?.[entity.capabilityId];
2624
+ return tool !== void 0 && (relationship !== "tool-input-schema" || tool.inputSchema !== void 0) && (relationship !== "tool-output-schema" || tool.outputSchema !== void 0);
2625
+ }
2626
+ if (relationship.startsWith("skill-")) return entity.capabilityKind === "skill" && entity.capabilityId !== void 0 && agent.declaration.skills?.[entity.capabilityId] !== void 0;
2627
+ if (entity.capabilityKind !== void 0 || entity.capabilityId !== void 0) return false;
2628
+ if (relationship === "runtime-agent") return agent.declaration.bindings?.runtimeAgent !== void 0;
2629
+ if (relationship === "instruction-loader") return agent.declaration.bindings?.instructionLoader !== void 0;
2630
+ if (relationship === "agent-input-schema") return agent.declaration.bindings?.inputSchema !== void 0;
2631
+ if (relationship === "agent-output-schema") return agent.declaration.bindings?.outputSchema !== void 0;
2632
+ return relationship === "handoff-registration" || relationship === "routing-description";
2633
+ };
2634
+ var normalizeWarningDetails = (candidate, entity, context) => {
2635
+ const details = normalizeDetails(candidate, context.adapterId);
2636
+ const relationship = details["relationship"];
2637
+ const reason = details["reason"];
2638
+ if (typeof relationship !== "string" || !UNVERIFIED_RELATIONSHIPS.has(relationship) || !isValidWarningSubject(relationship, entity, context)) return invalidAdapterResult(context.adapterId);
2639
+ if (reason === "unsupported-source-pattern" || reason === "dynamic-source-pattern") {
2640
+ if (!hasOnlyKeys(details, SIMPLE_WARNING_KEYS)) return invalidAdapterResult(context.adapterId);
2641
+ return freezeRecursively({
2642
+ relationship,
2643
+ reason
2644
+ });
2645
+ }
2646
+ if (reason !== "version-dependent-behavior" || !hasOnlyKeys(details, VERSION_WARNING_KEYS)) return invalidAdapterResult(context.adapterId);
2647
+ const packageName = details["packageName"];
2648
+ const declaredRange = details["declaredRange"];
2649
+ const boundaryVersion = details["boundaryVersion"];
2650
+ if (typeof packageName !== "string" || !PACKAGE_NAME_PATTERN.test(packageName) || declaredRange !== null && (typeof declaredRange !== "string" || !isNormalizedRangeWire(declaredRange)) || typeof boundaryVersion !== "string" || !BOUNDARY_VERSION_PATTERN.test(boundaryVersion)) return invalidAdapterResult(context.adapterId);
2651
+ return freezeRecursively({
2652
+ boundaryVersion,
2653
+ declaredRange,
2654
+ packageName,
2655
+ reason,
2656
+ relationship
2657
+ });
2658
+ };
2561
2659
  var normalizeReference = (candidate, adapterId) => {
2562
2660
  if (!isRecord$2(candidate) || !hasOnlyKeys(candidate, REFERENCE_KEYS)) return invalidAdapterResult(adapterId);
2563
2661
  const pathCandidate = candidate["path"];
@@ -2618,23 +2716,41 @@ var validateEvidenceReferences = async (evidence, context) => {
2618
2716
  var normalizeDiagnostic = (candidate, context) => {
2619
2717
  if (!isRecord$2(candidate) || !hasOnlyKeys(candidate, DIAGNOSTIC_KEYS)) return invalidAdapterResult(context.adapterId);
2620
2718
  const source = candidate["source"];
2719
+ const severity = candidate["severity"];
2621
2720
  const code = candidate["code"];
2622
2721
  const message = candidate["message"];
2623
2722
  const pathCandidate = candidate["path"];
2624
2723
  const pointer = candidate["pointer"];
2625
2724
  const namespace = `${context.adapterId.toUpperCase().replaceAll("-", "_")}_`;
2626
- if (source !== context.adapterId || !isSafeString(code) || !ADAPTER_CODE_PATTERN.test(code) || !code.startsWith(namespace) || code.length === namespace.length || !isSafeString(message) || message.length === 0 || pathCandidate !== null && (typeof pathCandidate !== "string" || !isRepositoryPath(pathCandidate)) || pointer !== null && (typeof pointer !== "string" || !isJsonPointer(pointer))) return invalidAdapterResult(context.adapterId);
2725
+ const isUnverified = code === `${namespace}RUNTIME_RELATIONSHIP_UNVERIFIED`;
2726
+ if (source !== context.adapterId || !isSafeString(code) || !ADAPTER_CODE_PATTERN.test(code) || !code.startsWith(namespace) || code.length === namespace.length || (isUnverified ? severity !== "warning" || message !== UNVERIFIED_MESSAGE : severity !== "error") || !isSafeString(message) || message.length === 0 || pathCandidate !== null && (typeof pathCandidate !== "string" || !isRepositoryPath(pathCandidate)) || pointer !== null && (typeof pointer !== "string" || !isJsonPointer(pointer))) return invalidAdapterResult(context.adapterId);
2627
2727
  const path = pathCandidate === null ? null : parseRepositoryPath(pathCandidate);
2628
2728
  const range = normalizeRange(candidate["range"], context.adapterId);
2729
+ const entity = normalizeEntity(candidate["entity"], context);
2629
2730
  if (path === null && (pointer !== null || range !== null)) return invalidAdapterResult(context.adapterId);
2731
+ if (isUnverified) {
2732
+ if (path === null) return invalidAdapterResult(context.adapterId);
2733
+ return freezeRecursively({
2734
+ code,
2735
+ details: normalizeWarningDetails(candidate["details"], entity, context),
2736
+ entity,
2737
+ message,
2738
+ path,
2739
+ pointer,
2740
+ range,
2741
+ severity: "warning",
2742
+ source
2743
+ });
2744
+ }
2630
2745
  return freezeRecursively({
2631
2746
  code,
2632
2747
  details: normalizeDetails(candidate["details"], context.adapterId),
2633
- entity: normalizeEntity(candidate["entity"], context),
2748
+ entity,
2634
2749
  message,
2635
2750
  path,
2636
2751
  pointer,
2637
2752
  range,
2753
+ severity: "error",
2638
2754
  source
2639
2755
  });
2640
2756
  };
@@ -3148,6 +3264,7 @@ var createRepositoryInspectionSession = (repository, limits, signal) => {
3148
3264
  readFilePage: readAdapterFilePage,
3149
3265
  snapshot: repository.snapshot
3150
3266
  });
3267
+ registerRuntimeAdapterRetainedByteReservation(adapterRepository, reserveRetainedBytes);
3151
3268
  return Object.freeze({
3152
3269
  adapterRepository,
3153
3270
  getResourceUsage: () => Object.freeze({
@@ -4899,39 +5016,49 @@ var validateProjectState = async (input, options) => {
4899
5016
  session,
4900
5017
  ...validatedInput.signal === void 0 ? {} : { signal: validatedInput.signal }
4901
5018
  }, operationOptions);
4902
- if (universal.project === null) return freezeRecursively({
4903
- project: null,
4904
- resourceUsage: session.getResourceUsage(),
4905
- result: {
4906
- diagnostics: universal.diagnostics,
4907
- evidence: [],
4908
- formatVersion: universal.formatVersion,
4909
- source: validatedInput.repository.snapshot,
4910
- summary: null,
4911
- valid: false
4912
- }
4913
- });
5019
+ if (universal.project === null) {
5020
+ const counts = countDiagnosticsBySeverity(universal.diagnostics);
5021
+ return freezeRecursively({
5022
+ project: null,
5023
+ resourceUsage: session.getResourceUsage(),
5024
+ result: {
5025
+ diagnostics: universal.diagnostics,
5026
+ ...counts,
5027
+ evidence: [],
5028
+ formatVersion: universal.formatVersion,
5029
+ source: validatedInput.repository.snapshot,
5030
+ summary: null,
5031
+ valid: false
5032
+ }
5033
+ });
5034
+ }
4914
5035
  const projectSummary = createProjectSummary(universal.project);
4915
5036
  const availabilityDiagnostics = validateRuntimeAdapterAvailability(universal.runtimeLocations, universal.project.formatVersion, operationOptions);
4916
- if (availabilityDiagnostics.length > 0) return freezeRecursively({
4917
- project: universal.project,
4918
- resourceUsage: session.getResourceUsage(),
4919
- result: {
4920
- diagnostics: availabilityDiagnostics,
4921
- evidence: [],
4922
- formatVersion: universal.formatVersion,
4923
- source: validatedInput.repository.snapshot,
4924
- summary: projectSummary,
4925
- valid: false
4926
- }
4927
- });
5037
+ if (availabilityDiagnostics.length > 0) {
5038
+ const counts = countDiagnosticsBySeverity(availabilityDiagnostics);
5039
+ return freezeRecursively({
5040
+ project: universal.project,
5041
+ resourceUsage: session.getResourceUsage(),
5042
+ result: {
5043
+ diagnostics: availabilityDiagnostics,
5044
+ ...counts,
5045
+ evidence: [],
5046
+ formatVersion: universal.formatVersion,
5047
+ source: validatedInput.repository.snapshot,
5048
+ summary: projectSummary,
5049
+ valid: false
5050
+ }
5051
+ });
5052
+ }
4928
5053
  const adapterInspection = await inspectRuntimeAdapters(universal.project, session, operationOptions, validatedInput.signal);
4929
- const valid = adapterInspection.diagnostics.length === 0;
5054
+ const counts = countDiagnosticsBySeverity(adapterInspection.diagnostics);
5055
+ const valid = counts.errorCount === 0;
4930
5056
  return freezeRecursively({
4931
5057
  project: universal.project,
4932
5058
  resourceUsage: session.getResourceUsage(),
4933
5059
  result: {
4934
5060
  diagnostics: adapterInspection.diagnostics,
5061
+ ...counts,
4935
5062
  evidence: adapterInspection.evidence,
4936
5063
  formatVersion: universal.formatVersion,
4937
5064
  source: validatedInput.repository.snapshot,
@@ -4944,7 +5071,7 @@ var validateProjectState = async (input, options) => {
4944
5071
  var validateProject = async (input, options) => (await validateProjectState(input, options)).result;
4945
5072
  //#endregion
4946
5073
  //#region src/project-inspection/index.ts
4947
- var CURSOR_PREFIX = "core4";
5074
+ var CURSOR_PREFIX = "core5";
4948
5075
  var PREPARED_FIXED_BYTES = 512;
4949
5076
  var PREPARED_ITEM_FIXED_BYTES = 64;
4950
5077
  var PREPARED_TEXT_BYTE_MULTIPLIER = 2;
@@ -4975,7 +5102,9 @@ var serializeDeterministically = (candidate) => {
4975
5102
  if (Array.isArray(candidate)) return `[${candidate.map((item) => serializeDeterministically(item)).join(",")}]`;
4976
5103
  return `{${Object.entries(candidate).filter(([, value]) => value !== void 0).sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0).map(([key, value]) => `${JSON.stringify(key)}:${serializeDeterministically(value)}`).join(",")}}`;
4977
5104
  };
4978
- var createIdentity = (parts) => createRepositoryIdentity(parts.map((part) => encoder.encode(part)));
5105
+ var createIdentity = (parts) => createRepositoryIdentity((function* () {
5106
+ for (const part of parts) yield encoder.encode(part);
5107
+ })());
4979
5108
  var createItemBaseKey = (item) => {
4980
5109
  if (item.kind === "agent") return [
4981
5110
  "3",
@@ -5007,19 +5136,19 @@ var createItemBaseKey = (item) => {
5007
5136
  };
5008
5137
  /** Assigns stable unique keys once without relying on collection offsets. */
5009
5138
  var createKeyedItems = (items) => {
5010
- const sorted = items.map((item) => ({
5011
- baseKey: createItemBaseKey(item),
5012
- item
5013
- })).sort((left, right) => left.baseKey < right.baseKey ? -1 : left.baseKey > right.baseKey ? 1 : 0);
5014
- const occurrences = /* @__PURE__ */ new Map();
5015
- return sorted.map(({ baseKey, item }) => {
5016
- const occurrence = occurrences.get(baseKey) ?? 0;
5017
- occurrences.set(baseKey, occurrence + 1);
5018
- return {
5019
- item,
5020
- key: `${baseKey}:${String(occurrence).padStart(10, "0")}`
5021
- };
5022
- });
5139
+ const sorted = Array.from(items, (item) => ({
5140
+ item,
5141
+ key: createItemBaseKey(item)
5142
+ })).sort((left, right) => left.key < right.key ? -1 : left.key > right.key ? 1 : 0);
5143
+ let previousBaseKey = null;
5144
+ let occurrence = 0;
5145
+ for (const item of sorted) {
5146
+ const baseKey = item.key;
5147
+ occurrence = baseKey === previousBaseKey ? occurrence + 1 : 0;
5148
+ previousBaseKey = baseKey;
5149
+ item.key = `${baseKey}:${String(occurrence).padStart(10, "0")}`;
5150
+ }
5151
+ return sorted;
5023
5152
  };
5024
5153
  var createCursorChecksum = (inspectionDigest, lastKey, view) => createIdentity([
5025
5154
  CURSOR_PREFIX,
@@ -5036,7 +5165,7 @@ var encodeCursor = (inspectionDigest, view, lastKey) => [
5036
5165
  ].join(":");
5037
5166
  var decodeCursor = (cursor, inspectionDigest, view) => {
5038
5167
  if (cursor === void 0) return null;
5039
- const match = /^core4:(all|diagnostics|evidence|metadata):([^:]+):(sha256:[0-9a-f]{64}):(sha256:[0-9a-f]{64})$/u.exec(cursor);
5168
+ const match = /^core5:(all|diagnostics|evidence|metadata):([^:]+):(sha256:[0-9a-f]{64}):(sha256:[0-9a-f]{64})$/u.exec(cursor);
5040
5169
  if (match === null || match[1] !== view || match[3] !== inspectionDigest) return invalidArgument$1();
5041
5170
  let lastKey;
5042
5171
  try {
@@ -5058,17 +5187,73 @@ var addRetainedBytes = (current, additional, retainedBeforePreparation, maximum)
5058
5187
  if (!Number.isSafeInteger(additional) || additional < 0 || !Number.isSafeInteger(projectedUsage) || projectedUsage > maximum) return resourceLimitExceeded$1(maximum, Number.isSafeInteger(projectedUsage) ? projectedUsage : Number.MAX_SAFE_INTEGER);
5059
5188
  return current + additional;
5060
5189
  };
5061
- /** Calculates deterministic logical bytes retained by prepared records and view indexes. */
5062
- var calculatePreparedBytes = (items, views, header, retainedBeforePreparation, maximum) => {
5190
+ /** Iterates every content-free inspection item without retaining preparation state. */
5191
+ var iterateProjectInspectionItems = function* (state) {
5192
+ if (state.project !== null) for (const metadata of iterateProjectMetadata(state.project)) yield {
5193
+ kind: "metadata",
5194
+ metadata
5195
+ };
5196
+ for (const diagnostic of state.result.diagnostics) yield {
5197
+ diagnostic,
5198
+ kind: "diagnostic"
5199
+ };
5200
+ for (const evidence of state.result.evidence) yield {
5201
+ evidence,
5202
+ kind: "evidence"
5203
+ };
5204
+ if (state.project !== null) for (const agent of iterateProjectAgentAssignments(state.project)) yield {
5205
+ agent,
5206
+ kind: "agent"
5207
+ };
5208
+ };
5209
+ /** Preflights the complete logical prepared-state cost before retaining its collections. */
5210
+ var estimatePreparedProjectInspection = (state, baseCounts, maximum) => {
5211
+ const retainedBeforePreparation = state.resourceUsage.retainedBytes;
5063
5212
  let bytes = addRetainedBytes(0, PREPARED_FIXED_BYTES, retainedBeforePreparation, maximum);
5064
- for (const { item, key } of items) {
5213
+ let metadataCount = 0;
5214
+ for (const item of iterateProjectInspectionItems(state)) {
5215
+ const key = `${createItemBaseKey(item)}:0000000000`;
5065
5216
  const encodedBytes = encoder.encode(key).byteLength + encoder.encode(serializeDeterministically(item)).byteLength;
5066
- bytes = addRetainedBytes(bytes, PREPARED_ITEM_FIXED_BYTES + encodedBytes * PREPARED_TEXT_BYTE_MULTIPLIER, retainedBeforePreparation, maximum);
5067
- }
5068
- bytes = addRetainedBytes(bytes, encoder.encode(serializeDeterministically(header)).byteLength * PREPARED_TEXT_BYTE_MULTIPLIER, retainedBeforePreparation, maximum);
5069
- bytes = addRetainedBytes(bytes, (views.diagnostics.length + views.evidence.length + views.metadata.length) * PREPARED_VIEW_REFERENCE_BYTES, retainedBeforePreparation, maximum);
5070
- return bytes;
5217
+ bytes = addRetainedBytes(bytes, PREPARED_ITEM_FIXED_BYTES + encodedBytes * PREPARED_TEXT_BYTE_MULTIPLIER + PREPARED_VIEW_REFERENCE_BYTES, retainedBeforePreparation, maximum);
5218
+ if (item.kind === "metadata") metadataCount += 1;
5219
+ }
5220
+ const counts = {
5221
+ agents: baseCounts.agents,
5222
+ context: baseCounts.context,
5223
+ decisions: baseCounts.decisions,
5224
+ diagnostics: baseCounts.diagnostics,
5225
+ errors: baseCounts.errors,
5226
+ evidence: baseCounts.evidence,
5227
+ metadata: metadataCount,
5228
+ mirrors: baseCounts.mirrors,
5229
+ runtimes: baseCounts.runtimes,
5230
+ unresolved: baseCounts.unresolved,
5231
+ warnings: baseCounts.warnings
5232
+ };
5233
+ bytes = addRetainedBytes(bytes, encoder.encode(serializeDeterministically({
5234
+ counts,
5235
+ formatVersion: state.result.formatVersion,
5236
+ inspectionDigest: "sha256:0000000000000000000000000000000000000000000000000000000000000000",
5237
+ source: state.result.source,
5238
+ summary: state.result.summary,
5239
+ valid: state.result.valid
5240
+ })).byteLength * PREPARED_TEXT_BYTE_MULTIPLIER, retainedBeforePreparation, maximum);
5241
+ return {
5242
+ counts,
5243
+ preparedBytes: bytes
5244
+ };
5071
5245
  };
5246
+ /** Creates the inspection digest without materializing a project-sized key projection. */
5247
+ var createInspectionDigest = (counts, formatVersion, items, summary, valid) => createIdentity((function* () {
5248
+ yield "core5-prepared-inspection";
5249
+ yield serializeDeterministically({
5250
+ counts,
5251
+ formatVersion,
5252
+ summary,
5253
+ valid
5254
+ });
5255
+ for (const { key } of items) yield key;
5256
+ })());
5072
5257
  var findStartIndex = (items, lastKey) => {
5073
5258
  if (lastKey === null) return 0;
5074
5259
  let lower = 0;
@@ -5085,23 +5270,9 @@ var findStartIndex = (items, lastKey) => {
5085
5270
  };
5086
5271
  /** Creates the returned inspection from content-free state only. */
5087
5272
  var createPreparedProjectInspection = (input) => {
5088
- const { counts, formatVersion, items, maxEntries, maxRetainedBytes, resourceUsage: validationUsage, source, summary, valid } = input;
5273
+ const { counts, formatVersion, items, maxEntries, preparedBytes, resourceUsage: validationUsage, source, summary, valid } = input;
5089
5274
  const views = createViews(items);
5090
- const inspectionDigest = createIdentity([serializeDeterministically({
5091
- counts,
5092
- formatVersion,
5093
- itemKeys: items.map(({ key }) => key),
5094
- summary,
5095
- valid
5096
- })]);
5097
- const preparedBytes = calculatePreparedBytes(items, views, {
5098
- counts,
5099
- formatVersion,
5100
- inspectionDigest,
5101
- source,
5102
- summary,
5103
- valid
5104
- }, validationUsage.retainedBytes, maxRetainedBytes);
5275
+ const inspectionDigest = createInspectionDigest(counts, formatVersion, items, summary, valid);
5105
5276
  const resourceUsage = freezeRecursively({
5106
5277
  canonicalBytes: validationUsage.canonicalBytes,
5107
5278
  peakRetainedBytes: Math.max(validationUsage.peakRetainedBytes, validationUsage.retainedBytes + preparedBytes),
@@ -5150,42 +5321,26 @@ var createPreparedProjectInspection = (input) => {
5150
5321
  /** Prepares one immutable content-free inspection for synchronous bounded page reads. */
5151
5322
  var createProjectInspection = async (input, options) => {
5152
5323
  const state = await validateProjectState(input, options);
5153
- const metadata = state.project === null ? [] : collectProjectMetadata(state.project);
5154
- const agentAssignments = state.project === null ? [] : collectProjectAgentAssignments(state.project);
5155
- const items = freezeRecursively(createKeyedItems([
5156
- ...metadata.map((metadataItem) => ({
5157
- kind: "metadata",
5158
- metadata: metadataItem
5159
- })),
5160
- ...state.result.diagnostics.map((diagnostic) => ({
5161
- diagnostic,
5162
- kind: "diagnostic"
5163
- })),
5164
- ...state.result.evidence.map((evidence) => ({
5165
- evidence,
5166
- kind: "evidence"
5167
- })),
5168
- ...agentAssignments.map((agent) => ({
5169
- agent,
5170
- kind: "agent"
5171
- }))
5172
- ]));
5324
+ const estimate = estimatePreparedProjectInspection(state, {
5325
+ agents: state.result.summary?.counts.agents ?? 0,
5326
+ context: state.result.summary?.counts.context ?? 0,
5327
+ decisions: state.result.summary?.counts.decisions ?? 0,
5328
+ diagnostics: state.result.diagnostics.length,
5329
+ errors: state.result.errorCount,
5330
+ evidence: state.result.evidence.length,
5331
+ mirrors: state.result.summary?.counts.mirrors ?? 0,
5332
+ runtimes: state.result.summary?.counts.runtimes ?? 0,
5333
+ unresolved: state.result.summary?.counts.unresolved ?? 0,
5334
+ warnings: state.result.warningCount
5335
+ }, options.limits.maxRetainedBytes);
5336
+ const counts = freezeRecursively(estimate.counts);
5337
+ const items = freezeRecursively(createKeyedItems(iterateProjectInspectionItems(state)));
5173
5338
  return createPreparedProjectInspection({
5174
- counts: freezeRecursively({
5175
- agents: state.result.summary?.counts.agents ?? 0,
5176
- context: state.result.summary?.counts.context ?? 0,
5177
- decisions: state.result.summary?.counts.decisions ?? 0,
5178
- diagnostics: state.result.diagnostics.length,
5179
- evidence: state.result.evidence.length,
5180
- metadata: metadata.length,
5181
- mirrors: state.result.summary?.counts.mirrors ?? 0,
5182
- runtimes: state.result.summary?.counts.runtimes ?? 0,
5183
- unresolved: state.result.summary?.counts.unresolved ?? 0
5184
- }),
5339
+ counts,
5185
5340
  formatVersion: state.result.formatVersion,
5186
5341
  items,
5187
5342
  maxEntries: options.limits.maxEntries,
5188
- maxRetainedBytes: options.limits.maxRetainedBytes,
5343
+ preparedBytes: estimate.preparedBytes,
5189
5344
  resourceUsage: state.resourceUsage,
5190
5345
  source: state.result.source,
5191
5346
  summary: state.result.summary,