@gitroll/tacitt-cli 0.6.8 → 0.6.10
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 +1 -1
- package/dist/{agent-setup-YlFIJz-h.mjs → agent-setup-LPd8WEsN.mjs} +2 -2
- package/dist/agent-setup-worker.mjs +5 -5
- package/dist/cli.mjs +19 -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-Dj5Zs6UW.mjs → frame-ByT1xayJ.mjs} +1 -1
- package/dist/{heap-DsE74_-n.mjs → heap-CM298Yu0.mjs} +8 -6
- package/dist/inspection-worker.mjs +4 -4
- package/dist/{job-CeSf9UCC.mjs → job-BHIwElNF.mjs} +5 -5
- package/dist/{locate-BWkblijS.mjs → locate-Cwv6WH8n.mjs} +25 -2
- package/dist/{model-f_QnDyyb.mjs → model-zvn5GUJ9.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-CaBXQlpF.mjs → query-By41gaKm.mjs} +585 -250
- package/dist/{run-RA_8zZsL.mjs → run-ZQx7p4Rw.mjs} +4 -4
- package/dist/{src-p_uJNjV3.mjs → src-3jvMvSQn.mjs} +3 -3
- package/dist/{src-d7n58sbH.mjs → src-BqtdFVq7.mjs} +683 -341
- package/dist/{src-BBjnljUs.mjs → src-D_DfY--2.mjs} +4 -4
- package/dist/store-database-worker.mjs +1 -1
- package/dist/web/assets/index-B14e6_-z.js +174 -0
- package/dist/web/index.html +1 -1
- package/package.json +1 -1
- package/skills/tacitt/INDEX.md +6 -6
- package/skills/tacitt/SKILL.md +4 -4
- package/skills/tacitt/references/INDEX.md +3 -3
- package/skills/tacitt/references/classification.md +12 -2
- package/skills/tacitt/references/commands.md +60 -13
- package/skills/tacitt/references/journey.md +10 -2
- package/skills/tacitt/references/parallel-review.md +21 -0
- package/skills/tacitt/references/send.md +29 -8
- package/skills/tacitt/scripts/INDEX.md +39 -36
- package/skills/tacitt/scripts/journey-classification-validation.d.mts +13 -0
- package/skills/tacitt/scripts/journey-classification-validation.mjs +38 -0
- package/skills/tacitt/scripts/journey-scan-timing.d.mts +15 -0
- package/skills/tacitt/scripts/journey-scan-timing.mjs +153 -1
- package/skills/tacitt/scripts/journey-state.d.mts +6 -0
- package/skills/tacitt/scripts/journey-state.mjs +24 -1
- package/skills/tacitt/scripts/journey.d.mts +5 -0
- package/skills/tacitt/scripts/journey.mjs +48 -3
- package/skills/tacitt/scripts/privacy-validator.mjs +11 -1
- package/skills/tacitt/scripts/review.mjs +294 -38
- package/LICENSE +0 -11
- package/dist/web/assets/index-B6kJ6XXF.js +0 -174
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as bCountSchema, $n as detectStatic, A as bDuplicateMirror, B as bEvidenceReader, Bt as sessionPeriodSchema, C as validateBUnit, Cn as inspectionSemanticVersions, Ct as cardsSubmitSchema, D as uncoveredBObligations, Dn as createStaticProcessor, Dt as privacyResolveSchema, E as bLiterals, Et as packageConfirmActionSchema, Fn as entityDictionaryVersion, Ft as termTypeInfo, G as subtractBRanges, Gn as validateProfile, H as codePointLength, Ht as journeyProfileAddressActionSchema, I as bIssue, It as termTypeSchema, J as bRetainedGroupSchema, Jn as validatePlan, Jt as respondProfileLinks, Kn as orderProfile, L as bOverlaps, Lt as termTypes, M as bLegacyBindings, Mt as reviewTermsResultSchema, N as bUnitFragments, Nt as termAssessmentSchema, O as indexBRanges, On as staticDefaults, Ot as privacyTermKey, P as bAdoptedObligations, Pn as cleanupImplementationVersion, Pt as termOverrideValueSchema, Q as bAnchorSchema, Qt as safeCode, R as unownedBObligations, Rt as deselectOutsidePeriod, S as validateBFields, Sn as currentDetectorVersion, St as cardsConfirmActionSchema, T as bLiteralTerms, Tn as gapReasons, Tt as emptyJourneyPrivacy, U as codePointSlice, Ut as journeyProfileLinksActionSchema, V as bDigest, Vt as emptyJourneyProfile, W as createCodePointIndex, X as bSessionDecisionSchema, Xt as ApplicationError, Y as bReviewSubmissionSchema, Yn as copyData, Yt as classificationTitleMaskSchema, Z as bTermSchema, Zt as UnfinishedJourneyError, _ as semanticFindingSchema, _t as hideConfirmSchema, a as reviewChunkSchema, an as observeSource, at as journeyExceptionSchema, b as validateBReview, bt as journeyConfigurationSchema, c as textDigest, cn as inventorySchema, cr as scalarBefore, ct as journeyPreferenceScopeSchema, dt as nativeJourneySchema, en as familyNeedsReview, et as bIdSchema, f as reviewAlignmentAuditSchema, fn as nativeSourceIdentitySchema, ft as journeyGuidanceSchema, g as validateReviewAlignment, h as reviewFindingsDigest, ht as journeyDescribeSchema, i as reviewBatchSchema, in as sourceKey, ir as createEntityMatcher, it as journeyDigestSchema, jt as reviewTermsInputSchema, kn as staticOptions, l as validateReview, lr as defaultDetectionLimits, lt as journeyProjectTypeSchema, m as reviewAlignmentSchema, mt as delegatedDecisionSchema, n as compileBFindings, nn as reviewFamilies, nt as journeyAccessSchema, o as reviewDigest, on as sourceSnapshotId, ot as journeyIdSchema, p as reviewAlignmentInputSchema, pt as journeyInstructionInputSchema, q as bRepresentationSchema, r as reviewBatchChunks, rn as sourceGraph, rt as journeyChoiceSchema, s as reviewSubmitSchema, sn as fileIdentitySchema, sr as scalarAfter, st as journeyKindSchema, tn as familySelected, tr as staticCategories, tt as bMethod, u as findingReferenceKey, un as sourcePartSchema, ut as journeyWorkTypeSchema, vt as hidePlanInputSchema, w as bLiteralAdmitted, x as createBAnalysisUnits, xt as cardAnswerActionSchema, y as validateBClassification, yt as hidePlanResourceSchema, z as bAnchorKey } from "./locate-
|
|
1
|
+
import { $ as bCountSchema, $n as detectStatic, A as bDuplicateMirror, B as bEvidenceReader, Bt as sessionPeriodSchema, C as validateBUnit, Cn as inspectionSemanticVersions, Ct as cardsSubmitSchema, D as uncoveredBObligations, Dn as createStaticProcessor, Dt as privacyResolveSchema, E as bLiterals, Et as packageConfirmActionSchema, Fn as entityDictionaryVersion, Ft as termTypeInfo, G as subtractBRanges, Gn as validateProfile, H as codePointLength, Ht as journeyProfileAddressActionSchema, I as bIssue, It as termTypeSchema, J as bRetainedGroupSchema, Jn as validatePlan, Jt as respondProfileLinks, Kn as orderProfile, L as bOverlaps, Lt as termTypes, M as bLegacyBindings, Mt as reviewTermsResultSchema, N as bUnitFragments, Nt as termAssessmentSchema, O as indexBRanges, On as staticDefaults, Ot as privacyTermKey, P as bAdoptedObligations, Pn as cleanupImplementationVersion, Pt as termOverrideValueSchema, Q as bAnchorSchema, Qt as safeCode, R as unownedBObligations, Rt as deselectOutsidePeriod, S as validateBFields, Sn as currentDetectorVersion, St as cardsConfirmActionSchema, T as bLiteralTerms, Tn as gapReasons, Tt as emptyJourneyPrivacy, U as codePointSlice, Ut as journeyProfileLinksActionSchema, V as bDigest, Vt as emptyJourneyProfile, W as createCodePointIndex, X as bSessionDecisionSchema, Xt as ApplicationError, Y as bReviewSubmissionSchema, Yn as copyData, Yt as classificationTitleMaskSchema, Z as bTermSchema, Zt as UnfinishedJourneyError, _ as semanticFindingSchema, _t as hideConfirmSchema, a as reviewChunkSchema, an as observeSource, at as journeyExceptionSchema, b as validateBReview, bt as journeyConfigurationSchema, c as textDigest, cn as inventorySchema, cr as scalarBefore, ct as journeyPreferenceScopeSchema, dt as nativeJourneySchema, en as familyNeedsReview, et as bIdSchema, f as reviewAlignmentAuditSchema, fn as nativeSourceIdentitySchema, ft as journeyGuidanceSchema, g as validateReviewAlignment, h as reviewFindingsDigest, ht as journeyDescribeSchema, i as reviewBatchSchema, in as sourceKey, ir as createEntityMatcher, it as journeyDigestSchema, jt as reviewTermsInputSchema, kn as staticOptions, l as validateReview, lr as defaultDetectionLimits, lt as journeyProjectTypeSchema, m as reviewAlignmentSchema, mt as delegatedDecisionSchema, n as compileBFindings, nn as reviewFamilies, nt as journeyAccessSchema, o as reviewDigest, on as sourceSnapshotId, ot as journeyIdSchema, p as reviewAlignmentInputSchema, pt as journeyInstructionInputSchema, q as bRepresentationSchema, r as reviewBatchChunks, rn as sourceGraph, rt as journeyChoiceSchema, s as reviewSubmitSchema, sn as fileIdentitySchema, sr as scalarAfter, st as journeyKindSchema, tn as familySelected, tr as staticCategories, tt as bMethod, u as findingReferenceKey, un as sourcePartSchema, ut as journeyWorkTypeSchema, vt as hidePlanInputSchema, w as bLiteralAdmitted, x as createBAnalysisUnits, xt as cardAnswerActionSchema, y as validateBClassification, yt as hidePlanResourceSchema, z as bAnchorKey } from "./locate-Cwv6WH8n.mjs";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { createHash, createHmac, createSecretKey, randomUUID } from "node:crypto";
|
|
4
4
|
import { setTimeout as setTimeout$1 } from "node:timers/promises";
|
|
@@ -14,6 +14,13 @@ const processingPlanSchema = z.unknown().transform((value, context) => {
|
|
|
14
14
|
return z.NEVER;
|
|
15
15
|
}
|
|
16
16
|
});
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region packages/application/src/processing/settings/data.ts
|
|
19
|
+
/**
|
|
20
|
+
* Sessions in one frozen configuration. Packaging admits at most 60,000 source parts per run
|
|
21
|
+
* (the artifact's entry bound) and every selected session has a part, so this matches it.
|
|
22
|
+
*/
|
|
23
|
+
const maximumConfigurationSessions = 6e4;
|
|
17
24
|
var SettingsError = class extends Error {
|
|
18
25
|
code;
|
|
19
26
|
field;
|
|
@@ -1192,152 +1199,6 @@ function requireSelecting(run) {
|
|
|
1192
1199
|
if (run.phase !== "selecting") throw new ApplicationError("INVALID_TRANSITION");
|
|
1193
1200
|
}
|
|
1194
1201
|
//#endregion
|
|
1195
|
-
//#region packages/application/src/journey/preview.ts
|
|
1196
|
-
const journeyRenderSchema = z.object({
|
|
1197
|
-
journeyId: journeyIdSchema,
|
|
1198
|
-
workId: journeyIdSchema
|
|
1199
|
-
}).strict();
|
|
1200
|
-
/** One Work, or several in one call where each Work renders or fails on its own. */
|
|
1201
|
-
const journeyRenderInputSchema = z.union([journeyRenderSchema, z.object({
|
|
1202
|
-
journeyId: journeyIdSchema,
|
|
1203
|
-
workIds: z.array(journeyIdSchema).min(1).max(256)
|
|
1204
|
-
}).strict()]);
|
|
1205
|
-
const journeyPreviewSchema = journeyRenderSchema.extend({ cursor: z.object({
|
|
1206
|
-
sha256: journeyDigestSchema,
|
|
1207
|
-
after: z.number().int().min(-1)
|
|
1208
|
-
}).strict().optional() }).strict();
|
|
1209
|
-
z.object({
|
|
1210
|
-
workId: journeyIdSchema,
|
|
1211
|
-
revision: z.number().int().nonnegative(),
|
|
1212
|
-
sha256: journeyDigestSchema,
|
|
1213
|
-
title: z.string(),
|
|
1214
|
-
rows: z.array(z.object({
|
|
1215
|
-
ordinal: z.number().int().nonnegative(),
|
|
1216
|
-
sessionId: z.string(),
|
|
1217
|
-
role: z.enum(["user", "assistant"]),
|
|
1218
|
-
text: z.string()
|
|
1219
|
-
}).strict()),
|
|
1220
|
-
cursor: z.object({
|
|
1221
|
-
sha256: journeyDigestSchema,
|
|
1222
|
-
after: z.number().int().min(-1)
|
|
1223
|
-
}).strict().nullable()
|
|
1224
|
-
}).strict();
|
|
1225
|
-
//#endregion
|
|
1226
|
-
//#region packages/application/src/journey/privacy/findings.ts
|
|
1227
|
-
/** UTF-16 source coordinates; contexts are local private evidence, never journey state. */
|
|
1228
|
-
const journeyFindingsSchema = journeyPreviewSchema;
|
|
1229
|
-
const journeyFindingSchema = z.object({
|
|
1230
|
-
ordinal: z.number().int().nonnegative(),
|
|
1231
|
-
termKey: z.string(),
|
|
1232
|
-
value: z.string(),
|
|
1233
|
-
type: termTypeSchema,
|
|
1234
|
-
disposition: z.enum(["hidden", "pending"]),
|
|
1235
|
-
reason: z.string(),
|
|
1236
|
-
entryPath: z.string(),
|
|
1237
|
-
basis: z.enum([
|
|
1238
|
-
"static-original",
|
|
1239
|
-
"static-base",
|
|
1240
|
-
"classification-metadata",
|
|
1241
|
-
"scan-source"
|
|
1242
|
-
]),
|
|
1243
|
-
source: z.discriminatedUnion("kind", [
|
|
1244
|
-
z.object({
|
|
1245
|
-
kind: z.literal("session"),
|
|
1246
|
-
sessionId: z.string(),
|
|
1247
|
-
sourcePartId: z.string().nullable(),
|
|
1248
|
-
recordIndex: z.number().int().nonnegative(),
|
|
1249
|
-
pointer: z.string()
|
|
1250
|
-
}).strict(),
|
|
1251
|
-
z.object({
|
|
1252
|
-
kind: z.literal("metadata"),
|
|
1253
|
-
field: z.string()
|
|
1254
|
-
}).strict(),
|
|
1255
|
-
z.object({
|
|
1256
|
-
kind: z.literal("setup"),
|
|
1257
|
-
pointer: z.string()
|
|
1258
|
-
}).strict()
|
|
1259
|
-
]),
|
|
1260
|
-
start: z.number().int().nonnegative(),
|
|
1261
|
-
end: z.number().int().nonnegative(),
|
|
1262
|
-
context: z.object({
|
|
1263
|
-
text: z.string(),
|
|
1264
|
-
start: z.number().int().nonnegative(),
|
|
1265
|
-
matchStart: z.number().int().nonnegative(),
|
|
1266
|
-
matchEnd: z.number().int().nonnegative()
|
|
1267
|
-
}).strict()
|
|
1268
|
-
}).strict();
|
|
1269
|
-
z.object({
|
|
1270
|
-
workId: z.uuid(),
|
|
1271
|
-
countScope: z.literal("source-evidence"),
|
|
1272
|
-
revision: z.number().int().nonnegative(),
|
|
1273
|
-
sha256: z.string(),
|
|
1274
|
-
rows: z.array(journeyFindingSchema).max(32),
|
|
1275
|
-
cursor: journeyPreviewSchema.shape.cursor.unwrap().nullable()
|
|
1276
|
-
}).strict();
|
|
1277
|
-
const journeyFindingImpactSchema = z.object({
|
|
1278
|
-
journeyId: z.uuid(),
|
|
1279
|
-
termKeys: z.array(z.string()).min(1).max(2e4),
|
|
1280
|
-
cursor: journeyPreviewSchema.shape.cursor
|
|
1281
|
-
}).strict();
|
|
1282
|
-
//#endregion
|
|
1283
|
-
//#region packages/application/src/journey/privacy/record.ts
|
|
1284
|
-
/** Merge independently reviewed occurrences into one journey-wide decision. */
|
|
1285
|
-
function mergePrivacyTerms(state, incoming) {
|
|
1286
|
-
const terms = new Map(state.privacy.terms.map((term) => [privacyTermKey(term), term]));
|
|
1287
|
-
const overrides = /* @__PURE__ */ new Map();
|
|
1288
|
-
for (const item of state.valueOverrides ?? []) {
|
|
1289
|
-
const value = item.value.normalize("NFC");
|
|
1290
|
-
if (!overrides.has(value)) overrides.set(value, item);
|
|
1291
|
-
}
|
|
1292
|
-
for (const term of incoming) {
|
|
1293
|
-
const key = privacyTermKey(term), prior = terms.get(key);
|
|
1294
|
-
const override = overrides.get(term.value.normalize("NFC"));
|
|
1295
|
-
const preference = state.groups.find((group) => group.key === `type:${term.type}` && group.origin === "preference");
|
|
1296
|
-
const disposition = !termTypeInfo[term.type].asked ? "hidden" : override ? override.choice === "hide" ? "hidden" : "keep" : preference?.choice ? preference.choice === "hide" ? "hidden" : "keep" : prior?.disposition === "hidden" || term.disposition === "hidden" ? "hidden" : prior && prior.disposition !== term.disposition ? "pending" : term.disposition;
|
|
1297
|
-
const sources = [...new Map([...prior?.sources ?? [], ...term.sources].map((source) => [JSON.stringify(source.kind === "session" ? [
|
|
1298
|
-
source.workId,
|
|
1299
|
-
source.batchId,
|
|
1300
|
-
source.chunkId
|
|
1301
|
-
] : [source.workId, source.field]), source])).values()];
|
|
1302
|
-
terms.set(key, {
|
|
1303
|
-
...term,
|
|
1304
|
-
disposition,
|
|
1305
|
-
sources,
|
|
1306
|
-
reason: prior && prior.disposition !== term.disposition ? disposition === "pending" ? "Conflicting scan judgments require a contextual decision." : disposition === "hidden" ? "A Hidden judgment for this keyword takes precedence." : term.reason : term.reason
|
|
1307
|
-
});
|
|
1308
|
-
}
|
|
1309
|
-
const values = Map.groupBy([...terms.values()], (term) => term.value.normalize("NFC"));
|
|
1310
|
-
for (const same of values.values()) if (same.some((term) => !termTypeInfo[term.type].asked)) for (const term of same) terms.set(privacyTermKey(term), {
|
|
1311
|
-
...term,
|
|
1312
|
-
disposition: "hidden"
|
|
1313
|
-
});
|
|
1314
|
-
else if (overrides.has(same[0]?.value.normalize("NFC") ?? "")) {
|
|
1315
|
-
const override = overrides.get(same[0]?.value.normalize("NFC") ?? "");
|
|
1316
|
-
for (const term of same) terms.set(privacyTermKey(term), {
|
|
1317
|
-
...term,
|
|
1318
|
-
disposition: override?.choice === "hide" ? "hidden" : "keep"
|
|
1319
|
-
});
|
|
1320
|
-
} else if (same.some((term) => term.disposition === "hidden")) for (const term of same) terms.set(privacyTermKey(term), {
|
|
1321
|
-
...term,
|
|
1322
|
-
disposition: "hidden",
|
|
1323
|
-
reason: term.disposition === "hidden" ? term.reason : "A Hidden judgment for this NFC keyword takes precedence across term types."
|
|
1324
|
-
});
|
|
1325
|
-
else if (new Set(same.map((term) => term.disposition)).size > 1) for (const term of same) terms.set(privacyTermKey(term), {
|
|
1326
|
-
...term,
|
|
1327
|
-
disposition: "pending",
|
|
1328
|
-
reason: "Conflicting scan judgments require a contextual decision."
|
|
1329
|
-
});
|
|
1330
|
-
return {
|
|
1331
|
-
...state.privacy,
|
|
1332
|
-
terms: [...terms.values()],
|
|
1333
|
-
packageApproval: null
|
|
1334
|
-
};
|
|
1335
|
-
}
|
|
1336
|
-
/** A journey-wide literal can affect selected Works even when its reporting Work was Dropped. */
|
|
1337
|
-
function activePrivacyTerms(state) {
|
|
1338
|
-
return state.works.some((work) => work.access !== "drop" && work.rootSessionIds.length > 0) ? state.privacy.terms : [];
|
|
1339
|
-
}
|
|
1340
|
-
//#endregion
|
|
1341
1202
|
//#region packages/application/src/journey/placement/readiness.ts
|
|
1342
1203
|
function hasCompleteWorkDescription(work) {
|
|
1343
1204
|
return work.placement === "placed" && !!work.description.trim() && work.classificationRecommendation !== null;
|
|
@@ -1366,6 +1227,18 @@ function isSkippedWork(work) {
|
|
|
1366
1227
|
function isIncludedWork(work) {
|
|
1367
1228
|
return isSelectedWork(work) && !isSkippedWork(work);
|
|
1368
1229
|
}
|
|
1230
|
+
/**
|
|
1231
|
+
* ADR 0274: Public needs a recorded choice: the person's panel click or named conversation
|
|
1232
|
+
* answer (origin `explicit`), or, under ADR 0275, the account proof that every root was already
|
|
1233
|
+
* Public (origin and channel `account`). A Public Work stored before `accessChoice` existed is
|
|
1234
|
+
* still pending. Mirrored by `phaseOf` in the Skill's `journey-state.mjs` and by the panel's
|
|
1235
|
+
* `WorkAccess`.
|
|
1236
|
+
*/
|
|
1237
|
+
function hasPublicChoice(work) {
|
|
1238
|
+
if (work.access !== "public") return true;
|
|
1239
|
+
if (!work.accessConfirmed || !work.accessChoice) return false;
|
|
1240
|
+
return work.accessChoice.channel === "account" ? work.accessOrigin === "account" : work.accessOrigin === "explicit";
|
|
1241
|
+
}
|
|
1369
1242
|
function selectedWorks(state) {
|
|
1370
1243
|
return state.works.filter(isSelectedWork);
|
|
1371
1244
|
}
|
|
@@ -1612,6 +1485,26 @@ const sendItemSchema = z.object({
|
|
|
1612
1485
|
title: z.string(),
|
|
1613
1486
|
access
|
|
1614
1487
|
}).strict().optional(),
|
|
1488
|
+
/** Safe preflight facts; local requested-access conflicts have no account owner. */
|
|
1489
|
+
accessConflict: z.object({
|
|
1490
|
+
sessionKey: journeyDigestSchema,
|
|
1491
|
+
requestedAccess: access,
|
|
1492
|
+
accountWorkId: journeyIdSchema.nullable(),
|
|
1493
|
+
accountAccess: z.enum([
|
|
1494
|
+
"public",
|
|
1495
|
+
"private",
|
|
1496
|
+
"removed",
|
|
1497
|
+
"mixed"
|
|
1498
|
+
]).nullable(),
|
|
1499
|
+
rule: z.enum([
|
|
1500
|
+
"held-elsewhere",
|
|
1501
|
+
"destination-access",
|
|
1502
|
+
"requested-access",
|
|
1503
|
+
"content-access"
|
|
1504
|
+
])
|
|
1505
|
+
}).strict().optional(),
|
|
1506
|
+
/** Distinct conflicting session keys across all rules and account holders. */
|
|
1507
|
+
accessConflictSessionCount: count$13.positive().optional(),
|
|
1615
1508
|
/** Membership readback retained for visible conflict recovery. */
|
|
1616
1509
|
membershipConflict: z.object({
|
|
1617
1510
|
revision: count$13,
|
|
@@ -1754,6 +1647,64 @@ function hasCurrentStaticReview(state, work) {
|
|
|
1754
1647
|
return work.staticReview !== void 0 && work.staticReview.snapshotId === state.snapshotId && work.staticReview.inputRevision === work.inputRevision;
|
|
1755
1648
|
}
|
|
1756
1649
|
//#endregion
|
|
1650
|
+
//#region packages/application/src/journey/privacy/record.ts
|
|
1651
|
+
/** Merge independently reviewed occurrences into one journey-wide decision. */
|
|
1652
|
+
function mergePrivacyTerms(state, incoming) {
|
|
1653
|
+
const terms = new Map(state.privacy.terms.map((term) => [privacyTermKey(term), term]));
|
|
1654
|
+
const overrides = /* @__PURE__ */ new Map();
|
|
1655
|
+
for (const item of state.valueOverrides ?? []) {
|
|
1656
|
+
const value = item.value.normalize("NFC");
|
|
1657
|
+
if (!overrides.has(value)) overrides.set(value, item);
|
|
1658
|
+
}
|
|
1659
|
+
for (const term of incoming) {
|
|
1660
|
+
const key = privacyTermKey(term), prior = terms.get(key);
|
|
1661
|
+
const override = overrides.get(term.value.normalize("NFC"));
|
|
1662
|
+
const preference = state.groups.find((group) => group.key === `type:${term.type}` && group.origin === "preference");
|
|
1663
|
+
const disposition = !termTypeInfo[term.type].asked ? "hidden" : override ? override.choice === "hide" ? "hidden" : "keep" : preference?.choice ? preference.choice === "hide" ? "hidden" : "keep" : prior?.disposition === "hidden" || term.disposition === "hidden" ? "hidden" : prior && prior.disposition !== term.disposition ? "pending" : term.disposition;
|
|
1664
|
+
const sources = [...new Map([...prior?.sources ?? [], ...term.sources].map((source) => [JSON.stringify(source.kind === "session" ? [
|
|
1665
|
+
source.workId,
|
|
1666
|
+
source.batchId,
|
|
1667
|
+
source.chunkId
|
|
1668
|
+
] : [source.workId, source.field]), source])).values()];
|
|
1669
|
+
terms.set(key, {
|
|
1670
|
+
...term,
|
|
1671
|
+
disposition,
|
|
1672
|
+
sources,
|
|
1673
|
+
reason: prior && prior.disposition !== term.disposition ? disposition === "pending" ? "Conflicting scan judgments require a contextual decision." : disposition === "hidden" ? "A Hidden judgment for this keyword takes precedence." : term.reason : term.reason
|
|
1674
|
+
});
|
|
1675
|
+
}
|
|
1676
|
+
const values = Map.groupBy([...terms.values()], (term) => term.value.normalize("NFC"));
|
|
1677
|
+
for (const same of values.values()) if (same.some((term) => !termTypeInfo[term.type].asked)) for (const term of same) terms.set(privacyTermKey(term), {
|
|
1678
|
+
...term,
|
|
1679
|
+
disposition: "hidden"
|
|
1680
|
+
});
|
|
1681
|
+
else if (overrides.has(same[0]?.value.normalize("NFC") ?? "")) {
|
|
1682
|
+
const override = overrides.get(same[0]?.value.normalize("NFC") ?? "");
|
|
1683
|
+
for (const term of same) terms.set(privacyTermKey(term), {
|
|
1684
|
+
...term,
|
|
1685
|
+
disposition: override?.choice === "hide" ? "hidden" : "keep"
|
|
1686
|
+
});
|
|
1687
|
+
} else if (same.some((term) => term.disposition === "hidden")) for (const term of same) terms.set(privacyTermKey(term), {
|
|
1688
|
+
...term,
|
|
1689
|
+
disposition: "hidden",
|
|
1690
|
+
reason: term.disposition === "hidden" ? term.reason : "A Hidden judgment for this NFC keyword takes precedence across term types."
|
|
1691
|
+
});
|
|
1692
|
+
else if (new Set(same.map((term) => term.disposition)).size > 1) for (const term of same) terms.set(privacyTermKey(term), {
|
|
1693
|
+
...term,
|
|
1694
|
+
disposition: "pending",
|
|
1695
|
+
reason: "Conflicting scan judgments require a contextual decision."
|
|
1696
|
+
});
|
|
1697
|
+
return {
|
|
1698
|
+
...state.privacy,
|
|
1699
|
+
terms: [...terms.values()],
|
|
1700
|
+
packageApproval: null
|
|
1701
|
+
};
|
|
1702
|
+
}
|
|
1703
|
+
/** A journey-wide literal can affect selected Works even when its reporting Work was Dropped. */
|
|
1704
|
+
function activePrivacyTerms(state) {
|
|
1705
|
+
return state.works.some((work) => work.access !== "drop" && work.rootSessionIds.length > 0) ? state.privacy.terms : [];
|
|
1706
|
+
}
|
|
1707
|
+
//#endregion
|
|
1757
1708
|
//#region packages/application/src/journey/policy/commands.ts
|
|
1758
1709
|
const journeyFindingReferenceSchema = z.object({
|
|
1759
1710
|
batchId: journeyIdSchema,
|
|
@@ -1809,6 +1760,16 @@ const journeyPropagateActionSchema = z.object({
|
|
|
1809
1760
|
//#region packages/application/src/journey/scope/model.ts
|
|
1810
1761
|
const count$11 = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
|
|
1811
1762
|
const safeText = z.string().trim().min(1).max(240);
|
|
1763
|
+
/**
|
|
1764
|
+
* One Work's stored account access (ADR 0274 D3(b), refined by ADR 0275): `public-all` when
|
|
1765
|
+
* every root key is held Public, `public` when the held keys are Public and other roots are new.
|
|
1766
|
+
*/
|
|
1767
|
+
const accountWorkAccessSchema = z.enum([
|
|
1768
|
+
"private",
|
|
1769
|
+
"public",
|
|
1770
|
+
"public-all",
|
|
1771
|
+
"mixed"
|
|
1772
|
+
]);
|
|
1812
1773
|
const journeyScopeConfirmActionSchema = z.object({ kind: z.literal("scope-confirm") }).strict();
|
|
1813
1774
|
const journeyWorkTypeActionSchema = z.object({
|
|
1814
1775
|
kind: z.literal("work-type"),
|
|
@@ -1818,7 +1779,11 @@ const journeyWorkTypeActionSchema = z.object({
|
|
|
1818
1779
|
const journeyWorksAccessActionSchema = z.object({
|
|
1819
1780
|
kind: z.literal("works-access"),
|
|
1820
1781
|
workIds: z.array(journeyIdSchema).min(1).max(1e4),
|
|
1821
|
-
access: journeyAccessSchema
|
|
1782
|
+
access: journeyAccessSchema,
|
|
1783
|
+
accessChoice: z.object({
|
|
1784
|
+
channel: z.literal("conversation"),
|
|
1785
|
+
at: z.iso.datetime()
|
|
1786
|
+
}).strict().optional()
|
|
1822
1787
|
}).strict();
|
|
1823
1788
|
/** Static-only Work facts for proposing project types and scan scope; no source bodies. */
|
|
1824
1789
|
const journeyCatalogQuerySchema = z.object({
|
|
@@ -2018,7 +1983,11 @@ const journeyActionSchema = z.discriminatedUnion("kind", [
|
|
|
2018
1983
|
z.object({
|
|
2019
1984
|
kind: z.literal("work-access"),
|
|
2020
1985
|
workId: journeyIdSchema,
|
|
2021
|
-
access: journeyAccessSchema
|
|
1986
|
+
access: journeyAccessSchema,
|
|
1987
|
+
accessChoice: z.object({
|
|
1988
|
+
channel: z.literal("conversation"),
|
|
1989
|
+
at: z.iso.datetime()
|
|
1990
|
+
}).strict().optional()
|
|
2022
1991
|
}).strict(),
|
|
2023
1992
|
z.object({
|
|
2024
1993
|
kind: z.literal("work-title"),
|
|
@@ -2137,13 +2106,22 @@ function privacyDecisionDigest(state) {
|
|
|
2137
2106
|
function assertJourneyScanned(state) {
|
|
2138
2107
|
if (!state.consent || state.scope.status !== "confirmed" || !state.readingComplete || state.works.some((work) => isIncludedWork(work) && (!work.classificationMetadata || work.totalBatches === 0 && !hasCertifiedNoBatchReview(work, state.snapshotId) || work.completedBatches !== work.totalBatches || work.status === "blocked"))) throw new ApplicationError("SCOPE_NOT_READY");
|
|
2139
2108
|
}
|
|
2109
|
+
/** Legacy model, delegate or unrecorded confirmation is not the person's Public choice. */
|
|
2110
|
+
function assertPublicChoices(state) {
|
|
2111
|
+
if (state.works.some((work) => isIncludedWork(work) && !hasPublicChoice(work))) throw new ApplicationError("SCOPE_NOT_READY");
|
|
2112
|
+
}
|
|
2140
2113
|
/** Track B (ADR 0172): preview and packaging need every selected Work's static base. */
|
|
2141
2114
|
function assertJourneyStaticReady(state) {
|
|
2142
2115
|
if (state.works.some((work) => work.access !== "drop" && work.rootSessionIds.length > 0 && !isSkippedWork(work) && !hasCurrentStaticReview(state, work))) throw new ApplicationError("SCOPE_NOT_READY");
|
|
2143
2116
|
}
|
|
2144
|
-
/**
|
|
2145
|
-
|
|
2117
|
+
/**
|
|
2118
|
+
* Cards need only Track A, AI review and metadata; this final gate also needs Track B.
|
|
2119
|
+
* `publicChoices` defaults to `packaging`: the Send click checks it before packaging, and the
|
|
2120
|
+
* follow-up of an already uploaded Send skips it because nothing more goes out (ADR 0274).
|
|
2121
|
+
*/
|
|
2122
|
+
function assertJourneyPrivacyReady(state, packaging = false, { publicChoices = packaging } = {}) {
|
|
2146
2123
|
assertJourneyScanned(state);
|
|
2124
|
+
if (publicChoices) assertPublicChoices(state);
|
|
2147
2125
|
if (activePrivacyTerms(state).some((term) => term.disposition === "pending") || state.privacy.cards.length > 0 && (state.privacy.cards.some((card) => !card.answer) || state.privacy.confirmedAnswersRevision !== state.privacy.answersRevision)) throw new ApplicationError("CONFIRMATION_REQUIRED");
|
|
2148
2126
|
assertJourneyStaticReady(state);
|
|
2149
2127
|
if (packaging && state.privacy.packageApproval !== privacyDecisionDigest(state)) throw new ApplicationError("CONFIRMATION_REQUIRED");
|
|
@@ -2173,15 +2151,23 @@ function appendDecisionCards(state, input) {
|
|
|
2173
2151
|
const open = new Set(activePrivacyTerms(state).filter((term) => term.disposition === "pending").map(privacyTermKey).filter((key) => !coveredBefore.has(key)));
|
|
2174
2152
|
const extend = input.extend ?? [];
|
|
2175
2153
|
const covered = [...input.cards.flatMap((card) => card.termKeys), ...extend.flatMap((item) => item.termKeys)];
|
|
2176
|
-
if (!covered.length
|
|
2154
|
+
if (!covered.length) throw new ApplicationError("INVALID_SELECTION", "cards.append.empty");
|
|
2155
|
+
if (state.privacy.cards.length + input.cards.length > 20) throw new ApplicationError("INVALID_SELECTION", "cards.append.limit");
|
|
2156
|
+
if (new Set(input.cards.map((card) => card.id)).size !== input.cards.length) throw new ApplicationError("INVALID_SELECTION", "cards.append.duplicate-card");
|
|
2157
|
+
if (input.cards.some((card) => existing.has(card.id))) throw new ApplicationError("INVALID_SELECTION", "cards.append.existing-card");
|
|
2158
|
+
if (new Set(extend.map((item) => item.cardId)).size !== extend.length) throw new ApplicationError("INVALID_SELECTION", "cards.append.duplicate-extension");
|
|
2159
|
+
if (extend.some((item) => !existing.has(item.cardId))) throw new ApplicationError("INVALID_SELECTION", "cards.append.unknown-card");
|
|
2160
|
+
if (new Set(covered).size !== covered.length) throw new ApplicationError("INVALID_SELECTION", "cards.append.duplicate-term");
|
|
2161
|
+
if (covered.some((key) => !open.has(key))) throw new ApplicationError("INVALID_SELECTION", "cards.append.term-not-open");
|
|
2177
2162
|
const terms = new Map(state.privacy.terms.map((term) => [privacyTermKey(term), term]));
|
|
2178
2163
|
const ownValues = ownIdentityValues(state);
|
|
2179
2164
|
for (const extension of extend) {
|
|
2180
2165
|
const ownCard = !!state.privacy.cards.find((item) => item.id === extension.cardId)?.termKeys.some((key) => terms.get(key)?.type === "own-identity");
|
|
2181
|
-
|
|
2166
|
+
for (const key of extension.termKeys) {
|
|
2182
2167
|
const term = terms.get(key);
|
|
2183
|
-
|
|
2184
|
-
|
|
2168
|
+
if (term?.type === "own-identity" && !ownCard) throw new ApplicationError("INVALID_SELECTION", "cards.append.own-identity-card");
|
|
2169
|
+
if (term?.type === "people" && ownCard && !ownValues.has(identityValue(term.value))) throw new ApplicationError("INVALID_SELECTION", "cards.append.other-person");
|
|
2170
|
+
}
|
|
2185
2171
|
}
|
|
2186
2172
|
const additions = new Map(extend.map((item) => [item.cardId, item.termKeys]));
|
|
2187
2173
|
const inherited = new Map(extend.flatMap((item) => item.termKeys.map((key) => [key, item.cardId])));
|
|
@@ -2391,6 +2377,7 @@ function respondPrivacy(state, action, source) {
|
|
|
2391
2377
|
};
|
|
2392
2378
|
}
|
|
2393
2379
|
if (action.kind === "package-confirm") {
|
|
2380
|
+
assertPublicChoices(state);
|
|
2394
2381
|
assertJourneyPrivacyReady(state);
|
|
2395
2382
|
return {
|
|
2396
2383
|
...state,
|
|
@@ -2403,6 +2390,127 @@ function respondPrivacy(state, action, source) {
|
|
|
2403
2390
|
return null;
|
|
2404
2391
|
}
|
|
2405
2392
|
//#endregion
|
|
2393
|
+
//#region packages/application/src/journey/send/displayed-scope.ts
|
|
2394
|
+
function hash(value) {
|
|
2395
|
+
return createHash("sha256").update(JSON.stringify(value)).digest("hex");
|
|
2396
|
+
}
|
|
2397
|
+
/** Artifact-independent authorization: packaging progress cannot expand this scope. */
|
|
2398
|
+
function requestedScope(journey) {
|
|
2399
|
+
return hash({
|
|
2400
|
+
privacy: privacyDecisionDigest(journey),
|
|
2401
|
+
configurationId: journey.configurationId,
|
|
2402
|
+
confirmedHideRevision: journey.confirmedHideRevision ?? 0,
|
|
2403
|
+
consent: journey.consent,
|
|
2404
|
+
profile: journey.profile,
|
|
2405
|
+
works: journey.works.map((work) => ({
|
|
2406
|
+
id: work.id,
|
|
2407
|
+
inputRevision: work.inputRevision,
|
|
2408
|
+
access: work.access,
|
|
2409
|
+
accessConfirmed: work.accessConfirmed,
|
|
2410
|
+
included: isIncludedWork(work),
|
|
2411
|
+
placement: work.placement,
|
|
2412
|
+
suggestion: work.suggestion
|
|
2413
|
+
}))
|
|
2414
|
+
});
|
|
2415
|
+
}
|
|
2416
|
+
/** Host-issued review fence; clients echo it without hashing private decision data. */
|
|
2417
|
+
function displayedScopeDigest(journey) {
|
|
2418
|
+
return hash({
|
|
2419
|
+
scope: requestedScope(journey),
|
|
2420
|
+
phase: journey.phase === "review" ? "ready" : journey.phase,
|
|
2421
|
+
pendingHideId: journey.pendingHideId,
|
|
2422
|
+
abandonedAt: journey.abandonedAt
|
|
2423
|
+
});
|
|
2424
|
+
}
|
|
2425
|
+
//#endregion
|
|
2426
|
+
//#region packages/application/src/journey/preview.ts
|
|
2427
|
+
const journeyRenderSchema = z.object({
|
|
2428
|
+
journeyId: journeyIdSchema,
|
|
2429
|
+
workId: journeyIdSchema
|
|
2430
|
+
}).strict();
|
|
2431
|
+
/** One Work, or several in one call where each Work renders or fails on its own. */
|
|
2432
|
+
const journeyRenderInputSchema = z.union([journeyRenderSchema, z.object({
|
|
2433
|
+
journeyId: journeyIdSchema,
|
|
2434
|
+
workIds: z.array(journeyIdSchema).min(1).max(maximumConfigurationSessions)
|
|
2435
|
+
}).strict()]);
|
|
2436
|
+
const journeyPreviewSchema = journeyRenderSchema.extend({ cursor: z.object({
|
|
2437
|
+
sha256: journeyDigestSchema,
|
|
2438
|
+
after: z.number().int().min(-1)
|
|
2439
|
+
}).strict().optional() }).strict();
|
|
2440
|
+
z.object({
|
|
2441
|
+
workId: journeyIdSchema,
|
|
2442
|
+
revision: z.number().int().nonnegative(),
|
|
2443
|
+
sha256: journeyDigestSchema,
|
|
2444
|
+
title: z.string(),
|
|
2445
|
+
rows: z.array(z.object({
|
|
2446
|
+
ordinal: z.number().int().nonnegative(),
|
|
2447
|
+
sessionId: z.string(),
|
|
2448
|
+
role: z.enum(["user", "assistant"]),
|
|
2449
|
+
text: z.string()
|
|
2450
|
+
}).strict()),
|
|
2451
|
+
cursor: z.object({
|
|
2452
|
+
sha256: journeyDigestSchema,
|
|
2453
|
+
after: z.number().int().min(-1)
|
|
2454
|
+
}).strict().nullable()
|
|
2455
|
+
}).strict();
|
|
2456
|
+
//#endregion
|
|
2457
|
+
//#region packages/application/src/journey/privacy/findings.ts
|
|
2458
|
+
/** UTF-16 source coordinates; contexts are local private evidence, never journey state. */
|
|
2459
|
+
const journeyFindingsSchema = journeyPreviewSchema;
|
|
2460
|
+
const journeyFindingSchema = z.object({
|
|
2461
|
+
ordinal: z.number().int().nonnegative(),
|
|
2462
|
+
termKey: z.string(),
|
|
2463
|
+
value: z.string(),
|
|
2464
|
+
type: termTypeSchema,
|
|
2465
|
+
disposition: z.enum(["hidden", "pending"]),
|
|
2466
|
+
reason: z.string(),
|
|
2467
|
+
entryPath: z.string(),
|
|
2468
|
+
basis: z.enum([
|
|
2469
|
+
"static-original",
|
|
2470
|
+
"static-base",
|
|
2471
|
+
"classification-metadata",
|
|
2472
|
+
"scan-source"
|
|
2473
|
+
]),
|
|
2474
|
+
source: z.discriminatedUnion("kind", [
|
|
2475
|
+
z.object({
|
|
2476
|
+
kind: z.literal("session"),
|
|
2477
|
+
sessionId: z.string(),
|
|
2478
|
+
sourcePartId: z.string().nullable(),
|
|
2479
|
+
recordIndex: z.number().int().nonnegative(),
|
|
2480
|
+
pointer: z.string()
|
|
2481
|
+
}).strict(),
|
|
2482
|
+
z.object({
|
|
2483
|
+
kind: z.literal("metadata"),
|
|
2484
|
+
field: z.string()
|
|
2485
|
+
}).strict(),
|
|
2486
|
+
z.object({
|
|
2487
|
+
kind: z.literal("setup"),
|
|
2488
|
+
pointer: z.string()
|
|
2489
|
+
}).strict()
|
|
2490
|
+
]),
|
|
2491
|
+
start: z.number().int().nonnegative(),
|
|
2492
|
+
end: z.number().int().nonnegative(),
|
|
2493
|
+
context: z.object({
|
|
2494
|
+
text: z.string(),
|
|
2495
|
+
start: z.number().int().nonnegative(),
|
|
2496
|
+
matchStart: z.number().int().nonnegative(),
|
|
2497
|
+
matchEnd: z.number().int().nonnegative()
|
|
2498
|
+
}).strict()
|
|
2499
|
+
}).strict();
|
|
2500
|
+
z.object({
|
|
2501
|
+
workId: z.uuid(),
|
|
2502
|
+
countScope: z.literal("source-evidence"),
|
|
2503
|
+
revision: z.number().int().nonnegative(),
|
|
2504
|
+
sha256: z.string(),
|
|
2505
|
+
rows: z.array(journeyFindingSchema).max(32),
|
|
2506
|
+
cursor: journeyPreviewSchema.shape.cursor.unwrap().nullable()
|
|
2507
|
+
}).strict();
|
|
2508
|
+
const journeyFindingImpactSchema = z.object({
|
|
2509
|
+
journeyId: z.uuid(),
|
|
2510
|
+
termKeys: z.array(z.string()).min(1).max(2e4),
|
|
2511
|
+
cursor: journeyPreviewSchema.shape.cursor
|
|
2512
|
+
}).strict();
|
|
2513
|
+
//#endregion
|
|
2406
2514
|
//#region packages/application/src/journey/scope/classification.ts
|
|
2407
2515
|
const count$10 = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
|
|
2408
2516
|
const classificationCursorSchema = z.object({
|
|
@@ -4768,32 +4876,200 @@ function retireScanGeneration(state, workId) {
|
|
|
4768
4876
|
});
|
|
4769
4877
|
return {
|
|
4770
4878
|
...state,
|
|
4771
|
-
readingComplete: false,
|
|
4772
|
-
phase: state.phase === "paused" ? "paused" : "processing",
|
|
4879
|
+
readingComplete: false,
|
|
4880
|
+
phase: state.phase === "paused" ? "paused" : "processing",
|
|
4881
|
+
privacy: {
|
|
4882
|
+
...state.privacy,
|
|
4883
|
+
terms,
|
|
4884
|
+
cards: state.privacy.cards.filter((card) => card.termKeys.every((key) => !changedKeys.has(key))),
|
|
4885
|
+
confirmedAnswersRevision: null,
|
|
4886
|
+
packageApproval: null
|
|
4887
|
+
},
|
|
4888
|
+
works: state.works.map((work) => work.id === workId ? resetWorkScan(work) : work)
|
|
4889
|
+
};
|
|
4890
|
+
}
|
|
4891
|
+
/** The same Work with a new scan generation: it is read again from its first session. */
|
|
4892
|
+
function resetWorkScan(work) {
|
|
4893
|
+
const { emptyReview: _empty, excludedReview: _excluded, staticReview: _static, metadataReviewedDigest: _metadata, reviewReuseFrom: _reuse, renderFailure: _failure, ...retained } = work;
|
|
4894
|
+
return {
|
|
4895
|
+
...retained,
|
|
4896
|
+
revision: work.revision + 1,
|
|
4897
|
+
inputRevision: work.inputRevision + 1,
|
|
4898
|
+
status: "pending",
|
|
4899
|
+
suggestion: null,
|
|
4900
|
+
totalBatches: 0,
|
|
4901
|
+
completedBatches: 0,
|
|
4902
|
+
groupIds: [],
|
|
4903
|
+
blockedCodes: [],
|
|
4904
|
+
artifact: null
|
|
4905
|
+
};
|
|
4906
|
+
}
|
|
4907
|
+
//#endregion
|
|
4908
|
+
//#region packages/application/src/journey/scope/respond.ts
|
|
4909
|
+
/**
|
|
4910
|
+
* Account-seeded access (ADR 0274 D3(b)). With `held`, the time the account inventory was read,
|
|
4911
|
+
* a Work whose every root is held Public is confirmed Public with the account as its recorded
|
|
4912
|
+
* choice (ADR 0275); without it, Public stays a suggestion.
|
|
4913
|
+
*/
|
|
4914
|
+
function accountSeededAccess(account, held) {
|
|
4915
|
+
const accessChoice = account === "public-all" && held !== void 0 ? {
|
|
4916
|
+
channel: "account",
|
|
4917
|
+
at: held
|
|
4918
|
+
} : void 0;
|
|
4919
|
+
return {
|
|
4920
|
+
access: account === "public" || account === "public-all" ? "public" : "private",
|
|
4921
|
+
accessOrigin: "account",
|
|
4922
|
+
accessConfirmed: account === "private" || accessChoice !== void 0,
|
|
4923
|
+
accountAccessConflict: account === "mixed",
|
|
4924
|
+
accessChoice
|
|
4925
|
+
};
|
|
4926
|
+
}
|
|
4927
|
+
/** Classification confirmation initializes visibility and scan membership for this journey. */
|
|
4928
|
+
function confirmScope(state, now, decision, accountAccess) {
|
|
4929
|
+
if (state.scope.status === "confirmed") return state;
|
|
4930
|
+
if (state.classificationRevision === null || !state.works.length || state.works.some((work) => work.placement !== "placed" && work.placement !== "classifying" || work.placement === "placed" && !(work.status === "blocked" && work.access === "drop" && work.accessConfirmed) && (!work.description.trim() || !work.projectType))) throw new ApplicationError("SCOPE_NOT_READY");
|
|
4931
|
+
return withReadingProgress({
|
|
4932
|
+
...state,
|
|
4933
|
+
scope: {
|
|
4934
|
+
status: "confirmed",
|
|
4935
|
+
actor: decision ? "delegate" : "human",
|
|
4936
|
+
at: now
|
|
4937
|
+
},
|
|
4938
|
+
works: state.works.map((work) => {
|
|
4939
|
+
if (work.placement === "classifying") return work;
|
|
4940
|
+
if (work.accessOrigin === "explicit" && work.accessConfirmed) return work;
|
|
4941
|
+
const account = accountAccess?.get(work.id);
|
|
4942
|
+
if (account) return {
|
|
4943
|
+
...work,
|
|
4944
|
+
...accountSeededAccess(account, now)
|
|
4945
|
+
};
|
|
4946
|
+
if (work.accessOrigin === "account") return work;
|
|
4947
|
+
const access = work.accessConfirmed ? work.access : work.classificationRecommendation?.access ?? work.access;
|
|
4948
|
+
return {
|
|
4949
|
+
...work,
|
|
4950
|
+
access,
|
|
4951
|
+
accessOrigin: work.accessConfirmed || !work.classificationRecommendation ? work.accessOrigin : "model",
|
|
4952
|
+
accessConfirmed: access !== "public"
|
|
4953
|
+
};
|
|
4954
|
+
})
|
|
4955
|
+
});
|
|
4956
|
+
}
|
|
4957
|
+
function setWorkType(state, workId, type, decision) {
|
|
4958
|
+
if (state.scope.status === "confirmed") throw new ApplicationError("INVALID_TRANSITION");
|
|
4959
|
+
const projectType = decision ? {
|
|
4960
|
+
type,
|
|
4961
|
+
reason: "Chosen by your delegate for this journey.",
|
|
4962
|
+
origin: "delegate"
|
|
4963
|
+
} : {
|
|
4964
|
+
type,
|
|
4965
|
+
reason: "Chosen by you.",
|
|
4966
|
+
origin: "explicit"
|
|
4967
|
+
};
|
|
4968
|
+
return {
|
|
4969
|
+
...state,
|
|
4970
|
+
scope: {
|
|
4971
|
+
status: "pending",
|
|
4972
|
+
actor: null,
|
|
4973
|
+
at: null
|
|
4974
|
+
},
|
|
4975
|
+
privacy: {
|
|
4976
|
+
...state.privacy,
|
|
4977
|
+
cards: [],
|
|
4978
|
+
confirmedAnswersRevision: null,
|
|
4979
|
+
packageApproval: null
|
|
4980
|
+
},
|
|
4981
|
+
works: state.works.map((work) => work.id !== workId || decision && work.projectType?.origin === "explicit" ? work : {
|
|
4982
|
+
...work,
|
|
4983
|
+
projectType
|
|
4984
|
+
})
|
|
4985
|
+
};
|
|
4986
|
+
}
|
|
4987
|
+
/** One rule for single and bulk choices; selection changes recompute reading completion. */
|
|
4988
|
+
function setWorksAccess(state, workIds, access, decision, accessChoice) {
|
|
4989
|
+
if (decision && access === "public") throw new ApplicationError("CONFIRMATION_REQUIRED");
|
|
4990
|
+
if (new Set(workIds).size !== workIds.length) throw new ApplicationError("INVALID_SELECTION");
|
|
4991
|
+
if (workIds.some((id) => !state.works.some((work) => work.id === id))) throw new ApplicationError("UNKNOWN_WORKSPACE");
|
|
4992
|
+
if (state.scope.status === "confirmed") return changeConfirmedAccess(state, workIds, access, decision, accessChoice);
|
|
4993
|
+
return withReadingProgress({
|
|
4994
|
+
...state,
|
|
4995
|
+
scope: {
|
|
4996
|
+
status: "pending",
|
|
4997
|
+
actor: null,
|
|
4998
|
+
at: null
|
|
4999
|
+
},
|
|
4773
5000
|
privacy: {
|
|
4774
5001
|
...state.privacy,
|
|
4775
|
-
|
|
4776
|
-
cards: state.privacy.cards.filter((card) => card.termKeys.every((key) => !changedKeys.has(key))),
|
|
5002
|
+
cards: [],
|
|
4777
5003
|
confirmedAnswersRevision: null,
|
|
4778
5004
|
packageApproval: null
|
|
4779
5005
|
},
|
|
4780
|
-
works: state.works.map((work) => work.id
|
|
5006
|
+
works: state.works.map((work) => !workIds.includes(work.id) ? work : {
|
|
5007
|
+
...work,
|
|
5008
|
+
revision: work.revision + 1,
|
|
5009
|
+
artifact: null,
|
|
5010
|
+
status: work.status === "ready" ? "review" : work.status,
|
|
5011
|
+
access,
|
|
5012
|
+
accessConfirmed: true,
|
|
5013
|
+
accountAccessConflict: false,
|
|
5014
|
+
accessChoice: access === "public" ? accessChoice : void 0,
|
|
5015
|
+
accessOrigin: decision && work.accessOrigin !== "explicit" ? "delegate" : "explicit"
|
|
5016
|
+
})
|
|
5017
|
+
});
|
|
5018
|
+
}
|
|
5019
|
+
/**
|
|
5020
|
+
* After confirmation the person, never a delegate, may still change any Work's visibility
|
|
5021
|
+
* (D2, superseding ADR 0162's lock and ADR 0188's blocked-only Drop). Drop stops that Work's
|
|
5022
|
+
* scan; a Work moved out of Drop is read again; reading progress is recomputed.
|
|
5023
|
+
*/
|
|
5024
|
+
function changeConfirmedAccess(state, workIds, access, decision, accessChoice) {
|
|
5025
|
+
if (decision || state.phase === "sending" || state.phase === "completed" || state.works.some((work) => workIds.includes(work.id) && work.access === access && work.accessConfirmed && hasPublicChoice(work))) throw new ApplicationError("INVALID_TRANSITION");
|
|
5026
|
+
if (access === "public" && state.works.every((work) => !workIds.includes(work.id) || work.access === "public" && work.accessConfirmed)) return {
|
|
5027
|
+
...state,
|
|
5028
|
+
works: state.works.map((work) => workIds.includes(work.id) && accessChoice ? {
|
|
5029
|
+
...work,
|
|
5030
|
+
accessOrigin: "explicit",
|
|
5031
|
+
accessChoice
|
|
5032
|
+
} : work)
|
|
4781
5033
|
};
|
|
5034
|
+
return withReadingProgress({
|
|
5035
|
+
...state,
|
|
5036
|
+
privacy: {
|
|
5037
|
+
...state.privacy,
|
|
5038
|
+
packageApproval: null
|
|
5039
|
+
},
|
|
5040
|
+
works: state.works.map((work) => workIds.includes(work.id) ? {
|
|
5041
|
+
...work,
|
|
5042
|
+
revision: work.revision + 1,
|
|
5043
|
+
artifact: null,
|
|
5044
|
+
status: work.status === "ready" ? "review" : work.status,
|
|
5045
|
+
access,
|
|
5046
|
+
accessConfirmed: true,
|
|
5047
|
+
accountAccessConflict: false,
|
|
5048
|
+
accessChoice: access === "public" ? accessChoice : void 0,
|
|
5049
|
+
accessOrigin: "explicit"
|
|
5050
|
+
} : work)
|
|
5051
|
+
});
|
|
4782
5052
|
}
|
|
4783
|
-
/**
|
|
4784
|
-
function
|
|
4785
|
-
|
|
5053
|
+
/** Model suggestions fill or refresh model types only; a person's or delegate's type stays. */
|
|
5054
|
+
function applyClassification(state, items) {
|
|
5055
|
+
if (state.scope.status === "confirmed") throw new ApplicationError("INVALID_TRANSITION");
|
|
5056
|
+
const byWork = new Map(items.map((item) => [item.workId, item]));
|
|
5057
|
+
if (byWork.size !== items.length) throw new ApplicationError("INVALID_SELECTION");
|
|
5058
|
+
if (items.some((item) => !state.works.some((work) => work.id === item.workId))) throw new ApplicationError("UNKNOWN_WORKSPACE");
|
|
4786
5059
|
return {
|
|
4787
|
-
...
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
5060
|
+
...state,
|
|
5061
|
+
works: state.works.map((work) => {
|
|
5062
|
+
const item = byWork.get(work.id);
|
|
5063
|
+
if (!item || work.projectType && work.projectType.origin !== "model") return work;
|
|
5064
|
+
return {
|
|
5065
|
+
...work,
|
|
5066
|
+
projectType: {
|
|
5067
|
+
type: item.type,
|
|
5068
|
+
reason: item.reason,
|
|
5069
|
+
origin: "model"
|
|
5070
|
+
}
|
|
5071
|
+
};
|
|
5072
|
+
})
|
|
4797
5073
|
};
|
|
4798
5074
|
}
|
|
4799
5075
|
//#endregion
|
|
@@ -4818,6 +5094,7 @@ const classificationCommitSchema = z.object({
|
|
|
4818
5094
|
/** `classificationPartition` of the state the proposal was prepared against. */
|
|
4819
5095
|
partition: journeyDigestSchema,
|
|
4820
5096
|
late: z.boolean(),
|
|
5097
|
+
accountAccess: z.record(z.string(), accountWorkAccessSchema).optional(),
|
|
4821
5098
|
items: z.array(journeyClassificationSubmitSchema.shape.items.element.extend({
|
|
4822
5099
|
workId: journeyIdSchema,
|
|
4823
5100
|
workspaceIds: workspaces
|
|
@@ -4841,13 +5118,22 @@ function classificationPartition(state) {
|
|
|
4841
5118
|
work.rootSessionIds.toSorted()
|
|
4842
5119
|
]))).digest("hex");
|
|
4843
5120
|
}
|
|
5121
|
+
/**
|
|
5122
|
+
* Two placed Works one late item may join: the same access, origin, confirmation, recorded
|
|
5123
|
+
* Public choice and account access conflict, as local-host isolation.ts compares. The Skill's `validateLatePlacedWorks` mirrors this rule before commit.
|
|
5124
|
+
*/
|
|
5125
|
+
function sameAccessRecord(work, other) {
|
|
5126
|
+
return work.access === other?.access && work.accessOrigin === other.accessOrigin && work.accessConfirmed === other.accessConfirmed && work.accessChoice?.channel === other.accessChoice?.channel && work.accessChoice?.at === other.accessChoice?.at && work.accountAccessConflict === other.accountAccessConflict;
|
|
5127
|
+
}
|
|
4844
5128
|
/** The proposal's Works built from the given state's current Works (E2). */
|
|
4845
5129
|
function classificationWorks(state, plan) {
|
|
4846
5130
|
const late = plan.late;
|
|
4847
5131
|
const works = [];
|
|
4848
5132
|
for (const item of plan.items) {
|
|
4849
5133
|
const existing = state.works.find((work) => work.placement !== "classifying" && work.rootSessionIds.length === item.rootSessionIds.length && work.rootSessionIds.every((root) => item.rootSessionIds.includes(root)));
|
|
4850
|
-
const
|
|
5134
|
+
const owners = late ? state.works.filter((work) => work.placement === "placed" && work.rootSessionIds.some((root) => item.rootSessionIds.includes(root))) : [];
|
|
5135
|
+
if (owners.some((work) => !sameAccessRecord(work, owners[0]))) throw new ApplicationError("INVALID_SELECTION", "classification.late.several-works");
|
|
5136
|
+
const extended = owners.find((work) => work.rootSessionIds.every((root) => item.rootSessionIds.includes(root)));
|
|
4851
5137
|
if (late && existing) {
|
|
4852
5138
|
works.push(existing);
|
|
4853
5139
|
continue;
|
|
@@ -4858,6 +5144,9 @@ function classificationWorks(state, plan) {
|
|
|
4858
5144
|
sourceWorkspaceIds: [.../* @__PURE__ */ new Set([...extended.sourceWorkspaceIds, ...item.workspaceIds])]
|
|
4859
5145
|
} : newJourneyWork(item.workId, item.projectName, item.rootSessionIds, item.workspaceIds, "placed"));
|
|
4860
5146
|
const { classificationMetadata: _display, ...original } = base;
|
|
5147
|
+
const account = plan.accountAccess?.[base.id];
|
|
5148
|
+
const inherit = late && account && base.accessOrigin !== "explicit";
|
|
5149
|
+
const unproven = extended && base.accessChoice?.channel === "account" && account !== "public-all";
|
|
4861
5150
|
works.push({
|
|
4862
5151
|
...original,
|
|
4863
5152
|
projectName: item.projectName,
|
|
@@ -4872,8 +5161,13 @@ function classificationWorks(state, plan) {
|
|
|
4872
5161
|
...late && !extended ? {
|
|
4873
5162
|
access: item.recommendation.access,
|
|
4874
5163
|
accessOrigin: "model",
|
|
4875
|
-
accessConfirmed:
|
|
5164
|
+
accessConfirmed: item.recommendation.access !== "public"
|
|
5165
|
+
} : {},
|
|
5166
|
+
...unproven ? {
|
|
5167
|
+
accessConfirmed: false,
|
|
5168
|
+
accessChoice: void 0
|
|
4876
5169
|
} : {},
|
|
5170
|
+
...inherit && account ? accountSeededAccess(account, plan.at) : {},
|
|
4877
5171
|
classificationRecommendation: item.recommendation,
|
|
4878
5172
|
suggestion: null,
|
|
4879
5173
|
artifact: null,
|
|
@@ -5146,7 +5440,7 @@ function assertDelegatedDecision(state, action, decision, source) {
|
|
|
5146
5440
|
}
|
|
5147
5441
|
if (action.kind === "cards-confirm") return;
|
|
5148
5442
|
if (action.kind === "work-access" || action.kind === "works-access") {
|
|
5149
|
-
if (action.access === "drop") throw new ApplicationError("CONFIRMATION_REQUIRED");
|
|
5443
|
+
if (action.access === "drop" || action.access === "public") throw new ApplicationError("CONFIRMATION_REQUIRED");
|
|
5150
5444
|
const ids = action.kind === "work-access" ? [action.workId] : action.workIds;
|
|
5151
5445
|
if (state.works.some((work) => ids.includes(work.id) && work.accessOrigin === "explicit" && work.access !== action.access)) throw new ApplicationError("CONFIRMATION_REQUIRED");
|
|
5152
5446
|
return;
|
|
@@ -5226,135 +5520,6 @@ function propagateGroups(state, action) {
|
|
|
5226
5520
|
};
|
|
5227
5521
|
}
|
|
5228
5522
|
//#endregion
|
|
5229
|
-
//#region packages/application/src/journey/scope/respond.ts
|
|
5230
|
-
/** Classification confirmation fixes visibility and scan membership for this journey. */
|
|
5231
|
-
function confirmScope(state, now, decision) {
|
|
5232
|
-
if (state.scope.status === "confirmed") return state;
|
|
5233
|
-
if (state.classificationRevision === null || !state.works.length || state.works.some((work) => work.placement !== "placed" && work.placement !== "classifying" || work.placement === "placed" && !(work.status === "blocked" && work.access === "drop" && work.accessConfirmed) && (!work.description.trim() || !work.projectType))) throw new ApplicationError("SCOPE_NOT_READY");
|
|
5234
|
-
return withReadingProgress({
|
|
5235
|
-
...state,
|
|
5236
|
-
scope: {
|
|
5237
|
-
status: "confirmed",
|
|
5238
|
-
actor: decision ? "delegate" : "human",
|
|
5239
|
-
at: now
|
|
5240
|
-
},
|
|
5241
|
-
works: state.works.map((work) => work.placement === "classifying" ? work : work.accessConfirmed || !work.classificationRecommendation ? {
|
|
5242
|
-
...work,
|
|
5243
|
-
accessConfirmed: true
|
|
5244
|
-
} : {
|
|
5245
|
-
...work,
|
|
5246
|
-
access: work.classificationRecommendation.access,
|
|
5247
|
-
accessOrigin: "model",
|
|
5248
|
-
accessConfirmed: true
|
|
5249
|
-
})
|
|
5250
|
-
});
|
|
5251
|
-
}
|
|
5252
|
-
function setWorkType(state, workId, type, decision) {
|
|
5253
|
-
if (state.scope.status === "confirmed") throw new ApplicationError("INVALID_TRANSITION");
|
|
5254
|
-
const projectType = decision ? {
|
|
5255
|
-
type,
|
|
5256
|
-
reason: "Chosen by your delegate for this journey.",
|
|
5257
|
-
origin: "delegate"
|
|
5258
|
-
} : {
|
|
5259
|
-
type,
|
|
5260
|
-
reason: "Chosen by you.",
|
|
5261
|
-
origin: "explicit"
|
|
5262
|
-
};
|
|
5263
|
-
return {
|
|
5264
|
-
...state,
|
|
5265
|
-
scope: {
|
|
5266
|
-
status: "pending",
|
|
5267
|
-
actor: null,
|
|
5268
|
-
at: null
|
|
5269
|
-
},
|
|
5270
|
-
privacy: {
|
|
5271
|
-
...state.privacy,
|
|
5272
|
-
cards: [],
|
|
5273
|
-
confirmedAnswersRevision: null,
|
|
5274
|
-
packageApproval: null
|
|
5275
|
-
},
|
|
5276
|
-
works: state.works.map((work) => work.id !== workId || decision && work.projectType?.origin === "explicit" ? work : {
|
|
5277
|
-
...work,
|
|
5278
|
-
projectType
|
|
5279
|
-
})
|
|
5280
|
-
};
|
|
5281
|
-
}
|
|
5282
|
-
/** One rule for single and bulk choices; selection changes recompute reading completion. */
|
|
5283
|
-
function setWorksAccess(state, workIds, access, decision) {
|
|
5284
|
-
if (new Set(workIds).size !== workIds.length) throw new ApplicationError("INVALID_SELECTION");
|
|
5285
|
-
if (workIds.some((id) => !state.works.some((work) => work.id === id))) throw new ApplicationError("UNKNOWN_WORKSPACE");
|
|
5286
|
-
if (state.scope.status === "confirmed") return changeConfirmedAccess(state, workIds, access, decision);
|
|
5287
|
-
return withReadingProgress({
|
|
5288
|
-
...state,
|
|
5289
|
-
scope: {
|
|
5290
|
-
status: "pending",
|
|
5291
|
-
actor: null,
|
|
5292
|
-
at: null
|
|
5293
|
-
},
|
|
5294
|
-
privacy: {
|
|
5295
|
-
...state.privacy,
|
|
5296
|
-
cards: [],
|
|
5297
|
-
confirmedAnswersRevision: null,
|
|
5298
|
-
packageApproval: null
|
|
5299
|
-
},
|
|
5300
|
-
works: state.works.map((work) => !workIds.includes(work.id) ? work : {
|
|
5301
|
-
...work,
|
|
5302
|
-
revision: work.revision + 1,
|
|
5303
|
-
artifact: null,
|
|
5304
|
-
status: work.status === "ready" ? "review" : work.status,
|
|
5305
|
-
access,
|
|
5306
|
-
accessConfirmed: true,
|
|
5307
|
-
accessOrigin: decision && work.accessOrigin !== "explicit" ? "delegate" : "explicit"
|
|
5308
|
-
})
|
|
5309
|
-
});
|
|
5310
|
-
}
|
|
5311
|
-
/**
|
|
5312
|
-
* After confirmation the person, never a delegate, may still change any Work's visibility
|
|
5313
|
-
* (D2, superseding ADR 0162's lock and ADR 0188's blocked-only Drop). Drop stops that Work's
|
|
5314
|
-
* scan; a Work moved out of Drop is read again; reading progress is recomputed.
|
|
5315
|
-
*/
|
|
5316
|
-
function changeConfirmedAccess(state, workIds, access, decision) {
|
|
5317
|
-
if (decision || state.phase === "sending" || state.phase === "completed" || state.works.some((work) => workIds.includes(work.id) && work.access === access)) throw new ApplicationError("INVALID_TRANSITION");
|
|
5318
|
-
return withReadingProgress({
|
|
5319
|
-
...state,
|
|
5320
|
-
privacy: {
|
|
5321
|
-
...state.privacy,
|
|
5322
|
-
packageApproval: null
|
|
5323
|
-
},
|
|
5324
|
-
works: state.works.map((work) => workIds.includes(work.id) ? {
|
|
5325
|
-
...work,
|
|
5326
|
-
revision: work.revision + 1,
|
|
5327
|
-
artifact: null,
|
|
5328
|
-
status: work.status === "ready" ? "review" : work.status,
|
|
5329
|
-
access,
|
|
5330
|
-
accessConfirmed: true,
|
|
5331
|
-
accessOrigin: "explicit"
|
|
5332
|
-
} : work)
|
|
5333
|
-
});
|
|
5334
|
-
}
|
|
5335
|
-
/** Model suggestions fill or refresh model types only; a person's or delegate's type stays. */
|
|
5336
|
-
function applyClassification(state, items) {
|
|
5337
|
-
if (state.scope.status === "confirmed") throw new ApplicationError("INVALID_TRANSITION");
|
|
5338
|
-
const byWork = new Map(items.map((item) => [item.workId, item]));
|
|
5339
|
-
if (byWork.size !== items.length) throw new ApplicationError("INVALID_SELECTION");
|
|
5340
|
-
if (items.some((item) => !state.works.some((work) => work.id === item.workId))) throw new ApplicationError("UNKNOWN_WORKSPACE");
|
|
5341
|
-
return {
|
|
5342
|
-
...state,
|
|
5343
|
-
works: state.works.map((work) => {
|
|
5344
|
-
const item = byWork.get(work.id);
|
|
5345
|
-
if (!item || work.projectType && work.projectType.origin !== "model") return work;
|
|
5346
|
-
return {
|
|
5347
|
-
...work,
|
|
5348
|
-
projectType: {
|
|
5349
|
-
type: item.type,
|
|
5350
|
-
reason: item.reason,
|
|
5351
|
-
origin: "model"
|
|
5352
|
-
}
|
|
5353
|
-
};
|
|
5354
|
-
})
|
|
5355
|
-
};
|
|
5356
|
-
}
|
|
5357
|
-
//#endregion
|
|
5358
5523
|
//#region packages/application/src/journey/respond.ts
|
|
5359
5524
|
/** A changed privacy instruction requires a new read of the same frozen roots. */
|
|
5360
5525
|
function invalidateAnalysisIntent(state) {
|
|
@@ -5378,7 +5543,7 @@ function invalidateAnalysisIntent(state) {
|
|
|
5378
5543
|
})
|
|
5379
5544
|
});
|
|
5380
5545
|
}
|
|
5381
|
-
function respondToJourney(state, action, source, now, decision, preferenceScope) {
|
|
5546
|
+
function respondToJourney(state, action, source, now, decision, preferenceScope, accountAccess) {
|
|
5382
5547
|
if (preferenceScope && (decision || !["group", "groups-hide"].includes(action.kind))) throw new ApplicationError("INVALID_ARGUMENTS");
|
|
5383
5548
|
if (state.abandonedAt) throw new ApplicationError("INVALID_TRANSITION");
|
|
5384
5549
|
if (action.kind === "abandon") {
|
|
@@ -5492,10 +5657,14 @@ function respondToJourney(state, action, source, now, decision, preferenceScope)
|
|
|
5492
5657
|
};
|
|
5493
5658
|
if (action.kind === "scope-confirm") {
|
|
5494
5659
|
if (source !== "conversation" || decision) throw new ApplicationError("CONFIRMATION_REQUIRED");
|
|
5495
|
-
return confirmScope(state, now);
|
|
5660
|
+
return confirmScope(state, now, void 0, accountAccess);
|
|
5496
5661
|
}
|
|
5497
5662
|
if (action.kind === "card-answer" || action.kind === "cards-confirm" || action.kind === "package-confirm") throw new ApplicationError("INVALID_TRANSITION");
|
|
5498
|
-
if (action.kind === "works-access")
|
|
5663
|
+
if ((action.kind === "work-access" || action.kind === "works-access") && action.access === "public" && source === "conversation" && (!action.accessChoice || action.accessChoice.channel !== "conversation" || !Number.isFinite(Date.parse(action.accessChoice.at)))) throw new ApplicationError("CONFIRMATION_REQUIRED");
|
|
5664
|
+
if (action.kind === "works-access") return setWorksAccess(state, action.workIds, action.access, decision, source === "panel" ? {
|
|
5665
|
+
channel: source,
|
|
5666
|
+
at: now
|
|
5667
|
+
} : action.accessChoice);
|
|
5499
5668
|
if (action.kind === "group" || action.kind === "groups-hide") {
|
|
5500
5669
|
const ids = action.kind === "group" ? [action.groupId] : action.groupIds;
|
|
5501
5670
|
if (new Set(ids).size !== ids.length || ids.some((id) => !state.groups.some((group) => group.id === id))) throw new ApplicationError("UNKNOWN_ITEM");
|
|
@@ -5526,7 +5695,10 @@ function respondToJourney(state, action, source, now, decision, preferenceScope)
|
|
|
5526
5695
|
})
|
|
5527
5696
|
});
|
|
5528
5697
|
}
|
|
5529
|
-
return setWorksAccess(state, [workId], action.access, decision
|
|
5698
|
+
return setWorksAccess(state, [workId], action.access, decision, source === "panel" ? {
|
|
5699
|
+
channel: source,
|
|
5700
|
+
at: now
|
|
5701
|
+
} : action.accessChoice);
|
|
5530
5702
|
}
|
|
5531
5703
|
//#endregion
|
|
5532
5704
|
//#region packages/application/src/journey/questions.ts
|
|
@@ -6261,6 +6433,7 @@ function journeyView(state, now) {
|
|
|
6261
6433
|
const terms = activePrivacyTerms(state);
|
|
6262
6434
|
return {
|
|
6263
6435
|
...safe,
|
|
6436
|
+
displayedScopeDigest: displayedScopeDigest(state),
|
|
6264
6437
|
privacy: {
|
|
6265
6438
|
...state.privacy,
|
|
6266
6439
|
terms
|
|
@@ -6317,6 +6490,59 @@ function journeyView(state, now) {
|
|
|
6317
6490
|
}
|
|
6318
6491
|
/** Works rendered at once by one several-Work call. */
|
|
6319
6492
|
const renderConcurrency = 4;
|
|
6493
|
+
const inFlightRenders = /* @__PURE__ */ new WeakMap();
|
|
6494
|
+
const renderScopeTails = /* @__PURE__ */ new WeakMap();
|
|
6495
|
+
function waitForRender(pending, signal) {
|
|
6496
|
+
signal.throwIfAborted();
|
|
6497
|
+
return new Promise((resolve, reject) => {
|
|
6498
|
+
const abort = () => reject(signal.reason);
|
|
6499
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
6500
|
+
pending.then(resolve, reject).finally(() => signal.removeEventListener("abort", abort));
|
|
6501
|
+
});
|
|
6502
|
+
}
|
|
6503
|
+
async function acquireRenderScope(port, signal) {
|
|
6504
|
+
const previous = renderScopeTails.get(port);
|
|
6505
|
+
const gate = Promise.withResolvers();
|
|
6506
|
+
const tail = (previous ?? Promise.resolve()).then(() => gate.promise);
|
|
6507
|
+
renderScopeTails.set(port, tail);
|
|
6508
|
+
const release = () => {
|
|
6509
|
+
gate.resolve();
|
|
6510
|
+
if (renderScopeTails.get(port) === tail) renderScopeTails.delete(port);
|
|
6511
|
+
};
|
|
6512
|
+
try {
|
|
6513
|
+
await waitForRender(previous ?? Promise.resolve(), signal);
|
|
6514
|
+
return {
|
|
6515
|
+
release,
|
|
6516
|
+
waited: previous !== void 0
|
|
6517
|
+
};
|
|
6518
|
+
} catch (error) {
|
|
6519
|
+
tail.then(() => {
|
|
6520
|
+
if (renderScopeTails.get(port) === tail) renderScopeTails.delete(port);
|
|
6521
|
+
});
|
|
6522
|
+
gate.resolve();
|
|
6523
|
+
throw error;
|
|
6524
|
+
}
|
|
6525
|
+
}
|
|
6526
|
+
async function joinRender(port, journeyId, workId, run, signal, retryConflict = true) {
|
|
6527
|
+
let pending = inFlightRenders.get(port);
|
|
6528
|
+
if (!pending) {
|
|
6529
|
+
pending = /* @__PURE__ */ new Map();
|
|
6530
|
+
inFlightRenders.set(port, pending);
|
|
6531
|
+
}
|
|
6532
|
+
const key = `${journeyId}:${workId}`;
|
|
6533
|
+
const existing = pending.get(key);
|
|
6534
|
+
if (existing) try {
|
|
6535
|
+
return await waitForRender(existing, signal);
|
|
6536
|
+
} catch (error) {
|
|
6537
|
+
signal.throwIfAborted();
|
|
6538
|
+
if (retryConflict && safeCode(error) === "REVISION_CONFLICT") return joinRender(port, journeyId, workId, run, signal, false);
|
|
6539
|
+
throw error;
|
|
6540
|
+
}
|
|
6541
|
+
const entries = pending;
|
|
6542
|
+
const result = Promise.resolve().then(run).finally(() => entries.delete(key));
|
|
6543
|
+
entries.set(key, result);
|
|
6544
|
+
return result;
|
|
6545
|
+
}
|
|
6320
6546
|
function createNativeJourney(storage, now = () => (/* @__PURE__ */ new Date()).toISOString(), local) {
|
|
6321
6547
|
/** Callers present after their write is durable, so a concurrent commit must not turn it into an error. */
|
|
6322
6548
|
async function present(committed) {
|
|
@@ -6600,7 +6826,8 @@ function createNativeJourney(storage, now = () => (/* @__PURE__ */ new Date()).t
|
|
|
6600
6826
|
const current = await storage.current(input.journeyId);
|
|
6601
6827
|
if (!current) throw new ApplicationError("UNKNOWN_ITEM");
|
|
6602
6828
|
const expectedRevision = rebase ? current.revision : input.expectedRevision;
|
|
6603
|
-
const
|
|
6829
|
+
const accountAccess = current.revision === expectedRevision && input.action.kind === "scope-confirm" && current.scope.status !== "confirmed" && source === "conversation" && !input.decision ? await local?.accountAccess?.(current, new AbortController().signal) : void 0;
|
|
6830
|
+
const state = current.revision === expectedRevision ? respondToJourney(current, input.action, source, now(), input.decision, input.preferenceScope, accountAccess) : current;
|
|
6604
6831
|
const groupIds = input.action.kind === "group" ? [input.action.groupId] : input.action.kind === "groups-hide" ? input.action.groupIds : [];
|
|
6605
6832
|
const preferenceScopes = input.decision ? [] : state.groups.flatMap((group) => groupIds.includes(group.id) && group.preferenceScope ? [{
|
|
6606
6833
|
groupId: group.id,
|
|
@@ -6716,7 +6943,7 @@ function createNativeJourney(storage, now = () => (/* @__PURE__ */ new Date()).t
|
|
|
6716
6943
|
const release = await port.renderActivity?.begin(input.journeyId, workIds);
|
|
6717
6944
|
let result;
|
|
6718
6945
|
try {
|
|
6719
|
-
result = "workId" in input ? { state: await port.render(input.journeyId, input.workId, signal) } : {
|
|
6946
|
+
result = "workId" in input ? { state: await joinRender(port, input.journeyId, input.workId, () => port.render(input.journeyId, input.workId, signal), signal) } : {
|
|
6720
6947
|
renders: await renderSeveral(port, input.journeyId, workIds, signal),
|
|
6721
6948
|
state: await currentState(input.journeyId)
|
|
6722
6949
|
};
|
|
@@ -6736,35 +6963,51 @@ function createNativeJourney(storage, now = () => (/* @__PURE__ */ new Date()).t
|
|
|
6736
6963
|
}
|
|
6737
6964
|
async function renderSeveral(port, journeyId, workIds, signal) {
|
|
6738
6965
|
const renders = [];
|
|
6739
|
-
|
|
6740
|
-
const scope = await port.renderScope?.(journeyId, workIds.length, signal);
|
|
6741
|
-
const renderWork = scope ? (workId) => scope.render(workId) : (workId) => port.render(journeyId, workId, signal);
|
|
6966
|
+
const lease = await acquireRenderScope(port, signal);
|
|
6742
6967
|
try {
|
|
6743
|
-
const
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
|
|
6968
|
+
const current = lease.waited ? await currentState(journeyId) : void 0;
|
|
6969
|
+
const completed = new Set(current?.works.filter((work) => work.artifact?.revision === work.revision && work.status === "ready" && !current.pendingHideId && current.phase !== "paused").map((work) => work.id));
|
|
6970
|
+
const remaining = workIds.filter((workId) => {
|
|
6971
|
+
if (!completed.has(workId)) return true;
|
|
6972
|
+
renders.push({
|
|
6973
|
+
workId,
|
|
6974
|
+
status: "rendered"
|
|
6975
|
+
});
|
|
6976
|
+
return false;
|
|
6977
|
+
});
|
|
6978
|
+
let next = 0;
|
|
6979
|
+
const scope = remaining.length ? await port.renderScope?.(journeyId, remaining.length, signal) : void 0;
|
|
6980
|
+
const renderWork = scope ? (workId) => scope.render(workId) : (workId) => port.render(journeyId, workId, signal);
|
|
6981
|
+
try {
|
|
6982
|
+
const failure = (await Promise.allSettled(Array.from({ length: Math.min(scope?.concurrency ?? renderConcurrency, remaining.length) }, async () => {
|
|
6983
|
+
for (let workId = remaining[next++]; workId !== void 0; workId = remaining[next++]) {
|
|
6984
|
+
try {
|
|
6985
|
+
await joinRender(port, journeyId, workId, () => renderWork(workId), signal);
|
|
6986
|
+
renders.push({
|
|
6987
|
+
workId,
|
|
6988
|
+
status: "rendered"
|
|
6989
|
+
});
|
|
6990
|
+
} catch (error) {
|
|
6991
|
+
signal.throwIfAborted();
|
|
6992
|
+
port.renderFailed?.(workId, error);
|
|
6993
|
+
renders.push({
|
|
6994
|
+
workId,
|
|
6995
|
+
status: "failed",
|
|
6996
|
+
code: safeCode(error)
|
|
6997
|
+
});
|
|
6998
|
+
}
|
|
6999
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
6759
7000
|
}
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
}
|
|
6763
|
-
|
|
7001
|
+
}))).find((item) => item.status === "rejected");
|
|
7002
|
+
if (failure) throw failure.reason;
|
|
7003
|
+
} finally {
|
|
7004
|
+
await scope?.close();
|
|
7005
|
+
}
|
|
7006
|
+
const order = new Map(workIds.map((workId, index) => [workId, index]));
|
|
7007
|
+
return renders.toSorted((a, b) => (order.get(a.workId) ?? 0) - (order.get(b.workId) ?? 0));
|
|
6764
7008
|
} finally {
|
|
6765
|
-
|
|
7009
|
+
lease.release();
|
|
6766
7010
|
}
|
|
6767
|
-
return renders.toSorted((a, b) => workIds.indexOf(a.workId) - workIds.indexOf(b.workId));
|
|
6768
7011
|
}
|
|
6769
7012
|
async function findings(value, signal = new AbortController().signal) {
|
|
6770
7013
|
if (!local) throw new ApplicationError("INVALID_TRANSITION");
|
|
@@ -6854,7 +7097,32 @@ function createNativeJourney(storage, now = () => (/* @__PURE__ */ new Date()).t
|
|
|
6854
7097
|
const current = await storage.current(input.journeyId);
|
|
6855
7098
|
if (!current) throw new ApplicationError("UNKNOWN_ITEM");
|
|
6856
7099
|
const expectedRevision = rebase ? current.revision : input.expectedRevision;
|
|
6857
|
-
|
|
7100
|
+
let state;
|
|
7101
|
+
try {
|
|
7102
|
+
state = current.revision !== expectedRevision ? current : "resolutions" in input ? resolvePrivacyTerms(current, input) : publishDecisionCards(current, input);
|
|
7103
|
+
} catch (error) {
|
|
7104
|
+
if (!rebase || current.revision <= input.expectedRevision || !(error instanceof ApplicationError) || error.code !== "INVALID_SELECTION") throw error;
|
|
7105
|
+
const receipt = await storage.commit({
|
|
7106
|
+
expectedRevision: input.expectedRevision,
|
|
7107
|
+
requestKey: input.idempotencyKey,
|
|
7108
|
+
requestHash: digest$1(input),
|
|
7109
|
+
state: current,
|
|
7110
|
+
event: {
|
|
7111
|
+
journeyId: current.journeyId,
|
|
7112
|
+
kind: "response",
|
|
7113
|
+
source: "conversation",
|
|
7114
|
+
at: now()
|
|
7115
|
+
}
|
|
7116
|
+
}).catch((probeError) => {
|
|
7117
|
+
if (probeError instanceof ApplicationError && probeError.code === "OPERATION_CONFLICT") throw error;
|
|
7118
|
+
throw probeError;
|
|
7119
|
+
});
|
|
7120
|
+
if (receipt.status === "replayed") return {
|
|
7121
|
+
...receipt,
|
|
7122
|
+
state: await present(receipt.state)
|
|
7123
|
+
};
|
|
7124
|
+
throw error;
|
|
7125
|
+
}
|
|
6858
7126
|
const result = await storage.commit({
|
|
6859
7127
|
expectedRevision,
|
|
6860
7128
|
requestKey: input.idempotencyKey,
|
|
@@ -6952,6 +7220,7 @@ const version$1 = z.number().int().nonnegative();
|
|
|
6952
7220
|
const sendPrepareSchema = z.object({
|
|
6953
7221
|
journeyId: journeyIdSchema,
|
|
6954
7222
|
expectedJourneyRevision: version$1,
|
|
7223
|
+
displayedScopeDigest: journeyDigestSchema.optional(),
|
|
6955
7224
|
idempotencyKey: journeyIdSchema
|
|
6956
7225
|
}).strict();
|
|
6957
7226
|
const sendActionSchema = z.object({
|
|
@@ -6963,6 +7232,7 @@ const sendActionSchema = z.object({
|
|
|
6963
7232
|
}).strict();
|
|
6964
7233
|
const sendStartSchema = sendActionSchema.extend({
|
|
6965
7234
|
scopeDigest: journeyDigestSchema,
|
|
7235
|
+
displayedScopeDigest: journeyDigestSchema.optional(),
|
|
6966
7236
|
confirmedWorkIds: z.array(journeyIdSchema),
|
|
6967
7237
|
confirmedOmittedWorkIds: z.array(journeyIdSchema)
|
|
6968
7238
|
}).strict();
|
|
@@ -11713,6 +11983,48 @@ const storedCredentialSchema = accountProfileSchema.extend({
|
|
|
11713
11983
|
expiresAt: z.string().min(1).max(64)
|
|
11714
11984
|
}).refine((value) => profileUrlMatchesIdentity(value.profileUrl, value.identityUrl));
|
|
11715
11985
|
//#endregion
|
|
11986
|
+
//#region packages/application/src/account/renew.ts
|
|
11987
|
+
const renewBeforeMs = 12e4;
|
|
11988
|
+
const renewTimeoutMs = 3e4;
|
|
11989
|
+
const renewals = /* @__PURE__ */ new WeakMap();
|
|
11990
|
+
function renew(account, credential) {
|
|
11991
|
+
function configured(value) {
|
|
11992
|
+
return value?.identityUrl === account.configuration.identityUrl && value.clientId === account.configuration.clientId ? value : null;
|
|
11993
|
+
}
|
|
11994
|
+
const running = renewals.get(account);
|
|
11995
|
+
if (running) return running;
|
|
11996
|
+
const renewing = (async () => {
|
|
11997
|
+
try {
|
|
11998
|
+
const stored = configured((await account.credentials.update((state) => state)).credential);
|
|
11999
|
+
if (!stored || stored.refreshToken !== credential.refreshToken) return stored;
|
|
12000
|
+
const token = await account.identity.refresh(credential.refreshToken, AbortSignal.timeout(renewTimeoutMs));
|
|
12001
|
+
if (!token) return configured((await account.credentials.update((state) => {
|
|
12002
|
+
if (state.credential?.refreshToken === credential.refreshToken) {
|
|
12003
|
+
state.credential = null;
|
|
12004
|
+
state.connection = null;
|
|
12005
|
+
state.lastError = "SIGN_IN_EXPIRED";
|
|
12006
|
+
}
|
|
12007
|
+
return state;
|
|
12008
|
+
})).credential);
|
|
12009
|
+
return configured((await account.credentials.update((value) => {
|
|
12010
|
+
if (value.credential?.refreshToken === credential.refreshToken) value.credential = {
|
|
12011
|
+
...value.credential,
|
|
12012
|
+
accessToken: token.accessToken,
|
|
12013
|
+
refreshToken: token.refreshToken ?? credential.refreshToken,
|
|
12014
|
+
scope: token.scope,
|
|
12015
|
+
issuedAt: account.now(),
|
|
12016
|
+
expiresAt: token.expiresAt
|
|
12017
|
+
};
|
|
12018
|
+
return value;
|
|
12019
|
+
})).credential);
|
|
12020
|
+
} finally {
|
|
12021
|
+
renewals.delete(account);
|
|
12022
|
+
}
|
|
12023
|
+
})();
|
|
12024
|
+
renewals.set(account, renewing);
|
|
12025
|
+
return renewing;
|
|
12026
|
+
}
|
|
12027
|
+
//#endregion
|
|
11716
12028
|
//#region packages/application/src/account/poll-interval.ts
|
|
11717
12029
|
/** RFC 8628 section 3.5: each `slow_down` lengthens the interval by five seconds. */
|
|
11718
12030
|
const slowDownStepMs = 5e3;
|
|
@@ -12001,11 +12313,41 @@ function createSharedAccount(ports) {
|
|
|
12001
12313
|
return stop(true);
|
|
12002
12314
|
},
|
|
12003
12315
|
async verify() {
|
|
12004
|
-
|
|
12316
|
+
let saved = (await read()).credential;
|
|
12005
12317
|
if (!saved || !belongsToConfiguration(saved)) throw new ApplicationError("ACCOUNT_SIGNED_OUT");
|
|
12006
|
-
|
|
12318
|
+
let result;
|
|
12319
|
+
let renewing = false;
|
|
12320
|
+
try {
|
|
12321
|
+
const left = Date.parse(saved.expiresAt) - Date.parse(ports.now());
|
|
12322
|
+
if (saved.refreshToken && (!Number.isFinite(left) || left <= 12e4)) {
|
|
12323
|
+
renewing = true;
|
|
12324
|
+
saved = await renew(ports, {
|
|
12325
|
+
...saved,
|
|
12326
|
+
refreshToken: saved.refreshToken
|
|
12327
|
+
});
|
|
12328
|
+
renewing = false;
|
|
12329
|
+
if (!saved) return view(await read());
|
|
12330
|
+
}
|
|
12331
|
+
result = await ports.connection.check(saved.accessToken, shutdown.signal);
|
|
12332
|
+
if (result === "rejected" && saved.refreshToken) {
|
|
12333
|
+
renewing = true;
|
|
12334
|
+
saved = await renew(ports, {
|
|
12335
|
+
...saved,
|
|
12336
|
+
refreshToken: saved.refreshToken
|
|
12337
|
+
});
|
|
12338
|
+
renewing = false;
|
|
12339
|
+
if (!saved) return view(await read());
|
|
12340
|
+
result = await ports.connection.check(saved.accessToken, shutdown.signal);
|
|
12341
|
+
}
|
|
12342
|
+
} catch (error) {
|
|
12343
|
+
if (safeCode(error) !== "IDENTITY_UNAVAILABLE" && !(renewing && saved && !expired(saved.expiresAt, ports.now()))) throw error;
|
|
12344
|
+
const detail = typeof error === "object" && error !== null && "detail" in error ? ` (${String(error.detail)})` : "";
|
|
12345
|
+
console.error(`Account verification failed: ${safeCode(error)}${detail}`);
|
|
12346
|
+
result = "unavailable";
|
|
12347
|
+
}
|
|
12348
|
+
const checked = saved;
|
|
12007
12349
|
return view(await update((state) => {
|
|
12008
|
-
if (sameCredential(state.credential,
|
|
12350
|
+
if (checked && sameCredential(state.credential, checked)) {
|
|
12009
12351
|
if (result === "rejected") {
|
|
12010
12352
|
state.credential = null;
|
|
12011
12353
|
state.connection = null;
|
|
@@ -13412,4 +13754,4 @@ function equivalenceDuplicates(batch) {
|
|
|
13412
13754
|
return bindings.sort();
|
|
13413
13755
|
}
|
|
13414
13756
|
//#endregion
|
|
13415
|
-
export {
|
|
13757
|
+
export { validateDetectionSummary as $, reviewRepairInputSchema as $n, isClassifying as $r, searchScopeDigest as $t, renewBeforeMs as A, addHideIndexTokens as An, displayedScopeDigest as Ar, obsoleteJourney as At, createApplication as B, confirmedHideKey as Bn, staticReviewDigest as Br, classificationPartition as Bt, rebindReviewOverlay as C, journeyEventSchema as Cn, validatePreparationFacts as Cr, sendActionSchema as Ct, staticallyHiddenFindings as D, renderedHideValue as Dn, journeyPreviewSchema as Dr, sendStartSchema as Dt, guardedFindingText as E, readConfirmedHideChange as En, journeyFindingsSchema as Er, sendRequestSchema as Et, readAccountAvatarUrl as F, bExceptionRanges as Fn, nativeEventsSchema as Fr, journeyGuidance as Ft, validateInspectionRequest as G, maskedHitsStale as Gn, agentSourcesSchema as Gr, reviewCompileSchema as Gt, inspectionStartSchema as H, confirmedHideTerms as Hn, staticSessionResourceSchema as Hr, applyClassification as Ht, storedCredentialSchema as I, bMaskedHits as In, nativeGetSchema as Ir, journeyBatchReadSchema as It, validateInspectionFence as J, workDecisionDigest as Jn, sendReceiptSchema as Jr, hideBeginSchema as Jt, inspectionQuerySchema as K, syncTermGroups as Kn, journeySendSchema as Kr, journeyContextQuerySchema as Kt, sourceIdentityEvidence as L, bTermMatcher as Ln, nativeRespondSchema as Lr, journeyReviewStorageQuerySchema as Lt, deviceAuthorizationSchema as M, maximumHideIndexTokens as Mn, applyCardAnswers as Mr, nativeAdapterVersions as Mt, deviceProfileScopeSchema as N, packHideIndex as Nn, assertJourneyPrivacyReady as Nr, attemptBudgetCodePoints as Nt, createAccount as O, settleConfirmedHides as On, journeyRenderInputSchema as Or, settleCorrections as Ot, profileUrlMatchesIdentity as P, bContainment as Pn, privacyDecisionDigest as Pr, validateAttemptAppend as Pt, validateInspectionContribution as Q, reviewCandidateResourceSchema as Qn, hasCompleteWorkDescription as Qr, journeySearchSaveSchema as Qt, withSourceEvidence as R, bWordBounded as Rn, mergePrivacyTerms as Rr, applyClassificationProposal as Rt, rebindReviewAlignment as S, journeyCommitSchema as Sn, preparationStartSchema as Sr, replaceSensitiveTermsSchema as St, reviewBatchReuse as T, confirmedHideDeltaSchema as Tn, journeyFindingImpactSchema as Tr, sendPrepareSchema as Tt, validateInspectionBatch as U, dictionaryHides as Un, agentSourcePathSegment as Ur, retireScanGeneration as Ut, inspectionCancelSchema as V, confirmedHideKinds as Vn, staticSessionId as Vr, classificationWorks as Vt, validateInspectionBatches as W, journeyConfirmedHides as Wn, agentSourceSchema as Wr, newJourneyWork as Wt, validateInspectionInputs as X, workCorrectionBinding as Xn, sendResolutionSchema as Xr, hidePublishSchema as Xt, validateInspectionHead as Y, workPrivacyDecisions as Yn, sendReplaceResultSchema as Yr, hideFinishSchema as Yt, validateInspectionQuery as Z, reviewCandidateInputSchema as Zn, sendSettingsSchema as Zr, journeySearchResultSchema as Zt, changeJourney as _, defaultScopedSettings as _i, sessionReviewResourceSchema as _n, journeyInventorySchema as _r, manualUploadStartSchema as _t, bCrossSegmentReviewSchema as a, withReadingProgress as ai, journeyPlaceSchema as an, scanAliasResourceSchema as ar, appendSensitiveTerms as at, isGenericPublicTerm as b, staticCatalogRef as bi, sessionUsefulnessResourceSchema as bn, preparationBeginSchema as br, maximumTermsFileBytes as bt, reconstructBFields as c, selectionBatchSchema as ci, reviewAttemptsQuerySchema as cn, scanSessionResourceSchema as cr, maximumAgentSetupSessions as ct, resolveGroupSplit as d, producerVersion as di, sessionReconcileResultSchema as dn, verifiedScanGitSeeds as dr, validateFailureLocation as dt, isIncludedWork as ei, journeyPolicyRespondSchema as en, reviewRepairResourceSchema as er, inspectionInputs as et, selectedValueMembers as f, stateSchema as fi, sessionReconciliationResourceSchema as fn, scanExclusionResourceSchema as fr, manualUploadActionSchema as ft, semanticGroupKey as g, effectiveTreatmentSchema as gi, sessionReviewQuerySchema as gn, journeyInventoryReadSchema as gr, manualUploadSchema as gt, hideScopeDigest as h, approvedTreatmentSchema as hi, sessionReviewInputSchema as hn, journeyInventoryQuerySchema as hr, manualUploadPrepareSchema as ht, validateBCrossSegmentReview as i, selectedWorks as ii, journeyIsolateSchema as in, planBRepair as ir, reviewInventory as it, accountProfileSchema as j, hideKeyId as jn, requestedScope as jr, metadataProcessingVersion as jt, renew as k, termHideAdditions as kn, journeyRenderSchema as kr, currentJourneyAdapters as kt, chooseCheapPlacement as l, selectionSchema as li, reviewAttemptsResultSchema as ln, scanGitSeedsId as lr, artifactFailureDetailSchema as lt, activeJourneyTerms as m, recommendParallelism as mi, sessionRereadResourceSchema as mn, resolveSourceSelection as mr, manualUploadChoiceSchema as mt, scanBatchEquivalenceDigest as n, isSelectedWork as ni, journeyResourceQuerySchema as nn, bReviewDigest as nr, settingsQuerySchema as nt, bRereadDigest as o, commandSchema as oi, sortingApplySchema as on, scanCanonicalResourceSchema as or, classifyAgentSetup as ot, splitSelectorValues as p, sourceChangePolicy as pi, sessionRereadInputSchema as pn, validateScanExclusion as pr, manualUploadBindingSchema as pt, validateInspectionClaim as q, retireWorkDescription as qn, sendArtifactSchema as qr, journeyContextSchema as qt, locateTermEvidence as r, isSkippedWork as ri, journeyResourceSchema as rn, mergeBRepair as rr, readWorkspaceOutcomes as rt, reconcileBSession as s, packageCommandSchema as si, reviewAttemptResourceSchema as sn, scanPreparationDigest as sr, defaultAgentSetupInclusion as st, scanBatchContextDigest as t, isReadingComplete as ti, projectPreparationProgress as tn, reviewTransportBytes as tr, settingsBatchSchema as tt, reviseGroupMembership as u, gitMetadataBudgetBytes as ui, sessionReconcileInputSchema as un, scanGitSeedsResource as ur, resolveFailureLocation as ut, projectJourneyInventory as v, freezeConfiguration as vi, sessionReviewStatusSchema as vn, journeyPreparationProgressSchema as vr, candidateSortAvailable as vt, rebindReviewSubmit as w, confirmedHideAdditions as wn, journeyClassificationSessionsSchema as wr, sendChoiceSchema as wt, bReviewScope as x, journeyCommitResultSchema as xn, preparationSettlementSchema as xr, normalizeSensitiveTerms as xt, preparationScope as y, selectFrozenConfiguration as yi, sessionUsefulnessInputSchema as yn, emptyPreparationFacts as yr, emptyTermsRevision as yt, agentSetupKey as z, confirmedHideGroupIds as zn, hasCurrentStaticReview as zr, classificationCommitSchema as zt };
|