@gitroll/tacitt-cli 0.6.10 → 0.6.12

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 (63) hide show
  1. package/README.md +47 -4
  2. package/bin/INDEX.md +6 -4
  3. package/bin/tacitt.cjs +1 -0
  4. package/dist/{agent-setup-LPd8WEsN.mjs → agent-setup-B12VbvN_.mjs} +2 -2
  5. package/dist/agent-setup-worker.mjs +5 -5
  6. package/dist/cli.mjs +39 -25
  7. package/dist/codex-title-worker.mjs +2 -2
  8. package/dist/configured-preview-worker.mjs +5 -5
  9. package/dist/configured-session-worker.mjs +27 -27
  10. package/dist/{frame-ByT1xayJ.mjs → frame-B3He21G8.mjs} +1 -1
  11. package/dist/{heap-CM298Yu0.mjs → heap-Blrat--4.mjs} +469 -30
  12. package/dist/inspection-worker.mjs +4 -4
  13. package/dist/{job-BHIwElNF.mjs → job-CBuIMTQ0.mjs} +57 -22
  14. package/dist/{locate-Cwv6WH8n.mjs → locate-D-ZaHpI0.mjs} +184 -18
  15. package/dist/{model-zvn5GUJ9.mjs → model-DR9odhWP.mjs} +1 -1
  16. package/dist/operation-executor.mjs +3 -3
  17. package/dist/preview-worker.mjs +1 -1
  18. package/dist/privacy-validator.mjs +49 -2
  19. package/dist/{query-By41gaKm.mjs → query-BYDcNKy2.mjs} +1869 -716
  20. package/dist/{run-ZQx7p4Rw.mjs → run-DQ9xyKSt.mjs} +4 -4
  21. package/dist/session-process.mjs +20 -0
  22. package/dist/{src-D_DfY--2.mjs → src-CKQlTA2Z.mjs} +297 -207
  23. package/dist/{src-3jvMvSQn.mjs → src-DeNJ8vOD.mjs} +535 -140
  24. package/dist/{src-BqtdFVq7.mjs → src-Do-qzuMn.mjs} +2329 -1786
  25. package/dist/store-database-worker.mjs +1 -1
  26. package/dist/web/assets/index-BgDdPL1c.js +172 -0
  27. package/dist/web/assets/index-DzOozqms.css +1 -0
  28. package/dist/web/index.html +3 -2
  29. package/package.json +2 -1
  30. package/skills/INDEX.md +6 -4
  31. package/skills/tacitt/INDEX.md +7 -6
  32. package/skills/tacitt/SKILL.md +11 -11
  33. package/skills/tacitt/references/INDEX.md +14 -11
  34. package/skills/tacitt/references/b-method.md +4 -4
  35. package/skills/tacitt/references/bootstrap.md +19 -5
  36. package/skills/tacitt/references/classification.md +4 -4
  37. package/skills/tacitt/references/commands.md +51 -34
  38. package/skills/tacitt/references/journey.md +7 -7
  39. package/skills/tacitt/references/parallel-review.md +35 -35
  40. package/skills/tacitt/references/send.md +15 -6
  41. package/skills/tacitt/scripts/INDEX.md +40 -37
  42. package/skills/tacitt/scripts/answer.mjs +91 -15
  43. package/skills/tacitt/scripts/journey-card-consolidation.mjs +1 -1
  44. package/skills/tacitt/scripts/journey-classification-metadata.mjs +75 -26
  45. package/skills/tacitt/scripts/journey-classification-progress.mjs +1 -2
  46. package/skills/tacitt/scripts/journey-classification-tasks.mjs +28 -8
  47. package/skills/tacitt/scripts/journey-classification.mjs +6 -1
  48. package/skills/tacitt/scripts/journey-consolidation.mjs +1 -0
  49. package/skills/tacitt/scripts/journey-panel-host.d.mts +2 -0
  50. package/skills/tacitt/scripts/journey-panel-host.mjs +25 -2
  51. package/skills/tacitt/scripts/journey-scan-timing.d.mts +5 -0
  52. package/skills/tacitt/scripts/journey-scan-timing.mjs +31 -4
  53. package/skills/tacitt/scripts/journey-state.d.mts +9 -1
  54. package/skills/tacitt/scripts/journey-state.mjs +95 -8
  55. package/skills/tacitt/scripts/journey-tasks.d.mts +1 -0
  56. package/skills/tacitt/scripts/journey-tasks.mjs +24 -9
  57. package/skills/tacitt/scripts/journey.d.mts +44 -31
  58. package/skills/tacitt/scripts/journey.mjs +34 -7
  59. package/skills/tacitt/scripts/privacy-validator.mjs +188 -11
  60. package/skills/tacitt/scripts/review.d.mts +7 -6
  61. package/skills/tacitt/scripts/review.mjs +922 -205
  62. package/dist/web/assets/index-B14e6_-z.js +0 -174
  63. package/dist/web/assets/index-CYJBq1px.css +0 -1
@@ -1,6 +1,6 @@
1
- import { $n as detectStatic, An as createReplacementKey, Bn as nativeItems, En as walkNativeFields, Fn as entityDictionaryVersion, Gn as validateProfile, H as codePointLength, Hn as transformRecords, In as nativeParserVersion, Jn as validatePlan, Ln as redactionImplementationVersion, Mn as projectNativeRecord, Nn as parseNativeRecord, Pn as cleanupImplementationVersion, Qn as resolveLimits, Qt as safeCode, Un as frameRecords, V as bDigest, Vn as nativeText, Wn as retainedMainTextNodes, Xn as defaultLimits, Xt as ApplicationError, Zn as recordPointerLimits, _n as reviewRoles, bn as createSessionPreparation, c as textDigest, dr as fail$1, fn as nativeSourceIdentitySchema, fr as isProcessingCode, gn as mainReviewRole, hn as projectNativeReviewInput, in as sourceKey, ir as createEntityMatcher, j as bDuplicateShift, jn as sessionNonce, k as bBindingCap, lr as defaultDetectionLimits, mn as processNativeRecord, nn as reviewFamilies, nr as jsonSpans, o as reviewDigest, on as sourceSnapshotId, pn as withMandatoryCustomTerms, qn as buildPlan, rr as agentContextLocation, tn as familySelected, ur as ProcessingError, vn as createSentenceContext, wn as createDetectionSummary, x as createBAnalysisUnits, xn as bindInspection, yn as renderNative, zn as nativeField } from "./locate-Cwv6WH8n.mjs";
2
- import { t as createZstdFrameCheck } from "./frame-ByT1xayJ.mjs";
3
- import { Fn as bExceptionRanges, L as sourceIdentityEvidence, Pn as bContainment, R as withSourceEvidence, Rn as bWordBounded, Ur as agentSourcePathSegment, Wr as agentSourceSchema, bi as staticCatalogRef, hi as approvedTreatmentSchema, jt as metadataProcessingVersion, mr as resolveSourceSelection, ot as classifyAgentSetup, pi as sourceChangePolicy, st as defaultAgentSetupInclusion, z as agentSetupKey } from "./src-BqtdFVq7.mjs";
1
+ import { $n as buildPlan, An as createDetectionSummary, Bn as cleanupImplementationVersion, C as createBAnalysisUnits, Cn as reviewRoles, Dn as bindInspection, En as createSessionPreparation, Gn as nativeField, Hn as nativeParserVersion, In as createReplacementKey, Jn as transformRecords, Kn as nativeItems, Ln as sessionNonce, Mn as walkNativeFields, N as bDuplicateShift, Rn as projectNativeRecord, Sn as mainReviewRole, Tn as renderNative, U as bDigest, Un as redactionImplementationVersion, Vn as entityDictionaryVersion, W as codePointLength, Xn as retainedMainTextNodes, Yn as frameRecords, Zn as validateProfile, ar as detectStatic, bn as processNativeRecord, br as processingSite, c as reviewDigest, cn as reviewFamilies, cr as jsonSpans, er as validatePlan, fn as sourceSnapshotId, gr as ProcessingError, hr as defaultDetectionLimits, in as safeCode, ir as resolveLimits, j as bBindingCap, lr as agentContextLocation, nn as ApplicationError, nr as defaultLimits, qn as nativeText, rr as recordPointerLimits, sn as familySelected, u as textDigest, un as sourceKey, ur as createEntityMatcher, vn as nativeSourceIdentitySchema, vr as fail$1, wn as createSentenceContext, xn as projectNativeReviewInput, xr as siteFields, yn as withMandatoryCustomTerms, yr as isProcessingCode, zn as parseNativeRecord } from "./locate-D-ZaHpI0.mjs";
2
+ import { t as createZstdFrameCheck } from "./frame-B3He21G8.mjs";
3
+ import { L as sourceIdentityEvidence, Mn as resolveSourceSelection, Ni as approvedTreatmentSchema, Qr as metadataProcessingVersion, R as withSourceEvidence, Ri as staticCatalogRef, ai as agentSourcePathSegment, ar as bWordBounded, ji as sourceChangePolicy, nr as bExceptionRanges, oi as agentSourceSchema, ot as classifyAgentSetup, st as defaultAgentSetupInclusion, tr as bContainment, z as agentSetupKey } from "./src-Do-qzuMn.mjs";
4
4
  import { constants } from "node:fs";
5
5
  import { link, lstat, mkdir, open, readFile, readdir, realpath, rm, rmdir, stat, unlink } from "node:fs/promises";
6
6
  import { execFile, fork, spawn } from "node:child_process";
