@gitroll/tacitt-cli 0.6.12 → 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 (38) hide show
  1. package/dist/{agent-setup-B12VbvN_.mjs → agent-setup-Doy_AnPY.mjs} +2 -2
  2. package/dist/agent-setup-worker.mjs +5 -5
  3. package/dist/cli.mjs +10 -10
  4. package/dist/codex-title-worker.mjs +1 -1
  5. package/dist/configured-preview-worker.mjs +5 -5
  6. package/dist/configured-session-worker.mjs +5 -5
  7. package/dist/{frame-B3He21G8.mjs → frame-BPbypzmt.mjs} +1 -1
  8. package/dist/{heap-Blrat--4.mjs → heap-DCS_WXIA.mjs} +7 -3
  9. package/dist/inspection-worker.mjs +4 -4
  10. package/dist/{job-CBuIMTQ0.mjs → job--zxwgaPy.mjs} +135 -36
  11. package/dist/{locate-D-ZaHpI0.mjs → locate-PLEyLYW-.mjs} +287 -236
  12. package/dist/{model-DR9odhWP.mjs → model-CyXvsWLz.mjs} +1 -1
  13. package/dist/operation-executor.mjs +3 -3
  14. package/dist/preview-worker.mjs +1 -1
  15. package/dist/privacy-validator.mjs +1 -1
  16. package/dist/{query-BYDcNKy2.mjs → query-BC7MIaWc.mjs} +335 -115
  17. package/dist/{run-DQ9xyKSt.mjs → run-Dod7Vykp.mjs} +6 -6
  18. package/dist/{src-DeNJ8vOD.mjs → src-CP-K2PBv.mjs} +1779 -1686
  19. package/dist/{src-Do-qzuMn.mjs → src-CttNuxOn.mjs} +590 -542
  20. package/dist/{src-CKQlTA2Z.mjs → src-dL6y2mcu.mjs} +180 -30
  21. package/dist/store-database-worker.mjs +1 -1
  22. package/package.json +1 -1
  23. package/skills/tacitt/SKILL.md +3 -3
  24. package/skills/tacitt/references/b-method.md +4 -2
  25. package/skills/tacitt/references/bootstrap.md +1 -1
  26. package/skills/tacitt/references/commands.md +10 -4
  27. package/skills/tacitt/references/journey.md +3 -3
  28. package/skills/tacitt/references/parallel-review.md +22 -9
  29. package/skills/tacitt/references/remote-workers.md +6 -2
  30. package/skills/tacitt/scripts/INDEX.md +4 -4
  31. package/skills/tacitt/scripts/answer.mjs +12 -1
  32. package/skills/tacitt/scripts/describe.mjs +3 -2
  33. package/skills/tacitt/scripts/journey-classification.mjs +1 -0
  34. package/skills/tacitt/scripts/journey-scan-timing.mjs +3 -2
  35. package/skills/tacitt/scripts/journey.mjs +1 -1
  36. package/skills/tacitt/scripts/privacy-validator.mjs +84 -33
  37. package/skills/tacitt/scripts/review.d.mts +1 -0
  38. package/skills/tacitt/scripts/review.mjs +296 -35
@@ -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-D-ZaHpI0.mjs";
2
- import { t as createZstdFrameCheck } from "./frame-B3He21G8.mjs";
3
- import { L as sourceIdentityEvidence, Mn as resolveSourceSelection, Ni as approvedTreatmentSchema, Qr as metadataProcessingVersion, R as withSourceEvidence, Ri as staticCatalogRef, ai as agentSourcePathSegment, ar as bWordBounded, ji as sourceChangePolicy, nr as bExceptionRanges, oi as agentSourceSchema, ot as classifyAgentSetup, st as defaultAgentSetupInclusion, tr as bContainment, z as agentSetupKey } from "./src-Do-qzuMn.mjs";
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";
@@ -15,7 +15,7 @@ import { ERR_UNSUPPORTED_FORMAT, Reader, TextReader, Uint8ArrayReader, ZipReader
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";
@@ -2787,7 +2787,7 @@ async function* decodeZstd(source, signal) {
2787
2787
  });
2788
2788
  const decoded = createZstdDecompress({
2789
2789
  chunkSize: sourceChunkBytes,
2790
- params: { [constants$1.ZSTD_d_windowLogMax]: 26 }
2790
+ params: { [constants$2.ZSTD_d_windowLogMax]: 26 }
2791
2791
  });
2792
2792
  const cancellation = new AbortController();
2793
2793
  const completion = pipeline(input, decoded, { signal: AbortSignal.any([signal, cancellation.signal]) }).then(() => void 0, (error) => error);
@@ -3245,7 +3245,11 @@ async function inspectInput(input, part, adapter, signal, overrides, complete =
3245
3245
  checkNativeEvidence(part, identity);
3246
3246
  return identity;
3247
3247
  } catch (error) {
3248
- 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;
3249
3253
  cleanup.failed(failure);
3250
3254
  if (signal.aborted) fail("ARTIFACT_ABORTED", { cause: failure });
3251
3255
  throw failure;
@@ -3263,7 +3267,7 @@ async function inspectSourceIdentity(part, adapter, signal, overrides, observe)
3263
3267
  async function inspectCapturedSourceIdentity(part, captured, adapter, signal, overrides) {
3264
3268
  return inspectInput(await openCapturedConfiguredSource(part, captured, signal), part, adapter, signal, overrides);
3265
3269
  }
3266
- /** Ancestor publication waits for identity accumulated over every fixed captured record. */
3270
+ /** Frozen admission and ancestor publication use identity from every captured record. */
3267
3271
  async function inspectCompleteCapturedSourceIdentity(part, captured, adapter, signal, overrides, observe) {
3268
3272
  return inspectInput(await openCapturedConfiguredSource(part, captured, signal), part, adapter, signal, overrides, true, observe);
3269
3273
  }
@@ -5708,13 +5712,6 @@ function addMaskSummary(a, b) {
5708
5712
  return result;
5709
5713
  }
5710
5714
  //#endregion
5711
- //#region packages/processing/src/session/marker.ts
5712
- /**
5713
- * One complete replacement marker as bindings and semantic markers write it. Group 1 names the
5714
- * static method, or `semantic` for an AI-review span. Dependency-free so the browser can use it.
5715
- */
5716
- const replacementMarkerPattern = /\[sp_[a-z0-9]{8,48}_([a-z][a-z0-9_]{0,47})_[a-f0-9]{24,64}\]/gu;
5717
- //#endregion
5718
5715
  //#region packages/artifact/src/configured/output/spans.ts
5719
5716
  function scalarBoundary(text, offset) {
5720
5717
  if (offset === 0 || offset === text.length) return true;
@@ -5800,6 +5797,9 @@ function indexOutputEdits(manifest, edits) {
5800
5797
  }
5801
5798
  return rows;
5802
5799
  }
5800
+ function rejectSemanticMarkerPrefix(text, markers) {
5801
+ if (text.includes(markers.prefix)) fail("ARTIFACT_PROCESSING_MISMATCH");
5802
+ }
5803
5803
  /** Parse/walk even unchanged records so native call/result state stays in source order. */
5804
5804
  function createOutputRowEditor(adapter, part, edits, markers, signal, onApplied) {
5805
5805
  const options = {
@@ -5823,7 +5823,7 @@ function createOutputRowEditor(adapter, part, edits, markers, signal, onApplied)
5823
5823
  limits: recordLimits,
5824
5824
  signal
5825
5825
  })) {
5826
- if (field.text.includes(markers.prefix)) fail("ARTIFACT_PROCESSING_MISMATCH");
5826
+ rejectSemanticMarkerPrefix(field.text, markers);
5827
5827
  if (field.subject !== "value") continue;
5828
5828
  const edit = pending.get(field.pointer);
5829
5829
  if (!edit) continue;
@@ -5894,1800 +5894,1866 @@ function maskOutputField(field, spans, markers, evidence, onApplied) {
5894
5894
  return changed;
5895
5895
  }
5896
5896
  //#endregion
5897
- //#region packages/artifact/src/collection/identity-map.ts
5898
- const maximumBundleIdentityMapBytes = 8388608;
5899
- const maximumLocatorBytes = 16384;
5900
- const maximumRemotes = 4096;
5901
- const uuid$2 = /^[a-f0-9]{8}-(?:[a-f0-9]{4}-){3}[a-f0-9]{12}$/;
5902
- const digest$3 = /^[a-f0-9]{64}$/;
5903
- function validBundleId(bundleId) {
5904
- if (!uuid$2.test(bundleId)) fail("ARTIFACT_INVALID_MANIFEST");
5905
- }
5906
- function boundedLocator(value) {
5907
- const result = string(value);
5908
- if (Buffer.byteLength(result) > maximumLocatorBytes) fail("ARTIFACT_METADATA_LIMIT");
5909
- return result;
5910
- }
5911
- function boundedHash(value) {
5912
- const result = string(value);
5913
- if (!digest$3.test(result)) fail("ARTIFACT_INVALID_MANIFEST");
5914
- return result;
5915
- }
5916
- function parseIdentityMap(value) {
5917
- const input = record$1(value);
5918
- keys(input, [
5919
- "format",
5920
- "formatVersion",
5921
- "bundleId",
5922
- "workspace"
5923
- ]);
5924
- const bundleId = string(input["bundleId"]);
5925
- validBundleId(bundleId);
5926
- const workspace = record$1(input["workspace"]);
5927
- keys(workspace, [
5928
- "path",
5929
- "pathHash",
5930
- "remotes",
5931
- "primaryRemoteHash"
5932
- ]);
5933
- const path = workspace["path"] === null ? null : boundedLocator(workspace["path"]);
5934
- const pathHash = workspace["pathHash"] === null ? null : boundedHash(workspace["pathHash"]);
5935
- if (path === null !== (pathHash === null)) fail("ARTIFACT_INVALID_MANIFEST");
5936
- const rawRemotes = workspace["remotes"];
5937
- if (!Array.isArray(rawRemotes)) return fail("ARTIFACT_INVALID_MANIFEST");
5938
- if (rawRemotes.length > maximumRemotes) fail("ARTIFACT_METADATA_LIMIT");
5939
- const remotes = rawRemotes.map((entry) => {
5940
- const remote = record$1(entry);
5941
- keys(remote, ["url", "hash"]);
5942
- return {
5943
- url: boundedLocator(remote["url"]),
5944
- hash: boundedHash(remote["hash"])
5945
- };
5946
- });
5947
- const primaryRemoteHash = nullableString(workspace["primaryRemoteHash"]);
5948
- if (primaryRemoteHash !== null) {
5949
- 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);
5950
5905
  }
5951
- return {
5952
- format: literal(input["format"], "sess-pilot-bundle-identity-map"),
5953
- formatVersion: literal(input["formatVersion"], 1),
5954
- bundleId,
5955
- workspace: {
5956
- path,
5957
- pathHash,
5958
- remotes,
5959
- primaryRemoteHash
5960
- }
5961
- };
5962
- }
5963
- function encoded(map) {
5964
- const text = `${JSON.stringify(map)}\n`;
5965
- if (Buffer.byteLength(text) > 8388608) fail("ARTIFACT_METADATA_LIMIT");
5966
- return text;
5967
- }
5968
- function sameFileVersion$2(left, right) {
5969
- return right.isFile() && left.dev === right.dev && left.ino === right.ino && left.size === right.size && left.mtimeNs === right.mtimeNs && left.ctimeNs === right.ctimeNs;
5970
- }
5971
- async function identityDirectory(root) {
5972
- const directory = join(root, "identity");
5973
- if (await mkdir(directory, {
5974
- recursive: true,
5975
- mode: 448
5976
- }) !== void 0 && process.platform === "win32") await restrictToOwner(directory, "directory");
5977
- const stat = await lstat(directory, { bigint: true });
5978
- const uid = process.getuid?.();
5979
- 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");
5980
- return directory;
5906
+ if (cursor !== span.end - 1 || offsets.length !== value.length + 1) fail("ARTIFACT_PROCESSING_MISMATCH");
5907
+ return offsets;
5981
5908
  }
5982
- /** Missing maps are recoverable from a current approval; malformed maps are not silently trusted. */
5983
- async function readBundleIdentityMap(root, bundleId) {
5984
- validBundleId(bundleId);
5985
- const directory = await identityDirectory(root);
5986
- const path = join(directory, `b-${bundleId}.json`);
5987
- 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;
5988
5917
  try {
5989
- before = await lstat(path, { bigint: true });
5918
+ parseNativeRecord(text, limits, signal);
5990
5919
  } catch (error) {
5991
- if (filesystemCode(error) === "ENOENT") return null;
5920
+ if (error instanceof ProcessingError && ["PROCESSING_INVALID_RECORD", "PROCESSING_KEY_COLLISION"].includes(error.code)) return void 0;
5992
5921
  throw error;
5993
5922
  }
5994
- const uid = process.getuid?.();
5995
- 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");
5996
- if (before.size > BigInt(8388608)) fail("ARTIFACT_METADATA_LIMIT");
5997
- const handle = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);
5998
- try {
5999
- const opened = await handle.stat({ bigint: true });
6000
- if (!sameFileVersion$2(before, opened)) fail("ARTIFACT_IDENTITY_MISMATCH");
6001
- const bytes = Buffer.alloc(Number(opened.size));
6002
- let offset = 0;
6003
- while (offset < bytes.length) {
6004
- const { bytesRead } = await handle.read(bytes, offset, bytes.length - offset, offset);
6005
- if (bytesRead === 0) fail("ARTIFACT_INVALID_MANIFEST");
6006
- offset += bytesRead;
6007
- }
6008
- if (!sameFileVersion$2(opened, await handle.stat({ bigint: true })) || !sameFileVersion$2(opened, await lstat(path, { bigint: true }))) fail("ARTIFACT_IDENTITY_MISMATCH");
6009
- let text;
6010
- try {
6011
- text = new TextDecoder$1("utf-8", { fatal: true }).decode(bytes);
6012
- } catch (error) {
6013
- return fail("ARTIFACT_INVALID_MANIFEST", { cause: error });
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);
6014
5930
  }
