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