@@ -11,7 +11,7 @@ import { Readable } from "node:stream";
11
11
  import { TextDecoder as TextDecoder$1, isDeepStrictEqual, promisify } from "node:util";
12
12
  import { createHash, createHmac, randomUUID } from "node:crypto";
13
13
  import { setImmediate } from "node:timers/promises";
14
- import { ERR_UNSUPPORTED_FORMAT, Reader, TextReader, ZipReader, ZipWriter, configure } from "@zip.js/zip.js/index-native.js";
14
+ import { ERR_UNSUPPORTED_FORMAT, Reader, TextReader, Uint8ArrayReader, ZipReader, ZipWriter, configure } from "@zip.js/zip.js/index-native.js";
15
15
  import "node:perf_hooks";
16
16
  import { availableParallelism, platform, tmpdir, totalmem } from "node:os";
17
17
  import { pipeline } from "node:stream/promises";
@@ -1874,11 +1874,11 @@ function description(value) {
1874
1874
  sha256
1875
1875
  };
1876
1876
  }
1877
- function checkWorkspaceManifest(text, entries, bundleId, expectedPathHash, summary) {
1878
- const manifest = record$1(strictJson(text, manifestLimitBytes, manifestNodeLimit));
1877
+ function checkWorkspaceManifest(source, entries, bundleId, expectedPathHash, summary) {
1878
+ const manifest = record$1(typeof source === "string" ? strictJson(source, manifestLimitBytes, manifestNodeLimit) : source);
1879
1879
  const treatment = manifest["contentTreatment"];
1880
1880
  const configured = treatment === "configured";
1881
- const configuredManifest = configured ? parseConfiguredManifest(text) : null;
1881
+ const configuredManifest = typeof source !== "string" ? source : configured ? parseConfiguredManifest(source) : null;
1882
1882
  if (configuredManifest) validateConfiguredManifest(configuredManifest);
1883
1883
  const sourceWorkspaces = configuredManifest?.sourceWorkspaces ?? [record$1(manifest["workspace"])];
1884
1884
  const workspaceIds = new Set(sourceWorkspaces.map((workspace) => string(workspace["id"])));
@@ -2443,7 +2443,7 @@ function parseAuditRow(value, sourceId, sourceSha256, ordinal) {
2443
2443
  diagnostics
2444
2444
  };
2445
2445
  }
2446
- const location$1 = (pointer, subject) => `${subject}:${pointer}`;
2446
+ const location$2 = (pointer, subject) => `${subject}:${pointer}`;
2447
2447
  const child = (pointer, key) => `${pointer}/${String(key).replaceAll("~", "~0").replaceAll("/", "~1")}`;
2448
2448
  function outputLocations(text, signal) {
2449
2449
  let root;
@@ -2462,7 +2462,7 @@ function outputLocations(text, signal) {
2462
2462
  let bytes = 0;
2463
2463
  function visit(node, pointer, subject) {
2464
2464
  checkAbort(signal);
2465
- const key = location$1(pointer, subject);
2465
+ const key = location$2(pointer, subject);
2466
2466
  bytes += Buffer.byteLength(key);
2467
2467
  if (bytes > maximumBytes) fail("ARTIFACT_INVALID_ARCHIVE");
2468
2468
  locations.set(key, node);
@@ -2491,7 +2491,7 @@ function verifyCompanion(row, outputText, signal) {
2491
2491
  if (!field.fieldId.startsWith(`${row.recordId}-f`) || match === null || Number(match[1]) >= maximumEntries || match[2] !== void 0 && Number(match[2]) >= maximumEntries || fields.has(field.fieldId)) fail("ARTIFACT_INVALID_ARCHIVE");
2492
2492
  if (match?.[2] === void 0 && match?.[3] === void 0) originals.add(Number(match?.[1]));
2493
2493
  if (field.pointer !== null) {
2494
- const key = location$1(field.pointer, field.subject);
2494
+ const key = location$2(field.pointer, field.subject);
2495
2495
  if (!locations.has(key) || referenced.has(key)) fail("ARTIFACT_INVALID_ARCHIVE");
2496
2496
  referenced.add(key);
2497
2497
  }
@@ -2505,7 +2505,7 @@ function verifyCompanion(row, outputText, signal) {
2505
2505
  if (marker === null) continue;
2506
2506
  const baseId = field.fieldId.replace(/-s\d+$|-k$/u, "");
2507
2507
  const base = fields.get(baseId);
2508
- if (!sampled.has(baseId) || base === void 0 || field.subject !== "value" || (base.pointer === null ? field.pointer !== null : field.pointer !== (marker[2] === "k" ? child(base.pointer, "skeleton") : child(child(base.pointer, "segments"), marker[1] ?? "")) || locations.get(location$1(field.pointer, field.subject))?.kind !== "string")) fail("ARTIFACT_INVALID_ARCHIVE");
2508
+ if (!sampled.has(baseId) || base === void 0 || field.subject !== "value" || (base.pointer === null ? field.pointer !== null : field.pointer !== (marker[2] === "k" ? child(base.pointer, "skeleton") : child(child(base.pointer, "segments"), marker[1] ?? "")) || locations.get(location$2(field.pointer, field.subject))?.kind !== "string")) fail("ARTIFACT_INVALID_ARCHIVE");
2509
2509
  }
2510
2510
  const synthetic = sampleLocations(row.bodies, fields, locations);
2511
2511
  for (const key of locations.keys()) if (!referenced.has(key) && !synthetic.has(key)) fail("ARTIFACT_INVALID_ARCHIVE");
@@ -2643,37 +2643,31 @@ async function verifyConfiguredPart(part, entries, descriptions, signal) {
2643
2643
  //#endregion
2644
2644
  //#region packages/artifact/src/read/configured/workspace.ts
2645
2645
  /** Public primary facts are parsed independently; no source file is opened. */
2646
- function workspaceSummary(text) {
2647
- const manifest = record$1(parseConfiguredManifest(text));
2648
- if (manifest["contentTreatment"] !== "configured" || manifest["formatVersion"] !== 5 || manifest["companionVersion"] !== 3) return fail("ARTIFACT_INVALID_MANIFEST");
2646
+ function workspaceSummary(input) {
2647
+ const manifest = typeof input === "string" ? parseConfiguredManifest(input) : input;
2649
2648
  return {
2650
2649
  format: "sess-pilot-workspace-summary",
2651
2650
  formatVersion: 1,
2652
- bundleId: string(manifest["bundleId"]),
2653
- counts: parseCounts(manifest["counts"]),
2654
- sessions: array(manifest["sessions"], (value) => {
2655
- const session = record$1(value);
2656
- const harness = session["harness"];
2657
- if (harness !== "claude" && harness !== "codex") return fail("ARTIFACT_INVALID_MANIFEST");
2658
- return {
2659
- sessionId: string(session["id"]),
2660
- scopeOrdinal: 0,
2661
- harness,
2662
- nativeSessionId: nullableString(session["sourceSessionId"]),
2663
- treatmentId: string(session["treatmentId"]),
2664
- sources: array(session["parts"], parseConfiguredPart).map((part, sourceOrdinal) => ({
2665
- sourceId: part.sourceId,
2666
- sourceOrdinal,
2667
- native: part.native
2668
- }))
2669
- };
2670
- })
2651
+ bundleId: manifest.bundleId,
2652
+ counts: manifest.counts,
2653
+ sessions: manifest.sessions.map((session) => ({
2654
+ sessionId: session.id,
2655
+ scopeOrdinal: 0,
2656
+ harness: session.harness,
2657
+ nativeSessionId: session.sourceSessionId,
2658
+ treatmentId: session.treatmentId,
2659
+ sources: session.parts.map((part, sourceOrdinal) => ({
2660
+ sourceId: part.sourceId,
2661
+ sourceOrdinal,
2662
+ native: part.native
2663
+ }))
2664
+ }))
2671
2665
  };
2672
2666
  }
2673
2667
  /** Validate exact primary coverage and metadata before either native-data consumer runs. */
2674
2668
  async function readPrimaryMetadata(primaryEntries, primaryText, signal, only) {
2675
- const summary = workspaceSummary(primaryText);
2676
2669
  const manifest = parseConfiguredManifest(primaryText);
2670
+ const summary = workspaceSummary(manifest);
2677
2671
  checkWorkspaceManifest(primaryText, primaryEntries, summary.bundleId, manifest.sourceWorkspaces.length === 1 ? manifest.sourceWorkspaces[0]?.pathHash ?? null : null, summary);
2678
2672
  for (const description of manifest.entries) {
2679
2673
  checkAbort(signal);
@@ -3544,7 +3538,9 @@ function unavailableContribution(kind, id, workspaceId, status, reason) {
3544
3538
  function reportInspectionFailure(observer, stage, error) {
3545
3539
  try {
3546
3540
  if (!observer) {
3547
- process.stderr.write(`Inspection processing failed: ${safeCode(error)} (${stage})\n`);
3541
+ const named = processingSite(error);
3542
+ const fields = named ? ` site=${named.site}` + (named.harness ? ` harness=${named.harness}` : "") + (named.harnessVersion ? ` version=${named.harnessVersion}` : "") : "";
3543
+ process.stderr.write(`Inspection processing failed: ${safeCode(error)} (${stage})${fields}\n`);
3548
3544
  return;
3549
3545
  }
3550
3546
  observer(stage, error);
@@ -4004,11 +4000,14 @@ function configuredSelection(selection, treatment) {
4004
4000
  mode: { kind: "remove" },
4005
4001
  replacement: edit.retainAs
4006
4002
  };
4007
- const { replacement: _replacement, ...original } = edit;
4003
+ if (mode.kind !== "retain") return {
4004
+ ...edit,
4005
+ mode
4006
+ };
4007
+ const { replacement: _replacement, replacementSourceRanges: _source, replacementTargetRanges: _target, ...original } = edit;
4008
4008
  return {
4009
4009
  ...original,
4010
- mode,
4011
- ...mode.kind !== "retain" && edit.replacement !== void 0 ? { replacement: edit.replacement } : {}
4010
+ mode
4012
4011
  };
4013
4012
  }),
4014
4013
  diagnostics: selection.diagnostics,
@@ -5583,17 +5582,20 @@ function matchFrozenOutput(input, checked) {
5583
5582
  if (input.sha256 !== checked.sha256 || input.archiveBytes !== checked.archiveBytes) fail("ARTIFACT_PROCESSING_MISMATCH");
5584
5583
  }
5585
5584
  async function checkFrozenOutput(input, signal) {
5586
- let manifestText = "";
5585
+ let verified;
5587
5586
  const checked = await checkWrittenArchive(input.path, input.identity, void 0, (text, entries) => {
5588
5587
  const manifest = parseConfiguredManifest(text);
5589
- checkWorkspaceManifest(text, entries, manifest.bundleId, manifest.sourceWorkspaces.length === 1 ? manifest.sourceWorkspaces[0]?.pathHash ?? null : null, workspaceSummary(text));
5590
- manifestText = text;
5588
+ checkWorkspaceManifest(manifest, entries, manifest.bundleId, manifest.sourceWorkspaces.length === 1 ? manifest.sourceWorkspaces[0]?.pathHash ?? null : null, workspaceSummary(manifest));
5589
+ verified = {
5590
+ manifestText: text,
5591
+ manifest
5592
+ };
5591
5593
  }, signal);
5592
5594
  matchFrozenOutput(input, checked);
5595
+ if (!verified) return fail("ARTIFACT_INVALID_MANIFEST");
5593
5596
  return {
5594
5597
  checked,
5595
- manifestText,
5596
- manifest: parseConfiguredManifest(manifestText)
5598
+ ...verified
5597
5599
  };
5598
5600
  }
5599
5601
  /** Hold the exact verified descriptor; every entry is separately hashed before use. */
@@ -7289,6 +7291,24 @@ function stringOffsets(root, changes) {
7289
7291
  return offsets;
7290
7292
  }
7291
7293
  const encodedLength = (text) => JSON.stringify(text).length - 2;
7294
+ /** Absolute JSON string-content coordinates. Fixed-size checkpoints bound both the work
7295
+ * per lookup and retained memory, including out-of-order overlapping contributor ranges. */
7296
+ function encodedOffset(text, base) {
7297
+ const stride = 1024;
7298
+ const offsets = [base];
7299
+ const boundary = (block) => {
7300
+ const at = block * stride;
7301
+ return scalarBoundary(text, at) ? at : at - 1;
7302
+ };
7303
+ return (position) => {
7304
+ const block = Math.floor(position / stride);
7305
+ while (offsets.length <= block) {
7306
+ const next = offsets.length;
7307
+ offsets.push((offsets[next - 1] ?? fail("ARTIFACT_PROCESSING_MISMATCH")) + encodedLength(text.slice(boundary(next - 1), boundary(next))));
7308
+ }
7309
+ return (offsets[block] ?? fail("ARTIFACT_PROCESSING_MISMATCH")) + encodedLength(text.slice(boundary(block), position));
7310
+ };
7311
+ }
7292
7312
  /** Restore verified untouched scalar lexemes without round-tripping through JS numbers. */
7293
7313
  function restoreLiterals(root, literals) {
7294
7314
  const raw = literals.get(root.id);
@@ -7362,37 +7382,42 @@ function renderReviewRow(row, before, edits, markers, signal) {
7362
7382
  const changed = inner ? renderNative(inner, innerChanges, reviewLimits, signal).text : pieces[0]?.changed ?? fail("ARTIFACT_PROCESSING_MISMATCH");
7363
7383
  const sourceOffsets = inner ? stringOffsets(inner, /* @__PURE__ */ new Map()) : void 0, outputOffsets = inner ? stringOffsets(inner, innerChanges) : void 0;
7364
7384
  const inputSha256 = hash$4(sourceText), outputSha256 = hash$4(changed), context = createSentenceContext(sourceText);
7365
- for (const piece of pieces) for (const item of piece.items) {
7366
- const coordinates = (range) => sourceOffsets ? {
7367
- start: (sourceOffsets.get(piece.node) ?? fail("ARTIFACT_PROCESSING_MISMATCH")) + encodedLength(piece.source.slice(0, range.start)),
7368
- end: (sourceOffsets.get(piece.node) ?? fail("ARTIFACT_PROCESSING_MISMATCH")) + encodedLength(piece.source.slice(0, range.end))
7385
+ for (const piece of pieces) {
7386
+ if (!piece.items.length) continue;
7387
+ const inputOffset = sourceOffsets && encodedOffset(piece.source, sourceOffsets.get(piece.node) ?? fail("ARTIFACT_PROCESSING_MISMATCH"));
7388
+ const outputOffset = outputOffsets && encodedOffset(piece.changed, outputOffsets.get(piece.node) ?? fail("ARTIFACT_PROCESSING_MISMATCH"));
7389
+ const coordinates = (range) => inputOffset ? {
7390
+ start: inputOffset(range.start),
7391
+ end: inputOffset(range.end)
7369
7392
  } : range;
7370
- const inputRange = coordinates(item.inputRange);
7371
- const start = outputOffsets ? (outputOffsets.get(piece.node) ?? fail("ARTIFACT_PROCESSING_MISMATCH")) + encodedLength(piece.changed.slice(0, item.outputRange.start)) : item.outputRange.start;
7372
- const { span, ...applied } = item;
7373
- const transcript = {
7374
- ...applied,
7375
- pointer,
7376
- inputSha256,
7377
- outputSha256,
7378
- inputRange,
7379
- outputRange: {
7380
- start,
7381
- end: start + item.replacement.length
7382
- },
7383
- context: context(inputRange)
7384
- };
7385
- transcripts.push({
7386
- ...transcript,
7387
- contributors: reconstructedContributors({
7388
- row,
7389
- field: piece.field,
7390
- span,
7391
- transcript,
7392
- coordinates,
7393
- context
7394
- })
7395
- });
7393
+ for (const item of piece.items) {
7394
+ const inputRange = coordinates(item.inputRange);
7395
+ const start = outputOffset ? outputOffset(item.outputRange.start) : item.outputRange.start;
7396
+ const { span, ...applied } = item;
7397
+ const transcript = {
7398
+ ...applied,
7399
+ pointer,
7400
+ inputSha256,
7401
+ outputSha256,
7402
+ inputRange,
7403
+ outputRange: {
7404
+ start,
7405
+ end: start + item.replacement.length
7406
+ },
7407
+ context: context(inputRange)
7408
+ };
7409
+ transcripts.push({
7410
+ ...transcript,
7411
+ contributors: reconstructedContributors({
7412
+ row,
7413
+ field: piece.field,
7414
+ span,
7415
+ transcript,
7416
+ coordinates,
7417
+ context
7418
+ })
7419
+ });
7420
+ }
7396
7421
  }
7397
7422
  if (nativeContainer && changed === sourceText) {
7398
7423
  if (nativeContainerText(target, signal) !== sourceText) fail("ARTIFACT_PROCESSING_MISMATCH");
@@ -7508,10 +7533,12 @@ function indexFamilyHides(manifest, hides = []) {
7508
7533
  if (!family) {
7509
7534
  const categories = /* @__PURE__ */ new Map();
7510
7535
  const bounded = /* @__PURE__ */ new Set();
7511
- for (const { term, category, bounded: whole } of hide.terms) {
7536
+ const toolResultEscapes = /* @__PURE__ */ new Set();
7537
+ for (const { term, category, bounded: whole, toolResultEscapes: escaped } of hide.terms) {
7512
7538
  if (categories.has(term)) mismatch("duplicate-term");
7513
7539
  categories.set(term, maskCategory(category));
7514
7540
  if (whole) bounded.add(term);
7541
+ if (escaped) toolResultEscapes.add(term);
7515
7542
  }
7516
7543
  family = {
7517
7544
  matcher: createEntityMatcher([...categories.keys()].map((value) => ({
@@ -7520,6 +7547,7 @@ function indexFamilyHides(manifest, hides = []) {
7520
7547
  }))),
7521
7548
  categories,
7522
7549
  bounded,
7550
+ toolResultEscapes,
7523
7551
  excepted: bExceptionRanges(hide.exceptions ?? [])
7524
7552
  };
7525
7553
  shared.set(key, family);
@@ -7530,7 +7558,7 @@ function indexFamilyHides(manifest, hides = []) {
7530
7558
  return parts;
7531
7559
  }
7532
7560
  /** Disjoint literal hits outside existing markers; overlaps join under the highest category. */
7533
- function familySpans(text, family, signal) {
7561
+ function familySpans(text, family, signal, toolResult) {
7534
7562
  const markers = [...text.matchAll(markerPattern)].map((match) => ({
7535
7563
  start: match.index,
7536
7564
  end: match.index + match[0].length
@@ -7546,7 +7574,7 @@ function familySpans(text, family, signal) {
7546
7574
  }
7547
7575
  return (markers[low]?.start ?? Infinity) < range.end;
7548
7576
  };
7549
- const hits = family.matcher.find(text, signal, 2e6).filter(({ range, entity }) => !marked(range) && (!family.bounded.has(entity.value) || bWordBounded(text, range.start, range.end)) && !excepted(range)).map(({ range, entity }) => ({
7577
+ const hits = family.matcher.find(text, signal, 2e6).filter(({ range, entity }) => !marked(range) && (!family.bounded.has(entity.value) || bWordBounded(text, range.start, range.end, toolResult && family.toolResultEscapes.has(entity.value))) && !excepted(range)).map(({ range, entity }) => ({
7550
7578
  ...range,
7551
7579
  category: family.categories.get(entity.value) ?? mismatch("unknown-term")
7552
7580
  })).sort((left, right) => left.start - right.start || right.end - left.end);
@@ -7620,8 +7648,10 @@ function maskFamilyFields(text, root, annotations, family, markers, signal, onAp
7620
7648
  if (skip(field)) continue;
7621
7649
  if (field.text.includes(markers.prefix)) mismatch("marker-prefix");
7622
7650
  if (field.subject !== "value" || field.scalarKind !== "string" || field.field.protection || !bodies.has(field.nodeId) && structural(field.field.name)) continue;
7623
- const raw = familySpans(field.text, family, signal);
7624
- const carrier = raw.length || field.text.includes("\\") ? familyCarrierSpans(field, (value) => familySpans(value, family, signal), signal) : void 0;
7651
+ const toolResult = field.origin.carrier === "tool-result";
7652
+ const find = (value) => familySpans(value, family, signal, toolResult);
7653
+ const raw = find(field.text);
7654
+ const carrier = raw.length || field.text.includes("\\") ? familyCarrierSpans(field, find, signal) : void 0;
7625
7655
  const spans = (carrier ?? raw).sort((left, right) => left.start - right.start);
7626
7656
  if (!spans.length) continue;
7627
7657
  const changed = maskOutputField({
@@ -9618,7 +9648,14 @@ function isWorkerMessage(value) {
9618
9648
  if (kind === "spool") return typeof path === "string" && path.length > 0;
9619
9649
  if (kind === "result") return isResult(Reflect.get(value, "result"));
9620
9650
  if (kind === "worker-error") return code === "ARTIFACT_WORKER_MEMORY" || code === "ARTIFACT_PROCESSING_FAILED";
9621
- return kind === "error" && typeof code === "string" && code.length > 0 && (sourceId === void 0 || typeof sourceId === "string");
9651
+ return kind === "error" && typeof code === "string" && code.length > 0 && (sourceId === void 0 || typeof sourceId === "string") && [
9652
+ "site",
9653
+ "harness",
9654
+ "harnessVersion"
9655
+ ].every((key) => {
9656
+ const field = Reflect.get(value, key);
9657
+ return field === void 0 || typeof field === "string";
9658
+ });
9622
9659
  }
9623
9660
  /** How long a stopped controller may take to end its Worker and flush its messages (ADR 0219). */
9624
9661
  const stopGraceMs = 2e3;
@@ -9699,13 +9736,18 @@ function createSessionProcess(workerUrl, heapMb, onMessage, onFailure) {
9699
9736
  }
9700
9737
  //#endregion
9701
9738
  //#region packages/artifact/src/configured/parallel/pool.ts
9702
- /** Failure code plus the frozen source id that produced it, when known. */
9739
+ /** Failure code plus the frozen source id and the named refusal site (#59), when known. */
9703
9740
  var SessionWorkerError = class extends Error {
9704
9741
  sourceId;
9742
+ site;
9743
+ harness;
9744
+ harnessVersion;
9705
9745
  constructor(code, sourceId, options) {
9706
9746
  super(code, options);
9707
9747
  this.name = "SessionWorkerError";
9708
9748
  if (sourceId !== void 0) this.sourceId = sourceId;
9749
+ const named = siteFields(options);
9750
+ if (named) Object.assign(this, named);
9709
9751
  }
9710
9752
  };
9711
9753
  /**
@@ -9827,7 +9869,16 @@ function createSessionWorkerPool(url, size, heapMb = workerHeapMb) {
9827
9869
  stopping = Promise.all(slots.map(async (slot) => {
9828
9870
  try {
9829
9871
  await slot.process.close();
9830
- if (slot.task) await removeStoppedSpools(slot.task.spoolPaths);
9872
+ if (slot.task) {
9873
+ if (requestKind(slot.task) === "journey-base") {
9874
+ await removeNamedTemporarySpools(slot.task.spoolPaths);
9875
+ for (const path of slot.task.spoolPaths) try {
9876
+ await unlink(path);
9877
+ } catch (error) {
9878
+ if (filesystemCode(error) !== "ENOENT") throw error;
9879
+ }
9880
+ } else await removeStoppedSpools(slot.task.spoolPaths);
9881
+ }
9831
9882
  } finally {
9832
9883
  slot.task?.reject(blame(slot));
9833
9884
  slot.task = void 0;
@@ -9868,6 +9919,10 @@ function createSessionWorkerPool(url, size, heapMb = workerHeapMb) {
9868
9919
  }
9869
9920
  task.spoolPaths.add(message.path);
9870
9921
  task.onSpool?.(message.path);
9922
+ if (!closed) slot.process.send({
9923
+ kind: "spool-owned",
9924
+ path: message.path
9925
+ });
9871
9926
  } else if (message.kind === "result") {
9872
9927
  const requestedKind = requestKind(task);
9873
9928
  if ((requestedKind === "render" || requestedKind === "capture" || requestedKind === "scan" || requestedKind === "journey-output" || requestedKind === "journey-output-shard" || requestedKind === "journey-output-verify" || requestedKind === "journey-base") && message.result.kind !== requestedKind) {
@@ -9912,7 +9967,7 @@ function createSessionWorkerPool(url, size, heapMb = workerHeapMb) {
9912
9967
  return;
9913
9968
  }
9914
9969
  settle(slot, void 0, message.result);
9915
- } else settle(slot, new SessionWorkerError(message.code, message.sourceId));
9970
+ } else settle(slot, new SessionWorkerError(message.code, message.sourceId, siteFields(message)));
9916
9971
  } catch {
9917
9972
  failPool(/* @__PURE__ */ new Error("ARTIFACT_PROCESSING_FAILED"), slot);
9918
9973
  }
@@ -10169,7 +10224,7 @@ function selectConfiguredApproval(approval, admission, configuration = configure
10169
10224
  //#region packages/artifact/src/collection/producer/versions.ts
10170
10225
  /** Only configured output consumes these dependencies; hash them with actual version facts. */
10171
10226
  const configuredProcessingSemantics = Object.freeze({
10172
- catalog: "11",
10227
+ catalog: "12",
10173
10228
  parser: nativeParserVersion,
10174
10229
  dictionary: entityDictionaryVersion,
10175
10230
  metadata: metadataProcessingVersion,
@@ -12855,32 +12910,39 @@ async function writeOriginalWorkspace(production, workspaceId, bundleId, identit
12855
12910
  }
12856
12911
  //#endregion
12857
12912
  //#region packages/artifact/src/configured/admission/lifecycle.ts
12858
- function lifecycleRecord(text, lifecycle) {
12913
+ function parsed(text) {
12859
12914
  try {
12860
- return lifecycle.record(JSON.parse(text));
12915
+ return JSON.parse(text);
12861
12916
  } catch {
12862
- return false;
12917
+ return;
12863
12918
  }
12864
12919
  }
12865
12920
  /**
12866
- * Reads the whole snapshot one bounded record at a time. Returns only when every record is an
12867
- * exact lifecycle envelope; anything else, including an empty or oversized record, fails closed.
12921
+ * Reads the whole snapshot one bounded record at a time. Returns only when every record is a
12922
+ * lifecycle record and either one names an agent run or all match the exact journal schema
12923
+ * (ADR 0279). A launched-only file at the exact journal path is excluded when every record
12924
+ * matches that schema. Empty files, other records and oversized records fail closed.
12868
12925
  */
12869
12926
  async function confirmLifecycleSource(part, lifecycle, signal, overrides, open = openConfiguredSource) {
12870
12927
  const input = await open(part, signal);
12871
12928
  const cleanup = createCleanup();
12872
12929
  try {
12930
+ let agentRecords = 0;
12873
12931
  let records = 0;
12932
+ let exactOnly = true;
12874
12933
  try {
12875
12934
  for await (const text of frameRecords(input.chunks, "jsonl", resolveLimits(overrides).maxRecordBytes, signal)) {
12876
- if (!lifecycleRecord(text, lifecycle)) fail("ARTIFACT_UNRECOGNIZED_JOURNAL");
12935
+ const value = parsed(text);
12936
+ if (!lifecycle.record(value)) fail("ARTIFACT_UNRECOGNIZED_JOURNAL");
12937
+ if (lifecycle.agentRecord(value)) agentRecords++;
12877
12938
  records++;
12939
+ if (!lifecycle.exactRecord(value)) exactOnly = false;
12878
12940
  }
12879
12941
  } catch (error) {
12880
12942
  if (error instanceof ProcessingError && (error.code === "PROCESSING_LIMIT" || error.code === "PROCESSING_INVALID_RECORD")) fail("ARTIFACT_UNRECOGNIZED_JOURNAL", { cause: error });
12881
12943
  throw error;
12882
12944
  }
12883
- if (records === 0) fail("ARTIFACT_UNRECOGNIZED_JOURNAL");
12945
+ if (records === 0 || agentRecords === 0 && !exactOnly) fail("ARTIFACT_UNRECOGNIZED_JOURNAL");
12884
12946
  await input.finish();
12885
12947
  } catch (error) {
12886
12948
  cleanup.failed(error);
@@ -15449,7 +15511,7 @@ async function sessionFileFacts(file, size, signal) {
15449
15511
  /** Verify bounded final redacted bytes before starting a second ZIP codec. */
15450
15512
  async function sessionPart(entry, expected, signal) {
15451
15513
  if (expected.byteLength > 268435456 || entry.uncompressedSize !== expected.byteLength) fail("ARTIFACT_PART_LIMIT");
15452
- const file = await sessionFile();
15514
+ const scratch = expected.byteLength <= 65536 ? { bytes: new Uint8Array(expected.byteLength) } : { file: await sessionFile() };
15453
15515
  let size = 0;
15454
15516
  const digest = createHash("sha256");
15455
15517
  let crc = 0;
@@ -15459,11 +15521,14 @@ async function sessionPart(entry, expected, signal) {
15459
15521
  if (size + bytes.byteLength > expected.byteLength) fail("ARTIFACT_PART_LIMIT");
15460
15522
  digest.update(bytes);
15461
15523
  crc = crc32(bytes, crc);
15462
- let offset = 0;
15463
- while (offset < bytes.byteLength) {
15464
- const result = await file.write(bytes, offset, bytes.byteLength - offset, size + offset);
15465
- if (!result.bytesWritten) fail("ARTIFACT_IO_FAILED");
15466
- offset += result.bytesWritten;
15524
+ if (scratch.bytes) scratch.bytes.set(bytes, size);
15525
+ else {
15526
+ let offset = 0;
15527
+ while (offset < bytes.byteLength) {
15528
+ const { bytesWritten } = await scratch.file.write(bytes, offset, bytes.byteLength - offset, size + offset);
15529
+ if (!bytesWritten) fail("ARTIFACT_IO_FAILED");
15530
+ offset += bytesWritten;
15531
+ }
15467
15532
  }
15468
15533
  size += bytes.byteLength;
15469
15534
  } }), {
@@ -15471,55 +15536,93 @@ async function sessionPart(entry, expected, signal) {
15471
15536
  checkSignature: true
15472
15537
  });
15473
15538
  if (size !== expected.byteLength || digest.digest("hex") !== expected.sha256) fail("ARTIFACT_INVALID_ARCHIVE");
15539
+ const reader = scratch.bytes ? new Uint8ArrayReader(scratch.bytes) : new FileReader(scratch.file, size, 262144, true, signal);
15474
15540
  return {
15475
- file,
15541
+ file: scratch.file,
15542
+ reader,
15476
15543
  crc32: crc
15477
15544
  };
15478
15545
  } catch (error) {
15479
15546
  const cleanup = createCleanup();
15480
15547
  cleanup.failed(error);
15481
- await cleanup.run(() => file.close());
15548
+ const { file } = scratch;
15549
+ if (file) await cleanup.run(() => file.close());
15482
15550
  throw error;
15483
15551
  }
15484
15552
  }
15485
15553
  //#endregion
15486
15554
  //#region packages/artifact/src/configured/output/sessions.ts
15487
- /** Each yielded spool stays open until the caller advances or closes this iterator. */
15488
- async function* configuredSessionUploads(input, identities, signal) {
15555
+ async function* configuredSessionUploads(input, identities, signal, mode = "upload", omitted = /* @__PURE__ */ new Set(), checkMinimumBytes) {
15489
15556
  const verified = await checkFrozenOutput(input, signal);
15490
15557
  const archive = await openCheckedOutput(input, verified.checked, signal);
15491
15558
  const cleanup = createCleanup();
15492
15559
  try {
15493
15560
  if (archive.manifestText !== verified.manifestText) fail("ARTIFACT_PROCESSING_MISMATCH");
15494
15561
  const descriptions = new Map(verified.manifest.entries.map((entry) => [entry.entryPath, entry]));
15562
+ const byId = new Map(identities.map((identity) => [identity.archiveSessionId, identity]));
15563
+ if (byId.size !== identities.length) fail("ARTIFACT_IDENTITY_MISMATCH");
15564
+ if (checkMinimumBytes) {
15565
+ const measured = /* @__PURE__ */ new Set();
15566
+ let bytes = 0;
15567
+ for (const session of verified.manifest.sessions) {
15568
+ if (omitted.has(session.id)) continue;
15569
+ if (!byId.has(session.id)) fail("ARTIFACT_IDENTITY_MISMATCH");
15570
+ for (const part of session.parts) {
15571
+ const entry = descriptions.get(part.dataPath) ?? fail("ARTIFACT_INVALID_ARCHIVE");
15572
+ if (measured.has(entry.sha256)) continue;
15573
+ measured.add(entry.sha256);
15574
+ bytes += entry.byteLength;
15575
+ }
15576
+ }
15577
+ checkMinimumBytes(bytes);
15578
+ }
15579
+ const workspaces = new Map(verified.manifest.sourceWorkspaces.map((workspace) => [workspace.id, workspace]));
15580
+ const workspaceFacts = /* @__PURE__ */ new Map();
15495
15581
  for (const session of verified.manifest.sessions) {
15496
15582
  signal.throwIfAborted();
15497
- const identity = identities.find((item) => item.archiveSessionId === session.id) ?? fail("ARTIFACT_IDENTITY_MISMATCH");
15498
- const workspace = verified.manifest.sourceWorkspaces.find((item) => item.id === session.workspaceId) ?? fail("ARTIFACT_INVALID_MANIFEST");
15499
- const entry = archive.entries.get(workspace.metadataPath) ?? fail("ARTIFACT_INVALID_ARCHIVE");
15500
- const description = descriptions.get(workspace.metadataPath) ?? fail("ARTIFACT_INVALID_ARCHIVE");
15501
- const text = await readMetadata(entry, signal);
15502
- if (Buffer.byteLength(text) !== description.byteLength || createHash("sha256").update(text).digest("hex") !== description.sha256) fail("ARTIFACT_INVALID_ARCHIVE");
15503
- const { version: _, ...facts } = validateConfiguredSourceMetadata(strictJson(text, metadataLimitBytes), workspace);
15583
+ if (omitted.has(session.id)) continue;
15584
+ const identity = byId.get(session.id) ?? fail("ARTIFACT_IDENTITY_MISMATCH");
15585
+ const workspace = workspaces.get(session.workspaceId) ?? fail("ARTIFACT_INVALID_MANIFEST");
15586
+ let facts = workspaceFacts.get(workspace.id);
15587
+ if (!facts) {
15588
+ const entry = archive.entries.get(workspace.metadataPath) ?? fail("ARTIFACT_INVALID_ARCHIVE");
15589
+ const description = descriptions.get(workspace.metadataPath) ?? fail("ARTIFACT_INVALID_ARCHIVE");
15590
+ const text = await readMetadata(entry, signal);
15591
+ if (Buffer.byteLength(text) !== description.byteLength || createHash("sha256").update(text).digest("hex") !== description.sha256) fail("ARTIFACT_INVALID_ARCHIVE");
15592
+ const { version: _, ...validated } = validateConfiguredSourceMetadata(strictJson(text, metadataLimitBytes), workspace);
15593
+ facts = validated;
15594
+ workspaceFacts.set(workspace.id, facts);
15595
+ }
15504
15596
  const native = session.parts[0]?.native;
15505
15597
  const nativeSessionId = native?.sessionId ?? session.sourceSessionId;
15506
15598
  if (!nativeSessionId?.trim() && !identity.relativePath) fail("ARTIFACT_IDENTITY_MISMATCH");
15507
15599
  const metadata = {
15508
- workspace: facts,
15600
+ workspace: {
15601
+ ...facts,
15602
+ remoteHashes: [...facts.remoteHashes]
15603
+ },
15509
15604
  sourceSessionId: nativeSessionId,
15510
15605
  harness: session.harness,
15511
15606
  lastAt: identity.lastAt,
15512
15607
  parts: []
15513
15608
  };
15514
- const file = await sessionFile();
15609
+ const file = mode === "upload" ? await sessionFile() : null;
15515
15610
  const sessionCleanup = createCleanup();
15516
15611
  try {
15517
15612
  let size = 0;
15518
- const sink = fileWriter(file, signal, (bytes) => {
15613
+ const limit = (bytes) => {
15519
15614
  if (bytes > 5 * 1024 ** 3) fail("ARTIFACT_ARCHIVE_LIMIT");
15520
15615
  size = bytes;
15521
- }, false);
15522
- const zip = new ZipWriter(sink.writable, {
15616
+ };
15617
+ const digest = createHash("sha256");
15618
+ let checksum = 0;
15619
+ const writable = file ? fileWriter(file, signal, limit, false).writable : new WritableStream({ write(bytes) {
15620
+ signal.throwIfAborted();
15621
+ limit(size + bytes.byteLength);
15622
+ digest.update(bytes);
15623
+ checksum = crc32(bytes, checksum);
15624
+ } });
15625
+ const zip = new ZipWriter(writable, {
15523
15626
  useWebWorkers: false,
15524
15627
  useCompressionStream: true,
15525
15628
  bufferedWrite: false,
@@ -15535,24 +15638,30 @@ async function* configuredSessionUploads(input, identities, signal) {
15535
15638
  const partCleanup = createCleanup();
15536
15639
  try {
15537
15640
  const path = `p${String(index + 1).padStart(6, "0")}.jsonl`;
15538
- await zip.add(path, new FileReader(prepared.file, expected.byteLength, 262144, true, signal), { signal });
15641
+ await zip.add(path, prepared.reader, { signal });
15539
15642
  metadata.parts.push({
15540
15643
  path,
15541
15644
  byteLength: expected.byteLength,
15542
15645
  sha256: expected.sha256,
15543
- crc32: prepared.crc32
15646
+ crc32: prepared.crc32,
15647
+ native: part.native
15544
15648
  });
15545
15649
  } catch (error) {
15546
15650
  partCleanup.failed(error);
15547
15651
  throw error;
15548
15652
  } finally {
15549
- await partCleanup.run(() => prepared.file.close());
15653
+ const { file } = prepared;
15654
+ if (file) await partCleanup.run(() => file.close());
15550
15655
  }
15551
15656
  }
15552
15657
  await zip.close();
15553
15658
  if (zip.warnings?.length) fail("ARTIFACT_INVALID_ARCHIVE");
15554
15659
  if (size > 5 * 1024 ** 3) fail("ARTIFACT_ARCHIVE_LIMIT");
15555
- const content = await sessionFileFacts(file, size, signal);
15660
+ const content = file ? await sessionFileFacts(file, size, signal) : {
15661
+ byteLength: size,
15662
+ sha256: digest.digest("hex"),
15663
+ crc32: checksum
15664
+ };
15556
15665
  await archive.fence();
15557
15666
  yield {
15558
15667
  ...content,
@@ -15562,13 +15671,13 @@ async function* configuredSessionUploads(input, identities, signal) {
15562
15671
  relativePath: identity.relativePath,
15563
15672
  harness: session.harness,
15564
15673
  lastAt: identity.lastAt,
15565
- stream: () => new FileReader(file, size, 262144, true, signal).createReadable()
15674
+ ...file ? { stream: () => new FileReader(file, size, 262144, true, signal).createReadable() } : {}
15566
15675
  };
15567
15676
  } catch (error) {
15568
15677
  sessionCleanup.failed(error);
15569
15678
  throw error;
15570
15679
  } finally {
15571
- await sessionCleanup.run(() => file.close());
15680
+ if (file) await sessionCleanup.run(() => file.close());
15572
15681
  }
15573
15682
  }
15574
15683
  } catch (error) {
@@ -16083,7 +16192,7 @@ async function scanPreparedSession(production, sessionId, directory, hooks, canc
16083
16192
  workspaceId: selected.workspace.id,
16084
16193
  sessionId,
16085
16194
  ...source ? { sourcePartId: source.source.id } : {}
16086
- }), async () => {
16195
+ }, void 0, error), async () => {
16087
16196
  if (result) await unlink(result.input.file.path);
16088
16197
  });
16089
16198
  throw classified;
@@ -16337,7 +16446,7 @@ const maxChunks = 8e4;
16337
16446
  function batchLoad(body) {
16338
16447
  return Math.max(body.chunks.length / maxChunks, (body.duplicates?.length ?? 0) / maxChunks, Buffer.byteLength(JSON.stringify(body)) / maxTransportBytes);
16339
16448
  }
16340
- function location(context, fieldId, part) {
16449
+ function location$1(context, fieldId, part) {
16341
16450
  const source = context.locations.get(fieldId);
16342
16451
  if (!source) throw new ApplicationError("CORRUPTED_STATE");
16343
16452
  const native = reviewSource(source);
@@ -16376,7 +16485,7 @@ function reviewBatchBody(context, unit, ordinal) {
16376
16485
  };
16377
16486
  const chunks = unit.fragments.map((part) => ({
16378
16487
  id: chunkId(part.fieldId, part),
16379
- ...location(context, part.fieldId, part),
16488
+ ...location$1(context, part.fieldId, part),
16380
16489
  core: part.core,
16381
16490
  offset: part.utf16Start,
16382
16491
  text: part.text,
@@ -16396,7 +16505,7 @@ function reviewBatchBody(context, unit, ordinal) {
16396
16505
  utf16Start: part.utf16Start + shift.utf16,
16397
16506
  utf16End: part.utf16End + shift.utf16
16398
16507
  };
16399
- const { displayMasks, ...own } = location(context, duplicate.fieldId, copy);
16508
+ const { displayMasks, ...own } = location$1(context, duplicate.fieldId, copy);
16400
16509
  const hash = fieldHash(duplicate.fieldId);
16401
16510
  return {
16402
16511
  id: chunkId(duplicate.fieldId, copy),
@@ -16807,24 +16916,36 @@ function buildWorkScanBatches(context, sessionId, fields, pieces) {
16807
16916
  /**
16808
16917
  * Roots whose complete frozen main capture names an automation launch. Discovery normally
16809
16918
  * keeps these out of classification; this catches a confirmed root it could not recognize.
16919
+ * A root whose capture the check cannot read fails like an admission refusal (issue #59), so
16920
+ * only that root leaves its Work (ADR 0188); an abort still escapes.
16810
16921
  */
16811
- async function automatedRoots(rows, families, request, signal) {
16922
+ async function automatedRoots(rows, families, request, signal, onFailure) {
16812
16923
  const roots = /* @__PURE__ */ new Set();
16813
16924
  for (const row of rows) {
16814
16925
  if (row.failure || families.owners.get(row.session.id)?.id !== row.session.id) continue;
16815
16926
  const adapter = request.processing.adapters[row.session.harness];
16816
16927
  for (const source of row.sources) {
16817
16928
  if (source.native.role !== "main") continue;
16818
- const opened = await openSourceCapture(request.captures.get(source.source.path) ?? fail("ARTIFACT_SOURCE_CHANGED"));
16819
- const cleanup = createCleanup();
16929
+ const capture = request.captures.get(source.source.path) ?? fail("ARTIFACT_SOURCE_CHANGED");
16930
+ let launch;
16820
16931
  try {
16821
- if (await capturedLaunch(source.source, opened, adapter, signal, request.processing.limits) === "automation") roots.add(row.session.id);
16932
+ const opened = await openSourceCapture(capture);
16933
+ const cleanup = createCleanup();
16934
+ try {
16935
+ launch = await capturedLaunch(source.source, opened, adapter, signal, request.processing.limits);
16936
+ } catch (error) {
16937
+ cleanup.failed(error);
16938
+ throw error;
16939
+ } finally {
16940
+ await cleanup.run(() => opened.close());
16941
+ }
16822
16942
  } catch (error) {
16823
- cleanup.failed(error);
16824
- throw error;
16825
- } finally {
16826
- await cleanup.run(() => opened.close());
16943
+ row.failure = inspectionFailure(error, signal);
16944
+ onFailure(row.session, row.failure, source.source.id, error);
16945
+ reportInspectionFailure(request.processing.onInspectionFailure, "inspection-admission", error);
16946
+ break;
16827
16947
  }
16948
+ if (launch === "automation") roots.add(row.session.id);
16828
16949
  }
16829
16950
  }
16830
16951
  return roots;
@@ -16860,15 +16981,16 @@ async function prepareSessionScans(request, signal) {
16860
16981
  });
16861
16982
  };
16862
16983
  const failures = [];
16984
+ const onFailure = (session, reason, sourcePartId, cause) => {
16985
+ failures.push({
16986
+ sessionId: session.id,
16987
+ reason,
16988
+ ...sourcePartId === void 0 ? {} : { sourcePartId },
16989
+ ...cause === void 0 ? {} : { cause }
16990
+ });
16991
+ };
16863
16992
  const rows = await admitInspection(request.inventory, request.processing, signal, {
16864
- onFailure(session, reason, sourcePartId, cause) {
16865
- failures.push({
16866
- sessionId: session.id,
16867
- reason,
16868
- ...sourcePartId === void 0 ? {} : { sourcePartId },
16869
- ...cause === void 0 ? {} : { cause }
16870
- });
16871
- },
16993
+ onFailure,
16872
16994
  async inspectIdentity(part, adapter, currentSignal, limits) {
16873
16995
  const opened = await openSourceCapture(request.captures.get(part.path) ?? fail("ARTIFACT_SOURCE_CHANGED"));
16874
16996
  const cleanup = createCleanup();
@@ -16883,7 +17005,7 @@ async function prepareSessionScans(request, signal) {
16883
17005
  },
16884
17006
  onExclusion: exclude
16885
17007
  });
16886
- const automated = await automatedRoots(rows, families, request, signal);
17008
+ const automated = await automatedRoots(rows, families, request, signal, onFailure);
16887
17009
  for (const row of rows) {
16888
17010
  const root = families.owners.get(row.session.id)?.id;
16889
17011
  if (row.failure || root === void 0 || !automated.has(root)) continue;
@@ -16974,4 +17096,277 @@ async function verifyPreparedSessionSources(prepared, input, signal) {
16974
17096
  }
16975
17097
  }
16976
17098
  //#endregion
16977
- export { createCleanup as $, renderJobDigest as A, parallelismLimits as B, readOriginalSearchFields as C, prepareCollectionProduction as D, checkReusableBundle as E, SessionWorkerError as F, processJourneyMetadataFields as G, privateJourneyDirectory as H, sessionWorkerFailure as I, listAgentSetup as J, staticMaskCategory as K, privateCollectionDirectory as L, readCollectionIndex as M, parseCollectionWorkspaceSummary as N, captureLogicalJourneySources as O, createSharedSessionPool as P, removeNamedTemporarySpools as Q, defaultParallelism as R, readPrivateReviewPayload as S, createCollectionArtifacts as T, readLogicalJourneyFinalMasks as U, writeLogicalJourneyOutput as V, readConfiguredOutputInfo as W, createInspectionProcessor as X, createConfiguredPreviewStream as Y, createTemporary as Z, processJourneyMetadata as _, scanReviewFields as a, windowsOwnerOnly as at, writeLogicalJourneyBase as b, readSessionScanRecords as c, verifyOutputShard as d, safeError as et, writeOutputShard as f, readCapturedOriginalRows as g, captureConfiguredSessionJob as h, buildWorkScanBatches as i, restrictToOwner as it, runConfiguredSessionJob as j, capturedJourneyScope as k, scanPreparedSession as l, openConfiguredUpload as m, verifyPreparedSessionSources as n, makePrivateDirectory as nt, createWorkPieces as o, isWindowsAclFailure as ot, configuredSessionUploads as p, readWorkspacePair as q, prepareSessionScans as r, openPrivateFile as rt, readSessionScanFields as s, windowsAclCodes as st, preparedScanConfiguration as t, exclusiveLock as tt, runConfiguredScanJob as u, readStaticSessionMasks as v, readConfiguredSearchFields as w, writePrivateReviewPayload as x, staticSessionJobs as y, gitSeedsProvider as z };
17099
+ //#region packages/artifact/src/configured/output/session-mask-equivalence.ts
17100
+ const exactMarker = new RegExp("^(?:" + replacementMarkerPattern.source + ")$", "u");
17101
+ function sessionMaskProof(row) {
17102
+ const lineage = row.contributors.map((item) => {
17103
+ const { inputRange, context } = item.kind === "static" ? item.source.mask : item.source;
17104
+ const quote = context.text.slice(inputRange.start - context.start, inputRange.end - context.start);
17105
+ const basis = item.kind === "static" ? [
17106
+ item.source.sourceRecordIndex,
17107
+ item.source.mask.originalPointer,
17108
+ item.source.mask.sourceRange,
17109
+ item.source.mask.inputSha256,
17110
+ item.source.mask.stepId,
17111
+ item.source.mask.node.id,
17112
+ item.source.mask.node.version,
17113
+ item.source.mask.ruleId
17114
+ ] : [item.source.pointer];
17115
+ return JSON.stringify([
17116
+ item.kind,
17117
+ item.category,
17118
+ basis,
17119
+ inputRange.start,
17120
+ inputRange.end,
17121
+ quote
17122
+ ]);
17123
+ }).sort();
17124
+ const first = row.contributors[0];
17125
+ return {
17126
+ pointer: row.pointer,
17127
+ subject: row.subject,
17128
+ start: row.outputRange.start,
17129
+ end: row.outputRange.end,
17130
+ replacement: row.replacement,
17131
+ lineage: createHash("sha256").update(JSON.stringify([row.category, lineage])).digest("hex"),
17132
+ mayRename: row.subject === "value" && exactMarker.test(row.replacement) && row.contributors.length === 1 && first?.kind === "static" && first.source.sourceRecordIndex !== null && first.source.mask.sourceRange !== null && first.source.mask.originalPointer !== null && first.source.mask.outputPointer === row.pointer && first.source.mask.subject === row.subject && first.source.mask.replacement === row.replacement
17133
+ };
17134
+ }
17135
+ const location = (mask) => JSON.stringify([
17136
+ mask.pointer,
17137
+ mask.subject,
17138
+ mask.start,
17139
+ mask.end
17140
+ ]);
17141
+ /** Both ledgers have already been independently joined to their own frozen output by the verifier. */
17142
+ function compareSessionRows(leftText, rightText, leftMasks, rightMasks) {
17143
+ if (leftMasks.length !== rightMasks.length) return null;
17144
+ const rightByLocation = new Map(rightMasks.map((mask) => [location(mask), mask]));
17145
+ if (rightByLocation.size !== rightMasks.length) return null;
17146
+ const changes = /* @__PURE__ */ new Map();
17147
+ const aliases = /* @__PURE__ */ new Map();
17148
+ const reverse = /* @__PURE__ */ new Map();
17149
+ for (const left of leftMasks) {
17150
+ const key = location(left);
17151
+ const right = rightByLocation.get(key);
17152
+ if (!right || left.lineage !== right.lineage) return null;
17153
+ rightByLocation.delete(key);
17154
+ if (left.replacement === right.replacement) continue;
17155
+ if (!left.mayRename || !right.mayRename || left.start < 0 || left.end - left.start !== left.replacement.length || right.replacement.length !== left.replacement.length) return null;
17156
+ const prior = aliases.get(left.replacement);
17157
+ const inverse = reverse.get(right.replacement);
17158
+ if (prior !== void 0 && prior !== right.replacement || inverse !== void 0 && inverse !== left.replacement) return null;
17159
+ aliases.set(left.replacement, right.replacement);
17160
+ reverse.set(right.replacement, left.replacement);
17161
+ const masks = changes.get(left.pointer) ?? [];
17162
+ masks.push(left);
17163
+ changes.set(left.pointer, masks);
17164
+ }
17165
+ if (!aliases.size) return leftText === rightText ? { aliases: [] } : null;
17166
+ const limits = {
17167
+ ...defaultLimits,
17168
+ maxRecordBytes: maximumRecordBytes
17169
+ };
17170
+ let tree;
17171
+ try {
17172
+ tree = parseNativeRecord(leftText, limits, new AbortController().signal);
17173
+ } catch {
17174
+ return null;
17175
+ }
17176
+ const changedCount = [...changes.values()].reduce((sum, field) => sum + field.length, 0);
17177
+ function authenticOccurrences(root, destination) {
17178
+ let used = 0;
17179
+ const markers = destination ? reverse : aliases;
17180
+ function check(node, pointer) {
17181
+ if (node.kind === "array") return node.items.every((item, i) => check(item, pointer + "/" + i));
17182
+ if (node.kind === "object") return node.properties.every(({ key, value }) => {
17183
+ for (const found of key.value.matchAll(replacementMarkerPattern)) if (markers.has(found[0])) return false;
17184
+ return check(value, pointer + "/" + key.value.replaceAll("~", "~0").replaceAll("/", "~1"));
17185
+ });
17186
+ if (node.kind !== "string") return true;
17187
+ const expected = new Map((changes.get(pointer) ?? []).map((mask) => [mask.start, mask]));
17188
+ for (const found of node.value.matchAll(replacementMarkerPattern)) {
17189
+ if (!markers.has(found[0])) continue;
17190
+ const mask = expected.get(found.index);
17191
+ if (!mask || (destination ? aliases.get(mask.replacement) : mask.replacement) !== found[0]) return false;
17192
+ expected.delete(found.index);
17193
+ used++;
17194
+ }
17195
+ return expected.size === 0;
17196
+ }
17197
+ return check(root, "") && used === changedCount;
17198
+ }
17199
+ if (!authenticOccurrences(tree, false)) return null;
17200
+ for (const winner of aliases.values()) if (aliases.has(winner)) return null;
17201
+ let replaced = 0;
17202
+ const renamed = leftText.replace(replacementMarkerPattern, (marker) => {
17203
+ const mapped = aliases.get(marker);
17204
+ if (!mapped) return marker;
17205
+ replaced++;
17206
+ return mapped;
17207
+ });
17208
+ if (changedCount !== replaced || renamed !== rightText) return null;
17209
+ try {
17210
+ if (!authenticOccurrences(parseNativeRecord(rightText, limits, new AbortController().signal), true)) return null;
17211
+ } catch {
17212
+ return null;
17213
+ }
17214
+ return { aliases: [...aliases] };
17215
+ }
17216
+ //#endregion
17217
+ //#region packages/artifact/src/configured/output/session-source-prefix.ts
17218
+ /**
17219
+ * Both parts come from the verified frozen primary. The caller locates longerSource through
17220
+ * its base source binding. A copied log may have a different path or inode from its ancestor.
17221
+ */
17222
+ async function sessionSourcePrefix(short, long, longerSource, signal) {
17223
+ checkAbort(signal);
17224
+ if (!short.native.sessionId?.trim() || !["main", "worker"].includes(short.native.role) || !isDeepStrictEqual(short.native, long.native) || short.source.representation !== long.source.representation || short.source.byteLength > long.source.byteLength || short.recordCount > long.recordCount || short.retainedRecordCount > long.retainedRecordCount) return false;
17225
+ if (short.source.byteLength === long.source.byteLength) return short.source.sha256 === long.source.sha256 && short.recordCount === long.recordCount;
17226
+ if (long.source.representation !== "jsonl" || !longerSource || longerSource.representation !== "jsonl" || longerSource.snapshot.size !== long.source.byteLength || short.source.byteLength === 0 || short.recordCount === long.recordCount) return false;
17227
+ try {
17228
+ checkNativeEvidence(longerSource, long.native);
17229
+ const input = await openConfiguredSource(longerSource, signal, void 0, "stable-prefix");
17230
+ try {
17231
+ const prefix = createHash("sha256");
17232
+ let remaining = short.source.byteLength;
17233
+ let endsAtRecord = false;
17234
+ for await (const chunk of input.chunks) {
17235
+ const take = Math.min(remaining, chunk.byteLength);
17236
+ if (take === 0) continue;
17237
+ prefix.update(chunk.subarray(0, take));
17238
+ remaining -= take;
17239
+ if (remaining === 0) endsAtRecord = chunk[take - 1] === 10;
17240
+ }
17241
+ const full = await input.finish();
17242
+ return remaining === 0 && endsAtRecord && prefix.digest("hex") === short.source.sha256 && full.sha256 === long.source.sha256 && full.byteLength === long.source.byteLength;
17243
+ } finally {
17244
+ await input.close();
17245
+ }
17246
+ } catch (error) {
17247
+ checkAbort(signal);
17248
+ if ([
17249
+ "ARTIFACT_SOURCE_CHANGED",
17250
+ "ARTIFACT_SOURCE_MISSING",
17251
+ "ARTIFACT_SOURCE_UNSAFE",
17252
+ "ARTIFACT_SOURCE_UNREADABLE",
17253
+ "ARTIFACT_SOURCE_TRUNCATED"
17254
+ ].includes(safeError(error).message)) return false;
17255
+ throw error;
17256
+ }
17257
+ }
17258
+ //#endregion
17259
+ //#region packages/artifact/src/configured/output/session-extension.ts
17260
+ /** Choose an entire already-approved variant. No edited or reconstructed bytes enter transport. */
17261
+ async function sessionExtensions(input, signal) {
17262
+ const verified = await checkFrozenOutput(input.primary, signal);
17263
+ const { manifest } = verified;
17264
+ const sessions = new Map(manifest.sessions.map((session) => [session.id, session]));
17265
+ const groups = input.groups.map((group) => group.map((id) => sessions.get(id) ?? fail("ARTIFACT_IDENTITY_MISMATCH")));
17266
+ const paths = new Set(groups.flat().flatMap((session) => session.parts.map((part) => part.dataPath)));
17267
+ const masks = /* @__PURE__ */ new Map();
17268
+ for await (const row of readLogicalJourneyFinalMasks({
17269
+ ledger: input.ledger,
17270
+ primary: input.primary
17271
+ }, signal, paths)) {
17272
+ const entry = masks.get(row.entryPath) ?? /* @__PURE__ */ new Map();
17273
+ if (!masks.has(row.entryPath)) masks.set(row.entryPath, entry);
17274
+ const list = entry.get(row.recordIndex) ?? [];
17275
+ list.push(sessionMaskProof(row));
17276
+ entry.set(row.recordIndex, list);
17277
+ }
17278
+ const archive = await openCheckedOutput(input.primary, verified.checked, signal);
17279
+ const omitted = /* @__PURE__ */ new Set();
17280
+ const aliases = /* @__PURE__ */ new Map();
17281
+ try {
17282
+ for (const group of groups) {
17283
+ const score = (s) => s.parts.reduce((sum, p) => sum + p.retainedRecordCount, 0);
17284
+ const sorted = group.toSorted((a, b) => score(b) - score(a) || Date.parse(input.lastAt(b.id)) - Date.parse(input.lastAt(a.id)) || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
17285
+ const winner = sorted[0];
17286
+ if (!winner) continue;
17287
+ for (const shorter of sorted.slice(1)) {
17288
+ if (shorter.workspaceId !== winner.workspaceId || shorter.harness !== winner.harness || shorter.treatmentId !== winner.treatmentId || shorter.sourceSessionId !== winner.sourceSessionId || shorter.parts.length !== winner.parts.length || Date.parse(input.lastAt(shorter.id)) > Date.parse(input.lastAt(winner.id))) return null;
17289
+ for (const [index, part] of shorter.parts.entries()) {
17290
+ const long = winner.parts[index];
17291
+ if (!long || part.retainedRecordCount > long.retainedRecordCount || !await sessionSourcePrefix(part, long, input.sourceFor(winner.id, long.sourceId), signal)) return null;
17292
+ if (!await compareParts(archive, manifest, part, long, masks, aliases, signal)) return null;
17293
+ }
17294
+ omitted.add(shorter.id);
17295
+ }
17296
+ }
17297
+ for (const value of aliases.values()) if (aliases.has(value)) return null;
17298
+ await archive.fence();
17299
+ return {
17300
+ omitted,
17301
+ retired: new Set(aliases.keys())
17302
+ };
17303
+ } finally {
17304
+ await archive.close();
17305
+ }
17306
+ }
17307
+ async function compareParts(archive, manifest, short, long, masks, aliases, signal) {
17308
+ const cleanup = createCleanup();
17309
+ const spools = [];
17310
+ try {
17311
+ for (const part of [short, long]) {
17312
+ const entry = archive.entries.get(part.dataPath) ?? fail("ARTIFACT_INVALID_ARCHIVE");
17313
+ const expected = manifest.entries.find((d) => d.entryPath === part.dataPath) ?? fail("ARTIFACT_INVALID_MANIFEST");
17314
+ spools.push(await spoolFacts(entry, expected, signal));
17315
+ }
17316
+ const [a, b] = spools;
17317
+ if (!a || !b) return fail("ARTIFACT_INVALID_ARCHIVE");
17318
+ let count = 0;
17319
+ for await (const row of a.lines) {
17320
+ const match = await b.lines.next();
17321
+ if (match.done) return false;
17322
+ const proof = compareSessionRows(row, match.value, masks.get(short.dataPath)?.get(count) ?? [], masks.get(long.dataPath)?.get(count) ?? []);
17323
+ if (!proof) return false;
17324
+ for (const [old, chosen] of proof.aliases) {
17325
+ if (aliases.has(old) && aliases.get(old) !== chosen) return false;
17326
+ aliases.set(old, chosen);
17327
+ }
17328
+ count++;
17329
+ }
17330
+ if (count !== short.retainedRecordCount) return false;
17331
+ for await (const _ of b.lines) count++;
17332
+ return count === long.retainedRecordCount;
17333
+ } catch (error) {
17334
+ cleanup.failed(error);
17335
+ throw error;
17336
+ } finally {
17337
+ await cleanup.run(...spools.flatMap((s) => [() => s.lines.return(void 0), () => s.close()]));
17338
+ }
17339
+ }
17340
+ /** Matches complete decoded marker spellings, including Unicode escape spellings in native JSON. */
17341
+ function refersToRetiredMarker(text, retired) {
17342
+ let candidate = text;
17343
+ for (let depth = 0; /\\u[\da-f]{4}/iu.test(candidate); depth++) {
17344
+ if (depth >= 8) return true;
17345
+ candidate = candidate.replace(/\\+u([\da-f]{4})/giu, (_, digits) => String.fromCharCode(Number.parseInt(digits, 16)));
17346
+ }
17347
+ for (const match of candidate.matchAll(replacementMarkerPattern)) if (retired.has(match[0])) return true;
17348
+ return false;
17349
+ }
17350
+ /** Search all kept uploaded fields of a confirmed Work before retiring an alias in another session. */
17351
+ async function hasRetiredSessionMarker(primary, omitted, retired, signal) {
17352
+ if (!retired.size) return false;
17353
+ const verified = await checkFrozenOutput(primary, signal);
17354
+ const archive = await openCheckedOutput(primary, verified.checked, signal);
17355
+ try {
17356
+ const entries = new Map(verified.manifest.entries.map((entry) => [entry.entryPath, entry]));
17357
+ for (const workspace of verified.manifest.sourceWorkspaces) if (refersToRetiredMarker(await readOutputJson(archive.entries.get(workspace.metadataPath) ?? fail("ARTIFACT_INVALID_ARCHIVE"), entries.get(workspace.metadataPath) ?? fail("ARTIFACT_INVALID_ARCHIVE"), signal), retired)) return true;
17358
+ for (const session of verified.manifest.sessions) {
17359
+ if (omitted.has(session.id)) continue;
17360
+ for (const part of session.parts) {
17361
+ const entry = archive.entries.get(part.dataPath) ?? fail("ARTIFACT_INVALID_ARCHIVE");
17362
+ const expected = entries.get(part.dataPath) ?? fail("ARTIFACT_INVALID_ARCHIVE");
17363
+ for await (const row of entryLines(entry, expected, signal)) if (refersToRetiredMarker(row, retired)) return true;
17364
+ }
17365
+ }
17366
+ return false;
17367
+ } finally {
17368
+ await archive.close();
17369
+ }
17370
+ }
17371
+ //#endregion
17372
+ export { decodeZstd as $, captureLogicalJourneySources as A, defaultParallelism as B, writePrivateReviewPayload as C, createCollectionArtifacts as D, readConfiguredSearchFields as E, parseCollectionWorkspaceSummary as F, readLogicalJourneyFinalMasks as G, parallelismLimits as H, createSharedSessionPool as I, staticMaskCategory as J, readConfiguredOutputInfo as K, SessionWorkerError as L, renderJobDigest as M, runConfiguredSessionJob as N, checkReusableBundle as O, readCollectionIndex as P, createInspectionProcessor as Q, sessionWorkerFailure as R, writeLogicalJourneyBase as S, readOriginalSearchFields as T, writeLogicalJourneyOutput as U, gitSeedsProvider as V, privateJourneyDirectory as W, listAgentSetup as X, readWorkspacePair as Y, createConfiguredPreviewStream as Z, captureConfiguredSessionJob as _, prepareSessionScans as a, makePrivateDirectory as at, readStaticSessionMasks as b, createWorkPieces as c, windowsOwnerOnly as ct, scanPreparedSession as d, createTemporary as et, runConfiguredScanJob as f, openConfiguredUpload as g, configuredSessionUploads as h, verifyPreparedSessionSources as i, exclusiveLock as it, capturedJourneyScope as j, prepareCollectionProduction as k, readSessionScanFields as l, isWindowsAclFailure as lt, writeOutputShard as m, sessionExtensions as n, createCleanup as nt, buildWorkScanBatches as o, openPrivateFile as ot, verifyOutputShard as p, processJourneyMetadataFields as q, preparedScanConfiguration as r, safeError as rt, scanReviewFields as s, restrictToOwner as st, hasRetiredSessionMarker as t, removeNamedTemporarySpools as tt, readSessionScanRecords as u, windowsAclCodes as ut, readCapturedOriginalRows as v, readPrivateReviewPayload as w, staticSessionJobs as x, processJourneyMetadata as y, privateCollectionDirectory as z };