@gitroll/tacitt-cli 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/{agent-setup-B85GaVIz.mjs → agent-setup-CLXdKr2I.mjs} +2 -2
  2. package/dist/agent-setup-worker.mjs +5 -5
  3. package/dist/cli.mjs +165 -9
  4. package/dist/codex-title-worker.mjs +1 -1
  5. package/dist/configured-preview-worker.mjs +5 -5
  6. package/dist/configured-session-worker.mjs +25 -4
  7. package/dist/{frame-D1j9R8xX.mjs → frame-waS5FnN5.mjs} +1 -1
  8. package/dist/{heap-tfU61Ehy.mjs → heap-eO_uWpD1.mjs} +63 -9
  9. package/dist/inspection-worker.mjs +57 -0
  10. package/dist/job-rK-Ho9OD.mjs +613 -0
  11. package/dist/{locate-Bn32k2se.mjs → locate-U3-nkird.mjs} +29 -6
  12. package/dist/messages-D3m3bhva.mjs +40 -0
  13. package/dist/{model-7Nu7szNP.mjs → model-BBAnsFAx.mjs} +1 -1
  14. package/dist/operation-executor.mjs +3 -3
  15. package/dist/preview-worker.mjs +1 -1
  16. package/dist/privacy-validator.mjs +1 -1
  17. package/dist/{query-Da-KDbSV.mjs → query-DN99jiRc.mjs} +710 -630
  18. package/dist/{run-CCATsHS2.mjs → run-4G_CvdDj.mjs} +4 -4
  19. package/dist/session-process.mjs +6 -1
  20. package/dist/{src-CPPjOyHZ.mjs → src-B4R5XMEP.mjs} +621 -224
  21. package/dist/{src-BngGpFKd.mjs → src-CPbdnGrk.mjs} +130 -53
  22. package/dist/{src-DynBRDBc.mjs → src-qoLRvX-A.mjs} +34 -11
  23. package/dist/store-database-worker.mjs +1 -1
  24. package/dist/web/assets/index-BkuUI3Eu.js +67 -0
  25. package/dist/web/assets/index-Clg6Pfv_.css +1 -0
  26. package/dist/web/index.html +2 -2
  27. package/package.json +1 -1
  28. package/skills/tacitt/SKILL.md +15 -11
  29. package/skills/tacitt/references/b-method.md +1 -1
  30. package/skills/tacitt/references/classification.md +3 -3
  31. package/skills/tacitt/references/commands.md +19 -14
  32. package/skills/tacitt/references/journey.md +17 -11
  33. package/skills/tacitt/references/parallel-review.md +3 -3
  34. package/skills/tacitt/references/send.md +5 -5
  35. package/skills/tacitt/scripts/INDEX.md +6 -2
  36. package/skills/tacitt/scripts/answer.mjs +29 -8
  37. package/skills/tacitt/scripts/journey-card-consolidation.d.mts +13 -4
  38. package/skills/tacitt/scripts/journey-card-consolidation.mjs +170 -21
  39. package/skills/tacitt/scripts/journey-card-values.d.mts +17 -0
  40. package/skills/tacitt/scripts/journey-card-values.mjs +116 -0
  41. package/skills/tacitt/scripts/journey-classification-progress.mjs +2 -1
  42. package/skills/tacitt/scripts/journey-classification-validation.mjs +49 -28
  43. package/skills/tacitt/scripts/journey-classification.mjs +6 -2
  44. package/skills/tacitt/scripts/journey-consolidation-submit.mjs +42 -5
  45. package/skills/tacitt/scripts/journey-consolidation.d.mts +5 -0
  46. package/skills/tacitt/scripts/journey-consolidation.mjs +4 -1
  47. package/skills/tacitt/scripts/journey-panel-host.d.mts +9 -0
  48. package/skills/tacitt/scripts/journey-panel-host.mjs +56 -0
  49. package/skills/tacitt/scripts/journey-state.d.mts +1 -0
  50. package/skills/tacitt/scripts/journey-state.mjs +38 -6
  51. package/skills/tacitt/scripts/journey-tasks.mjs +5 -3
  52. package/skills/tacitt/scripts/journey.d.mts +4 -0
  53. package/skills/tacitt/scripts/journey.mjs +249 -41
  54. package/skills/tacitt/scripts/privacy-validator.mjs +25 -6
  55. package/skills/tacitt/scripts/review-stream-client.mjs +1 -1
  56. package/skills/tacitt/scripts/review.mjs +24 -3
  57. package/dist/job--TceKk0l.mjs +0 -194
  58. package/dist/web/assets/index-CWQ05PFl.js +0 -67
  59. package/dist/web/assets/index-J-AWt_cW.css +0 -1
@@ -1,4 +1,4 @@
1
- import { $ as bCountSchema, $n as scalarAfter, $t as fileIdentitySchema, A as bDuplicateMirror, B as bEvidenceReader, Bn as validatePlan, Bt as sessionPeriodSchema, C as validateBUnit, Ct as cardsSubmitSchema, D as uncoveredBObligations, Dn as entityDictionaryVersion, Dt as privacyResolveSchema, E as bLiterals, En as cleanupImplementationVersion, Et as packageConfirmActionSchema, Ft as termTypeInfo, G as subtractBRanges, Gn as detectStatic, H as codePointLength, Ht as ApplicationError, I as bIssue, It as termTypeSchema, J as bRetainedGroupSchema, Jt as reviewFamilies, Kt as familyNeedsReview, L as bOverlaps, Ln as validateProfile, Lt as termTypes, M as bLegacyBindings, Mt as reviewTermsResultSchema, N as bUnitFragments, Nt as termAssessmentSchema, O as indexBRanges, Ot as privacyTermKey, P as bAdoptedObligations, Pt as termOverrideValueSchema, Q as bAnchorSchema, Qt as sourceSnapshotId, R as unownedBObligations, Rn as orderProfile, Rt as deselectOutsidePeriod, S as validateBFields, St as cardsConfirmActionSchema, T as bLiteralTerms, Tt as emptyJourneyPrivacy, U as codePointSlice, Ut as UnfinishedJourneyError, V as bDigest, Vn as copyData, Vt as classificationTitleMaskSchema, W as createCodePointIndex, Wt as safeCode, X as bSessionDecisionSchema, Xn as createEntityMatcher, Xt as sourceKey, Y as bReviewSubmissionSchema, Yt as sourceGraph, Z as bTermSchema, Zt as observeSource, _ as semanticFindingSchema, _n as gapReasons, _t as hideConfirmSchema, a as reviewChunkSchema, at as journeyExceptionSchema, b as validateBReview, bn as staticDefaults, bt as journeyConfigurationSchema, c as textDigest, ct as journeyPreferenceScopeSchema, dt as nativeJourneySchema, en as inventorySchema, er as scalarBefore, et as bIdSchema, f as reviewAlignmentAuditSchema, ft as journeyGuidanceSchema, g as validateReviewAlignment, h as reviewFindingsDigest, hn as inspectionSemanticVersions, ht as journeyDescribeSchema, i as reviewBatchSchema, in as nativeSourceIdentitySchema, it as journeyDigestSchema, jt as reviewTermsInputSchema, l as validateReview, lt as journeyProjectTypeSchema, m as reviewAlignmentSchema, mn as currentDetectorVersion, mt as delegatedDecisionSchema, n as compileBFindings, nn as sourcePartSchema, nt as journeyAccessSchema, o as reviewDigest, ot as journeyIdSchema, p as reviewAlignmentInputSchema, pt as journeyInstructionInputSchema, q as bRepresentationSchema, qn as staticCategories, qt as familySelected, r as reviewBatchChunks, rt as journeyChoiceSchema, s as reviewSubmitSchema, st as journeyKindSchema, tr as defaultDetectionLimits, tt as bMethod, u as findingReferenceKey, ut as journeyWorkTypeSchema, vt as hidePlanInputSchema, w as bLiteralAdmitted, x as createBAnalysisUnits, xn as staticOptions, xt as cardAnswerActionSchema, y as validateBClassification, yn as createStaticProcessor, yt as hidePlanResourceSchema, z as bAnchorKey } from "./locate-Bn32k2se.mjs";
1
+ import { $ as bCountSchema, $n as scalarAfter, $t as fileIdentitySchema, A as bDuplicateMirror, B as bEvidenceReader, Bn as validatePlan, Bt as sessionPeriodSchema, C as validateBUnit, Ct as cardsSubmitSchema, D as uncoveredBObligations, Dn as entityDictionaryVersion, Dt as privacyResolveSchema, E as bLiterals, En as cleanupImplementationVersion, Et as packageConfirmActionSchema, Ft as termTypeInfo, G as subtractBRanges, Gn as detectStatic, H as codePointLength, Ht as ApplicationError, I as bIssue, It as termTypeSchema, J as bRetainedGroupSchema, Jt as reviewFamilies, Kt as familyNeedsReview, L as bOverlaps, Ln as validateProfile, Lt as termTypes, M as bLegacyBindings, Mt as reviewTermsResultSchema, N as bUnitFragments, Nt as termAssessmentSchema, O as indexBRanges, Ot as privacyTermKey, P as bAdoptedObligations, Pt as termOverrideValueSchema, Q as bAnchorSchema, Qt as sourceSnapshotId, R as unownedBObligations, Rn as orderProfile, Rt as deselectOutsidePeriod, S as validateBFields, St as cardsConfirmActionSchema, T as bLiteralTerms, Tt as emptyJourneyPrivacy, U as codePointSlice, Ut as UnfinishedJourneyError, V as bDigest, Vn as copyData, Vt as classificationTitleMaskSchema, W as createCodePointIndex, Wt as safeCode, X as bSessionDecisionSchema, Xn as createEntityMatcher, Xt as sourceKey, Y as bReviewSubmissionSchema, Yt as sourceGraph, Z as bTermSchema, Zt as observeSource, _ as semanticFindingSchema, _n as gapReasons, _t as hideConfirmSchema, a as reviewChunkSchema, at as journeyExceptionSchema, b as validateBReview, bn as staticDefaults, bt as journeyConfigurationSchema, c as textDigest, ct as journeyPreferenceScopeSchema, dt as nativeJourneySchema, en as inventorySchema, er as scalarBefore, et as bIdSchema, f as reviewAlignmentAuditSchema, ft as journeyGuidanceSchema, g as validateReviewAlignment, h as reviewFindingsDigest, hn as inspectionSemanticVersions, ht as journeyDescribeSchema, i as reviewBatchSchema, in as nativeSourceIdentitySchema, it as journeyDigestSchema, jt as reviewTermsInputSchema, l as validateReview, lt as journeyProjectTypeSchema, m as reviewAlignmentSchema, mn as currentDetectorVersion, mt as delegatedDecisionSchema, n as compileBFindings, nn as sourcePartSchema, nt as journeyAccessSchema, o as reviewDigest, ot as journeyIdSchema, p as reviewAlignmentInputSchema, pt as journeyInstructionInputSchema, q as bRepresentationSchema, qn as staticCategories, qt as familySelected, r as reviewBatchChunks, rt as journeyChoiceSchema, s as reviewSubmitSchema, st as journeyKindSchema, tr as defaultDetectionLimits, tt as bMethod, u as findingReferenceKey, ut as journeyWorkTypeSchema, vt as hidePlanInputSchema, w as bLiteralAdmitted, x as createBAnalysisUnits, xn as staticOptions, xt as cardAnswerActionSchema, y as validateBClassification, yn as createStaticProcessor, yt as hidePlanResourceSchema, z as bAnchorKey } from "./locate-U3-nkird.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";
@@ -1330,8 +1330,6 @@ function mergePrivacyTerms(state, incoming) {
1330
1330
  return {
1331
1331
  ...state.privacy,
1332
1332
  terms: [...terms.values()],
1333
- cards: [],
1334
- confirmedAnswersRevision: null,
1335
1333
  packageApproval: null
1336
1334
  };
1337
1335
  }
