@gitroll/tacitt-cli 0.6.12 → 0.6.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agent-setup-B12VbvN_.mjs → agent-setup-CEPQfjBv.mjs} +2 -2
- package/dist/agent-setup-worker.mjs +5 -5
- package/dist/cli.mjs +10 -10
- package/dist/codex-title-worker.mjs +1 -1
- package/dist/configured-preview-worker.mjs +5 -5
- package/dist/configured-session-worker.mjs +5 -5
- package/dist/{frame-B3He21G8.mjs → frame-CRm99088.mjs} +1 -1
- package/dist/{heap-Blrat--4.mjs → heap-Bh9tySJp.mjs} +12 -7
- package/dist/inspection-worker.mjs +4 -4
- package/dist/{job-CBuIMTQ0.mjs → job-CsWKWcM4.mjs} +135 -36
- package/dist/{locate-D-ZaHpI0.mjs → locate-CP2t26j2.mjs} +449 -244
- package/dist/{model-DR9odhWP.mjs → model-ChHuVKoB.mjs} +1 -1
- package/dist/operation-executor.mjs +3 -3
- package/dist/preview-worker.mjs +1 -1
- package/dist/privacy-validator.mjs +1 -1
- package/dist/{query-BYDcNKy2.mjs → query-D28k3XOr.mjs} +6044 -5706
- package/dist/{run-DQ9xyKSt.mjs → run-CiJmV__5.mjs} +6 -6
- package/dist/{src-Do-qzuMn.mjs → src-B3il9x5F.mjs} +617 -545
- package/dist/{src-CKQlTA2Z.mjs → src-CWMrGXJK.mjs} +180 -30
- package/dist/{src-DeNJ8vOD.mjs → src-CmvEJj46.mjs} +1806 -1690
- package/dist/store-database-worker.mjs +1 -1
- package/dist/web/assets/index-XdWDOC5H.js +172 -0
- package/dist/web/index.html +1 -1
- package/package.json +1 -1
- package/skills/tacitt/INDEX.md +1 -1
- package/skills/tacitt/SKILL.md +5 -3
- package/skills/tacitt/references/INDEX.md +2 -2
- package/skills/tacitt/references/b-method.md +4 -2
- package/skills/tacitt/references/bootstrap.md +1 -1
- package/skills/tacitt/references/commands.md +23 -4
- package/skills/tacitt/references/journey.md +5 -3
- package/skills/tacitt/references/parallel-review.md +22 -9
- package/skills/tacitt/references/remote-workers.md +6 -2
- package/skills/tacitt/scripts/INDEX.md +5 -5
- package/skills/tacitt/scripts/answer.mjs +12 -1
- package/skills/tacitt/scripts/describe.mjs +3 -2
- package/skills/tacitt/scripts/journey-classification-tasks.mjs +2 -0
- package/skills/tacitt/scripts/journey-classification.mjs +1 -0
- package/skills/tacitt/scripts/journey-scan-timing.mjs +3 -2
- package/skills/tacitt/scripts/journey-state.d.mts +3 -0
- package/skills/tacitt/scripts/journey-state.mjs +8 -1
- package/skills/tacitt/scripts/journey.mjs +31 -1
- package/skills/tacitt/scripts/privacy-validator.mjs +160 -40
- package/skills/tacitt/scripts/review.d.mts +1 -0
- package/skills/tacitt/scripts/review.mjs +296 -35
- package/dist/web/assets/index-BgDdPL1c.js +0 -172
|
@@ -7202,7 +7202,7 @@ const inspectionSemanticVersions = Object.freeze({
|
|
|
7202
7202
|
});
|
|
7203
7203
|
//#endregion
|
|
7204
7204
|
//#region packages/processing/src/inspection/binding.ts
|
|
7205
|
-
function digest$
|
|
7205
|
+
function digest$7(value) {
|
|
7206
7206
|
return createHash("sha256").update(JSON.stringify(value)).digest("hex");
|
|
7207
7207
|
}
|
|
7208
7208
|
function identity(value) {
|
|
@@ -7222,14 +7222,14 @@ function sourceSet(values) {
|
|
|
7222
7222
|
/** Deliberately accepts no redaction plan; only cleanup changes the retained ID. */
|
|
7223
7223
|
function bindInspection(input) {
|
|
7224
7224
|
const shared = {
|
|
7225
|
-
sourceSetId: digest$
|
|
7225
|
+
sourceSetId: digest$7(["inspection-source-set-1", sourceSet(input.sources)]),
|
|
7226
7226
|
detectorVersion: currentDetectorVersion,
|
|
7227
7227
|
detectorConfigurationId: identity(input.detectorConfigurationId),
|
|
7228
7228
|
parserVersion: identity(input.parserVersion),
|
|
7229
7229
|
dictionaryVersion: entityDictionaryVersion,
|
|
7230
7230
|
attributionVersion: identity(input.attributionVersion)
|
|
7231
7231
|
};
|
|
7232
|
-
const originalId = digest$
|
|
7232
|
+
const originalId = digest$7([
|
|
7233
7233
|
originalInspectionVersion,
|
|
7234
7234
|
shared,
|
|
7235
7235
|
sourceSet(input.dictionarySources)
|
|
@@ -7239,7 +7239,7 @@ function bindInspection(input) {
|
|
|
7239
7239
|
...shared,
|
|
7240
7240
|
originalId,
|
|
7241
7241
|
projectionId,
|
|
7242
|
-
retainedId: digest$
|
|
7242
|
+
retainedId: digest$7([
|
|
7243
7243
|
"inspection-retained-1",
|
|
7244
7244
|
originalId,
|
|
7245
7245
|
projectionId
|
|
@@ -7546,7 +7546,7 @@ function createSentenceContext(text) {
|
|
|
7546
7546
|
}
|
|
7547
7547
|
//#endregion
|
|
7548
7548
|
//#region packages/processing/src/native/masks.ts
|
|
7549
|
-
const digest$
|
|
7549
|
+
const digest$6 = (text) => createHash("sha256").update(text).digest("hex");
|
|
7550
7550
|
/** Keeps only final retained mask regions and separates pre-static from provable raw offsets. */
|
|
7551
7551
|
function createNativeMaskCapture(options, originals) {
|
|
7552
7552
|
const captured = /* @__PURE__ */ new Map();
|
|
@@ -7586,8 +7586,8 @@ function createNativeMaskCapture(options, originals) {
|
|
|
7586
7586
|
if (value.whole && window === void 0) fail("PROCESSING_INVALID_RECORD");
|
|
7587
7587
|
const outputText = value.whole ? field.text : value.output;
|
|
7588
7588
|
const original = originalById.get(value.field.fieldId);
|
|
7589
|
-
const inputSha256 = digest$
|
|
7590
|
-
const outputSha256 = digest$
|
|
7589
|
+
const inputSha256 = digest$6(value.field.text);
|
|
7590
|
+
const outputSha256 = digest$6(outputText);
|
|
7591
7591
|
const context = createSentenceContext(value.field.text);
|
|
7592
7592
|
for (const mask of value.masks) {
|
|
7593
7593
|
let start = mask.outputRange.start;
|
|
@@ -8555,6 +8555,8 @@ const safeCodes = /* @__PURE__ */ new Set([
|
|
|
8555
8555
|
"ACCOUNT_NOT_CONFIGURED",
|
|
8556
8556
|
"ACCOUNT_SIGNED_OUT",
|
|
8557
8557
|
"ACCOUNT_ACCESS_UNAVAILABLE",
|
|
8558
|
+
"ACCOUNT_WORKS_UNAVAILABLE",
|
|
8559
|
+
"ACCOUNT_NOTHING_TO_SEND",
|
|
8558
8560
|
"JOURNEY_SIGN_IN_REQUIRED",
|
|
8559
8561
|
"ACCOUNT_PROFILE_UNAVAILABLE",
|
|
8560
8562
|
"PASSPORT_ADDRESS_TAKEN",
|
|
@@ -8714,7 +8716,8 @@ const safeFields = /* @__PURE__ */ new Set([
|
|
|
8714
8716
|
"cards.append.term-not-open",
|
|
8715
8717
|
"cards.append.own-identity-card",
|
|
8716
8718
|
"cards.append.other-person",
|
|
8717
|
-
"classification.late.several-works"
|
|
8719
|
+
"classification.late.several-works",
|
|
8720
|
+
"classification.account-work-split"
|
|
8718
8721
|
]);
|
|
8719
8722
|
function safeField(error) {
|
|
8720
8723
|
if (!(error instanceof ApplicationError) || !error.field) return null;
|
|
@@ -8735,7 +8738,7 @@ const range = z.object({
|
|
|
8735
8738
|
start: z.number().int().nonnegative(),
|
|
8736
8739
|
end: z.number().int().nonnegative()
|
|
8737
8740
|
}).strict();
|
|
8738
|
-
const digest$
|
|
8741
|
+
const digest$5 = z.string().regex(/^[a-f0-9]{64}$/u);
|
|
8739
8742
|
/** Original static title mask provenance for keyword-only preview/packaging. */
|
|
8740
8743
|
const classificationTitleMaskSchema = z.object({
|
|
8741
8744
|
inputRange: range,
|
|
@@ -8752,14 +8755,66 @@ const classificationTitleMaskSchema = z.object({
|
|
|
8752
8755
|
originalPointer: z.string().nullable(),
|
|
8753
8756
|
outputPointer: z.string().nullable(),
|
|
8754
8757
|
sourceRange: range.nullable(),
|
|
8755
|
-
inputSha256: digest$
|
|
8756
|
-
outputSha256: digest$
|
|
8758
|
+
inputSha256: digest$5,
|
|
8759
|
+
outputSha256: digest$5,
|
|
8757
8760
|
context: z.object({
|
|
8758
8761
|
start: z.number().int().nonnegative(),
|
|
8759
8762
|
text: z.string()
|
|
8760
8763
|
}).strict()
|
|
8761
8764
|
}).strict();
|
|
8762
8765
|
//#endregion
|
|
8766
|
+
//#region packages/application/src/journey/account-works.ts
|
|
8767
|
+
const digest$4 = z.string().regex(/^[0-9a-f]{64}$/u);
|
|
8768
|
+
const stored = z.object({
|
|
8769
|
+
/** Wire field from issue #131; a formation reply without it is read as no stored metadata. */
|
|
8770
|
+
metadataSha256: digest$4.nullish().transform((value) => value ?? null),
|
|
8771
|
+
key: digest$4,
|
|
8772
|
+
sessionKey: z.string().regex(/^sess-pilot\/[^/]+\/[^/]+\/[^/]+$/u).nullable(),
|
|
8773
|
+
sha256: digest$4,
|
|
8774
|
+
byteLength: z.number().int().positive(),
|
|
8775
|
+
lastAt: z.iso.datetime()
|
|
8776
|
+
});
|
|
8777
|
+
const access = z.enum([
|
|
8778
|
+
"public",
|
|
8779
|
+
"private",
|
|
8780
|
+
"removed"
|
|
8781
|
+
]);
|
|
8782
|
+
const accountWorksInventorySchema = z.object({
|
|
8783
|
+
works: z.array(z.object({
|
|
8784
|
+
logicalWorkId: z.uuid(),
|
|
8785
|
+
title: z.string().min(1).max(300),
|
|
8786
|
+
access,
|
|
8787
|
+
unitAccess: access,
|
|
8788
|
+
sessions: z.array(stored)
|
|
8789
|
+
})),
|
|
8790
|
+
unassigned: z.array(stored.extend({ removedFromWork: z.uuid().nullish().transform((value) => value ?? null) }))
|
|
8791
|
+
});
|
|
8792
|
+
const accountWorksSchema = z.discriminatedUnion("status", [
|
|
8793
|
+
z.strictObject({
|
|
8794
|
+
status: z.literal("read"),
|
|
8795
|
+
subject: z.string().min(1).max(128),
|
|
8796
|
+
at: z.iso.datetime(),
|
|
8797
|
+
inventory: accountWorksInventorySchema,
|
|
8798
|
+
/** Families with a key unassigned after its Work's removal: no Work, not sent (D4). */
|
|
8799
|
+
leftOut: z.array(z.strictObject({
|
|
8800
|
+
rootSessionId: z.string().min(1).max(128),
|
|
8801
|
+
removedWorkId: z.uuid()
|
|
8802
|
+
})).default([]),
|
|
8803
|
+
/** Families with a held key that are not cleanly placed: no Work, not sent (D9). */
|
|
8804
|
+
heldBack: z.array(z.string().min(1).max(128)).default([]),
|
|
8805
|
+
/** Every family was left out or held back: no Work and no snapshot (#129 review). */
|
|
8806
|
+
nothingToSend: z.literal(true).optional()
|
|
8807
|
+
}),
|
|
8808
|
+
z.strictObject({
|
|
8809
|
+
status: z.literal("signed-out"),
|
|
8810
|
+
at: z.iso.datetime()
|
|
8811
|
+
}),
|
|
8812
|
+
z.strictObject({
|
|
8813
|
+
status: z.literal("unavailable"),
|
|
8814
|
+
at: z.iso.datetime()
|
|
8815
|
+
})
|
|
8816
|
+
]);
|
|
8817
|
+
//#endregion
|
|
8763
8818
|
//#region packages/application/src/journey/profile.ts
|
|
8764
8819
|
/**
|
|
8765
8820
|
* Passport's own rules (talent-platform `profile-settings.ts`): 1 to 39 letters and digits with
|
|
@@ -9170,6 +9225,8 @@ const decisionCardSchema = decisionCardInputSchema.extend({ answer: z.object({
|
|
|
9170
9225
|
rule: z.string().max(4001),
|
|
9171
9226
|
additionalRule: z.string().max(2e3),
|
|
9172
9227
|
remember: z.boolean(),
|
|
9228
|
+
/** Where the answer came from; only the person's panel Hide is remembered (issue #126). */
|
|
9229
|
+
source: z.enum(["conversation", "panel"]).optional(),
|
|
9173
9230
|
excludedTermKeys: z.array(z.string().min(1)).max(2e4).optional()
|
|
9174
9231
|
}).strict().nullable() }).strict();
|
|
9175
9232
|
const journeyPrivacySchema = z.object({
|
|
@@ -9516,7 +9573,8 @@ const reviewInterruptionSchema = z.object({
|
|
|
9516
9573
|
}).strict();
|
|
9517
9574
|
const journeyWorkSchema = z.object({
|
|
9518
9575
|
id: journeyIdSchema,
|
|
9519
|
-
title
|
|
9576
|
+
/** 240 characters; an `account` title holds the server's 300 (ADR 0276 D2). */
|
|
9577
|
+
title: z.string().trim().min(1).max(300),
|
|
9520
9578
|
/** Statically processed repository or folder name; the original stays in the private plan. */
|
|
9521
9579
|
projectName: label,
|
|
9522
9580
|
projectType: journeyWorkTypeSchema.nullable(),
|
|
@@ -9532,7 +9590,11 @@ const journeyWorkSchema = z.object({
|
|
|
9532
9590
|
description: z.string(),
|
|
9533
9591
|
reason: z.string()
|
|
9534
9592
|
}).strict().optional(),
|
|
9535
|
-
titleOrigin: z.enum([
|
|
9593
|
+
titleOrigin: z.enum([
|
|
9594
|
+
"model",
|
|
9595
|
+
"explicit",
|
|
9596
|
+
"account"
|
|
9597
|
+
]),
|
|
9536
9598
|
explicitTitleId: journeyIdSchema.nullable(),
|
|
9537
9599
|
accessOrigin: z.enum([
|
|
9538
9600
|
"default",
|
|
@@ -9570,6 +9632,8 @@ const journeyWorkSchema = z.object({
|
|
|
9570
9632
|
inputRevision: count$1.min(1),
|
|
9571
9633
|
/** Placement created this Work (create-work or a sorting "new" decision): its name is generic. */
|
|
9572
9634
|
createdByPlacement: z.literal(true).optional(),
|
|
9635
|
+
/** Rebuilt at formation from the account Work with this id (ADR 0276 D1); never classified. */
|
|
9636
|
+
accountWork: z.literal(true).optional(),
|
|
9573
9637
|
/** Host-owned eligibility after removal-only regrouping; never authorizes output by itself. */
|
|
9574
9638
|
reviewReuseFrom: z.object({
|
|
9575
9639
|
inputRevision: count$1.min(1),
|
|
@@ -9625,7 +9689,7 @@ const journeyWorkSchema = z.object({
|
|
|
9625
9689
|
sentBundleId: journeyIdSchema.optional(),
|
|
9626
9690
|
sentAccess: z.enum(["public", "private"]).optional()
|
|
9627
9691
|
}).strict().nullable()
|
|
9628
|
-
}).strict();
|
|
9692
|
+
}).strict().refine((work) => work.titleOrigin === "account" || work.title.length <= 240, { path: ["title"] });
|
|
9629
9693
|
const journeyConsentSchema = z.object({
|
|
9630
9694
|
provider: label,
|
|
9631
9695
|
allowedAt: z.iso.datetime(),
|
|
@@ -9647,7 +9711,7 @@ const journeyExceptionSchema = z.object({
|
|
|
9647
9711
|
value: z.string().min(1).max(1024)
|
|
9648
9712
|
}).strict();
|
|
9649
9713
|
const nativeJourneySchema = z.object({
|
|
9650
|
-
formatVersion: z.literal(10),
|
|
9714
|
+
formatVersion: z.literal([10, 11]),
|
|
9651
9715
|
outputVersion: z.number().int().positive().optional(),
|
|
9652
9716
|
classificationRevision: count$1.nullable(),
|
|
9653
9717
|
privacy: journeyPrivacySchema,
|
|
@@ -9691,6 +9755,11 @@ const nativeJourneySchema = z.object({
|
|
|
9691
9755
|
/** ADR 0086: per-value Hide or Keep over the term types' answers; absent means none. */
|
|
9692
9756
|
valueOverrides: z.array(journeyValueOverrideSchema).max(1e4).optional(),
|
|
9693
9757
|
/**
|
|
9758
|
+
* Values the person hid in earlier journeys on this machine, frozen at formation (issue #126).
|
|
9759
|
+
* Private: never in a view, reader guidance or anything sent.
|
|
9760
|
+
*/
|
|
9761
|
+
rememberedHides: z.array(z.string().min(1).max(1024)).max(1e5).optional(),
|
|
9762
|
+
/**
|
|
9694
9763
|
* ADR 0086: the snapshot is read by dictionary review. A snapshot without it was read by B
|
|
9695
9764
|
* review, whose evidence this release no longer renders, so it is obsolete.
|
|
9696
9765
|
*/
|
|
@@ -9712,6 +9781,8 @@ const nativeJourneySchema = z.object({
|
|
|
9712
9781
|
* confirmation and Retry set `read`; late classification records only a failure. Absent in a
|
|
9713
9782
|
* journey of an earlier version, which reads as not `read`.
|
|
9714
9783
|
*/
|
|
9784
|
+
/** Formation read only; never establishes access proof. */
|
|
9785
|
+
accountWorks: accountWorksSchema.optional(),
|
|
9715
9786
|
accountRead: z.object({
|
|
9716
9787
|
status: z.enum([
|
|
9717
9788
|
"read",
|
|
@@ -9815,61 +9886,6 @@ const bCategorySchema = z.enum([
|
|
|
9815
9886
|
"other-identifying-information"
|
|
9816
9887
|
]);
|
|
9817
9888
|
//#endregion
|
|
9818
|
-
//#region packages/application/src/journey/b/submission.ts
|
|
9819
|
-
const bOccurrenceSchema = bAnchorSchema.extend({
|
|
9820
|
-
decision: z.enum([
|
|
9821
|
-
"sensitive",
|
|
9822
|
-
"retained",
|
|
9823
|
-
"uncertain"
|
|
9824
|
-
]),
|
|
9825
|
-
reason: z.string().min(1).max(1e3),
|
|
9826
|
-
classification: bClassificationSchema.nullable()
|
|
9827
|
-
}).strict();
|
|
9828
|
-
const bTermSchema = z.object({
|
|
9829
|
-
term: z.string().min(1).max(1024),
|
|
9830
|
-
category: bCategorySchema,
|
|
9831
|
-
occurrences: z.array(bOccurrenceSchema).min(1)
|
|
9832
|
-
}).strict();
|
|
9833
|
-
const bRetainedGroupSchema = bAnchorSchema.omit({
|
|
9834
|
-
start: true,
|
|
9835
|
-
end: true
|
|
9836
|
-
}).extend({
|
|
9837
|
-
starts: z.array(bCountSchema).min(1),
|
|
9838
|
-
reason: z.string().min(1).max(1e3)
|
|
9839
|
-
}).strict();
|
|
9840
|
-
const bRepresentationSchema = bAnchorSchema.extend({
|
|
9841
|
-
category: bCategorySchema,
|
|
9842
|
-
classification: bClassificationSchema,
|
|
9843
|
-
reason: z.string().min(1).max(1e3)
|
|
9844
|
-
}).strict();
|
|
9845
|
-
const bCoverageSchema = z.object({
|
|
9846
|
-
fieldId: bIdSchema,
|
|
9847
|
-
fieldHash: journeyDigestSchema,
|
|
9848
|
-
start: bCountSchema,
|
|
9849
|
-
end: bCountSchema,
|
|
9850
|
-
status: z.enum(["reviewed", "incomplete"])
|
|
9851
|
-
}).strict();
|
|
9852
|
-
const bSessionDecisionSchema = z.object({
|
|
9853
|
-
action: z.enum([
|
|
9854
|
-
"local_redaction",
|
|
9855
|
-
"exclude_session",
|
|
9856
|
-
"uncertain"
|
|
9857
|
-
]),
|
|
9858
|
-
reason: z.string().min(1).max(1e3),
|
|
9859
|
-
evidence: z.array(bAnchorSchema)
|
|
9860
|
-
}).strict();
|
|
9861
|
-
const bReviewSubmissionSchema = z.object({
|
|
9862
|
-
method: z.literal(bMethod),
|
|
9863
|
-
unitId: journeyDigestSchema,
|
|
9864
|
-
unitDigest: journeyDigestSchema,
|
|
9865
|
-
terms: z.array(bTermSchema),
|
|
9866
|
-
retainedSourceGroups: z.array(bRetainedGroupSchema),
|
|
9867
|
-
representationLimits: z.array(bRepresentationSchema),
|
|
9868
|
-
uncertainOccurrences: z.array(bAnchorSchema),
|
|
9869
|
-
coverage: z.array(bCoverageSchema).min(1),
|
|
9870
|
-
sessionDecision: bSessionDecisionSchema
|
|
9871
|
-
}).strict();
|
|
9872
|
-
//#endregion
|
|
9873
9889
|
//#region packages/application/src/journey/b/text.ts
|
|
9874
9890
|
const bDigest = (value) => createHash("sha256").update(value).digest("hex");
|
|
9875
9891
|
function codePointLength(text) {
|
|
@@ -10030,6 +10046,61 @@ function bEvidenceReader(unit, visible = unit.fragments) {
|
|
|
10030
10046
|
};
|
|
10031
10047
|
}
|
|
10032
10048
|
//#endregion
|
|
10049
|
+
//#region packages/application/src/journey/b/submission.ts
|
|
10050
|
+
const bOccurrenceSchema = bAnchorSchema.extend({
|
|
10051
|
+
decision: z.enum([
|
|
10052
|
+
"sensitive",
|
|
10053
|
+
"retained",
|
|
10054
|
+
"uncertain"
|
|
10055
|
+
]),
|
|
10056
|
+
reason: z.string().min(1).max(1e3),
|
|
10057
|
+
classification: bClassificationSchema.nullable()
|
|
10058
|
+
}).strict();
|
|
10059
|
+
const bTermSchema = z.object({
|
|
10060
|
+
term: z.string().min(1).max(1024),
|
|
10061
|
+
category: bCategorySchema,
|
|
10062
|
+
occurrences: z.array(bOccurrenceSchema).min(1)
|
|
10063
|
+
}).strict();
|
|
10064
|
+
const bRetainedGroupSchema = bAnchorSchema.omit({
|
|
10065
|
+
start: true,
|
|
10066
|
+
end: true
|
|
10067
|
+
}).extend({
|
|
10068
|
+
starts: z.array(bCountSchema).min(1),
|
|
10069
|
+
reason: z.string().min(1).max(1e3)
|
|
10070
|
+
}).strict();
|
|
10071
|
+
const bRepresentationSchema = bAnchorSchema.extend({
|
|
10072
|
+
category: bCategorySchema,
|
|
10073
|
+
classification: bClassificationSchema,
|
|
10074
|
+
reason: z.string().min(1).max(1e3)
|
|
10075
|
+
}).strict();
|
|
10076
|
+
const bCoverageSchema = z.object({
|
|
10077
|
+
fieldId: bIdSchema,
|
|
10078
|
+
fieldHash: journeyDigestSchema,
|
|
10079
|
+
start: bCountSchema,
|
|
10080
|
+
end: bCountSchema,
|
|
10081
|
+
status: z.enum(["reviewed", "incomplete"])
|
|
10082
|
+
}).strict();
|
|
10083
|
+
const bSessionDecisionSchema = z.object({
|
|
10084
|
+
action: z.enum([
|
|
10085
|
+
"local_redaction",
|
|
10086
|
+
"exclude_session",
|
|
10087
|
+
"uncertain"
|
|
10088
|
+
]),
|
|
10089
|
+
reason: z.string().min(1).max(1e3),
|
|
10090
|
+
evidence: z.array(bAnchorSchema)
|
|
10091
|
+
}).strict();
|
|
10092
|
+
const bReviewSubmissionSchema = z.object({
|
|
10093
|
+
method: z.literal(bMethod),
|
|
10094
|
+
unitId: journeyDigestSchema,
|
|
10095
|
+
unitDigest: journeyDigestSchema,
|
|
10096
|
+
terms: z.array(bTermSchema),
|
|
10097
|
+
retainedSourceGroups: z.array(bRetainedGroupSchema),
|
|
10098
|
+
representationLimits: z.array(bRepresentationSchema),
|
|
10099
|
+
uncertainOccurrences: z.array(bAnchorSchema),
|
|
10100
|
+
coverage: z.array(bCoverageSchema).min(1),
|
|
10101
|
+
sessionDecision: bSessionDecisionSchema
|
|
10102
|
+
}).strict();
|
|
10103
|
+
//#endregion
|
|
10033
10104
|
//#region packages/application/src/journey/b/result.ts
|
|
10034
10105
|
function bIssue(code, anchor) {
|
|
10035
10106
|
return {
|
|
@@ -10075,6 +10146,152 @@ function unownedBObligations(parts) {
|
|
|
10075
10146
|
return parts.filter((part) => !part.owned && !owned.some((other) => bProtects(other, part))).map((part) => bIssue("UNOWNED_SENSITIVE_CONTENT", part));
|
|
10076
10147
|
}
|
|
10077
10148
|
//#endregion
|
|
10149
|
+
//#region packages/application/src/journey/b/ranges.ts
|
|
10150
|
+
/** Invocation-local coverage of already validated code-point ranges. */
|
|
10151
|
+
function indexBRanges(parts) {
|
|
10152
|
+
const ranges = [];
|
|
10153
|
+
const ordered = parts.map(({ start, end }) => ({
|
|
10154
|
+
start,
|
|
10155
|
+
end
|
|
10156
|
+
}));
|
|
10157
|
+
ordered.sort((left, right) => left.start - right.start);
|
|
10158
|
+
for (const part of ordered) {
|
|
10159
|
+
const last = ranges.at(-1);
|
|
10160
|
+
if (last && part.start <= last.end) last.end = Math.max(last.end, part.end);
|
|
10161
|
+
else ranges.push(part);
|
|
10162
|
+
}
|
|
10163
|
+
const firstOverlap = (start) => {
|
|
10164
|
+
let low = 0;
|
|
10165
|
+
let high = ranges.length;
|
|
10166
|
+
while (low < high) {
|
|
10167
|
+
const middle = Math.floor((low + high) / 2);
|
|
10168
|
+
if ((ranges[middle]?.end ?? Infinity) <= start) low = middle + 1;
|
|
10169
|
+
else high = middle;
|
|
10170
|
+
}
|
|
10171
|
+
return low;
|
|
10172
|
+
};
|
|
10173
|
+
return {
|
|
10174
|
+
relation(query) {
|
|
10175
|
+
const part = ranges[firstOverlap(query.start)];
|
|
10176
|
+
return {
|
|
10177
|
+
covers: Boolean(part && part.start <= query.start && part.end >= query.end),
|
|
10178
|
+
overlaps: Boolean(part && part.start < query.end)
|
|
10179
|
+
};
|
|
10180
|
+
},
|
|
10181
|
+
uncovered(query) {
|
|
10182
|
+
const result = [];
|
|
10183
|
+
let cursor = query.start;
|
|
10184
|
+
for (let index = firstOverlap(cursor); index < ranges.length; index += 1) {
|
|
10185
|
+
const part = ranges[index];
|
|
10186
|
+
if (!part || part.start >= query.end) break;
|
|
10187
|
+
if (cursor < part.start) result.push({
|
|
10188
|
+
start: cursor,
|
|
10189
|
+
end: part.start
|
|
10190
|
+
});
|
|
10191
|
+
cursor = Math.max(cursor, part.end);
|
|
10192
|
+
if (cursor >= query.end) break;
|
|
10193
|
+
}
|
|
10194
|
+
if (cursor < query.end) result.push({
|
|
10195
|
+
start: cursor,
|
|
10196
|
+
end: query.end
|
|
10197
|
+
});
|
|
10198
|
+
return result;
|
|
10199
|
+
}
|
|
10200
|
+
};
|
|
10201
|
+
}
|
|
10202
|
+
//#endregion
|
|
10203
|
+
//#region packages/application/src/journey/b/literals.ts
|
|
10204
|
+
function bLiteralAdmitted(value) {
|
|
10205
|
+
return admitGitName(value, 1)?.value === value;
|
|
10206
|
+
}
|
|
10207
|
+
function bLiterals(evidence) {
|
|
10208
|
+
const value = evidence.exactQuote.normalize("NFC");
|
|
10209
|
+
if (bLiteralAdmitted(value)) return [{
|
|
10210
|
+
...evidence,
|
|
10211
|
+
term: value
|
|
10212
|
+
}];
|
|
10213
|
+
return literalPieces(evidence.exactQuote).map((part) => ({
|
|
10214
|
+
...evidence,
|
|
10215
|
+
start: evidence.start + part.start,
|
|
10216
|
+
end: evidence.start + part.end,
|
|
10217
|
+
utf16Start: evidence.utf16Start + part.utf16Start,
|
|
10218
|
+
utf16End: evidence.utf16Start + part.utf16End,
|
|
10219
|
+
exactQuote: part.exactQuote,
|
|
10220
|
+
term: part.term
|
|
10221
|
+
}));
|
|
10222
|
+
}
|
|
10223
|
+
/** The same admitted NFC terms for hidden text that is not one B evidence anchor. */
|
|
10224
|
+
function bLiteralTerms(text) {
|
|
10225
|
+
const value = text.normalize("NFC");
|
|
10226
|
+
return bLiteralAdmitted(value) ? [value] : literalPieces(text).map((part) => part.term);
|
|
10227
|
+
}
|
|
10228
|
+
/** Bounded line pieces of a nonrepresentable quote, in quote-relative coordinates. */
|
|
10229
|
+
function literalPieces(quote) {
|
|
10230
|
+
const chars = Array.from(quote);
|
|
10231
|
+
const index = createCodePointIndex(quote);
|
|
10232
|
+
const parts = [];
|
|
10233
|
+
let cursor = 0;
|
|
10234
|
+
while (cursor < chars.length) {
|
|
10235
|
+
while (cursor < chars.length && /\s/u.test(chars[cursor] ?? "")) cursor += 1;
|
|
10236
|
+
if (cursor === chars.length) break;
|
|
10237
|
+
const newline = chars.indexOf("\n", cursor);
|
|
10238
|
+
const lineEnd = newline < 0 ? chars.length : newline;
|
|
10239
|
+
let end = Math.min(lineEnd, cursor + 256);
|
|
10240
|
+
if (end < lineEnd) {
|
|
10241
|
+
let soft = end;
|
|
10242
|
+
while (soft > cursor + 12 && !/\s/u.test(chars[soft - 1] ?? "")) soft -= 1;
|
|
10243
|
+
if (soft > cursor + 12) end = soft;
|
|
10244
|
+
}
|
|
10245
|
+
while (end > cursor && /\s/u.test(chars[end - 1] ?? "")) end -= 1;
|
|
10246
|
+
if (end <= cursor) {
|
|
10247
|
+
cursor += 1;
|
|
10248
|
+
continue;
|
|
10249
|
+
}
|
|
10250
|
+
const exactQuote = index.slice(cursor, end);
|
|
10251
|
+
const term = exactQuote.normalize("NFC");
|
|
10252
|
+
if (end - cursor >= 12 && bLiteralAdmitted(term)) parts.push({
|
|
10253
|
+
start: cursor,
|
|
10254
|
+
end,
|
|
10255
|
+
utf16Start: index.offset(cursor),
|
|
10256
|
+
utf16End: index.offset(end),
|
|
10257
|
+
exactQuote,
|
|
10258
|
+
term
|
|
10259
|
+
});
|
|
10260
|
+
cursor = end;
|
|
10261
|
+
}
|
|
10262
|
+
return parts;
|
|
10263
|
+
}
|
|
10264
|
+
function uncoveredBObligations(sensitive, literals) {
|
|
10265
|
+
if (sensitive.length === 0) return [];
|
|
10266
|
+
const fields = new Map([...Map.groupBy(literals, (part) => part.fieldId)].map(([fieldId, parts]) => [fieldId, indexBRanges(parts)]));
|
|
10267
|
+
return sensitive.flatMap((evidence) => (fields.get(evidence.fieldId)?.uncovered(evidence) ?? [{
|
|
10268
|
+
start: evidence.start,
|
|
10269
|
+
end: evidence.end
|
|
10270
|
+
}]).filter((range) => /\S/u.test(codePointSlice(evidence.exactQuote, range.start - evidence.start, range.end - evidence.start))).map((range) => ({
|
|
10271
|
+
fieldId: evidence.fieldId,
|
|
10272
|
+
...range
|
|
10273
|
+
})));
|
|
10274
|
+
}
|
|
10275
|
+
//#endregion
|
|
10276
|
+
//#region packages/application/src/journey/review/findings.ts
|
|
10277
|
+
const semanticFindingSchema = z.object({
|
|
10278
|
+
id: journeyIdSchema,
|
|
10279
|
+
chunkId: journeyIdSchema,
|
|
10280
|
+
start: z.number().int().nonnegative(),
|
|
10281
|
+
end: z.number().int().nonnegative(),
|
|
10282
|
+
spanHash: journeyDigestSchema,
|
|
10283
|
+
kind: journeyKindSchema,
|
|
10284
|
+
class: z.enum([
|
|
10285
|
+
"certain",
|
|
10286
|
+
"gray",
|
|
10287
|
+
"clear"
|
|
10288
|
+
]),
|
|
10289
|
+
label: z.string().trim().min(1).max(120),
|
|
10290
|
+
groupKey: z.string().trim().min(1).max(120).nullable(),
|
|
10291
|
+
condition: z.string().max(1e3),
|
|
10292
|
+
defaultHide: z.number().min(0).max(1)
|
|
10293
|
+
}).strict();
|
|
10294
|
+
//#endregion
|
|
10078
10295
|
//#region packages/application/src/journey/b/duplicates.ts
|
|
10079
10296
|
/** At most this many fields bind to one analysed occurrence, so one field's bindings fit a batch. */
|
|
10080
10297
|
const bBindingCap = 2e3;
|
|
@@ -10203,133 +10420,93 @@ function expandBDuplicates(unit, review) {
|
|
|
10203
10420
|
};
|
|
10204
10421
|
}
|
|
10205
10422
|
//#endregion
|
|
10206
|
-
//#region packages/application/src/journey/b/
|
|
10207
|
-
|
|
10208
|
-
|
|
10209
|
-
|
|
10210
|
-
const
|
|
10211
|
-
|
|
10212
|
-
|
|
10213
|
-
|
|
10214
|
-
|
|
10215
|
-
|
|
10216
|
-
const
|
|
10217
|
-
|
|
10218
|
-
|
|
10423
|
+
//#region packages/application/src/journey/b/unit-budget.ts
|
|
10424
|
+
const wide = /[ᄀ-ᇿ⺀-가-豈-︰-﹏-\p{Extended_Pictographic}]/u;
|
|
10425
|
+
/** Matches the reader's estimate; rounds each line up and reserves field headers. */
|
|
10426
|
+
function bUnitBudget(fields) {
|
|
10427
|
+
const lines = [];
|
|
10428
|
+
let end = 0;
|
|
10429
|
+
for (const field of fields) {
|
|
10430
|
+
let start = end;
|
|
10431
|
+
const fieldStart = end;
|
|
10432
|
+
let thirds = 0;
|
|
10433
|
+
const take = () => {
|
|
10434
|
+
if (end > start) lines.push({
|
|
10435
|
+
start,
|
|
10436
|
+
end,
|
|
10437
|
+
tokens: (start === fieldStart ? 40 : 0) + Math.ceil(thirds / 3)
|
|
10438
|
+
});
|
|
10439
|
+
start = end;
|
|
10440
|
+
thirds = 0;
|
|
10441
|
+
};
|
|
10442
|
+
for (const scalar of field.text) {
|
|
10443
|
+
end++;
|
|
10444
|
+
thirds += wide.test(scalar) ? 3 : 1;
|
|
10445
|
+
if (scalar === "\n" || end - start === 64e3) take();
|
|
10446
|
+
}
|
|
10447
|
+
take();
|
|
10219
10448
|
}
|
|
10220
|
-
const
|
|
10449
|
+
const cores = [];
|
|
10450
|
+
let core = 0;
|
|
10451
|
+
let tokens = 40;
|
|
10452
|
+
const whole = lines.reduce((sum, line) => sum + line.tokens, 0) <= 8e3 && end <= 64e3;
|
|
10453
|
+
for (const line of lines) {
|
|
10454
|
+
const length = line.end - line.start;
|
|
10455
|
+
if (core && !whole && (tokens + line.tokens > 6e3 || core + length > 64e3)) {
|
|
10456
|
+
cores.push(core);
|
|
10457
|
+
core = 0;
|
|
10458
|
+
tokens = 40;
|
|
10459
|
+
}
|
|
10460
|
+
core += length;
|
|
10461
|
+
tokens += line.tokens;
|
|
10462
|
+
}
|
|
10463
|
+
if (core) cores.push(core);
|
|
10464
|
+
const totals = [0];
|
|
10465
|
+
for (const line of lines) totals.push((totals.at(-1) ?? 0) + line.tokens);
|
|
10466
|
+
const boundary = (point) => {
|
|
10221
10467
|
let low = 0;
|
|
10222
|
-
let high =
|
|
10468
|
+
let high = lines.length;
|
|
10223
10469
|
while (low < high) {
|
|
10224
|
-
const
|
|
10225
|
-
if ((
|
|
10226
|
-
else high =
|
|
10470
|
+
const mid = Math.floor((low + high) / 2);
|
|
10471
|
+
if ((lines[mid]?.start ?? Infinity) < point) low = mid + 1;
|
|
10472
|
+
else high = mid;
|
|
10227
10473
|
}
|
|
10228
10474
|
return low;
|
|
10229
10475
|
};
|
|
10476
|
+
function context(start, finish) {
|
|
10477
|
+
const left = boundary(start);
|
|
10478
|
+
const right = boundary(finish);
|
|
10479
|
+
const coreTokens = 40 + (totals[right] ?? 0) - (totals[left] ?? 0);
|
|
10480
|
+
const allowance = coreTokens > 8e3 ? 960 : Math.max(0, Math.min(960, Math.floor((8e3 - coreTokens) / 2) - 40));
|
|
10481
|
+
let before = start;
|
|
10482
|
+
let after = finish;
|
|
10483
|
+
let remaining = allowance;
|
|
10484
|
+
for (let i = left - 1; i >= 0; i--) {
|
|
10485
|
+
const line = lines[i];
|
|
10486
|
+
if (!line || line.tokens > remaining) break;
|
|
10487
|
+
before = line.start;
|
|
10488
|
+
remaining -= line.tokens;
|
|
10489
|
+
}
|
|
10490
|
+
remaining = allowance;
|
|
10491
|
+
for (let i = right; i < lines.length; i++) {
|
|
10492
|
+
const line = lines[i];
|
|
10493
|
+
if (!line || line.tokens > remaining) break;
|
|
10494
|
+
after = line.end;
|
|
10495
|
+
remaining -= line.tokens;
|
|
10496
|
+
}
|
|
10497
|
+
if (before === start && start > 0) before = Math.max(lines[left - 1]?.start ?? 0, start - allowance);
|
|
10498
|
+
if (after === finish && finish < end) after = Math.min(lines[right]?.end ?? end, finish + allowance);
|
|
10499
|
+
return {
|
|
10500
|
+
before,
|
|
10501
|
+
after
|
|
10502
|
+
};
|
|
10503
|
+
}
|
|
10230
10504
|
return {
|
|
10231
|
-
|
|
10232
|
-
|
|
10233
|
-
return {
|
|
10234
|
-
covers: Boolean(part && part.start <= query.start && part.end >= query.end),
|
|
10235
|
-
overlaps: Boolean(part && part.start < query.end)
|
|
10236
|
-
};
|
|
10237
|
-
},
|
|
10238
|
-
uncovered(query) {
|
|
10239
|
-
const result = [];
|
|
10240
|
-
let cursor = query.start;
|
|
10241
|
-
for (let index = firstOverlap(cursor); index < ranges.length; index += 1) {
|
|
10242
|
-
const part = ranges[index];
|
|
10243
|
-
if (!part || part.start >= query.end) break;
|
|
10244
|
-
if (cursor < part.start) result.push({
|
|
10245
|
-
start: cursor,
|
|
10246
|
-
end: part.start
|
|
10247
|
-
});
|
|
10248
|
-
cursor = Math.max(cursor, part.end);
|
|
10249
|
-
if (cursor >= query.end) break;
|
|
10250
|
-
}
|
|
10251
|
-
if (cursor < query.end) result.push({
|
|
10252
|
-
start: cursor,
|
|
10253
|
-
end: query.end
|
|
10254
|
-
});
|
|
10255
|
-
return result;
|
|
10256
|
-
}
|
|
10505
|
+
cores,
|
|
10506
|
+
context
|
|
10257
10507
|
};
|
|
10258
10508
|
}
|
|
10259
10509
|
//#endregion
|
|
10260
|
-
//#region packages/application/src/journey/b/literals.ts
|
|
10261
|
-
function bLiteralAdmitted(value) {
|
|
10262
|
-
return admitGitName(value, 1)?.value === value;
|
|
10263
|
-
}
|
|
10264
|
-
function bLiterals(evidence) {
|
|
10265
|
-
const value = evidence.exactQuote.normalize("NFC");
|
|
10266
|
-
if (bLiteralAdmitted(value)) return [{
|
|
10267
|
-
...evidence,
|
|
10268
|
-
term: value
|
|
10269
|
-
}];
|
|
10270
|
-
return literalPieces(evidence.exactQuote).map((part) => ({
|
|
10271
|
-
...evidence,
|
|
10272
|
-
start: evidence.start + part.start,
|
|
10273
|
-
end: evidence.start + part.end,
|
|
10274
|
-
utf16Start: evidence.utf16Start + part.utf16Start,
|
|
10275
|
-
utf16End: evidence.utf16Start + part.utf16End,
|
|
10276
|
-
exactQuote: part.exactQuote,
|
|
10277
|
-
term: part.term
|
|
10278
|
-
}));
|
|
10279
|
-
}
|
|
10280
|
-
/** The same admitted NFC terms for hidden text that is not one B evidence anchor. */
|
|
10281
|
-
function bLiteralTerms(text) {
|
|
10282
|
-
const value = text.normalize("NFC");
|
|
10283
|
-
return bLiteralAdmitted(value) ? [value] : literalPieces(text).map((part) => part.term);
|
|
10284
|
-
}
|
|
10285
|
-
/** Bounded line pieces of a nonrepresentable quote, in quote-relative coordinates. */
|
|
10286
|
-
function literalPieces(quote) {
|
|
10287
|
-
const chars = Array.from(quote);
|
|
10288
|
-
const index = createCodePointIndex(quote);
|
|
10289
|
-
const parts = [];
|
|
10290
|
-
let cursor = 0;
|
|
10291
|
-
while (cursor < chars.length) {
|
|
10292
|
-
while (cursor < chars.length && /\s/u.test(chars[cursor] ?? "")) cursor += 1;
|
|
10293
|
-
if (cursor === chars.length) break;
|
|
10294
|
-
const newline = chars.indexOf("\n", cursor);
|
|
10295
|
-
const lineEnd = newline < 0 ? chars.length : newline;
|
|
10296
|
-
let end = Math.min(lineEnd, cursor + 256);
|
|
10297
|
-
if (end < lineEnd) {
|
|
10298
|
-
let soft = end;
|
|
10299
|
-
while (soft > cursor + 12 && !/\s/u.test(chars[soft - 1] ?? "")) soft -= 1;
|
|
10300
|
-
if (soft > cursor + 12) end = soft;
|
|
10301
|
-
}
|
|
10302
|
-
while (end > cursor && /\s/u.test(chars[end - 1] ?? "")) end -= 1;
|
|
10303
|
-
if (end <= cursor) {
|
|
10304
|
-
cursor += 1;
|
|
10305
|
-
continue;
|
|
10306
|
-
}
|
|
10307
|
-
const exactQuote = index.slice(cursor, end);
|
|
10308
|
-
const term = exactQuote.normalize("NFC");
|
|
10309
|
-
if (end - cursor >= 12 && bLiteralAdmitted(term)) parts.push({
|
|
10310
|
-
start: cursor,
|
|
10311
|
-
end,
|
|
10312
|
-
utf16Start: index.offset(cursor),
|
|
10313
|
-
utf16End: index.offset(end),
|
|
10314
|
-
exactQuote,
|
|
10315
|
-
term
|
|
10316
|
-
});
|
|
10317
|
-
cursor = end;
|
|
10318
|
-
}
|
|
10319
|
-
return parts;
|
|
10320
|
-
}
|
|
10321
|
-
function uncoveredBObligations(sensitive, literals) {
|
|
10322
|
-
if (sensitive.length === 0) return [];
|
|
10323
|
-
const fields = new Map([...Map.groupBy(literals, (part) => part.fieldId)].map(([fieldId, parts]) => [fieldId, indexBRanges(parts)]));
|
|
10324
|
-
return sensitive.flatMap((evidence) => (fields.get(evidence.fieldId)?.uncovered(evidence) ?? [{
|
|
10325
|
-
start: evidence.start,
|
|
10326
|
-
end: evidence.end
|
|
10327
|
-
}]).filter((range) => /\S/u.test(codePointSlice(evidence.exactQuote, range.start - evidence.start, range.end - evidence.start))).map((range) => ({
|
|
10328
|
-
fieldId: evidence.fieldId,
|
|
10329
|
-
...range
|
|
10330
|
-
})));
|
|
10331
|
-
}
|
|
10332
|
-
//#endregion
|
|
10333
10510
|
//#region packages/application/src/journey/b/units.ts
|
|
10334
10511
|
function validateBFields(fields) {
|
|
10335
10512
|
const ids = /* @__PURE__ */ new Set();
|
|
@@ -10400,8 +10577,9 @@ function createBAnalysisUnits(input) {
|
|
|
10400
10577
|
};
|
|
10401
10578
|
});
|
|
10402
10579
|
if (total === 0) return [];
|
|
10403
|
-
const
|
|
10404
|
-
const
|
|
10580
|
+
const budget = bUnitBudget(unique);
|
|
10581
|
+
const coreSize = total <= 4e4 ? 4e4 : 24e3;
|
|
10582
|
+
const cores = input.cores ?? (input.lineContext ? budget.cores : Array.from({ length: Math.ceil(total / coreSize) }, (_, ordinal) => Math.min(coreSize, total - ordinal * coreSize)));
|
|
10405
10583
|
if (cores.reduce((sum, core) => sum + core, 0) !== total) throw new ApplicationError("INCOMPLETE_REVIEW");
|
|
10406
10584
|
const totalUnits = cores.length;
|
|
10407
10585
|
const result = [];
|
|
@@ -10409,8 +10587,10 @@ function createBAnalysisUnits(input) {
|
|
|
10409
10587
|
for (const [ordinal, core] of cores.entries()) {
|
|
10410
10588
|
const start = end;
|
|
10411
10589
|
end += core;
|
|
10412
|
-
const before =
|
|
10413
|
-
|
|
10590
|
+
const { before, after } = input.lineContext ? budget.context(start, end) : {
|
|
10591
|
+
before: Math.max(0, start - 8e3),
|
|
10592
|
+
after: Math.min(total, end + 8e3)
|
|
10593
|
+
};
|
|
10414
10594
|
const parts = [
|
|
10415
10595
|
...totalUnits === 1 ? [] : fragments(positions, before, start, false),
|
|
10416
10596
|
...fragments(positions, start, end, true),
|
|
@@ -10566,25 +10746,6 @@ function bContextEvidence(unit, raw) {
|
|
|
10566
10746
|
].map(read).find((part) => !part.owned);
|
|
10567
10747
|
}
|
|
10568
10748
|
//#endregion
|
|
10569
|
-
//#region packages/application/src/journey/review/findings.ts
|
|
10570
|
-
const semanticFindingSchema = z.object({
|
|
10571
|
-
id: journeyIdSchema,
|
|
10572
|
-
chunkId: journeyIdSchema,
|
|
10573
|
-
start: z.number().int().nonnegative(),
|
|
10574
|
-
end: z.number().int().nonnegative(),
|
|
10575
|
-
spanHash: journeyDigestSchema,
|
|
10576
|
-
kind: journeyKindSchema,
|
|
10577
|
-
class: z.enum([
|
|
10578
|
-
"certain",
|
|
10579
|
-
"gray",
|
|
10580
|
-
"clear"
|
|
10581
|
-
]),
|
|
10582
|
-
label: z.string().trim().min(1).max(120),
|
|
10583
|
-
groupKey: z.string().trim().min(1).max(120).nullable(),
|
|
10584
|
-
condition: z.string().max(1e3),
|
|
10585
|
-
defaultHide: z.number().min(0).max(1)
|
|
10586
|
-
}).strict();
|
|
10587
|
-
//#endregion
|
|
10588
10749
|
//#region packages/application/src/journey/review/alignment.ts
|
|
10589
10750
|
const referenceSchema = z.object({
|
|
10590
10751
|
batchId: journeyIdSchema,
|
|
@@ -10904,43 +11065,82 @@ function matchesReadReceipts(batch, attemptId, receipts) {
|
|
|
10904
11065
|
}
|
|
10905
11066
|
//#endregion
|
|
10906
11067
|
//#region packages/application/src/journey/terms/locate.ts
|
|
10907
|
-
/**
|
|
10908
|
-
|
|
10909
|
-
|
|
11068
|
+
/**
|
|
11069
|
+
* Issue #140: per batch and field, contiguous core and context chunks in offset order, never
|
|
11070
|
+
* joined across fields, field revisions or gaps. A core boundary maps to the NFC length of the
|
|
11071
|
+
* text before it.
|
|
11072
|
+
*/
|
|
11073
|
+
function* termSearchRuns(batches) {
|
|
10910
11074
|
for (const batch of batches) {
|
|
10911
|
-
const fields = Map.groupBy(batch.chunks
|
|
10912
|
-
for (const
|
|
10913
|
-
let
|
|
10914
|
-
|
|
10915
|
-
|
|
10916
|
-
|
|
10917
|
-
|
|
10918
|
-
|
|
10919
|
-
|
|
10920
|
-
|
|
11075
|
+
const fields = Map.groupBy(batch.chunks, (chunk) => JSON.stringify([chunk.fieldId, chunk.fieldHash]));
|
|
11076
|
+
for (const group of fields.values()) {
|
|
11077
|
+
let run = [];
|
|
11078
|
+
const runs = [run];
|
|
11079
|
+
for (const chunk of group.toSorted((a, b) => a.offset - b.offset)) {
|
|
11080
|
+
const last = run.at(-1);
|
|
11081
|
+
if (last && last.offset + last.text.length !== chunk.offset) runs.push(run = []);
|
|
11082
|
+
run.push(chunk);
|
|
11083
|
+
}
|
|
11084
|
+
for (const chunks of runs) {
|
|
11085
|
+
if (!chunks.some((chunk) => chunk.core)) continue;
|
|
11086
|
+
const raw = chunks.map((chunk) => chunk.text).join("");
|
|
11087
|
+
const text = raw.normalize("NFC");
|
|
11088
|
+
const at = (end) => Math.min(text.length, raw.slice(0, end).normalize("NFC").length);
|
|
11089
|
+
const cores = [];
|
|
11090
|
+
let offset = 0;
|
|
11091
|
+
for (const chunk of chunks) {
|
|
11092
|
+
const start = offset;
|
|
11093
|
+
offset += chunk.text.length;
|
|
11094
|
+
if (!chunk.core) continue;
|
|
11095
|
+
const last = cores.at(-1);
|
|
11096
|
+
if (last && last[1] === start) last[1] = offset;
|
|
11097
|
+
else cores.push([start, offset]);
|
|
10921
11098
|
}
|
|
10922
|
-
|
|
10923
|
-
|
|
11099
|
+
yield {
|
|
11100
|
+
batch,
|
|
11101
|
+
chunks,
|
|
11102
|
+
text,
|
|
11103
|
+
cores: cores.map(([start, end]) => [at(start), at(end)])
|
|
11104
|
+
};
|
|
10924
11105
|
}
|
|
10925
|
-
if (text) texts.push({
|
|
10926
|
-
workId: batch.workId,
|
|
10927
|
-
text: text.normalize("NFC")
|
|
10928
|
-
});
|
|
10929
11106
|
}
|
|
10930
11107
|
}
|
|
10931
|
-
return texts;
|
|
10932
11108
|
}
|
|
10933
|
-
|
|
10934
|
-
|
|
10935
|
-
|
|
10936
|
-
|
|
11109
|
+
/**
|
|
11110
|
+
* Occurrences of `value` in a run: `owned` counts non-overlapping occurrences that start in a
|
|
11111
|
+
* core range; `first` is the first occurrence overlapping a core range, or -1. An occurrence that
|
|
11112
|
+
* starts outside the core is skipped by one position only, so it never hides an owned one.
|
|
11113
|
+
*/
|
|
11114
|
+
function runOccurrences(run, value) {
|
|
11115
|
+
let owned = 0, first = -1;
|
|
11116
|
+
if (!value) return {
|
|
11117
|
+
owned,
|
|
11118
|
+
first
|
|
11119
|
+
};
|
|
11120
|
+
for (let at = run.text.indexOf(value); at >= 0;) {
|
|
11121
|
+
const end = at + value.length;
|
|
11122
|
+
if (run.cores.some(([start, stop]) => at >= start && at < stop)) {
|
|
11123
|
+
owned++;
|
|
11124
|
+
if (first < 0) first = at;
|
|
11125
|
+
at = run.text.indexOf(value, end);
|
|
11126
|
+
continue;
|
|
11127
|
+
}
|
|
11128
|
+
if (first < 0 && run.cores.some(([start, stop]) => at < stop && end > start)) first = at;
|
|
11129
|
+
at = run.text.indexOf(value, at + 1);
|
|
11130
|
+
}
|
|
11131
|
+
return {
|
|
11132
|
+
owned,
|
|
11133
|
+
first
|
|
11134
|
+
};
|
|
10937
11135
|
}
|
|
10938
11136
|
/**
|
|
10939
|
-
* ADR 0086: a value is kept only if it occurs verbatim (NFC,
|
|
10940
|
-
*
|
|
11137
|
+
* ADR 0086, refined by issue #140: a value is kept only if it occurs verbatim (NFC,
|
|
11138
|
+
* case-sensitive) in a pack field's contiguous core and context text, overlapping a core chunk;
|
|
11139
|
+
* only occurrences that start in a core chunk are counted. Its complete admitted NFC value
|
|
11140
|
+
* becomes one dictionary entry (ADR 0088).
|
|
10941
11141
|
*/
|
|
10942
11142
|
function locateTerms(batches, terms) {
|
|
10943
|
-
const
|
|
11143
|
+
const runs = [...termSearchRuns(batches)];
|
|
10944
11144
|
const located = /* @__PURE__ */ new Map();
|
|
10945
11145
|
const unlocatedIndices = [];
|
|
10946
11146
|
let kept = 0, unlocated = 0;
|
|
@@ -10953,20 +11153,25 @@ function locateTerms(batches, terms) {
|
|
|
10953
11153
|
}];
|
|
10954
11154
|
}));
|
|
10955
11155
|
for (const { type, value, index } of unique.values()) {
|
|
10956
|
-
|
|
11156
|
+
let count = 0;
|
|
11157
|
+
let workId;
|
|
11158
|
+
if (!value.includes("█") && admitCustomTerm(value)?.value === value) for (const run of runs) {
|
|
11159
|
+
const { owned, first } = runOccurrences(run, value);
|
|
11160
|
+
if (first < 0) continue;
|
|
11161
|
+
count += owned;
|
|
11162
|
+
workId ??= run.batch.workId;
|
|
11163
|
+
}
|
|
11164
|
+
if (workId === void 0) {
|
|
10957
11165
|
unlocated++;
|
|
10958
11166
|
unlocatedIndices.push(index);
|
|
10959
11167
|
continue;
|
|
10960
11168
|
}
|
|
10961
11169
|
kept++;
|
|
10962
|
-
const holders = texts.filter((item) => item.text.includes(value));
|
|
10963
|
-
const first = holders[0];
|
|
10964
|
-
if (!first) continue;
|
|
10965
11170
|
located.set(JSON.stringify([type, value]), {
|
|
10966
11171
|
type,
|
|
10967
11172
|
value,
|
|
10968
|
-
count
|
|
10969
|
-
workId
|
|
11173
|
+
count,
|
|
11174
|
+
workId
|
|
10970
11175
|
});
|
|
10971
11176
|
}
|
|
10972
11177
|
return {
|
|
@@ -10977,4 +11182,4 @@ function locateTerms(batches, terms) {
|
|
|
10977
11182
|
};
|
|
10978
11183
|
}
|
|
10979
11184
|
//#endregion
|
|
10980
|
-
export {
|
|
11185
|
+
export { createCodePointIndex as $, retainedMainTextNodes as $n, ownerProfileSchema as $t, bLegacyBindings as A, bindInspection as An, decisionCardInputSchema as At, bIssue as B, sessionNonce as Bn, reviewTermsResultSchema as Bt, validateBReview as C, processNativeRecord as Cn, processingSite as Cr, hideConfirmSchema as Ct, bBindingCap as D, createSentenceContext as Dn, cardAnswerActionSchema as Dt, validateBUnit as E, reviewRoles as En, journeyConfigurationSchema as Et, bLiterals as F, walkNativeFields as Fn, privacyTermSchema as Ft, bReviewSubmissionSchema as G, nativeParserVersion as Gn, termTypes as Gt, unownedBObligations as H, parseNativeRecord as Hn, termOverrideValueSchema as Ht, uncoveredBObligations as I, createStaticProcessor as In, emptyReviewCorrectionResultSchema as It, bAnchorKey as J, nativeField as Jn, sessionPeriodSchema as Jt, bSessionDecisionSchema as K, redactionImplementationVersion as Kn, deselectOutsidePeriod as Kt, indexBRanges as L, staticDefaults as Ln, emptyReviewCorrectionSchema as Lt, semanticFindingSchema as M, inspectionSemanticVersions as Mn, packageConfirmActionSchema as Mt, bLiteralAdmitted as N, createDetectionSummary as Nn, privacyResolveSchema as Nt, bDuplicateMirror as O, renderNative as On, cardsConfirmActionSchema as Ot, bLiteralTerms as P, gapReasons as Pn, privacyTermKey as Pt, codePointSlice as Q, frameRecords as Qn, mergeOwnerProfile as Qt, bAdoptedObligations as R, staticOptions as Rn, journeyTermSchema as Rt, validateBClassification as S, withMandatoryCustomTerms as Sn, isProcessingCode as Sr, journeyWorkSuggestionSchema as St, validateBFields as T, mainReviewRole as Tn, hidePlanResourceSchema as Tt, bRepresentationSchema as U, cleanupImplementationVersion as Un, termTypeInfo as Ut, bOverlaps as V, projectNativeRecord as Vn, termAssessmentSchema as Vt, bRetainedGroupSchema as W, entityDictionaryVersion as Wn, termTypeSchema as Wt, bDigest as X, nativeText as Xn, journeyProfileAddressActionSchema as Xt, bEvidenceReader as Y, nativeItems as Yn, emptyJourneyProfile as Yt, codePointLength as Z, transformRecords as Zn, journeyProfileLinksActionSchema as Zt, reviewAlignmentInputSchema as _, inventorySchema as _n, scalarBefore as _r, reviewInterruptionSchema as _t, reviewReadPages as a, ApplicationError as an, defaultLimits as ar, bMethod as at, validateReviewAlignment as b, workspaceSchema as bn, declaredVersion as br, delegatedDecisionSchema as bt, reviewBatchSchema as c, safeField as cn, detectStatic as cr, journeyChoiceSchema as ct, reviewSubmitSchema as d, reviewFamilies as dn, jsonSpans as dr, journeyIdSchema as dt, passportAddressSchema as en, validateProfile as er, subtractBRanges as et, textDigest as f, sourceGraph as fn, agentContextLocation as fr, journeyKindSchema as ft, reviewAlignmentAuditSchema as g, fileIdentitySchema as gn, scalarAfter as gr, nativeJourneySchema as gt, reviewAlignmentAudit as h, sourceSnapshotId as hn, admitGitName as hr, journeyWorkTypeSchema as ht, matchesReadReceipts as i, classificationTitleMaskSchema as in, copyData as ir, bIdSchema as it, bUnitFragments as j, currentDetectorVersion as jn, emptyJourneyPrivacy as jt, bDuplicateShift as k, createSessionPreparation as kn, cardsSubmitSchema as kt, reviewChunkSchema as l, familyNeedsReview as ln, isStaticCategory as lr, journeyDigestSchema as lt, findingReferenceKey as m, observeSource as mn, admitCustomTerm as mr, journeyProjectTypeSchema as mt, runOccurrences as n, respondProfileLinks as nn, buildPlan as nr, bAnchorSchema as nt, compileBFindings as o, UnfinishedJourneyError as on, recordPointerLimits as or, consentedWithoutAccount as ot, validateReview as p, sourceKey as pn, createEntityMatcher as pr, journeyPreferenceScopeSchema as pt, bTermSchema as q, nativeBoolean as qn, filterInventoryByPeriod as qt, termSearchRuns as r, accountWorksInventorySchema as rn, validatePlan as rr, bCountSchema as rt, reviewBatchChunks as s, safeCode as sn, resolveLimits as sr, journeyAccessSchema as st, locateTerms as t, profileHasChoices as tn, orderProfile as tr, utf16Offset as tt, reviewDigest as u, familySelected as un, staticCategories as ur, journeyExceptionSchema as ut, reviewAlignmentSchema as v, sessionSchema as vn, defaultDetectionLimits as vr, journeyGuidanceSchema as vt, createBAnalysisUnits as w, projectNativeReviewInput as wn, siteFields as wr, hidePlanInputSchema as wt, bContextEvidence as x, nativeSourceIdentitySchema as xn, fail as xr, journeyDescribeSchema as xt, reviewFindingsDigest as y, sourcePartSchema as yn, ProcessingError as yr, journeyInstructionInputSchema as yt, bClassificationKey as z, createReplacementKey as zn, reviewTermsInputSchema as zt };
|