@gitroll/tacitt-cli 0.6.11 → 0.6.13

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 (57) hide show
  1. package/README.md +4 -0
  2. package/bin/INDEX.md +6 -4
  3. package/bin/tacitt.cjs +1 -0
  4. package/dist/{agent-setup-DdfF3zch.mjs → agent-setup-Doy_AnPY.mjs} +2 -2
  5. package/dist/agent-setup-worker.mjs +5 -5
  6. package/dist/cli.mjs +32 -32
  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 +23 -25
  10. package/dist/{frame-Bq2zRh-i.mjs → frame-BPbypzmt.mjs} +1 -1
  11. package/dist/{heap-CV8Eca8V.mjs → heap-DCS_WXIA.mjs} +264 -23
  12. package/dist/inspection-worker.mjs +4 -4
  13. package/dist/{job-BKsifhyv.mjs → job--zxwgaPy.mjs} +155 -41
  14. package/dist/{locate-Cx52Zqxv.mjs → locate-PLEyLYW-.mjs} +292 -236
  15. package/dist/{model-C1UXkHh9.mjs → model-CyXvsWLz.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 +28 -8
  19. package/dist/{query-AMZerUh8.mjs → query-BC7MIaWc.mjs} +1914 -759
  20. package/dist/{run-CaPktPhH.mjs → run-Dod7Vykp.mjs} +6 -6
  21. package/dist/session-process.mjs +20 -0
  22. package/dist/{src-DlVbGB32.mjs → src-CP-K2PBv.mjs} +2100 -1649
  23. package/dist/{src-D1iONla3.mjs → src-CttNuxOn.mjs} +925 -630
  24. package/dist/{src-wZx_v0Ih.mjs → src-dL6y2mcu.mjs} +180 -30
  25. package/dist/store-database-worker.mjs +1 -1
  26. package/dist/web/assets/index-BgDdPL1c.js +172 -0
  27. package/dist/web/index.html +2 -1
  28. package/package.json +2 -1
  29. package/skills/INDEX.md +6 -4
  30. package/skills/tacitt/INDEX.md +7 -6
  31. package/skills/tacitt/SKILL.md +7 -7
  32. package/skills/tacitt/references/INDEX.md +14 -11
  33. package/skills/tacitt/references/b-method.md +6 -4
  34. package/skills/tacitt/references/bootstrap.md +18 -4
  35. package/skills/tacitt/references/classification.md +1 -1
  36. package/skills/tacitt/references/commands.md +34 -10
  37. package/skills/tacitt/references/journey.md +7 -7
  38. package/skills/tacitt/references/parallel-review.md +31 -12
  39. package/skills/tacitt/references/remote-workers.md +6 -2
  40. package/skills/tacitt/references/send.md +7 -3
  41. package/skills/tacitt/scripts/INDEX.md +40 -37
  42. package/skills/tacitt/scripts/answer.mjs +31 -2
  43. package/skills/tacitt/scripts/describe.mjs +3 -2
  44. package/skills/tacitt/scripts/journey-card-consolidation.mjs +1 -1
  45. package/skills/tacitt/scripts/journey-classification-tasks.mjs +28 -8
  46. package/skills/tacitt/scripts/journey-classification.mjs +1 -0
  47. package/skills/tacitt/scripts/journey-panel-host.d.mts +2 -0
  48. package/skills/tacitt/scripts/journey-panel-host.mjs +25 -2
  49. package/skills/tacitt/scripts/journey-scan-timing.d.mts +4 -0
  50. package/skills/tacitt/scripts/journey-scan-timing.mjs +15 -2
  51. package/skills/tacitt/scripts/journey-state.mjs +11 -0
  52. package/skills/tacitt/scripts/journey-tasks.mjs +12 -5
  53. package/skills/tacitt/scripts/journey.mjs +11 -3
  54. package/skills/tacitt/scripts/privacy-validator.mjs +112 -40
  55. package/skills/tacitt/scripts/review.d.mts +1 -0
  56. package/skills/tacitt/scripts/review.mjs +680 -119
  57. package/dist/web/assets/index-CYl7eDUu.js +0 -172
@@ -1,6 +1,6 @@
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-Cx52Zqxv.mjs";
2
- import { t as createZstdFrameCheck } from "./frame-Bq2zRh-i.mjs";
3
- import { Jr as agentSourceSchema, L as sourceIdentityEvidence, Pn as resolveSourceSelection, R as withSourceEvidence, _i as sourceChangePolicy, jt as metadataProcessingVersion, nr as bContainment, or as bWordBounded, ot as classifyAgentSetup, qr as agentSourcePathSegment, rr as bExceptionRanges, st as defaultAgentSetupInclusion, wi as staticCatalogRef, yi as approvedTreatmentSchema, z as agentSetupKey } from "./src-D1iONla3.mjs";
1
+ import { $n as validateProfile, Bn as projectNativeRecord, Cn as projectNativeReviewInput, Cr as siteFields, D as bBindingCap, Dn as renderNative, En as createSentenceContext, Gn as redactionImplementationVersion, Hn as cleanupImplementationVersion, Jn as nativeItems, Mn as createDetectionSummary, On as createSessionPreparation, Pn as walkNativeFields, Qn as retainedMainTextNodes, Rn as createReplacementKey, Sn as processNativeRecord, Sr as processingSite, Tn as reviewRoles, Un as entityDictionaryVersion, Vn as parseNativeRecord, Wn as nativeParserVersion, X as bDigest, Xn as transformRecords, Yn as nativeText, Z as codePointLength, Zn as frameRecords, _r as defaultDetectionLimits, ar as recordPointerLimits, bn as nativeSourceIdentitySchema, br as fail$1, dr as agentContextLocation, f as textDigest, fn as sourceKey, fr as createEntityMatcher, in as ApplicationError, ir as defaultLimits, k as bDuplicateShift, kn as bindInspection, ln as familySelected, mn as sourceSnapshotId, nr as validatePlan, on as safeCode, or as resolveLimits, qn as nativeField, sr as detectStatic, tr as buildPlan, u as reviewDigest, un as reviewFamilies, ur as jsonSpans, vr as ProcessingError, w as createBAnalysisUnits, wn as mainReviewRole, xn as withMandatoryCustomTerms, xr as isProcessingCode, zn as sessionNonce } from "./locate-PLEyLYW-.mjs";
2
+ import { t as createZstdFrameCheck } from "./frame-BPbypzmt.mjs";
3
+ import { Bi as staticCatalogRef, Br as metadataProcessingVersion, Fi as approvedTreatmentSchema, Jr as agentSourceSchema, L as sourceIdentityEvidence, Mn as resolveSourceSelection, Ni as sourceChangePolicy, R as withSourceEvidence, Ti as replacementMarkerPattern, bi as bContainment, ot as classifyAgentSetup, qr as agentSourcePathSegment, st as defaultAgentSetupInclusion, wi as bWordBounded, xi as bExceptionRanges, z as agentSetupKey } from "./src-CttNuxOn.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,11 +11,11 @@ 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";
18
- import { constants as constants$1, crc32, createZstdDecompress } from "node:zlib";
18
+ import { constants as constants$2, crc32, createZstdDecompress } from "node:zlib";
19
19
  import { parse } from "@decimalturn/toml-patch";
20
20
  //#region packages/file-privacy/src/windows/descriptor.ts
21
21
  const system = "S-1-5-18";
@@ -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);
@@ -2793,7 +2787,7 @@ async function* decodeZstd(source, signal) {
2793
2787
  });
2794
2788
  const decoded = createZstdDecompress({
2795
2789
  chunkSize: sourceChunkBytes,
2796
- params: { [constants$1.ZSTD_d_windowLogMax]: 26 }
2790
+ params: { [constants$2.ZSTD_d_windowLogMax]: 26 }
2797
2791
  });
2798
2792
  const cancellation = new AbortController();
2799
2793
  const completion = pipeline(input, decoded, { signal: AbortSignal.any([signal, cancellation.signal]) }).then(() => void 0, (error) => error);