6015
- const map = parseIdentityMap(strictJson(text, maximumBundleIdentityMapBytes, 5e4));
6016
- if (map.bundleId !== bundleId) fail("ARTIFACT_INVALID_MANIFEST");
6017
- return map;
6018
- } finally {
6019
- await handle.close();
6020
- }
6021
- }
6022
- /** Publish before the corresponding ZIP; retained maps are never removed automatically. */
6023
- async function writeBundleIdentityMap(root, map) {
6024
- const validated = parseIdentityMap(map);
6025
- const text = encoded(validated);
6026
- const directory = await identityDirectory(root);
6027
- await syncDirectory(root);
6028
- const finalPath = join(directory, `b-${validated.bundleId}.json`);
6029
- const existing = await readBundleIdentityMap(root, validated.bundleId);
6030
- if (existing) {
6031
- if (encoded(existing) !== text) fail("ARTIFACT_DESTINATION_EXISTS");
6032
- return;
6033
- }
6034
- const tempPath = join(directory, `.sess-pilot-b-${randomUUID()}.part`);
6035
- const handle = await openPrivateFile(tempPath, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY | constants.O_NOFOLLOW, 384);
6036
- try {
6037
- const stat = await handle.stat({ bigint: true });
6038
- const uid = process.getuid?.();
6039
- 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");
6040
- await handle.writeFile(text);
6041
- await handle.sync();
6042
- try {
6043
- await link(tempPath, finalPath);
6044
- } catch (error) {
6045
- if (filesystemCode(error) !== "EEXIST") throw error;
6046
- const raced = await readBundleIdentityMap(root, validated.bundleId);
6047
- if (!raced || encoded(raced) !== text) fail("ARTIFACT_DESTINATION_EXISTS");
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
+ });
6048
5956
  }
6049
- await syncDirectory(directory);
6050
- } finally {
6051
- await handle.close();
6052
- await unlink(tempPath);
6053
- }
6054
- }
6055
- //#endregion
6056
- //#region packages/artifact/src/collection/identity/hash.ts
6057
- /** Hash the private canonical path under an OS-installation namespace. */
6058
- function hashWorkspacePath(normalizedPath, environmentId) {
6059
- if (!/^[0-9a-f]{64}$/.test(environmentId)) throw new Error("ARTIFACT_ENVIRONMENT_UNAVAILABLE");
6060
- return createHash("sha256").update("sess-pilot-workspace-path-v2\0").update(environmentId).update("\0").update(normalizedPath).digest("hex");
6061
- }
6062
- /** Keep the installation identifier out of the distributable bundle. */
6063
- function installationEnvironmentId(kind, installationId) {
6064
- if (!kind || !installationId) throw new Error("ARTIFACT_ENVIRONMENT_UNAVAILABLE");
6065
- return createHash("sha256").update("sess-pilot-workspace-environment-v2\0").update(kind).update("\0").update(installationId).digest("hex");
5957
+ };
5958
+ visit(root);
5959
+ return spans;
6066
5960
  }
6067
- //#endregion
6068
- //#region packages/artifact/src/collection/identity/wsl.ts
6069
- async function isWsl() {
5961
+ /** Never publish a carrier whose edited keys collide or whose JSON structure changed. */
5962
+ function validateFamilyCarrier(text, signal) {
6070
5963
  try {
6071
- return /microsoft|wsl/i.test(await readFile("/proc/sys/kernel/osrelease", "utf8"));
6072
- } catch {
6073
- return false;
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;
6074
5968
  }
6075
5969
  }
6076
5970
  //#endregion
6077
- //#region packages/artifact/src/collection/identity/path.ts
6078
- const execute$1 = promisify(execFile);
6079
- const unavailable$1 = () => fail("ARTIFACT_ENVIRONMENT_UNAVAILABLE");
6080
- function pathPart(value) {
6081
- if (value.length === 0 || Buffer.byteLength(value, "utf8") > 16384 || Array.from(value).some((character) => {
6082
- const code = character.charCodeAt(0);
6083
- return code < 32 || code === 127;
6084
- })) return unavailable$1();
6085
- return value;
6086
- }
6087
- function wslUnc(path) {
6088
- const match = /^\\\\(?:wsl\.localhost|wsl\$)\\([^\\]+)(?:\\(.*))?$/i.exec(path);
6089
- if (!match) return null;
6090
- const distro = pathPart(match[1] ?? "").toLowerCase();
6091
- const remainder = (match[2] ?? "").replaceAll("\\", "/");
6092
- return `wsl:${encodeURIComponent(distro)}:${posix.normalize(`/${remainder}`)}`;
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;
6093
6005
  }
6094
- /** Canonical path is private input to the digest and is never written to the bundle. */
6095
- function normalizeWindowsWorkspacePath(rawPath) {
6096
- pathPart(rawPath);
6097
- const normalized = win32.normalize(rawPath);
6098
- const wslPath = wslUnc(normalized);
6099
- if (wslPath !== null) return wslPath;
6100
- const drive = /^([a-zA-Z]):\\(.*)$/.exec(normalized);
6101
- if (drive) return `win-drive:${(drive[1] ?? "").toLowerCase()}:${posix.normalize(`/${(drive[2] ?? "").replaceAll("\\", "/")}`)}`;
6102
- const share = /^\\\\([^\\]+)\\([^\\]+)(?:\\(.*))?$/.exec(normalized);
6103
- if (share) {
6104
- const server = encodeURIComponent(pathPart(share[1] ?? "").toLowerCase());
6105
- const name = encodeURIComponent(pathPart(share[2] ?? "").toLowerCase());
6106
- const remainder = (share[3] ?? "").replaceAll("\\", "/");
6107
- return `win-unc:${server}/${name}:${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);
6108
6051
  }
6109
- return unavailable$1();
6110
- }
6111
- function normalizePosixWorkspacePath(rawPath) {
6112
- pathPart(rawPath);
6113
- if (!posix.isAbsolute(rawPath)) return unavailable$1();
6114
- return `posix:${posix.normalize(rawPath)}`;
6052
+ return parts;
6115
6053
  }
6116
- async function wslWindowsPath(rawPath, signal) {
6117
- checkAbort(signal);
6118
- pathPart(rawPath);
6119
- if (!posix.isAbsolute(rawPath)) return unavailable$1();
6120
- try {
6121
- const { stdout } = await execute$1("wslpath", ["-w", rawPath], {
6122
- encoding: "utf8",
6123
- maxBuffer: 32768,
6124
- timeout: 15e3,
6125
- windowsHide: true,
6126
- signal
6127
- });
6128
- checkAbort(signal);
6129
- return stdout.replace(/\r?\n$/, "");
6130
- } catch {
6131
- checkAbort(signal);
6132
- return unavailable$1();
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;
6133
6084
  }
6085
+ return spans;
6134
6086
  }
6135
- /** Translate Windows/WSL aliases lexically, including paths that no longer exist. */
6136
- async function normalizeWorkspacePath(rawPath, signal) {
6137
- checkAbort(signal);
6138
- if (/^(?:[A-Za-z]:[\\/]|\\\\)/u.test(rawPath)) return normalizeWindowsWorkspacePath(rawPath);
6139
- if (platform() === "win32") {
6140
- const wslDrive = /^\/mnt\/([A-Za-z])(?:\/(.*))?$/u.exec(rawPath);
6141
- if (wslDrive) return normalizeWindowsWorkspacePath(`${wslDrive[1]}:\\${(wslDrive[2] ?? "").replaceAll("/", "\\")}`);
6142
- return normalizePosixWorkspacePath(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;
6120
+ }
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("\\"));
6131
+ }
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);
6143
6158
  }
6144
- if (platform() === "darwin") return normalizePosixWorkspacePath(rawPath);
6145
- if (platform() !== "linux") return unavailable$1();
6146
- 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) {
6147
6182
  checkAbort(signal);
6148
- if (wsl) return normalizeWindowsWorkspacePath(await wslWindowsPath(rawPath, signal));
6149
- 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);
6150
6185
  }
6151
6186
  //#endregion
6152
- //#region packages/artifact/src/collection/identity/environment.ts
6153
- const execute = promisify(execFile);
6154
- const unavailable = () => fail("ARTIFACT_ENVIRONMENT_UNAVAILABLE");
6155
- async function run(file, args, signal) {
6156
- checkAbort(signal);
6157
- try {
6158
- const { stdout } = await execute(file, [...args], {
6159
- encoding: "utf8",
6160
- maxBuffer: 32768,
6161
- timeout: 15e3,
6162
- windowsHide: true,
6163
- 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
6164
6211
  });
6165
- checkAbort(signal);
6166
- return stdout.trim();
6167
- } catch {
6168
- checkAbort(signal);
6169
- return unavailable();
6170
- }
6212
+ };
6171
6213
  }
6172
- function identifier(value, pattern) {
6173
- const id = value.trim().toLowerCase();
6174
- if (id.length > 128 || !pattern.test(id) || /^0+$/.test(id.replaceAll("-", ""))) return unavailable();
6175
- 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");
6176
6223
  }
6177
- async function windowsInstallationId() {
6178
- const script = [
6179
- "$ErrorActionPreference='Stop'",
6180
- "$id=(Get-ItemProperty -Path 'HKLM:\\SOFTWARE\\Microsoft\\Cryptography').MachineGuid",
6181
- "if ([string]::IsNullOrWhiteSpace($id)) { exit 2 }",
6182
- "[Console]::Out.WriteLine($id)"
6183
- ].join(";");
6184
- return identifier(await run("powershell.exe", [
6185
- "-NoProfile",
6186
- "-NonInteractive",
6187
- "-EncodedCommand",
6188
- Buffer.from(script, "utf16le").toString("base64")
6189
- ]), /^[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;
6190
6228
  }
6191
- async function linuxInstallationId() {
6192
- try {
6193
- return identifier(await readFile("/etc/machine-id", "utf8"), /^[0-9a-f]{32}$/);
6194
- } catch {
6195
- return unavailable();
6196
- }
6229
+ function boundedHash(value) {
6230
+ const result = string(value);
6231
+ if (!digest$3.test(result)) fail("ARTIFACT_INVALID_MANIFEST");
6232
+ return result;
6197
6233
  }
6198
- async function macInstallationId() {
6199
- const plist = await run("diskutil", [
6200
- "info",
6201
- "-plist",
6202
- "/"
6234
+ function parseIdentityMap(value) {
6235
+ const input = record$1(value);
6236
+ keys(input, [
6237
+ "format",
6238
+ "formatVersion",
6239
+ "bundleId",
6240
+ "workspace"
6203
6241
  ]);
6204
- const match = /<key>APFSVolumeGroupID<\/key>\s*<string>([0-9a-fA-F-]+)<\/string>/.exec(plist);
6205
- if (!match) return unavailable();
6206
- return identifier(match[1] ?? "", /^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/);
6207
- }
6208
- async function installationId() {
6209
- if (platform() === "win32") return installationEnvironmentId("windows-installation", await windowsInstallationId());
6210
- if (platform() === "darwin") return installationEnvironmentId("macos-apfs-installation", await macInstallationId());
6211
- if (platform() === "linux") {
6212
- if (await isWsl()) return installationEnvironmentId("windows-installation", await windowsInstallationId());
6213
- return installationEnvironmentId("linux-installation", await linuxInstallationId());
6214
- }
6215
- return unavailable();
6216
- }
6217
- let installationPromise;
6218
- function waitForInstallation(id, signal) {
6219
- if (!signal) return id;
6220
- checkAbort(signal);
6221
- return new Promise((resolve, reject) => {
6222
- const onAbort = () => reject(/* @__PURE__ */ new Error("ARTIFACT_ABORTED"));
6223
- signal.addEventListener("abort", onAbort, { once: true });
6224
- id.then((value) => {
6225
- signal.removeEventListener("abort", onAbort);
6226
- resolve(value);
6227
- }, (error) => {
6228
- signal.removeEventListener("abort", onAbort);
6229
- reject(error);
6230
- });
6231
- });
6232
- }
6233
- /** Same OS installation receives one stable namespace across process and state-dir changes. */
6234
- async function resolveWorkspaceEnvironmentId(signal) {
6235
- checkAbort(signal);
6236
- if (!installationPromise) installationPromise = installationId().catch((error) => {
6237
- installationPromise = void 0;
6238
- throw error;
6239
- });
6240
- const id = await waitForInstallation(installationPromise, signal);
6241
- checkAbort(signal);
6242
- return id;
6243
- }
6244
- //#endregion
6245
- //#region packages/artifact/src/collection/identity/remote.ts
6246
- /** Versioned canonical form shared by archive producers and downstream consumers. */
6247
- function canonicalRemote(value) {
6248
- const input = value.trim();
6249
- if (!input || Buffer.byteLength(input) > 16384) return fail("ARTIFACT_UNSAFE_REMOTE");
6250
- for (const character of input) {
6251
- const code = character.charCodeAt(0);
6252
- if (code < 32 || code === 127) return fail("ARTIFACT_UNSAFE_REMOTE");
6253
- }
6254
- if (input.startsWith("/") || /^[a-z]:[\\/]/i.test(input) || input.startsWith("\\\\")) return input.replaceAll("\\", "/");
6255
- const scp = /^[a-z][a-z0-9+.-]*:\/\//i.test(input) ? null : /^(?:[^@/\s]+@)?(\[[^\]]+\]|[^/:\s]+):([^:].*)$/.exec(input);
6256
- const candidate = scp?.[1] && scp[2] ? `ssh://${scp[1]}/${scp[2]}` : input;
6257
- let url;
6258
- try {
6259
- url = new URL(candidate);
6260
- } catch (error) {
6261
- return fail("ARTIFACT_UNSAFE_REMOTE", { cause: error });
6262
- }
6263
- if (![
6264
- "https:",
6265
- "http:",
6266
- "ssh:",
6267
- "git:",
6268
- "file:"
6269
- ].includes(url.protocol)) fail("ARTIFACT_UNSAFE_REMOTE");
6270
- url.username = "";
6271
- url.password = "";
6272
- url.search = "";
6273
- url.hash = "";
6274
- url.hostname = url.hostname.toLowerCase();
6275
- if (url.protocol === "ssh:" && url.port === "22" || url.protocol === "git:" && url.port === "9418") url.port = "";
6276
- if (url.protocol !== "file:") {
6277
- if (!url.hostname) fail("ARTIFACT_UNSAFE_REMOTE");
6278
- url.pathname = url.pathname.replace(/\/+$/, "").replace(/\.git$/, "");
6279
- }
6280
- return url.href;
6281
- }
6282
- function hashRemote(canonical) {
6283
- return createHash("sha256").update("sess-pilot/git-remote/v1\0").update(canonical).digest("hex");
6284
- }
6285
- //#endregion
6286
- //#region packages/artifact/src/collection/identity/workspace.ts
6287
- async function workspaceIdentity(workspace, signal) {
6288
- checkAbort(signal);
6289
- const pathHash = workspace.path === null ? null : hashWorkspacePath(await normalizeWorkspacePath(workspace.path, signal), await resolveWorkspaceEnvironmentId(signal));
6290
- const remotes = workspace.remotes.map((remote) => {
6291
- 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"]);
6292
6260
  return {
6293
- url,
6294
- hash: hashRemote(url)
6261
+ url: boundedLocator(remote["url"]),
6262
+ hash: boundedHash(remote["hash"])
6295
6263
  };
6296
6264
  });
6297
- const primaryRemoteHash = workspace.primaryRemote ? hashRemote(canonicalRemote(workspace.primaryRemote.locator)) : null;
6298
- if (primaryRemoteHash !== null && !remotes.some((remote) => remote.hash === primaryRemoteHash)) fail("ARTIFACT_UNSAFE_REMOTE");
6299
- const challengeId = await readChallengeId(workspace.path, signal);
6300
- checkAbort(signal);
6301
- return {
6302
- title: workspace.title,
6303
- path: workspace.path,
6304
- pathHash,
6305
- remotes,
6306
- primaryRemoteHash,
6307
- challengeId
6308
- };
6309
- }
6310
- function workspaceMetadata(identity) {
6311
- return {
6312
- version: 3,
6313
- title: identity.title,
6314
- pathHash: identity.pathHash,
6315
- remoteHashes: identity.remotes.map((remote) => remote.hash),
6316
- primaryRemoteHash: identity.primaryRemoteHash
6317
- };
6318
- }
6319
- 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
+ }
6320
6269
  return {
6321
- format: "sess-pilot-bundle-identity-map",
6322
- formatVersion: 1,
6270
+ format: literal(input["format"], "sess-pilot-bundle-identity-map"),
6271
+ formatVersion: literal(input["formatVersion"], 1),
6323
6272
  bundleId,
6324
6273
  workspace: {
6325
- path: identity.path,
6326
- pathHash: identity.pathHash,
6327
- remotes: identity.remotes,
6328
- primaryRemoteHash: identity.primaryRemoteHash
6274
+ path,
6275
+ pathHash,
6276
+ remotes,
6277
+ primaryRemoteHash
6329
6278
  }
6330
6279
  };
6331
6280
  }