@@ -1344,9 +1342,16 @@ function activePrivacyTerms(state) {
1344
1342
  function hasCompleteWorkDescription(work) {
1345
1343
  return work.placement === "placed" && !!work.description.trim() && work.classificationRecommendation !== null;
1346
1344
  }
1347
- /** Dropped Works are not AI-read; a Work emptied by repartition has nothing left to read. */
1345
+ /**
1346
+ * Dropped Works are not AI-read; a Work emptied by repartition has nothing left to read, and
1347
+ * roots classification has not grouped yet are read once they join a Work (E2).
1348
+ */
1348
1349
  function isSelectedWork(work) {
1349
- return work.access !== "drop" && work.rootSessionIds.length > 0;
1350
+ return work.access !== "drop" && work.rootSessionIds.length > 0 && work.placement !== "classifying";
1351
+ }
1352
+ /** Classification published some Works and is still grouping the remaining roots (E2). */
1353
+ function isClassifying(state) {
1354
+ return state.works.some((work) => work.placement === "classifying");
1350
1355
  }
1351
1356
  function selectedWorks(state) {
1352
1357
  return state.works.filter(isSelectedWork);
@@ -1365,7 +1370,7 @@ function hasCertifiedNoBatchReview(work, snapshotId) {
1365
1370
  }
1366
1371
  /** Reading completes over selected Works once the person has confirmed the scan scope. */
1367
1372
  function isReadingComplete(state) {
1368
- return state.scope.status === "confirmed" && state.works.length > 0 && selectedWorks(state).every((work) => work.status !== "pending" && work.status !== "blocked" && (work.totalBatches > 0 || hasCertifiedNoBatchReview(work, state.snapshotId)) && work.completedBatches === work.totalBatches);
1373
+ return state.scope.status === "confirmed" && state.works.length > 0 && !isClassifying(state) && selectedWorks(state).every((work) => work.status !== "pending" && work.status !== "blocked" && (work.totalBatches > 0 || hasCertifiedNoBatchReview(work, state.snapshotId)) && work.completedBatches === work.totalBatches);
1369
1374
  }
1370
1375
  /** Recompute completion after a selection or reading change without leaving a paused/send phase. */
1371
1376
  function withReadingProgress(state) {
@@ -1379,12 +1384,12 @@ function withReadingProgress(state) {
1379
1384
  }
1380
1385
  //#endregion
1381
1386
  //#region packages/application/src/journey/static-session.ts
1382
- const count$12 = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
1387
+ const count$13 = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
1383
1388
  const staticFileSchema = z.object({
1384
1389
  path: z.string().min(1),
1385
1390
  identity: fileIdentitySchema,
1386
1391
  sha256: journeyDigestSchema,
1387
- byteLength: count$12
1392
+ byteLength: count$13
1388
1393
  }).strict();
1389
1394
  /**
1390
1395
  * Track B (ADR 0172): one admitted session of the private packaging base, with every built-in
@@ -1396,7 +1401,7 @@ const staticSessionResourceSchema = z.object({
1396
1401
  kind: z.literal("static-session"),
1397
1402
  journeyId: journeyIdSchema,
1398
1403
  workId: journeyIdSchema,
1399
- inputRevision: count$12.min(1),
1404
+ inputRevision: count$13.min(1),
1400
1405
  snapshotId: journeyDigestSchema,
1401
1406
  sessionId: z.string().min(1).max(128),
1402
1407
  jobDigest: journeyDigestSchema,
@@ -1404,7 +1409,9 @@ const staticSessionResourceSchema = z.object({
1404
1409
  result: staticFileSchema,
1405
1410
  primary: staticFileSchema,
1406
1411
  companion: staticFileSchema,
1407
- masks: staticFileSchema
1412
+ masks: staticFileSchema,
1413
+ /** Model-facing image blocks this session's output leaves out; absent on older receipts. */
1414
+ imagesOmitted: count$13.optional()
1408
1415
  }).strict();
1409
1416
  const staticSessionId = (resource) => `${resource.workId}:${resource.inputRevision}:${resource.sessionId}`;
1410
1417
  /** Binds one Work's complete static base to the exact session results it was sealed from. */
@@ -1473,7 +1480,7 @@ const journeyPropagateActionSchema = z.object({
1473
1480
  }).strict();
1474
1481
  //#endregion
1475
1482
  //#region packages/application/src/journey/scope/model.ts
1476
- const count$11 = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
1483
+ const count$12 = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
1477
1484
  const safeText = z.string().trim().min(1).max(240);
1478
1485
  const journeyScopeConfirmActionSchema = z.object({ kind: z.literal("scope-confirm") }).strict();
1479
1486
  const journeyWorkTypeActionSchema = z.object({
@@ -1489,7 +1496,7 @@ const journeyWorksAccessActionSchema = z.object({
1489
1496
  /** Static-only Work facts for proposing project types and scan scope; no source bodies. */
1490
1497
  const journeyCatalogQuerySchema = z.object({
1491
1498
  journeyId: journeyIdSchema,
1492
- after: count$11.default(0),
1499
+ after: count$12.default(0),
1493
1500
  limit: z.number().int().min(1).max(100).default(50),
1494
1501
  /** Bounded frozen root routing metadata for classification helpers. */
1495
1502
  includeClassificationRouting: z.boolean().optional(),
@@ -1500,23 +1507,27 @@ const journeyCatalogQuerySchema = z.object({
1500
1507
  path: ["includeProjectEvidence"]
1501
1508
  });
1502
1509
  const workspaceKinds = z.object({
1503
- checkout: count$11,
1504
- worktree: count$11,
1505
- folder: count$11,
1506
- scratch: count$11,
1507
- temp: count$11,
1508
- home: count$11,
1509
- unresolved: count$11
1510
+ checkout: count$12,
1511
+ worktree: count$12,
1512
+ folder: count$12,
1513
+ scratch: count$12,
1514
+ temp: count$12,
1515
+ home: count$12,
1516
+ unresolved: count$12
1510
1517
  }).strict();
1511
1518
  const day = z.string().regex(/^\d{4}-\d{2}-\d{2}$/u);
1512
1519
  const journeyCatalogWorkSchema = z.object({
1513
1520
  id: journeyIdSchema,
1514
1521
  projectName: safeText,
1515
- placement: z.enum(["placed", "unsorted"]),
1522
+ placement: z.enum([
1523
+ "placed",
1524
+ "unsorted",
1525
+ "classifying"
1526
+ ]),
1516
1527
  access: journeyAccessSchema,
1517
1528
  projectType: journeyWorkTypeSchema.nullable(),
1518
- roots: count$11,
1519
- children: count$11,
1529
+ roots: count$12,
1530
+ children: count$12,
1520
1531
  firstActivity: day.nullable(),
1521
1532
  lastActivity: day.nullable(),
1522
1533
  workspaces: workspaceKinds,
@@ -1530,7 +1541,7 @@ const classificationRootSchema = z.object({
1530
1541
  workspaceKind: z.string().min(1).max(40),
1531
1542
  harness: z.enum(["claude", "codex"]),
1532
1543
  titleAvailable: z.boolean(),
1533
- memberCount: count$11,
1544
+ memberCount: count$12,
1534
1545
  titles: z.array(safeText).max(3),
1535
1546
  projectEvidence: z.object({
1536
1547
  status: z.enum([
@@ -1539,7 +1550,7 @@ const classificationRootSchema = z.object({
1539
1550
  "insufficient"
1540
1551
  ]),
1541
1552
  incomplete: z.boolean(),
1542
- ignored: count$11,
1553
+ ignored: count$12,
1543
1554
  workspace: z.object({
1544
1555
  kind: safeText,
1545
1556
  name: safeText.nullable()
@@ -1547,10 +1558,10 @@ const classificationRootSchema = z.object({
1547
1558
  repositories: z.array(z.object({
1548
1559
  id: z.string().regex(/^[a-f0-9]{64}$/u),
1549
1560
  name: safeText,
1550
- references: count$11,
1551
- reads: count$11,
1552
- changes: count$11,
1553
- commands: count$11
1561
+ references: count$12,
1562
+ reads: count$12,
1563
+ changes: count$12,
1564
+ commands: count$12
1554
1565
  }).strict()).max(8)
1555
1566
  }).strict().optional()
1556
1567
  }).strict();
@@ -1575,11 +1586,11 @@ const classificationAssignmentSchema = z.object({
1575
1586
  }).strict();
1576
1587
  const journeyCatalogSchema = z.object({
1577
1588
  journeyId: journeyIdSchema,
1578
- revision: count$11,
1589
+ revision: count$12,
1579
1590
  scope: z.enum(["pending", "confirmed"]),
1580
- total: count$11,
1591
+ total: count$12,
1581
1592
  works: z.array(journeyCatalogWorkSchema).max(100),
1582
- next: count$11.nullable(),
1593
+ next: count$12.nullable(),
1583
1594
  classificationRouting: z.object({
1584
1595
  knownProjects: z.array(classificationKnownProjectSchema),
1585
1596
  unresolvedRoots: z.array(classificationRootSchema),
@@ -1589,7 +1600,7 @@ const journeyCatalogSchema = z.object({
1589
1600
  /** Model project-type suggestions; explicit and delegated types are never overwritten. */
1590
1601
  const journeyClassifySchema = z.object({
1591
1602
  journeyId: journeyIdSchema,
1592
- expectedRevision: count$11,
1603
+ expectedRevision: count$12,
1593
1604
  idempotencyKey: journeyIdSchema,
1594
1605
  items: z.array(z.object({
1595
1606
  workId: journeyIdSchema,
@@ -1808,7 +1819,45 @@ function assertJourneyPrivacyReady(state, packaging = false) {
1808
1819
  assertJourneyStaticReady(state);
1809
1820
  if (packaging && state.privacy.packageApproval !== privacyDecisionDigest(state)) throw new ApplicationError("CONFIRMATION_REQUIRED");
1810
1821
  }
1822
+ /** Card batches start once the scan scope is confirmed (D3); they need not wait for reading. */
1823
+ function assertCardsAllowed(state) {
1824
+ if (!state.consent || state.scope.status !== "confirmed") throw new ApplicationError("SCOPE_NOT_READY");
1825
+ }
1826
+ /**
1827
+ * D3: a batch covers only Pending values no card covers yet. Values added to an existing card
1828
+ * take its answer at once when the person already answered it.
1829
+ */
1830
+ function appendDecisionCards(state, input) {
1831
+ assertCardsAllowed(state);
1832
+ const existing = new Set(state.privacy.cards.map((card) => card.id));
1833
+ const coveredBefore = new Set(state.privacy.cards.flatMap((card) => card.termKeys));
1834
+ const open = new Set(activePrivacyTerms(state).filter((term) => term.disposition === "pending").map(privacyTermKey).filter((key) => !coveredBefore.has(key)));
1835
+ const extend = input.extend ?? [];
1836
+ const covered = [...input.cards.flatMap((card) => card.termKeys), ...extend.flatMap((item) => item.termKeys)];
1837
+ if (!covered.length || state.privacy.cards.length + input.cards.length > 20 || new Set(input.cards.map((card) => card.id)).size !== input.cards.length || input.cards.some((card) => existing.has(card.id)) || new Set(extend.map((item) => item.cardId)).size !== extend.length || extend.some((item) => !existing.has(item.cardId)) || new Set(covered).size !== covered.length || covered.some((key) => !open.has(key))) throw new ApplicationError("INVALID_SELECTION");
1838
+ const additions = new Map(extend.map((item) => [item.cardId, item.termKeys]));
1839
+ return applyCardAnswers({
1840
+ ...retirePrivacyArtifacts(state),
1841
+ privacy: {
1842
+ ...state.privacy,
1843
+ cards: [...state.privacy.cards.map((card) => {
1844
+ const added = additions.get(card.id);
1845
+ return added ? {
1846
+ ...card,
1847
+ termKeys: [...card.termKeys, ...added]
1848
+ } : card;
1849
+ }), ...input.cards.map((card) => ({
1850
+ ...card,
1851
+ answer: null
1852
+ }))],
1853
+ confirmedAnswersRevision: input.cards.length ? null : state.privacy.confirmedAnswersRevision,
1854
+ packageApproval: null
1855
+ }
1856
+ });
1857
+ }
1811
1858
  function publishDecisionCards(state, input) {
1859
+ if (input.mode === "append") return appendDecisionCards(state, input);
1860
+ if (input.extend?.length) throw new ApplicationError("INVALID_SELECTION");
1812
1861
  assertJourneyScanned(state);
1813
1862
  const pending = new Set(activePrivacyTerms(state).filter((term) => term.disposition === "pending").map(privacyTermKey));
1814
1863
  const covered = input.cards.flatMap((card) => card.termKeys);
@@ -1838,19 +1887,45 @@ function resolvePrivacyTerms(state, input) {
1838
1887
  const resolutions = new Map(input.resolutions.map((term) => [privacyTermKey(term), term]));
1839
1888
  const pending = new Set(activePrivacyTerms(state).filter((term) => term.disposition === "pending").map(privacyTermKey));
1840
1889
  if (resolutions.size !== input.resolutions.length || [...resolutions.keys()].some((key) => !pending.has(key))) throw new ApplicationError("INVALID_SELECTION");
1841
- let terms = state.privacy.terms.map((term) => {
1890
+ const terms = state.privacy.terms.map((term) => {
1842
1891
  const resolution = resolutions.get(privacyTermKey(term));
1843
1892
  return resolution ? {
1844
1893
  ...term,
1845
1894
  ...resolution
1846
1895
  } : term;
1847
1896
  });
1848
- const active = activePrivacyTerms({
1897
+ for (const same of Map.groupBy(activePrivacyTerms({
1849
1898
  ...state,
1850
1899
  privacy: {
1851
1900
  ...state.privacy,
1852
1901
  terms
1853
1902
  }
1903
+ }), (term) => term.value.normalize("NFC")).values()) if (same.some((term) => term.disposition === "pending") && input.resolutions.some((item) => item.value.normalize("NFC") === same[0]?.value.normalize("NFC"))) throw new ApplicationError("INVALID_SELECTION");
1904
+ return {
1905
+ ...retirePrivacyArtifacts(state),
1906
+ privacy: {
1907
+ ...state.privacy,
1908
+ terms: normalizeValues(state, terms),
1909
+ packageApproval: null
1910
+ }
1911
+ };
1912
+ }
1913
+ /** Keys of answered cards that took one option, leaving out values the person unticked. */
1914
+ function answeredKeys(state, optionId) {
1915
+ return new Set(state.privacy.cards.flatMap((card) => {
1916
+ if (!card.answer) return [];
1917
+ const excluded = new Set(card.answer.excludedTermKeys ?? []);
1918
+ return card.answer.optionId === optionId ? card.termKeys.filter((key) => !excluded.has(key)) : [...excluded];
1919
+ }));
1920
+ }
1921
+ /** One NFC value has one outcome across term types, cards and per-value rules. */
1922
+ function normalizeValues(state, input) {
1923
+ const active = activePrivacyTerms({
1924
+ ...state,
1925
+ privacy: {
1926
+ ...state.privacy,
1927
+ terms: input
1928
+ }
1854
1929
  });
1855
1930
  const overrides = /* @__PURE__ */ new Map();
1856
1931
  for (const item of state.valueOverrides ?? []) {
@@ -1858,7 +1933,7 @@ function resolvePrivacyTerms(state, input) {
1858
1933
  if (!overrides.has(value)) overrides.set(value, item);
1859
1934
  }
1860
1935
  const cardValues = (optionId) => {
1861
- const keys = new Set(state.privacy.cards.flatMap((card) => card.answer?.optionId === optionId ? card.termKeys : []));
1936
+ const keys = answeredKeys(state, optionId);
1862
1937
  return new Set(state.privacy.terms.filter((term) => keys.has(privacyTermKey(term))).map((term) => term.value.normalize("NFC")));
1863
1938
  };
1864
1939
  const hideCardValues = cardValues("hide");
@@ -1866,7 +1941,6 @@ function resolvePrivacyTerms(state, input) {
1866
1941
  const ownNames = workProjectNames(state);
1867
1942
  const normalized = /* @__PURE__ */ new Map();
1868
1943
  for (const same of Map.groupBy(active, (term) => term.value.normalize("NFC")).values()) {
1869
- if (same.some((term) => term.disposition === "pending") && input.resolutions.some((item) => item.value.normalize("NFC") === same[0]?.value.normalize("NFC"))) throw new ApplicationError("INVALID_SELECTION");
1870
1944
  if (same.some((term) => term.disposition === "pending")) continue;
1871
1945
  const forcedHidden = same.some((term) => !termTypeInfo[term.type].asked);
1872
1946
  const override = overrides.get(same[0]?.value.normalize("NFC") ?? "");
@@ -1879,51 +1953,79 @@ function resolvePrivacyTerms(state, input) {
1879
1953
  reason: disposition === "hidden" && term.disposition !== "hidden" ? hideCard && !same.some((item) => item.disposition === "hidden") ? "A Hide card answer covering this value takes precedence over Keep." : "A Hidden judgment for this NFC keyword takes precedence across term types." : ownKeep && term.disposition !== "keep" ? OWN_PROJECT_KEEP_REASON : term.reason
1880
1954
  });
1881
1955
  }
1882
- terms = terms.map((term) => {
1956
+ return input.map((term) => {
1883
1957
  const result = normalized.get(privacyTermKey(term));
1884
1958
  return result ? {
1885
1959
  ...term,
1886
1960
  ...result
1887
1961
  } : term;
1888
1962
  });
1963
+ }
1964
+ /**
1965
+ * The CLI applies card answers itself (D3): Hide makes every covered value Hidden and Keep keeps
1966
+ * it, an unticked value takes the other option, then one value gets one outcome.
1967
+ */
1968
+ function applyCardAnswers(state) {
1969
+ if (!state.privacy.cards.some((card) => card.answer)) return state;
1970
+ const hide = answeredKeys(state, "hide");
1971
+ const keep = answeredKeys(state, "keep");
1972
+ const terms = state.privacy.terms.map((term) => {
1973
+ const key = privacyTermKey(term);
1974
+ if (hide.has(key) && term.disposition !== "hidden") return {
1975
+ ...term,
1976
+ disposition: "hidden",
1977
+ reason: "Hidden by your decision card answer."
1978
+ };
1979
+ if (keep.has(key) && !hide.has(key) && term.disposition !== "keep") return {
1980
+ ...term,
1981
+ disposition: "keep",
1982
+ reason: "Kept by your decision card answer."
1983
+ };
1984
+ return term;
1985
+ });
1889
1986
  return {
1890
- ...retirePrivacyArtifacts(state),
1987
+ ...state,
1891
1988
  privacy: {
1892
1989
  ...state.privacy,
1893
- terms,
1894
- packageApproval: null
1990
+ terms: normalizeValues(state, terms)
1895
1991
  }
1896
1992
  };
1897
1993
  }
1898
1994
  function respondPrivacy(state, action, source) {
1899
1995
  if (action.kind === "card-answer") {
1900
- assertJourneyScanned(state);
1996
+ assertCardsAllowed(state);
1997
+ if (state.phase === "sending" || state.phase === "completed") throw new ApplicationError("INVALID_TRANSITION");
1901
1998
  const card = state.privacy.cards.find((item) => item.id === action.cardId);
1902
1999
  const option = card?.options.find((item) => item.id === action.optionId);
1903
2000
  if (!card || !option) throw new ApplicationError("UNKNOWN_ITEM");
2001
+ const excluded = action.excludedTermKeys ?? [];
1904
2002
  const keys = new Set(card.termKeys);
1905
- return {
2003
+ if (new Set(excluded).size !== excluded.length || excluded.some((key) => !keys.has(key))) throw new ApplicationError("INVALID_SELECTION");
2004
+ const cards = state.privacy.cards.map((item) => item.id !== card.id ? item : {
2005
+ ...item,
2006
+ answer: {
2007
+ optionId: option.id,
2008
+ rule: [option.rule, action.rule?.trim()].filter(Boolean).join("\n"),
2009
+ additionalRule: action.rule?.trim() ?? "",
2010
+ remember: action.remember,
2011
+ ...excluded.length ? { excludedTermKeys: excluded } : {}
2012
+ }
2013
+ });
2014
+ const answersRevision = state.privacy.answersRevision + 1;
2015
+ return applyCardAnswers({
1906
2016
  ...retirePrivacyArtifacts(state),
1907
2017
  privacy: {
1908
2018
  ...state.privacy,
1909
- cards: state.privacy.cards.map((item) => item.id !== card.id ? item : {
1910
- ...item,
1911
- answer: {
1912
- optionId: option.id,
1913
- rule: [option.rule, action.rule?.trim()].filter(Boolean).join("\n"),
1914
- additionalRule: action.rule?.trim() ?? "",
1915
- remember: action.remember
1916
- }
1917
- }),
2019
+ cards,
1918
2020
  terms: state.privacy.terms.map((term) => keys.has(privacyTermKey(term)) ? {
1919
2021
  ...term,
1920
2022
  disposition: "pending"
1921
2023
  } : term),
1922
- answersRevision: state.privacy.answersRevision + 1,
1923
- confirmedAnswersRevision: null,
2024
+ answersRevision,
2025
+ confirmedAnswersRevision: cards.every((item) => item.answer) ? answersRevision : null,
1924
2026
  packageApproval: null
1925
2027
  }
1926
- };
2028
+ });
1927
2029
  }
1928
2030
  if (action.kind === "cards-confirm") {
1929
2031
  assertJourneyScanned(state);
@@ -1951,12 +2053,12 @@ function respondPrivacy(state, action, source) {
1951
2053
  }
1952
2054
  //#endregion
1953
2055
  //#region packages/application/src/journey/scope/classification.ts
1954
- const count$10 = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
2056
+ const count$11 = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
1955
2057
  const classificationCursorSchema = z.object({
1956
2058
  snapshotId: journeyDigestSchema,
1957
- inputRevision: count$10,
2059
+ inputRevision: count$11,
1958
2060
  rootSessionId: z.string().min(1).max(128).optional(),
1959
- partIndex: count$10,
2061
+ partIndex: count$11,
1960
2062
  afterOrdinal: z.number().int().min(-1)
1961
2063
  }).strict();
1962
2064
  /** Private frozen content; reading it never records privacy-review coverage. */
@@ -1968,7 +2070,7 @@ const journeyClassificationReadSchema = z.object({
1968
2070
  }).strict();
1969
2071
  const journeyClassificationSubmitSchema = z.object({
1970
2072
  journeyId: journeyIdSchema,
1971
- expectedRevision: count$10,
2073
+ expectedRevision: count$11,
1972
2074
  idempotencyKey: journeyIdSchema,
1973
2075
  items: z.array(z.object({
1974
2076
  projectName: z.string().trim().min(1).max(240),
@@ -1979,7 +2081,17 @@ const journeyClassificationSubmitSchema = z.object({
1979
2081
  access: journeyAccessSchema,
1980
2082
  reason: z.string().trim().min(1).max(200)
1981
2083
  }).strict()
1982
- }).strict()).min(1).max(1e3)
2084
+ }).strict()).min(1).max(1e3),
2085
+ /**
2086
+ * E2: roots classification has not grouped yet. They wait in one unread Work while the
2087
+ * listed Works are confirmed and read; a later submission without them completes it.
2088
+ */
2089
+ pendingRootSessionIds: z.array(z.string().min(1).max(128)).max(1e4).optional(),
2090
+ /**
2091
+ * While roots are still being grouped, scan writes keep moving the revision: a later
2092
+ * submission is bound to the classification it replaces instead (E2).
2093
+ */
2094
+ expectedClassificationRevision: count$11.optional()
1983
2095
  }).strict();
1984
2096
  const journeyClassificationSessionsSchema = z.object({
1985
2097
  journeyId: journeyIdSchema,
@@ -1987,7 +2099,7 @@ const journeyClassificationSessionsSchema = z.object({
1987
2099
  rootsOnly: z.boolean().optional(),
1988
2100
  includeProjectEvidence: z.boolean().optional(),
1989
2101
  projectEvidenceRootSessionIds: z.array(z.string().min(1).max(128)).min(1).max(100).optional(),
1990
- after: count$10.default(0),
2102
+ after: count$11.default(0),
1991
2103
  limit: z.number().int().min(1).max(100).default(50)
1992
2104
  }).strict();
1993
2105
  //#endregion
@@ -2392,12 +2504,12 @@ function verifiedScanGitSeeds(resource, snapshotId, roots) {
2392
2504
  }
2393
2505
  //#endregion
2394
2506
  //#region packages/application/src/journey/scan-session.ts
2395
- const count$9 = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
2507
+ const count$10 = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
2396
2508
  const scanFileSchema = z.object({
2397
2509
  path: z.string().min(1),
2398
2510
  identity: fileIdentitySchema,
2399
2511
  sha256: journeyDigestSchema,
2400
- byteLength: count$9
2512
+ byteLength: count$10
2401
2513
  }).strict();
2402
2514
  /**
2403
2515
  * Track A source-bound prose (`file`) with built-in static protection spans; no delivery archive
@@ -2413,13 +2525,13 @@ const sessionScanInputSchema = z.object({
2413
2525
  native: nativeSourceIdentitySchema,
2414
2526
  facts: z.object({
2415
2527
  representation: z.enum(["jsonl", "jsonl.zst"]),
2416
- byteLength: count$9,
2528
+ byteLength: count$10,
2417
2529
  sha256: journeyDigestSchema
2418
2530
  }).strict()
2419
2531
  }).strict()),
2420
- recordCount: count$9,
2421
- fieldCount: count$9,
2422
- inputUtf16: count$9,
2532
+ recordCount: count$10,
2533
+ fieldCount: count$10,
2534
+ inputUtf16: count$10,
2423
2535
  mainReviewVerified: z.literal(true),
2424
2536
  emptyReviewVerified: z.boolean()
2425
2537
  }).strict().refine((input) => new Set(input.sources.map((source) => source.sourceId)).size === input.sources.length);
@@ -2427,7 +2539,7 @@ const scanSessionResourceSchema = z.object({
2427
2539
  kind: z.literal("scan-session"),
2428
2540
  journeyId: journeyIdSchema,
2429
2541
  workId: journeyIdSchema,
2430
- inputRevision: count$9.min(1),
2542
+ inputRevision: count$10.min(1),
2431
2543
  snapshotId: journeyDigestSchema,
2432
2544
  configurationDigest: journeyDigestSchema,
2433
2545
  rootSessionId: z.string().min(1),
@@ -2446,7 +2558,7 @@ function scanPreparationDigest(resources) {
2446
2558
  const scanBatchBinding = {
2447
2559
  journeyId: journeyIdSchema,
2448
2560
  workId: journeyIdSchema,
2449
- inputRevision: count$9.min(1),
2561
+ inputRevision: count$10.min(1),
2450
2562
  snapshotId: journeyDigestSchema,
2451
2563
  configurationDigest: journeyDigestSchema
2452
2564
  };
@@ -3461,7 +3573,7 @@ const reviewProgressSchema = z.array(z.object({
3461
3573
  }).strict());
3462
3574
  //#endregion
3463
3575
  //#region packages/application/src/journey/review/session-schema.ts
3464
- const count$8 = z.number().int().nonnegative();
3576
+ const count$9 = z.number().int().nonnegative();
3465
3577
  const sessionReviewInputSchema = z.object({
3466
3578
  journeyId: journeyIdSchema,
3467
3579
  workId: journeyIdSchema,
@@ -3482,7 +3594,7 @@ const sessionReviewResourceSchema = z.object({
3482
3594
  workId: journeyIdSchema,
3483
3595
  sessionId: z.string().min(1).max(128),
3484
3596
  snapshotId: journeyDigestSchema,
3485
- inputRevision: count$8.positive(),
3597
+ inputRevision: count$9.positive(),
3486
3598
  requestHash: journeyDigestSchema,
3487
3599
  bindingDigest: journeyDigestSchema,
3488
3600
  at: z.iso.datetime(),
@@ -3496,8 +3608,8 @@ const sessionReviewResourceSchema = z.object({
3496
3608
  issues: z.array(reviewIssueSchema),
3497
3609
  requiresSemantic: z.boolean(),
3498
3610
  usefulness: sessionUsefulnessSchema,
3499
- totalCodePoints: count$8,
3500
- reviewedCodePoints: count$8
3611
+ totalCodePoints: count$9,
3612
+ reviewedCodePoints: count$9
3501
3613
  }).strict();
3502
3614
  const sessionRereadInputSchema = z.object({
3503
3615
  journeyId: journeyIdSchema,
@@ -3506,8 +3618,8 @@ const sessionRereadInputSchema = z.object({
3506
3618
  anchors: z.array(z.object({
3507
3619
  fieldId: z.string().min(1),
3508
3620
  fieldHash: journeyDigestSchema,
3509
- start: count$8,
3510
- end: count$8
3621
+ start: count$9,
3622
+ end: count$9
3511
3623
  }).strict()).min(1).max(128)
3512
3624
  }).strict();
3513
3625
  const sessionRereadResourceSchema = z.object({
@@ -3516,7 +3628,7 @@ const sessionRereadResourceSchema = z.object({
3516
3628
  journeyId: journeyIdSchema,
3517
3629
  workId: journeyIdSchema,
3518
3630
  sessionId: z.string().min(1).max(128),
3519
- inputRevision: count$8.positive(),
3631
+ inputRevision: count$9.positive(),
3520
3632
  snapshotId: journeyDigestSchema,
3521
3633
  sessionReviewId: journeyIdSchema,
3522
3634
  bindingDigest: journeyDigestSchema,
@@ -3534,8 +3646,8 @@ const sessionReconcileInputSchema = z.object({
3534
3646
  alignment: reviewAlignmentSchema
3535
3647
  }).strict();
3536
3648
  const retainedReviewAnchorSchema = bAnchorSchema.extend({
3537
- utf16Start: count$8,
3538
- utf16End: count$8,
3649
+ utf16Start: count$9,
3650
+ utf16End: count$9,
3539
3651
  owned: z.boolean()
3540
3652
  }).strict();
3541
3653
  const sessionOverlaySchema = z.object({
@@ -3549,7 +3661,7 @@ const sessionReconciliationResourceSchema = z.object({
3549
3661
  journeyId: journeyIdSchema,
3550
3662
  workId: journeyIdSchema,
3551
3663
  sessionId: z.string().min(1).max(128),
3552
- inputRevision: count$8.positive(),
3664
+ inputRevision: count$9.positive(),
3553
3665
  snapshotId: journeyDigestSchema,
3554
3666
  sessionReviewId: journeyIdSchema,
3555
3667
  bindingDigest: journeyDigestSchema,
@@ -3577,8 +3689,8 @@ const sessionReviewQuerySchema = z.object({
3577
3689
  workId: journeyIdSchema.optional(),
3578
3690
  sessionId: z.string().min(1).max(128).optional(),
3579
3691
  sessionReviewId: journeyIdSchema.optional(),
3580
- afterHit: count$8.default(0),
3581
- limit: count$8.positive().max(500).default(100)
3692
+ afterHit: count$9.default(0),
3693
+ limit: count$9.positive().max(500).default(100)
3582
3694
  }).strict();
3583
3695
  const sessionReviewStatusSchema = z.object({
3584
3696
  complete: z.boolean(),
@@ -3594,8 +3706,8 @@ const sessionReviewStatusSchema = z.object({
3594
3706
  requiresHumanDecision: z.boolean(),
3595
3707
  requiresSemantic: z.boolean(),
3596
3708
  issues: z.array(reviewIssueSchema),
3597
- totalCodePoints: count$8,
3598
- reviewedCodePoints: count$8,
3709
+ totalCodePoints: count$9,
3710
+ reviewedCodePoints: count$9,
3599
3711
  reconciliationId: journeyIdSchema.nullable(),
3600
3712
  /** ADR 0086: a read unit of the session suggests excluding it; advice, never a gate. */
3601
3713
  suggestExclude: z.boolean(),
@@ -3603,8 +3715,8 @@ const sessionReviewStatusSchema = z.object({
3603
3715
  reason: z.string().min(1).max(2e3).nullable()
3604
3716
  }).strict()),
3605
3717
  hits: z.array(sessionReviewHitSchema),
3606
- nextHit: count$8.nullable(),
3607
- totalHits: count$8
3718
+ nextHit: count$9.nullable(),
3719
+ totalHits: count$9
3608
3720
  }).strict();
3609
3721
  const sessionReviewResultSchema = z.object({
3610
3722
  preparation: sessionReviewResourceSchema,
@@ -3688,13 +3800,13 @@ const metadataFieldsSchema = z.object({
3688
3800
  }).strict();
3689
3801
  //#endregion
3690
3802
  //#region packages/application/src/journey/placement/routing-schema.ts
3691
- const count$7 = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
3803
+ const count$8 = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
3692
3804
  const bucket = z.object({
3693
3805
  complete: z.boolean(),
3694
- total: count$7,
3806
+ total: count$8,
3695
3807
  repositories: z.array(z.object({
3696
3808
  id: z.string().min(1),
3697
- count: count$7.min(1)
3809
+ count: count$8.min(1)
3698
3810
  }).strict())
3699
3811
  }).strict();
3700
3812
  const placementSignalsSchema = z.object({
@@ -3712,8 +3824,8 @@ const cheapPlacementSchema = z.object({
3712
3824
  "name"
3713
3825
  ]),
3714
3826
  confidence: z.enum(["high", "medium"]),
3715
- matched: count$7.min(1),
3716
- total: count$7.min(1),
3827
+ matched: count$8.min(1),
3828
+ total: count$8.min(1),
3717
3829
  otherRepositoryIds: z.array(z.string())
3718
3830
  }).strict();
3719
3831
  const sortingResourceSchema = z.object({
@@ -3734,26 +3846,26 @@ const sortingResourceSchema = z.object({
3734
3846
  const sortingApplySchema = z.object({
3735
3847
  journeyId: z.uuid(),
3736
3848
  sessionId: z.string().min(1).max(128),
3737
- expectedRevision: count$7,
3849
+ expectedRevision: count$8,
3738
3850
  idempotencyKey: z.uuid()
3739
3851
  }).strict();
3740
3852
  /** Preparation moves identified failing roots of one pending Work into its blocked Work. */
3741
3853
  const journeyIsolateSchema = z.object({
3742
3854
  journeyId: z.uuid(),
3743
3855
  workId: z.uuid(),
3744
- inputRevision: count$7.min(1),
3856
+ inputRevision: count$8.min(1),
3745
3857
  roots: z.array(z.object({
3746
3858
  sessionId: z.string().min(1).max(128),
3747
3859
  code: z.string().regex(/^[A-Z_]{3,80}$/u)
3748
3860
  }).strict()).min(1).max(1e5),
3749
- expectedRevision: count$7,
3861
+ expectedRevision: count$8,
3750
3862
  idempotencyKey: z.uuid()
3751
3863
  }).strict();
3752
3864
  const placement = z.object({
3753
3865
  workId: z.uuid(),
3754
3866
  sessionId: z.string().min(1).max(128),
3755
- inputRevision: count$7.min(1),
3756
- throughEvent: count$7,
3867
+ inputRevision: count$8.min(1),
3868
+ throughEvent: count$8,
3757
3869
  contextDigest: z.string().regex(/^[a-f0-9]{64}$/u),
3758
3870
  decision: z.enum([
3759
3871
  "join",
@@ -3769,13 +3881,13 @@ const placement = z.object({
3769
3881
  }).strict();
3770
3882
  const journeyPlaceSchema = z.object({
3771
3883
  journeyId: z.uuid(),
3772
- expectedRevision: count$7,
3884
+ expectedRevision: count$8,
3773
3885
  idempotencyKey: z.uuid(),
3774
3886
  placements: z.array(placement).min(1).max(1e3)
3775
3887
  }).strict();
3776
3888
  //#endregion
3777
3889
  //#region packages/application/src/journey/scope/progress.ts
3778
- const count$6 = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
3890
+ const count$7 = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
3779
3891
  const ids = z.array(z.string().min(1).max(128)).max(1e5).refine((values) => new Set(values).size === values.length);
3780
3892
  const journeyClassificationProgressSchema = z.object({
3781
3893
  journeyId: journeyIdSchema,
@@ -3783,8 +3895,8 @@ const journeyClassificationProgressSchema = z.object({
3783
3895
  id: z.literal("current"),
3784
3896
  snapshotId: journeyDigestSchema,
3785
3897
  inputFingerprint: journeyDigestSchema,
3786
- baselineRevision: count$6,
3787
- proposalRevision: count$6.nullable(),
3898
+ baselineRevision: count$7,
3899
+ proposalRevision: count$7.nullable(),
3788
3900
  stage: z.enum(["classification", "proposal"]),
3789
3901
  status: z.enum([
3790
3902
  "running",
@@ -3794,7 +3906,7 @@ const journeyClassificationProgressSchema = z.object({
3794
3906
  ]),
3795
3907
  startedAt: z.iso.datetime(),
3796
3908
  updatedAt: z.iso.datetime(),
3797
- elapsedMs: count$6,
3909
+ elapsedMs: count$7,
3798
3910
  rootIds: ids,
3799
3911
  completedRootIds: ids,
3800
3912
  groupedRootIds: ids,
@@ -4057,7 +4169,7 @@ const journeyPolicyRespondSchema = z.object({
4057
4169
  }).strict();
4058
4170
  //#endregion
4059
4171
  //#region packages/application/src/journey/search.ts
4060
- const count$5 = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
4172
+ const count$6 = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
4061
4173
  const term = z.string().min(1).max(1024).refine((value) => Buffer.byteLength(value) <= 1024 && !/[\0\r\n]/u.test(value));
4062
4174
  const journeySearchSchema = z.object({
4063
4175
  journeyId: journeyIdSchema,
@@ -4071,11 +4183,11 @@ const journeySearchResultSchema = z.object({
4071
4183
  binding: z.object({
4072
4184
  journeyId: journeyIdSchema,
4073
4185
  snapshotId: journeyDigestSchema,
4074
- revision: count$5,
4186
+ revision: count$6,
4075
4187
  scopeDigest: journeyDigestSchema,
4076
4188
  outputs: z.array(z.object({
4077
4189
  workId: journeyIdSchema,
4078
- outputRevision: count$5,
4190
+ outputRevision: count$6,
4079
4191
  sha256: journeyDigestSchema
4080
4192
  }).strict())
4081
4193
  }).strict(),
@@ -4092,10 +4204,10 @@ const journeySearchResultSchema = z.object({
4092
4204
  terms: z.array(z.object({
4093
4205
  id: z.string(),
4094
4206
  tried: z.array(z.string()),
4095
- sentMatches: count$5.nullable(),
4096
- originalMatches: count$5.nullable(),
4097
- sentSessions: count$5.nullable(),
4098
- originalSessions: count$5.nullable()
4207
+ sentMatches: count$6.nullable(),
4208
+ originalMatches: count$6.nullable(),
4209
+ sentSessions: count$6.nullable(),
4210
+ originalSessions: count$6.nullable()
4099
4211
  }).strict()),
4100
4212
  hits: z.array(z.object({
4101
4213
  termId: z.string(),
@@ -4111,16 +4223,16 @@ const journeySearchResultSchema = z.object({
4111
4223
  archiveSessionId: z.string().optional(),
4112
4224
  sessionId: z.string().optional(),
4113
4225
  sourcePartId: z.string().optional(),
4114
- recordIndex: count$5,
4226
+ recordIndex: count$6,
4115
4227
  fieldId: z.string(),
4116
- line: count$5
4228
+ line: count$6
4117
4229
  }).strict(),
4118
- occurrences: count$5,
4230
+ occurrences: count$6,
4119
4231
  modelContext: z.string().max(4096).optional(),
4120
4232
  match: z.object({
4121
- variantIndex: count$5.max(7),
4122
- start: count$5,
4123
- end: count$5
4233
+ variantIndex: count$6.max(7),
4234
+ start: count$6,
4235
+ end: count$6
4124
4236
  }).strict().optional()
4125
4237
  }).strict()),
4126
4238
  failures: z.array(z.object({
@@ -4143,7 +4255,7 @@ const journeySearchResultSchema = z.object({
4143
4255
  }));
4144
4256
  const journeySearchSaveSchema = z.object({
4145
4257
  journeyId: journeyIdSchema,
4146
- expectedRevision: count$5,
4258
+ expectedRevision: count$6,
4147
4259
  idempotencyKey: journeyIdSchema,
4148
4260
  result: journeySearchResultSchema
4149
4261
  }).strict();
@@ -4180,10 +4292,10 @@ const hideFinishSchema = z.object({
4180
4292
  }).strict();
4181
4293
  //#endregion
4182
4294
  //#region packages/application/src/journey/placement/context-schema.ts
4183
- const count$4 = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
4295
+ const count$5 = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
4184
4296
  const cursor = z.object({
4185
- inputRevision: count$4.min(1),
4186
- throughEvent: count$4,
4297
+ inputRevision: count$5.min(1),
4298
+ throughEvent: count$5,
4187
4299
  afterOrdinal: z.number().int().min(-1)
4188
4300
  }).strict();
4189
4301
  const journeyContextQuerySchema = z.object({
@@ -4196,14 +4308,14 @@ const journeyContextSchema = z.object({
4196
4308
  journeyId: z.uuid(),
4197
4309
  workId: z.uuid(),
4198
4310
  sessionId: z.string().min(1).max(128).nullable(),
4199
- inputRevision: count$4.min(1),
4311
+ inputRevision: count$5.min(1),
4200
4312
  explicitTitleId: z.uuid().nullable(),
4201
4313
  titleReview: z.object({
4202
4314
  id: z.uuid(),
4203
4315
  text: z.string().min(1).max(240),
4204
4316
  sha256: z.string().regex(/^[a-f0-9]{64}$/u)
4205
4317
  }).strict().nullable(),
4206
- throughEvent: count$4,
4318
+ throughEvent: count$5,
4207
4319
  digest: z.string().regex(/^[a-f0-9]{64}$/u),
4208
4320
  decisionDigest: z.string().regex(/^[a-f0-9]{64}$/u),
4209
4321
  decisions: z.array(z.object({
@@ -4221,13 +4333,13 @@ const journeyContextSchema = z.object({
4221
4333
  confirmed: z.boolean()
4222
4334
  }).strict()),
4223
4335
  describedCheckpoints: z.array(z.enum(["initial", "complete"])).max(2),
4224
- totalBatches: count$4,
4225
- reviewedBatches: count$4,
4336
+ totalBatches: count$5,
4337
+ reviewedBatches: count$5,
4226
4338
  complete: z.boolean(),
4227
4339
  placementReviewed: z.boolean(),
4228
4340
  fragments: z.array(z.object({
4229
4341
  batchId: z.uuid(),
4230
- ordinal: count$4
4342
+ ordinal: count$5
4231
4343
  }).strict()).max(16),
4232
4344
  cursor: cursor.nullable()
4233
4345
  }).strict();
@@ -4255,6 +4367,268 @@ z.discriminatedUnion("kind", [z.object({
4255
4367
  submission: sessionReconcileInputSchema
4256
4368
  }).strict()]);
4257
4369
  //#endregion
4370
+ //#region packages/application/src/journey/placement/work.ts
4371
+ /** The processed project name is both the initial title and the retired-description fallback. */
4372
+ function newJourneyWork(id, projectName, rootSessionIds, sourceWorkspaceIds, placement = "placed") {
4373
+ return {
4374
+ id,
4375
+ title: projectName,
4376
+ projectName,
4377
+ projectType: null,
4378
+ description: "",
4379
+ titleOrigin: "model",
4380
+ explicitTitleId: null,
4381
+ accessOrigin: "default",
4382
+ placement,
4383
+ suggestion: null,
4384
+ classificationRecommendation: null,
4385
+ sourceWorkspaceIds,
4386
+ rootSessionIds,
4387
+ grouping: sourceWorkspaceIds.length === 1 ? "workspace" : "regrouped",
4388
+ access: "private",
4389
+ accessConfirmed: false,
4390
+ reason: "Awaiting content review.",
4391
+ revision: 1,
4392
+ inputRevision: 1,
4393
+ status: "pending",
4394
+ totalBatches: 0,
4395
+ completedBatches: 0,
4396
+ groupIds: [],
4397
+ blockedCodes: [],
4398
+ artifact: null,
4399
+ binding: null
4400
+ };
4401
+ }
4402
+ //#endregion
4403
+ //#region packages/application/src/journey/scan-generation.ts
4404
+ /** Retire one scan generation while preserving the person's confirmed classification. */
4405
+ function retireScanGeneration(state, workId) {
4406
+ if (!state.works.some((work) => work.id === workId)) throw new ApplicationError("UNKNOWN_ITEM");
4407
+ const changedKeys = /* @__PURE__ */ new Set();
4408
+ const terms = state.privacy.terms.flatMap((term) => {
4409
+ if (!term.sources.some((source) => source.workId === workId)) return [term];
4410
+ changedKeys.add(privacyTermKey(term));
4411
+ const sources = term.sources.filter((source) => source.workId !== workId);
4412
+ return sources.length ? [{
4413
+ ...term,
4414
+ sources,
4415
+ disposition: term.disposition === "keep" ? "pending" : term.disposition
4416
+ }] : [];
4417
+ });
4418
+ return {
4419
+ ...state,
4420
+ readingComplete: false,
4421
+ phase: state.phase === "paused" ? "paused" : "processing",
4422
+ privacy: {
4423
+ ...state.privacy,
4424
+ terms,
4425
+ cards: state.privacy.cards.filter((card) => card.termKeys.every((key) => !changedKeys.has(key))),
4426
+ confirmedAnswersRevision: null,
4427
+ packageApproval: null
4428
+ },
4429
+ works: state.works.map((work) => work.id === workId ? resetWorkScan(work) : work)
4430
+ };
4431
+ }
4432
+ /** The same Work with a new scan generation: it is read again from its first session. */
4433
+ function resetWorkScan(work) {
4434
+ const { emptyReview: _empty, excludedReview: _excluded, staticReview: _static, metadataReviewedDigest: _metadata, reviewReuseFrom: _reuse, renderFailure: _failure, ...retained } = work;
4435
+ return {
4436
+ ...retained,
4437
+ revision: work.revision + 1,
4438
+ inputRevision: work.inputRevision + 1,
4439
+ status: "pending",
4440
+ suggestion: null,
4441
+ totalBatches: 0,
4442
+ completedBatches: 0,
4443
+ groupIds: [],
4444
+ blockedCodes: [],
4445
+ artifact: null
4446
+ };
4447
+ }
4448
+ //#endregion
4449
+ //#region packages/application/src/journey/scope/proposal.ts
4450
+ const count$4 = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
4451
+ const workspaces = z.array(z.string().min(1).max(128));
4452
+ /**
4453
+ * A complete classification proposal prepared outside the store and applied inside one store
4454
+ * transaction against the current state (BL-216). New Work IDs and the session of every finding
4455
+ * chunk the regrouping moves are resolved beforehand, so applying it needs no I/O.
4456
+ */
4457
+ const classificationCommitSchema = z.object({
4458
+ journeyId: journeyIdSchema,
4459
+ requestKey: journeyIdSchema,
4460
+ requestHash: journeyDigestSchema,
4461
+ at: z.iso.datetime(),
4462
+ /** Unbound proposals keep the exact journey revision fence. */
4463
+ expectedRevision: count$4,
4464
+ /** Bound proposals (E2) are fenced on the classification they replace instead. */
4465
+ expectedClassificationRevision: count$4.nullable(),
4466
+ snapshotId: journeyDigestSchema,
4467
+ /** `classificationPartition` of the state the proposal was prepared against. */
4468
+ partition: journeyDigestSchema,
4469
+ late: z.boolean(),
4470
+ items: z.array(journeyClassificationSubmitSchema.shape.items.element.extend({
4471
+ workId: journeyIdSchema,
4472
+ workspaceIds: workspaces
4473
+ })).min(1).max(1e3),
4474
+ pending: z.object({
4475
+ workId: journeyIdSchema,
4476
+ rootSessionIds: z.array(z.string().min(1).max(128)).min(1).max(1e4),
4477
+ workspaceIds: workspaces
4478
+ }).strict().nullable(),
4479
+ chunkSessions: z.array(z.object({
4480
+ batchId: z.uuid(),
4481
+ chunkId: z.uuid(),
4482
+ sessionId: z.string().min(1).max(128)
4483
+ }).strict()).max(1e6)
4484
+ }).strict();
4485
+ /** The Works and roots a proposal regroups; scan progress and access never change it. */
4486
+ function classificationPartition(state) {
4487
+ return createHash("sha256").update(JSON.stringify(state.works.map((work) => [
4488
+ work.id,
4489
+ work.placement,
4490
+ work.rootSessionIds.toSorted()
4491
+ ]))).digest("hex");
4492
+ }
4493
+ /** The proposal's Works built from the given state's current Works (E2). */
4494
+ function classificationWorks(state, plan) {
4495
+ const late = plan.late;
4496
+ const works = [];
4497
+ for (const item of plan.items) {
4498
+ const existing = state.works.find((work) => work.placement !== "classifying" && work.rootSessionIds.length === item.rootSessionIds.length && work.rootSessionIds.every((root) => item.rootSessionIds.includes(root)));
4499
+ const extended = late ? state.works.find((work) => work.placement === "placed" && work.rootSessionIds.every((root) => item.rootSessionIds.includes(root))) : void 0;
4500
+ if (late && existing) {
4501
+ works.push(existing);
4502
+ continue;
4503
+ }
4504
+ const base = existing ?? (extended ? {
4505
+ ...resetWorkScan(extended),
4506
+ rootSessionIds: item.rootSessionIds,
4507
+ sourceWorkspaceIds: [.../* @__PURE__ */ new Set([...extended.sourceWorkspaceIds, ...item.workspaceIds])]
4508
+ } : newJourneyWork(item.workId, item.projectName, item.rootSessionIds, item.workspaceIds, "placed"));
4509
+ const { classificationMetadata: _display, ...original } = base;
4510
+ works.push({
4511
+ ...original,
4512
+ projectName: item.projectName,
4513
+ title: base.titleOrigin === "explicit" ? base.title : item.projectName,
4514
+ description: item.description,
4515
+ projectType: {
4516
+ type: item.projectType,
4517
+ reason: item.recommendation.reason,
4518
+ origin: "model"
4519
+ },
4520
+ placement: "placed",
4521
+ ...late && !extended ? {
4522
+ access: item.recommendation.access,
4523
+ accessOrigin: "model",
4524
+ accessConfirmed: true
4525
+ } : {},
4526
+ classificationRecommendation: item.recommendation,
4527
+ suggestion: null,
4528
+ artifact: null,
4529
+ revision: base.revision + 1
4530
+ });
4531
+ }
4532
+ const pending = plan.pending;
4533
+ if (pending) {
4534
+ const prior = state.works.find((work) => work.placement === "classifying" && work.rootSessionIds.length === pending.rootSessionIds.length && work.rootSessionIds.every((root) => pending.rootSessionIds.includes(root)));
4535
+ works.push(prior ?? newJourneyWork(pending.workId, "Still being grouped", pending.rootSessionIds, pending.workspaceIds, "classifying"));
4536
+ }
4537
+ const fields = (work) => JSON.stringify([
4538
+ work?.title,
4539
+ work?.projectName,
4540
+ work?.description,
4541
+ work?.classificationRecommendation?.reason
4542
+ ]);
4543
+ return {
4544
+ works,
4545
+ changedMetadata: new Set(works.filter((work) => {
4546
+ const old = state.works.find((item) => item.id === work.id);
4547
+ return !old || fields(work) !== fields(old);
4548
+ }).map((work) => work.id))
4549
+ };
4550
+ }
4551
+ /**
4552
+ * Rebind accepted frozen evidence; original batch/chunk IDs remain its audit provenance. Null
4553
+ * when a finding in a moved Work was not resolved beforehand, so the proposal is stale.
4554
+ */
4555
+ function regroupTerms(terms, works, changedMetadata, chunkSessions) {
4556
+ const owners = new Map(works.flatMap((work) => work.rootSessionIds.map((id) => [id, work.id])));
4557
+ const retained = new Set(works.map((work) => work.id));
4558
+ const sessions = new Map(chunkSessions.map((item) => [`${item.batchId}:${item.chunkId}`, item.sessionId]));
4559
+ const regrouped = [];
4560
+ for (const term of terms) {
4561
+ const sources = [];
4562
+ for (const source of term.sources) {
4563
+ if (source.kind === "metadata") {
4564
+ if (retained.has(source.workId) && !changedMetadata.has(source.workId)) sources.push(source);
4565
+ continue;
4566
+ }
4567
+ if (retained.has(source.workId)) {
4568
+ sources.push(source);
4569
+ continue;
4570
+ }
4571
+ const session = sessions.get(`${source.batchId}:${source.chunkId}`);
4572
+ if (session === void 0) return null;
4573
+ const workId = owners.get(session);
4574
+ if (!workId) throw new ApplicationError("CORRUPTED_STATE");
4575
+ sources.push({
4576
+ ...source,
4577
+ workId
4578
+ });
4579
+ }
4580
+ regrouped.push({
4581
+ ...term,
4582
+ sources
4583
+ });
4584
+ }
4585
+ return regrouped;
4586
+ }
4587
+ /**
4588
+ * The proposal applied to the current state, or null when it is stale: the classification, the
4589
+ * frozen snapshot, the regrouped Works and roots, or the scope changed since it was prepared.
4590
+ * Scan progress, Work input revisions and the person's visibility choices do not make it stale;
4591
+ * they are kept as the current state has them.
4592
+ */
4593
+ function applyClassificationProposal(state, plan) {
4594
+ const classifying = isClassifying(state);
4595
+ if (!state.consent || state.journeyId !== plan.journeyId || (plan.expectedClassificationRevision === null ? state.revision !== plan.expectedRevision : !classifying || state.classificationRevision !== plan.expectedClassificationRevision) || state.snapshotId !== plan.snapshotId || state.scope.status === "confirmed" !== plan.late || plan.late && !classifying || state.phase === "paused" || state.pendingHideId || classificationPartition(state) !== plan.partition) return null;
4596
+ const { works, changedMetadata } = classificationWorks(state, plan);
4597
+ const retained = new Set(works.map((work) => work.id));
4598
+ const regrouped = !plan.late && (state.works.some((work) => !retained.has(work.id)) || changedMetadata.size > 0);
4599
+ const cardTerms = new Set(state.privacy.cards.flatMap((card) => card.termKeys));
4600
+ const preserved = regroupTerms(state.privacy.terms, works, changedMetadata, plan.chunkSessions);
4601
+ if (!preserved) return null;
4602
+ const forced = new Set(preserved.filter((term) => !termTypeInfo[term.type].asked).map((term) => term.value));
4603
+ const overrides = new Map(state.valueOverrides?.map((item) => [item.value, item.choice]) ?? []);
4604
+ const terms = preserved.map((term) => ({
4605
+ ...term,
4606
+ disposition: forced.has(term.value) ? "hidden" : overrides.has(term.value) ? overrides.get(term.value) === "hide" ? "hidden" : "keep" : regrouped && cardTerms.has(privacyTermKey(term)) ? "pending" : term.disposition
4607
+ }));
4608
+ return {
4609
+ ...state,
4610
+ works,
4611
+ classificationRevision: state.revision + 1,
4612
+ scope: plan.late ? state.scope : {
4613
+ status: "pending",
4614
+ actor: null,
4615
+ at: null
4616
+ },
4617
+ privacy: {
4618
+ ...state.privacy,
4619
+ terms,
4620
+ packageApproval: null,
4621
+ ...regrouped ? {
4622
+ cards: [],
4623
+ answersRevision: state.privacy.answersRevision + 1,
4624
+ confirmedAnswersRevision: null
4625
+ } : {}
4626
+ },
4627
+ readingComplete: !plan.pending && works.filter((work) => work.access !== "drop").every((work) => work.totalBatches > 0 && work.completedBatches === work.totalBatches),
4628
+ phase: "processing"
4629
+ };
4630
+ }
4631
+ //#endregion
4258
4632
  //#region packages/application/src/journey/review/port.ts
4259
4633
  /** Batches are served in publication order; only a Drop or un-Drop invalidates a cursor. */
4260
4634
  const journeyReadCursorSchema = z.object({
@@ -4505,7 +4879,7 @@ function propagateGroups(state, action) {
4505
4879
  /** Classification confirmation fixes visibility and scan membership for this journey. */
4506
4880
  function confirmScope(state, now, decision) {
4507
4881
  if (state.scope.status === "confirmed") return state;
4508
- if (state.classificationRevision === null || !state.works.length || state.works.some((work) => work.placement !== "placed" || !(work.status === "blocked" && work.access === "drop" && work.accessConfirmed) && (!work.description.trim() || !work.projectType))) throw new ApplicationError("SCOPE_NOT_READY");
4882
+ 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");
4509
4883
  return withReadingProgress({
4510
4884
  ...state,
4511
4885
  scope: {
@@ -4513,7 +4887,7 @@ function confirmScope(state, now, decision) {
4513
4887
  actor: decision ? "delegate" : "human",
4514
4888
  at: now
4515
4889
  },
4516
- works: state.works.map((work) => work.accessConfirmed || !work.classificationRecommendation ? {
4890
+ works: state.works.map((work) => work.placement === "classifying" ? work : work.accessConfirmed || !work.classificationRecommendation ? {
4517
4891
  ...work,
4518
4892
  accessConfirmed: true
4519
4893
  } : {
@@ -4558,7 +4932,7 @@ function setWorkType(state, workId, type, decision) {
4558
4932
  function setWorksAccess(state, workIds, access, decision) {
4559
4933
  if (new Set(workIds).size !== workIds.length) throw new ApplicationError("INVALID_SELECTION");
4560
4934
  if (workIds.some((id) => !state.works.some((work) => work.id === id))) throw new ApplicationError("UNKNOWN_WORKSPACE");
4561
- if (state.scope.status === "confirmed") return dropBlockedWorks(state, workIds, access, decision);
4935
+ if (state.scope.status === "confirmed") return changeConfirmedAccess(state, workIds, access, decision);
4562
4936
  return withReadingProgress({
4563
4937
  ...state,
4564
4938
  scope: {
@@ -4584,11 +4958,12 @@ function setWorksAccess(state, workIds, access, decision) {
4584
4958
  });
4585
4959
  }
4586
4960
  /**
4587
- * ADR 0188: after confirmation the person, never a delegate, may only Drop a Work that
4588
- * preparation blocked. The scope stays confirmed; reading progress is recomputed.
4961
+ * After confirmation the person, never a delegate, may still change any Work's visibility
4962
+ * (D2, superseding ADR 0162's lock and ADR 0188's blocked-only Drop). Drop stops that Work's
4963
+ * scan; a Work moved out of Drop is read again; reading progress is recomputed.
4589
4964
  */
4590
- function dropBlockedWorks(state, workIds, access, decision) {
4591
- if (decision || access !== "drop" || state.phase === "sending" || state.phase === "completed" || state.works.some((work) => workIds.includes(work.id) && (work.status !== "blocked" || work.access === "drop"))) throw new ApplicationError("INVALID_TRANSITION");
4965
+ function changeConfirmedAccess(state, workIds, access, decision) {
4966
+ if (decision || state.phase === "sending" || state.phase === "completed" || state.works.some((work) => workIds.includes(work.id) && work.access === access)) throw new ApplicationError("INVALID_TRANSITION");
4592
4967
  return withReadingProgress({
4593
4968
  ...state,
4594
4969
  privacy: {
@@ -4598,7 +4973,9 @@ function dropBlockedWorks(state, workIds, access, decision) {
4598
4973
  works: state.works.map((work) => workIds.includes(work.id) ? {
4599
4974
  ...work,
4600
4975
  revision: work.revision + 1,
4601
- access: "drop",
4976
+ artifact: null,
4977
+ status: work.status === "ready" ? "review" : work.status,
4978
+ access,
4602
4979
  accessConfirmed: true,
4603
4980
  accessOrigin: "explicit"
4604
4981
  } : work)
@@ -4687,7 +5064,7 @@ function respondToJourney(state, action, source, now, decision, preferenceScope)
4687
5064
  };
4688
5065
  }
4689
5066
  if (action.kind === "consent") {
4690
- if (source !== "conversation" || decision) throw new ApplicationError("CONFIRMATION_REQUIRED");
5067
+ if (decision) throw new ApplicationError("CONFIRMATION_REQUIRED");
4691
5068
  if (state.consent) return state;
4692
5069
  if (!action.allow) return {
4693
5070
  ...state,
@@ -4801,7 +5178,7 @@ function pendingGroups(state) {
4801
5178
  * It is never filtered by Work or relevance, so its digest proves which guidance was current.
4802
5179
  */
4803
5180
  function journeyGuidance(state) {
4804
- const rules = [...state.privacy.rememberedRules, ...state.privacy.cards.flatMap((card) => card.answer ? [card.answer.rule] : [])];
5181
+ const rules = [...state.privacy.rememberedRules, ...state.privacy.cards.flatMap((card) => card.answer ? [answeredRule(card)] : [])];
4805
5182
  const conditions = state.groups.map(({ id, kind, key, label, condition, choice, confirmed, origin }) => ({
4806
5183
  groupId: id,
4807
5184
  kind,
@@ -4841,6 +5218,17 @@ function journeyGuidance(state) {
4841
5218
  rules
4842
5219
  };
4843
5220
  }
5221
+ /**
5222
+ * An answered card as scan children read it: the question with the answer, so a value that fits
5223
+ * the question takes that answer instead of staying Pending (E3).
5224
+ */
5225
+ function answeredRule(card) {
5226
+ const answer = card.answer;
5227
+ if (!answer) return "";
5228
+ const label = card.options.find((option) => option.id === answer.optionId)?.label;
5229
+ const rule = `Answered question “${card.question}”: ${answer.optionId === "hide" ? "Hide" : "Keep"}${label ? ` (“${label}”)` : ""}. ${answer.rule}`;
5230
+ return rule.length <= 4001 ? rule : answer.rule;
5231
+ }
4844
5232
  //#endregion
4845
5233
  //#region packages/application/src/journey/review/agents.ts
4846
5234
  /** A dispatch without a pack ID is its own analysis agent. */
@@ -5513,9 +5901,11 @@ function journeyView(state, now) {
5513
5901
  },
5514
5902
  works: state.works.map((work) => {
5515
5903
  const localTitle = work.suggestion || work.explicitTitleId ? work.title : work.classificationMetadata?.title ?? work.title;
5904
+ const imagesOmitted = hasCurrentStaticReview(state, work) ? work.staticReview?.imagesOmitted ?? 0 : 0;
5516
5905
  if (!work.classificationMetadata) return {
5517
5906
  ...work,
5518
- localTitle
5907
+ localTitle,
5908
+ imagesOmitted
5519
5909
  };
5520
5910
  const metadata = work.classificationMetadata;
5521
5911
  const displayed = {
@@ -5528,6 +5918,7 @@ function journeyView(state, now) {
5528
5918
  ...work,
5529
5919
  ...displayed,
5530
5920
  localTitle,
5921
+ imagesOmitted,
5531
5922
  projectType: work.projectType ? {
5532
5923
  ...work.projectType,
5533
5924
  reason: work.projectType.origin === "model" ? displayed.reason : work.projectType.reason
@@ -5668,10 +6059,30 @@ function createNativeJourney(storage, now = () => (/* @__PURE__ */ new Date()).t
5668
6059
  id: "current"
5669
6060
  })).find((resource) => resource.kind === "classification-progress");
5670
6061
  if (previous) {
5671
- const contains = (next, prior) => prior.every((id) => next.includes(id));
5672
6062
  const replacesObsoleteAttempt = previous.baselineRevision !== progress.baselineRevision && progress.baselineRevision === state.revision && progress.status === "running" && progress.stage === "classification" && progress.completedRootIds.length === 0 && progress.groupedRootIds.length === 0 && progress.aiCompletedRootIds.length === 0 && Date.parse(progress.startedAt) > Date.parse(previous.startedAt);
5673
6063
  const restartsFailedAttempt = previous.status === "failed" && previous.baselineRevision === progress.baselineRevision && progress.baselineRevision === state.revision && progress.status === "running" && progress.stage === "classification" && progress.completedRootIds.length === 0 && progress.groupedRootIds.length === 0 && progress.aiCompletedRootIds.length === 0 && Date.parse(progress.startedAt) > Date.parse(previous.startedAt);
5674
- if (!replacesObsoleteAttempt && !restartsFailedAttempt && (previous.inputFingerprint !== progress.inputFingerprint || previous.baselineRevision !== progress.baselineRevision || previous.proposalRevision !== null && previous.proposalRevision !== progress.proposalRevision || previous.startedAt !== progress.startedAt || Date.parse(progress.updatedAt) < Date.parse(previous.updatedAt) || progress.elapsedMs < previous.elapsedMs || previous.stage === "proposal" && progress.stage === "classification" || previous.status === "complete" && progress.status !== "complete" || !contains(progress.completedRootIds, previous.completedRootIds) || !contains(progress.groupedRootIds, previous.groupedRootIds) || !contains(progress.aiCompletedRootIds, previous.aiCompletedRootIds))) throw new ApplicationError("REVISION_CONFLICT");
6064
+ if (!replacesObsoleteAttempt && !restartsFailedAttempt) {
6065
+ if (previous.inputFingerprint !== progress.inputFingerprint || previous.baselineRevision !== progress.baselineRevision || previous.proposalRevision !== null && previous.proposalRevision !== progress.proposalRevision || previous.startedAt !== progress.startedAt) throw new ApplicationError("REVISION_CONFLICT");
6066
+ const union = (left, right) => [.../* @__PURE__ */ new Set([...left, ...right])].toSorted();
6067
+ const rank = {
6068
+ running: 0,
6069
+ paused: 0,
6070
+ failed: 1,
6071
+ complete: 2
6072
+ };
6073
+ await storage.saveResource({
6074
+ ...progress,
6075
+ stage: previous.stage === "proposal" ? "proposal" : progress.stage,
6076
+ status: rank[previous.status] > rank[progress.status] ? previous.status : progress.status,
6077
+ proposalRevision: progress.proposalRevision ?? previous.proposalRevision,
6078
+ updatedAt: Date.parse(previous.updatedAt) > Date.parse(progress.updatedAt) ? previous.updatedAt : progress.updatedAt,
6079
+ elapsedMs: Math.max(previous.elapsedMs, progress.elapsedMs),
6080
+ completedRootIds: union(previous.completedRootIds, progress.completedRootIds),
6081
+ groupedRootIds: union(previous.groupedRootIds, progress.groupedRootIds),
6082
+ aiCompletedRootIds: union(previous.aiCompletedRootIds, progress.aiCompletedRootIds)
6083
+ });
6084
+ return { accepted: true };
6085
+ }
5675
6086
  }
5676
6087
  await storage.saveResource(progress);
5677
6088
  return { accepted: true };
@@ -5806,16 +6217,29 @@ function createNativeJourney(storage, now = () => (/* @__PURE__ */ new Date()).t
5806
6217
  state: await present(result.state)
5807
6218
  };
5808
6219
  }
6220
+ const rebase = source === "panel" && !input.decision && [
6221
+ "consent",
6222
+ "work-access",
6223
+ "works-access",
6224
+ "card-answer"
6225
+ ].includes(input.action.kind);
6226
+ for (let attempt = 0;; attempt++) {
6227
+ const result = await commitResponse(input, source, rebase);
6228
+ if (result.status !== "stale" || !rebase || attempt >= 4) return result;
6229
+ }
6230
+ }
6231
+ async function commitResponse(input, source, rebase) {
5809
6232
  const current = await storage.current(input.journeyId);
5810
6233
  if (!current) throw new ApplicationError("UNKNOWN_ITEM");
5811
- const state = current.revision === input.expectedRevision ? respondToJourney(current, input.action, source, now(), input.decision, input.preferenceScope) : current;
6234
+ const expectedRevision = rebase ? current.revision : input.expectedRevision;
6235
+ const state = current.revision === expectedRevision ? respondToJourney(current, input.action, source, now(), input.decision, input.preferenceScope) : current;
5812
6236
  const groupIds = input.action.kind === "group" ? [input.action.groupId] : input.action.kind === "groups-hide" ? input.action.groupIds : [];
5813
6237
  const preferenceScopes = input.decision ? [] : state.groups.flatMap((group) => groupIds.includes(group.id) && group.preferenceScope ? [{
5814
6238
  groupId: group.id,
5815
6239
  preferenceScope: group.preferenceScope
5816
6240
  }] : []);
5817
6241
  const result = await storage.commit({
5818
- expectedRevision: input.expectedRevision,
6242
+ expectedRevision,
5819
6243
  requestKey: input.idempotencyKey,
5820
6244
  requestHash: digest$1(input),
5821
6245
  state,
@@ -5845,7 +6269,7 @@ function createNativeJourney(storage, now = () => (/* @__PURE__ */ new Date()).t
5845
6269
  events: rows,
5846
6270
  state: await get({ journeyId: input.journeyId })
5847
6271
  };
5848
- await setTimeout$1(Math.min(250, Math.max(0, deadline - Date.now())), void 0, { signal });
6272
+ await setTimeout$1(Math.min(1e3, Math.max(0, deadline - Date.now())), void 0, { signal });
5849
6273
  }
5850
6274
  }
5851
6275
  async function prepare(value, signal) {
@@ -5948,7 +6372,7 @@ function createNativeJourney(storage, now = () => (/* @__PURE__ */ new Date()).t
5948
6372
  const scope = await port.renderScope?.(journeyId, workIds.length, signal);
5949
6373
  const renderWork = scope ? (workId) => scope.render(workId) : (workId) => port.render(journeyId, workId, signal);
5950
6374
  try {
5951
- await Promise.all(Array.from({ length: Math.min(scope?.concurrency ?? renderConcurrency, workIds.length) }, async () => {
6375
+ const failure = (await Promise.allSettled(Array.from({ length: Math.min(scope?.concurrency ?? renderConcurrency, workIds.length) }, async () => {
5952
6376
  for (let workId = workIds[next++]; workId !== void 0; workId = workIds[next++]) {
5953
6377
  try {
5954
6378
  await renderWork(workId);
@@ -5967,7 +6391,8 @@ function createNativeJourney(storage, now = () => (/* @__PURE__ */ new Date()).t
5967
6391
  }
5968
6392
  await new Promise((resolve) => setImmediate(resolve));
5969
6393
  }
5970
- }));
6394
+ }))).find((item) => item.status === "rejected");
6395
+ if (failure) throw failure.reason;
5971
6396
  } finally {
5972
6397
  await scope?.close();
5973
6398
  }
@@ -6051,11 +6476,19 @@ function createNativeJourney(storage, now = () => (/* @__PURE__ */ new Date()).t
6051
6476
  }
6052
6477
  async function privacyWrite(value, resolve) {
6053
6478
  const input = resolve ? privacyResolveSchema.parse(value) : cardsSubmitSchema.parse(value);
6479
+ const rebase = "mode" in input && input.mode === "append";
6480
+ for (let attempt = 0;; attempt++) {
6481
+ const result = await commitPrivacy(input, rebase);
6482
+ if (result.status !== "stale" || !rebase || attempt >= 4) return result;
6483
+ }
6484
+ }
6485
+ async function commitPrivacy(input, rebase) {
6054
6486
  const current = await storage.current(input.journeyId);
6055
6487
  if (!current) throw new ApplicationError("UNKNOWN_ITEM");
6056
- const state = current.revision !== input.expectedRevision ? current : "resolutions" in input ? resolvePrivacyTerms(current, input) : publishDecisionCards(current, input);
6488
+ const expectedRevision = rebase ? current.revision : input.expectedRevision;
6489
+ const state = current.revision !== expectedRevision ? current : "resolutions" in input ? resolvePrivacyTerms(current, input) : publishDecisionCards(current, input);
6057
6490
  const result = await storage.commit({
6058
- expectedRevision: input.expectedRevision,
6491
+ expectedRevision,
6059
6492
  requestKey: input.idempotencyKey,
6060
6493
  requestHash: digest$1(input),
6061
6494
  state,
@@ -6252,7 +6685,12 @@ const sendReceiptSchema = z.object({
6252
6685
  passportIncluded: z.boolean(),
6253
6686
  upload: z.object({
6254
6687
  uploadUrl: z.url(),
6255
- expiresAt: z.iso.datetime()
6688
+ expiresAt: z.iso.datetime(),
6689
+ /**
6690
+ * Headers the signed URL requires besides type and length: Passport answers them only
6691
+ * for a checksum upload, whose PUT writes the immutable object directly (ADR 0230).
6692
+ */
6693
+ headers: z.object({ "x-amz-checksum-sha256": z.base64().length(44) }).strict().optional()
6256
6694
  }).strict().nullable()
6257
6695
  }).strict();
6258
6696
  /** `POST /me/works/replace`: the owner's other Works are retired (ADR 0204). */
@@ -6298,6 +6736,13 @@ const sendItemSchema = z.object({
6298
6736
  reservation: sendUploadInputSchema.nullable(),
6299
6737
  receipt: savedSendReceiptSchema.nullable(),
6300
6738
  previousReceipts: z.array(savedSendReceiptSchema),
6739
+ /** The receipt whose bytes were PUT but not yet completed: the next step completes it (BL-210). */
6740
+ uploadedReceiptId: journeyIdSchema.nullable().optional(),
6741
+ /**
6742
+ * Passport answered `bundle_mismatch` to this Work's checksum upload: the rest of this Send
6743
+ * uploads through staging (ADR 0231).
6744
+ */
6745
+ checksumUploadRefused: z.literal(true).optional(),
6301
6746
  status: z.enum([
6302
6747
  "ready",
6303
6748
  "target",
@@ -6417,6 +6862,9 @@ function safeJourneySender(sender, now) {
6417
6862
  async resume(input) {
6418
6863
  return safe(await sender.resume(input));
6419
6864
  },
6865
+ async withdraw(input) {
6866
+ return safe(await sender.withdraw(input));
6867
+ },
6420
6868
  async advance(input, signal = new AbortController().signal) {
6421
6869
  return safe(await sender.advance(input, signal));
6422
6870
  }
@@ -10009,6 +10457,28 @@ const validateInspectionClaim = (input) => decode(inspectionClaimSchema, input);
10009
10457
  const validateInspectionHead = (input) => decode(inspectionHeadSchema, input);
10010
10458
  const validateInspectionQuery = (input) => decode(inspectionQuerySchema, input);
10011
10459
  //#endregion
10460
+ //#region packages/application/src/inspection/validation/request.ts
10461
+ /**
10462
+ * The inspection Worker receives its request across a thread boundary. A real inventory can exceed
10463
+ * the persisted-evidence decoding bounds, so this parses the host's own request unbounded.
10464
+ */
10465
+ const inspectionRequestSchema = z.object({
10466
+ customTerms: z.object({
10467
+ revision: z.string().min(1).max(64),
10468
+ terms: z.array(z.string().max(1024)).max(1e5)
10469
+ }).optional(),
10470
+ inputs: inspectionInputsSchema,
10471
+ inventory: inventorySchema,
10472
+ cleanupBySession: z.record(z.string(), cleanupSelectionSchema)
10473
+ });
10474
+ const validateInspectionRequest = (input) => {
10475
+ const { customTerms, ...request } = inspectionRequestSchema.parse(input);
10476
+ return customTerms ? {
10477
+ ...request,
10478
+ customTerms
10479
+ } : request;
10480
+ };
10481
+ //#endregion
10012
10482
  //#region packages/application/src/inspection/validation/index.ts
10013
10483
  const inspectionBatchSchema = z.object({
10014
10484
  contributions: z.array(inspectionContributionSchema).max(128),
@@ -11025,7 +11495,7 @@ function profileUrlMatchesIdentity(profileUrl, identityUrl) {
11025
11495
  }
11026
11496
  const deviceProfileScopeSchema = z.string().max(256).refine((scope) => {
11027
11497
  const scopes = new Set(scope.trim().split(/\s+/u));
11028
- return scopes.size === 2 && scopes.has("openid") && scopes.has("profile");
11498
+ return scopes.size === (scopes.has("offline_access") ? 3 : 2) && scopes.has("openid") && scopes.has("profile");
11029
11499
  });
11030
11500
  /** Display data resolved together from the issued token's UserInfo response. */
11031
11501
  const accountProfileSchema = z.object({
@@ -11052,6 +11522,8 @@ const storedCredentialSchema = accountProfileSchema.extend({
11052
11522
  identityUrl: z.string().min(1).max(2048),
11053
11523
  clientId: z.string().min(1).max(256),
11054
11524
  accessToken: z.string().min(1).max(4096),
11525
+ /** Renews the access token without a new device approval (BL-210); absent when not issued. */
11526
+ refreshToken: z.string().min(1).max(4096).optional(),
11055
11527
  tokenType: z.literal("Bearer"),
11056
11528
  scope: deviceProfileScopeSchema,
11057
11529
  issuedAt: z.string().min(1).max(64),
@@ -11113,7 +11585,7 @@ function createSharedAccount(ports) {
11113
11585
  async function read() {
11114
11586
  return update((state) => {
11115
11587
  const saved = state.credential;
11116
- if (saved && expired(saved.expiresAt, ports.now())) {
11588
+ if (saved && !saved.refreshToken && expired(saved.expiresAt, ports.now())) {
11117
11589
  state.credential = null;
11118
11590
  state.connection = null;
11119
11591
  state.lastError = "SIGN_IN_EXPIRED";
@@ -11168,6 +11640,7 @@ function createSharedAccount(ports) {
11168
11640
  avatarUrl: state.credential.avatarUrl,
11169
11641
  profileUrl: state.credential.profileUrl,
11170
11642
  expiresAt: state.credential.expiresAt,
11643
+ renews: Boolean(state.credential.refreshToken),
11171
11644
  connection: state.connection ?? null
11172
11645
  };
11173
11646
  return {
@@ -11227,6 +11700,7 @@ function createSharedAccount(ports) {
11227
11700
  avatarUrl: identity.avatarUrl,
11228
11701
  profileUrl: identity.profileUrl,
11229
11702
  accessToken: result.accessToken,
11703
+ ...result.refreshToken ? { refreshToken: result.refreshToken } : {},
11230
11704
  tokenType: "Bearer",
11231
11705
  scope: result.scope,
11232
11706
  issuedAt: ports.now(),
@@ -11287,7 +11761,8 @@ function createSharedAccount(ports) {
11287
11761
  })).authorization?.id === id) await poll(id, signal, clientId);
11288
11762
  } catch (error) {
11289
11763
  if (signal.aborted) return;
11290
- console.error(`Account authorization failed: ${safeCode(error)}`);
11764
+ const detail = typeof error === "object" && error !== null && "detail" in error ? ` (${String(error.detail)})` : "";
11765
+ console.error(`Account authorization failed: ${safeCode(error)}${detail}`);
11291
11766
  await finish(id, safeCode(error));
11292
11767
  throw error;
11293
11768
  } finally {
@@ -12085,39 +12560,6 @@ function reviseGroupMembership(state, action, members, preferenceScope) {
12085
12560
  };
12086
12561
  }
12087
12562
  //#endregion
12088
- //#region packages/application/src/journey/placement/work.ts
12089
- /** The processed project name is both the initial title and the retired-description fallback. */
12090
- function newJourneyWork(id, projectName, rootSessionIds, sourceWorkspaceIds, placement = "placed") {
12091
- return {
12092
- id,
12093
- title: projectName,
12094
- projectName,
12095
- projectType: null,
12096
- description: "",
12097
- titleOrigin: "model",
12098
- explicitTitleId: null,
12099
- accessOrigin: "default",
12100
- placement,
12101
- suggestion: null,
12102
- classificationRecommendation: null,
12103
- sourceWorkspaceIds,
12104
- rootSessionIds,
12105
- grouping: sourceWorkspaceIds.length === 1 ? "workspace" : "regrouped",
12106
- access: "private",
12107
- accessConfirmed: false,
12108
- reason: "Awaiting content review.",
12109
- revision: 1,
12110
- inputRevision: 1,
12111
- status: "pending",
12112
- totalBatches: 0,
12113
- completedBatches: 0,
12114
- groupIds: [],
12115
- blockedCodes: [],
12116
- artifact: null,
12117
- binding: null
12118
- };
12119
- }
12120
- //#endregion
12121
12563
  //#region packages/application/src/journey/b/reconstruct.ts
12122
12564
  function reconstructBFields(inputs) {
12123
12565
  const units = inputs.map(validateBUnit).sort((left, right) => left.ordinal - right.ordinal);
@@ -12734,49 +13176,4 @@ function equivalenceDuplicates(batch) {
12734
13176
  return bindings.sort();
12735
13177
  }
12736
13178
  //#endregion
12737
- //#region packages/application/src/journey/scan-generation.ts
12738
- /** Retire one scan generation while preserving the person's confirmed classification. */
12739
- function retireScanGeneration(state, workId) {
12740
- if (!state.works.some((work) => work.id === workId)) throw new ApplicationError("UNKNOWN_ITEM");
12741
- const changedKeys = /* @__PURE__ */ new Set();
12742
- const terms = state.privacy.terms.flatMap((term) => {
12743
- if (!term.sources.some((source) => source.workId === workId)) return [term];
12744
- changedKeys.add(privacyTermKey(term));
12745
- const sources = term.sources.filter((source) => source.workId !== workId);
12746
- return sources.length ? [{
12747
- ...term,
12748
- sources,
12749
- disposition: term.disposition === "keep" ? "pending" : term.disposition
12750
- }] : [];
12751
- });
12752
- return {
12753
- ...state,
12754
- readingComplete: false,
12755
- phase: state.phase === "paused" ? "paused" : "processing",
12756
- privacy: {
12757
- ...state.privacy,
12758
- terms,
12759
- cards: state.privacy.cards.filter((card) => card.termKeys.every((key) => !changedKeys.has(key))),
12760
- confirmedAnswersRevision: null,
12761
- packageApproval: null
12762
- },
12763
- works: state.works.map((work) => {
12764
- if (work.id !== workId) return work;
12765
- const { emptyReview: _empty, excludedReview: _excluded, staticReview: _static, metadataReviewedDigest: _metadata, reviewReuseFrom: _reuse, renderFailure: _failure, ...retained } = work;
12766
- return {
12767
- ...retained,
12768
- revision: work.revision + 1,
12769
- inputRevision: work.inputRevision + 1,
12770
- status: "pending",
12771
- suggestion: null,
12772
- totalBatches: 0,
12773
- completedBatches: 0,
12774
- groupIds: [],
12775
- blockedCodes: [],
12776
- artifact: null
12777
- };
12778
- })
12779
- };
12780
- }
12781
- //#endregion
12782
- export { settingsBatchSchema as $, bReviewDigest as $n, defaultScopedSettings as $r, journeyResourceQuerySchema as $t, accountProfileSchema as A, packHideIndex as An, staticSessionResourceSchema as Ar, sendSettingsSchema as At, inspectionCancelSchema as B, dictionaryHides as Bn, journeyRenderInputSchema as Br, journeyBatchReadSchema as Bt, rebindReviewAlignment as C, readConfirmedHideChange as Cn, privacyDecisionDigest as Cr, sendPrepareSchema as Ct, guardedFindingText as D, addHideIndexTokens as Dn, hasCurrentStaticReview as Dr, sendReceiptSchema as Dt, reviewBatchReuse as E, termHideAdditions as En, nativeRespondSchema as Er, sendArtifactSchema as Et, storedCredentialSchema as F, bWordBounded as Fn, withReadingProgress as Fr, nativeAdapterVersions as Ft, validateInspectionClaim as G, workDecisionDigest as Gn, selectionSchema as Gr, hideBeginSchema as Gt, validateInspectionBatch as H, maskedHitsStale as Hn, commandSchema as Hr, reviewCompileSchema as Ht, sourceIdentityEvidence as I, confirmedHideGroupIds as In, mergePrivacyTerms as Ir, attemptBudgetCodePoints as It, validateInspectionInputs as J, reviewCandidateInputSchema as Jn, stateSchema as Jr, journeySearchResultSchema as Jt, validateInspectionFence as K, workPrivacyDecisions as Kn, gitMetadataBudgetBytes as Kr, hideFinishSchema as Kt, withSourceEvidence as L, confirmedHideKey as Ln, journeyFindingImpactSchema as Lr, validateAttemptAppend as Lt, deviceProfileScopeSchema as M, bExceptionRanges as Mn, isReadingComplete as Mr, currentJourneyAdapters as Mt, profileUrlMatchesIdentity as N, bMaskedHits as Nn, isSelectedWork as Nr, obsoleteJourney as Nt, staticallyHiddenFindings as O, hideKeyId as On, staticReviewDigest as Or, sendReplaceResultSchema as Ot, readAccountAvatarUrl as P, bTermMatcher as Pn, selectedWorks as Pr, metadataProcessingVersion as Pt, inspectionInputs as Q, reviewTransportBytes as Qn, effectiveTreatmentSchema as Qr, projectPreparationProgress as Qt, agentSetupKey as R, confirmedHideKinds as Rn, journeyFindingsSchema as Rr, journeyGuidance as Rt, bReviewScope as S, confirmedHideDeltaSchema as Sn, assertJourneyPrivacyReady as Sr, sendChoiceSchema as St, rebindReviewSubmit as T, settleConfirmedHides as Tn, nativeGetSchema as Tr, journeySendSchema as Tt, validateInspectionBatches as U, syncTermGroups as Un, packageCommandSchema as Ur, journeyContextQuerySchema as Ut, inspectionStartSchema as V, journeyConfirmedHides as Vn, journeyRenderSchema as Vr, journeyReviewStorageQuerySchema as Vt, inspectionQuerySchema as W, retireWorkDescription as Wn, selectionBatchSchema as Wr, journeyContextSchema as Wt, validateInspectionContribution as X, reviewRepairInputSchema as Xn, recommendParallelism as Xr, searchScopeDigest as Xt, validateInspectionQuery as Y, reviewCandidateResourceSchema as Yn, sourceChangePolicy as Yr, journeySearchSaveSchema as Yt, validateDetectionSummary as Z, reviewRepairResourceSchema as Zn, approvedTreatmentSchema as Zr, journeyPolicyRespondSchema as Zt, semanticGroupKey as _, sessionUsefulnessResourceSchema as _n, preparationBeginSchema as _r, emptyTermsRevision as _t, validateBCrossSegmentReview as a, reviewAttemptsQuerySchema as an, scanSessionResourceSchema as ar, defaultAgentSetupInclusion as at, preparationScope as b, journeyEventSchema as bn, validatePreparationFacts as br, replaceSensitiveTermsSchema as bt, reconcileBSession as c, sessionReconcileResultSchema as cn, verifiedScanGitSeeds as cr, resolveFailureLocation as ct, reviseGroupMembership as d, sessionRereadResourceSchema as dn, resolveSourceSelection as dr, manualUploadBindingSchema as dt, freezeConfiguration as ei, journeyResourceSchema as en, mergeBRepair as er, settingsQuerySchema as et, resolveGroupSplit as f, sessionReviewInputSchema as fn, journeyInventoryQuerySchema as fr, manualUploadChoiceSchema as ft, hideScopeDigest as g, sessionUsefulnessInputSchema as gn, emptyPreparationFacts as gr, candidateSortAvailable as gt, activeJourneyTerms as h, sessionReviewStatusSchema as hn, journeyPreparationProgressSchema as hr, manualUploadStartSchema as ht, locateTermEvidence as i, reviewAttemptResourceSchema as in, scanPreparationDigest as ir, classifyAgentSetup as it, deviceAuthorizationSchema as j, bContainment as jn, hasCompleteWorkDescription as jr, settleCorrections as jt, createAccount as k, maximumHideIndexTokens as kn, staticSessionId as kr, sendResolutionSchema as kt, reconstructBFields as l, sessionReconciliationResourceSchema as ln, scanExclusionResourceSchema as lr, validateFailureLocation as lt, splitSelectorValues as m, sessionReviewResourceSchema as mn, journeyInventorySchema as mr, manualUploadSchema as mt, scanBatchContextDigest as n, staticCatalogRef as ni, journeyPlaceSchema as nn, scanAliasResourceSchema as nr, reviewInventory as nt, bCrossSegmentReviewSchema as o, reviewAttemptsResultSchema as on, scanGitSeedsId as or, maximumAgentSetupSessions as ot, selectedValueMembers as p, sessionReviewQuerySchema as pn, journeyInventoryReadSchema as pr, manualUploadPrepareSchema as pt, validateInspectionHead as q, workCorrectionBinding as qn, producerVersion as qr, hidePublishSchema as qt, scanBatchEquivalenceDigest as r, sortingApplySchema as rn, scanCanonicalResourceSchema as rr, appendSensitiveTerms as rt, bRereadDigest as s, sessionReconcileInputSchema as sn, scanGitSeedsResource as sr, artifactFailureDetailSchema as st, retireScanGeneration as t, selectFrozenConfiguration as ti, journeyIsolateSchema as tn, planBRepair as tr, readWorkspaceOutcomes as tt, newJourneyWork as u, sessionRereadInputSchema as un, validateScanExclusion as ur, manualUploadActionSchema as ut, changeJourney as v, journeyCommitResultSchema as vn, preparationSettlementSchema as vr, maximumTermsFileBytes as vt, rebindReviewOverlay as w, renderedHideValue as wn, nativeEventsSchema as wr, sendStartSchema as wt, isGenericPublicTerm as x, confirmedHideAdditions as xn, journeyClassificationSessionsSchema as xr, sendActionSchema as xt, projectJourneyInventory as y, journeyCommitSchema as yn, preparationStartSchema as yr, normalizeSensitiveTerms as yt, createApplication as z, confirmedHideTerms as zn, journeyPreviewSchema as zr, applyClassification as zt };
13179
+ export { settingsQuerySchema as $, reviewCandidateInputSchema as $n, gitMetadataBudgetBytes as $r, journeySearchResultSchema as $t, deviceProfileScopeSchema as A, settleConfirmedHides as An, nativeEventsSchema as Ar, settleCorrections as At, validateInspectionBatch as B, bWordBounded as Bn, isSelectedWork as Br, journeyReviewStorageQuerySchema as Bt, rebindReviewSubmit as C, journeyCommitResultSchema as Cn, preparationSettlementSchema as Cr, sendStartSchema as Ct, createAccount as D, confirmedHideDeltaSchema as Dn, applyCardAnswers as Dr, sendReplaceResultSchema as Dt, staticallyHiddenFindings as E, confirmedHideAdditions as En, journeyClassificationSessionsSchema as Er, sendReceiptSchema as Et, withSourceEvidence as F, packHideIndex as Fn, staticSessionId as Fr, attemptBudgetCodePoints as Ft, validateInspectionFence as G, dictionaryHides as Gn, journeyFindingsSchema as Gr, retireScanGeneration as Gt, validateInspectionRequest as H, confirmedHideKey as Hn, withReadingProgress as Hr, classificationCommitSchema as Ht, agentSetupKey as I, bContainment as In, staticSessionResourceSchema as Ir, validateAttemptAppend as It, validateInspectionQuery as J, syncTermGroups as Jn, journeyRenderSchema as Jr, journeyContextQuerySchema as Jt, validateInspectionHead as K, journeyConfirmedHides as Kn, journeyPreviewSchema as Kr, newJourneyWork as Kt, createApplication as L, bExceptionRanges as Ln, hasCompleteWorkDescription as Lr, journeyGuidance as Lt, readAccountAvatarUrl as M, addHideIndexTokens as Mn, nativeRespondSchema as Mr, obsoleteJourney as Mt, storedCredentialSchema as N, hideKeyId as Nn, hasCurrentStaticReview as Nr, metadataProcessingVersion as Nt, accountProfileSchema as O, readConfirmedHideChange as On, assertJourneyPrivacyReady as Or, sendResolutionSchema as Ot, sourceIdentityEvidence as P, maximumHideIndexTokens as Pn, staticReviewDigest as Pr, nativeAdapterVersions as Pt, settingsBatchSchema as Q, workCorrectionBinding as Qn, selectionSchema as Qr, hidePublishSchema as Qt, inspectionCancelSchema as R, bMaskedHits as Rn, isClassifying as Rr, applyClassification as Rt, rebindReviewOverlay as S, sessionUsefulnessResourceSchema as Sn, preparationBeginSchema as Sr, sendPrepareSchema as St, guardedFindingText as T, journeyEventSchema as Tn, validatePreparationFacts as Tr, sendArtifactSchema as Tt, inspectionQuerySchema as U, confirmedHideKinds as Un, mergePrivacyTerms as Ur, classificationPartition as Ut, validateInspectionBatches as V, confirmedHideGroupIds as Vn, selectedWorks as Vr, applyClassificationProposal as Vt, validateInspectionClaim as W, confirmedHideTerms as Wn, journeyFindingImpactSchema as Wr, classificationWorks as Wt, validateDetectionSummary as X, workDecisionDigest as Xn, packageCommandSchema as Xr, hideBeginSchema as Xt, validateInspectionContribution as Y, retireWorkDescription as Yn, commandSchema as Yr, journeyContextSchema as Yt, inspectionInputs as Z, workPrivacyDecisions as Zn, selectionBatchSchema as Zr, hideFinishSchema as Zt, projectJourneyInventory as _, sessionReviewInputSchema as _n, journeyInventoryQuerySchema as _r, maximumTermsFileBytes as _t, bCrossSegmentReviewSchema as a, effectiveTreatmentSchema as ai, journeyResourceSchema as an, mergeBRepair as ar, maximumAgentSetupSessions as at, bReviewScope as b, sessionReviewStatusSchema as bn, journeyPreparationProgressSchema as br, sendActionSchema as bt, reconstructBFields as c, selectFrozenConfiguration as ci, sortingApplySchema as cn, scanCanonicalResourceSchema as cr, validateFailureLocation as ct, selectedValueMembers as d, reviewAttemptsResultSchema as dn, scanGitSeedsId as dr, manualUploadChoiceSchema as dt, producerVersion as ei, journeySearchSaveSchema as en, reviewCandidateResourceSchema as er, readWorkspaceOutcomes as et, splitSelectorValues as f, sessionReconcileInputSchema as fn, scanGitSeedsResource as fr, manualUploadPrepareSchema as ft, changeJourney as g, sessionRereadResourceSchema as gn, resolveSourceSelection as gr, emptyTermsRevision as gt, semanticGroupKey as h, sessionRereadInputSchema as hn, validateScanExclusion as hr, candidateSortAvailable as ht, validateBCrossSegmentReview as i, approvedTreatmentSchema as ii, journeyResourceQuerySchema as in, bReviewDigest as ir, defaultAgentSetupInclusion as it, profileUrlMatchesIdentity as j, termHideAdditions as jn, nativeGetSchema as jr, currentJourneyAdapters as jt, deviceAuthorizationSchema as k, renderedHideValue as kn, privacyDecisionDigest as kr, sendSettingsSchema as kt, reviseGroupMembership as l, staticCatalogRef as li, reviewAttemptResourceSchema as ln, scanPreparationDigest as lr, manualUploadActionSchema as lt, hideScopeDigest as m, sessionReconciliationResourceSchema as mn, scanExclusionResourceSchema as mr, manualUploadStartSchema as mt, scanBatchEquivalenceDigest as n, sourceChangePolicy as ni, journeyPolicyRespondSchema as nn, reviewRepairResourceSchema as nr, appendSensitiveTerms as nt, bRereadDigest as o, defaultScopedSettings as oi, journeyIsolateSchema as on, planBRepair as or, artifactFailureDetailSchema as ot, activeJourneyTerms as p, sessionReconcileResultSchema as pn, verifiedScanGitSeeds as pr, manualUploadSchema as pt, validateInspectionInputs as q, maskedHitsStale as qn, journeyRenderInputSchema as qr, reviewCompileSchema as qt, locateTermEvidence as r, recommendParallelism as ri, projectPreparationProgress as rn, reviewTransportBytes as rr, classifyAgentSetup as rt, reconcileBSession as s, freezeConfiguration as si, journeyPlaceSchema as sn, scanAliasResourceSchema as sr, resolveFailureLocation as st, scanBatchContextDigest as t, stateSchema as ti, searchScopeDigest as tn, reviewRepairInputSchema as tr, reviewInventory as tt, resolveGroupSplit as u, reviewAttemptsQuerySchema as un, scanSessionResourceSchema as ur, manualUploadBindingSchema as ut, preparationScope as v, sessionReviewQuerySchema as vn, journeyInventoryReadSchema as vr, normalizeSensitiveTerms as vt, reviewBatchReuse as w, journeyCommitSchema as wn, preparationStartSchema as wr, journeySendSchema as wt, rebindReviewAlignment as x, sessionUsefulnessInputSchema as xn, emptyPreparationFacts as xr, sendChoiceSchema as xt, isGenericPublicTerm as y, sessionReviewResourceSchema as yn, journeyInventorySchema as yr, replaceSensitiveTermsSchema as yt, inspectionStartSchema as z, bTermMatcher as zn, isReadingComplete as zr, journeyBatchReadSchema as zt };