@@ -3251,7 +3245,11 @@ async function inspectInput(input, part, adapter, signal, overrides, complete =
3251
3245
  checkNativeEvidence(part, identity);
3252
3246
  return identity;
3253
3247
  } catch (error) {
3254
- const failure = readingRecords ? recordError(error, part.id, records, signal) : error;
3248
+ const named = complete && error instanceof ProcessingError && error.code === "PROCESSING_INVALID_RECORD" ? new ProcessingError(error.code, {
3249
+ cause: error,
3250
+ site: "captured-source-invalid-record"
3251
+ }) : error;
3252
+ const failure = readingRecords ? recordError(named, part.id, records, signal) : named;
3255
3253
  cleanup.failed(failure);
3256
3254
  if (signal.aborted) fail("ARTIFACT_ABORTED", { cause: failure });
3257
3255
  throw failure;
@@ -3269,7 +3267,7 @@ async function inspectSourceIdentity(part, adapter, signal, overrides, observe)
3269
3267
  async function inspectCapturedSourceIdentity(part, captured, adapter, signal, overrides) {
3270
3268
  return inspectInput(await openCapturedConfiguredSource(part, captured, signal), part, adapter, signal, overrides);
3271
3269
  }
3272
- /** Ancestor publication waits for identity accumulated over every fixed captured record. */
3270
+ /** Frozen admission and ancestor publication use identity from every captured record. */
3273
3271
  async function inspectCompleteCapturedSourceIdentity(part, captured, adapter, signal, overrides, observe) {
3274
3272
  return inspectInput(await openCapturedConfiguredSource(part, captured, signal), part, adapter, signal, overrides, true, observe);
3275
3273
  }
@@ -5588,17 +5586,20 @@ function matchFrozenOutput(input, checked) {
5588
5586
  if (input.sha256 !== checked.sha256 || input.archiveBytes !== checked.archiveBytes) fail("ARTIFACT_PROCESSING_MISMATCH");
5589
5587
  }
5590
5588
  async function checkFrozenOutput(input, signal) {
5591
- let manifestText = "";
5589
+ let verified;
5592
5590
  const checked = await checkWrittenArchive(input.path, input.identity, void 0, (text, entries) => {
5593
5591
  const manifest = parseConfiguredManifest(text);
5594
- checkWorkspaceManifest(text, entries, manifest.bundleId, manifest.sourceWorkspaces.length === 1 ? manifest.sourceWorkspaces[0]?.pathHash ?? null : null, workspaceSummary(text));
5595
- manifestText = text;
5592
+ checkWorkspaceManifest(manifest, entries, manifest.bundleId, manifest.sourceWorkspaces.length === 1 ? manifest.sourceWorkspaces[0]?.pathHash ?? null : null, workspaceSummary(manifest));
5593
+ verified = {
5594
+ manifestText: text,
5595
+ manifest
5596
+ };
5596
5597
  }, signal);
5597
5598
  matchFrozenOutput(input, checked);
5599
+ if (!verified) return fail("ARTIFACT_INVALID_MANIFEST");
5598
5600
  return {
5599
5601
  checked,
5600
- manifestText,
5601
- manifest: parseConfiguredManifest(manifestText)
5602
+ ...verified
5602
5603
  };
5603
5604
  }
5604
5605
  /** Hold the exact verified descriptor; every entry is separately hashed before use. */
@@ -5711,13 +5712,6 @@ function addMaskSummary(a, b) {
5711
5712
  return result;
5712
5713
  }
5713
5714
  //#endregion
5714
- //#region packages/processing/src/session/marker.ts
5715
- /**
5716
- * One complete replacement marker as bindings and semantic markers write it. Group 1 names the
5717
- * static method, or `semantic` for an AI-review span. Dependency-free so the browser can use it.
5718
- */
5719
- const replacementMarkerPattern = /\[sp_[a-z0-9]{8,48}_([a-z][a-z0-9_]{0,47})_[a-f0-9]{24,64}\]/gu;
5720
- //#endregion
5721
5715
  //#region packages/artifact/src/configured/output/spans.ts
5722
5716
  function scalarBoundary(text, offset) {
5723
5717
  if (offset === 0 || offset === text.length) return true;
@@ -5803,6 +5797,9 @@ function indexOutputEdits(manifest, edits) {
5803
5797
  }
5804
5798
  return rows;
5805
5799
  }
5800
+ function rejectSemanticMarkerPrefix(text, markers) {
5801
+ if (text.includes(markers.prefix)) fail("ARTIFACT_PROCESSING_MISMATCH");
5802
+ }
5806
5803
  /** Parse/walk even unchanged records so native call/result state stays in source order. */
5807
5804
  function createOutputRowEditor(adapter, part, edits, markers, signal, onApplied) {
5808
5805
  const options = {
@@ -5826,7 +5823,7 @@ function createOutputRowEditor(adapter, part, edits, markers, signal, onApplied)
5826
5823
  limits: recordLimits,
5827
5824
  signal
5828
5825
  })) {
5829
- if (field.text.includes(markers.prefix)) fail("ARTIFACT_PROCESSING_MISMATCH");
5826
+ rejectSemanticMarkerPrefix(field.text, markers);
5830
5827
  if (field.subject !== "value") continue;
5831
5828
  const edit = pending.get(field.pointer);
5832
5829
  if (!edit) continue;
@@ -5897,1182 +5894,1504 @@ function maskOutputField(field, spans, markers, evidence, onApplied) {
5897
5894
  return changed;
5898
5895
  }
5899
5896
  //#endregion
5900
- //#region packages/artifact/src/collection/identity-map.ts
5901
- const maximumBundleIdentityMapBytes = 8388608;
5902
- const maximumLocatorBytes = 16384;
5903
- const maximumRemotes = 4096;
5904
- const uuid$2 = /^[a-f0-9]{8}-(?:[a-f0-9]{4}-){3}[a-f0-9]{12}$/;
5905
- const digest$3 = /^[a-f0-9]{64}$/;
5906
- function validBundleId(bundleId) {
5907
- if (!uuid$2.test(bundleId)) fail("ARTIFACT_INVALID_MANIFEST");
5908
- }
5909
- function boundedLocator(value) {
5910
- const result = string(value);
5911
- if (Buffer.byteLength(result) > maximumLocatorBytes) fail("ARTIFACT_METADATA_LIMIT");
5912
- return result;
5913
- }
5914
- function boundedHash(value) {
5915
- const result = string(value);
5916
- if (!digest$3.test(result)) fail("ARTIFACT_INVALID_MANIFEST");
5917
- return result;
5918
- }
5919
- function parseIdentityMap(value) {
5920
- const input = record$1(value);
5921
- keys(input, [
5922
- "format",
5923
- "formatVersion",
5924
- "bundleId",
5925
- "workspace"
5926
- ]);
5927
- const bundleId = string(input["bundleId"]);
5928
- validBundleId(bundleId);
5929
- const workspace = record$1(input["workspace"]);
5930
- keys(workspace, [
5931
- "path",
5932
- "pathHash",
5933
- "remotes",
5934
- "primaryRemoteHash"
5935
- ]);
5936
- const path = workspace["path"] === null ? null : boundedLocator(workspace["path"]);
5937
- const pathHash = workspace["pathHash"] === null ? null : boundedHash(workspace["pathHash"]);
5938
- if (path === null !== (pathHash === null)) fail("ARTIFACT_INVALID_MANIFEST");
5939
- const rawRemotes = workspace["remotes"];
5940
- if (!Array.isArray(rawRemotes)) return fail("ARTIFACT_INVALID_MANIFEST");
5941
- if (rawRemotes.length > maximumRemotes) fail("ARTIFACT_METADATA_LIMIT");
5942
- const remotes = rawRemotes.map((entry) => {
5943
- const remote = record$1(entry);
5944
- keys(remote, ["url", "hash"]);
5945
- return {
5946
- url: boundedLocator(remote["url"]),
5947
- hash: boundedHash(remote["hash"])
5948
- };
5949
- });
5950
- const primaryRemoteHash = nullableString(workspace["primaryRemoteHash"]);
5951
- if (primaryRemoteHash !== null) {
5952
- if (!digest$3.test(primaryRemoteHash) || !remotes.some((remote) => remote.hash === primaryRemoteHash)) fail("ARTIFACT_INVALID_MANIFEST");
5897
+ //#region packages/artifact/src/configured/output/family-carrier.ts
5898
+ /** Map decoded UTF-16 boundaries to complete JSON escape tokens in the original string. */
5899
+ function boundaries(text, span, value) {
5900
+ const offsets = [span.start + 1];
5901
+ let cursor = span.start + 1;
5902
+ while (cursor < span.end - 1) {
5903
+ cursor += text[cursor] === "\\" ? text[cursor + 1] === "u" ? 6 : 2 : 1;
5904
+ offsets.push(cursor);
5953
5905
  }
5954
- return {
5955
- format: literal(input["format"], "sess-pilot-bundle-identity-map"),
5956
- formatVersion: literal(input["formatVersion"], 1),
5957
- bundleId,
5958
- workspace: {
5959
- path,
5960
- pathHash,
5961
- remotes,
5962
- primaryRemoteHash
5963
- }
5964
- };
5965
- }
5966
- function encoded(map) {
5967
- const text = `${JSON.stringify(map)}\n`;
5968
- if (Buffer.byteLength(text) > 8388608) fail("ARTIFACT_METADATA_LIMIT");
5969
- return text;
5970
- }
5971
- function sameFileVersion$2(left, right) {
5972
- return right.isFile() && left.dev === right.dev && left.ino === right.ino && left.size === right.size && left.mtimeNs === right.mtimeNs && left.ctimeNs === right.ctimeNs;
5973
- }
5974
- async function identityDirectory(root) {
5975
- const directory = join(root, "identity");
5976
- if (await mkdir(directory, {
5977
- recursive: true,
5978
- mode: 448
5979
- }) !== void 0 && process.platform === "win32") await restrictToOwner(directory, "directory");
5980
- const stat = await lstat(directory, { bigint: true });
5981
- const uid = process.getuid?.();
5982
- if (!stat.isDirectory() || (process.platform === "win32" ? !await windowsOwnerOnly(directory, "directory") : uid === void 0 || stat.uid !== BigInt(uid) || (stat.mode & 63n) !== 0n) || await realpath(directory) !== directory) fail("ARTIFACT_OUTPUT_UNSAFE");
5983
- return directory;
5906
+ if (cursor !== span.end - 1 || offsets.length !== value.length + 1) fail("ARTIFACT_PROCESSING_MISMATCH");
5907
+ return offsets;
5984
5908
  }
5985
- /** Missing maps are recoverable from a current approval; malformed maps are not silently trusted. */
5986
- async function readBundleIdentityMap(root, bundleId) {
5987
- validBundleId(bundleId);
5988
- const directory = await identityDirectory(root);
5989
- const path = join(directory, `b-${bundleId}.json`);
5990
- let before;
5909
+ /** One harness-declared JSON carrier layer; never interpret ordinary strings recursively. */
5910
+ function familyCarrierSpans(field, find, signal) {
5911
+ const text = field.text;
5912
+ if (![
5913
+ "tool-call",
5914
+ "tool-result",
5915
+ "runtime"
5916
+ ].includes(field.origin.carrier) || !/^\s*[[{]/u.test(text)) return void 0;
5991
5917
  try {
5992
- before = await lstat(path, { bigint: true });
5918
+ parseNativeRecord(text, limits, signal);
5993
5919
  } catch (error) {
5994
- if (filesystemCode(error) === "ENOENT") return null;
5920
+ if (error instanceof ProcessingError && ["PROCESSING_INVALID_RECORD", "PROCESSING_KEY_COLLISION"].includes(error.code)) return void 0;
5995
5921
  throw error;
5996
5922
  }
5997
- const uid = process.getuid?.();
5998
- if (!before.isFile() || (process.platform === "win32" ? !await windowsOwnerOnly(path, "file") : uid === void 0 || before.uid !== BigInt(uid) || (before.mode & 63n) !== 0n)) fail("ARTIFACT_OUTPUT_UNSAFE");
5999
- if (before.size > BigInt(8388608)) fail("ARTIFACT_METADATA_LIMIT");
6000
- const handle = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);
6001
- try {
6002
- const opened = await handle.stat({ bigint: true });
6003
- if (!sameFileVersion$2(before, opened)) fail("ARTIFACT_IDENTITY_MISMATCH");
6004
- const bytes = Buffer.alloc(Number(opened.size));
6005
- let offset = 0;
6006
- while (offset < bytes.length) {
6007
- const { bytesRead } = await handle.read(bytes, offset, bytes.length - offset, offset);
6008
- if (bytesRead === 0) fail("ARTIFACT_INVALID_MANIFEST");
6009
- offset += bytesRead;
5923
+ const root = jsonSpans(text, signal) ?? fail("ARTIFACT_PROCESSING_MISMATCH");
5924
+ const spans = [];
5925
+ const visit = (part) => {
5926
+ checkAbort(signal);
5927
+ if (part.fields) for (const [key, value] of part.fields) {
5928
+ visit(part.keys?.get(key) ?? fail("ARTIFACT_PROCESSING_MISMATCH"));
5929
+ visit(value);
6010
5930
  }
6011
- if (!sameFileVersion$2(opened, await handle.stat({ bigint: true })) || !sameFileVersion$2(opened, await lstat(path, { bigint: true }))) fail("ARTIFACT_IDENTITY_MISMATCH");
6012
- let text;
6013
- try {
6014
- text = new TextDecoder$1("utf-8", { fatal: true }).decode(bytes);
6015
- } catch (error) {
6016
- return fail("ARTIFACT_INVALID_MANIFEST", { cause: error });
5931
+ else if (part.items) for (const item of part.items) visit(item);
5932
+ else if (typeof part.value === "string") {
5933
+ const matches = find(part.value);
5934
+ if (!matches.length) return;
5935
+ const offsets = boundaries(text, part, part.value);
5936
+ for (const match of matches) {
5937
+ const start = offsets[match.start] ?? fail("ARTIFACT_PROCESSING_MISMATCH");
5938
+ const end = offsets[match.end] ?? fail("ARTIFACT_PROCESSING_MISMATCH");
5939
+ spans.push({
5940
+ ...match,
5941
+ start,
5942
+ end
5943
+ });
5944
+ }
5945
+ } else {
5946
+ const value = text.slice(part.start, part.end);
5947
+ for (const match of find(value)) spans.push({
5948
+ ...match,
5949
+ start: part.start + match.start,
5950
+ end: part.start + match.end,
5951
+ jsonScalar: {
5952
+ start: part.start,
5953
+ end: part.end
5954
+ }
5955
+ });
6017
5956
  }
6018
- const map = parseIdentityMap(strictJson(text, maximumBundleIdentityMapBytes, 5e4));
6019
- if (map.bundleId !== bundleId) fail("ARTIFACT_INVALID_MANIFEST");
6020
- return map;
6021
- } finally {
6022
- await handle.close();
6023
- }
5957
+ };
5958
+ visit(root);
5959
+ return spans;
6024
5960
  }
6025
- /** Publish before the corresponding ZIP; retained maps are never removed automatically. */
6026
- async function writeBundleIdentityMap(root, map) {
6027
- const validated = parseIdentityMap(map);
6028
- const text = encoded(validated);
6029
- const directory = await identityDirectory(root);
6030
- await syncDirectory(root);
6031
- const finalPath = join(directory, `b-${validated.bundleId}.json`);
6032
- const existing = await readBundleIdentityMap(root, validated.bundleId);
6033
- if (existing) {
6034
- if (encoded(existing) !== text) fail("ARTIFACT_DESTINATION_EXISTS");
6035
- return;
6036
- }
6037
- const tempPath = join(directory, `.sess-pilot-b-${randomUUID()}.part`);
6038
- const handle = await openPrivateFile(tempPath, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY | constants.O_NOFOLLOW, 384);
5961
+ /** Never publish a carrier whose edited keys collide or whose JSON structure changed. */
5962
+ function validateFamilyCarrier(text, signal) {
6039
5963
  try {
6040
- const stat = await handle.stat({ bigint: true });
6041
- const uid = process.getuid?.();
6042
- if (!stat.isFile() || (process.platform === "win32" ? !await windowsOwnerOnly(tempPath, "file") : uid === void 0 || stat.uid !== BigInt(uid) || (stat.mode & 63n) !== 0n)) fail("ARTIFACT_OUTPUT_UNSAFE");
6043
- await handle.writeFile(text);
6044
- await handle.sync();
6045
- try {
6046
- await link(tempPath, finalPath);
6047
- } catch (error) {
6048
- if (filesystemCode(error) !== "EEXIST") throw error;
6049
- const raced = await readBundleIdentityMap(root, validated.bundleId);
6050
- if (!raced || encoded(raced) !== text) fail("ARTIFACT_DESTINATION_EXISTS");
6051
- }
6052
- await syncDirectory(directory);
6053
- } finally {
6054
- await handle.close();
6055
- await unlink(tempPath);
5964
+ parseNativeRecord(text, limits, signal);
5965
+ } catch (error) {
5966
+ if (error instanceof ProcessingError && ["PROCESSING_INVALID_RECORD", "PROCESSING_KEY_COLLISION"].includes(error.code)) fail("ARTIFACT_PROCESSING_MISMATCH", { cause: error });
5967
+ throw error;
6056
5968
  }
6057
5969
  }
6058
5970
  //#endregion
6059
- //#region packages/artifact/src/collection/identity/hash.ts
6060
- /** Hash the private canonical path under an OS-installation namespace. */
6061
- function hashWorkspacePath(normalizedPath, environmentId) {
6062
- if (!/^[0-9a-f]{64}$/.test(environmentId)) throw new Error("ARTIFACT_ENVIRONMENT_UNAVAILABLE");
6063
- return createHash("sha256").update("sess-pilot-workspace-path-v2\0").update(environmentId).update("\0").update(normalizedPath).digest("hex");
6064
- }
6065
- /** Keep the installation identifier out of the distributable bundle. */
6066
- function installationEnvironmentId(kind, installationId) {
6067
- if (!kind || !installationId) throw new Error("ARTIFACT_ENVIRONMENT_UNAVAILABLE");
6068
- return createHash("sha256").update("sess-pilot-workspace-environment-v2\0").update(kind).update("\0").update(installationId).digest("hex");
6069
- }
6070
- //#endregion
6071
- //#region packages/artifact/src/collection/identity/wsl.ts
6072
- async function isWsl() {
6073
- try {
6074
- return /microsoft|wsl/i.test(await readFile("/proc/sys/kernel/osrelease", "utf8"));
6075
- } catch {
6076
- return false;
6077
- }
5971
+ //#region packages/artifact/src/configured/output/family.ts
5972
+ /** The same bounded categorized dictionary is shared by all final-generation family parts. */
5973
+ function confirmedFamily(terms, exceptions) {
5974
+ const categories = new Map(terms.map(({ term, category }) => [term, maskCategory(category)]));
5975
+ if (categories.size !== terms.length) mismatch("duplicate-term");
5976
+ const bounded = new Set(categories.keys());
5977
+ return {
5978
+ matcher: createEntityMatcher([...categories.keys()].map((value) => ({
5979
+ kind: "custom-term",
5980
+ value
5981
+ }))),
5982
+ categories,
5983
+ bounded,
5984
+ toolResultEscapes: bounded,
5985
+ excepted: bExceptionRanges(exceptions)
5986
+ };
5987
+ }
5988
+ /** A masked title never grows past a Work label (240), the Send title limit being 300. */
5989
+ const titleLimit = 240;
5990
+ const titleMask = 8;
5991
+ /**
5992
+ * Name fields use exactly the confirmed card-Hide matcher, without tool carrier escapes. Many
5993
+ * short hidden words can make the masked title longer than the limit (#125); then the whole
5994
+ * title is one mask, never the raw text.
5995
+ */
5996
+ function confirmedTitleSpans(text, family, signal = new AbortController().signal) {
5997
+ const spans = familySpans(text, family, signal, false);
5998
+ const masked = spans.reduce((length, span) => length - (span.end - span.start) + titleMask, text.length);
5999
+ const [first] = spans;
6000
+ return first && masked > titleLimit ? [{
6001
+ start: 0,
6002
+ end: text.length,
6003
+ category: first.category
6004
+ }] : spans;
6078
6005
  }
6079
- //#endregion
6080
- //#region packages/artifact/src/collection/identity/path.ts
6081
- const execute$1 = promisify(execFile);
6082
- const unavailable$1 = () => fail("ARTIFACT_ENVIRONMENT_UNAVAILABLE");
6083
- function pathPart(value) {
6084
- if (value.length === 0 || Buffer.byteLength(value, "utf8") > 16384 || Array.from(value).some((character) => {
6085
- const code = character.charCodeAt(0);
6086
- return code < 32 || code === 127;
6087
- })) return unavailable$1();
6088
- return value;
6089
- }
6090
- function wslUnc(path) {
6091
- const match = /^\\\\(?:wsl\.localhost|wsl\$)\\([^\\]+)(?:\\(.*))?$/i.exec(path);
6092
- if (!match) return null;
6093
- const distro = pathPart(match[1] ?? "").toLowerCase();
6094
- const remainder = (match[2] ?? "").replaceAll("\\", "/");
6095
- return `wsl:${encodeURIComponent(distro)}:${posix.normalize(`/${remainder}`)}`;
6006
+ /** Names the failed check in the private cause chain; it never carries session text. */
6007
+ const mismatch = (check) => fail("ARTIFACT_PROCESSING_MISMATCH", { cause: /* @__PURE__ */ new Error(`configured family hide check=${check}`) });
6008
+ /** Binds each family's main Hide literals to its main and worker data and metadata entries. */
6009
+ function indexFamilyHides(manifest, hides = []) {
6010
+ const sessions = new Map(manifest.sessions.map((session) => [session.id, session]));
6011
+ const parts = /* @__PURE__ */ new Map();
6012
+ const bind = (id, family, main) => {
6013
+ const session = sessions.get(id) ?? mismatch("unknown-session");
6014
+ if (parts.has(session.metadataPath)) mismatch("duplicate-session");
6015
+ if (session.parts.some((part) => part.native.role === "main") !== main) mismatch("session-role");
6016
+ parts.set(session.metadataPath, family);
6017
+ for (const part of session.parts) {
6018
+ if (parts.has(part.dataPath)) mismatch("duplicate-part");
6019
+ parts.set(part.dataPath, family);
6020
+ }
6021
+ };
6022
+ const shared = /* @__PURE__ */ new Map();
6023
+ for (const hide of hides) {
6024
+ if (!hide.terms.length || !(hide.mainSessionIds.length + hide.workerSessionIds.length)) mismatch("empty-family");
6025
+ const key = JSON.stringify([hide.terms, hide.exceptions ?? []]);
6026
+ let family = shared.get(key);
6027
+ if (!family) {
6028
+ const categories = /* @__PURE__ */ new Map();
6029
+ const bounded = /* @__PURE__ */ new Set();
6030
+ const toolResultEscapes = /* @__PURE__ */ new Set();
6031
+ for (const { term, category, bounded: whole, toolResultEscapes: escaped } of hide.terms) {
6032
+ if (categories.has(term)) mismatch("duplicate-term");
6033
+ categories.set(term, maskCategory(category));
6034
+ if (whole) bounded.add(term);
6035
+ if (escaped) toolResultEscapes.add(term);
6036
+ }
6037
+ family = {
6038
+ matcher: createEntityMatcher([...categories.keys()].map((value) => ({
6039
+ kind: "custom-term",
6040
+ value
6041
+ }))),
6042
+ categories,
6043
+ bounded,
6044
+ toolResultEscapes,
6045
+ excepted: bExceptionRanges(hide.exceptions ?? [])
6046
+ };
6047
+ shared.set(key, family);
6048
+ }
6049
+ for (const id of hide.mainSessionIds) bind(id, family, true);
6050
+ for (const id of hide.workerSessionIds) bind(id, family, false);
6051
+ }
6052
+ return parts;
6096
6053
  }
6097
- /** Canonical path is private input to the digest and is never written to the bundle. */
6098
- function normalizeWindowsWorkspacePath(rawPath) {
6099
- pathPart(rawPath);
6100
- const normalized = win32.normalize(rawPath);
6101
- const wslPath = wslUnc(normalized);
6102
- if (wslPath !== null) return wslPath;
6103
- const drive = /^([a-zA-Z]):\\(.*)$/.exec(normalized);
6104
- if (drive) return `win-drive:${(drive[1] ?? "").toLowerCase()}:${posix.normalize(`/${(drive[2] ?? "").replaceAll("\\", "/")}`)}`;
6105
- const share = /^\\\\([^\\]+)\\([^\\]+)(?:\\(.*))?$/.exec(normalized);
6106
- if (share) {
6107
- const server = encodeURIComponent(pathPart(share[1] ?? "").toLowerCase());
6108
- const name = encodeURIComponent(pathPart(share[2] ?? "").toLowerCase());
6109
- const remainder = (share[3] ?? "").replaceAll("\\", "/");
6110
- return `win-unc:${server}/${name}:${posix.normalize(`/${remainder}`)}`;
6054
+ /** Disjoint literal hits outside existing markers; overlaps join under the highest category. */
6055
+ function familySpans(text, family, signal, toolResult) {
6056
+ const markers = [...text.matchAll(markerPattern)].map((match) => ({
6057
+ start: match.index,
6058
+ end: match.index + match[0].length
6059
+ }));
6060
+ let kept;
6061
+ const excepted = (range) => (kept ??= bContainment(family.excepted(text, signal)))(range);
6062
+ const marked = (range) => {
6063
+ let low = 0, high = markers.length;
6064
+ while (low < high) {
6065
+ const middle = low + high >> 1;
6066
+ if ((markers[middle]?.end ?? Infinity) <= range.start) low = middle + 1;
6067
+ else high = middle;
6068
+ }
6069
+ return (markers[low]?.start ?? Infinity) < range.end;
6070
+ };
6071
+ 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 }) => ({
6072
+ ...range,
6073
+ category: family.categories.get(entity.value) ?? mismatch("unknown-term")
6074
+ })).sort((left, right) => left.start - right.start || right.end - left.end);
6075
+ const spans = [];
6076
+ for (const hit of hits) {
6077
+ const prior = spans.at(-1);
6078
+ if (!prior || hit.start >= prior.end) {
6079
+ spans.push(hit);
6080
+ continue;
6081
+ }
6082
+ prior.end = Math.max(prior.end, hit.end);
6083
+ if (categoryOrder.indexOf(hit.category) > categoryOrder.indexOf(prior.category)) prior.category = hit.category;
6111
6084
  }
6112
- return unavailable$1();
6085
+ return spans;
6113
6086
  }
6114
- function normalizePosixWorkspacePath(rawPath) {
6115
- pathPart(rawPath);
6116
- if (!posix.isAbsolute(rawPath)) return unavailable$1();
6117
- return `posix:${posix.normalize(rawPath)}`;
6087
+ /**
6088
+ * Enum-like envelope values that native parsing interprets. Values inside an adapter-retained
6089
+ * body are free text; outside bodies these names (and IDs) never take family terms.
6090
+ */
6091
+ const structuralNames = /* @__PURE__ */ new Set([
6092
+ "type",
6093
+ "role",
6094
+ "name",
6095
+ "subtype",
6096
+ "stop_reason",
6097
+ "status",
6098
+ "kind",
6099
+ "level",
6100
+ "source",
6101
+ "originator",
6102
+ "mode",
6103
+ "tool_name",
6104
+ "toolName",
6105
+ "function_name"
6106
+ ]);
6107
+ const structural = (name) => name !== void 0 && (structuralNames.has(name) || /(?:^id|_id|Id|uuid|Uuid)$/u.test(name));
6108
+ /** Node IDs inside the adapter's retained bodies: the native free-text classification. */
6109
+ function bodyNodes(root, selection) {
6110
+ const bodies = new Set(selection.edits.map((edit) => edit.nodeId));
6111
+ const nodes = /* @__PURE__ */ new Set();
6112
+ const visit = (node, inside) => {
6113
+ const body = inside || bodies.has(node.id);
6114
+ if (body) nodes.add(node.id);
6115
+ if (node.kind === "array") for (const item of node.items) visit(item, body);
6116
+ if (node.kind === "object") for (const property of node.properties) visit(property.value, body);
6117
+ };
6118
+ visit(root, false);
6119
+ return nodes;
6118
6120
  }
6119
- async function wslWindowsPath(rawPath, signal) {
6120
- checkAbort(signal);
6121
- pathPart(rawPath);
6122
- if (!posix.isAbsolute(rawPath)) return unavailable$1();
6123
- try {
6124
- const { stdout } = await execute$1("wslpath", ["-w", rawPath], {
6125
- encoding: "utf8",
6126
- maxBuffer: 32768,
6127
- timeout: 15e3,
6128
- windowsHide: true,
6129
- signal
6130
- });
6131
- checkAbort(signal);
6132
- return stdout.replace(/\r?\n$/, "");
6133
- } catch {
6134
- checkAbort(signal);
6135
- return unavailable$1();
6136
- }
6121
+ /** Exact, cheap check that any string value can match: one linear scan whatever the term count. */
6122
+ function mayMatch(root, family, signal) {
6123
+ const values = [];
6124
+ const visit = (node) => {
6125
+ if (node.kind === "string") values.push(node.value);
6126
+ else if (node.kind === "array") for (const item of node.items) visit(item);
6127
+ else if (node.kind === "object") for (const property of node.properties) visit(property.value);
6128
+ };
6129
+ visit(root);
6130
+ return family.matcher.hasCustomTerm(values.join("\0"), signal) || values.some((value) => /^\s*[[{]/u.test(value) && value.includes("\\"));
6137
6131
  }
6138
- /** Translate Windows/WSL aliases lexically, including paths that no longer exist. */
6139
- async function normalizeWorkspacePath(rawPath, signal) {
6140
- checkAbort(signal);
6141
- if (/^(?:[A-Za-z]:[\\/]|\\\\)/u.test(rawPath)) return normalizeWindowsWorkspacePath(rawPath);
6142
- if (platform() === "win32") {
6143
- const wslDrive = /^\/mnt\/([A-Za-z])(?:\/(.*))?$/u.exec(rawPath);
6144
- if (wslDrive) return normalizeWindowsWorkspacePath(`${wslDrive[1]}:\\${(wslDrive[2] ?? "").replaceAll("/", "\\")}`);
6145
- return normalizePosixWorkspacePath(rawPath);
6132
+ /** Masks family literals in unprotected, non-structural string values `skip` does not exclude. */
6133
+ function maskFamilyFields(text, root, annotations, family, markers, signal, onApplied, bodies, skip) {
6134
+ const changes = /* @__PURE__ */ new Map();
6135
+ const evidence = { bytes: 0 };
6136
+ const recordLimits = recordPointerLimits(limits, Buffer.byteLength(text));
6137
+ for (const field of walkNativeFields(root, annotations, {
6138
+ recordId: digest$4(text),
6139
+ limits: recordLimits,
6140
+ signal
6141
+ })) {
6142
+ if (skip(field)) continue;
6143
+ if (field.text.includes(markers.prefix)) mismatch("marker-prefix");
6144
+ if (field.subject !== "value" || field.scalarKind !== "string" || field.field.protection || !bodies.has(field.nodeId) && structural(field.field.name)) continue;
6145
+ const toolResult = field.origin.carrier === "tool-result";
6146
+ const find = (value) => familySpans(value, family, signal, toolResult);
6147
+ const raw = find(field.text);
6148
+ const carrier = raw.length || field.text.includes("\\") ? familyCarrierSpans(field, find, signal) : void 0;
6149
+ const spans = (carrier ?? raw).sort((left, right) => left.start - right.start);
6150
+ if (!spans.length) continue;
6151
+ const changed = maskOutputField({
6152
+ pointer: field.pointer,
6153
+ text: field.text,
6154
+ sha256: digest$4(field.text)
6155
+ }, spans, markers, evidence, onApplied);
6156
+ if (carrier) validateFamilyCarrier(changed, signal);
6157
+ changes.set(field.nodeId, changed);
6146
6158
  }
6147
- if (platform() === "darwin") return normalizePosixWorkspacePath(rawPath);
6148
- if (platform() !== "linux") return unavailable$1();
6149
- const wsl = await isWsl();
6159
+ return changes.size ? renderNative(root, changes, recordLimits, signal).text : text;
6160
+ }
6161
+ /**
6162
+ * Every row of a family part is parsed in order so native call/result state stays aligned.
6163
+ * Worker rows: every unprotected string value. Main rows: every one that is not a B review
6164
+ * field, which keeps its exact B decisions. Keys, roles, identities and tool links stay exact.
6165
+ */
6166
+ function createFamilyHideEditor(adapter, part, family, markers, signal, onApplied) {
6167
+ const options = {
6168
+ sourceRole: part.native.role,
6169
+ nativeSessionId: part.native.sessionId
6170
+ };
6171
+ const retention = adapter.retention(options);
6172
+ return (text, reviewed = /* @__PURE__ */ new Set()) => {
6173
+ checkAbort(signal);
6174
+ const root = parseNativeRecord(text, limits, signal);
6175
+ const selection = retention(root);
6176
+ if (!mayMatch(root, family, signal)) return text;
6177
+ return maskFamilyFields(text, root, adapter.annotations(root, options, selection), family, markers, signal, onApplied, bodyNodes(root, selection), (field) => reviewed.has(field.pointer));
6178
+ };
6179
+ }
6180
+ /** Session metadata is never analysed; its unprotected text (such as a title) takes family terms. */
6181
+ function maskFamilyMetadata(text, family, markers, signal, onApplied) {
6150
6182
  checkAbort(signal);
6151
- if (wsl) return normalizeWindowsWorkspacePath(await wslWindowsPath(rawPath, signal));
6152
- return normalizePosixWorkspacePath(rawPath);
6183
+ const root = parseNativeRecord(text, limits, signal);
6184
+ return maskFamilyFields(text, root, metadataAnnotations(root), family, markers, signal, onApplied, /* @__PURE__ */ new Set(), () => false);
6153
6185
  }
6154
6186
  //#endregion
6155
- //#region packages/artifact/src/collection/identity/environment.ts
6156
- const execute = promisify(execFile);
6157
- const unavailable = () => fail("ARTIFACT_ENVIRONMENT_UNAVAILABLE");
6158
- async function run(file, args, signal) {
6159
- checkAbort(signal);
6160
- try {
6161
- const { stdout } = await execute(file, [...args], {
6162
- encoding: "utf8",
6163
- maxBuffer: 32768,
6164
- timeout: 15e3,
6165
- windowsHide: true,
6166
- signal
6187
+ //#region packages/artifact/src/configured/output/workspace-title.ts
6188
+ function createWorkspaceTitleMasker(request, manifest, markers, signal) {
6189
+ const hides = request.metadata?.workspaceTitleHides;
6190
+ const family = hides && {
6191
+ ...confirmedFamily(hides.terms, hides.exceptions),
6192
+ bounded: new Set(hides.terms.filter((term) => term.bounded).map((term) => term.term))
6193
+ };
6194
+ const workspaces = new Map(manifest.sourceWorkspaces.map((item) => [item.metadataPath, item]));
6195
+ return (text, entryPath, onApplied) => {
6196
+ const workspace = workspaces.get(entryPath);
6197
+ if (!workspace || !family) return text;
6198
+ const metadata = validateConfiguredSourceMetadata(strictJson(text, metadataLimitBytes), workspace);
6199
+ if (metadata.title.includes(markers.prefix)) fail("ARTIFACT_PROCESSING_MISMATCH");
6200
+ const title = maskOutputField({
6201
+ pointer: "/title",
6202
+ text: metadata.title,
6203
+ sha256: digest$4(metadata.title)
6204
+ }, confirmedTitleSpans(metadata.title, family, signal), {
6205
+ ...markers,
6206
+ marker: () => "[hidden]"
6207
+ }, { bytes: 0 }, onApplied);
6208
+ return JSON.stringify({
6209
+ ...metadata,
6210
+ title
6167
6211
  });
6168
- checkAbort(signal);
6169
- return stdout.trim();
6170
- } catch {
6171
- checkAbort(signal);
6172
- return unavailable();
6173
- }
6212
+ };
6174
6213
  }
6175
- function identifier(value, pattern) {
6176
- const id = value.trim().toLowerCase();
6177
- if (id.length > 128 || !pattern.test(id) || /^0+$/.test(id.replaceAll("-", ""))) return unavailable();
6178
- return id;
6214
+ //#endregion
6215
+ //#region packages/artifact/src/collection/identity-map.ts
6216
+ const maximumBundleIdentityMapBytes = 8388608;
6217
+ const maximumLocatorBytes = 16384;
6218
+ const maximumRemotes = 4096;
6219
+ const uuid$2 = /^[a-f0-9]{8}-(?:[a-f0-9]{4}-){3}[a-f0-9]{12}$/;
6220
+ const digest$3 = /^[a-f0-9]{64}$/;
6221
+ function validBundleId(bundleId) {
6222
+ if (!uuid$2.test(bundleId)) fail("ARTIFACT_INVALID_MANIFEST");
6179
6223
  }
6180
- async function windowsInstallationId() {
6181
- const script = [
6182
- "$ErrorActionPreference='Stop'",
6183
- "$id=(Get-ItemProperty -Path 'HKLM:\\SOFTWARE\\Microsoft\\Cryptography').MachineGuid",
6184
- "if ([string]::IsNullOrWhiteSpace($id)) { exit 2 }",
6185
- "[Console]::Out.WriteLine($id)"
6186
- ].join(";");
6187
- return identifier(await run("powershell.exe", [
6188
- "-NoProfile",
6189
- "-NonInteractive",
6190
- "-EncodedCommand",
6191
- Buffer.from(script, "utf16le").toString("base64")
6192
- ]), /^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/);
6224
+ function boundedLocator(value) {
6225
+ const result = string(value);
6226
+ if (Buffer.byteLength(result) > maximumLocatorBytes) fail("ARTIFACT_METADATA_LIMIT");
6227
+ return result;
6193
6228
  }
6194
- async function linuxInstallationId() {
6195
- try {
6196
- return identifier(await readFile("/etc/machine-id", "utf8"), /^[0-9a-f]{32}$/);
6197
- } catch {
6198
- return unavailable();
6199
- }
6229
+ function boundedHash(value) {
6230
+ const result = string(value);
6231
+ if (!digest$3.test(result)) fail("ARTIFACT_INVALID_MANIFEST");
6232
+ return result;
6200
6233
  }
6201
- async function macInstallationId() {
6202
- const plist = await run("diskutil", [
6203
- "info",
6204
- "-plist",
6205
- "/"
6234
+ function parseIdentityMap(value) {
6235
+ const input = record$1(value);
6236
+ keys(input, [
6237
+ "format",
6238
+ "formatVersion",
6239
+ "bundleId",
6240
+ "workspace"
6206
6241
  ]);
6207
- const match = /<key>APFSVolumeGroupID<\/key>\s*<string>([0-9a-fA-F-]+)<\/string>/.exec(plist);
6208
- if (!match) return unavailable();
6209
- return identifier(match[1] ?? "", /^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/);
6210
- }
6211
- async function installationId() {
6212
- if (platform() === "win32") return installationEnvironmentId("windows-installation", await windowsInstallationId());
6213
- if (platform() === "darwin") return installationEnvironmentId("macos-apfs-installation", await macInstallationId());
6214
- if (platform() === "linux") {
6215
- if (await isWsl()) return installationEnvironmentId("windows-installation", await windowsInstallationId());
6216
- return installationEnvironmentId("linux-installation", await linuxInstallationId());
6217
- }
6218
- return unavailable();
6219
- }
6220
- let installationPromise;
6221
- function waitForInstallation(id, signal) {
6222
- if (!signal) return id;
6223
- checkAbort(signal);
6224
- return new Promise((resolve, reject) => {
6225
- const onAbort = () => reject(/* @__PURE__ */ new Error("ARTIFACT_ABORTED"));
6226
- signal.addEventListener("abort", onAbort, { once: true });
6227
- id.then((value) => {
6228
- signal.removeEventListener("abort", onAbort);
6229
- resolve(value);
6230
- }, (error) => {
6231
- signal.removeEventListener("abort", onAbort);
6232
- reject(error);
6233
- });
6234
- });
6235
- }
6236
- /** Same OS installation receives one stable namespace across process and state-dir changes. */
6237
- async function resolveWorkspaceEnvironmentId(signal) {
6238
- checkAbort(signal);
6239
- if (!installationPromise) installationPromise = installationId().catch((error) => {
6240
- installationPromise = void 0;
6241
- throw error;
6242
- });
6243
- const id = await waitForInstallation(installationPromise, signal);
6244
- checkAbort(signal);
6245
- return id;
6246
- }
6247
- //#endregion
6248
- //#region packages/artifact/src/collection/identity/remote.ts
6249
- /** Versioned canonical form shared by archive producers and downstream consumers. */
6250
- function canonicalRemote(value) {
6251
- const input = value.trim();
6252
- if (!input || Buffer.byteLength(input) > 16384) return fail("ARTIFACT_UNSAFE_REMOTE");
6253
- for (const character of input) {
6254
- const code = character.charCodeAt(0);
6255
- if (code < 32 || code === 127) return fail("ARTIFACT_UNSAFE_REMOTE");
6256
- }
6257
- if (input.startsWith("/") || /^[a-z]:[\\/]/i.test(input) || input.startsWith("\\\\")) return input.replaceAll("\\", "/");
6258
- const scp = /^[a-z][a-z0-9+.-]*:\/\//i.test(input) ? null : /^(?:[^@/\s]+@)?(\[[^\]]+\]|[^/:\s]+):([^:].*)$/.exec(input);
6259
- const candidate = scp?.[1] && scp[2] ? `ssh://${scp[1]}/${scp[2]}` : input;
6260
- let url;
6261
- try {
6262
- url = new URL(candidate);
6263
- } catch (error) {
6264
- return fail("ARTIFACT_UNSAFE_REMOTE", { cause: error });
6265
- }
6266
- if (![
6267
- "https:",
6268
- "http:",
6269
- "ssh:",
6270
- "git:",
6271
- "file:"
6272
- ].includes(url.protocol)) fail("ARTIFACT_UNSAFE_REMOTE");
6273
- url.username = "";
6274
- url.password = "";
6275
- url.search = "";
6276
- url.hash = "";
6277
- url.hostname = url.hostname.toLowerCase();
6278
- if (url.protocol === "ssh:" && url.port === "22" || url.protocol === "git:" && url.port === "9418") url.port = "";
6279
- if (url.protocol !== "file:") {
6280
- if (!url.hostname) fail("ARTIFACT_UNSAFE_REMOTE");
6281
- url.pathname = url.pathname.replace(/\/+$/, "").replace(/\.git$/, "");
6282
- }
6283
- return url.href;
6284
- }
6285
- function hashRemote(canonical) {
6286
- return createHash("sha256").update("sess-pilot/git-remote/v1\0").update(canonical).digest("hex");
6287
- }
6288
- //#endregion
6289
- //#region packages/artifact/src/collection/identity/workspace.ts
6290
- async function workspaceIdentity(workspace, signal) {
6291
- checkAbort(signal);
6292
- const pathHash = workspace.path === null ? null : hashWorkspacePath(await normalizeWorkspacePath(workspace.path, signal), await resolveWorkspaceEnvironmentId(signal));
6293
- const remotes = workspace.remotes.map((remote) => {
6294
- const url = canonicalRemote(remote);
6242
+ const bundleId = string(input["bundleId"]);
6243
+ validBundleId(bundleId);
6244
+ const workspace = record$1(input["workspace"]);
6245
+ keys(workspace, [
6246
+ "path",
6247
+ "pathHash",
6248
+ "remotes",
6249
+ "primaryRemoteHash"
6250
+ ]);
6251
+ const path = workspace["path"] === null ? null : boundedLocator(workspace["path"]);
6252
+ const pathHash = workspace["pathHash"] === null ? null : boundedHash(workspace["pathHash"]);
6253
+ if (path === null !== (pathHash === null)) fail("ARTIFACT_INVALID_MANIFEST");
6254
+ const rawRemotes = workspace["remotes"];
6255
+ if (!Array.isArray(rawRemotes)) return fail("ARTIFACT_INVALID_MANIFEST");
6256
+ if (rawRemotes.length > maximumRemotes) fail("ARTIFACT_METADATA_LIMIT");
6257
+ const remotes = rawRemotes.map((entry) => {
6258
+ const remote = record$1(entry);
6259
+ keys(remote, ["url", "hash"]);
6295
6260
  return {
6296
- url,
6297
- hash: hashRemote(url)
6261
+ url: boundedLocator(remote["url"]),
6262
+ hash: boundedHash(remote["hash"])
6298
6263
  };
6299
6264
  });
6300
- const primaryRemoteHash = workspace.primaryRemote ? hashRemote(canonicalRemote(workspace.primaryRemote.locator)) : null;
6301
- if (primaryRemoteHash !== null && !remotes.some((remote) => remote.hash === primaryRemoteHash)) fail("ARTIFACT_UNSAFE_REMOTE");
6302
- const challengeId = await readChallengeId(workspace.path, signal);
6303
- checkAbort(signal);
6304
- return {
6305
- title: workspace.title,
6306
- path: workspace.path,
6307
- pathHash,
6308
- remotes,
6309
- primaryRemoteHash,
6310
- challengeId
6311
- };
6312
- }
6313
- function workspaceMetadata(identity) {
6314
- return {
6315
- version: 3,
6316
- title: identity.title,
6317
- pathHash: identity.pathHash,
6318
- remoteHashes: identity.remotes.map((remote) => remote.hash),
6319
- primaryRemoteHash: identity.primaryRemoteHash
6320
- };
6321
- }
6322
- function bundleIdentityMap(bundleId, identity) {
6265
+ const primaryRemoteHash = nullableString(workspace["primaryRemoteHash"]);
6266
+ if (primaryRemoteHash !== null) {
6267
+ if (!digest$3.test(primaryRemoteHash) || !remotes.some((remote) => remote.hash === primaryRemoteHash)) fail("ARTIFACT_INVALID_MANIFEST");
6268
+ }
6323
6269
  return {
6324
- format: "sess-pilot-bundle-identity-map",
6325
- formatVersion: 1,
6270
+ format: literal(input["format"], "sess-pilot-bundle-identity-map"),
6271
+ formatVersion: literal(input["formatVersion"], 1),
6326
6272
  bundleId,
6327
6273
  workspace: {
6328
- path: identity.path,
6329
- pathHash: identity.pathHash,
6330
- remotes: identity.remotes,
6331
- primaryRemoteHash: identity.primaryRemoteHash
6274
+ path,
6275
+ pathHash,
6276
+ remotes,
6277
+ primaryRemoteHash
6332
6278
  }
6333
6279
  };
6334
6280
  }
6335
- //#endregion
6336
- //#region packages/artifact/src/collection/producer/workspace-metadata.ts
6337
- /** Workspace titles are emitted once, independently of per-session optional profiles. */
6338
- async function configuredWorkspaceMetadata(identity, processing, signal, titlePlan, onMasks, replacementScope) {
6339
- const metadata = workspaceMetadata(identity);
6340
- const terms = processing.customTerms?.terms ?? [];
6341
- if (terms.length === 0 && titlePlan === void 0) return metadata;
6342
- const preparation = createSessionPreparation({
6343
- environment: processing.environment,
6344
- customTerms: terms,
6345
- ...processing.staticExceptions === void 0 ? {} : { staticExceptions: processing.staticExceptions.values },
6346
- ...processing.replacementKey === void 0 ? {} : { replacementKey: processing.replacementKey },
6347
- ...replacementScope === void 0 ? {} : { replacementScope }
6348
- }, signal);
6349
- let bindings;
6281
+ function encoded(map) {
6282
+ const text = `${JSON.stringify(map)}\n`;
6283
+ if (Buffer.byteLength(text) > 8388608) fail("ARTIFACT_METADATA_LIMIT");
6284
+ return text;
6285
+ }
6286
+ function sameFileVersion$2(left, right) {
6287
+ return right.isFile() && left.dev === right.dev && left.ino === right.ino && left.size === right.size && left.mtimeNs === right.mtimeNs && left.ctimeNs === right.ctimeNs;
6288
+ }
6289
+ async function identityDirectory(root) {
6290
+ const directory = join(root, "identity");
6291
+ if (await mkdir(directory, {
6292
+ recursive: true,
6293
+ mode: 448
6294
+ }) !== void 0 && process.platform === "win32") await restrictToOwner(directory, "directory");
6295
+ const stat = await lstat(directory, { bigint: true });
6296
+ const uid = process.getuid?.();
6297
+ if (!stat.isDirectory() || (process.platform === "win32" ? !await windowsOwnerOnly(directory, "directory") : uid === void 0 || stat.uid !== BigInt(uid) || (stat.mode & 63n) !== 0n) || await realpath(directory) !== directory) fail("ARTIFACT_OUTPUT_UNSAFE");
6298
+ return directory;
6299
+ }
6300
+ /** Missing maps are recoverable from a current approval; malformed maps are not silently trusted. */
6301
+ async function readBundleIdentityMap(root, bundleId) {
6302
+ validBundleId(bundleId);
6303
+ const directory = await identityDirectory(root);
6304
+ const path = join(directory, `b-${bundleId}.json`);
6305
+ let before;
6350
6306
  try {
6351
- if (titlePlan) {
6352
- const seeds = await processing.gitNames(identity.path === null ? [] : [identity.path], signal);
6353
- for (const name of seeds.names) preparation.gitName(name);
6307
+ before = await lstat(path, { bigint: true });
6308
+ } catch (error) {
6309
+ if (filesystemCode(error) === "ENOENT") return null;
6310
+ throw error;
6311
+ }
6312
+ const uid = process.getuid?.();
6313
+ if (!before.isFile() || (process.platform === "win32" ? !await windowsOwnerOnly(path, "file") : uid === void 0 || before.uid !== BigInt(uid) || (before.mode & 63n) !== 0n)) fail("ARTIFACT_OUTPUT_UNSAFE");
6314
+ if (before.size > BigInt(8388608)) fail("ARTIFACT_METADATA_LIMIT");
6315
+ const handle = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);
6316
+ try {
6317
+ const opened = await handle.stat({ bigint: true });
6318
+ if (!sameFileVersion$2(before, opened)) fail("ARTIFACT_IDENTITY_MISMATCH");
6319
+ const bytes = Buffer.alloc(Number(opened.size));
6320
+ let offset = 0;
6321
+ while (offset < bytes.length) {
6322
+ const { bytesRead } = await handle.read(bytes, offset, bytes.length - offset, offset);
6323
+ if (bytesRead === 0) fail("ARTIFACT_INVALID_MANIFEST");
6324
+ offset += bytesRead;
6354
6325
  }
6355
- preparation.original(metadata.title, false);
6356
- bindings = preparation.finish();
6357
- const input = {
6358
- attemptId: "workspace-metadata",
6359
- sourceRef: "workspace-metadata",
6360
- unitId: "title",
6361
- text: metadata.title,
6362
- ...onMasks ? { captureMasks: true } : {}
6363
- };
6364
- async function* units() {
6365
- yield input;
6366
- }
6367
- let title;
6368
- for await (const output of processing.processor.transform(units(), withMandatoryCustomTerms(titlePlan ?? buildPlan([], [])), signal, bindings.session)) {
6369
- if (title !== void 0 || output.unitId !== input.unitId || output.sourceRef !== input.sourceRef || output.attemptId !== input.attemptId) fail("ARTIFACT_PROCESSING_FAILED");
6370
- title = output.text;
6371
- onMasks?.(input.text, output);
6326
+ if (!sameFileVersion$2(opened, await handle.stat({ bigint: true })) || !sameFileVersion$2(opened, await lstat(path, { bigint: true }))) fail("ARTIFACT_IDENTITY_MISMATCH");
6327
+ let text;
6328
+ try {
6329
+ text = new TextDecoder$1("utf-8", { fatal: true }).decode(bytes);
6330
+ } catch (error) {
6331
+ return fail("ARTIFACT_INVALID_MANIFEST", { cause: error });
6372
6332
  }
6373
- if (title === void 0) return fail("ARTIFACT_PROCESSING_FAILED");
6374
- return {
6375
- ...metadata,
6376
- title
6377
- };
6333
+ const map = parseIdentityMap(strictJson(text, maximumBundleIdentityMapBytes, 5e4));
6334
+ if (map.bundleId !== bundleId) fail("ARTIFACT_INVALID_MANIFEST");
6335
+ return map;
6378
6336
  } finally {
6379
- bindings?.close();
6380
- preparation.close();
6337
+ await handle.close();
6381
6338
  }
6382
6339
  }
6383
- //#endregion
6384
- //#region packages/artifact/src/configured/journey/metadata-spans.ts
6385
- /** Raw semantic boundaries expand over actual static replacements; static text is never restored. */
6386
- function metadataOutputSpans(text, masks, semantic) {
6387
- if (!semantic) return [];
6388
- if (semantic.textSha256 !== createHash("sha256").update(text).digest("hex") || semantic.spans.length > 5e4) fail("ARTIFACT_PROCESSING_MISMATCH");
6389
- const ordered = masks.toSorted((a, b) => a.inputRange.start - b.inputRange.start);
6390
- const map = (position, edge) => {
6391
- let delta = 0;
6392
- for (const mask of ordered) {
6393
- if (position <= mask.inputRange.start) break;
6394
- if (position < mask.inputRange.end) return edge === "start" ? mask.outputRange.start : mask.outputRange.end;
6395
- delta += mask.replacement.length - (mask.inputRange.end - mask.inputRange.start);
6340
+ /** Publish before the corresponding ZIP; retained maps are never removed automatically. */
6341
+ async function writeBundleIdentityMap(root, map) {
6342
+ const validated = parseIdentityMap(map);
6343
+ const text = encoded(validated);
6344
+ const directory = await identityDirectory(root);
6345
+ await syncDirectory(root);
6346
+ const finalPath = join(directory, `b-${validated.bundleId}.json`);
6347
+ const existing = await readBundleIdentityMap(root, validated.bundleId);
6348
+ if (existing) {
6349
+ if (encoded(existing) !== text) fail("ARTIFACT_DESTINATION_EXISTS");
6350
+ return;
6351
+ }
6352
+ const tempPath = join(directory, `.sess-pilot-b-${randomUUID()}.part`);
6353
+ const handle = await openPrivateFile(tempPath, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY | constants.O_NOFOLLOW, 384);
6354
+ try {
6355
+ const stat = await handle.stat({ bigint: true });
6356
+ const uid = process.getuid?.();
6357
+ if (!stat.isFile() || (process.platform === "win32" ? !await windowsOwnerOnly(tempPath, "file") : uid === void 0 || stat.uid !== BigInt(uid) || (stat.mode & 63n) !== 0n)) fail("ARTIFACT_OUTPUT_UNSAFE");
6358
+ await handle.writeFile(text);
6359
+ await handle.sync();
6360
+ try {
6361
+ await link(tempPath, finalPath);
6362
+ } catch (error) {
6363
+ if (filesystemCode(error) !== "EEXIST") throw error;
6364
+ const raced = await readBundleIdentityMap(root, validated.bundleId);
6365
+ if (!raced || encoded(raced) !== text) fail("ARTIFACT_DESTINATION_EXISTS");
6396
6366
  }
6397
- return position + delta;
6398
- };
6399
- const mapped = semantic.spans.flatMap((span) => {
6400
- if (!Number.isSafeInteger(span.start) || !Number.isSafeInteger(span.end) || span.start < 0 || span.end <= span.start || span.end > text.length || !scalarBoundary(text, span.start) || !scalarBoundary(text, span.end)) fail("ARTIFACT_PROCESSING_MISMATCH");
6401
- const category = maskCategory(span.category);
6402
- const start = map(span.start, "start"), end = map(span.end, "end");
6403
- return start === end ? [] : [{
6404
- start,
6405
- end,
6406
- category
6407
- }];
6408
- }).sort((a, b) => a.start - b.start || b.end - a.end);
6409
- const result = [];
6410
- for (const span of mapped) {
6411
- const previous = result.at(-1);
6412
- if (previous && span.start < previous.end) {
6413
- const category = categoryOrder.indexOf(maskCategory(previous.category)) >= categoryOrder.indexOf(span.category) ? previous.category : span.category;
6414
- result[result.length - 1] = {
6415
- start: previous.start,
6416
- end: Math.max(previous.end, span.end),
6417
- category
6418
- };
6419
- } else result.push(span);
6367
+ await syncDirectory(directory);
6368
+ } finally {
6369
+ await handle.close();
6370
+ await unlink(tempPath);
6420
6371
  }
6421
- return result;
6422
6372
  }
6423
6373
  //#endregion
6424
- //#region packages/artifact/src/configured/journey/metadata-fields.ts
6425
- /** This accepts private raw proposals once. Safe strings must never be re-ingested as originals. */
6426
- async function processJourneyMetadataFields(request, signal = new AbortController().signal) {
6427
- const { workId, fields, processing, redactionPlan } = request;
6428
- if (!/^[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12}$/u.test(workId) || processing.staticExceptions !== void 0 && processing.staticExceptions.workId !== workId || fields.length > 16 || fields.some(({ text }) => !text.isWellFormed() || Buffer.byteLength(text) > 16384) || fields.reduce((sum, { text }) => sum + Buffer.byteLength(text), 0) > 65536) fail("ARTIFACT_INVALID_APPROVAL");
6429
- const results = [];
6430
- let bytes = 0;
6431
- for (const field of fields) {
6432
- checkAbort(signal);
6433
- if (field.semantic && field.processedSemantic) fail("ARTIFACT_INVALID_APPROVAL");
6434
- let staticMasks;
6435
- const output = await configuredWorkspaceMetadata({
6436
- title: field.text,
6437
- path: null,
6438
- pathHash: null,
6439
- remotes: [],
6440
- primaryRemoteHash: null,
6441
- challengeId: null
6442
- }, processing, signal, redactionPlan, (input, processed) => {
6443
- staticMasks = titleMasks(input, processed);
6444
- }, processing.replacementKey === void 0 ? void 0 : `work-metadata:${workId}`);
6445
- const masks = staticMasks ?? fail("ARTIFACT_PROCESSING_FAILED");
6446
- const spans = field.processedSemantic ? metadataOutputSpans(output.title, [], field.processedSemantic) : metadataOutputSpans(field.text, masks, field.semantic);
6447
- let text = output.title;
6448
- const transcripts = [];
6449
- if (spans.length) {
6450
- const markers = createSemanticMarkers(processing.replacementKey ?? fail("ARTIFACT_INVALID_APPROVAL"), workId);
6451
- try {
6452
- const inputSha256 = createHash("sha256").update(text).digest("hex");
6453
- const input = text;
6454
- text = replaceSemanticSpans(input, spans, markers, (span, replacement, start) => {
6455
- const contextStart = Math.max(0, span.start - 120);
6456
- transcripts.push({
6457
- pointer: "/title",
6458
- inputSha256,
6459
- inputRange: {
6460
- start: span.start,
6461
- end: span.end
6462
- },
6463
- outputRange: {
6464
- start,
6465
- end: start + replacement.length
6466
- },
6467
- replacement,
6468
- category: maskCategory(span.category),
6469
- context: {
6470
- start: contextStart,
6471
- text: input.slice(contextStart, Math.min(input.length, contextStart + 512, span.end + 120))
6472
- }
6473
- });
6474
- });
6475
- } finally {
6476
- markers.close();
6477
- }
6478
- }
6479
- bytes += Buffer.byteLength(text);
6480
- if (Buffer.byteLength(text) > 32768 || bytes > 65536) fail("ARTIFACT_METADATA_LIMIT");
6481
- const outputSha256 = createHash("sha256").update(text).digest("hex");
6482
- results.push({
6483
- text,
6484
- staticMasks: masks,
6485
- semanticTranscript: transcripts.map((item) => ({
6486
- ...item,
6487
- outputSha256
6488
- }))
6489
- });
6490
- }
6491
- return results;
6374
+ //#region packages/artifact/src/collection/identity/hash.ts
6375
+ /** Hash the private canonical path under an OS-installation namespace. */
6376
+ function hashWorkspacePath(normalizedPath, environmentId) {
6377
+ if (!/^[0-9a-f]{64}$/.test(environmentId)) throw new Error("ARTIFACT_ENVIRONMENT_UNAVAILABLE");
6378
+ return createHash("sha256").update("sess-pilot-workspace-path-v2\0").update(environmentId).update("\0").update(normalizedPath).digest("hex");
6379
+ }
6380
+ /** Keep the installation identifier out of the distributable bundle. */
6381
+ function installationEnvironmentId(kind, installationId) {
6382
+ if (!kind || !installationId) throw new Error("ARTIFACT_ENVIRONMENT_UNAVAILABLE");
6383
+ return createHash("sha256").update("sess-pilot-workspace-environment-v2\0").update(kind).update("\0").update(installationId).digest("hex");
6492
6384
  }
6493
6385
  //#endregion
6494
- //#region packages/artifact/src/configured/output/metadata.ts
6495
- async function updateOutputWorkMetadata(text, manifest, request, signal, onTitleMasks) {
6496
- const work = parseConfiguredWorkMetadata(strictJson(text, metadataLimitBytes));
6497
- if (work.id !== manifest.work.id) fail("ARTIFACT_INVALID_MANIFEST");
6498
- const update = request.metadata;
6499
- if (!update) return text;
6500
- if ((update.titleSemantic || update.titleProcessedSemantic) && update.title === void 0) fail("ARTIFACT_INVALID_APPROVAL");
6501
- let title = work.title;
6502
- if (update.cachedTitle) {
6503
- if (update.title !== void 0 || update.titleSemantic || update.titleProcessedSemantic) fail("ARTIFACT_INVALID_APPROVAL");
6504
- const cached = update.cachedTitle;
6505
- const sha256 = createHash("sha256").update(cached.text).digest("hex");
6506
- if (sha256 !== cached.semantic.textSha256) fail("ARTIFACT_PROCESSING_MISMATCH");
6507
- const markers = createSemanticMarkers(request.replacementKey, request.workId);
6508
- const transcripts = [];
6509
- try {
6510
- title = maskOutputField({
6511
- pointer: "/title",
6512
- text: cached.text,
6513
- sha256
6514
- }, cached.semantic.spans, markers, { bytes: 0 }, (value) => transcripts.push(value));
6515
- } finally {
6516
- markers.close();
6517
- }
6518
- onTitleMasks?.({
6519
- text: title,
6520
- staticMasks: cached.staticMasks,
6521
- semanticTranscript: transcripts
6522
- });
6523
- } else if (update.title !== void 0) {
6524
- if (!update.title.trim() || Buffer.byteLength(update.title) > 16384) fail("ARTIFACT_INVALID_APPROVAL");
6525
- const treatment = manifest.configuration.definitions.find((item) => item.id === manifest.sessions[0]?.treatmentId) ?? fail("ARTIFACT_INVALID_MANIFEST");
6526
- const metadata = (await processJourneyMetadataFields({
6527
- workId: manifest.work.id,
6528
- fields: [{
6529
- text: update.title,
6530
- ...update.titleSemantic ? { semantic: update.titleSemantic } : {},
6531
- ...update.titleProcessedSemantic ? { processedSemantic: update.titleProcessedSemantic } : {}
6532
- }],
6533
- processing: {
6534
- ...request.processing,
6535
- replacementKey: request.replacementKey
6536
- },
6537
- redactionPlan: treatment.redactionPlan
6538
- }, signal))[0] ?? fail("ARTIFACT_PROCESSING_FAILED");
6539
- title = metadata.text;
6540
- onTitleMasks?.(metadata);
6386
+ //#region packages/artifact/src/collection/identity/wsl.ts
6387
+ async function isWsl() {
6388
+ try {
6389
+ return /microsoft|wsl/i.test(await readFile("/proc/sys/kernel/osrelease", "utf8"));
6390
+ } catch {
6391
+ return false;
6541
6392
  }
6542
- const changed = parseConfiguredWorkMetadata({
6543
- ...work,
6544
- title,
6545
- access: update.access ?? work.access
6546
- });
6547
- return JSON.stringify(changed);
6548
6393
  }
6549
6394
  //#endregion
6550
- //#region packages/artifact/src/configured/output/read.ts
6551
- async function verifiedMetadata(entry, description, signal) {
6552
- const text = await readMetadata(entry, signal);
6553
- if (Buffer.byteLength(text) !== description.byteLength || createHash("sha256").update(text).digest("hex") !== description.sha256) fail("ARTIFACT_INVALID_ARCHIVE");
6554
- return strictJson(text, metadataLimitBytes);
6395
+ //#region packages/artifact/src/collection/identity/path.ts
6396
+ const execute$1 = promisify(execFile);
6397
+ const unavailable$1 = () => fail("ARTIFACT_ENVIRONMENT_UNAVAILABLE");
6398
+ function pathPart(value) {
6399
+ if (value.length === 0 || Buffer.byteLength(value, "utf8") > 16384 || Array.from(value).some((character) => {
6400
+ const code = character.charCodeAt(0);
6401
+ return code < 32 || code === 127;
6402
+ })) return unavailable$1();
6403
+ return value;
6555
6404
  }
6556
- async function readConfiguredOutputInfo(input, signal = new AbortController().signal) {
6557
- const verified = await checkFrozenOutput(input, signal);
6558
- const archive = await openCheckedOutput(input, verified.checked, signal);
6559
- const cleanup = createCleanup();
6560
- try {
6561
- if (archive.manifestText !== verified.manifestText) fail("ARTIFACT_PROCESSING_MISMATCH");
6562
- const path = verified.manifest.work.metadataPath;
6563
- const description = verified.manifest.entries.find((entry) => entry.entryPath === path) ?? fail("ARTIFACT_INVALID_MANIFEST");
6564
- const work = parseConfiguredWorkMetadata(await verifiedMetadata(archive.entries.get(path) ?? fail("ARTIFACT_INVALID_ARCHIVE"), description, signal));
6565
- if (work.id !== verified.manifest.work.id) fail("ARTIFACT_INVALID_MANIFEST");
6566
- const sources = [];
6567
- for (const source of verified.manifest.sourceWorkspaces) {
6568
- const metadata = validateConfiguredSourceMetadata(await verifiedMetadata(archive.entries.get(source.metadataPath) ?? fail("ARTIFACT_INVALID_ARCHIVE"), verified.manifest.entries.find((candidate) => candidate.entryPath === source.metadataPath) ?? fail("ARTIFACT_INVALID_MANIFEST"), signal), source);
6569
- sources.push({
6570
- id: source.id,
6571
- pathHash: metadata.pathHash,
6572
- remoteHashes: metadata.remoteHashes,
6573
- primaryRemoteHash: metadata.primaryRemoteHash,
6574
- ...source.challengeId === void 0 ? {} : { challengeId: source.challengeId }
6575
- });
6576
- }
6577
- return {
6578
- manifest: verified.manifest,
6579
- work,
6580
- checked: verified.checked,
6581
- sources,
6582
- createdAt: verified.manifest.createdAt,
6583
- sessionCount: verified.manifest.sessions.length
6584
- };
6585
- } catch (error) {
6586
- cleanup.failed(error);
6587
- throw error;
6588
- } finally {
6589
- await cleanup.run(() => archive.close());
6405
+ function wslUnc(path) {
6406
+ const match = /^\\\\(?:wsl\.localhost|wsl\$)\\([^\\]+)(?:\\(.*))?$/i.exec(path);
6407
+ if (!match) return null;
6408
+ const distro = pathPart(match[1] ?? "").toLowerCase();
6409
+ const remainder = (match[2] ?? "").replaceAll("\\", "/");
6410
+ return `wsl:${encodeURIComponent(distro)}:${posix.normalize(`/${remainder}`)}`;
6411
+ }
6412
+ /** Canonical path is private input to the digest and is never written to the bundle. */
6413
+ function normalizeWindowsWorkspacePath(rawPath) {
6414
+ pathPart(rawPath);
6415
+ const normalized = win32.normalize(rawPath);
6416
+ const wslPath = wslUnc(normalized);
6417
+ if (wslPath !== null) return wslPath;
6418
+ const drive = /^([a-zA-Z]):\\(.*)$/.exec(normalized);
6419
+ if (drive) return `win-drive:${(drive[1] ?? "").toLowerCase()}:${posix.normalize(`/${(drive[2] ?? "").replaceAll("\\", "/")}`)}`;
6420
+ const share = /^\\\\([^\\]+)\\([^\\]+)(?:\\(.*))?$/.exec(normalized);
6421
+ if (share) {
6422
+ const server = encodeURIComponent(pathPart(share[1] ?? "").toLowerCase());
6423
+ const name = encodeURIComponent(pathPart(share[2] ?? "").toLowerCase());
6424
+ const remainder = (share[3] ?? "").replaceAll("\\", "/");
6425
+ return `win-unc:${server}/${name}:${posix.normalize(`/${remainder}`)}`;
6590
6426
  }
6427
+ return unavailable$1();
6591
6428
  }
6592
- /** Model-safe rows only: read a digest-bound static primary, never its original source. */
6593
- async function* readConfiguredOutputRows(input, signal = new AbortController().signal) {
6594
- const verified = await checkFrozenOutput(input, signal);
6595
- const archive = await openCheckedOutput(input, verified.checked, signal);
6596
- const cleanup = createCleanup();
6429
+ function normalizePosixWorkspacePath(rawPath) {
6430
+ pathPart(rawPath);
6431
+ if (!posix.isAbsolute(rawPath)) return unavailable$1();
6432
+ return `posix:${posix.normalize(rawPath)}`;
6433
+ }
6434
+ async function wslWindowsPath(rawPath, signal) {
6435
+ checkAbort(signal);
6436
+ pathPart(rawPath);
6437
+ if (!posix.isAbsolute(rawPath)) return unavailable$1();
6597
6438
  try {
6598
- if (archive.manifestText !== verified.manifestText) fail("ARTIFACT_PROCESSING_MISMATCH");
6599
- const descriptions = new Map(verified.manifest.entries.map((entry) => [entry.entryPath, entry]));
6600
- for (const session of verified.manifest.sessions) for (const part of session.parts) {
6601
- const spool = await spoolFacts(archive.entries.get(part.dataPath) ?? fail("ARTIFACT_INVALID_ARCHIVE"), descriptions.get(part.dataPath) ?? fail("ARTIFACT_INVALID_MANIFEST"), signal);
6602
- const partCleanup = createCleanup();
6603
- try {
6604
- await archive.fence();
6605
- let recordIndex = 0;
6606
- for await (const text of spool.lines) {
6607
- checkAbort(signal);
6608
- if (recordIndex >= part.retainedRecordCount) fail("ARTIFACT_INVALID_ARCHIVE");
6609
- yield {
6610
- entryPath: part.dataPath,
6611
- recordIndex,
6612
- archiveSessionId: session.id,
6613
- sourceId: part.sourceId,
6614
- harness: session.harness,
6615
- native: part.native,
6616
- text,
6617
- rowSha256: createHash("sha256").update(text).digest("hex")
6618
- };
6619
- recordIndex++;
6620
- }
6621
- if (recordIndex !== part.retainedRecordCount) fail("ARTIFACT_INVALID_ARCHIVE");
6622
- } catch (error) {
6623
- partCleanup.failed(error);
6624
- throw error;
6625
- } finally {
6626
- await partCleanup.run(() => spool.lines.return(void 0), () => spool.close());
6627
- }
6628
- }
6629
- } catch (error) {
6630
- cleanup.failed(error);
6631
- throw error;
6632
- } finally {
6633
- await cleanup.run(() => archive.close());
6439
+ const { stdout } = await execute$1("wslpath", ["-w", rawPath], {
6440
+ encoding: "utf8",
6441
+ maxBuffer: 32768,
6442
+ timeout: 15e3,
6443
+ windowsHide: true,
6444
+ signal
6445
+ });
6446
+ checkAbort(signal);
6447
+ return stdout.replace(/\r?\n$/, "");
6448
+ } catch {
6449
+ checkAbort(signal);
6450
+ return unavailable$1();
6451
+ }
6452
+ }
6453
+ /** Translate Windows/WSL aliases lexically, including paths that no longer exist. */
6454
+ async function normalizeWorkspacePath(rawPath, signal) {
6455
+ checkAbort(signal);
6456
+ if (/^(?:[A-Za-z]:[\\/]|\\\\)/u.test(rawPath)) return normalizeWindowsWorkspacePath(rawPath);
6457
+ if (platform() === "win32") {
6458
+ const wslDrive = /^\/mnt\/([A-Za-z])(?:\/(.*))?$/u.exec(rawPath);
6459
+ if (wslDrive) return normalizeWindowsWorkspacePath(`${wslDrive[1]}:\\${(wslDrive[2] ?? "").replaceAll("/", "\\")}`);
6460
+ return normalizePosixWorkspacePath(rawPath);
6634
6461
  }
6462
+ if (platform() === "darwin") return normalizePosixWorkspacePath(rawPath);
6463
+ if (platform() !== "linux") return unavailable$1();
6464
+ const wsl = await isWsl();
6465
+ checkAbort(signal);
6466
+ if (wsl) return normalizeWindowsWorkspacePath(await wslWindowsPath(rawPath, signal));
6467
+ return normalizePosixWorkspacePath(rawPath);
6635
6468
  }
6636
6469
  //#endregion
6637
- //#region packages/artifact/src/configured/review/parse.ts
6638
- const digest$2 = (text) => createHash("sha256").update(text).digest("hex");
6639
- const hash$6 = (value) => {
6640
- const text = string(value);
6641
- if (!/^[a-f0-9]{64}$/u.test(text)) fail("ARTIFACT_INVALID_MANIFEST");
6642
- return text;
6643
- };
6644
- const pointer$3 = (value) => {
6645
- const text = string(value);
6646
- if (!text.startsWith("/") || /~(?:[^01]|$)/u.test(text)) fail("ARTIFACT_INVALID_MANIFEST");
6647
- return text;
6648
- };
6649
- const range$2 = (value) => {
6650
- const v = record$1(value);
6651
- keys(v, ["start", "end"]);
6652
- const start = integer(v["start"]), end = integer(v["end"]);
6653
- if (end <= start) fail("ARTIFACT_INVALID_MANIFEST");
6654
- return {
6655
- start,
6656
- end
6657
- };
6658
- };
6659
- function checkedRanges(value, length) {
6660
- const ranges = array(value, range$2);
6661
- let end = 0;
6662
- for (const r of ranges) {
6663
- if (r.start < end || r.end > length) fail("ARTIFACT_INVALID_MANIFEST");
6664
- end = r.end;
6470
+ //#region packages/artifact/src/collection/identity/environment.ts
6471
+ const execute = promisify(execFile);
6472
+ const unavailable = () => fail("ARTIFACT_ENVIRONMENT_UNAVAILABLE");
6473
+ async function run(file, args, signal) {
6474
+ checkAbort(signal);
6475
+ try {
6476
+ const { stdout } = await execute(file, [...args], {
6477
+ encoding: "utf8",
6478
+ maxBuffer: 32768,
6479
+ timeout: 15e3,
6480
+ windowsHide: true,
6481
+ signal
6482
+ });
6483
+ checkAbort(signal);
6484
+ return stdout.trim();
6485
+ } catch {
6486
+ checkAbort(signal);
6487
+ return unavailable();
6665
6488
  }
6666
- return ranges;
6667
6489
  }
6668
- function rowRanges(value, fields) {
6669
- const ranges = array(value, (value) => value);
6670
- if (ranges.length !== fields.length) fail("ARTIFACT_INVALID_MANIFEST");
6671
- return ranges.map((value, index) => {
6672
- return checkedRanges(value, (fields[index] ?? fail("ARTIFACT_INVALID_MANIFEST")).text.length);
6673
- });
6490
+ function identifier(value, pattern) {
6491
+ const id = value.trim().toLowerCase();
6492
+ if (id.length > 128 || !pattern.test(id) || /^0+$/.test(id.replaceAll("-", ""))) return unavailable();
6493
+ return id;
6674
6494
  }
6675
- function mask(value) {
6676
- const v = record$1(value);
6677
- keys(v, [
6678
- "inputRange",
6679
- "outputRange",
6680
- "replacement",
6681
- "stepId",
6682
- "node",
6683
- "ruleId"
6684
- ]);
6685
- const node = record$1(v["node"]);
6686
- keys(node, ["id", "version"]);
6687
- const output = record$1(v["outputRange"]);
6688
- keys(output, ["start", "end"]);
6689
- const start = integer(output["start"]), end = integer(output["end"]);
6690
- const replacement = string(v["replacement"]);
6691
- if (end < start || end - start !== replacement.length) fail("ARTIFACT_INVALID_MANIFEST");
6692
- return {
6693
- inputRange: range$2(v["inputRange"]),
6694
- outputRange: {
6695
- start,
6696
- end
6697
- },
6698
- replacement,
6699
- stepId: string(v["stepId"]),
6700
- node: {
6701
- id: string(node["id"]),
6702
- version: string(node["version"])
6703
- },
6704
- ruleId: string(v["ruleId"])
6705
- };
6495
+ async function windowsInstallationId() {
6496
+ const script = [
6497
+ "$ErrorActionPreference='Stop'",
6498
+ "$id=(Get-ItemProperty -Path 'HKLM:\\SOFTWARE\\Microsoft\\Cryptography').MachineGuid",
6499
+ "if ([string]::IsNullOrWhiteSpace($id)) { exit 2 }",
6500
+ "[Console]::Out.WriteLine($id)"
6501
+ ].join(";");
6502
+ return identifier(await run("powershell.exe", [
6503
+ "-NoProfile",
6504
+ "-NonInteractive",
6505
+ "-EncodedCommand",
6506
+ Buffer.from(script, "utf16le").toString("base64")
6507
+ ]), /^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/);
6706
6508
  }
6707
- function field(value) {
6708
- const v = record$1(value);
6709
- keys(v, [
6710
- "pointer",
6711
- "cleanedPointer",
6712
- "originalPointer",
6713
- ...v["originalRange"] === void 0 ? [] : ["originalRange"],
6714
- ...v["originalFieldHash"] === void 0 ? [] : ["originalFieldHash"],
6715
- ...v["innerPointer"] === void 0 ? [] : ["innerPointer"],
6716
- ...v["scalarKind"] === void 0 ? [] : ["scalarKind"],
6717
- "role",
6718
- "text",
6719
- "fieldHash",
6720
- "staticMasks",
6721
- "nonPathMasks",
6722
- "protectedRanges",
6723
- ...v["customRanges"] === void 0 ? [] : ["customRanges"]
6509
+ async function linuxInstallationId() {
6510
+ try {
6511
+ return identifier(await readFile("/etc/machine-id", "utf8"), /^[0-9a-f]{32}$/);
6512
+ } catch {
6513
+ return unavailable();
6514
+ }
6515
+ }
6516
+ async function macInstallationId() {
6517
+ const plist = await run("diskutil", [
6518
+ "info",
6519
+ "-plist",
6520
+ "/"
6724
6521
  ]);
6725
- const role = v["role"];
6726
- if (role !== "user" && role !== "assistant" && role !== "tool-output") return fail("ARTIFACT_INVALID_MANIFEST");
6727
- const text = string(v["text"]), fieldHash = hash$6(v["fieldHash"]);
6728
- const scalarKind = v["scalarKind"];
6729
- if (scalarKind !== void 0 && scalarKind !== "literal" && scalarKind !== "structure" && scalarKind !== "container") return fail("ARTIFACT_INVALID_MANIFEST");
6730
- if (digest$2(text) !== fieldHash) fail("ARTIFACT_PROCESSING_MISMATCH");
6731
- const result = {
6732
- pointer: pointer$3(v["pointer"]),
6733
- cleanedPointer: pointer$3(v["cleanedPointer"]),
6734
- originalPointer: pointer$3(v["originalPointer"]),
6735
- ...v["originalRange"] === void 0 ? {} : { originalRange: range$2(v["originalRange"]) },
6736
- ...v["originalFieldHash"] === void 0 ? {} : { originalFieldHash: hash$6(v["originalFieldHash"]) },
6737
- ...v["innerPointer"] === void 0 ? {} : { innerPointer: pointer$3(v["innerPointer"]) },
6738
- ...scalarKind === void 0 ? {} : { scalarKind },
6739
- role,
6740
- text,
6741
- fieldHash,
6742
- staticMasks: array(v["staticMasks"], mask),
6743
- nonPathMasks: array(v["nonPathMasks"], mask),
6744
- protectedRanges: array(v["protectedRanges"], range$2),
6745
- ...v["customRanges"] === void 0 ? {} : { customRanges: array(v["customRanges"], range$2) }
6746
- };
6747
- if ([...result.staticMasks, ...result.nonPathMasks].some((m) => m.inputRange.end > text.length) || result.protectedRanges.some((r) => r.end > text.length) || result.customRanges?.some((r) => r.end > text.length) || result.originalRange === void 0 !== (result.originalFieldHash === void 0) || result.scalarKind === "structure" && (result.innerPointer !== void 0 || result.staticMasks.length > 0 || result.nonPathMasks.length > 0 || result.protectedRanges.length > 0 || (result.customRanges?.length ?? 0) > 0) || result.originalRange !== void 0 && (result.innerPointer !== void 0 || result.scalarKind !== void 0 || result.originalRange.end - result.originalRange.start !== text.length)) fail("ARTIFACT_INVALID_MANIFEST");
6748
- return result;
6522
+ const match = /<key>APFSVolumeGroupID<\/key>\s*<string>([0-9a-fA-F-]+)<\/string>/.exec(plist);
6523
+ if (!match) return unavailable();
6524
+ return identifier(match[1] ?? "", /^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/);
6749
6525
  }
6750
- function parsePrivateReviewRow(text) {
6751
- const v = record$1(strictJson(text, 67108864));
6752
- keys(v, [
6753
- "entryPath",
6754
- "recordIndex",
6755
- "sourcePartId",
6756
- "sourceRecordIndex",
6757
- "archiveSessionId",
6758
- "outputSha256",
6759
- "cleanedText",
6760
- "fields",
6761
- "aiRanges"
6762
- ]);
6763
- const parsedFields = array(v["fields"], field);
6764
- return {
6765
- entryPath: string(v["entryPath"]),
6766
- recordIndex: integer(v["recordIndex"]),
6767
- sourcePartId: string(v["sourcePartId"]),
6768
- sourceRecordIndex: integer(v["sourceRecordIndex"]),
6769
- archiveSessionId: string(v["archiveSessionId"]),
6770
- outputSha256: hash$6(v["outputSha256"]),
6771
- cleanedText: string(v["cleanedText"]),
6772
- fields: parsedFields,
6773
- aiRanges: rowRanges(v["aiRanges"], parsedFields)
6774
- };
6526
+ async function installationId() {
6527
+ if (platform() === "win32") return installationEnvironmentId("windows-installation", await windowsInstallationId());
6528
+ if (platform() === "darwin") return installationEnvironmentId("macos-apfs-installation", await macInstallationId());
6529
+ if (platform() === "linux") {
6530
+ if (await isWsl()) return installationEnvironmentId("windows-installation", await windowsInstallationId());
6531
+ return installationEnvironmentId("linux-installation", await linuxInstallationId());
6532
+ }
6533
+ return unavailable();
6775
6534
  }
6776
- function parsePrivateReviewManifest(text, entries, primary) {
6777
- const v = record$1(strictJson(text, manifestLimitBytes, manifestNodeLimit));
6778
- keys(v, [
6779
- "format",
6780
- "version",
6781
- "bundleId",
6782
- "workId",
6783
- "primary",
6784
- "entries",
6785
- "rows"
6786
- ]);
6787
- const bound = record$1(v["primary"]);
6788
- keys(bound, ["sha256", "archiveBytes"]);
6789
- if (v["bundleId"] !== primary.manifest.bundleId || v["workId"] !== primary.manifest.work.id || bound["sha256"] !== primary.sha256 || bound["archiveBytes"] !== primary.archiveBytes) fail("ARTIFACT_PROCESSING_MISMATCH");
6790
- const descriptions = array(v["entries"], (value) => {
6791
- const e = record$1(value);
6792
- keys(e, [
6793
- "entryPath",
6794
- "kind",
6795
- "representation",
6796
- "byteLength",
6797
- "sha256",
6798
- "rows"
6799
- ]);
6800
- return {
6801
- entryPath: string(e["entryPath"]),
6802
- kind: literal(e["kind"], "facts"),
6803
- representation: literal(e["representation"], "jsonl"),
6804
- byteLength: integer(e["byteLength"]),
6805
- sha256: hash$6(e["sha256"]),
6806
- rows: integer(e["rows"])
6807
- };
6535
+ let installationPromise;
6536
+ function waitForInstallation(id, signal) {
6537
+ if (!signal) return id;
6538
+ checkAbort(signal);
6539
+ return new Promise((resolve, reject) => {
6540
+ const onAbort = () => reject(/* @__PURE__ */ new Error("ARTIFACT_ABORTED"));
6541
+ signal.addEventListener("abort", onAbort, { once: true });
6542
+ id.then((value) => {
6543
+ signal.removeEventListener("abort", onAbort);
6544
+ resolve(value);
6545
+ }, (error) => {
6546
+ signal.removeEventListener("abort", onAbort);
6547
+ reject(error);
6548
+ });
6808
6549
  });
6809
- const expected = new Set(primary.manifest.sessions.flatMap((s) => s.parts.map((p) => `${p.dataPath}.review.jsonl`)));
6810
- let rows = 0;
6811
- for (const d of descriptions) {
6812
- const e = entries.get(d.entryPath);
6813
- if (!expected.delete(d.entryPath) || !e || e.compressionMethod !== 8 || e.uncompressedSize !== d.byteLength || d.byteLength > maximumPartBytes) fail("ARTIFACT_INVALID_ARCHIVE");
6814
- rows += d.rows;
6815
- }
6816
- if (expected.size || entries.size !== descriptions.length + 1 || rows !== integer(v["rows"])) fail("ARTIFACT_INVALID_ARCHIVE");
6817
- return {
6818
- format: literal(v["format"], "sess-pilot-private-b-review"),
6819
- version: literal(v["version"], 2),
6820
- bundleId: primary.manifest.bundleId,
6821
- workId: primary.manifest.work.id,
6822
- primary: {
6823
- sha256: primary.sha256,
6824
- archiveBytes: primary.archiveBytes
6825
- },
6826
- entries: descriptions,
6827
- rows
6828
- };
6550
+ }
6551
+ /** Same OS installation receives one stable namespace across process and state-dir changes. */
6552
+ async function resolveWorkspaceEnvironmentId(signal) {
6553
+ checkAbort(signal);
6554
+ if (!installationPromise) installationPromise = installationId().catch((error) => {
6555
+ installationPromise = void 0;
6556
+ throw error;
6557
+ });
6558
+ const id = await waitForInstallation(installationPromise, signal);
6559
+ checkAbort(signal);
6560
+ return id;
6829
6561
  }
6830
6562
  //#endregion
6831
- //#region packages/artifact/src/configured/review/native.ts
6832
- const reviewLimits = {
6833
- ...defaultLimits,
6834
- maxRecordBytes: maximumRecordBytes,
6835
- maxUnitBytes: maximumRecordBytes,
6836
- maxOutputRecordBytes: maximumRecordBytes
6837
- };
6838
- function reviewNative(text, signal) {
6839
- return parseNativeRecord(text, reviewLimits, signal);
6563
+ //#region packages/artifact/src/collection/identity/remote.ts
6564
+ /** Versioned canonical form shared by archive producers and downstream consumers. */
6565
+ function canonicalRemote(value) {
6566
+ const input = value.trim();
6567
+ if (!input || Buffer.byteLength(input) > 16384) return fail("ARTIFACT_UNSAFE_REMOTE");
6568
+ for (const character of input) {
6569
+ const code = character.charCodeAt(0);
6570
+ if (code < 32 || code === 127) return fail("ARTIFACT_UNSAFE_REMOTE");
6571
+ }
6572
+ if (input.startsWith("/") || /^[a-z]:[\\/]/i.test(input) || input.startsWith("\\\\")) return input.replaceAll("\\", "/");
6573
+ const scp = /^[a-z][a-z0-9+.-]*:\/\//i.test(input) ? null : /^(?:[^@/\s]+@)?(\[[^\]]+\]|[^/:\s]+):([^:].*)$/.exec(input);
6574
+ const candidate = scp?.[1] && scp[2] ? `ssh://${scp[1]}/${scp[2]}` : input;
6575
+ let url;
6576
+ try {
6577
+ url = new URL(candidate);
6578
+ } catch (error) {
6579
+ return fail("ARTIFACT_UNSAFE_REMOTE", { cause: error });
6580
+ }
6581
+ if (![
6582
+ "https:",
6583
+ "http:",
6584
+ "ssh:",
6585
+ "git:",
6586
+ "file:"
6587
+ ].includes(url.protocol)) fail("ARTIFACT_UNSAFE_REMOTE");
6588
+ url.username = "";
6589
+ url.password = "";
6590
+ url.search = "";
6591
+ url.hash = "";
6592
+ url.hostname = url.hostname.toLowerCase();
6593
+ if (url.protocol === "ssh:" && url.port === "22" || url.protocol === "git:" && url.port === "9418") url.port = "";
6594
+ if (url.protocol !== "file:") {
6595
+ if (!url.hostname) fail("ARTIFACT_UNSAFE_REMOTE");
6596
+ url.pathname = url.pathname.replace(/\/+$/, "").replace(/\.git$/, "");
6597
+ }
6598
+ return url.href;
6840
6599
  }
6841
- function emptyNativeStructure(node) {
6842
- if (node.kind === "literal") return false;
6843
- if (node.kind === "string") return node.value.length === 0;
6844
- return node.kind === "array" ? node.items.every(emptyNativeStructure) : node.properties.every((property) => emptyNativeStructure(property.value));
6600
+ function hashRemote(canonical) {
6601
+ return createHash("sha256").update("sess-pilot/git-remote/v1\0").update(canonical).digest("hex");
6845
6602
  }
6846
- function nativePointer(root, pointer) {
6847
- let node = root;
6848
- if (pointer === "") return node;
6849
- if (!pointer.startsWith("/") || /~(?:[^01]|$)/u.test(pointer)) fail("ARTIFACT_PROCESSING_MISMATCH");
6850
- for (const key of pointer.slice(1).split("/").map((part) => part.replaceAll("~1", "/").replaceAll("~0", "~"))) node = (node.kind === "object" ? node.properties.find((property) => property.key.value === key)?.value : node.kind === "array" && /^(?:0|[1-9]\d*)$/u.test(key) ? node.items[Number(key)] : void 0) ?? fail("ARTIFACT_PROCESSING_MISMATCH");
6851
- return node;
6603
+ //#endregion
6604
+ //#region packages/artifact/src/collection/identity/workspace.ts
6605
+ async function workspaceIdentity(workspace, signal) {
6606
+ checkAbort(signal);
6607
+ const pathHash = workspace.path === null ? null : hashWorkspacePath(await normalizeWorkspacePath(workspace.path, signal), await resolveWorkspaceEnvironmentId(signal));
6608
+ const remotes = workspace.remotes.map((remote) => {
6609
+ const url = canonicalRemote(remote);
6610
+ return {
6611
+ url,
6612
+ hash: hashRemote(url)
6613
+ };
6614
+ });
6615
+ const primaryRemoteHash = workspace.primaryRemote ? hashRemote(canonicalRemote(workspace.primaryRemote.locator)) : null;
6616
+ if (primaryRemoteHash !== null && !remotes.some((remote) => remote.hash === primaryRemoteHash)) fail("ARTIFACT_UNSAFE_REMOTE");
6617
+ const challengeId = await readChallengeId(workspace.path, signal);
6618
+ checkAbort(signal);
6619
+ return {
6620
+ title: workspace.title,
6621
+ path: workspace.path,
6622
+ pathHash,
6623
+ remotes,
6624
+ primaryRemoteHash,
6625
+ challengeId
6626
+ };
6852
6627
  }
6853
- /** Exact numeric-array lexemes for grouped geography, including targets decoded from native strings. */
6854
- function nativeContainerText(node, signal) {
6855
- if (node.kind !== "array") return void 0;
6856
- const numeric = (value) => {
6857
- signal.throwIfAborted();
6858
- return value.kind === "array" ? value.items.every(numeric) : value.kind === "literal" && Number.isFinite(Number(value.raw));
6628
+ function workspaceMetadata(identity) {
6629
+ return {
6630
+ version: 3,
6631
+ title: identity.title,
6632
+ pathHash: identity.pathHash,
6633
+ remoteHashes: identity.remotes.map((remote) => remote.hash),
6634
+ primaryRemoteHash: identity.primaryRemoteHash
6859
6635
  };
6860
- return numeric(node) ? renderNative(node, /* @__PURE__ */ new Map(), reviewLimits, signal).text : void 0;
6861
6636
  }
6862
- //#endregion
6863
- //#region packages/artifact/src/configured/review/read.ts
6864
- async function checkPrivateReviewProjection(file, primary, signal) {
6865
- const output = await checkFrozenOutput(primary, signal);
6866
- let manifest;
6637
+ function bundleIdentityMap(bundleId, identity) {
6867
6638
  return {
6868
- checked: await checkWrittenArchive(file.path, file.identity, void 0, (text, entries) => {
6869
- manifest = parsePrivateReviewManifest(text, entries, {
6870
- manifest: output.manifest,
6871
- sha256: primary.sha256,
6872
- archiveBytes: primary.archiveBytes
6873
- });
6874
- }, signal),
6875
- manifest: manifest ?? fail("ARTIFACT_INVALID_ARCHIVE"),
6876
- output: output.manifest
6639
+ format: "sess-pilot-bundle-identity-map",
6640
+ formatVersion: 1,
6641
+ bundleId,
6642
+ workspace: {
6643
+ path: identity.path,
6644
+ pathHash: identity.pathHash,
6645
+ remotes: identity.remotes,
6646
+ primaryRemoteHash: identity.primaryRemoteHash
6647
+ }
6877
6648
  };
6878
6649
  }
6879
- /** Internal reconstruction iterator; callers exposing model input must use the field-only iterator. */
6880
- async function* readPrivateReviewRows(request, signal) {
6881
- const { projection, primary } = request;
6882
- const verified = await checkPrivateReviewProjection(projection, primary, signal);
6883
- if (projection.primarySha256 !== primary.sha256 || projection.rows !== verified.manifest.rows) fail("ARTIFACT_PROCESSING_MISMATCH");
6884
- const archive = await openCheckedOutput(projection, verified.checked, signal);
6885
- const output = readConfiguredOutputRows(primary, signal);
6886
- const parts = new Map(verified.output.sessions.flatMap((session) => session.parts.map((part) => [part.dataPath, {
6887
- part,
6888
- sessionId: session.id
6889
- }])));
6890
- let next = await output.next();
6891
- const cleanup = createCleanup();
6650
+ //#endregion
6651
+ //#region packages/artifact/src/collection/producer/workspace-metadata.ts
6652
+ /** Workspace titles are emitted once, independently of per-session optional profiles. */
6653
+ async function configuredWorkspaceMetadata(identity, processing, signal, titlePlan, onMasks, replacementScope) {
6654
+ const metadata = workspaceMetadata(identity);
6655
+ const terms = processing.customTerms?.terms ?? [];
6656
+ if (terms.length === 0 && titlePlan === void 0) return metadata;
6657
+ const preparation = createSessionPreparation({
6658
+ environment: processing.environment,
6659
+ customTerms: terms,
6660
+ ...processing.staticExceptions === void 0 ? {} : { staticExceptions: processing.staticExceptions.values },
6661
+ ...processing.replacementKey === void 0 ? {} : { replacementKey: processing.replacementKey },
6662
+ ...replacementScope === void 0 ? {} : { replacementScope }
6663
+ }, signal);
6664
+ let bindings;
6892
6665
  try {
6893
- for (const description of verified.manifest.entries) {
6894
- const spool = await spoolFacts(archive.entries.get(description.entryPath) ?? fail("ARTIFACT_INVALID_ARCHIVE"), description, signal);
6895
- const partCleanup = createCleanup();
6896
- let rows = 0, last = -1;
6897
- try {
6898
- for await (const text of spool.lines) {
6899
- const row = parsePrivateReviewRow(text), part = parts.get(row.entryPath);
6900
- if (!part || part.part.native.role !== "main" || row.archiveSessionId !== part.sessionId || `${row.entryPath}.review.jsonl` !== description.entryPath || row.recordIndex <= last || row.recordIndex >= part.part.retainedRecordCount || row.sourceRecordIndex >= part.part.recordCount) fail("ARTIFACT_INVALID_ARCHIVE");
6901
- while (!next.done && (next.value.entryPath !== row.entryPath || next.value.recordIndex < row.recordIndex)) next = await output.next();
6902
- if (next.done || next.value.entryPath !== row.entryPath || next.value.recordIndex !== row.recordIndex || next.value.rowSha256 !== row.outputSha256) fail("ARTIFACT_PROCESSING_MISMATCH");
6903
- const root = reviewNative(row.cleanedText, signal), actual = reviewNative(next.value.text, signal), seen = /* @__PURE__ */ new Set();
6904
- for (const field of row.fields) {
6905
- const key = JSON.stringify([field.pointer, field.innerPointer ?? null]);
6906
- if (seen.has(key)) fail("ARTIFACT_PROCESSING_MISMATCH");
6907
- seen.add(key);
6908
- let source = nativePointer(root, field.cleanedPointer);
6909
- const target = nativePointer(actual, field.pointer), nativeLiteral = field.scalarKind === "literal" && field.innerPointer === void 0;
6910
- if (field.scalarKind === "container" && field.innerPointer === void 0 ? nativeContainerText(source, signal) === void 0 || !["array", "string"].includes(target.kind) : nativeLiteral ? source.kind !== "literal" || !["literal", "string"].includes(target.kind) : source.kind !== "string" || target.kind !== "string") return fail("ARTIFACT_PROCESSING_MISMATCH");
6911
- if (field.scalarKind === "structure") {
6912
- if (source.kind !== "string") return fail("ARTIFACT_PROCESSING_MISMATCH");
6913
- const structure = reviewNative(source.value, signal);
6914
- if (!["object", "array"].includes(structure.kind) || !emptyNativeStructure(structure)) fail("ARTIFACT_PROCESSING_MISMATCH");
6915
- }
6916
- if (field.innerPointer !== void 0) {
6917
- if (source.kind !== "string") return fail("ARTIFACT_PROCESSING_MISMATCH");
6918
- source = nativePointer(reviewNative(source.value, signal), field.innerPointer);
6919
- }
6920
- const text = field.scalarKind === "container" ? nativeContainerText(source, signal) : field.scalarKind === "literal" ? source.kind === "literal" ? source.raw : void 0 : source.kind === "string" ? source.value : void 0;
6921
- if (text === void 0 || text !== field.text || createHash("sha256").update(text).digest("hex") !== field.fieldHash) fail("ARTIFACT_PROCESSING_MISMATCH");
6922
- }
6923
- rows++;
6924
- last = row.recordIndex;
6925
- yield row;
6926
- }
6927
- if (rows !== description.rows) fail("ARTIFACT_INVALID_ARCHIVE");
6928
- } catch (error) {
6929
- partCleanup.failed(error);
6930
- throw error;
6931
- } finally {
6932
- await partCleanup.run(() => spool.lines.return(void 0), () => spool.close());
6933
- }
6934
- await archive.fence();
6666
+ if (titlePlan) {
6667
+ const seeds = await processing.gitNames(identity.path === null ? [] : [identity.path], signal);
6668
+ for (const name of seeds.names) preparation.gitName(name);
6935
6669
  }
6936
- } catch (error) {
6937
- cleanup.failed(error);
6938
- throw error;
6670
+ preparation.original(metadata.title, false);
6671
+ bindings = preparation.finish();
6672
+ const input = {
6673
+ attemptId: "workspace-metadata",
6674
+ sourceRef: "workspace-metadata",
6675
+ unitId: "title",
6676
+ text: metadata.title,
6677
+ ...onMasks ? { captureMasks: true } : {}
6678
+ };
6679
+ async function* units() {
6680
+ yield input;
6681
+ }
6682
+ let title;
6683
+ for await (const output of processing.processor.transform(units(), withMandatoryCustomTerms(titlePlan ?? buildPlan([], [])), signal, bindings.session)) {
6684
+ if (title !== void 0 || output.unitId !== input.unitId || output.sourceRef !== input.sourceRef || output.attemptId !== input.attemptId) fail("ARTIFACT_PROCESSING_FAILED");
6685
+ title = output.text;
6686
+ onMasks?.(input.text, output);
6687
+ }
6688
+ if (title === void 0) return fail("ARTIFACT_PROCESSING_FAILED");
6689
+ return {
6690
+ ...metadata,
6691
+ title
6692
+ };
6939
6693
  } finally {
6940
- await cleanup.run(() => output.return(void 0), () => archive.close());
6694
+ bindings?.close();
6695
+ preparation.close();
6941
6696
  }
6942
6697
  }
6943
6698
  //#endregion
6944
- //#region packages/artifact/src/configured/review/rules.ts
6945
- const generic = /* @__PURE__ */ new Set([
6946
- "src",
6947
- "lib",
6948
- "test",
6949
- "tests",
6950
- "docs",
6951
- "README.md",
6952
- "package.json",
6953
- "pnpm-lock.yaml",
6954
- "index.ts",
6955
- "main.ts",
6956
- "index.js",
6957
- ".claude.json",
6958
- ".codex",
6959
- "config.toml"
6960
- ]);
6961
- /** Dipper B v6.2 component policy, translated to native UTF-16 coordinates. */
6962
- function componentPaths(text, fullPath = false) {
6963
- const found = [];
6964
- for (const match of text.matchAll(/(?:\/Users\/|\/home\/|[A-Za-z]:\\Users\\)[^\r\n"'`<>[\];|]+/gu)) {
6965
- let raw = match[0];
6966
- const separator = raw.includes("\\") ? "\\" : "/";
6967
- raw = (raw.split(/\s+(?:&&|\|\||--\w|(?:and|then|with|to|from|is)\s)/u)[0] ?? "").replace(/[.,):\s]+$/u, "");
6968
- const quoted = [
6969
- "\"",
6970
- "'",
6971
- "`"
6972
- ].includes(text[match.index - 1] ?? ""), bracketed = /\[(?:project|workspace):\s*$/u.test(text.slice(0, match.index));
6973
- if (!quoted && !bracketed && !fullPath) {
6974
- const token = `Desktop${separator}Folders`;
6975
- raw = (raw.replace(`Desktop Folders${separator}`, token).split(/\s/u)[0] ?? "").replace(token, `Desktop Folders${separator}`);
6976
- }
6977
- const root = /^(?:\/Users\/|\/home\/|[A-Za-z]:\\Users\\)/u.exec(raw)?.[0];
6978
- if (!root) continue;
6979
- const parts = raw.slice(root.length).split(separator);
6980
- if (!parts[0] || /\s/u.test(parts[0])) continue;
6981
- let offset = root.length;
6982
- const coords = parts.map((value) => {
6983
- const range = {
6984
- value,
6985
- start: match.index + offset,
6986
- end: match.index + offset + value.length
6987
- };
6988
- offset += value.length + separator.length;
6989
- return range;
6990
- });
6991
- const first = coords[0];
6992
- if (!first) continue;
6993
- const components = [{
6994
- start: first.start,
6995
- end: first.end
6996
- }];
6997
- let project = -1;
6998
- if (parts.length > 1) {
6999
- if ([
7000
- "Desktop",
7001
- "Desktop Folders",
7002
- "Documents",
7003
- "Projects",
7004
- "workspace",
7005
- "workspaces",
7006
- "repos",
7007
- "code"
7008
- ].includes(parts[1] ?? "")) project = parts.length > 2 ? 2 : -1;
7009
- else if (!(parts[1] ?? "").startsWith(".")) project = 1;
7010
- }
7011
- for (let index = 1; index < coords.length; index++) {
7012
- const value = coords[index];
7013
- if (!value?.value || index === 1 && project === 2) continue;
7014
- if (index === project || !generic.has(value.value)) components.push({
7015
- start: value.start,
7016
- end: value.end
7017
- });
6699
+ //#region packages/artifact/src/configured/journey/metadata-spans.ts
6700
+ /** Raw semantic boundaries expand over actual static replacements; static text is never restored. */
6701
+ function metadataOutputSpans(text, masks, semantic) {
6702
+ if (!semantic) return [];
6703
+ if (semantic.textSha256 !== createHash("sha256").update(text).digest("hex") || semantic.spans.length > 5e4) fail("ARTIFACT_PROCESSING_MISMATCH");
6704
+ const ordered = masks.toSorted((a, b) => a.inputRange.start - b.inputRange.start);
6705
+ const map = (position, edge) => {
6706
+ let delta = 0;
6707
+ for (const mask of ordered) {
6708
+ if (position <= mask.inputRange.start) break;
6709
+ if (position < mask.inputRange.end) return edge === "start" ? mask.outputRange.start : mask.outputRange.end;
6710
+ delta += mask.replacement.length - (mask.inputRange.end - mask.inputRange.start);
7018
6711
  }
7019
- found.push({
7020
- start: match.index,
7021
- end: match.index + raw.length,
7022
- components
7023
- });
7024
- }
7025
- return found;
7026
- }
7027
- /** Only isolated low-information values inside an explicitly marked CLI example section. */
7028
- function helpSentinels(text) {
7029
- if (!/^Usage:/mu.test(text) || !/^Examples:/mu.test(text)) return [];
7030
- const begin = text.indexOf("Examples:"), end = text.indexOf("\nOptions:", begin), zone = text.slice(begin, end < 0 ? text.length : end), result = [];
7031
- for (const match of zone.matchAll(/\b(?:API_KEY|api_key|TOKEN|password)=(xxx|\.\.\.|<API_KEY>|<TOKEN>)(?=\s|$)/gu)) {
7032
- const value = match[1];
7033
- if (!value) continue;
7034
- const start = begin + match.index + match[0].lastIndexOf(value);
7035
- result.push({
6712
+ return position + delta;
6713
+ };
6714
+ const mapped = semantic.spans.flatMap((span) => {
6715
+ if (!Number.isSafeInteger(span.start) || !Number.isSafeInteger(span.end) || span.start < 0 || span.end <= span.start || span.end > text.length || !scalarBoundary(text, span.start) || !scalarBoundary(text, span.end)) fail("ARTIFACT_PROCESSING_MISMATCH");
6716
+ const category = maskCategory(span.category);
6717
+ const start = map(span.start, "start"), end = map(span.end, "end");
6718
+ return start === end ? [] : [{
7036
6719
  start,
7037
- end: start + value.length
7038
- });
6720
+ end,
6721
+ category
6722
+ }];
6723
+ }).sort((a, b) => a.start - b.start || b.end - a.end);
6724
+ const result = [];
6725
+ for (const span of mapped) {
6726
+ const previous = result.at(-1);
6727
+ if (previous && span.start < previous.end) {
6728
+ const category = categoryOrder.indexOf(maskCategory(previous.category)) >= categoryOrder.indexOf(span.category) ? previous.category : span.category;
6729
+ result[result.length - 1] = {
6730
+ start: previous.start,
6731
+ end: Math.max(previous.end, span.end),
6732
+ category
6733
+ };
6734
+ } else result.push(span);
7039
6735
  }
7040
6736
  return result;
7041
6737
  }
7042
6738
  //#endregion
7043
- //#region packages/artifact/src/configured/review/ranges.ts
7044
- function staticSpan(mask) {
7045
- return {
7046
- ...mask.inputRange,
7047
- category: staticMaskCategory(mask.node.id),
7048
- causes: [{
7049
- kind: "static",
7050
- range: mask.inputRange,
7051
- stepId: mask.stepId,
7052
- node: mask.node,
7053
- ruleId: mask.ruleId
7054
- }]
7055
- };
7056
- }
7057
- /** These are deterministic B rules, independent of a model's occurrence decisions. */
7058
- function policySpan(range, nodeId, ruleId) {
7059
- return {
7060
- ...range,
7061
- category: staticMaskCategory(nodeId),
7062
- causes: [{
7063
- kind: "static",
7064
- range,
7065
- node: {
7066
- id: nodeId,
7067
- version: "sesspilot-b-v1"
7068
- },
7069
- stepId: "sesspilot-b-v1",
7070
- ruleId
7071
- }]
7072
- };
7073
- }
7074
- function subtract(input, retained) {
7075
- return input.flatMap((range) => {
6739
+ //#region packages/artifact/src/configured/journey/metadata-fields.ts
6740
+ /** This accepts private raw proposals once. Safe strings must never be re-ingested as originals. */
6741
+ async function processJourneyMetadataFields(request, signal = new AbortController().signal) {
6742
+ const { workId, fields, processing, redactionPlan } = request;
6743
+ if (!/^[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12}$/u.test(workId) || processing.staticExceptions !== void 0 && processing.staticExceptions.workId !== workId || fields.length > 16 || fields.some(({ text }) => !text.isWellFormed() || Buffer.byteLength(text) > 16384) || fields.reduce((sum, { text }) => sum + Buffer.byteLength(text), 0) > 65536) fail("ARTIFACT_INVALID_APPROVAL");
6744
+ const results = [];
6745
+ let bytes = 0;
6746
+ for (const field of fields) {
6747
+ checkAbort(signal);
6748
+ if (field.semantic && field.processedSemantic) fail("ARTIFACT_INVALID_APPROVAL");
6749
+ let staticMasks;
6750
+ const output = await configuredWorkspaceMetadata({
6751
+ title: field.text,
6752
+ path: null,
6753
+ pathHash: null,
6754
+ remotes: [],
6755
+ primaryRemoteHash: null,
6756
+ challengeId: null
6757
+ }, processing, signal, redactionPlan, (input, processed) => {
6758
+ staticMasks = titleMasks(input, processed);
6759
+ }, processing.replacementKey === void 0 ? void 0 : `work-metadata:${workId}`);
6760
+ const masks = staticMasks ?? fail("ARTIFACT_PROCESSING_FAILED");
6761
+ const spans = field.processedSemantic ? metadataOutputSpans(output.title, [], field.processedSemantic) : metadataOutputSpans(field.text, masks, field.semantic);
6762
+ let text = output.title;
6763
+ const transcripts = [];
6764
+ if (spans.length) {
6765
+ const markers = createSemanticMarkers(processing.replacementKey ?? fail("ARTIFACT_INVALID_APPROVAL"), workId);
6766
+ try {
6767
+ const inputSha256 = createHash("sha256").update(text).digest("hex");
6768
+ const input = text;
6769
+ text = replaceSemanticSpans(input, spans, markers, (span, replacement, start) => {
6770
+ const contextStart = Math.max(0, span.start - 120);
6771
+ transcripts.push({
6772
+ pointer: "/title",
6773
+ inputSha256,
6774
+ inputRange: {
6775
+ start: span.start,
6776
+ end: span.end
6777
+ },
6778
+ outputRange: {
6779
+ start,
6780
+ end: start + replacement.length
6781
+ },
6782
+ replacement,
6783
+ category: maskCategory(span.category),
6784
+ context: {
6785
+ start: contextStart,
6786
+ text: input.slice(contextStart, Math.min(input.length, contextStart + 512, span.end + 120))
6787
+ }
6788
+ });
6789
+ });
6790
+ } finally {
6791
+ markers.close();
6792
+ }
6793
+ }
6794
+ bytes += Buffer.byteLength(text);
6795
+ if (Buffer.byteLength(text) > 32768 || bytes > 65536) fail("ARTIFACT_METADATA_LIMIT");
6796
+ const outputSha256 = createHash("sha256").update(text).digest("hex");
6797
+ results.push({
6798
+ text,
6799
+ staticMasks: masks,
6800
+ semanticTranscript: transcripts.map((item) => ({
6801
+ ...item,
6802
+ outputSha256
6803
+ }))
6804
+ });
6805
+ }
6806
+ return results;
6807
+ }
6808
+ //#endregion
6809
+ //#region packages/artifact/src/configured/output/metadata.ts
6810
+ async function updateOutputWorkMetadata(text, manifest, request, signal, onTitleMasks) {
6811
+ const work = parseConfiguredWorkMetadata(strictJson(text, metadataLimitBytes));
6812
+ if (work.id !== manifest.work.id) fail("ARTIFACT_INVALID_MANIFEST");
6813
+ const update = request.metadata;
6814
+ if (!update) return text;
6815
+ if ((update.titleSemantic || update.titleProcessedSemantic) && update.title === void 0) fail("ARTIFACT_INVALID_APPROVAL");
6816
+ let title = work.title;
6817
+ if (update.cachedTitle) {
6818
+ if (update.title !== void 0 || update.titleSemantic || update.titleProcessedSemantic) fail("ARTIFACT_INVALID_APPROVAL");
6819
+ const cached = update.cachedTitle;
6820
+ const sha256 = createHash("sha256").update(cached.text).digest("hex");
6821
+ if (sha256 !== cached.semantic.textSha256) fail("ARTIFACT_PROCESSING_MISMATCH");
6822
+ const markers = createSemanticMarkers(request.replacementKey, request.workId);
6823
+ const transcripts = [];
6824
+ try {
6825
+ rejectSemanticMarkerPrefix(cached.text, markers);
6826
+ title = maskOutputField({
6827
+ pointer: "/title",
6828
+ text: cached.text,
6829
+ sha256
6830
+ }, cached.semantic.spans, {
6831
+ ...markers,
6832
+ marker: () => "[hidden]"
6833
+ }, { bytes: 0 }, (value) => transcripts.push(value));
6834
+ } finally {
6835
+ markers.close();
6836
+ }
6837
+ onTitleMasks?.({
6838
+ text: title,
6839
+ staticMasks: cached.staticMasks,
6840
+ semanticTranscript: transcripts
6841
+ });
6842
+ } else if (update.title !== void 0) {
6843
+ if (!update.title.trim() || Buffer.byteLength(update.title) > 16384) fail("ARTIFACT_INVALID_APPROVAL");
6844
+ const treatment = manifest.configuration.definitions.find((item) => item.id === manifest.sessions[0]?.treatmentId) ?? fail("ARTIFACT_INVALID_MANIFEST");
6845
+ const metadata = (await processJourneyMetadataFields({
6846
+ workId: manifest.work.id,
6847
+ fields: [{
6848
+ text: update.title,
6849
+ ...update.titleSemantic ? { semantic: update.titleSemantic } : {},
6850
+ ...update.titleProcessedSemantic ? { processedSemantic: update.titleProcessedSemantic } : {}
6851
+ }],
6852
+ processing: {
6853
+ ...request.processing,
6854
+ replacementKey: request.replacementKey
6855
+ },
6856
+ redactionPlan: treatment.redactionPlan
6857
+ }, signal))[0] ?? fail("ARTIFACT_PROCESSING_FAILED");
6858
+ title = metadata.text;
6859
+ onTitleMasks?.(metadata);
6860
+ }
6861
+ const changed = parseConfiguredWorkMetadata({
6862
+ ...work,
6863
+ title,
6864
+ access: update.access ?? work.access
6865
+ });
6866
+ return JSON.stringify(changed);
6867
+ }
6868
+ //#endregion
6869
+ //#region packages/artifact/src/configured/output/read.ts
6870
+ async function verifiedMetadata(entry, description, signal) {
6871
+ const text = await readMetadata(entry, signal);
6872
+ if (Buffer.byteLength(text) !== description.byteLength || createHash("sha256").update(text).digest("hex") !== description.sha256) fail("ARTIFACT_INVALID_ARCHIVE");
6873
+ return strictJson(text, metadataLimitBytes);
6874
+ }
6875
+ async function readConfiguredOutputInfo(input, signal = new AbortController().signal) {
6876
+ const verified = await checkFrozenOutput(input, signal);
6877
+ const archive = await openCheckedOutput(input, verified.checked, signal);
6878
+ const cleanup = createCleanup();
6879
+ try {
6880
+ if (archive.manifestText !== verified.manifestText) fail("ARTIFACT_PROCESSING_MISMATCH");
6881
+ const path = verified.manifest.work.metadataPath;
6882
+ const description = verified.manifest.entries.find((entry) => entry.entryPath === path) ?? fail("ARTIFACT_INVALID_MANIFEST");
6883
+ const work = parseConfiguredWorkMetadata(await verifiedMetadata(archive.entries.get(path) ?? fail("ARTIFACT_INVALID_ARCHIVE"), description, signal));
6884
+ if (work.id !== verified.manifest.work.id) fail("ARTIFACT_INVALID_MANIFEST");
6885
+ const sources = [];
6886
+ for (const source of verified.manifest.sourceWorkspaces) {
6887
+ const metadata = validateConfiguredSourceMetadata(await verifiedMetadata(archive.entries.get(source.metadataPath) ?? fail("ARTIFACT_INVALID_ARCHIVE"), verified.manifest.entries.find((candidate) => candidate.entryPath === source.metadataPath) ?? fail("ARTIFACT_INVALID_MANIFEST"), signal), source);
6888
+ sources.push({
6889
+ id: source.id,
6890
+ pathHash: metadata.pathHash,
6891
+ remoteHashes: metadata.remoteHashes,
6892
+ primaryRemoteHash: metadata.primaryRemoteHash,
6893
+ ...source.challengeId === void 0 ? {} : { challengeId: source.challengeId }
6894
+ });
6895
+ }
6896
+ return {
6897
+ manifest: verified.manifest,
6898
+ work,
6899
+ checked: verified.checked,
6900
+ sources,
6901
+ createdAt: verified.manifest.createdAt,
6902
+ sessionCount: verified.manifest.sessions.length
6903
+ };
6904
+ } catch (error) {
6905
+ cleanup.failed(error);
6906
+ throw error;
6907
+ } finally {
6908
+ await cleanup.run(() => archive.close());
6909
+ }
6910
+ }
6911
+ /** Model-safe rows only: read a digest-bound static primary, never its original source. */
6912
+ async function* readConfiguredOutputRows(input, signal = new AbortController().signal) {
6913
+ const verified = await checkFrozenOutput(input, signal);
6914
+ const archive = await openCheckedOutput(input, verified.checked, signal);
6915
+ const cleanup = createCleanup();
6916
+ try {
6917
+ if (archive.manifestText !== verified.manifestText) fail("ARTIFACT_PROCESSING_MISMATCH");
6918
+ const descriptions = new Map(verified.manifest.entries.map((entry) => [entry.entryPath, entry]));
6919
+ for (const session of verified.manifest.sessions) for (const part of session.parts) {
6920
+ const spool = await spoolFacts(archive.entries.get(part.dataPath) ?? fail("ARTIFACT_INVALID_ARCHIVE"), descriptions.get(part.dataPath) ?? fail("ARTIFACT_INVALID_MANIFEST"), signal);
6921
+ const partCleanup = createCleanup();
6922
+ try {
6923
+ await archive.fence();
6924
+ let recordIndex = 0;
6925
+ for await (const text of spool.lines) {
6926
+ checkAbort(signal);
6927
+ if (recordIndex >= part.retainedRecordCount) fail("ARTIFACT_INVALID_ARCHIVE");
6928
+ yield {
6929
+ entryPath: part.dataPath,
6930
+ recordIndex,
6931
+ archiveSessionId: session.id,
6932
+ sourceId: part.sourceId,
6933
+ harness: session.harness,
6934
+ native: part.native,
6935
+ text,
6936
+ rowSha256: createHash("sha256").update(text).digest("hex")
6937
+ };
6938
+ recordIndex++;
6939
+ }
6940
+ if (recordIndex !== part.retainedRecordCount) fail("ARTIFACT_INVALID_ARCHIVE");
6941
+ } catch (error) {
6942
+ partCleanup.failed(error);
6943
+ throw error;
6944
+ } finally {
6945
+ await partCleanup.run(() => spool.lines.return(void 0), () => spool.close());
6946
+ }
6947
+ }
6948
+ } catch (error) {
6949
+ cleanup.failed(error);
6950
+ throw error;
6951
+ } finally {
6952
+ await cleanup.run(() => archive.close());
6953
+ }
6954
+ }
6955
+ //#endregion
6956
+ //#region packages/artifact/src/configured/review/parse.ts
6957
+ const digest$2 = (text) => createHash("sha256").update(text).digest("hex");
6958
+ const hash$6 = (value) => {
6959
+ const text = string(value);
6960
+ if (!/^[a-f0-9]{64}$/u.test(text)) fail("ARTIFACT_INVALID_MANIFEST");
6961
+ return text;
6962
+ };
6963
+ const pointer$3 = (value) => {
6964
+ const text = string(value);
6965
+ if (!text.startsWith("/") || /~(?:[^01]|$)/u.test(text)) fail("ARTIFACT_INVALID_MANIFEST");
6966
+ return text;
6967
+ };
6968
+ const range$2 = (value) => {
6969
+ const v = record$1(value);
6970
+ keys(v, ["start", "end"]);
6971
+ const start = integer(v["start"]), end = integer(v["end"]);
6972
+ if (end <= start) fail("ARTIFACT_INVALID_MANIFEST");
6973
+ return {
6974
+ start,
6975
+ end
6976
+ };
6977
+ };
6978
+ function checkedRanges(value, length) {
6979
+ const ranges = array(value, range$2);
6980
+ let end = 0;
6981
+ for (const r of ranges) {
6982
+ if (r.start < end || r.end > length) fail("ARTIFACT_INVALID_MANIFEST");
6983
+ end = r.end;
6984
+ }
6985
+ return ranges;
6986
+ }
6987
+ function rowRanges(value, fields) {
6988
+ const ranges = array(value, (value) => value);
6989
+ if (ranges.length !== fields.length) fail("ARTIFACT_INVALID_MANIFEST");
6990
+ return ranges.map((value, index) => {
6991
+ return checkedRanges(value, (fields[index] ?? fail("ARTIFACT_INVALID_MANIFEST")).text.length);
6992
+ });
6993
+ }
6994
+ function mask(value) {
6995
+ const v = record$1(value);
6996
+ keys(v, [
6997
+ "inputRange",
6998
+ "outputRange",
6999
+ "replacement",
7000
+ "stepId",
7001
+ "node",
7002
+ "ruleId"
7003
+ ]);
7004
+ const node = record$1(v["node"]);
7005
+ keys(node, ["id", "version"]);
7006
+ const output = record$1(v["outputRange"]);
7007
+ keys(output, ["start", "end"]);
7008
+ const start = integer(output["start"]), end = integer(output["end"]);
7009
+ const replacement = string(v["replacement"]);
7010
+ if (end < start || end - start !== replacement.length) fail("ARTIFACT_INVALID_MANIFEST");
7011
+ return {
7012
+ inputRange: range$2(v["inputRange"]),
7013
+ outputRange: {
7014
+ start,
7015
+ end
7016
+ },
7017
+ replacement,
7018
+ stepId: string(v["stepId"]),
7019
+ node: {
7020
+ id: string(node["id"]),
7021
+ version: string(node["version"])
7022
+ },
7023
+ ruleId: string(v["ruleId"])
7024
+ };
7025
+ }
7026
+ function field(value) {
7027
+ const v = record$1(value);
7028
+ keys(v, [
7029
+ "pointer",
7030
+ "cleanedPointer",
7031
+ "originalPointer",
7032
+ ...v["originalRange"] === void 0 ? [] : ["originalRange"],
7033
+ ...v["originalFieldHash"] === void 0 ? [] : ["originalFieldHash"],
7034
+ ...v["innerPointer"] === void 0 ? [] : ["innerPointer"],
7035
+ ...v["scalarKind"] === void 0 ? [] : ["scalarKind"],
7036
+ "role",
7037
+ "text",
7038
+ "fieldHash",
7039
+ "staticMasks",
7040
+ "nonPathMasks",
7041
+ "protectedRanges",
7042
+ ...v["customRanges"] === void 0 ? [] : ["customRanges"]
7043
+ ]);
7044
+ const role = v["role"];
7045
+ if (role !== "user" && role !== "assistant" && role !== "tool-output") return fail("ARTIFACT_INVALID_MANIFEST");
7046
+ const text = string(v["text"]), fieldHash = hash$6(v["fieldHash"]);
7047
+ const scalarKind = v["scalarKind"];
7048
+ if (scalarKind !== void 0 && scalarKind !== "literal" && scalarKind !== "structure" && scalarKind !== "container") return fail("ARTIFACT_INVALID_MANIFEST");
7049
+ if (digest$2(text) !== fieldHash) fail("ARTIFACT_PROCESSING_MISMATCH");
7050
+ const result = {
7051
+ pointer: pointer$3(v["pointer"]),
7052
+ cleanedPointer: pointer$3(v["cleanedPointer"]),
7053
+ originalPointer: pointer$3(v["originalPointer"]),
7054
+ ...v["originalRange"] === void 0 ? {} : { originalRange: range$2(v["originalRange"]) },
7055
+ ...v["originalFieldHash"] === void 0 ? {} : { originalFieldHash: hash$6(v["originalFieldHash"]) },
7056
+ ...v["innerPointer"] === void 0 ? {} : { innerPointer: pointer$3(v["innerPointer"]) },
7057
+ ...scalarKind === void 0 ? {} : { scalarKind },
7058
+ role,
7059
+ text,
7060
+ fieldHash,
7061
+ staticMasks: array(v["staticMasks"], mask),
7062
+ nonPathMasks: array(v["nonPathMasks"], mask),
7063
+ protectedRanges: array(v["protectedRanges"], range$2),
7064
+ ...v["customRanges"] === void 0 ? {} : { customRanges: array(v["customRanges"], range$2) }
7065
+ };
7066
+ if ([...result.staticMasks, ...result.nonPathMasks].some((m) => m.inputRange.end > text.length) || result.protectedRanges.some((r) => r.end > text.length) || result.customRanges?.some((r) => r.end > text.length) || result.originalRange === void 0 !== (result.originalFieldHash === void 0) || result.scalarKind === "structure" && (result.innerPointer !== void 0 || result.staticMasks.length > 0 || result.nonPathMasks.length > 0 || result.protectedRanges.length > 0 || (result.customRanges?.length ?? 0) > 0) || result.originalRange !== void 0 && (result.innerPointer !== void 0 || result.scalarKind !== void 0 || result.originalRange.end - result.originalRange.start !== text.length)) fail("ARTIFACT_INVALID_MANIFEST");
7067
+ return result;
7068
+ }
7069
+ function parsePrivateReviewRow(text) {
7070
+ const v = record$1(strictJson(text, 67108864));
7071
+ keys(v, [
7072
+ "entryPath",
7073
+ "recordIndex",
7074
+ "sourcePartId",
7075
+ "sourceRecordIndex",
7076
+ "archiveSessionId",
7077
+ "outputSha256",
7078
+ "cleanedText",
7079
+ "fields",
7080
+ "aiRanges"
7081
+ ]);
7082
+ const parsedFields = array(v["fields"], field);
7083
+ return {
7084
+ entryPath: string(v["entryPath"]),
7085
+ recordIndex: integer(v["recordIndex"]),
7086
+ sourcePartId: string(v["sourcePartId"]),
7087
+ sourceRecordIndex: integer(v["sourceRecordIndex"]),
7088
+ archiveSessionId: string(v["archiveSessionId"]),
7089
+ outputSha256: hash$6(v["outputSha256"]),
7090
+ cleanedText: string(v["cleanedText"]),
7091
+ fields: parsedFields,
7092
+ aiRanges: rowRanges(v["aiRanges"], parsedFields)
7093
+ };
7094
+ }
7095
+ function parsePrivateReviewManifest(text, entries, primary) {
7096
+ const v = record$1(strictJson(text, manifestLimitBytes, manifestNodeLimit));
7097
+ keys(v, [
7098
+ "format",
7099
+ "version",
7100
+ "bundleId",
7101
+ "workId",
7102
+ "primary",
7103
+ "entries",
7104
+ "rows"
7105
+ ]);
7106
+ const bound = record$1(v["primary"]);
7107
+ keys(bound, ["sha256", "archiveBytes"]);
7108
+ if (v["bundleId"] !== primary.manifest.bundleId || v["workId"] !== primary.manifest.work.id || bound["sha256"] !== primary.sha256 || bound["archiveBytes"] !== primary.archiveBytes) fail("ARTIFACT_PROCESSING_MISMATCH");
7109
+ const descriptions = array(v["entries"], (value) => {
7110
+ const e = record$1(value);
7111
+ keys(e, [
7112
+ "entryPath",
7113
+ "kind",
7114
+ "representation",
7115
+ "byteLength",
7116
+ "sha256",
7117
+ "rows"
7118
+ ]);
7119
+ return {
7120
+ entryPath: string(e["entryPath"]),
7121
+ kind: literal(e["kind"], "facts"),
7122
+ representation: literal(e["representation"], "jsonl"),
7123
+ byteLength: integer(e["byteLength"]),
7124
+ sha256: hash$6(e["sha256"]),
7125
+ rows: integer(e["rows"])
7126
+ };
7127
+ });
7128
+ const expected = new Set(primary.manifest.sessions.flatMap((s) => s.parts.map((p) => `${p.dataPath}.review.jsonl`)));
7129
+ let rows = 0;
7130
+ for (const d of descriptions) {
7131
+ const e = entries.get(d.entryPath);
7132
+ if (!expected.delete(d.entryPath) || !e || e.compressionMethod !== 8 || e.uncompressedSize !== d.byteLength || d.byteLength > maximumPartBytes) fail("ARTIFACT_INVALID_ARCHIVE");
7133
+ rows += d.rows;
7134
+ }
7135
+ if (expected.size || entries.size !== descriptions.length + 1 || rows !== integer(v["rows"])) fail("ARTIFACT_INVALID_ARCHIVE");
7136
+ return {
7137
+ format: literal(v["format"], "sess-pilot-private-b-review"),
7138
+ version: literal(v["version"], 2),
7139
+ bundleId: primary.manifest.bundleId,
7140
+ workId: primary.manifest.work.id,
7141
+ primary: {
7142
+ sha256: primary.sha256,
7143
+ archiveBytes: primary.archiveBytes
7144
+ },
7145
+ entries: descriptions,
7146
+ rows
7147
+ };
7148
+ }
7149
+ //#endregion
7150
+ //#region packages/artifact/src/configured/review/native.ts
7151
+ const reviewLimits = {
7152
+ ...defaultLimits,
7153
+ maxRecordBytes: maximumRecordBytes,
7154
+ maxUnitBytes: maximumRecordBytes,
7155
+ maxOutputRecordBytes: maximumRecordBytes
7156
+ };
7157
+ function reviewNative(text, signal) {
7158
+ return parseNativeRecord(text, reviewLimits, signal);
7159
+ }
7160
+ function emptyNativeStructure(node) {
7161
+ if (node.kind === "literal") return false;
7162
+ if (node.kind === "string") return node.value.length === 0;
7163
+ return node.kind === "array" ? node.items.every(emptyNativeStructure) : node.properties.every((property) => emptyNativeStructure(property.value));
7164
+ }
7165
+ function nativePointer(root, pointer) {
7166
+ let node = root;
7167
+ if (pointer === "") return node;
7168
+ if (!pointer.startsWith("/") || /~(?:[^01]|$)/u.test(pointer)) fail("ARTIFACT_PROCESSING_MISMATCH");
7169
+ for (const key of pointer.slice(1).split("/").map((part) => part.replaceAll("~1", "/").replaceAll("~0", "~"))) node = (node.kind === "object" ? node.properties.find((property) => property.key.value === key)?.value : node.kind === "array" && /^(?:0|[1-9]\d*)$/u.test(key) ? node.items[Number(key)] : void 0) ?? fail("ARTIFACT_PROCESSING_MISMATCH");
7170
+ return node;
7171
+ }
7172
+ /** Exact numeric-array lexemes for grouped geography, including targets decoded from native strings. */
7173
+ function nativeContainerText(node, signal) {
7174
+ if (node.kind !== "array") return void 0;
7175
+ const numeric = (value) => {
7176
+ signal.throwIfAborted();
7177
+ return value.kind === "array" ? value.items.every(numeric) : value.kind === "literal" && Number.isFinite(Number(value.raw));
7178
+ };
7179
+ return numeric(node) ? renderNative(node, /* @__PURE__ */ new Map(), reviewLimits, signal).text : void 0;
7180
+ }
7181
+ //#endregion
7182
+ //#region packages/artifact/src/configured/review/read.ts
7183
+ async function checkPrivateReviewProjection(file, primary, signal) {
7184
+ const output = await checkFrozenOutput(primary, signal);
7185
+ let manifest;
7186
+ return {
7187
+ checked: await checkWrittenArchive(file.path, file.identity, void 0, (text, entries) => {
7188
+ manifest = parsePrivateReviewManifest(text, entries, {
7189
+ manifest: output.manifest,
7190
+ sha256: primary.sha256,
7191
+ archiveBytes: primary.archiveBytes
7192
+ });
7193
+ }, signal),
7194
+ manifest: manifest ?? fail("ARTIFACT_INVALID_ARCHIVE"),
7195
+ output: output.manifest
7196
+ };
7197
+ }
7198
+ /** Internal reconstruction iterator; callers exposing model input must use the field-only iterator. */
7199
+ async function* readPrivateReviewRows(request, signal) {
7200
+ const { projection, primary } = request;
7201
+ const verified = await checkPrivateReviewProjection(projection, primary, signal);
7202
+ if (projection.primarySha256 !== primary.sha256 || projection.rows !== verified.manifest.rows) fail("ARTIFACT_PROCESSING_MISMATCH");
7203
+ const archive = await openCheckedOutput(projection, verified.checked, signal);
7204
+ const output = readConfiguredOutputRows(primary, signal);
7205
+ const parts = new Map(verified.output.sessions.flatMap((session) => session.parts.map((part) => [part.dataPath, {
7206
+ part,
7207
+ sessionId: session.id
7208
+ }])));
7209
+ let next = await output.next();
7210
+ const cleanup = createCleanup();
7211
+ try {
7212
+ for (const description of verified.manifest.entries) {
7213
+ const spool = await spoolFacts(archive.entries.get(description.entryPath) ?? fail("ARTIFACT_INVALID_ARCHIVE"), description, signal);
7214
+ const partCleanup = createCleanup();
7215
+ let rows = 0, last = -1;
7216
+ try {
7217
+ for await (const text of spool.lines) {
7218
+ const row = parsePrivateReviewRow(text), part = parts.get(row.entryPath);
7219
+ if (!part || part.part.native.role !== "main" || row.archiveSessionId !== part.sessionId || `${row.entryPath}.review.jsonl` !== description.entryPath || row.recordIndex <= last || row.recordIndex >= part.part.retainedRecordCount || row.sourceRecordIndex >= part.part.recordCount) fail("ARTIFACT_INVALID_ARCHIVE");
7220
+ while (!next.done && (next.value.entryPath !== row.entryPath || next.value.recordIndex < row.recordIndex)) next = await output.next();
7221
+ if (next.done || next.value.entryPath !== row.entryPath || next.value.recordIndex !== row.recordIndex || next.value.rowSha256 !== row.outputSha256) fail("ARTIFACT_PROCESSING_MISMATCH");
7222
+ const root = reviewNative(row.cleanedText, signal), actual = reviewNative(next.value.text, signal), seen = /* @__PURE__ */ new Set();
7223
+ for (const field of row.fields) {
7224
+ const key = JSON.stringify([field.pointer, field.innerPointer ?? null]);
7225
+ if (seen.has(key)) fail("ARTIFACT_PROCESSING_MISMATCH");
7226
+ seen.add(key);
7227
+ let source = nativePointer(root, field.cleanedPointer);
7228
+ const target = nativePointer(actual, field.pointer), nativeLiteral = field.scalarKind === "literal" && field.innerPointer === void 0;
7229
+ if (field.scalarKind === "container" && field.innerPointer === void 0 ? nativeContainerText(source, signal) === void 0 || !["array", "string"].includes(target.kind) : nativeLiteral ? source.kind !== "literal" || !["literal", "string"].includes(target.kind) : source.kind !== "string" || target.kind !== "string") return fail("ARTIFACT_PROCESSING_MISMATCH");
7230
+ if (field.scalarKind === "structure") {
7231
+ if (source.kind !== "string") return fail("ARTIFACT_PROCESSING_MISMATCH");
7232
+ const structure = reviewNative(source.value, signal);
7233
+ if (!["object", "array"].includes(structure.kind) || !emptyNativeStructure(structure)) fail("ARTIFACT_PROCESSING_MISMATCH");
7234
+ }
7235
+ if (field.innerPointer !== void 0) {
7236
+ if (source.kind !== "string") return fail("ARTIFACT_PROCESSING_MISMATCH");
7237
+ source = nativePointer(reviewNative(source.value, signal), field.innerPointer);
7238
+ }
7239
+ const text = field.scalarKind === "container" ? nativeContainerText(source, signal) : field.scalarKind === "literal" ? source.kind === "literal" ? source.raw : void 0 : source.kind === "string" ? source.value : void 0;
7240
+ if (text === void 0 || text !== field.text || createHash("sha256").update(text).digest("hex") !== field.fieldHash) fail("ARTIFACT_PROCESSING_MISMATCH");
7241
+ }
7242
+ rows++;
7243
+ last = row.recordIndex;
7244
+ yield row;
7245
+ }
7246
+ if (rows !== description.rows) fail("ARTIFACT_INVALID_ARCHIVE");
7247
+ } catch (error) {
7248
+ partCleanup.failed(error);
7249
+ throw error;
7250
+ } finally {
7251
+ await partCleanup.run(() => spool.lines.return(void 0), () => spool.close());
7252
+ }
7253
+ await archive.fence();
7254
+ }
7255
+ } catch (error) {
7256
+ cleanup.failed(error);
7257
+ throw error;
7258
+ } finally {
7259
+ await cleanup.run(() => output.return(void 0), () => archive.close());
7260
+ }
7261
+ }
7262
+ //#endregion
7263
+ //#region packages/artifact/src/configured/review/rules.ts
7264
+ const generic = /* @__PURE__ */ new Set([
7265
+ "src",
7266
+ "lib",
7267
+ "test",
7268
+ "tests",
7269
+ "docs",
7270
+ "README.md",
7271
+ "package.json",
7272
+ "pnpm-lock.yaml",
7273
+ "index.ts",
7274
+ "main.ts",
7275
+ "index.js",
7276
+ ".claude.json",
7277
+ ".codex",
7278
+ "config.toml"
7279
+ ]);
7280
+ /** Dipper B v6.2 component policy, translated to native UTF-16 coordinates. */
7281
+ function componentPaths(text, fullPath = false) {
7282
+ const found = [];
7283
+ for (const match of text.matchAll(/(?:\/Users\/|\/home\/|[A-Za-z]:\\Users\\)[^\r\n"'`<>[\];|]+/gu)) {
7284
+ let raw = match[0];
7285
+ const separator = raw.includes("\\") ? "\\" : "/";
7286
+ raw = (raw.split(/\s+(?:&&|\|\||--\w|(?:and|then|with|to|from|is)\s)/u)[0] ?? "").replace(/[.,):\s]+$/u, "");
7287
+ const quoted = [
7288
+ "\"",
7289
+ "'",
7290
+ "`"
7291
+ ].includes(text[match.index - 1] ?? ""), bracketed = /\[(?:project|workspace):\s*$/u.test(text.slice(0, match.index));
7292
+ if (!quoted && !bracketed && !fullPath) {
7293
+ const token = `Desktop${separator}Folders`;
7294
+ raw = (raw.replace(`Desktop Folders${separator}`, token).split(/\s/u)[0] ?? "").replace(token, `Desktop Folders${separator}`);
7295
+ }
7296
+ const root = /^(?:\/Users\/|\/home\/|[A-Za-z]:\\Users\\)/u.exec(raw)?.[0];
7297
+ if (!root) continue;
7298
+ const parts = raw.slice(root.length).split(separator);
7299
+ if (!parts[0] || /\s/u.test(parts[0])) continue;
7300
+ let offset = root.length;
7301
+ const coords = parts.map((value) => {
7302
+ const range = {
7303
+ value,
7304
+ start: match.index + offset,
7305
+ end: match.index + offset + value.length
7306
+ };
7307
+ offset += value.length + separator.length;
7308
+ return range;
7309
+ });
7310
+ const first = coords[0];
7311
+ if (!first) continue;
7312
+ const components = [{
7313
+ start: first.start,
7314
+ end: first.end
7315
+ }];
7316
+ let project = -1;
7317
+ if (parts.length > 1) {
7318
+ if ([
7319
+ "Desktop",
7320
+ "Desktop Folders",
7321
+ "Documents",
7322
+ "Projects",
7323
+ "workspace",
7324
+ "workspaces",
7325
+ "repos",
7326
+ "code"
7327
+ ].includes(parts[1] ?? "")) project = parts.length > 2 ? 2 : -1;
7328
+ else if (!(parts[1] ?? "").startsWith(".")) project = 1;
7329
+ }
7330
+ for (let index = 1; index < coords.length; index++) {
7331
+ const value = coords[index];
7332
+ if (!value?.value || index === 1 && project === 2) continue;
7333
+ if (index === project || !generic.has(value.value)) components.push({
7334
+ start: value.start,
7335
+ end: value.end
7336
+ });
7337
+ }
7338
+ found.push({
7339
+ start: match.index,
7340
+ end: match.index + raw.length,
7341
+ components
7342
+ });
7343
+ }
7344
+ return found;
7345
+ }
7346
+ /** Only isolated low-information values inside an explicitly marked CLI example section. */
7347
+ function helpSentinels(text) {
7348
+ if (!/^Usage:/mu.test(text) || !/^Examples:/mu.test(text)) return [];
7349
+ const begin = text.indexOf("Examples:"), end = text.indexOf("\nOptions:", begin), zone = text.slice(begin, end < 0 ? text.length : end), result = [];
7350
+ for (const match of zone.matchAll(/\b(?:API_KEY|api_key|TOKEN|password)=(xxx|\.\.\.|<API_KEY>|<TOKEN>)(?=\s|$)/gu)) {
7351
+ const value = match[1];
7352
+ if (!value) continue;
7353
+ const start = begin + match.index + match[0].lastIndexOf(value);
7354
+ result.push({
7355
+ start,
7356
+ end: start + value.length
7357
+ });
7358
+ }
7359
+ return result;
7360
+ }
7361
+ //#endregion
7362
+ //#region packages/artifact/src/configured/review/ranges.ts
7363
+ function staticSpan(mask) {
7364
+ return {
7365
+ ...mask.inputRange,
7366
+ category: staticMaskCategory(mask.node.id),
7367
+ causes: [{
7368
+ kind: "static",
7369
+ range: mask.inputRange,
7370
+ stepId: mask.stepId,
7371
+ node: mask.node,
7372
+ ruleId: mask.ruleId
7373
+ }]
7374
+ };
7375
+ }
7376
+ /** These are deterministic B rules, independent of a model's occurrence decisions. */
7377
+ function policySpan(range, nodeId, ruleId) {
7378
+ return {
7379
+ ...range,
7380
+ category: staticMaskCategory(nodeId),
7381
+ causes: [{
7382
+ kind: "static",
7383
+ range,
7384
+ node: {
7385
+ id: nodeId,
7386
+ version: "sesspilot-b-v1"
7387
+ },
7388
+ stepId: "sesspilot-b-v1",
7389
+ ruleId
7390
+ }]
7391
+ };
7392
+ }
7393
+ function subtract(input, retained) {
7394
+ return input.flatMap((range) => {
7076
7395
  let pieces = [range];
7077
7396
  for (const keep of retained) pieces = pieces.flatMap((piece) => keep.end <= piece.start || keep.start >= piece.end ? [piece] : [{
7078
7397
  ...piece,
@@ -7172,497 +7491,269 @@ function reviewSpans(field, edit) {
7172
7491
  };
7173
7492
  } else merged.push(range);
7174
7493
  }
7175
- return merged;
7176
- }
7177
- //#endregion
7178
- //#region packages/artifact/src/configured/review/provenance.ts
7179
- const hash$5 = (value) => createHash("sha256").update(JSON.stringify(value)).digest("hex");
7180
- /** Final positions come from reconstruction; original causes keep their actual scope and stage. */
7181
- function reconstructedContributors(input) {
7182
- const { row, field, span, transcript, coordinates, context } = input;
7183
- const contributors = /* @__PURE__ */ new Map();
7184
- for (const cause of span.causes) {
7185
- const localRange = {
7186
- start: Math.max(cause.range.start, span.start),
7187
- end: Math.min(cause.range.end, span.end)
7188
- };
7189
- if (localRange.end <= localRange.start) continue;
7190
- const inputRange = coordinates(localRange);
7191
- if (cause.kind === "semantic" || cause.kind === "correction") {
7192
- const source = {
7193
- ...transcript,
7194
- inputRange,
7195
- context: context(inputRange),
7196
- category: maskCategory(cause.category)
7197
- };
7198
- const id = hash$5([
7199
- row.entryPath,
7200
- row.recordIndex,
7201
- cause.kind,
7202
- source
7203
- ]);
7204
- contributors.set(id, {
7205
- id,
7206
- kind: cause.kind,
7207
- category: source.category,
7208
- source
7209
- });
7210
- } else {
7211
- const source = {
7212
- entryPath: row.entryPath,
7213
- recordIndex: row.recordIndex,
7214
- sourcePartId: row.sourcePartId,
7215
- sourceRecordIndex: row.sourceRecordIndex,
7216
- archiveSessionId: row.archiveSessionId,
7217
- mask: {
7218
- stepId: cause.stepId,
7219
- node: cause.node,
7220
- ruleId: cause.ruleId,
7221
- inputRange,
7222
- outputRange: transcript.outputRange,
7223
- replacement: transcript.replacement,
7224
- fieldId: hash$5([
7225
- row.sourcePartId,
7226
- row.sourceRecordIndex,
7227
- field.originalPointer,
7228
- field.innerPointer ?? null
7229
- ]),
7230
- subject: "value",
7231
- originalPointer: field.originalPointer,
7232
- outputPointer: transcript.pointer,
7233
- sourceRange: field.innerPointer === void 0 ? {
7234
- start: (field.originalRange?.start ?? 0) + localRange.start,
7235
- end: (field.originalRange?.start ?? 0) + localRange.end
7236
- } : null,
7237
- inputSha256: transcript.inputSha256,
7238
- outputSha256: transcript.outputSha256,
7239
- context: context(inputRange)
7240
- }
7241
- };
7242
- const id = hash$5([
7243
- row.entryPath,
7244
- row.recordIndex,
7245
- "static",
7246
- source.mask
7247
- ]);
7248
- contributors.set(id, {
7249
- id,
7250
- kind: "static",
7251
- category: staticMaskCategory(cause.node.id),
7252
- source
7253
- });
7254
- }
7255
- }
7256
- if (!contributors.size) fail("ARTIFACT_PROCESSING_MISMATCH");
7257
- return [...contributors.values()];
7258
- }
7259
- //#endregion
7260
- //#region packages/artifact/src/configured/review/render.ts
7261
- const hash$4 = (text) => createHash("sha256").update(text).digest("hex");
7262
- const address = (pointer, inner) => JSON.stringify([pointer, inner ?? null]);
7263
- /** Offsets in the same lossless serialization used by renderNative, including escaped JSON strings. */
7264
- function stringOffsets(root, changes) {
7265
- const offsets = /* @__PURE__ */ new Map();
7266
- let offset = 0;
7267
- const visit = (node) => {
7268
- const changed = changes.get(node.id);
7269
- if (node.kind === "string" || changed !== void 0) {
7270
- offsets.set(node.id, offset + 1);
7271
- offset += JSON.stringify(changed ?? (node.kind === "string" ? node.value : "")).length;
7272
- } else if (node.kind === "literal") {
7273
- offsets.set(node.id, offset);
7274
- offset += node.raw.length;
7275
- } else if (node.kind === "array") {
7276
- offsets.set(node.id, offset);
7277
- offset++;
7278
- node.items.forEach((child, index) => {
7279
- if (index) offset++;
7280
- visit(child);
7281
- });
7282
- offset++;
7283
- } else {
7284
- offset++;
7285
- node.properties.forEach((property, index) => {
7286
- if (index) offset++;
7287
- offset += JSON.stringify(property.key.value).length + 1;
7288
- visit(property.value);
7289
- });
7290
- offset++;
7291
- }
7292
- };
7293
- visit(root);
7294
- return offsets;
7295
- }
7296
- const encodedLength = (text) => JSON.stringify(text).length - 2;
7297
- /** Restore verified untouched scalar lexemes without round-tripping through JS numbers. */
7298
- function restoreLiterals(root, literals) {
7299
- const raw = literals.get(root.id);
7300
- if (raw !== void 0) return {
7301
- id: root.id,
7302
- kind: "literal",
7303
- raw
7304
- };
7305
- if (root.kind === "array") return {
7306
- ...root,
7307
- items: root.items.map((node) => restoreLiterals(node, literals))
7308
- };
7309
- if (root.kind === "object") return {
7310
- ...root,
7311
- properties: root.properties.map((entry) => ({
7312
- ...entry,
7313
- value: restoreLiterals(entry.value, literals)
7314
- }))
7315
- };
7316
- return root;
7317
- }
7318
- /** Rewrite only admitted value leaves; every other byte comes from the verified static base. */
7319
- function renderReviewRow(row, before, edits, markers, signal) {
7320
- if (hash$4(before) !== row.outputSha256) fail("ARTIFACT_PROCESSING_MISMATCH");
7321
- const raw = reviewNative(row.cleanedText, signal), actual = reviewNative(before, signal);
7322
- const pending = /* @__PURE__ */ new Map();
7323
- for (const edit of edits) {
7324
- const key = address(edit.pointer, edit.innerPointer);
7325
- if (pending.has(key)) fail("ARTIFACT_PROCESSING_MISMATCH");
7326
- pending.set(key, edit);
7327
- }
7328
- const groups = /* @__PURE__ */ new Map();
7329
- for (const field of row.fields) groups.set(field.pointer, [...groups.get(field.pointer) ?? [], field]);
7330
- const changes = /* @__PURE__ */ new Map(), literals = /* @__PURE__ */ new Map(), transcripts = [], replaced = [];
7331
- for (const [pointer, fields] of groups) {
7332
- const first = fields[0] ?? fail("ARTIFACT_PROCESSING_MISMATCH"), original = nativePointer(raw, first.cleanedPointer), target = nativePointer(actual, pointer), nativeLiteral = first.scalarKind === "literal" && first.innerPointer === void 0, nativeContainer = first.scalarKind === "container" && first.innerPointer === void 0;
7333
- if (nativeContainer ? nativeContainerText(original, signal) === void 0 || !["array", "string"].includes(target.kind) : nativeLiteral ? original.kind !== "literal" || !["literal", "string"].includes(target.kind) : original.kind !== "string" || target.kind !== "string") return fail("ARTIFACT_PROCESSING_MISMATCH");
7334
- const inner = first.innerPointer === void 0 ? void 0 : original.kind === "string" ? reviewNative(original.value, signal) : fail("ARTIFACT_PROCESSING_MISMATCH");
7335
- const innerChanges = /* @__PURE__ */ new Map(), pieces = [];
7336
- for (const field of fields) {
7337
- if (field.cleanedPointer !== first.cleanedPointer || field.innerPointer === void 0 !== (first.innerPointer === void 0)) fail("ARTIFACT_PROCESSING_MISMATCH");
7338
- const source = inner && field.innerPointer !== void 0 ? nativePointer(inner, field.innerPointer) : original;
7339
- const sourceValue = field.scalarKind === "container" ? nativeContainerText(source, signal) : field.scalarKind === "literal" ? source.kind === "literal" ? source.raw : void 0 : source.kind === "string" ? source.value : void 0;
7340
- if (sourceValue === void 0 || sourceValue !== field.text || hash$4(sourceValue) !== field.fieldHash) return fail("ARTIFACT_PROCESSING_MISMATCH");
7341
- const key = address(field.pointer, field.innerPointer), edit = pending.get(key);
7342
- pending.delete(key);
7343
- const spans = reviewSpans(field, edit), causes = new Map(spans.map((span) => [span.start, span])), items = [];
7344
- const changed = replaceSemanticSpans(field.text, spans, markers, (span, replacement, start) => items.push({
7345
- inputRange: {
7346
- start: span.start,
7347
- end: span.end
7348
- },
7349
- outputRange: {
7350
- start,
7351
- end: start + replacement.length
7352
- },
7353
- replacement,
7354
- category: maskCategory(span.category),
7355
- span: causes.get(span.start) ?? fail("ARTIFACT_PROCESSING_MISMATCH")
7356
- }));
7357
- pieces.push({
7358
- node: source.id,
7359
- field,
7360
- source: sourceValue,
7361
- changed,
7362
- items
7363
- });
7364
- if (inner && changed !== sourceValue) innerChanges.set(source.id, changed);
7365
- }
7366
- const sourceText = inner ? renderNative(inner, /* @__PURE__ */ new Map(), reviewLimits, signal).text : nativeContainer ? nativeContainerText(original, signal) ?? fail("ARTIFACT_PROCESSING_MISMATCH") : original.kind === "string" ? original.value : original.kind === "literal" ? original.raw : fail("ARTIFACT_PROCESSING_MISMATCH");
7367
- const changed = inner ? renderNative(inner, innerChanges, reviewLimits, signal).text : pieces[0]?.changed ?? fail("ARTIFACT_PROCESSING_MISMATCH");
7368
- const sourceOffsets = inner ? stringOffsets(inner, /* @__PURE__ */ new Map()) : void 0, outputOffsets = inner ? stringOffsets(inner, innerChanges) : void 0;
7369
- const inputSha256 = hash$4(sourceText), outputSha256 = hash$4(changed), context = createSentenceContext(sourceText);
7370
- for (const piece of pieces) for (const item of piece.items) {
7371
- const coordinates = (range) => sourceOffsets ? {
7372
- start: (sourceOffsets.get(piece.node) ?? fail("ARTIFACT_PROCESSING_MISMATCH")) + encodedLength(piece.source.slice(0, range.start)),
7373
- end: (sourceOffsets.get(piece.node) ?? fail("ARTIFACT_PROCESSING_MISMATCH")) + encodedLength(piece.source.slice(0, range.end))
7374
- } : range;
7375
- const inputRange = coordinates(item.inputRange);
7376
- const start = outputOffsets ? (outputOffsets.get(piece.node) ?? fail("ARTIFACT_PROCESSING_MISMATCH")) + encodedLength(piece.changed.slice(0, item.outputRange.start)) : item.outputRange.start;
7377
- const { span, ...applied } = item;
7378
- const transcript = {
7379
- ...applied,
7380
- pointer,
7381
- inputSha256,
7382
- outputSha256,
7383
- inputRange,
7384
- outputRange: {
7385
- start,
7386
- end: start + item.replacement.length
7387
- },
7388
- context: context(inputRange)
7389
- };
7390
- transcripts.push({
7391
- ...transcript,
7392
- contributors: reconstructedContributors({
7393
- row,
7394
- field: piece.field,
7395
- span,
7396
- transcript,
7397
- coordinates,
7398
- context
7399
- })
7400
- });
7401
- }
7402
- if (nativeContainer && changed === sourceText) {
7403
- if (nativeContainerText(target, signal) !== sourceText) fail("ARTIFACT_PROCESSING_MISMATCH");
7404
- } else if (nativeLiteral && changed === sourceText) literals.set(target.id, sourceText);
7405
- else changes.set(target.id, changed);
7406
- replaced.push(pointer);
7407
- }
7408
- if (pending.size) fail("ARTIFACT_PROCESSING_MISMATCH");
7409
- const restored = literals.size ? restoreLiterals(actual, literals) : actual;
7410
- return {
7411
- text: renderNative(restored, changes, reviewLimits, signal).text,
7412
- transcripts,
7413
- replaced
7414
- };
7415
- }
7416
- //#endregion
7417
- //#region packages/artifact/src/configured/output/family-carrier.ts
7418
- /** Map decoded UTF-16 boundaries to complete JSON escape tokens in the original string. */
7419
- function boundaries(text, span, value) {
7420
- const offsets = [span.start + 1];
7421
- let cursor = span.start + 1;
7422
- while (cursor < span.end - 1) {
7423
- cursor += text[cursor] === "\\" ? text[cursor + 1] === "u" ? 6 : 2 : 1;
7424
- offsets.push(cursor);
7425
- }
7426
- if (cursor !== span.end - 1 || offsets.length !== value.length + 1) fail("ARTIFACT_PROCESSING_MISMATCH");
7427
- return offsets;
7428
- }
7429
- /** One harness-declared JSON carrier layer; never interpret ordinary strings recursively. */
7430
- function familyCarrierSpans(field, find, signal) {
7431
- const text = field.text;
7432
- if (![
7433
- "tool-call",
7434
- "tool-result",
7435
- "runtime"
7436
- ].includes(field.origin.carrier) || !/^\s*[[{]/u.test(text)) return void 0;
7437
- try {
7438
- parseNativeRecord(text, limits, signal);
7439
- } catch (error) {
7440
- if (error instanceof ProcessingError && ["PROCESSING_INVALID_RECORD", "PROCESSING_KEY_COLLISION"].includes(error.code)) return void 0;
7441
- throw error;
7442
- }
7443
- const root = jsonSpans(text, signal) ?? fail("ARTIFACT_PROCESSING_MISMATCH");
7444
- const spans = [];
7445
- const visit = (part) => {
7446
- checkAbort(signal);
7447
- if (part.fields) for (const [key, value] of part.fields) {
7448
- visit(part.keys?.get(key) ?? fail("ARTIFACT_PROCESSING_MISMATCH"));
7449
- visit(value);
7450
- }
7451
- else if (part.items) for (const item of part.items) visit(item);
7452
- else if (typeof part.value === "string") {
7453
- const matches = find(part.value);
7454
- if (!matches.length) return;
7455
- const offsets = boundaries(text, part, part.value);
7456
- for (const match of matches) {
7457
- const start = offsets[match.start] ?? fail("ARTIFACT_PROCESSING_MISMATCH");
7458
- const end = offsets[match.end] ?? fail("ARTIFACT_PROCESSING_MISMATCH");
7459
- spans.push({
7460
- ...match,
7461
- start,
7462
- end
7463
- });
7464
- }
7494
+ return merged;
7495
+ }
7496
+ //#endregion
7497
+ //#region packages/artifact/src/configured/review/provenance.ts
7498
+ const hash$5 = (value) => createHash("sha256").update(JSON.stringify(value)).digest("hex");
7499
+ /** Final positions come from reconstruction; original causes keep their actual scope and stage. */
7500
+ function reconstructedContributors(input) {
7501
+ const { row, field, span, transcript, coordinates, context } = input;
7502
+ const contributors = /* @__PURE__ */ new Map();
7503
+ for (const cause of span.causes) {
7504
+ const localRange = {
7505
+ start: Math.max(cause.range.start, span.start),
7506
+ end: Math.min(cause.range.end, span.end)
7507
+ };
7508
+ if (localRange.end <= localRange.start) continue;
7509
+ const inputRange = coordinates(localRange);
7510
+ if (cause.kind === "semantic" || cause.kind === "correction") {
7511
+ const source = {
7512
+ ...transcript,
7513
+ inputRange,
7514
+ context: context(inputRange),
7515
+ category: maskCategory(cause.category)
7516
+ };
7517
+ const id = hash$5([
7518
+ row.entryPath,
7519
+ row.recordIndex,
7520
+ cause.kind,
7521
+ source
7522
+ ]);
7523
+ contributors.set(id, {
7524
+ id,
7525
+ kind: cause.kind,
7526
+ category: source.category,
7527
+ source
7528
+ });
7465
7529
  } else {
7466
- const value = text.slice(part.start, part.end);
7467
- for (const match of find(value)) spans.push({
7468
- ...match,
7469
- start: part.start + match.start,
7470
- end: part.start + match.end,
7471
- jsonScalar: {
7472
- start: part.start,
7473
- end: part.end
7530
+ const source = {
7531
+ entryPath: row.entryPath,
7532
+ recordIndex: row.recordIndex,
7533
+ sourcePartId: row.sourcePartId,
7534
+ sourceRecordIndex: row.sourceRecordIndex,
7535
+ archiveSessionId: row.archiveSessionId,
7536
+ mask: {
7537
+ stepId: cause.stepId,
7538
+ node: cause.node,
7539
+ ruleId: cause.ruleId,
7540
+ inputRange,
7541
+ outputRange: transcript.outputRange,
7542
+ replacement: transcript.replacement,
7543
+ fieldId: hash$5([
7544
+ row.sourcePartId,
7545
+ row.sourceRecordIndex,
7546
+ field.originalPointer,
7547
+ field.innerPointer ?? null
7548
+ ]),
7549
+ subject: "value",
7550
+ originalPointer: field.originalPointer,
7551
+ outputPointer: transcript.pointer,
7552
+ sourceRange: field.innerPointer === void 0 ? {
7553
+ start: (field.originalRange?.start ?? 0) + localRange.start,
7554
+ end: (field.originalRange?.start ?? 0) + localRange.end
7555
+ } : null,
7556
+ inputSha256: transcript.inputSha256,
7557
+ outputSha256: transcript.outputSha256,
7558
+ context: context(inputRange)
7474
7559
  }
7560
+ };
7561
+ const id = hash$5([
7562
+ row.entryPath,
7563
+ row.recordIndex,
7564
+ "static",
7565
+ source.mask
7566
+ ]);
7567
+ contributors.set(id, {
7568
+ id,
7569
+ kind: "static",
7570
+ category: staticMaskCategory(cause.node.id),
7571
+ source
7475
7572
  });
7476
7573
  }
7477
- };
7478
- visit(root);
7479
- return spans;
7480
- }
7481
- /** Never publish a carrier whose edited keys collide or whose JSON structure changed. */
7482
- function validateFamilyCarrier(text, signal) {
7483
- try {
7484
- parseNativeRecord(text, limits, signal);
7485
- } catch (error) {
7486
- if (error instanceof ProcessingError && ["PROCESSING_INVALID_RECORD", "PROCESSING_KEY_COLLISION"].includes(error.code)) fail("ARTIFACT_PROCESSING_MISMATCH", { cause: error });
7487
- throw error;
7488
7574
  }
7575
+ if (!contributors.size) fail("ARTIFACT_PROCESSING_MISMATCH");
7576
+ return [...contributors.values()];
7489
7577
  }
7490
7578
  //#endregion
7491
- //#region packages/artifact/src/configured/output/family.ts
7492
- /** Names the failed check in the private cause chain; it never carries session text. */
7493
- const mismatch = (check) => fail("ARTIFACT_PROCESSING_MISMATCH", { cause: /* @__PURE__ */ new Error(`configured family hide check=${check}`) });
7494
- /** Binds each family's main Hide literals to its main and worker data and metadata entries. */
7495
- function indexFamilyHides(manifest, hides = []) {
7496
- const sessions = new Map(manifest.sessions.map((session) => [session.id, session]));
7497
- const parts = /* @__PURE__ */ new Map();
7498
- const bind = (id, family, main) => {
7499
- const session = sessions.get(id) ?? mismatch("unknown-session");
7500
- if (parts.has(session.metadataPath)) mismatch("duplicate-session");
7501
- if (session.parts.some((part) => part.native.role === "main") !== main) mismatch("session-role");
7502
- parts.set(session.metadataPath, family);
7503
- for (const part of session.parts) {
7504
- if (parts.has(part.dataPath)) mismatch("duplicate-part");
7505
- parts.set(part.dataPath, family);
7506
- }
7507
- };
7508
- const shared = /* @__PURE__ */ new Map();
7509
- for (const hide of hides) {
7510
- if (!hide.terms.length || !(hide.mainSessionIds.length + hide.workerSessionIds.length)) mismatch("empty-family");
7511
- const key = JSON.stringify([hide.terms, hide.exceptions ?? []]);
7512
- let family = shared.get(key);
7513
- if (!family) {
7514
- const categories = /* @__PURE__ */ new Map();
7515
- const bounded = /* @__PURE__ */ new Set();
7516
- for (const { term, category, bounded: whole } of hide.terms) {
7517
- if (categories.has(term)) mismatch("duplicate-term");
7518
- categories.set(term, maskCategory(category));
7519
- if (whole) bounded.add(term);
7520
- }
7521
- family = {
7522
- matcher: createEntityMatcher([...categories.keys()].map((value) => ({
7523
- kind: "custom-term",
7524
- value
7525
- }))),
7526
- categories,
7527
- bounded,
7528
- excepted: bExceptionRanges(hide.exceptions ?? [])
7529
- };
7530
- shared.set(key, family);
7531
- }
7532
- for (const id of hide.mainSessionIds) bind(id, family, true);
7533
- for (const id of hide.workerSessionIds) bind(id, family, false);
7534
- }
7535
- return parts;
7536
- }
7537
- /** Disjoint literal hits outside existing markers; overlaps join under the highest category. */
7538
- function familySpans(text, family, signal) {
7539
- const markers = [...text.matchAll(markerPattern)].map((match) => ({
7540
- start: match.index,
7541
- end: match.index + match[0].length
7542
- }));
7543
- let kept;
7544
- const excepted = (range) => (kept ??= bContainment(family.excepted(text, signal)))(range);
7545
- const marked = (range) => {
7546
- let low = 0, high = markers.length;
7547
- while (low < high) {
7548
- const middle = low + high >> 1;
7549
- if ((markers[middle]?.end ?? Infinity) <= range.start) low = middle + 1;
7550
- else high = middle;
7551
- }
7552
- return (markers[low]?.start ?? Infinity) < range.end;
7553
- };
7554
- 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 }) => ({
7555
- ...range,
7556
- category: family.categories.get(entity.value) ?? mismatch("unknown-term")
7557
- })).sort((left, right) => left.start - right.start || right.end - left.end);
7558
- const spans = [];
7559
- for (const hit of hits) {
7560
- const prior = spans.at(-1);
7561
- if (!prior || hit.start >= prior.end) {
7562
- spans.push(hit);
7563
- continue;
7564
- }
7565
- prior.end = Math.max(prior.end, hit.end);
7566
- if (categoryOrder.indexOf(hit.category) > categoryOrder.indexOf(prior.category)) prior.category = hit.category;
7567
- }
7568
- return spans;
7569
- }
7570
- /**
7571
- * Enum-like envelope values that native parsing interprets. Values inside an adapter-retained
7572
- * body are free text; outside bodies these names (and IDs) never take family terms.
7573
- */
7574
- const structuralNames = /* @__PURE__ */ new Set([
7575
- "type",
7576
- "role",
7577
- "name",
7578
- "subtype",
7579
- "stop_reason",
7580
- "status",
7581
- "kind",
7582
- "level",
7583
- "source",
7584
- "originator",
7585
- "mode",
7586
- "tool_name",
7587
- "toolName",
7588
- "function_name"
7589
- ]);
7590
- const structural = (name) => name !== void 0 && (structuralNames.has(name) || /(?:^id|_id|Id|uuid|Uuid)$/u.test(name));
7591
- /** Node IDs inside the adapter's retained bodies: the native free-text classification. */
7592
- function bodyNodes(root, selection) {
7593
- const bodies = new Set(selection.edits.map((edit) => edit.nodeId));
7594
- const nodes = /* @__PURE__ */ new Set();
7595
- const visit = (node, inside) => {
7596
- const body = inside || bodies.has(node.id);
7597
- if (body) nodes.add(node.id);
7598
- if (node.kind === "array") for (const item of node.items) visit(item, body);
7599
- if (node.kind === "object") for (const property of node.properties) visit(property.value, body);
7600
- };
7601
- visit(root, false);
7602
- return nodes;
7603
- }
7604
- /** Exact, cheap check that any string value can match: one linear scan whatever the term count. */
7605
- function mayMatch(root, family, signal) {
7606
- const values = [];
7579
+ //#region packages/artifact/src/configured/review/render.ts
7580
+ const hash$4 = (text) => createHash("sha256").update(text).digest("hex");
7581
+ const address = (pointer, inner) => JSON.stringify([pointer, inner ?? null]);
7582
+ /** Offsets in the same lossless serialization used by renderNative, including escaped JSON strings. */
7583
+ function stringOffsets(root, changes) {
7584
+ const offsets = /* @__PURE__ */ new Map();
7585
+ let offset = 0;
7607
7586
  const visit = (node) => {
7608
- if (node.kind === "string") values.push(node.value);
7609
- else if (node.kind === "array") for (const item of node.items) visit(item);
7610
- else if (node.kind === "object") for (const property of node.properties) visit(property.value);
7587
+ const changed = changes.get(node.id);
7588
+ if (node.kind === "string" || changed !== void 0) {
7589
+ offsets.set(node.id, offset + 1);
7590
+ offset += JSON.stringify(changed ?? (node.kind === "string" ? node.value : "")).length;
7591
+ } else if (node.kind === "literal") {
7592
+ offsets.set(node.id, offset);
7593
+ offset += node.raw.length;
7594
+ } else if (node.kind === "array") {
7595
+ offsets.set(node.id, offset);
7596
+ offset++;
7597
+ node.items.forEach((child, index) => {
7598
+ if (index) offset++;
7599
+ visit(child);
7600
+ });
7601
+ offset++;
7602
+ } else {
7603
+ offset++;
7604
+ node.properties.forEach((property, index) => {
7605
+ if (index) offset++;
7606
+ offset += JSON.stringify(property.key.value).length + 1;
7607
+ visit(property.value);
7608
+ });
7609
+ offset++;
7610
+ }
7611
7611
  };
7612
7612
  visit(root);
7613
- return family.matcher.hasCustomTerm(values.join("\0"), signal) || values.some((value) => /^\s*[[{]/u.test(value) && value.includes("\\"));
7613
+ return offsets;
7614
7614
  }
7615
- /** Masks family literals in unprotected, non-structural string values `skip` does not exclude. */
7616
- function maskFamilyFields(text, root, annotations, family, markers, signal, onApplied, bodies, skip) {
7617
- const changes = /* @__PURE__ */ new Map();
7618
- const evidence = { bytes: 0 };
7619
- const recordLimits = recordPointerLimits(limits, Buffer.byteLength(text));
7620
- for (const field of walkNativeFields(root, annotations, {
7621
- recordId: digest$4(text),
7622
- limits: recordLimits,
7623
- signal
7624
- })) {
7625
- if (skip(field)) continue;
7626
- if (field.text.includes(markers.prefix)) mismatch("marker-prefix");
7627
- if (field.subject !== "value" || field.scalarKind !== "string" || field.field.protection || !bodies.has(field.nodeId) && structural(field.field.name)) continue;
7628
- const raw = familySpans(field.text, family, signal);
7629
- const carrier = raw.length || field.text.includes("\\") ? familyCarrierSpans(field, (value) => familySpans(value, family, signal), signal) : void 0;
7630
- const spans = (carrier ?? raw).sort((left, right) => left.start - right.start);
7631
- if (!spans.length) continue;
7632
- const changed = maskOutputField({
7633
- pointer: field.pointer,
7634
- text: field.text,
7635
- sha256: digest$4(field.text)
7636
- }, spans, markers, evidence, onApplied);
7637
- if (carrier) validateFamilyCarrier(changed, signal);
7638
- changes.set(field.nodeId, changed);
7639
- }
7640
- return changes.size ? renderNative(root, changes, recordLimits, signal).text : text;
7615
+ const encodedLength = (text) => JSON.stringify(text).length - 2;
7616
+ /** Absolute JSON string-content coordinates. Fixed-size checkpoints bound both the work
7617
+ * per lookup and retained memory, including out-of-order overlapping contributor ranges. */
7618
+ function encodedOffset(text, base) {
7619
+ const stride = 1024;
7620
+ const offsets = [base];
7621
+ const boundary = (block) => {
7622
+ const at = block * stride;
7623
+ return scalarBoundary(text, at) ? at : at - 1;
7624
+ };
7625
+ return (position) => {
7626
+ const block = Math.floor(position / stride);
7627
+ while (offsets.length <= block) {
7628
+ const next = offsets.length;
7629
+ offsets.push((offsets[next - 1] ?? fail("ARTIFACT_PROCESSING_MISMATCH")) + encodedLength(text.slice(boundary(next - 1), boundary(next))));
7630
+ }
7631
+ return (offsets[block] ?? fail("ARTIFACT_PROCESSING_MISMATCH")) + encodedLength(text.slice(boundary(block), position));
7632
+ };
7641
7633
  }
7642
- /**
7643
- * Every row of a family part is parsed in order so native call/result state stays aligned.
7644
- * Worker rows: every unprotected string value. Main rows: every one that is not a B review
7645
- * field, which keeps its exact B decisions. Keys, roles, identities and tool links stay exact.
7646
- */
7647
- function createFamilyHideEditor(adapter, part, family, markers, signal, onApplied) {
7648
- const options = {
7649
- sourceRole: part.native.role,
7650
- nativeSessionId: part.native.sessionId
7634
+ /** Restore verified untouched scalar lexemes without round-tripping through JS numbers. */
7635
+ function restoreLiterals(root, literals) {
7636
+ const raw = literals.get(root.id);
7637
+ if (raw !== void 0) return {
7638
+ id: root.id,
7639
+ kind: "literal",
7640
+ raw
7651
7641
  };
7652
- const retention = adapter.retention(options);
7653
- return (text, reviewed = /* @__PURE__ */ new Set()) => {
7654
- checkAbort(signal);
7655
- const root = parseNativeRecord(text, limits, signal);
7656
- const selection = retention(root);
7657
- if (!mayMatch(root, family, signal)) return text;
7658
- return maskFamilyFields(text, root, adapter.annotations(root, options, selection), family, markers, signal, onApplied, bodyNodes(root, selection), (field) => reviewed.has(field.pointer));
7642
+ if (root.kind === "array") return {
7643
+ ...root,
7644
+ items: root.items.map((node) => restoreLiterals(node, literals))
7645
+ };
7646
+ if (root.kind === "object") return {
7647
+ ...root,
7648
+ properties: root.properties.map((entry) => ({
7649
+ ...entry,
7650
+ value: restoreLiterals(entry.value, literals)
7651
+ }))
7659
7652
  };
7653
+ return root;
7660
7654
  }
7661
- /** Session metadata is never analysed; its unprotected text (such as a title) takes family terms. */
7662
- function maskFamilyMetadata(text, family, markers, signal, onApplied) {
7663
- checkAbort(signal);
7664
- const root = parseNativeRecord(text, limits, signal);
7665
- return maskFamilyFields(text, root, metadataAnnotations(root), family, markers, signal, onApplied, /* @__PURE__ */ new Set(), () => false);
7655
+ /** Rewrite only admitted value leaves; every other byte comes from the verified static base. */
7656
+ function renderReviewRow(row, before, edits, markers, signal) {
7657
+ if (hash$4(before) !== row.outputSha256) fail("ARTIFACT_PROCESSING_MISMATCH");
7658
+ const raw = reviewNative(row.cleanedText, signal), actual = reviewNative(before, signal);
7659
+ const pending = /* @__PURE__ */ new Map();
7660
+ for (const edit of edits) {
7661
+ const key = address(edit.pointer, edit.innerPointer);
7662
+ if (pending.has(key)) fail("ARTIFACT_PROCESSING_MISMATCH");
7663
+ pending.set(key, edit);
7664
+ }
7665
+ const groups = /* @__PURE__ */ new Map();
7666
+ for (const field of row.fields) groups.set(field.pointer, [...groups.get(field.pointer) ?? [], field]);
7667
+ const changes = /* @__PURE__ */ new Map(), literals = /* @__PURE__ */ new Map(), transcripts = [], replaced = [];
7668
+ for (const [pointer, fields] of groups) {
7669
+ const first = fields[0] ?? fail("ARTIFACT_PROCESSING_MISMATCH"), original = nativePointer(raw, first.cleanedPointer), target = nativePointer(actual, pointer), nativeLiteral = first.scalarKind === "literal" && first.innerPointer === void 0, nativeContainer = first.scalarKind === "container" && first.innerPointer === void 0;
7670
+ if (nativeContainer ? nativeContainerText(original, signal) === void 0 || !["array", "string"].includes(target.kind) : nativeLiteral ? original.kind !== "literal" || !["literal", "string"].includes(target.kind) : original.kind !== "string" || target.kind !== "string") return fail("ARTIFACT_PROCESSING_MISMATCH");
7671
+ const inner = first.innerPointer === void 0 ? void 0 : original.kind === "string" ? reviewNative(original.value, signal) : fail("ARTIFACT_PROCESSING_MISMATCH");
7672
+ const innerChanges = /* @__PURE__ */ new Map(), pieces = [];
7673
+ for (const field of fields) {
7674
+ if (field.cleanedPointer !== first.cleanedPointer || field.innerPointer === void 0 !== (first.innerPointer === void 0)) fail("ARTIFACT_PROCESSING_MISMATCH");
7675
+ const source = inner && field.innerPointer !== void 0 ? nativePointer(inner, field.innerPointer) : original;
7676
+ const sourceValue = field.scalarKind === "container" ? nativeContainerText(source, signal) : field.scalarKind === "literal" ? source.kind === "literal" ? source.raw : void 0 : source.kind === "string" ? source.value : void 0;
7677
+ if (sourceValue === void 0 || sourceValue !== field.text || hash$4(sourceValue) !== field.fieldHash) return fail("ARTIFACT_PROCESSING_MISMATCH");
7678
+ const key = address(field.pointer, field.innerPointer), edit = pending.get(key);
7679
+ pending.delete(key);
7680
+ const spans = reviewSpans(field, edit), causes = new Map(spans.map((span) => [span.start, span])), items = [];
7681
+ const changed = replaceSemanticSpans(field.text, spans, markers, (span, replacement, start) => items.push({
7682
+ inputRange: {
7683
+ start: span.start,
7684
+ end: span.end
7685
+ },
7686
+ outputRange: {
7687
+ start,
7688
+ end: start + replacement.length
7689
+ },
7690
+ replacement,
7691
+ category: maskCategory(span.category),
7692
+ span: causes.get(span.start) ?? fail("ARTIFACT_PROCESSING_MISMATCH")
7693
+ }));
7694
+ pieces.push({
7695
+ node: source.id,
7696
+ field,
7697
+ source: sourceValue,
7698
+ changed,
7699
+ items
7700
+ });
7701
+ if (inner && changed !== sourceValue) innerChanges.set(source.id, changed);
7702
+ }
7703
+ const sourceText = inner ? renderNative(inner, /* @__PURE__ */ new Map(), reviewLimits, signal).text : nativeContainer ? nativeContainerText(original, signal) ?? fail("ARTIFACT_PROCESSING_MISMATCH") : original.kind === "string" ? original.value : original.kind === "literal" ? original.raw : fail("ARTIFACT_PROCESSING_MISMATCH");
7704
+ const changed = inner ? renderNative(inner, innerChanges, reviewLimits, signal).text : pieces[0]?.changed ?? fail("ARTIFACT_PROCESSING_MISMATCH");
7705
+ const sourceOffsets = inner ? stringOffsets(inner, /* @__PURE__ */ new Map()) : void 0, outputOffsets = inner ? stringOffsets(inner, innerChanges) : void 0;
7706
+ const inputSha256 = hash$4(sourceText), outputSha256 = hash$4(changed), context = createSentenceContext(sourceText);
7707
+ for (const piece of pieces) {
7708
+ if (!piece.items.length) continue;
7709
+ const inputOffset = sourceOffsets && encodedOffset(piece.source, sourceOffsets.get(piece.node) ?? fail("ARTIFACT_PROCESSING_MISMATCH"));
7710
+ const outputOffset = outputOffsets && encodedOffset(piece.changed, outputOffsets.get(piece.node) ?? fail("ARTIFACT_PROCESSING_MISMATCH"));
7711
+ const coordinates = (range) => inputOffset ? {
7712
+ start: inputOffset(range.start),
7713
+ end: inputOffset(range.end)
7714
+ } : range;
7715
+ for (const item of piece.items) {
7716
+ const inputRange = coordinates(item.inputRange);
7717
+ const start = outputOffset ? outputOffset(item.outputRange.start) : item.outputRange.start;
7718
+ const { span, ...applied } = item;
7719
+ const transcript = {
7720
+ ...applied,
7721
+ pointer,
7722
+ inputSha256,
7723
+ outputSha256,
7724
+ inputRange,
7725
+ outputRange: {
7726
+ start,
7727
+ end: start + item.replacement.length
7728
+ },
7729
+ context: context(inputRange)
7730
+ };
7731
+ transcripts.push({
7732
+ ...transcript,
7733
+ contributors: reconstructedContributors({
7734
+ row,
7735
+ field: piece.field,
7736
+ span,
7737
+ transcript,
7738
+ coordinates,
7739
+ context
7740
+ })
7741
+ });
7742
+ }
7743
+ }
7744
+ if (nativeContainer && changed === sourceText) {
7745
+ if (nativeContainerText(target, signal) !== sourceText) fail("ARTIFACT_PROCESSING_MISMATCH");
7746
+ } else if (nativeLiteral && changed === sourceText) literals.set(target.id, sourceText);
7747
+ else changes.set(target.id, changed);
7748
+ replaced.push(pointer);
7749
+ }
7750
+ if (pending.size) fail("ARTIFACT_PROCESSING_MISMATCH");
7751
+ const restored = literals.size ? restoreLiterals(actual, literals) : actual;
7752
+ return {
7753
+ text: renderNative(restored, changes, reviewLimits, signal).text,
7754
+ transcripts,
7755
+ replaced
7756
+ };
7666
7757
  }
7667
7758
  //#endregion
7668
7759
  //#region packages/artifact/src/configured/output/transform.ts
@@ -7686,6 +7777,7 @@ async function createOutputTransform(request, manifest, markers, signal) {
7686
7777
  session,
7687
7778
  part
7688
7779
  }])));
7780
+ const workspaceTitle = createWorkspaceTitleMasker(request, manifest, markers, signal);
7689
7781
  return {
7690
7782
  families,
7691
7783
  async metadata(text, entryPath) {
@@ -7695,7 +7787,7 @@ async function createOutputTransform(request, manifest, markers, signal) {
7695
7787
  return {
7696
7788
  text: family ? maskFamilyMetadata(text, family, markers, signal, (value) => transcripts.push(value)) : entryPath === manifest.work.metadataPath ? await updateOutputWorkMetadata(text, manifest, request, signal, (value) => {
7697
7789
  title = value;
7698
- }) : text,
7790
+ }) : workspaceTitle(text, entryPath, (value) => transcripts.push(value)),
7699
7791
  transcripts: title?.semanticTranscript ?? transcripts,
7700
7792
  titleMasks: title?.staticMasks
7701
7793
  };
@@ -9844,7 +9936,16 @@ function createSessionWorkerPool(url, size, heapMb = workerHeapMb) {
9844
9936
  stopping = Promise.all(slots.map(async (slot) => {
9845
9937
  try {
9846
9938
  await slot.process.close();
9847
- if (slot.task) await removeStoppedSpools(slot.task.spoolPaths);
9939
+ if (slot.task) {
9940
+ if (requestKind(slot.task) === "journey-base") {
9941
+ await removeNamedTemporarySpools(slot.task.spoolPaths);
9942
+ for (const path of slot.task.spoolPaths) try {
9943
+ await unlink(path);
9944
+ } catch (error) {
9945
+ if (filesystemCode(error) !== "ENOENT") throw error;
9946
+ }
9947
+ } else await removeStoppedSpools(slot.task.spoolPaths);
9948
+ }
9848
9949
  } finally {
9849
9950
  slot.task?.reject(blame(slot));
9850
9951
  slot.task = void 0;
@@ -9885,6 +9986,10 @@ function createSessionWorkerPool(url, size, heapMb = workerHeapMb) {
9885
9986
  }
9886
9987
  task.spoolPaths.add(message.path);
9887
9988
  task.onSpool?.(message.path);
9989
+ if (!closed) slot.process.send({
9990
+ kind: "spool-owned",
9991
+ path: message.path
9992
+ });
9888
9993
  } else if (message.kind === "result") {
9889
9994
  const requestedKind = requestKind(task);
9890
9995
  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) {
@@ -15312,9 +15417,35 @@ async function processJourneyMetadata(request, signal = new AbortController().si
15312
15417
  }
15313
15418
  //#endregion
15314
15419
  //#region packages/artifact/src/configured/journey/original.ts
15315
- /** Verify the complete frozen source into an unlinked private spool before yielding originals. */
15420
+ /** Fully verify before yielding by default; classification prefixes explicitly opt into early close. */
15316
15421
  async function* readCapturedOriginalRows(source, options, signal = new AbortController().signal) {
15317
15422
  const directory = await privateJourneyDirectory(options.directory);
15423
+ if (options.verification === "classification-prefix") {
15424
+ const cleanup = createCleanup();
15425
+ const input = await openCapturedFile(source.capture.source, source.capture.path, source.capture.facts, signal);
15426
+ try {
15427
+ let recordIndex = 0;
15428
+ const limits = resolveLimits();
15429
+ for await (const text of frameRecords(input.chunks, "jsonl", limits.maxRecordBytes, signal)) {
15430
+ parseNativeRecord(text, limits, signal);
15431
+ yield {
15432
+ harness: source.harness,
15433
+ sessionId: source.sessionId,
15434
+ sourcePartId: source.capture.partId,
15435
+ recordIndex: recordIndex++,
15436
+ rowSha256: createHash("sha256").update(text).digest("hex"),
15437
+ text
15438
+ };
15439
+ }
15440
+ await input.finish();
15441
+ } catch (error) {
15442
+ cleanup.failed(error);
15443
+ throw error;
15444
+ } finally {
15445
+ await cleanup.run(() => input.close());
15446
+ }
15447
+ return;
15448
+ }
15318
15449
  const temporary = await createTemporary({
15319
15450
  outputDir: directory,
15320
15451
  keepTemp: false
@@ -15473,7 +15604,7 @@ async function sessionFileFacts(file, size, signal) {
15473
15604
  /** Verify bounded final redacted bytes before starting a second ZIP codec. */
15474
15605
  async function sessionPart(entry, expected, signal) {
15475
15606
  if (expected.byteLength > 268435456 || entry.uncompressedSize !== expected.byteLength) fail("ARTIFACT_PART_LIMIT");
15476
- const file = await sessionFile();
15607
+ const scratch = expected.byteLength <= 65536 ? { bytes: new Uint8Array(expected.byteLength) } : { file: await sessionFile() };
15477
15608
  let size = 0;
15478
15609
  const digest = createHash("sha256");
15479
15610
  let crc = 0;
@@ -15483,11 +15614,14 @@ async function sessionPart(entry, expected, signal) {
15483
15614
  if (size + bytes.byteLength > expected.byteLength) fail("ARTIFACT_PART_LIMIT");
15484
15615
  digest.update(bytes);
15485
15616
  crc = crc32(bytes, crc);
15486
- let offset = 0;
15487
- while (offset < bytes.byteLength) {
15488
- const result = await file.write(bytes, offset, bytes.byteLength - offset, size + offset);
15489
- if (!result.bytesWritten) fail("ARTIFACT_IO_FAILED");
15490
- offset += result.bytesWritten;
15617
+ if (scratch.bytes) scratch.bytes.set(bytes, size);
15618
+ else {
15619
+ let offset = 0;
15620
+ while (offset < bytes.byteLength) {
15621
+ const { bytesWritten } = await scratch.file.write(bytes, offset, bytes.byteLength - offset, size + offset);
15622
+ if (!bytesWritten) fail("ARTIFACT_IO_FAILED");
15623
+ offset += bytesWritten;
15624
+ }
15491
15625
  }
15492
15626
  size += bytes.byteLength;
15493
15627
  } }), {
@@ -15495,55 +15629,93 @@ async function sessionPart(entry, expected, signal) {
15495
15629
  checkSignature: true
15496
15630
  });
15497
15631
  if (size !== expected.byteLength || digest.digest("hex") !== expected.sha256) fail("ARTIFACT_INVALID_ARCHIVE");
15632
+ const reader = scratch.bytes ? new Uint8ArrayReader(scratch.bytes) : new FileReader(scratch.file, size, 262144, true, signal);
15498
15633
  return {
15499
- file,
15634
+ file: scratch.file,
15635
+ reader,
15500
15636
  crc32: crc
15501
15637
  };
15502
15638
  } catch (error) {
15503
15639
  const cleanup = createCleanup();
15504
15640
  cleanup.failed(error);
15505
- await cleanup.run(() => file.close());
15641
+ const { file } = scratch;
15642
+ if (file) await cleanup.run(() => file.close());
15506
15643
  throw error;
15507
15644
  }
15508
15645
  }
15509
15646
  //#endregion
15510
15647
  //#region packages/artifact/src/configured/output/sessions.ts
15511
- /** Each yielded spool stays open until the caller advances or closes this iterator. */
15512
- async function* configuredSessionUploads(input, identities, signal) {
15648
+ async function* configuredSessionUploads(input, identities, signal, mode = "upload", omitted = /* @__PURE__ */ new Set(), checkMinimumBytes) {
15513
15649
  const verified = await checkFrozenOutput(input, signal);
15514
15650
  const archive = await openCheckedOutput(input, verified.checked, signal);
15515
15651
  const cleanup = createCleanup();
15516
15652
  try {
15517
15653
  if (archive.manifestText !== verified.manifestText) fail("ARTIFACT_PROCESSING_MISMATCH");
15518
15654
  const descriptions = new Map(verified.manifest.entries.map((entry) => [entry.entryPath, entry]));
15655
+ const byId = new Map(identities.map((identity) => [identity.archiveSessionId, identity]));
15656
+ if (byId.size !== identities.length) fail("ARTIFACT_IDENTITY_MISMATCH");
15657
+ if (checkMinimumBytes) {
15658
+ const measured = /* @__PURE__ */ new Set();
15659
+ let bytes = 0;
15660
+ for (const session of verified.manifest.sessions) {
15661
+ if (omitted.has(session.id)) continue;
15662
+ if (!byId.has(session.id)) fail("ARTIFACT_IDENTITY_MISMATCH");
15663
+ for (const part of session.parts) {
15664
+ const entry = descriptions.get(part.dataPath) ?? fail("ARTIFACT_INVALID_ARCHIVE");
15665
+ if (measured.has(entry.sha256)) continue;
15666
+ measured.add(entry.sha256);
15667
+ bytes += entry.byteLength;
15668
+ }
15669
+ }
15670
+ checkMinimumBytes(bytes);
15671
+ }
15672
+ const workspaces = new Map(verified.manifest.sourceWorkspaces.map((workspace) => [workspace.id, workspace]));
15673
+ const workspaceFacts = /* @__PURE__ */ new Map();
15519
15674
  for (const session of verified.manifest.sessions) {
15520
15675
  signal.throwIfAborted();
15521
- const identity = identities.find((item) => item.archiveSessionId === session.id) ?? fail("ARTIFACT_IDENTITY_MISMATCH");
15522
- const workspace = verified.manifest.sourceWorkspaces.find((item) => item.id === session.workspaceId) ?? fail("ARTIFACT_INVALID_MANIFEST");
15523
- const entry = archive.entries.get(workspace.metadataPath) ?? fail("ARTIFACT_INVALID_ARCHIVE");
15524
- const description = descriptions.get(workspace.metadataPath) ?? fail("ARTIFACT_INVALID_ARCHIVE");
15525
- const text = await readMetadata(entry, signal);
15526
- if (Buffer.byteLength(text) !== description.byteLength || createHash("sha256").update(text).digest("hex") !== description.sha256) fail("ARTIFACT_INVALID_ARCHIVE");
15527
- const { version: _, ...facts } = validateConfiguredSourceMetadata(strictJson(text, metadataLimitBytes), workspace);
15676
+ if (omitted.has(session.id)) continue;
15677
+ const identity = byId.get(session.id) ?? fail("ARTIFACT_IDENTITY_MISMATCH");
15678
+ const workspace = workspaces.get(session.workspaceId) ?? fail("ARTIFACT_INVALID_MANIFEST");
15679
+ let facts = workspaceFacts.get(workspace.id);
15680
+ if (!facts) {
15681
+ const entry = archive.entries.get(workspace.metadataPath) ?? fail("ARTIFACT_INVALID_ARCHIVE");
15682
+ const description = descriptions.get(workspace.metadataPath) ?? fail("ARTIFACT_INVALID_ARCHIVE");
15683
+ const text = await readMetadata(entry, signal);
15684
+ if (Buffer.byteLength(text) !== description.byteLength || createHash("sha256").update(text).digest("hex") !== description.sha256) fail("ARTIFACT_INVALID_ARCHIVE");
15685
+ const { version: _, ...validated } = validateConfiguredSourceMetadata(strictJson(text, metadataLimitBytes), workspace);
15686
+ facts = validated;
15687
+ workspaceFacts.set(workspace.id, facts);
15688
+ }
15528
15689
  const native = session.parts[0]?.native;
15529
15690
  const nativeSessionId = native?.sessionId ?? session.sourceSessionId;
15530
15691
  if (!nativeSessionId?.trim() && !identity.relativePath) fail("ARTIFACT_IDENTITY_MISMATCH");
15531
15692
  const metadata = {
15532
- workspace: facts,
15693
+ workspace: {
15694
+ ...facts,
15695
+ remoteHashes: [...facts.remoteHashes]
15696
+ },
15533
15697
  sourceSessionId: nativeSessionId,
15534
15698
  harness: session.harness,
15535
15699
  lastAt: identity.lastAt,
15536
15700
  parts: []
15537
15701
  };
15538
- const file = await sessionFile();
15702
+ const file = mode === "upload" ? await sessionFile() : null;
15539
15703
  const sessionCleanup = createCleanup();
15540
15704
  try {
15541
15705
  let size = 0;
15542
- const sink = fileWriter(file, signal, (bytes) => {
15706
+ const limit = (bytes) => {
15543
15707
  if (bytes > 5 * 1024 ** 3) fail("ARTIFACT_ARCHIVE_LIMIT");
15544
15708
  size = bytes;
15545
- }, false);
15546
- const zip = new ZipWriter(sink.writable, {
15709
+ };
15710
+ const digest = createHash("sha256");
15711
+ let checksum = 0;
15712
+ const writable = file ? fileWriter(file, signal, limit, false).writable : new WritableStream({ write(bytes) {
15713
+ signal.throwIfAborted();
15714
+ limit(size + bytes.byteLength);
15715
+ digest.update(bytes);
15716
+ checksum = crc32(bytes, checksum);
15717
+ } });
15718
+ const zip = new ZipWriter(writable, {
15547
15719
  useWebWorkers: false,
15548
15720
  useCompressionStream: true,
15549
15721
  bufferedWrite: false,
@@ -15559,24 +15731,30 @@ async function* configuredSessionUploads(input, identities, signal) {
15559
15731
  const partCleanup = createCleanup();
15560
15732
  try {
15561
15733
  const path = `p${String(index + 1).padStart(6, "0")}.jsonl`;
15562
- await zip.add(path, new FileReader(prepared.file, expected.byteLength, 262144, true, signal), { signal });
15734
+ await zip.add(path, prepared.reader, { signal });
15563
15735
  metadata.parts.push({
15564
15736
  path,
15565
15737
  byteLength: expected.byteLength,
15566
15738
  sha256: expected.sha256,
15567
- crc32: prepared.crc32
15739
+ crc32: prepared.crc32,
15740
+ native: part.native
15568
15741
  });
15569
15742
  } catch (error) {
15570
15743
  partCleanup.failed(error);
15571
15744
  throw error;
15572
15745
  } finally {
15573
- await partCleanup.run(() => prepared.file.close());
15746
+ const { file } = prepared;
15747
+ if (file) await partCleanup.run(() => file.close());
15574
15748
  }
15575
15749
  }
15576
15750
  await zip.close();
15577
15751
  if (zip.warnings?.length) fail("ARTIFACT_INVALID_ARCHIVE");
15578
15752
  if (size > 5 * 1024 ** 3) fail("ARTIFACT_ARCHIVE_LIMIT");
15579
- const content = await sessionFileFacts(file, size, signal);
15753
+ const content = file ? await sessionFileFacts(file, size, signal) : {
15754
+ byteLength: size,
15755
+ sha256: digest.digest("hex"),
15756
+ crc32: checksum
15757
+ };
15580
15758
  await archive.fence();
15581
15759
  yield {
15582
15760
  ...content,
@@ -15586,13 +15764,13 @@ async function* configuredSessionUploads(input, identities, signal) {
15586
15764
  relativePath: identity.relativePath,
15587
15765
  harness: session.harness,
15588
15766
  lastAt: identity.lastAt,
15589
- stream: () => new FileReader(file, size, 262144, true, signal).createReadable()
15767
+ ...file ? { stream: () => new FileReader(file, size, 262144, true, signal).createReadable() } : {}
15590
15768
  };
15591
15769
  } catch (error) {
15592
15770
  sessionCleanup.failed(error);
15593
15771
  throw error;
15594
15772
  } finally {
15595
- await sessionCleanup.run(() => file.close());
15773
+ if (file) await sessionCleanup.run(() => file.close());
15596
15774
  }
15597
15775
  }
15598
15776
  } catch (error) {
@@ -16361,7 +16539,7 @@ const maxChunks = 8e4;
16361
16539
  function batchLoad(body) {
16362
16540
  return Math.max(body.chunks.length / maxChunks, (body.duplicates?.length ?? 0) / maxChunks, Buffer.byteLength(JSON.stringify(body)) / maxTransportBytes);
16363
16541
  }
16364
- function location(context, fieldId, part) {
16542
+ function location$1(context, fieldId, part) {
16365
16543
  const source = context.locations.get(fieldId);
16366
16544
  if (!source) throw new ApplicationError("CORRUPTED_STATE");
16367
16545
  const native = reviewSource(source);
@@ -16400,7 +16578,7 @@ function reviewBatchBody(context, unit, ordinal) {
16400
16578
  };
16401
16579
  const chunks = unit.fragments.map((part) => ({
16402
16580
  id: chunkId(part.fieldId, part),
16403
- ...location(context, part.fieldId, part),
16581
+ ...location$1(context, part.fieldId, part),
16404
16582
  core: part.core,
16405
16583
  offset: part.utf16Start,
16406
16584
  text: part.text,
@@ -16420,7 +16598,7 @@ function reviewBatchBody(context, unit, ordinal) {
16420
16598
  utf16Start: part.utf16Start + shift.utf16,
16421
16599
  utf16End: part.utf16End + shift.utf16
16422
16600
  };
16423
- const { displayMasks, ...own } = location(context, duplicate.fieldId, copy);
16601
+ const { displayMasks, ...own } = location$1(context, duplicate.fieldId, copy);
16424
16602
  const hash = fieldHash(duplicate.fieldId);
16425
16603
  return {
16426
16604
  id: chunkId(duplicate.fieldId, copy),
@@ -16910,7 +17088,7 @@ async function prepareSessionScans(request, signal) {
16910
17088
  const opened = await openSourceCapture(request.captures.get(part.path) ?? fail("ARTIFACT_SOURCE_CHANGED"));
16911
17089
  const cleanup = createCleanup();
16912
17090
  try {
16913
- return await inspectCapturedSourceIdentity(part, opened, adapter, currentSignal, limits);
17091
+ return await (part.nativeEvidence?.identity?.role === "main" ? inspectCapturedSourceIdentity : inspectCompleteCapturedSourceIdentity)(part, opened, adapter, currentSignal, limits);
16914
17092
  } catch (error) {
16915
17093
  cleanup.failed(error);
16916
17094
  throw error;
@@ -17011,4 +17189,277 @@ async function verifyPreparedSessionSources(prepared, input, signal) {
17011
17189
  }
17012
17190
  }
17013
17191
  //#endregion
17014
- export { removeNamedTemporarySpools 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, createTemporary 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, decodeZstd as Z, processJourneyMetadata as _, scanReviewFields as a, restrictToOwner as at, writeLogicalJourneyBase as b, readSessionScanRecords as c, windowsAclCodes as ct, verifyOutputShard as d, createCleanup as et, writeOutputShard as f, readCapturedOriginalRows as g, captureConfiguredSessionJob as h, buildWorkScanBatches as i, openPrivateFile as it, runConfiguredSessionJob as j, capturedJourneyScope as k, scanPreparedSession as l, openConfiguredUpload as m, verifyPreparedSessionSources as n, exclusiveLock as nt, createWorkPieces as o, windowsOwnerOnly as ot, configuredSessionUploads as p, readWorkspacePair as q, prepareSessionScans as r, makePrivateDirectory as rt, readSessionScanFields as s, isWindowsAclFailure as st, preparedScanConfiguration as t, safeError as tt, runConfiguredScanJob as u, readStaticSessionMasks as v, readConfiguredSearchFields as w, writePrivateReviewPayload as x, staticSessionJobs as y, gitSeedsProvider as z };
17192
+ //#region packages/artifact/src/configured/output/session-mask-equivalence.ts
17193
+ const exactMarker = new RegExp("^(?:" + replacementMarkerPattern.source + ")$", "u");
17194
+ function sessionMaskProof(row) {
17195
+ const lineage = row.contributors.map((item) => {
17196
+ const { inputRange, context } = item.kind === "static" ? item.source.mask : item.source;
17197
+ const quote = context.text.slice(inputRange.start - context.start, inputRange.end - context.start);
17198
+ const basis = item.kind === "static" ? [
17199
+ item.source.sourceRecordIndex,
17200
+ item.source.mask.originalPointer,
17201
+ item.source.mask.sourceRange,
17202
+ item.source.mask.inputSha256,
17203
+ item.source.mask.stepId,
17204
+ item.source.mask.node.id,
17205
+ item.source.mask.node.version,
17206
+ item.source.mask.ruleId
17207
+ ] : [item.source.pointer];
17208
+ return JSON.stringify([
17209
+ item.kind,
17210
+ item.category,
17211
+ basis,
17212
+ inputRange.start,
17213
+ inputRange.end,
17214
+ quote
17215
+ ]);
17216
+ }).sort();
17217
+ const first = row.contributors[0];
17218
+ return {
17219
+ pointer: row.pointer,
17220
+ subject: row.subject,
17221
+ start: row.outputRange.start,
17222
+ end: row.outputRange.end,
17223
+ replacement: row.replacement,
17224
+ lineage: createHash("sha256").update(JSON.stringify([row.category, lineage])).digest("hex"),
17225
+ 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
17226
+ };
17227
+ }
17228
+ const location = (mask) => JSON.stringify([
17229
+ mask.pointer,
17230
+ mask.subject,
17231
+ mask.start,
17232
+ mask.end
17233
+ ]);
17234
+ /** Both ledgers have already been independently joined to their own frozen output by the verifier. */
17235
+ function compareSessionRows(leftText, rightText, leftMasks, rightMasks) {
17236
+ if (leftMasks.length !== rightMasks.length) return null;
17237
+ const rightByLocation = new Map(rightMasks.map((mask) => [location(mask), mask]));
17238
+ if (rightByLocation.size !== rightMasks.length) return null;
17239
+ const changes = /* @__PURE__ */ new Map();
17240
+ const aliases = /* @__PURE__ */ new Map();
17241
+ const reverse = /* @__PURE__ */ new Map();
17242
+ for (const left of leftMasks) {
17243
+ const key = location(left);
17244
+ const right = rightByLocation.get(key);
17245
+ if (!right || left.lineage !== right.lineage) return null;
17246
+ rightByLocation.delete(key);
17247
+ if (left.replacement === right.replacement) continue;
17248
+ if (!left.mayRename || !right.mayRename || left.start < 0 || left.end - left.start !== left.replacement.length || right.replacement.length !== left.replacement.length) return null;
17249
+ const prior = aliases.get(left.replacement);
17250
+ const inverse = reverse.get(right.replacement);
17251
+ if (prior !== void 0 && prior !== right.replacement || inverse !== void 0 && inverse !== left.replacement) return null;
17252
+ aliases.set(left.replacement, right.replacement);
17253
+ reverse.set(right.replacement, left.replacement);
17254
+ const masks = changes.get(left.pointer) ?? [];
17255
+ masks.push(left);
17256
+ changes.set(left.pointer, masks);
17257
+ }
17258
+ if (!aliases.size) return leftText === rightText ? { aliases: [] } : null;
17259
+ const limits = {
17260
+ ...defaultLimits,
17261
+ maxRecordBytes: maximumRecordBytes
17262
+ };
17263
+ let tree;
17264
+ try {
17265
+ tree = parseNativeRecord(leftText, limits, new AbortController().signal);
17266
+ } catch {
17267
+ return null;
17268
+ }
17269
+ const changedCount = [...changes.values()].reduce((sum, field) => sum + field.length, 0);
17270
+ function authenticOccurrences(root, destination) {
17271
+ let used = 0;
17272
+ const markers = destination ? reverse : aliases;
17273
+ function check(node, pointer) {
17274
+ if (node.kind === "array") return node.items.every((item, i) => check(item, pointer + "/" + i));
17275
+ if (node.kind === "object") return node.properties.every(({ key, value }) => {
17276
+ for (const found of key.value.matchAll(replacementMarkerPattern)) if (markers.has(found[0])) return false;
17277
+ return check(value, pointer + "/" + key.value.replaceAll("~", "~0").replaceAll("/", "~1"));
17278
+ });
17279
+ if (node.kind !== "string") return true;
17280
+ const expected = new Map((changes.get(pointer) ?? []).map((mask) => [mask.start, mask]));
17281
+ for (const found of node.value.matchAll(replacementMarkerPattern)) {
17282
+ if (!markers.has(found[0])) continue;
17283
+ const mask = expected.get(found.index);
17284
+ if (!mask || (destination ? aliases.get(mask.replacement) : mask.replacement) !== found[0]) return false;
17285
+ expected.delete(found.index);
17286
+ used++;
17287
+ }
17288
+ return expected.size === 0;
17289
+ }
17290
+ return check(root, "") && used === changedCount;
17291
+ }
17292
+ if (!authenticOccurrences(tree, false)) return null;
17293
+ for (const winner of aliases.values()) if (aliases.has(winner)) return null;
17294
+ let replaced = 0;
17295
+ const renamed = leftText.replace(replacementMarkerPattern, (marker) => {
17296
+ const mapped = aliases.get(marker);
17297
+ if (!mapped) return marker;
17298
+ replaced++;
17299
+ return mapped;
17300
+ });
17301
+ if (changedCount !== replaced || renamed !== rightText) return null;
17302
+ try {
17303
+ if (!authenticOccurrences(parseNativeRecord(rightText, limits, new AbortController().signal), true)) return null;
17304
+ } catch {
17305
+ return null;
17306
+ }
17307
+ return { aliases: [...aliases] };
17308
+ }
17309
+ //#endregion
17310
+ //#region packages/artifact/src/configured/output/session-source-prefix.ts
17311
+ /**
17312
+ * Both parts come from the verified frozen primary. The caller locates longerSource through
17313
+ * its base source binding. A copied log may have a different path or inode from its ancestor.
17314
+ */
17315
+ async function sessionSourcePrefix(short, long, longerSource, signal) {
17316
+ checkAbort(signal);
17317
+ 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;
17318
+ if (short.source.byteLength === long.source.byteLength) return short.source.sha256 === long.source.sha256 && short.recordCount === long.recordCount;
17319
+ 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;
17320
+ try {
17321
+ checkNativeEvidence(longerSource, long.native);
17322
+ const input = await openConfiguredSource(longerSource, signal, void 0, "stable-prefix");
17323
+ try {
17324
+ const prefix = createHash("sha256");
17325
+ let remaining = short.source.byteLength;
17326
+ let endsAtRecord = false;
17327
+ for await (const chunk of input.chunks) {
17328
+ const take = Math.min(remaining, chunk.byteLength);
17329
+ if (take === 0) continue;
17330
+ prefix.update(chunk.subarray(0, take));
17331
+ remaining -= take;
17332
+ if (remaining === 0) endsAtRecord = chunk[take - 1] === 10;
17333
+ }
17334
+ const full = await input.finish();
17335
+ return remaining === 0 && endsAtRecord && prefix.digest("hex") === short.source.sha256 && full.sha256 === long.source.sha256 && full.byteLength === long.source.byteLength;
17336
+ } finally {
17337
+ await input.close();
17338
+ }
17339
+ } catch (error) {
17340
+ checkAbort(signal);
17341
+ if ([
17342
+ "ARTIFACT_SOURCE_CHANGED",
17343
+ "ARTIFACT_SOURCE_MISSING",
17344
+ "ARTIFACT_SOURCE_UNSAFE",
17345
+ "ARTIFACT_SOURCE_UNREADABLE",
17346
+ "ARTIFACT_SOURCE_TRUNCATED"
17347
+ ].includes(safeError(error).message)) return false;
17348
+ throw error;
17349
+ }
17350
+ }
17351
+ //#endregion
17352
+ //#region packages/artifact/src/configured/output/session-extension.ts
17353
+ /** Choose an entire already-approved variant. No edited or reconstructed bytes enter transport. */
17354
+ async function sessionExtensions(input, signal) {
17355
+ const verified = await checkFrozenOutput(input.primary, signal);
17356
+ const { manifest } = verified;
17357
+ const sessions = new Map(manifest.sessions.map((session) => [session.id, session]));
17358
+ const groups = input.groups.map((group) => group.map((id) => sessions.get(id) ?? fail("ARTIFACT_IDENTITY_MISMATCH")));
17359
+ const paths = new Set(groups.flat().flatMap((session) => session.parts.map((part) => part.dataPath)));
17360
+ const masks = /* @__PURE__ */ new Map();
17361
+ for await (const row of readLogicalJourneyFinalMasks({
17362
+ ledger: input.ledger,
17363
+ primary: input.primary
17364
+ }, signal, paths)) {
17365
+ const entry = masks.get(row.entryPath) ?? /* @__PURE__ */ new Map();
17366
+ if (!masks.has(row.entryPath)) masks.set(row.entryPath, entry);
17367
+ const list = entry.get(row.recordIndex) ?? [];
17368
+ list.push(sessionMaskProof(row));
17369
+ entry.set(row.recordIndex, list);
17370
+ }
17371
+ const archive = await openCheckedOutput(input.primary, verified.checked, signal);
17372
+ const omitted = /* @__PURE__ */ new Set();
17373
+ const aliases = /* @__PURE__ */ new Map();
17374
+ try {
17375
+ for (const group of groups) {
17376
+ const score = (s) => s.parts.reduce((sum, p) => sum + p.retainedRecordCount, 0);
17377
+ 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));
17378
+ const winner = sorted[0];
17379
+ if (!winner) continue;
17380
+ for (const shorter of sorted.slice(1)) {
17381
+ 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;
17382
+ for (const [index, part] of shorter.parts.entries()) {
17383
+ const long = winner.parts[index];
17384
+ if (!long || part.retainedRecordCount > long.retainedRecordCount || !await sessionSourcePrefix(part, long, input.sourceFor(winner.id, long.sourceId), signal)) return null;
17385
+ if (!await compareParts(archive, manifest, part, long, masks, aliases, signal)) return null;
17386
+ }
17387
+ omitted.add(shorter.id);
17388
+ }
17389
+ }
17390
+ for (const value of aliases.values()) if (aliases.has(value)) return null;
17391
+ await archive.fence();
17392
+ return {
17393
+ omitted,
17394
+ retired: new Set(aliases.keys())
17395
+ };
17396
+ } finally {
17397
+ await archive.close();
17398
+ }
17399
+ }
17400
+ async function compareParts(archive, manifest, short, long, masks, aliases, signal) {
17401
+ const cleanup = createCleanup();
17402
+ const spools = [];
17403
+ try {
17404
+ for (const part of [short, long]) {
17405
+ const entry = archive.entries.get(part.dataPath) ?? fail("ARTIFACT_INVALID_ARCHIVE");
17406
+ const expected = manifest.entries.find((d) => d.entryPath === part.dataPath) ?? fail("ARTIFACT_INVALID_MANIFEST");
17407
+ spools.push(await spoolFacts(entry, expected, signal));
17408
+ }
17409
+ const [a, b] = spools;
17410
+ if (!a || !b) return fail("ARTIFACT_INVALID_ARCHIVE");
17411
+ let count = 0;
17412
+ for await (const row of a.lines) {
17413
+ const match = await b.lines.next();
17414
+ if (match.done) return false;
17415
+ const proof = compareSessionRows(row, match.value, masks.get(short.dataPath)?.get(count) ?? [], masks.get(long.dataPath)?.get(count) ?? []);
17416
+ if (!proof) return false;
17417
+ for (const [old, chosen] of proof.aliases) {
17418
+ if (aliases.has(old) && aliases.get(old) !== chosen) return false;
17419
+ aliases.set(old, chosen);
17420
+ }
17421
+ count++;
17422
+ }
17423
+ if (count !== short.retainedRecordCount) return false;
17424
+ for await (const _ of b.lines) count++;
17425
+ return count === long.retainedRecordCount;
17426
+ } catch (error) {
17427
+ cleanup.failed(error);
17428
+ throw error;
17429
+ } finally {
17430
+ await cleanup.run(...spools.flatMap((s) => [() => s.lines.return(void 0), () => s.close()]));
17431
+ }
17432
+ }
17433
+ /** Matches complete decoded marker spellings, including Unicode escape spellings in native JSON. */
17434
+ function refersToRetiredMarker(text, retired) {
17435
+ let candidate = text;
17436
+ for (let depth = 0; /\\u[\da-f]{4}/iu.test(candidate); depth++) {
17437
+ if (depth >= 8) return true;
17438
+ candidate = candidate.replace(/\\+u([\da-f]{4})/giu, (_, digits) => String.fromCharCode(Number.parseInt(digits, 16)));
17439
+ }
17440
+ for (const match of candidate.matchAll(replacementMarkerPattern)) if (retired.has(match[0])) return true;
17441
+ return false;
17442
+ }
17443
+ /** Search all kept uploaded fields of a confirmed Work before retiring an alias in another session. */
17444
+ async function hasRetiredSessionMarker(primary, omitted, retired, signal) {
17445
+ if (!retired.size) return false;
17446
+ const verified = await checkFrozenOutput(primary, signal);
17447
+ const archive = await openCheckedOutput(primary, verified.checked, signal);
17448
+ try {
17449
+ const entries = new Map(verified.manifest.entries.map((entry) => [entry.entryPath, entry]));
17450
+ 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;
17451
+ for (const session of verified.manifest.sessions) {
17452
+ if (omitted.has(session.id)) continue;
17453
+ for (const part of session.parts) {
17454
+ const entry = archive.entries.get(part.dataPath) ?? fail("ARTIFACT_INVALID_ARCHIVE");
17455
+ const expected = entries.get(part.dataPath) ?? fail("ARTIFACT_INVALID_ARCHIVE");
17456
+ for await (const row of entryLines(entry, expected, signal)) if (refersToRetiredMarker(row, retired)) return true;
17457
+ }
17458
+ }
17459
+ return false;
17460
+ } finally {
17461
+ await archive.close();
17462
+ }
17463
+ }
17464
+ //#endregion
17465
+ export { createConfiguredPreviewStream 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, confirmedFamily as J, readConfiguredOutputInfo as K, SessionWorkerError as L, renderJobDigest as M, runConfiguredSessionJob as N, checkReusableBundle as O, readCollectionIndex as P, listAgentSetup as Q, sessionWorkerFailure as R, writeLogicalJourneyBase as S, readOriginalSearchFields as T, writeLogicalJourneyOutput as U, gitSeedsProvider as V, privateJourneyDirectory as W, staticMaskCategory as X, confirmedTitleSpans as Y, readWorkspacePair as Z, captureConfiguredSessionJob as _, prepareSessionScans as a, safeError as at, readStaticSessionMasks as b, createWorkPieces as c, openPrivateFile as ct, scanPreparedSession as d, isWindowsAclFailure as dt, createInspectionProcessor as et, runConfiguredScanJob as f, windowsAclCodes as ft, openConfiguredUpload as g, configuredSessionUploads as h, verifyPreparedSessionSources as i, createCleanup as it, capturedJourneyScope as j, prepareCollectionProduction as k, readSessionScanFields as l, restrictToOwner as lt, writeOutputShard as m, sessionExtensions as n, createTemporary as nt, buildWorkScanBatches as o, exclusiveLock as ot, verifyOutputShard as p, processJourneyMetadataFields as q, preparedScanConfiguration as r, removeNamedTemporarySpools as rt, scanReviewFields as s, makePrivateDirectory as st, hasRetiredSessionMarker as t, decodeZstd as tt, readSessionScanRecords as u, windowsOwnerOnly as ut, readCapturedOriginalRows as v, readPrivateReviewPayload as w, staticSessionJobs as x, processJourneyMetadata as y, privateCollectionDirectory as z };