6332
- //#endregion
6333
- //#region packages/artifact/src/collection/producer/workspace-metadata.ts
6334
- /** Workspace titles are emitted once, independently of per-session optional profiles. */
6335
- async function configuredWorkspaceMetadata(identity, processing, signal, titlePlan, onMasks, replacementScope) {
6336
- const metadata = workspaceMetadata(identity);
6337
- const terms = processing.customTerms?.terms ?? [];
6338
- if (terms.length === 0 && titlePlan === void 0) return metadata;
6339
- const preparation = createSessionPreparation({
6340
- environment: processing.environment,
6341
- customTerms: terms,
6342
- ...processing.staticExceptions === void 0 ? {} : { staticExceptions: processing.staticExceptions.values },
6343
- ...processing.replacementKey === void 0 ? {} : { replacementKey: processing.replacementKey },
6344
- ...replacementScope === void 0 ? {} : { replacementScope }
6345
- }, signal);
6346
- 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;
6347
6306
  try {
6348
- if (titlePlan) {
6349
- const seeds = await processing.gitNames(identity.path === null ? [] : [identity.path], signal);
6350
- 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;
6351
6325
  }
6352
- preparation.original(metadata.title, false);
6353
- bindings = preparation.finish();
6354
- const input = {
6355
- attemptId: "workspace-metadata",
6356
- sourceRef: "workspace-metadata",
6357
- unitId: "title",
6358
- text: metadata.title,
6359
- ...onMasks ? { captureMasks: true } : {}
6360
- };
6361
- async function* units() {
6362
- yield input;
6363
- }
6364
- let title;
6365
- for await (const output of processing.processor.transform(units(), withMandatoryCustomTerms(titlePlan ?? buildPlan([], [])), signal, bindings.session)) {
6366
- if (title !== void 0 || output.unitId !== input.unitId || output.sourceRef !== input.sourceRef || output.attemptId !== input.attemptId) fail("ARTIFACT_PROCESSING_FAILED");
6367
- title = output.text;
6368
- 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 });
6369
6332
  }
6370
- if (title === void 0) return fail("ARTIFACT_PROCESSING_FAILED");
6371
- return {
6372
- ...metadata,
6373
- title
6374
- };
6333
+ const map = parseIdentityMap(strictJson(text, maximumBundleIdentityMapBytes, 5e4));
6334
+ if (map.bundleId !== bundleId) fail("ARTIFACT_INVALID_MANIFEST");
6335
+ return map;
6375
6336
  } finally {
6376
- bindings?.close();
6377
- preparation.close();
6337
+ await handle.close();
6378
6338
  }
6379
6339
  }
6380
- //#endregion
6381
- //#region packages/artifact/src/configured/journey/metadata-spans.ts
6382
- /** Raw semantic boundaries expand over actual static replacements; static text is never restored. */
6383
- function metadataOutputSpans(text, masks, semantic) {
6384
- if (!semantic) return [];
6385
- if (semantic.textSha256 !== createHash("sha256").update(text).digest("hex") || semantic.spans.length > 5e4) fail("ARTIFACT_PROCESSING_MISMATCH");
6386
- const ordered = masks.toSorted((a, b) => a.inputRange.start - b.inputRange.start);
6387
- const map = (position, edge) => {
6388
- let delta = 0;
6389
- for (const mask of ordered) {
6390
- if (position <= mask.inputRange.start) break;
6391
- if (position < mask.inputRange.end) return edge === "start" ? mask.outputRange.start : mask.outputRange.end;
6392
- 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");
6393
6366
  }
6394
- return position + delta;
6395
- };
6396
- const mapped = semantic.spans.flatMap((span) => {
6397
- 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");
6398
- const category = maskCategory(span.category);
6399
- const start = map(span.start, "start"), end = map(span.end, "end");
6400
- return start === end ? [] : [{
6401
- start,
6402
- end,
6403
- category
6404
- }];
6405
- }).sort((a, b) => a.start - b.start || b.end - a.end);
6406
- const result = [];
6407
- for (const span of mapped) {
6408
- const previous = result.at(-1);
6409
- if (previous && span.start < previous.end) {
6410
- const category = categoryOrder.indexOf(maskCategory(previous.category)) >= categoryOrder.indexOf(span.category) ? previous.category : span.category;
6411
- result[result.length - 1] = {
6412
- start: previous.start,
6413
- end: Math.max(previous.end, span.end),
6414
- category
6415
- };
6416
- } else result.push(span);
6367
+ await syncDirectory(directory);
6368
+ } finally {
6369
+ await handle.close();
6370
+ await unlink(tempPath);
6417
6371
  }
6418
- return result;
6419
6372
  }
6420
6373
  //#endregion
6421
- //#region packages/artifact/src/configured/journey/metadata-fields.ts
6422
- /** This accepts private raw proposals once. Safe strings must never be re-ingested as originals. */
6423
- async function processJourneyMetadataFields(request, signal = new AbortController().signal) {
6424
- const { workId, fields, processing, redactionPlan } = request;
6425
- 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");
6426
- const results = [];
6427
- let bytes = 0;
6428
- for (const field of fields) {
6429
- checkAbort(signal);
6430
- if (field.semantic && field.processedSemantic) fail("ARTIFACT_INVALID_APPROVAL");
6431
- let staticMasks;
6432
- const output = await configuredWorkspaceMetadata({
6433
- title: field.text,
6434
- path: null,
6435
- pathHash: null,
6436
- remotes: [],
6437
- primaryRemoteHash: null,
6438
- challengeId: null
6439
- }, processing, signal, redactionPlan, (input, processed) => {
6440
- staticMasks = titleMasks(input, processed);
6441
- }, processing.replacementKey === void 0 ? void 0 : `work-metadata:${workId}`);
6442
- const masks = staticMasks ?? fail("ARTIFACT_PROCESSING_FAILED");
6443
- const spans = field.processedSemantic ? metadataOutputSpans(output.title, [], field.processedSemantic) : metadataOutputSpans(field.text, masks, field.semantic);
6444
- let text = output.title;
6445
- const transcripts = [];
6446
- if (spans.length) {
6447
- const markers = createSemanticMarkers(processing.replacementKey ?? fail("ARTIFACT_INVALID_APPROVAL"), workId);
6448
- try {
6449
- const inputSha256 = createHash("sha256").update(text).digest("hex");
6450
- const input = text;
6451
- text = replaceSemanticSpans(input, spans, markers, (span, replacement, start) => {
6452
- const contextStart = Math.max(0, span.start - 120);
6453
- transcripts.push({
6454
- pointer: "/title",
6455
- inputSha256,
6456
- inputRange: {
6457
- start: span.start,
6458
- end: span.end
6459
- },
6460
- outputRange: {
6461
- start,
6462
- end: start + replacement.length
6463
- },
6464
- replacement,
6465
- category: maskCategory(span.category),
6466
- context: {
6467
- start: contextStart,
6468
- text: input.slice(contextStart, Math.min(input.length, contextStart + 512, span.end + 120))
6469
- }
6470
- });
6471
- });
6472
- } finally {
6473
- markers.close();
6474
- }
6475
- }
6476
- bytes += Buffer.byteLength(text);
6477
- if (Buffer.byteLength(text) > 32768 || bytes > 65536) fail("ARTIFACT_METADATA_LIMIT");
6478
- const outputSha256 = createHash("sha256").update(text).digest("hex");
6479
- results.push({
6480
- text,
6481
- staticMasks: masks,
6482
- semanticTranscript: transcripts.map((item) => ({
6483
- ...item,
6484
- outputSha256
6485
- }))
6486
- });
6487
- }
6488
- 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");
6489
6384
  }
6490
6385
  //#endregion
6491
- //#region packages/artifact/src/configured/output/metadata.ts
6492
- async function updateOutputWorkMetadata(text, manifest, request, signal, onTitleMasks) {
6493
- const work = parseConfiguredWorkMetadata(strictJson(text, metadataLimitBytes));
6494
- if (work.id !== manifest.work.id) fail("ARTIFACT_INVALID_MANIFEST");
6495
- const update = request.metadata;
6496
- if (!update) return text;
6497
- if ((update.titleSemantic || update.titleProcessedSemantic) && update.title === void 0) fail("ARTIFACT_INVALID_APPROVAL");
6498
- let title = work.title;
6499
- if (update.cachedTitle) {
6500
- if (update.title !== void 0 || update.titleSemantic || update.titleProcessedSemantic) fail("ARTIFACT_INVALID_APPROVAL");
6501
- const cached = update.cachedTitle;
6502
- const sha256 = createHash("sha256").update(cached.text).digest("hex");
6503
- if (sha256 !== cached.semantic.textSha256) fail("ARTIFACT_PROCESSING_MISMATCH");
6504
- const markers = createSemanticMarkers(request.replacementKey, request.workId);
6505
- const transcripts = [];
6506
- try {
6507
- title = maskOutputField({
6508
- pointer: "/title",
6509
- text: cached.text,
6510
- sha256
6511
- }, cached.semantic.spans, markers, { bytes: 0 }, (value) => transcripts.push(value));
6512
- } finally {
6513
- markers.close();
6514
- }
6515
- onTitleMasks?.({
6516
- text: title,
6517
- staticMasks: cached.staticMasks,
6518
- semanticTranscript: transcripts
6519
- });
6520
- } else if (update.title !== void 0) {
6521
- if (!update.title.trim() || Buffer.byteLength(update.title) > 16384) fail("ARTIFACT_INVALID_APPROVAL");
6522
- const treatment = manifest.configuration.definitions.find((item) => item.id === manifest.sessions[0]?.treatmentId) ?? fail("ARTIFACT_INVALID_MANIFEST");
6523
- const metadata = (await processJourneyMetadataFields({
6524
- workId: manifest.work.id,
6525
- fields: [{
6526
- text: update.title,
6527
- ...update.titleSemantic ? { semantic: update.titleSemantic } : {},
6528
- ...update.titleProcessedSemantic ? { processedSemantic: update.titleProcessedSemantic } : {}
6529
- }],
6530
- processing: {
6531
- ...request.processing,
6532
- replacementKey: request.replacementKey
6533
- },
6534
- redactionPlan: treatment.redactionPlan
6535
- }, signal))[0] ?? fail("ARTIFACT_PROCESSING_FAILED");
6536
- title = metadata.text;
6537
- 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;
6538
6392
  }
6539
- const changed = parseConfiguredWorkMetadata({
6540
- ...work,
6541
- title,
6542
- access: update.access ?? work.access
6543
- });
6544
- return JSON.stringify(changed);
6545
6393
  }
6546
6394
  //#endregion
6547
- //#region packages/artifact/src/configured/output/read.ts
6548
- async function verifiedMetadata(entry, description, signal) {
6549
- const text = await readMetadata(entry, signal);
6550
- if (Buffer.byteLength(text) !== description.byteLength || createHash("sha256").update(text).digest("hex") !== description.sha256) fail("ARTIFACT_INVALID_ARCHIVE");
6551
- 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;
6552
6404
  }
6553
- async function readConfiguredOutputInfo(input, signal = new AbortController().signal) {
6554
- const verified = await checkFrozenOutput(input, signal);
6555
- const archive = await openCheckedOutput(input, verified.checked, signal);
6556
- const cleanup = createCleanup();
6557
- try {
6558
- if (archive.manifestText !== verified.manifestText) fail("ARTIFACT_PROCESSING_MISMATCH");
6559
- const path = verified.manifest.work.metadataPath;
6560
- const description = verified.manifest.entries.find((entry) => entry.entryPath === path) ?? fail("ARTIFACT_INVALID_MANIFEST");
6561
- const work = parseConfiguredWorkMetadata(await verifiedMetadata(archive.entries.get(path) ?? fail("ARTIFACT_INVALID_ARCHIVE"), description, signal));
6562
- if (work.id !== verified.manifest.work.id) fail("ARTIFACT_INVALID_MANIFEST");
6563
- const sources = [];
6564
- for (const source of verified.manifest.sourceWorkspaces) {
6565
- 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);
6566
- sources.push({
6567
- id: source.id,
6568
- pathHash: metadata.pathHash,
6569
- remoteHashes: metadata.remoteHashes,
6570
- primaryRemoteHash: metadata.primaryRemoteHash,
6571
- ...source.challengeId === void 0 ? {} : { challengeId: source.challengeId }
6572
- });
6573
- }
6574
- return {
6575
- manifest: verified.manifest,
6576
- work,
6577
- checked: verified.checked,
6578
- sources,
6579
- createdAt: verified.manifest.createdAt,
6580
- sessionCount: verified.manifest.sessions.length
6581
- };
6582
- } catch (error) {
6583
- cleanup.failed(error);
6584
- throw error;
6585
- } finally {
6586
- 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}`)}`;
6587
6426
  }
6427
+ return unavailable$1();
6588
6428
  }
6589
- /** Model-safe rows only: read a digest-bound static primary, never its original source. */
6590
- async function* readConfiguredOutputRows(input, signal = new AbortController().signal) {
6591
- const verified = await checkFrozenOutput(input, signal);
6592
- const archive = await openCheckedOutput(input, verified.checked, signal);
6593
- 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();
6594
6438
  try {
6595
- if (archive.manifestText !== verified.manifestText) fail("ARTIFACT_PROCESSING_MISMATCH");
6596
- const descriptions = new Map(verified.manifest.entries.map((entry) => [entry.entryPath, entry]));
6597
- for (const session of verified.manifest.sessions) for (const part of session.parts) {
6598
- const spool = await spoolFacts(archive.entries.get(part.dataPath) ?? fail("ARTIFACT_INVALID_ARCHIVE"), descriptions.get(part.dataPath) ?? fail("ARTIFACT_INVALID_MANIFEST"), signal);
6599
- const partCleanup = createCleanup();
6600
- try {
6601
- await archive.fence();
6602
- let recordIndex = 0;
6603
- for await (const text of spool.lines) {
6604
- checkAbort(signal);
6605
- if (recordIndex >= part.retainedRecordCount) fail("ARTIFACT_INVALID_ARCHIVE");
6606
- yield {
6607
- entryPath: part.dataPath,
6608
- recordIndex,
6609
- archiveSessionId: session.id,
6610
- sourceId: part.sourceId,
6611
- harness: session.harness,
6612
- native: part.native,
6613
- text,
6614
- rowSha256: createHash("sha256").update(text).digest("hex")
6615
- };
6616
- recordIndex++;
6617
- }
6618
- if (recordIndex !== part.retainedRecordCount) fail("ARTIFACT_INVALID_ARCHIVE");
6619
- } catch (error) {
6620
- partCleanup.failed(error);
6621
- throw error;
6622
- } finally {
6623
- await partCleanup.run(() => spool.lines.return(void 0), () => spool.close());
6624
- }
6625
- }
6626
- } catch (error) {
6627
- cleanup.failed(error);
6628
- throw error;
6629
- } finally {
6630
- 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);
6631
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);
6632
6468
  }
6633
6469
  //#endregion
6634
- //#region packages/artifact/src/configured/review/parse.ts
6635
- const digest$2 = (text) => createHash("sha256").update(text).digest("hex");
6636
- const hash$6 = (value) => {
6637
- const text = string(value);
6638
- if (!/^[a-f0-9]{64}$/u.test(text)) fail("ARTIFACT_INVALID_MANIFEST");
6639
- return text;
6640
- };
6641
- const pointer$3 = (value) => {
6642
- const text = string(value);
6643
- if (!text.startsWith("/") || /~(?:[^01]|$)/u.test(text)) fail("ARTIFACT_INVALID_MANIFEST");
6644
- return text;
6645
- };
6646
- const range$2 = (value) => {
6647
- const v = record$1(value);
6648
- keys(v, ["start", "end"]);
6649
- const start = integer(v["start"]), end = integer(v["end"]);
6650
- if (end <= start) fail("ARTIFACT_INVALID_MANIFEST");
6651
- return {
6652
- start,
6653
- end
6654
- };
6655
- };
6656
- function checkedRanges(value, length) {
6657
- const ranges = array(value, range$2);
6658
- let end = 0;
6659
- for (const r of ranges) {
6660
- if (r.start < end || r.end > length) fail("ARTIFACT_INVALID_MANIFEST");
6661
- 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();
6662
6488
  }
6663
- return ranges;
6664
6489
  }
6665
- function rowRanges(value, fields) {
6666
- const ranges = array(value, (value) => value);
6667
- if (ranges.length !== fields.length) fail("ARTIFACT_INVALID_MANIFEST");
6668
- return ranges.map((value, index) => {
6669
- return checkedRanges(value, (fields[index] ?? fail("ARTIFACT_INVALID_MANIFEST")).text.length);
6670
- });
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;
6671
6494
  }
6672
- function mask(value) {
6673
- const v = record$1(value);
6674
- keys(v, [
6675
- "inputRange",
6676
- "outputRange",
6677
- "replacement",
6678
- "stepId",
6679
- "node",
6680
- "ruleId"
6681
- ]);
6682
- const node = record$1(v["node"]);
6683
- keys(node, ["id", "version"]);
6684
- const output = record$1(v["outputRange"]);
6685
- keys(output, ["start", "end"]);
6686
- const start = integer(output["start"]), end = integer(output["end"]);
6687
- const replacement = string(v["replacement"]);
6688
- if (end < start || end - start !== replacement.length) fail("ARTIFACT_INVALID_MANIFEST");
6689
- return {
6690
- inputRange: range$2(v["inputRange"]),
6691
- outputRange: {
6692
- start,
6693
- end
6694
- },
6695
- replacement,
6696
- stepId: string(v["stepId"]),
6697
- node: {
6698
- id: string(node["id"]),
6699
- version: string(node["version"])
6700
- },
6701
- ruleId: string(v["ruleId"])
6702
- };
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}$/);
6703
6508
  }
6704
- function field(value) {
6705
- const v = record$1(value);
6706
- keys(v, [
6707
- "pointer",
6708
- "cleanedPointer",
6709
- "originalPointer",
6710
- ...v["originalRange"] === void 0 ? [] : ["originalRange"],
6711
- ...v["originalFieldHash"] === void 0 ? [] : ["originalFieldHash"],
6712
- ...v["innerPointer"] === void 0 ? [] : ["innerPointer"],
6713
- ...v["scalarKind"] === void 0 ? [] : ["scalarKind"],
6714
- "role",
6715
- "text",
6716
- "fieldHash",
6717
- "staticMasks",
6718
- "nonPathMasks",
6719
- "protectedRanges",
6720
- ...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
+ "/"
6721
6521
  ]);
6722
- const role = v["role"];
6723
- if (role !== "user" && role !== "assistant" && role !== "tool-output") return fail("ARTIFACT_INVALID_MANIFEST");
6724
- const text = string(v["text"]), fieldHash = hash$6(v["fieldHash"]);
6725
- const scalarKind = v["scalarKind"];
6726
- if (scalarKind !== void 0 && scalarKind !== "literal" && scalarKind !== "structure" && scalarKind !== "container") return fail("ARTIFACT_INVALID_MANIFEST");
6727
- if (digest$2(text) !== fieldHash) fail("ARTIFACT_PROCESSING_MISMATCH");
6728
- const result = {
6729
- pointer: pointer$3(v["pointer"]),
6730
- cleanedPointer: pointer$3(v["cleanedPointer"]),
6731
- originalPointer: pointer$3(v["originalPointer"]),
6732
- ...v["originalRange"] === void 0 ? {} : { originalRange: range$2(v["originalRange"]) },
6733
- ...v["originalFieldHash"] === void 0 ? {} : { originalFieldHash: hash$6(v["originalFieldHash"]) },
6734
- ...v["innerPointer"] === void 0 ? {} : { innerPointer: pointer$3(v["innerPointer"]) },
6735
- ...scalarKind === void 0 ? {} : { scalarKind },
6736
- role,
6737
- text,
6738
- fieldHash,
6739
- staticMasks: array(v["staticMasks"], mask),
6740
- nonPathMasks: array(v["nonPathMasks"], mask),
6741
- protectedRanges: array(v["protectedRanges"], range$2),
6742
- ...v["customRanges"] === void 0 ? {} : { customRanges: array(v["customRanges"], range$2) }
6743
- };
6744
- 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");
6745
- 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}$/);
6746
6525
  }
6747
- function parsePrivateReviewRow(text) {
6748
- const v = record$1(strictJson(text, 67108864));
6749
- keys(v, [
6750
- "entryPath",
6751
- "recordIndex",
6752
- "sourcePartId",
6753
- "sourceRecordIndex",
6754
- "archiveSessionId",
6755
- "outputSha256",
6756
- "cleanedText",
6757
- "fields",
6758
- "aiRanges"
6759
- ]);
6760
- const parsedFields = array(v["fields"], field);
6761
- return {
6762
- entryPath: string(v["entryPath"]),
6763
- recordIndex: integer(v["recordIndex"]),
6764
- sourcePartId: string(v["sourcePartId"]),
6765
- sourceRecordIndex: integer(v["sourceRecordIndex"]),
6766
- archiveSessionId: string(v["archiveSessionId"]),
6767
- outputSha256: hash$6(v["outputSha256"]),
6768
- cleanedText: string(v["cleanedText"]),
6769
- fields: parsedFields,
6770
- aiRanges: rowRanges(v["aiRanges"], parsedFields)
6771
- };
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();
6772
6534
  }
6773
- function parsePrivateReviewManifest(text, entries, primary) {
6774
- const v = record$1(strictJson(text, manifestLimitBytes, manifestNodeLimit));
6775
- keys(v, [
6776
- "format",
6777
- "version",
6778
- "bundleId",
6779
- "workId",
6780
- "primary",
6781
- "entries",
6782
- "rows"
6783
- ]);
6784
- const bound = record$1(v["primary"]);
6785
- keys(bound, ["sha256", "archiveBytes"]);
6786
- if (v["bundleId"] !== primary.manifest.bundleId || v["workId"] !== primary.manifest.work.id || bound["sha256"] !== primary.sha256 || bound["archiveBytes"] !== primary.archiveBytes) fail("ARTIFACT_PROCESSING_MISMATCH");
6787
- const descriptions = array(v["entries"], (value) => {
6788
- const e = record$1(value);
6789
- keys(e, [
6790
- "entryPath",
6791
- "kind",
6792
- "representation",
6793
- "byteLength",
6794
- "sha256",
6795
- "rows"
6796
- ]);
6797
- return {
6798
- entryPath: string(e["entryPath"]),
6799
- kind: literal(e["kind"], "facts"),
6800
- representation: literal(e["representation"], "jsonl"),
6801
- byteLength: integer(e["byteLength"]),
6802
- sha256: hash$6(e["sha256"]),
6803
- rows: integer(e["rows"])
6804
- };
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
+ });
6805
6549
  });
6806
- const expected = new Set(primary.manifest.sessions.flatMap((s) => s.parts.map((p) => `${p.dataPath}.review.jsonl`)));
6807
- let rows = 0;
6808
- for (const d of descriptions) {
6809
- const e = entries.get(d.entryPath);
6810
- if (!expected.delete(d.entryPath) || !e || e.compressionMethod !== 8 || e.uncompressedSize !== d.byteLength || d.byteLength > maximumPartBytes) fail("ARTIFACT_INVALID_ARCHIVE");
6811
- rows += d.rows;
6812
- }
6813
- if (expected.size || entries.size !== descriptions.length + 1 || rows !== integer(v["rows"])) fail("ARTIFACT_INVALID_ARCHIVE");
6814
- return {
6815
- format: literal(v["format"], "sess-pilot-private-b-review"),
6816
- version: literal(v["version"], 2),
6817
- bundleId: primary.manifest.bundleId,
6818
- workId: primary.manifest.work.id,
6819
- primary: {
6820
- sha256: primary.sha256,
6821
- archiveBytes: primary.archiveBytes
6822
- },
6823
- entries: descriptions,
6824
- rows
6825
- };
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;
6826
6561
  }
6827
6562
  //#endregion
6828
- //#region packages/artifact/src/configured/review/native.ts
6829
- const reviewLimits = {
6830
- ...defaultLimits,
6831
- maxRecordBytes: maximumRecordBytes,
6832
- maxUnitBytes: maximumRecordBytes,
6833
- maxOutputRecordBytes: maximumRecordBytes
6834
- };
6835
- function reviewNative(text, signal) {
6836
- 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;
6837
6599
  }
6838
- function emptyNativeStructure(node) {
6839
- if (node.kind === "literal") return false;
6840
- if (node.kind === "string") return node.value.length === 0;
6841
- 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");
6842
6602
  }
6843
- function nativePointer(root, pointer) {
6844
- let node = root;
6845
- if (pointer === "") return node;
6846
- if (!pointer.startsWith("/") || /~(?:[^01]|$)/u.test(pointer)) fail("ARTIFACT_PROCESSING_MISMATCH");
6847
- 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");
6848
- 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
+ };
6849
6627
  }
6850
- /** Exact numeric-array lexemes for grouped geography, including targets decoded from native strings. */
6851
- function nativeContainerText(node, signal) {
6852
- if (node.kind !== "array") return void 0;
6853
- const numeric = (value) => {
6854
- signal.throwIfAborted();
6855
- 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
6856
6635
  };
6857
- return numeric(node) ? renderNative(node, /* @__PURE__ */ new Map(), reviewLimits, signal).text : void 0;
6858
6636
  }
6859
- //#endregion
6860
- //#region packages/artifact/src/configured/review/read.ts
6861
- async function checkPrivateReviewProjection(file, primary, signal) {
6862
- const output = await checkFrozenOutput(primary, signal);
6863
- let manifest;
6637
+ function bundleIdentityMap(bundleId, identity) {
6864
6638
  return {
6865
- checked: await checkWrittenArchive(file.path, file.identity, void 0, (text, entries) => {
6866
- manifest = parsePrivateReviewManifest(text, entries, {
6867
- manifest: output.manifest,
6868
- sha256: primary.sha256,
6869
- archiveBytes: primary.archiveBytes
6870
- });
6871
- }, signal),
6872
- manifest: manifest ?? fail("ARTIFACT_INVALID_ARCHIVE"),
6873
- 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
+ }
6874
6648
  };
6875
6649
  }
6876
- /** Internal reconstruction iterator; callers exposing model input must use the field-only iterator. */
6877
- async function* readPrivateReviewRows(request, signal) {
6878
- const { projection, primary } = request;
6879
- const verified = await checkPrivateReviewProjection(projection, primary, signal);
6880
- if (projection.primarySha256 !== primary.sha256 || projection.rows !== verified.manifest.rows) fail("ARTIFACT_PROCESSING_MISMATCH");
6881
- const archive = await openCheckedOutput(projection, verified.checked, signal);
6882
- const output = readConfiguredOutputRows(primary, signal);
6883
- const parts = new Map(verified.output.sessions.flatMap((session) => session.parts.map((part) => [part.dataPath, {
6884
- part,
6885
- sessionId: session.id
6886
- }])));
6887
- let next = await output.next();
6888
- 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;
6889
6665
  try {
6890
- for (const description of verified.manifest.entries) {
6891
- const spool = await spoolFacts(archive.entries.get(description.entryPath) ?? fail("ARTIFACT_INVALID_ARCHIVE"), description, signal);
6892
- const partCleanup = createCleanup();
6893
- let rows = 0, last = -1;
6894
- try {
6895
- for await (const text of spool.lines) {
6896
- const row = parsePrivateReviewRow(text), part = parts.get(row.entryPath);
6897
- 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");
6898
- while (!next.done && (next.value.entryPath !== row.entryPath || next.value.recordIndex < row.recordIndex)) next = await output.next();
6899
- if (next.done || next.value.entryPath !== row.entryPath || next.value.recordIndex !== row.recordIndex || next.value.rowSha256 !== row.outputSha256) fail("ARTIFACT_PROCESSING_MISMATCH");
6900
- const root = reviewNative(row.cleanedText, signal), actual = reviewNative(next.value.text, signal), seen = /* @__PURE__ */ new Set();
6901
- for (const field of row.fields) {
6902
- const key = JSON.stringify([field.pointer, field.innerPointer ?? null]);
6903
- if (seen.has(key)) fail("ARTIFACT_PROCESSING_MISMATCH");
6904
- seen.add(key);
6905
- let source = nativePointer(root, field.cleanedPointer);
6906
- const target = nativePointer(actual, field.pointer), nativeLiteral = field.scalarKind === "literal" && field.innerPointer === void 0;
6907
- 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");
6908
- if (field.scalarKind === "structure") {
6909
- if (source.kind !== "string") return fail("ARTIFACT_PROCESSING_MISMATCH");
6910
- const structure = reviewNative(source.value, signal);
6911
- if (!["object", "array"].includes(structure.kind) || !emptyNativeStructure(structure)) fail("ARTIFACT_PROCESSING_MISMATCH");
6912
- }
6913
- if (field.innerPointer !== void 0) {
6914
- if (source.kind !== "string") return fail("ARTIFACT_PROCESSING_MISMATCH");
6915
- source = nativePointer(reviewNative(source.value, signal), field.innerPointer);
6916
- }
6917
- 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;
6918
- if (text === void 0 || text !== field.text || createHash("sha256").update(text).digest("hex") !== field.fieldHash) fail("ARTIFACT_PROCESSING_MISMATCH");
6919
- }
6920
- rows++;
6921
- last = row.recordIndex;
6922
- yield row;
6923
- }
6924
- if (rows !== description.rows) fail("ARTIFACT_INVALID_ARCHIVE");
6925
- } catch (error) {
6926
- partCleanup.failed(error);
6927
- throw error;
6928
- } finally {
6929
- await partCleanup.run(() => spool.lines.return(void 0), () => spool.close());
6930
- }
6931
- 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);
6932
6669
  }
6933
- } catch (error) {
6934
- cleanup.failed(error);
6935
- 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
+ };
6936
6693
  } finally {
6937
- await cleanup.run(() => output.return(void 0), () => archive.close());
6694
+ bindings?.close();
6695
+ preparation.close();
6938
6696
  }
6939
6697
  }
6940
6698
  //#endregion
6941
- //#region packages/artifact/src/configured/review/rules.ts
6942
- const generic = /* @__PURE__ */ new Set([
6943
- "src",
6944
- "lib",
6945
- "test",
6946
- "tests",
6947
- "docs",
6948
- "README.md",
6949
- "package.json",
6950
- "pnpm-lock.yaml",
6951
- "index.ts",
6952
- "main.ts",
6953
- "index.js",
6954
- ".claude.json",
6955
- ".codex",
6956
- "config.toml"
6957
- ]);
6958
- /** Dipper B v6.2 component policy, translated to native UTF-16 coordinates. */
6959
- function componentPaths(text, fullPath = false) {
6960
- const found = [];
6961
- for (const match of text.matchAll(/(?:\/Users\/|\/home\/|[A-Za-z]:\\Users\\)[^\r\n"'`<>[\];|]+/gu)) {
6962
- let raw = match[0];
6963
- const separator = raw.includes("\\") ? "\\" : "/";
6964
- raw = (raw.split(/\s+(?:&&|\|\||--\w|(?:and|then|with|to|from|is)\s)/u)[0] ?? "").replace(/[.,):\s]+$/u, "");
6965
- const quoted = [
6966
- "\"",
6967
- "'",
6968
- "`"
6969
- ].includes(text[match.index - 1] ?? ""), bracketed = /\[(?:project|workspace):\s*$/u.test(text.slice(0, match.index));
6970
- if (!quoted && !bracketed && !fullPath) {
6971
- const token = `Desktop${separator}Folders`;
6972
- raw = (raw.replace(`Desktop Folders${separator}`, token).split(/\s/u)[0] ?? "").replace(token, `Desktop Folders${separator}`);
6973
- }
6974
- const root = /^(?:\/Users\/|\/home\/|[A-Za-z]:\\Users\\)/u.exec(raw)?.[0];
6975
- if (!root) continue;
6976
- const parts = raw.slice(root.length).split(separator);
6977
- if (!parts[0] || /\s/u.test(parts[0])) continue;
6978
- let offset = root.length;
6979
- const coords = parts.map((value) => {
6980
- const range = {
6981
- value,
6982
- start: match.index + offset,
6983
- end: match.index + offset + value.length
6984
- };
6985
- offset += value.length + separator.length;
6986
- return range;
6987
- });
6988
- const first = coords[0];
6989
- if (!first) continue;
6990
- const components = [{
6991
- start: first.start,
6992
- end: first.end
6993
- }];
6994
- let project = -1;
6995
- if (parts.length > 1) {
6996
- if ([
6997
- "Desktop",
6998
- "Desktop Folders",
6999
- "Documents",
7000
- "Projects",
7001
- "workspace",
7002
- "workspaces",
7003
- "repos",
7004
- "code"
7005
- ].includes(parts[1] ?? "")) project = parts.length > 2 ? 2 : -1;
7006
- else if (!(parts[1] ?? "").startsWith(".")) project = 1;
7007
- }
7008
- for (let index = 1; index < coords.length; index++) {
7009
- const value = coords[index];
7010
- if (!value?.value || index === 1 && project === 2) continue;
7011
- if (index === project || !generic.has(value.value)) components.push({
7012
- start: value.start,
7013
- end: value.end
7014
- });
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);
7015
6711
  }
7016
- found.push({
7017
- start: match.index,
7018
- end: match.index + raw.length,
7019
- components
7020
- });
7021
- }
7022
- return found;
7023
- }
7024
- /** Only isolated low-information values inside an explicitly marked CLI example section. */
7025
- function helpSentinels(text) {
7026
- if (!/^Usage:/mu.test(text) || !/^Examples:/mu.test(text)) return [];
7027
- const begin = text.indexOf("Examples:"), end = text.indexOf("\nOptions:", begin), zone = text.slice(begin, end < 0 ? text.length : end), result = [];
7028
- for (const match of zone.matchAll(/\b(?:API_KEY|api_key|TOKEN|password)=(xxx|\.\.\.|<API_KEY>|<TOKEN>)(?=\s|$)/gu)) {
7029
- const value = match[1];
7030
- if (!value) continue;
7031
- const start = begin + match.index + match[0].lastIndexOf(value);
7032
- 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 ? [] : [{
7033
6719
  start,
7034
- end: start + value.length
7035
- });
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);
7036
6735
  }
7037
6736
  return result;
7038
6737
  }
7039
6738
  //#endregion
7040
- //#region packages/artifact/src/configured/review/ranges.ts
7041
- function staticSpan(mask) {
7042
- return {
7043
- ...mask.inputRange,
7044
- category: staticMaskCategory(mask.node.id),
7045
- causes: [{
7046
- kind: "static",
7047
- range: mask.inputRange,
7048
- stepId: mask.stepId,
7049
- node: mask.node,
7050
- ruleId: mask.ruleId
7051
- }]
7052
- };
7053
- }
7054
- /** These are deterministic B rules, independent of a model's occurrence decisions. */
7055
- function policySpan(range, nodeId, ruleId) {
7056
- return {
7057
- ...range,
7058
- category: staticMaskCategory(nodeId),
7059
- causes: [{
7060
- kind: "static",
7061
- range,
7062
- node: {
7063
- id: nodeId,
7064
- version: "sesspilot-b-v1"
7065
- },
7066
- stepId: "sesspilot-b-v1",
7067
- ruleId
7068
- }]
7069
- };
7070
- }
7071
- function subtract(input, retained) {
7072
- return input.flatMap((range) => {
7073
- let pieces = [range];
7074
- for (const keep of retained) pieces = pieces.flatMap((piece) => keep.end <= piece.start || keep.start >= piece.end ? [piece] : [{
7075
- ...piece,
7076
- end: Math.min(piece.end, keep.start)
7077
- }, {
7078
- ...piece,
7079
- start: Math.max(piece.start, keep.end)
7080
- }].filter((part) => part.end > part.start));
7081
- return pieces;
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
7082
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;
7083
7068
  }
7084
- function validate(text, range) {
7085
- if (!Number.isSafeInteger(range.start) || !Number.isSafeInteger(range.end) || range.start < 0 || range.end <= range.start || range.end > text.length || !scalarBoundary(text, range.start) || !scalarBoundary(text, range.end)) fail("ARTIFACT_PROCESSING_MISMATCH");
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
+ };
7086
7094
  }
7087
- /** B rule comparison and precise retention; no dictionary term becomes a global replacement. */
7088
- function reviewSpans(field, edit) {
7089
- for (const range of [
7090
- ...edit?.spans ?? [],
7091
- ...edit?.corrections ?? [],
7092
- ...edit?.retained ?? []
7093
- ]) validate(field.text, range);
7094
- if (edit && edit.textSha256 !== field.fieldHash) fail("ARTIFACT_PROCESSING_MISMATCH");
7095
- if (field.scalarKind === "structure") {
7096
- if (edit) fail("ARTIFACT_PROCESSING_MISMATCH");
7097
- return [];
7098
- }
7099
- const paths = componentPaths(field.text, /\/(?:file_path|filePath|path|cwd|root)$/u.test(field.innerPointer ?? field.originalPointer)), sentinels = helpSentinels(field.text);
7100
- const rules = [...field.staticMasks.filter((mask) => !paths.some((path) => path.start <= mask.inputRange.start && path.end >= mask.inputRange.end)), ...field.nonPathMasks].map(staticSpan);
7101
- rules.push(...paths.flatMap((path) => path.components.map((range) => policySpan(range, "filesystem-paths", "component-path-v2"))));
7102
- const mandatory = [...field.staticMasks, ...field.nonPathMasks].filter((mask) => mask.node.id === "custom-terms");
7103
- const sentinel = (range) => !(field.customRanges ?? []).some((r) => r.start < range.end && r.end > range.start) && !mandatory.some((mask) => mask.inputRange.start < range.end && mask.inputRange.end > range.start) && sentinels.some((s) => s.start <= range.start && s.end >= range.end);
7104
- const isolated = rules.filter((range) => !sentinel(range));
7105
- const protectedSources = /* @__PURE__ */ new Map(), customSources = /* @__PURE__ */ new Map();
7106
- for (const mask of [...field.staticMasks, ...field.nonPathMasks]) {
7107
- const key = `${mask.inputRange.start}:${mask.inputRange.end}`, previous = protectedSources.get(key);
7108
- if (mask.node.id === "custom-terms") customSources.set(key, mask);
7109
- if (!previous || categoryOrder.indexOf(staticMaskCategory(mask.node.id)) > categoryOrder.indexOf(staticMaskCategory(previous.node.id))) protectedSources.set(key, mask);
7110
- }
7111
- const protectedSpans = field.protectedRanges.filter((range) => !sentinel(range)).map((range) => {
7112
- return staticSpan({
7113
- ...protectedSources.get(`${range.start}:${range.end}`) ?? fail("ARTIFACT_PROCESSING_MISMATCH"),
7114
- inputRange: range
7115
- });
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
+ };
7116
7127
  });
7117
- const all = [
7118
- ...subtract(isolated, edit?.retained ?? []),
7119
- ...protectedSpans,
7120
- ...(field.customRanges ?? []).map((range) => {
7121
- const source = customSources.get(`${range.start}:${range.end}`);
7122
- return source ? staticSpan(source) : policySpan(range, "custom-terms", "explicit-term");
7123
- }),
7124
- ...(edit?.spans ?? []).map((span) => ({
7125
- ...span,
7126
- causes: [{
7127
- kind: "semantic",
7128
- range: {
7129
- start: span.start,
7130
- end: span.end
7131
- },
7132
- category: span.category
7133
- }]
7134
- })),
7135
- ...(edit?.corrections ?? []).map((span) => ({
7136
- ...span,
7137
- causes: [{
7138
- kind: "correction",
7139
- range: {
7140
- start: span.start,
7141
- end: span.end
7142
- },
7143
- category: span.category
7144
- }]
7145
- }))
7146
- ];
7147
- for (const range of all) {
7148
- validate(field.text, range);
7149
- if (!categoryOrder.some((category) => category === range.category)) fail("ARTIFACT_PROCESSING_MISMATCH");
7150
- }
7151
- const markers = all.length ? [...field.text.matchAll(markerPattern)] : [];
7152
- const ordered = all.map((range) => markers.reduce((span, marker) => {
7153
- const start = marker.index, end = start + marker[0].length;
7154
- return span.start < end && span.end > start ? {
7155
- ...span,
7156
- start: Math.min(span.start, start),
7157
- end: Math.max(span.end, end)
7158
- } : span;
7159
- }, range)).toSorted((a, b) => a.start - b.start || a.end - b.end), merged = [];
7160
- for (const range of ordered) {
7161
- const previous = merged.at(-1);
7162
- if (previous && range.start < previous.end) {
7163
- const priority = (category) => categoryOrder.findIndex((value) => value === category);
7164
- merged[merged.length - 1] = {
7165
- start: previous.start,
7166
- end: Math.max(previous.end, range.end),
7167
- category: priority(previous.category) >= priority(range.category) ? previous.category : range.category,
7168
- causes: [...previous.causes, ...range.causes]
7169
- };
7170
- } else merged.push(range);
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;
7171
7134
  }
7172
- return merged;
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
+ };
7173
7148
  }
7174
7149
  //#endregion
7175
- //#region packages/artifact/src/configured/review/provenance.ts
7176
- const hash$5 = (value) => createHash("sha256").update(JSON.stringify(value)).digest("hex");
7177
- /** Final positions come from reconstruction; original causes keep their actual scope and stage. */
7178
- function reconstructedContributors(input) {
7179
- const { row, field, span, transcript, coordinates, context } = input;
7180
- const contributors = /* @__PURE__ */ new Map();
7181
- for (const cause of span.causes) {
7182
- const localRange = {
7183
- start: Math.max(cause.range.start, span.start),
7184
- end: Math.min(cause.range.end, span.end)
7185
- };
7186
- if (localRange.end <= localRange.start) continue;
7187
- const inputRange = coordinates(localRange);
7188
- if (cause.kind === "semantic" || cause.kind === "correction") {
7189
- const source = {
7190
- ...transcript,
7191
- inputRange,
7192
- context: context(inputRange),
7193
- category: maskCategory(cause.category)
7194
- };
7195
- const id = hash$5([
7196
- row.entryPath,
7197
- row.recordIndex,
7198
- cause.kind,
7199
- source
7200
- ]);
7201
- contributors.set(id, {
7202
- id,
7203
- kind: cause.kind,
7204
- category: source.category,
7205
- source
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
7206
7192
  });
7207
- } else {
7208
- const source = {
7209
- entryPath: row.entryPath,
7210
- recordIndex: row.recordIndex,
7211
- sourcePartId: row.sourcePartId,
7212
- sourceRecordIndex: row.sourceRecordIndex,
7213
- archiveSessionId: row.archiveSessionId,
7214
- mask: {
7215
- stepId: cause.stepId,
7216
- node: cause.node,
7217
- ruleId: cause.ruleId,
7218
- inputRange,
7219
- outputRange: transcript.outputRange,
7220
- replacement: transcript.replacement,
7221
- fieldId: hash$5([
7222
- row.sourcePartId,
7223
- row.sourceRecordIndex,
7224
- field.originalPointer,
7225
- field.innerPointer ?? null
7226
- ]),
7227
- subject: "value",
7228
- originalPointer: field.originalPointer,
7229
- outputPointer: transcript.pointer,
7230
- sourceRange: field.innerPointer === void 0 ? {
7231
- start: (field.originalRange?.start ?? 0) + localRange.start,
7232
- end: (field.originalRange?.start ?? 0) + localRange.end
7233
- } : null,
7234
- inputSha256: transcript.inputSha256,
7235
- outputSha256: transcript.outputSha256,
7236
- context: context(inputRange)
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;
7237
7245
  }
7238
- };
7239
- const id = hash$5([
7240
- row.entryPath,
7241
- row.recordIndex,
7242
- "static",
7243
- source.mask
7244
- ]);
7245
- contributors.set(id, {
7246
- id,
7247
- kind: "static",
7248
- category: staticMaskCategory(cause.node.id),
7249
- source
7250
- });
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();
7251
7254
  }
7255
+ } catch (error) {
7256
+ cleanup.failed(error);
7257
+ throw error;
7258
+ } finally {
7259
+ await cleanup.run(() => output.return(void 0), () => archive.close());
7252
7260
  }
7253
- if (!contributors.size) fail("ARTIFACT_PROCESSING_MISMATCH");
7254
- return [...contributors.values()];
7255
7261
  }
7256
7262
  //#endregion
7257
- //#region packages/artifact/src/configured/review/render.ts
7258
- const hash$4 = (text) => createHash("sha256").update(text).digest("hex");
7259
- const address = (pointer, inner) => JSON.stringify([pointer, inner ?? null]);
7260
- /** Offsets in the same lossless serialization used by renderNative, including escaped JSON strings. */
7261
- function stringOffsets(root, changes) {
7262
- const offsets = /* @__PURE__ */ new Map();
7263
- let offset = 0;
7264
- const visit = (node) => {
7265
- const changed = changes.get(node.id);
7266
- if (node.kind === "string" || changed !== void 0) {
7267
- offsets.set(node.id, offset + 1);
7268
- offset += JSON.stringify(changed ?? (node.kind === "string" ? node.value : "")).length;
7269
- } else if (node.kind === "literal") {
7270
- offsets.set(node.id, offset);
7271
- offset += node.raw.length;
7272
- } else if (node.kind === "array") {
7273
- offsets.set(node.id, offset);
7274
- offset++;
7275
- node.items.forEach((child, index) => {
7276
- if (index) offset++;
7277
- visit(child);
7278
- });
7279
- offset++;
7280
- } else {
7281
- offset++;
7282
- node.properties.forEach((property, index) => {
7283
- if (index) offset++;
7284
- offset += JSON.stringify(property.key.value).length + 1;
7285
- visit(property.value);
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
7286
7336
  });
7287
- offset++;
7288
7337
  }
7289
- };
7290
- visit(root);
7291
- return offsets;
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;
7292
7360
  }
7293
- const encodedLength = (text) => JSON.stringify(text).length - 2;
7294
- /** Absolute JSON string-content coordinates. Fixed-size checkpoints bound both the work
7295
- * per lookup and retained memory, including out-of-order overlapping contributor ranges. */
7296
- function encodedOffset(text, base) {
7297
- const stride = 1024;
7298
- const offsets = [base];
7299
- const boundary = (block) => {
7300
- const at = block * stride;
7301
- return scalarBoundary(text, at) ? at : at - 1;
7302
- };
7303
- return (position) => {
7304
- const block = Math.floor(position / stride);
7305
- while (offsets.length <= block) {
7306
- const next = offsets.length;
7307
- offsets.push((offsets[next - 1] ?? fail("ARTIFACT_PROCESSING_MISMATCH")) + encodedLength(text.slice(boundary(next - 1), boundary(next))));
7308
- }
7309
- return (offsets[block] ?? fail("ARTIFACT_PROCESSING_MISMATCH")) + encodedLength(text.slice(boundary(block), position));
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
+ }]
7310
7374
  };
7311
7375
  }
7312
- /** Restore verified untouched scalar lexemes without round-tripping through JS numbers. */
7313
- function restoreLiterals(root, literals) {
7314
- const raw = literals.get(root.id);
7315
- if (raw !== void 0) return {
7316
- id: root.id,
7317
- kind: "literal",
7318
- raw
7319
- };
7320
- if (root.kind === "array") return {
7321
- ...root,
7322
- items: root.items.map((node) => restoreLiterals(node, literals))
7323
- };
7324
- if (root.kind === "object") return {
7325
- ...root,
7326
- properties: root.properties.map((entry) => ({
7327
- ...entry,
7328
- value: restoreLiterals(entry.value, literals)
7329
- }))
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
+ }]
7330
7391
  };
7331
- return root;
7332
7392
  }
7333
- /** Rewrite only admitted value leaves; every other byte comes from the verified static base. */
7334
- function renderReviewRow(row, before, edits, markers, signal) {
7335
- if (hash$4(before) !== row.outputSha256) fail("ARTIFACT_PROCESSING_MISMATCH");
7336
- const raw = reviewNative(row.cleanedText, signal), actual = reviewNative(before, signal);
7337
- const pending = /* @__PURE__ */ new Map();
7338
- for (const edit of edits) {
7339
- const key = address(edit.pointer, edit.innerPointer);
7340
- if (pending.has(key)) fail("ARTIFACT_PROCESSING_MISMATCH");
7341
- pending.set(key, edit);
7393
+ function subtract(input, retained) {
7394
+ return input.flatMap((range) => {
7395
+ let pieces = [range];
7396
+ for (const keep of retained) pieces = pieces.flatMap((piece) => keep.end <= piece.start || keep.start >= piece.end ? [piece] : [{
7397
+ ...piece,
7398
+ end: Math.min(piece.end, keep.start)
7399
+ }, {
7400
+ ...piece,
7401
+ start: Math.max(piece.start, keep.end)
7402
+ }].filter((part) => part.end > part.start));
7403
+ return pieces;
7404
+ });
7405
+ }
7406
+ function validate(text, range) {
7407
+ if (!Number.isSafeInteger(range.start) || !Number.isSafeInteger(range.end) || range.start < 0 || range.end <= range.start || range.end > text.length || !scalarBoundary(text, range.start) || !scalarBoundary(text, range.end)) fail("ARTIFACT_PROCESSING_MISMATCH");
7408
+ }
7409
+ /** B rule comparison and precise retention; no dictionary term becomes a global replacement. */
7410
+ function reviewSpans(field, edit) {
7411
+ for (const range of [
7412
+ ...edit?.spans ?? [],
7413
+ ...edit?.corrections ?? [],
7414
+ ...edit?.retained ?? []
7415
+ ]) validate(field.text, range);
7416
+ if (edit && edit.textSha256 !== field.fieldHash) fail("ARTIFACT_PROCESSING_MISMATCH");
7417
+ if (field.scalarKind === "structure") {
7418
+ if (edit) fail("ARTIFACT_PROCESSING_MISMATCH");
7419
+ return [];
7342
7420
  }
7343
- const groups = /* @__PURE__ */ new Map();
7344
- for (const field of row.fields) groups.set(field.pointer, [...groups.get(field.pointer) ?? [], field]);
7345
- const changes = /* @__PURE__ */ new Map(), literals = /* @__PURE__ */ new Map(), transcripts = [], replaced = [];
7346
- for (const [pointer, fields] of groups) {
7347
- 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;
7348
- 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");
7349
- const inner = first.innerPointer === void 0 ? void 0 : original.kind === "string" ? reviewNative(original.value, signal) : fail("ARTIFACT_PROCESSING_MISMATCH");
7350
- const innerChanges = /* @__PURE__ */ new Map(), pieces = [];
7351
- for (const field of fields) {
7352
- if (field.cleanedPointer !== first.cleanedPointer || field.innerPointer === void 0 !== (first.innerPointer === void 0)) fail("ARTIFACT_PROCESSING_MISMATCH");
7353
- const source = inner && field.innerPointer !== void 0 ? nativePointer(inner, field.innerPointer) : original;
7354
- 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;
7355
- if (sourceValue === void 0 || sourceValue !== field.text || hash$4(sourceValue) !== field.fieldHash) return fail("ARTIFACT_PROCESSING_MISMATCH");
7356
- const key = address(field.pointer, field.innerPointer), edit = pending.get(key);
7357
- pending.delete(key);
7358
- const spans = reviewSpans(field, edit), causes = new Map(spans.map((span) => [span.start, span])), items = [];
7359
- const changed = replaceSemanticSpans(field.text, spans, markers, (span, replacement, start) => items.push({
7360
- inputRange: {
7421
+ const paths = componentPaths(field.text, /\/(?:file_path|filePath|path|cwd|root)$/u.test(field.innerPointer ?? field.originalPointer)), sentinels = helpSentinels(field.text);
7422
+ const rules = [...field.staticMasks.filter((mask) => !paths.some((path) => path.start <= mask.inputRange.start && path.end >= mask.inputRange.end)), ...field.nonPathMasks].map(staticSpan);
7423
+ rules.push(...paths.flatMap((path) => path.components.map((range) => policySpan(range, "filesystem-paths", "component-path-v2"))));
7424
+ const mandatory = [...field.staticMasks, ...field.nonPathMasks].filter((mask) => mask.node.id === "custom-terms");
7425
+ const sentinel = (range) => !(field.customRanges ?? []).some((r) => r.start < range.end && r.end > range.start) && !mandatory.some((mask) => mask.inputRange.start < range.end && mask.inputRange.end > range.start) && sentinels.some((s) => s.start <= range.start && s.end >= range.end);
7426
+ const isolated = rules.filter((range) => !sentinel(range));
7427
+ const protectedSources = /* @__PURE__ */ new Map(), customSources = /* @__PURE__ */ new Map();
7428
+ for (const mask of [...field.staticMasks, ...field.nonPathMasks]) {
7429
+ const key = `${mask.inputRange.start}:${mask.inputRange.end}`, previous = protectedSources.get(key);
7430
+ if (mask.node.id === "custom-terms") customSources.set(key, mask);
7431
+ if (!previous || categoryOrder.indexOf(staticMaskCategory(mask.node.id)) > categoryOrder.indexOf(staticMaskCategory(previous.node.id))) protectedSources.set(key, mask);
7432
+ }
7433
+ const protectedSpans = field.protectedRanges.filter((range) => !sentinel(range)).map((range) => {
7434
+ return staticSpan({
7435
+ ...protectedSources.get(`${range.start}:${range.end}`) ?? fail("ARTIFACT_PROCESSING_MISMATCH"),
7436
+ inputRange: range
7437
+ });
7438
+ });
7439
+ const all = [
7440
+ ...subtract(isolated, edit?.retained ?? []),
7441
+ ...protectedSpans,
7442
+ ...(field.customRanges ?? []).map((range) => {
7443
+ const source = customSources.get(`${range.start}:${range.end}`);
7444
+ return source ? staticSpan(source) : policySpan(range, "custom-terms", "explicit-term");
7445
+ }),
7446
+ ...(edit?.spans ?? []).map((span) => ({
7447
+ ...span,
7448
+ causes: [{
7449
+ kind: "semantic",
7450
+ range: {
7361
7451
  start: span.start,
7362
7452
  end: span.end
7363
7453
  },
7364
- outputRange: {
7365
- start,
7366
- end: start + replacement.length
7367
- },
7368
- replacement,
7369
- category: maskCategory(span.category),
7370
- span: causes.get(span.start) ?? fail("ARTIFACT_PROCESSING_MISMATCH")
7371
- }));
7372
- pieces.push({
7373
- node: source.id,
7374
- field,
7375
- source: sourceValue,
7376
- changed,
7377
- items
7378
- });
7379
- if (inner && changed !== sourceValue) innerChanges.set(source.id, changed);
7380
- }
7381
- 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");
7382
- const changed = inner ? renderNative(inner, innerChanges, reviewLimits, signal).text : pieces[0]?.changed ?? fail("ARTIFACT_PROCESSING_MISMATCH");
7383
- const sourceOffsets = inner ? stringOffsets(inner, /* @__PURE__ */ new Map()) : void 0, outputOffsets = inner ? stringOffsets(inner, innerChanges) : void 0;
7384
- const inputSha256 = hash$4(sourceText), outputSha256 = hash$4(changed), context = createSentenceContext(sourceText);
7385
- for (const piece of pieces) {
7386
- if (!piece.items.length) continue;
7387
- const inputOffset = sourceOffsets && encodedOffset(piece.source, sourceOffsets.get(piece.node) ?? fail("ARTIFACT_PROCESSING_MISMATCH"));
7388
- const outputOffset = outputOffsets && encodedOffset(piece.changed, outputOffsets.get(piece.node) ?? fail("ARTIFACT_PROCESSING_MISMATCH"));
7389
- const coordinates = (range) => inputOffset ? {
7390
- start: inputOffset(range.start),
7391
- end: inputOffset(range.end)
7392
- } : range;
7393
- for (const item of piece.items) {
7394
- const inputRange = coordinates(item.inputRange);
7395
- const start = outputOffset ? outputOffset(item.outputRange.start) : item.outputRange.start;
7396
- const { span, ...applied } = item;
7397
- const transcript = {
7398
- ...applied,
7399
- pointer,
7400
- inputSha256,
7401
- outputSha256,
7402
- inputRange,
7403
- outputRange: {
7404
- start,
7405
- end: start + item.replacement.length
7406
- },
7407
- context: context(inputRange)
7408
- };
7409
- transcripts.push({
7410
- ...transcript,
7411
- contributors: reconstructedContributors({
7412
- row,
7413
- field: piece.field,
7414
- span,
7415
- transcript,
7416
- coordinates,
7417
- context
7418
- })
7419
- });
7420
- }
7421
- }
7422
- if (nativeContainer && changed === sourceText) {
7423
- if (nativeContainerText(target, signal) !== sourceText) fail("ARTIFACT_PROCESSING_MISMATCH");
7424
- } else if (nativeLiteral && changed === sourceText) literals.set(target.id, sourceText);
7425
- else changes.set(target.id, changed);
7426
- replaced.push(pointer);
7427
- }
7428
- if (pending.size) fail("ARTIFACT_PROCESSING_MISMATCH");
7429
- const restored = literals.size ? restoreLiterals(actual, literals) : actual;
7430
- return {
7431
- text: renderNative(restored, changes, reviewLimits, signal).text,
7432
- transcripts,
7433
- replaced
7434
- };
7435
- }
7436
- //#endregion
7437
- //#region packages/artifact/src/configured/output/family-carrier.ts
7438
- /** Map decoded UTF-16 boundaries to complete JSON escape tokens in the original string. */
7439
- function boundaries(text, span, value) {
7440
- const offsets = [span.start + 1];
7441
- let cursor = span.start + 1;
7442
- while (cursor < span.end - 1) {
7443
- cursor += text[cursor] === "\\" ? text[cursor + 1] === "u" ? 6 : 2 : 1;
7444
- offsets.push(cursor);
7445
- }
7446
- if (cursor !== span.end - 1 || offsets.length !== value.length + 1) fail("ARTIFACT_PROCESSING_MISMATCH");
7447
- return offsets;
7448
- }
7449
- /** One harness-declared JSON carrier layer; never interpret ordinary strings recursively. */
7450
- function familyCarrierSpans(field, find, signal) {
7451
- const text = field.text;
7452
- if (![
7453
- "tool-call",
7454
- "tool-result",
7455
- "runtime"
7456
- ].includes(field.origin.carrier) || !/^\s*[[{]/u.test(text)) return void 0;
7457
- try {
7458
- parseNativeRecord(text, limits, signal);
7459
- } catch (error) {
7460
- if (error instanceof ProcessingError && ["PROCESSING_INVALID_RECORD", "PROCESSING_KEY_COLLISION"].includes(error.code)) return void 0;
7461
- throw error;
7454
+ category: span.category
7455
+ }]
7456
+ })),
7457
+ ...(edit?.corrections ?? []).map((span) => ({
7458
+ ...span,
7459
+ causes: [{
7460
+ kind: "correction",
7461
+ range: {
7462
+ start: span.start,
7463
+ end: span.end
7464
+ },
7465
+ category: span.category
7466
+ }]
7467
+ }))
7468
+ ];
7469
+ for (const range of all) {
7470
+ validate(field.text, range);
7471
+ if (!categoryOrder.some((category) => category === range.category)) fail("ARTIFACT_PROCESSING_MISMATCH");
7462
7472
  }
7463
- const root = jsonSpans(text, signal) ?? fail("ARTIFACT_PROCESSING_MISMATCH");
7464
- const spans = [];
7465
- const visit = (part) => {
7466
- checkAbort(signal);
7467
- if (part.fields) for (const [key, value] of part.fields) {
7468
- visit(part.keys?.get(key) ?? fail("ARTIFACT_PROCESSING_MISMATCH"));
7469
- visit(value);
7470
- }
7471
- else if (part.items) for (const item of part.items) visit(item);
7472
- else if (typeof part.value === "string") {
7473
- const matches = find(part.value);
7474
- if (!matches.length) return;
7475
- const offsets = boundaries(text, part, part.value);
7476
- for (const match of matches) {
7477
- const start = offsets[match.start] ?? fail("ARTIFACT_PROCESSING_MISMATCH");
7478
- const end = offsets[match.end] ?? fail("ARTIFACT_PROCESSING_MISMATCH");
7479
- spans.push({
7480
- ...match,
7481
- start,
7482
- end
7483
- });
7484
- }
7485
- } else {
7486
- const value = text.slice(part.start, part.end);
7487
- for (const match of find(value)) spans.push({
7488
- ...match,
7489
- start: part.start + match.start,
7490
- end: part.start + match.end,
7491
- jsonScalar: {
7492
- start: part.start,
7493
- end: part.end
7494
- }
7495
- });
7496
- }
7497
- };
7498
- visit(root);
7499
- return spans;
7500
- }
7501
- /** Never publish a carrier whose edited keys collide or whose JSON structure changed. */
7502
- function validateFamilyCarrier(text, signal) {
7503
- try {
7504
- parseNativeRecord(text, limits, signal);
7505
- } catch (error) {
7506
- if (error instanceof ProcessingError && ["PROCESSING_INVALID_RECORD", "PROCESSING_KEY_COLLISION"].includes(error.code)) fail("ARTIFACT_PROCESSING_MISMATCH", { cause: error });
7507
- throw error;
7473
+ const markers = all.length ? [...field.text.matchAll(markerPattern)] : [];
7474
+ const ordered = all.map((range) => markers.reduce((span, marker) => {
7475
+ const start = marker.index, end = start + marker[0].length;
7476
+ return span.start < end && span.end > start ? {
7477
+ ...span,
7478
+ start: Math.min(span.start, start),
7479
+ end: Math.max(span.end, end)
7480
+ } : span;
7481
+ }, range)).toSorted((a, b) => a.start - b.start || a.end - b.end), merged = [];
7482
+ for (const range of ordered) {
7483
+ const previous = merged.at(-1);
7484
+ if (previous && range.start < previous.end) {
7485
+ const priority = (category) => categoryOrder.findIndex((value) => value === category);
7486
+ merged[merged.length - 1] = {
7487
+ start: previous.start,
7488
+ end: Math.max(previous.end, range.end),
7489
+ category: priority(previous.category) >= priority(range.category) ? previous.category : range.category,
7490
+ causes: [...previous.causes, ...range.causes]
7491
+ };
7492
+ } else merged.push(range);
7508
7493
  }
7494
+ return merged;
7509
7495
  }
7510
7496
  //#endregion
7511
- //#region packages/artifact/src/configured/output/family.ts
7512
- /** Names the failed check in the private cause chain; it never carries session text. */
7513
- const mismatch = (check) => fail("ARTIFACT_PROCESSING_MISMATCH", { cause: /* @__PURE__ */ new Error(`configured family hide check=${check}`) });
7514
- /** Binds each family's main Hide literals to its main and worker data and metadata entries. */
7515
- function indexFamilyHides(manifest, hides = []) {
7516
- const sessions = new Map(manifest.sessions.map((session) => [session.id, session]));
7517
- const parts = /* @__PURE__ */ new Map();
7518
- const bind = (id, family, main) => {
7519
- const session = sessions.get(id) ?? mismatch("unknown-session");
7520
- if (parts.has(session.metadataPath)) mismatch("duplicate-session");
7521
- if (session.parts.some((part) => part.native.role === "main") !== main) mismatch("session-role");
7522
- parts.set(session.metadataPath, family);
7523
- for (const part of session.parts) {
7524
- if (parts.has(part.dataPath)) mismatch("duplicate-part");
7525
- parts.set(part.dataPath, family);
7526
- }
7527
- };
7528
- const shared = /* @__PURE__ */ new Map();
7529
- for (const hide of hides) {
7530
- if (!hide.terms.length || !(hide.mainSessionIds.length + hide.workerSessionIds.length)) mismatch("empty-family");
7531
- const key = JSON.stringify([hide.terms, hide.exceptions ?? []]);
7532
- let family = shared.get(key);
7533
- if (!family) {
7534
- const categories = /* @__PURE__ */ new Map();
7535
- const bounded = /* @__PURE__ */ new Set();
7536
- const toolResultEscapes = /* @__PURE__ */ new Set();
7537
- for (const { term, category, bounded: whole, toolResultEscapes: escaped } of hide.terms) {
7538
- if (categories.has(term)) mismatch("duplicate-term");
7539
- categories.set(term, maskCategory(category));
7540
- if (whole) bounded.add(term);
7541
- if (escaped) toolResultEscapes.add(term);
7542
- }
7543
- family = {
7544
- matcher: createEntityMatcher([...categories.keys()].map((value) => ({
7545
- kind: "custom-term",
7546
- value
7547
- }))),
7548
- categories,
7549
- bounded,
7550
- toolResultEscapes,
7551
- excepted: bExceptionRanges(hide.exceptions ?? [])
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)
7552
7516
  };
7553
- shared.set(key, family);
7554
- }
7555
- for (const id of hide.mainSessionIds) bind(id, family, true);
7556
- for (const id of hide.workerSessionIds) bind(id, family, false);
7557
- }
7558
- return parts;
7559
- }
7560
- /** Disjoint literal hits outside existing markers; overlaps join under the highest category. */
7561
- function familySpans(text, family, signal, toolResult) {
7562
- const markers = [...text.matchAll(markerPattern)].map((match) => ({
7563
- start: match.index,
7564
- end: match.index + match[0].length
7565
- }));
7566
- let kept;
7567
- const excepted = (range) => (kept ??= bContainment(family.excepted(text, signal)))(range);
7568
- const marked = (range) => {
7569
- let low = 0, high = markers.length;
7570
- while (low < high) {
7571
- const middle = low + high >> 1;
7572
- if ((markers[middle]?.end ?? Infinity) <= range.start) low = middle + 1;
7573
- else high = middle;
7574
- }
7575
- return (markers[low]?.start ?? Infinity) < range.end;
7576
- };
7577
- const hits = family.matcher.find(text, signal, 2e6).filter(({ range, entity }) => !marked(range) && (!family.bounded.has(entity.value) || bWordBounded(text, range.start, range.end, toolResult && family.toolResultEscapes.has(entity.value))) && !excepted(range)).map(({ range, entity }) => ({
7578
- ...range,
7579
- category: family.categories.get(entity.value) ?? mismatch("unknown-term")
7580
- })).sort((left, right) => left.start - right.start || right.end - left.end);
7581
- const spans = [];
7582
- for (const hit of hits) {
7583
- const prior = spans.at(-1);
7584
- if (!prior || hit.start >= prior.end) {
7585
- spans.push(hit);
7586
- continue;
7587
- }
7588
- prior.end = Math.max(prior.end, hit.end);
7589
- if (categoryOrder.indexOf(hit.category) > categoryOrder.indexOf(prior.category)) prior.category = hit.category;
7590
- }
7591
- return spans;
7592
- }
7593
- /**
7594
- * Enum-like envelope values that native parsing interprets. Values inside an adapter-retained
7595
- * body are free text; outside bodies these names (and IDs) never take family terms.
7596
- */
7597
- const structuralNames = /* @__PURE__ */ new Set([
7598
- "type",
7599
- "role",
7600
- "name",
7601
- "subtype",
7602
- "stop_reason",
7603
- "status",
7604
- "kind",
7605
- "level",
7606
- "source",
7607
- "originator",
7608
- "mode",
7609
- "tool_name",
7610
- "toolName",
7611
- "function_name"
7612
- ]);
7613
- const structural = (name) => name !== void 0 && (structuralNames.has(name) || /(?:^id|_id|Id|uuid|Uuid)$/u.test(name));
7614
- /** Node IDs inside the adapter's retained bodies: the native free-text classification. */
7615
- function bodyNodes(root, selection) {
7616
- const bodies = new Set(selection.edits.map((edit) => edit.nodeId));
7617
- const nodes = /* @__PURE__ */ new Set();
7618
- const visit = (node, inside) => {
7619
- const body = inside || bodies.has(node.id);
7620
- if (body) nodes.add(node.id);
7621
- if (node.kind === "array") for (const item of node.items) visit(item, body);
7622
- if (node.kind === "object") for (const property of node.properties) visit(property.value, body);
7623
- };
7624
- visit(root, false);
7625
- return nodes;
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
+ });
7529
+ } else {
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)
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
7572
+ });
7573
+ }
7574
+ }
7575
+ if (!contributors.size) fail("ARTIFACT_PROCESSING_MISMATCH");
7576
+ return [...contributors.values()];
7626
7577
  }
7627
- /** Exact, cheap check that any string value can match: one linear scan whatever the term count. */
7628
- function mayMatch(root, family, signal) {
7629
- const values = [];
7578
+ //#endregion
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;
7630
7586
  const visit = (node) => {
7631
- if (node.kind === "string") values.push(node.value);
7632
- else if (node.kind === "array") for (const item of node.items) visit(item);
7633
- 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
+ }
7634
7611
  };
7635
7612
  visit(root);
7636
- return family.matcher.hasCustomTerm(values.join("\0"), signal) || values.some((value) => /^\s*[[{]/u.test(value) && value.includes("\\"));
7613
+ return offsets;
7637
7614
  }
7638
- /** Masks family literals in unprotected, non-structural string values `skip` does not exclude. */
7639
- function maskFamilyFields(text, root, annotations, family, markers, signal, onApplied, bodies, skip) {
7640
- const changes = /* @__PURE__ */ new Map();
7641
- const evidence = { bytes: 0 };
7642
- const recordLimits = recordPointerLimits(limits, Buffer.byteLength(text));
7643
- for (const field of walkNativeFields(root, annotations, {
7644
- recordId: digest$4(text),
7645
- limits: recordLimits,
7646
- signal
7647
- })) {
7648
- if (skip(field)) continue;
7649
- if (field.text.includes(markers.prefix)) mismatch("marker-prefix");
7650
- if (field.subject !== "value" || field.scalarKind !== "string" || field.field.protection || !bodies.has(field.nodeId) && structural(field.field.name)) continue;
7651
- const toolResult = field.origin.carrier === "tool-result";
7652
- const find = (value) => familySpans(value, family, signal, toolResult);
7653
- const raw = find(field.text);
7654
- const carrier = raw.length || field.text.includes("\\") ? familyCarrierSpans(field, find, signal) : void 0;
7655
- const spans = (carrier ?? raw).sort((left, right) => left.start - right.start);
7656
- if (!spans.length) continue;
7657
- const changed = maskOutputField({
7658
- pointer: field.pointer,
7659
- text: field.text,
7660
- sha256: digest$4(field.text)
7661
- }, spans, markers, evidence, onApplied);
7662
- if (carrier) validateFamilyCarrier(changed, signal);
7663
- changes.set(field.nodeId, changed);
7664
- }
7665
- 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
+ };
7666
7633
  }
7667
- /**
7668
- * Every row of a family part is parsed in order so native call/result state stays aligned.
7669
- * Worker rows: every unprotected string value. Main rows: every one that is not a B review
7670
- * field, which keeps its exact B decisions. Keys, roles, identities and tool links stay exact.
7671
- */
7672
- function createFamilyHideEditor(adapter, part, family, markers, signal, onApplied) {
7673
- const options = {
7674
- sourceRole: part.native.role,
7675
- 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
7676
7641
  };
7677
- const retention = adapter.retention(options);
7678
- return (text, reviewed = /* @__PURE__ */ new Set()) => {
7679
- checkAbort(signal);
7680
- const root = parseNativeRecord(text, limits, signal);
7681
- const selection = retention(root);
7682
- if (!mayMatch(root, family, signal)) return text;
7683
- 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
+ }))
7684
7652
  };
7653
+ return root;
7685
7654
  }
7686
- /** Session metadata is never analysed; its unprotected text (such as a title) takes family terms. */
7687
- function maskFamilyMetadata(text, family, markers, signal, onApplied) {
7688
- checkAbort(signal);
7689
- const root = parseNativeRecord(text, limits, signal);
7690
- 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
+ };
7691
7757
  }
7692
7758
  //#endregion
7693
7759
  //#region packages/artifact/src/configured/output/transform.ts
@@ -7711,6 +7777,7 @@ async function createOutputTransform(request, manifest, markers, signal) {
7711
7777
  session,
7712
7778
  part
7713
7779
  }])));
7780
+ const workspaceTitle = createWorkspaceTitleMasker(request, manifest, markers, signal);
7714
7781
  return {
7715
7782
  families,
7716
7783
  async metadata(text, entryPath) {
@@ -7720,7 +7787,7 @@ async function createOutputTransform(request, manifest, markers, signal) {
7720
7787
  return {
7721
7788
  text: family ? maskFamilyMetadata(text, family, markers, signal, (value) => transcripts.push(value)) : entryPath === manifest.work.metadataPath ? await updateOutputWorkMetadata(text, manifest, request, signal, (value) => {
7722
7789
  title = value;
7723
- }) : text,
7790
+ }) : workspaceTitle(text, entryPath, (value) => transcripts.push(value)),
7724
7791
  transcripts: title?.semanticTranscript ?? transcripts,
7725
7792
  titleMasks: title?.staticMasks
7726
7793
  };
@@ -15350,9 +15417,35 @@ async function processJourneyMetadata(request, signal = new AbortController().si
15350
15417
  }
15351
15418
  //#endregion
15352
15419
  //#region packages/artifact/src/configured/journey/original.ts
15353
- /** 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. */
15354
15421
  async function* readCapturedOriginalRows(source, options, signal = new AbortController().signal) {
15355
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
+ }
15356
15449
  const temporary = await createTemporary({
15357
15450
  outputDir: directory,
15358
15451
  keepTemp: false
@@ -16995,7 +17088,7 @@ async function prepareSessionScans(request, signal) {
16995
17088
  const opened = await openSourceCapture(request.captures.get(part.path) ?? fail("ARTIFACT_SOURCE_CHANGED"));
16996
17089
  const cleanup = createCleanup();
16997
17090
  try {
16998
- return await inspectCapturedSourceIdentity(part, opened, adapter, currentSignal, limits);
17091
+ return await (part.nativeEvidence?.identity?.role === "main" ? inspectCapturedSourceIdentity : inspectCompleteCapturedSourceIdentity)(part, opened, adapter, currentSignal, limits);
16999
17092
  } catch (error) {
17000
17093
  cleanup.failed(error);
17001
17094
  throw error;
@@ -17369,4 +17462,4 @@ async function hasRetiredSessionMarker(primary, omitted, retired, signal) {
17369
17462
  }
17370
17463
  }
17371
17464
  //#endregion
17372
- export { decodeZstd as $, captureLogicalJourneySources as A, defaultParallelism as B, writePrivateReviewPayload as C, createCollectionArtifacts as D, readConfiguredSearchFields as E, parseCollectionWorkspaceSummary as F, readLogicalJourneyFinalMasks as G, parallelismLimits as H, createSharedSessionPool as I, staticMaskCategory as J, readConfiguredOutputInfo as K, SessionWorkerError as L, renderJobDigest as M, runConfiguredSessionJob as N, checkReusableBundle as O, readCollectionIndex as P, createInspectionProcessor as Q, sessionWorkerFailure as R, writeLogicalJourneyBase as S, readOriginalSearchFields as T, writeLogicalJourneyOutput as U, gitSeedsProvider as V, privateJourneyDirectory as W, listAgentSetup as X, readWorkspacePair as Y, createConfiguredPreviewStream as Z, captureConfiguredSessionJob as _, prepareSessionScans as a, makePrivateDirectory as at, readStaticSessionMasks as b, createWorkPieces as c, windowsOwnerOnly as ct, scanPreparedSession as d, createTemporary as et, runConfiguredScanJob as f, openConfiguredUpload as g, configuredSessionUploads as h, verifyPreparedSessionSources as i, exclusiveLock as it, capturedJourneyScope as j, prepareCollectionProduction as k, readSessionScanFields as l, isWindowsAclFailure as lt, writeOutputShard as m, sessionExtensions as n, createCleanup as nt, buildWorkScanBatches as o, openPrivateFile as ot, verifyOutputShard as p, processJourneyMetadataFields as q, preparedScanConfiguration as r, safeError as rt, scanReviewFields as s, restrictToOwner as st, hasRetiredSessionMarker as t, removeNamedTemporarySpools as tt, readSessionScanRecords as u, windowsAclCodes as ut, readCapturedOriginalRows as v, readPrivateReviewPayload as w, staticSessionJobs as x, processJourneyMetadata as y, privateCollectionDirectory as z };
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 };