@gitroll/tacitt-cli 0.6.11 → 0.6.12

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 (53) hide show
  1. package/README.md +4 -0
  2. package/bin/INDEX.md +6 -4
  3. package/bin/tacitt.cjs +1 -0
  4. package/dist/{agent-setup-DdfF3zch.mjs → agent-setup-B12VbvN_.mjs} +2 -2
  5. package/dist/agent-setup-worker.mjs +5 -5
  6. package/dist/cli.mjs +28 -28
  7. package/dist/codex-title-worker.mjs +2 -2
  8. package/dist/configured-preview-worker.mjs +5 -5
  9. package/dist/configured-session-worker.mjs +23 -25
  10. package/dist/{frame-Bq2zRh-i.mjs → frame-B3He21G8.mjs} +1 -1
  11. package/dist/{heap-CV8Eca8V.mjs → heap-Blrat--4.mjs} +260 -23
  12. package/dist/inspection-worker.mjs +4 -4
  13. package/dist/{job-BKsifhyv.mjs → job-CBuIMTQ0.mjs} +24 -9
  14. package/dist/{locate-Cx52Zqxv.mjs → locate-D-ZaHpI0.mjs} +5 -0
  15. package/dist/{model-C1UXkHh9.mjs → model-DR9odhWP.mjs} +1 -1
  16. package/dist/operation-executor.mjs +3 -3
  17. package/dist/preview-worker.mjs +1 -1
  18. package/dist/privacy-validator.mjs +28 -8
  19. package/dist/{query-AMZerUh8.mjs → query-BYDcNKy2.mjs} +1614 -679
  20. package/dist/{run-CaPktPhH.mjs → run-DQ9xyKSt.mjs} +4 -4
  21. package/dist/session-process.mjs +20 -0
  22. package/dist/{src-wZx_v0Ih.mjs → src-CKQlTA2Z.mjs} +4 -4
  23. package/dist/{src-DlVbGB32.mjs → src-DeNJ8vOD.mjs} +465 -107
  24. package/dist/{src-D1iONla3.mjs → src-Do-qzuMn.mjs} +377 -130
  25. package/dist/store-database-worker.mjs +1 -1
  26. package/dist/web/assets/index-BgDdPL1c.js +172 -0
  27. package/dist/web/index.html +2 -1
  28. package/package.json +2 -1
  29. package/skills/INDEX.md +6 -4
  30. package/skills/tacitt/INDEX.md +7 -6
  31. package/skills/tacitt/SKILL.md +5 -5
  32. package/skills/tacitt/references/INDEX.md +14 -11
  33. package/skills/tacitt/references/b-method.md +4 -4
  34. package/skills/tacitt/references/bootstrap.md +17 -3
  35. package/skills/tacitt/references/classification.md +1 -1
  36. package/skills/tacitt/references/commands.md +24 -6
  37. package/skills/tacitt/references/journey.md +4 -4
  38. package/skills/tacitt/references/parallel-review.md +13 -7
  39. package/skills/tacitt/references/send.md +7 -3
  40. package/skills/tacitt/scripts/INDEX.md +40 -37
  41. package/skills/tacitt/scripts/answer.mjs +19 -1
  42. package/skills/tacitt/scripts/journey-card-consolidation.mjs +1 -1
  43. package/skills/tacitt/scripts/journey-classification-tasks.mjs +28 -8
  44. package/skills/tacitt/scripts/journey-panel-host.d.mts +2 -0
  45. package/skills/tacitt/scripts/journey-panel-host.mjs +25 -2
  46. package/skills/tacitt/scripts/journey-scan-timing.d.mts +4 -0
  47. package/skills/tacitt/scripts/journey-scan-timing.mjs +12 -0
  48. package/skills/tacitt/scripts/journey-state.mjs +11 -0
  49. package/skills/tacitt/scripts/journey-tasks.mjs +12 -5
  50. package/skills/tacitt/scripts/journey.mjs +10 -2
  51. package/skills/tacitt/scripts/privacy-validator.mjs +28 -7
  52. package/skills/tacitt/scripts/review.mjs +399 -99
  53. package/dist/web/assets/index-CYl7eDUu.js +0 -172
@@ -1,4 +1,4 @@
1
- import { $ as bTermSchema, A as indexBRanges, At as packageConfirmActionSchema, B as unownedBObligations, Bn as cleanupImplementationVersion, Bt as termOverrideValueSchema, C as createBAnalysisUnits, Ct as hidePlanResourceSchema, D as bLiteralTerms, Dt as cardsSubmitSchema, E as bLiteralAdmitted, Et as cardsConfirmActionSchema, F as bUnitFragments, Fn as staticOptions, Ft as emptyReviewCorrectionSchema, G as codePointSlice, H as bEvidenceReader, Ht as termTypeSchema, I as bAdoptedObligations, Jt as journeyProfileAddressActionSchema, K as createCodePointIndex, Kt as sessionPeriodSchema, Lt as reviewTermsInputSchema, M as bDuplicateMirror, Mt as privacyTermKey, Nn as createStaticProcessor, O as bLiterals, On as currentDetectorVersion, P as bLegacyBindings, Pn as staticDefaults, Q as bSessionDecisionSchema, Qn as orderProfile, R as bIssue, Rt as reviewTermsResultSchema, S as validateBReview, St as hidePlanInputSchema, T as validateBUnit, Tt as cardAnswerActionSchema, U as bDigest, Ut as termTypes, V as bAnchorKey, Vn as entityDictionaryVersion, Vt as termTypeInfo, W as codePointLength, Wt as deselectOutsidePeriod, X as bRetainedGroupSchema, Y as bRepresentationSchema, Yt as journeyProfileLinksActionSchema, Z as bReviewSubmissionSchema, Zn as validateProfile, _ as reviewFindingsDigest, _t as journeyInstructionInputSchema, a as reviewBatchChunks, ar as detectStatic, at as journeyAccessSchema, c as reviewDigest, cn as reviewFamilies, ct as journeyExceptionSchema, d as validateReview, dn as observeSource, dt as journeyPreferenceScopeSchema, en as respondProfileLinks, er as validatePlan, et as bAnchorSchema, f as findingReferenceKey, fn as sourceSnapshotId, ft as journeyProjectTypeSchema, g as reviewAlignmentSchema, gn as sourcePartSchema, gt as journeyGuidanceSchema, h as reviewAlignmentInputSchema, hr as defaultDetectionLimits, ht as reviewInterruptionSchema, i as compileBFindings, in as safeCode, it as consentedWithoutAccount, jn as gapReasons, jt as privacyResolveSchema, k as uncoveredBObligations, kn as inspectionSemanticVersions, kt as emptyJourneyPrivacy, l as reviewSubmitSchema, ln as sourceGraph, lt as journeyIdSchema, m as reviewAlignmentAuditSchema, mn as inventorySchema, mr as scalarBefore, mt as nativeJourneySchema, nn as ApplicationError, nt as bIdSchema, o as reviewBatchSchema, on as familyNeedsReview, ot as journeyChoiceSchema, pn as fileIdentitySchema, pr as scalarAfter, pt as journeyWorkTypeSchema, q as subtractBRanges, qt as emptyJourneyProfile, rn as UnfinishedJourneyError, rt as bMethod, s as reviewChunkSchema, sn as familySelected, sr as staticCategories, st as journeyDigestSchema, tn as classificationTitleMaskSchema, tr as copyData, tt as bCountSchema, u as textDigest, un as sourceKey, ur as createEntityMatcher, ut as journeyKindSchema, v as validateReviewAlignment, vn as nativeSourceIdentitySchema, vt as delegatedDecisionSchema, w as validateBFields, wt as journeyConfigurationSchema, x as validateBClassification, xt as hideConfirmSchema, y as semanticFindingSchema, yt as journeyDescribeSchema, z as bOverlaps, zt as termAssessmentSchema } from "./locate-Cx52Zqxv.mjs";
1
+ import { $ as bTermSchema, A as indexBRanges, At as packageConfirmActionSchema, B as unownedBObligations, Bn as cleanupImplementationVersion, Bt as termOverrideValueSchema, C as createBAnalysisUnits, Ct as hidePlanResourceSchema, D as bLiteralTerms, Dt as cardsSubmitSchema, E as bLiteralAdmitted, Et as cardsConfirmActionSchema, F as bUnitFragments, Fn as staticOptions, Ft as emptyReviewCorrectionSchema, G as codePointSlice, H as bEvidenceReader, Ht as termTypeSchema, I as bAdoptedObligations, Jt as journeyProfileAddressActionSchema, K as createCodePointIndex, Kt as sessionPeriodSchema, Lt as reviewTermsInputSchema, M as bDuplicateMirror, Mt as privacyTermKey, Nn as createStaticProcessor, O as bLiterals, On as currentDetectorVersion, P as bLegacyBindings, Pn as staticDefaults, Q as bSessionDecisionSchema, Qn as orderProfile, R as bIssue, Rt as reviewTermsResultSchema, S as validateBReview, St as hidePlanInputSchema, T as validateBUnit, Tt as cardAnswerActionSchema, U as bDigest, Ut as termTypes, V as bAnchorKey, Vn as entityDictionaryVersion, Vt as termTypeInfo, W as codePointLength, Wt as deselectOutsidePeriod, X as bRetainedGroupSchema, Y as bRepresentationSchema, Yt as journeyProfileLinksActionSchema, Z as bReviewSubmissionSchema, Zn as validateProfile, _ as reviewFindingsDigest, _t as journeyInstructionInputSchema, a as reviewBatchChunks, ar as detectStatic, at as journeyAccessSchema, c as reviewDigest, cn as reviewFamilies, ct as journeyExceptionSchema, d as validateReview, dn as observeSource, dt as journeyPreferenceScopeSchema, en as respondProfileLinks, er as validatePlan, et as bAnchorSchema, f as findingReferenceKey, fn as sourceSnapshotId, ft as journeyProjectTypeSchema, g as reviewAlignmentSchema, gn as sourcePartSchema, gt as journeyGuidanceSchema, h as reviewAlignmentInputSchema, hr as defaultDetectionLimits, ht as reviewInterruptionSchema, i as compileBFindings, in as safeCode, it as consentedWithoutAccount, jn as gapReasons, jt as privacyResolveSchema, k as uncoveredBObligations, kn as inspectionSemanticVersions, kt as emptyJourneyPrivacy, l as reviewSubmitSchema, ln as sourceGraph, lt as journeyIdSchema, m as reviewAlignmentAuditSchema, mn as inventorySchema, mr as scalarBefore, mt as nativeJourneySchema, nn as ApplicationError, nt as bIdSchema, o as reviewBatchSchema, on as familyNeedsReview, ot as journeyChoiceSchema, pn as fileIdentitySchema, pr as scalarAfter, pt as journeyWorkTypeSchema, q as subtractBRanges, qt as emptyJourneyProfile, rn as UnfinishedJourneyError, rt as bMethod, s as reviewChunkSchema, sn as familySelected, sr as staticCategories, st as journeyDigestSchema, tn as classificationTitleMaskSchema, tr as copyData, tt as bCountSchema, u as textDigest, un as sourceKey, ur as createEntityMatcher, ut as journeyKindSchema, v as validateReviewAlignment, vn as nativeSourceIdentitySchema, vt as delegatedDecisionSchema, w as validateBFields, wt as journeyConfigurationSchema, x as validateBClassification, xt as hideConfirmSchema, y as semanticFindingSchema, yt as journeyDescribeSchema, z as bOverlaps, zt as termAssessmentSchema } from "./locate-D-ZaHpI0.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";
@@ -1203,6 +1203,14 @@ function requireSelecting(run) {
1203
1203
  function hasCompleteWorkDescription(work) {
1204
1204
  return work.placement === "placed" && !!work.description.trim() && work.classificationRecommendation !== null;
1205
1205
  }
1206
+ /** Explain why a requested Work still has no usable output after rendering. */
1207
+ function unfinishedPackagingCode(work) {
1208
+ if (!work) return "REVISION_CONFLICT";
1209
+ if (work.renderFailure?.revision === work.revision) return work.renderFailure.code;
1210
+ if (!hasCompleteWorkDescription(work)) return "WORK_METADATA_INCOMPLETE";
1211
+ if (!work.accessConfirmed) return "CONFIRMATION_REQUIRED";
1212
+ return "PACKAGING_FAILED";
1213
+ }
1206
1214
  /**
1207
1215
  * Dropped Works are not AI-read; a Work emptied by repartition has nothing left to read, and
1208
1216
  * roots classification has not grouped yet are read once they join a Work (E2).
@@ -1443,6 +1451,19 @@ const sendUploadInputSchema = z.object({
1443
1451
  expectedScopeVersion: count$13
1444
1452
  }).strict();
1445
1453
  const savedSendReceiptSchema = sendReceiptSchema.omit({ upload: true });
1454
+ const sendSessionUploadSchema = z.object({
1455
+ key: journeyDigestSchema,
1456
+ sha256: journeyDigestSchema,
1457
+ /** Byte-started transport/server errors charged to this Send. */
1458
+ attempt: count$13.optional(),
1459
+ /** Transient failures used only to schedule capped zero-byte retries. */
1460
+ retryCount: count$13.optional(),
1461
+ bytesAttempted: count$13.optional(),
1462
+ bytesAcknowledged: count$13.optional(),
1463
+ contentLength: count$13.optional(),
1464
+ bytesSent: count$13.optional(),
1465
+ nextAttemptAt: z.iso.datetime().optional()
1466
+ }).strict();
1446
1467
  const sendItemSchema = z.object({
1447
1468
  workId: journeyIdSchema,
1448
1469
  title: z.string(),
@@ -1471,22 +1492,13 @@ const sendItemSchema = z.object({
1471
1492
  * uploads through staging (ADR 0231).
1472
1493
  */
1473
1494
  checksumUploadRefused: z.literal(true).optional(),
1495
+ /** Selected session ZIPs confirmed by inventory or completion during this traversal. */
1496
+ storedSessions: count$13.optional(),
1474
1497
  /** Write-ahead upload intent; completion probes recover an unacknowledged blob PUT. */
1475
- sessionUpload: z.object({
1476
- key: journeyDigestSchema,
1477
- sha256: journeyDigestSchema,
1478
- /** Byte-started transport/server failures charged to this Send. */
1479
- attempt: count$13.optional(),
1480
- /** Transient failures used only to schedule capped zero-byte retries. */
1481
- retryCount: count$13.optional(),
1482
- bytesAttempted: count$13.optional(),
1483
- bytesAcknowledged: count$13.optional(),
1484
- contentLength: count$13.optional(),
1485
- bytesSent: count$13.optional(),
1486
- nextAttemptAt: z.iso.datetime().optional()
1487
- }).strict().nullable().optional(),
1498
+ sessionUpload: sendSessionUploadSchema.nullable().optional(),
1488
1499
  /** Local key-rule marker; current membership replays need no artifact migration inspection. */
1489
1500
  sessionMembershipKeyVersion: z.literal(2).optional(),
1501
+ sessionMembershipMetadataVersion: z.literal(1).optional(),
1490
1502
  /** Exact write-ahead membership request; never rebase it after an uncertain PUT. */
1491
1503
  sessionMembership: z.object({
1492
1504
  workId: journeyIdSchema,
@@ -1658,19 +1670,32 @@ function hasCurrentStaticReview(state, work) {
1658
1670
  }
1659
1671
  //#endregion
1660
1672
  //#region packages/application/src/journey/privacy/record.ts
1661
- /** Merge independently reviewed occurrences into one journey-wide decision. */
1662
- function mergePrivacyTerms(state, incoming) {
1663
- const terms = new Map(state.privacy.terms.map((term) => [privacyTermKey(term), term]));
1673
+ /** Only a stored human rule or an explicitly delegated category choice can settle a reader proposal. */
1674
+ function currentTermRules(state) {
1664
1675
  const overrides = /* @__PURE__ */ new Map();
1665
1676
  for (const item of state.valueOverrides ?? []) {
1666
1677
  const value = item.value.normalize("NFC");
1667
1678
  if (!overrides.has(value)) overrides.set(value, item);
1668
1679
  }
1680
+ const categories = new Map(state.groups.filter((group) => group.origin === "preference" || group.confirmed && (group.origin === "explicit" || group.origin === "delegate")).map((group) => [group.key, group.choice]));
1681
+ function choice(term) {
1682
+ return overrides.get(term.value.normalize("NFC"))?.choice ?? categories.get(`type:${term.type}`);
1683
+ }
1684
+ return {
1685
+ overrides,
1686
+ choice
1687
+ };
1688
+ }
1689
+ /** Merge independently reviewed occurrences into one journey-wide decision. */
1690
+ function mergePrivacyTerms(state, incoming) {
1691
+ const terms = new Map(state.privacy.terms.map((term) => [privacyTermKey(term), term]));
1692
+ const rules = currentTermRules(state);
1693
+ const overrides = rules.overrides;
1669
1694
  for (const term of incoming) {
1670
- const key = privacyTermKey(term), prior = terms.get(key);
1671
- const override = overrides.get(term.value.normalize("NFC"));
1672
- const preference = state.groups.find((group) => group.key === `type:${term.type}` && group.origin === "preference");
1673
- const disposition = !termTypeInfo[term.type].asked ? "hidden" : override ? override.choice === "hide" ? "hidden" : "keep" : preference?.choice ? preference.choice === "hide" ? "hidden" : "keep" : prior?.disposition === "hidden" || term.disposition === "hidden" ? "hidden" : prior && prior.disposition !== term.disposition ? "pending" : term.disposition;
1695
+ const key = privacyTermKey(term);
1696
+ const prior = terms.get(key);
1697
+ const choice = rules.choice(term);
1698
+ const disposition = !termTypeInfo[term.type].asked || choice === "hide" ? "hidden" : choice === "keep" ? "keep" : prior?.disposition === "hidden" || term.disposition === "hidden" ? "hidden" : "pending";
1674
1699
  const sources = [...new Map([...prior?.sources ?? [], ...term.sources].map((source) => [JSON.stringify(source.kind === "session" ? [
1675
1700
  source.workId,
1676
1701
  source.batchId,
@@ -1680,7 +1705,7 @@ function mergePrivacyTerms(state, incoming) {
1680
1705
  ...term,
1681
1706
  disposition,
1682
1707
  sources,
1683
- reason: prior && prior.disposition !== term.disposition ? disposition === "pending" ? "Conflicting scan judgments require a contextual decision." : disposition === "hidden" ? "A Hidden judgment for this keyword takes precedence." : term.reason : term.reason
1708
+ reason: term.disposition === "keep" && disposition === "pending" ? "A current decision is required to keep this value." : choice && term.disposition !== disposition ? "The current value or category decision applies." : prior && prior.disposition !== term.disposition ? disposition === "pending" ? "Conflicting scan judgments require a contextual decision." : disposition === "hidden" ? "A Hidden judgment for this keyword takes precedence." : term.reason : term.reason
1684
1709
  });
1685
1710
  }
1686
1711
  const values = Map.groupBy([...terms.values()], (term) => term.value.normalize("NFC"));
@@ -1715,6 +1740,97 @@ function activePrivacyTerms(state) {
1715
1740
  return state.works.some((work) => work.access !== "drop" && work.rootSessionIds.length > 0) ? state.privacy.terms : [];
1716
1741
  }
1717
1742
  //#endregion
1743
+ //#region packages/application/src/export/versions.ts
1744
+ /** Current built-in admission, annotation and retention contracts; implementations share these. */
1745
+ const nativeAdapterVersions = Object.freeze({
1746
+ claude: "claude-native-export-v19",
1747
+ codex: "codex-native-export-v16"
1748
+ });
1749
+ /** Shared metadata annotation/preparation semantics, independent of serialization formats. */
1750
+ const metadataProcessingVersion = "metadata-annotations-v1";
1751
+ //#endregion
1752
+ //#region packages/application/src/journey/adapters.ts
1753
+ /** The adapter contracts a Journey's snapshot is prepared under. */
1754
+ const currentJourneyAdapters = () => ({
1755
+ claude: `${nativeAdapterVersions.claude}/main-prose-source-scan-v3`,
1756
+ codex: `${nativeAdapterVersions.codex}/main-prose-source-scan-v3`
1757
+ });
1758
+ /**
1759
+ * An unfinished snapshot frozen under other adapter contracts (absent: an earlier release), or
1760
+ * read by B review instead of dictionary review (ADR 0086), cannot render its Works (ADR 0076).
1761
+ * A new scan replaces it unless a Work was sent or a Send may have reached Passport, which the
1762
+ * store keeps for the person to finish (ADR 0284).
1763
+ */
1764
+ function obsoleteJourney(state) {
1765
+ return state.phase !== "completed" && state.snapshotId !== null && (state.adapters?.claude !== currentJourneyAdapters().claude || state.adapters.codex !== currentJourneyAdapters().codex || state.reviewMethod !== "dictionary");
1766
+ }
1767
+ /** A receipt or persisted session mutation intent means a Send may have reached Passport. */
1768
+ function sendReachedPassport(send) {
1769
+ return send.items.some((item) => item.receipt || item.previousReceipts.length || item.sessionUpload !== void 0 || item.sessionMembership || item.sessionAssembly);
1770
+ }
1771
+ /**
1772
+ * ADR 0284: Passport acknowledged this Send's Work: this Send's receipt for it is past
1773
+ * `awaiting_upload`, or its session membership is acknowledged. An `awaiting_upload` receipt is
1774
+ * an empty reservation, and a reservation, a session upload intent or a membership intent is saved
1775
+ * before the call it announces, so none of them shows that anything left.
1776
+ */
1777
+ function itemAtPassport(item) {
1778
+ return Boolean(item.receipt && item.receipt.state !== "awaiting_upload" || item.sessionAssembly);
1779
+ }
1780
+ /**
1781
+ * The Works the next advance steps without the person to send something: an upload, a
1782
+ * completion or a confirmed access change. `pickBatch` selects upload work by this; a Work being
1783
+ * assessed is only read, and the other states wait on the person or have ended.
1784
+ */
1785
+ function sendsOnNextAdvance(item) {
1786
+ return item.status === "uploading" || item.status === "ready";
1787
+ }
1788
+ /**
1789
+ * A completed Send that Passport has not finished with: a Work is still assessed or reapplied
1790
+ * (ADR 0233). A blocked Work waits on the person's Retry, not on Passport.
1791
+ */
1792
+ function awaitingPassport(send) {
1793
+ return send.status === "completed" && send.items.some((item) => !["completed", "blocked"].includes(item.status));
1794
+ }
1795
+ /**
1796
+ * Whether an advance steps this Send's Works at all. `advanceSend` returns early exactly when this
1797
+ * is false: the person paused the journey, the Send is unconfirmed, paused or prepared, or it is
1798
+ * completed with every Work settled. A blocked Send is stepped only to re-check its scope.
1799
+ */
1800
+ function advanceStepsSend(journey, send) {
1801
+ return journey.phase !== "paused" && send.confirmedAt !== null && send.status !== "paused" && send.status !== "prepared" && !(send.status === "completed" && send.items.every((item) => item.status === "completed" || item.status === "blocked"));
1802
+ }
1803
+ /**
1804
+ * Whether a Send in each state is stepped without the person once `advanceStepsSend` holds.
1805
+ * Every status is listed, so a new one fails the type check until it is classified. Unconfirmed
1806
+ * requests and the person's pause, refusal, sign-in and review decisions stay explicit.
1807
+ */
1808
+ const drivenWithoutPerson = {
1809
+ "awaiting-packaging": false,
1810
+ prepared: false,
1811
+ "sign-in": false,
1812
+ review: false,
1813
+ paused: false,
1814
+ blocked: false,
1815
+ sending: true,
1816
+ waiting: true,
1817
+ completed: true
1818
+ };
1819
+ /**
1820
+ * The one decision whether the advance steps a Send without the person: the detached host's
1821
+ * timer drives exactly these Sends, and a CLI step defers to a live host for them (ADR 0271).
1822
+ */
1823
+ function hostDrives(journey, send) {
1824
+ return advanceStepsSend(journey, send) && drivenWithoutPerson[send.status];
1825
+ }
1826
+ /**
1827
+ * ADR 0284: a Work at Passport still owes Passport something that this Send's next advance sends
1828
+ * without the person. An obsolete journey gives way unless its current Send owes.
1829
+ */
1830
+ function sendOwesPassport(journey, send) {
1831
+ return hostDrives(journey, send) && send.items.some((item) => itemAtPassport(item) && sendsOnNextAdvance(item));
1832
+ }
1833
+ //#endregion
1718
1834
  //#region packages/application/src/journey/policy/commands.ts
1719
1835
  const journeyFindingReferenceSchema = z.object({
1720
1836
  batchId: journeyIdSchema,
@@ -2067,6 +2183,7 @@ const nativeRespondSchema = z.object({
2067
2183
  const nativeEventsSchema = z.object({
2068
2184
  journeyId: journeyIdSchema,
2069
2185
  after: z.number().int().nonnegative(),
2186
+ changesOnly: z.boolean().optional(),
2070
2187
  waitMs: z.number().int().min(0).max(3e4).default(0)
2071
2188
  }).strict();
2072
2189
  //#endregion
@@ -2141,6 +2258,58 @@ function assertPublicChoices(state) {
2141
2258
  function assertJourneyStaticReady(state) {
2142
2259
  if (state.works.some((work) => work.access !== "drop" && work.rootSessionIds.length > 0 && !isSkippedWork(work) && !hasCurrentStaticReview(state, work))) throw new ApplicationError("SCOPE_NOT_READY");
2143
2260
  }
2261
+ /** Check a proposed or stored Keep against the current structured decisions. An answered
2262
+ * card covers its actual members, including the opposite choice for an unticked member. */
2263
+ function keepAuthority(state) {
2264
+ const rules = currentTermRules(state);
2265
+ const { keep, hide } = answeredValues(state);
2266
+ const mandatory = new Set(state.privacy.terms.filter((term) => !termTypeInfo[term.type].asked).map((term) => term.value.normalize("NFC")));
2267
+ const own = workProjectNames(state);
2268
+ return (term) => {
2269
+ const value = term.value.normalize("NFC");
2270
+ if (mandatory.has(value)) return "hidden";
2271
+ const override = rules.overrides.get(value);
2272
+ if (override) return override.choice === "keep" ? "keep" : "hidden";
2273
+ if (keep.has(value) && own.has(value.toLowerCase())) return "keep";
2274
+ if (hide.has(value)) return "hidden";
2275
+ if (keep.has(value)) return "keep";
2276
+ const choice = rules.choice(term);
2277
+ return choice === "keep" ? "keep" : choice === "hide" ? "hidden" : "pending";
2278
+ };
2279
+ }
2280
+ const reconciledKeeps = /* @__PURE__ */ new WeakMap();
2281
+ /** Recover unresolved visibility in a stored unfinished journey without repeating source reads. */
2282
+ function reconcileReaderKeeps(state) {
2283
+ if (state.phase === "completed") return state;
2284
+ const cached = reconciledKeeps.get(state);
2285
+ if (cached) return cached;
2286
+ let result = state;
2287
+ if (state.privacy.terms.some((term) => term.disposition === "keep")) {
2288
+ const authority = keepAuthority(state);
2289
+ let changed = false;
2290
+ const terms = state.privacy.terms.map((term) => {
2291
+ if (term.disposition !== "keep") return term;
2292
+ const disposition = authority(term);
2293
+ if (disposition === "keep") return term;
2294
+ changed = true;
2295
+ return {
2296
+ ...term,
2297
+ disposition,
2298
+ reason: "Current privacy decisions require review of this value."
2299
+ };
2300
+ });
2301
+ if (changed) result = {
2302
+ ...retirePrivacyArtifacts(state),
2303
+ privacy: {
2304
+ ...state.privacy,
2305
+ terms,
2306
+ packageApproval: null
2307
+ }
2308
+ };
2309
+ }
2310
+ reconciledKeeps.set(state, result);
2311
+ return result;
2312
+ }
2144
2313
  /**
2145
2314
  * Cards need only Track A, AI review and metadata; this final gate also needs Track B.
2146
2315
  * `publicChoices` defaults to `packaging`: the Send click checks it before packaging, and the
@@ -2149,7 +2318,7 @@ function assertJourneyStaticReady(state) {
2149
2318
  function assertJourneyPrivacyReady(state, packaging = false, { publicChoices = packaging } = {}) {
2150
2319
  assertJourneyScanned(state);
2151
2320
  if (publicChoices) assertPublicChoices(state);
2152
- if (activePrivacyTerms(state).some((term) => term.disposition === "pending") || state.privacy.cards.length > 0 && (state.privacy.cards.some((card) => !card.answer) || state.privacy.confirmedAnswersRevision !== state.privacy.answersRevision)) throw new ApplicationError("CONFIRMATION_REQUIRED");
2321
+ if (reconcileReaderKeeps(state) !== state || activePrivacyTerms(state).some((term) => term.disposition === "pending") || state.privacy.cards.length > 0 && (state.privacy.cards.some((card) => !card.answer) || state.privacy.confirmedAnswersRevision !== state.privacy.answersRevision)) throw new ApplicationError("CONFIRMATION_REQUIRED");
2153
2322
  assertJourneyStaticReady(state);
2154
2323
  if (packaging && state.privacy.packageApproval !== privacyDecisionDigest(state)) throw new ApplicationError("CONFIRMATION_REQUIRED");
2155
2324
  }
@@ -2169,7 +2338,7 @@ function ownIdentityValues(state) {
2169
2338
  }
2170
2339
  /**
2171
2340
  * D3: a batch covers only Pending values no card covers yet. Values added to an existing card
2172
- * take its answer at once when the person already answered it.
2341
+ * take its answer, except new literals on an answered Keep card arrive Hidden off-card.
2173
2342
  */
2174
2343
  function appendDecisionCards(state, input) {
2175
2344
  assertCardsAllowed(state);
@@ -2196,12 +2365,27 @@ function appendDecisionCards(state, input) {
2196
2365
  if (term?.type === "people" && ownCard && !ownValues.has(identityValue(term.value))) throw new ApplicationError("INVALID_SELECTION", "cards.append.other-person");
2197
2366
  }
2198
2367
  }
2199
- const additions = new Map(extend.map((item) => [item.cardId, item.termKeys]));
2200
- const inherited = new Map(extend.flatMap((item) => item.termKeys.map((key) => [key, item.cardId])));
2368
+ const keepCards = state.privacy.cards.filter((card) => card.answer?.optionId === "keep");
2369
+ const keptValues = new Set(keepCards.flatMap((card) => card.termKeys.flatMap((key) => {
2370
+ const term = terms.get(key);
2371
+ return term?.disposition === "keep" && !card.answer?.excludedTermKeys?.includes(key) ? [term.value.normalize("NFC")] : [];
2372
+ })));
2373
+ const diverted = new Set(extend.flatMap((item) => keepCards.some((card) => card.id === item.cardId) ? item.termKeys.filter((key) => !keptValues.has(terms.get(key)?.value.normalize("NFC") ?? "")) : []));
2374
+ const joined = extend.map((item) => ({
2375
+ ...item,
2376
+ termKeys: item.termKeys.filter((key) => !diverted.has(key))
2377
+ }));
2378
+ const additions = new Map(joined.map((item) => [item.cardId, item.termKeys]));
2379
+ const inherited = new Map(joined.flatMap((item) => item.termKeys.map((key) => [key, item.cardId])));
2201
2380
  return applyCardAnswers({
2202
2381
  ...retirePrivacyArtifacts(state),
2203
2382
  privacy: {
2204
2383
  ...state.privacy,
2384
+ terms: state.privacy.terms.map((term) => diverted.has(privacyTermKey(term)) ? {
2385
+ ...term,
2386
+ disposition: "hidden",
2387
+ reason: "Found after you answered Keep on its card; hidden."
2388
+ } : term),
2205
2389
  cards: [...state.privacy.cards.map((card) => {
2206
2390
  const added = additions.get(card.id);
2207
2391
  if (!added) return card;
@@ -2264,11 +2448,14 @@ function resolvePrivacyTerms(state, input) {
2264
2448
  terms
2265
2449
  }
2266
2450
  }), (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");
2451
+ const normalized = normalizeValues(state, terms);
2452
+ const canKeep = keepAuthority(state);
2453
+ if (normalized.some((term) => resolutions.has(privacyTermKey(term)) && term.disposition === "keep" && canKeep(term) !== "keep")) throw new ApplicationError("CONFIRMATION_REQUIRED");
2267
2454
  return {
2268
2455
  ...retirePrivacyArtifacts(state),
2269
2456
  privacy: {
2270
2457
  ...state.privacy,
2271
- terms: normalizeValues(state, terms),
2458
+ terms: normalized,
2272
2459
  packageApproval: null
2273
2460
  }
2274
2461
  };
@@ -2281,6 +2468,22 @@ function answeredKeys(state, optionId) {
2281
2468
  return card.answer.optionId === optionId ? card.termKeys.filter((key) => !excluded.has(key)) : [...excluded];
2282
2469
  }));
2283
2470
  }
2471
+ function answeredValues(state) {
2472
+ const keepKeys = answeredKeys(state, "keep");
2473
+ const hideKeys = answeredKeys(state, "hide");
2474
+ const keep = /* @__PURE__ */ new Set();
2475
+ const hide = /* @__PURE__ */ new Set();
2476
+ for (const term of state.privacy.terms) {
2477
+ const key = privacyTermKey(term);
2478
+ const value = term.value.normalize("NFC");
2479
+ if (keepKeys.has(key)) keep.add(value);
2480
+ if (hideKeys.has(key)) hide.add(value);
2481
+ }
2482
+ return {
2483
+ keep,
2484
+ hide
2485
+ };
2486
+ }
2284
2487
  /** One NFC value has one outcome across term types, cards and per-value rules. */
2285
2488
  function normalizeValues(state, input) {
2286
2489
  const active = activePrivacyTerms({
@@ -2290,17 +2493,8 @@ function normalizeValues(state, input) {
2290
2493
  terms: input
2291
2494
  }
2292
2495
  });
2293
- const overrides = /* @__PURE__ */ new Map();
2294
- for (const item of state.valueOverrides ?? []) {
2295
- const value = item.value.normalize("NFC");
2296
- if (!overrides.has(value)) overrides.set(value, item);
2297
- }
2298
- const cardValues = (optionId) => {
2299
- const keys = answeredKeys(state, optionId);
2300
- return new Set(state.privacy.terms.filter((term) => keys.has(privacyTermKey(term))).map((term) => term.value.normalize("NFC")));
2301
- };
2302
- const hideCardValues = cardValues("hide");
2303
- const keepCardValues = cardValues("keep");
2496
+ const { overrides } = currentTermRules(state);
2497
+ const { keep: keepCardValues, hide: hideCardValues } = answeredValues(state);
2304
2498
  const ownNames = workProjectNames(state);
2305
2499
  const normalized = /* @__PURE__ */ new Map();
2306
2500
  for (const same of Map.groupBy(active, (term) => term.value.normalize("NFC")).values()) {
@@ -2404,6 +2598,7 @@ function respondPrivacy(state, action, source) {
2404
2598
  };
2405
2599
  }
2406
2600
  if (action.kind === "package-confirm") {
2601
+ if (obsoleteJourney(state)) throw new ApplicationError("JOURNEY_OBSOLETE");
2407
2602
  assertPublicChoices(state);
2408
2603
  assertJourneyPrivacyReady(state);
2409
2604
  return {
@@ -2579,6 +2774,12 @@ const journeyClassificationSubmitSchema = z.object({
2579
2774
  */
2580
2775
  expectedClassificationRevision: count$10.optional()
2581
2776
  }).strict();
2777
+ /** Restore only the split families that can be proven against the accepted original proposal. */
2778
+ const isolatedMetadataRecoverySchema = z.object({
2779
+ proposal: journeyClassificationSubmitSchema,
2780
+ workIds: z.array(journeyIdSchema).min(1).max(1e3),
2781
+ idempotencyKey: journeyIdSchema
2782
+ }).strict();
2582
2783
  const journeyClassificationSessionsSchema = z.object({
2583
2784
  journeyId: journeyIdSchema,
2584
2785
  workId: journeyIdSchema,
@@ -3052,9 +3253,17 @@ function unclassifiedBHits(hits, literals, negative) {
3052
3253
  return issues;
3053
3254
  }
3054
3255
  const bSpacedWord = (value) => /[\p{L}\p{N}_]/u.test(value) && !/[\p{sc=Han}\p{sc=Hiragana}\p{sc=Katakana}\p{sc=Thai}\p{sc=Lao}\p{sc=Khmer}\p{sc=Myanmar}]/u.test(value);
3256
+ /** In decoded tool text an odd backslash run escapes its following n, r or t. */
3257
+ function afterEscapedSpace(text, start) {
3258
+ const letter = text[start - 1];
3259
+ if (letter !== "n" && letter !== "r" && letter !== "t") return false;
3260
+ let index = start - 2;
3261
+ while (index >= 0 && text[index] === "\\") index--;
3262
+ return (start - 2 - index) % 2 === 1;
3263
+ }
3055
3264
  /** A confirmed Hide value matches only where it does not run into a neighbouring word (ADR 0069). */
3056
- function bWordBounded(text, start, end) {
3057
- return !(bSpacedWord(scalarBefore(text, start)) && bSpacedWord(scalarAfter(text, start)) || bSpacedWord(scalarBefore(text, end)) && bSpacedWord(scalarAfter(text, end)));
3265
+ function bWordBounded(text, start, end, toolResultEscapes = false) {
3266
+ return !(bSpacedWord(scalarBefore(text, start)) && bSpacedWord(scalarAfter(text, start)) && !(toolResultEscapes && afterEscapedSpace(text, start)) || bSpacedWord(scalarBefore(text, end)) && bSpacedWord(scalarAfter(text, end)));
3058
3267
  }
3059
3268
  /**
3060
3269
  * Occurrences of a Work's explicit exceptions, matched like Hide everywhere: exact NFC values
@@ -3126,6 +3335,14 @@ const maximumHideIndexTokens = 2e6;
3126
3335
  * has too many such positions to list.
3127
3336
  */
3128
3337
  function addHideIndexTokens(text, add) {
3338
+ let complete = ordinaryTokens(text, add);
3339
+ if (text.includes("\\")) {
3340
+ if (/^\s*[[{]/u.test(text) && text.includes("\\u")) return false;
3341
+ for (const [, word] of text.matchAll(/\\[nrt]([\p{L}\p{N}\p{M}_]+)/gu)) if (word) complete = ordinaryTokens(word, add) && complete;
3342
+ }
3343
+ return complete;
3344
+ }
3345
+ function ordinaryTokens(text, add) {
3129
3346
  let complete = true;
3130
3347
  let from = 0;
3131
3348
  for (const { index } of text.matchAll(/[^\p{ASCII}]+/gu)) {
@@ -3944,6 +4161,40 @@ const journeyPreparationProgressSchema = z.object({
3944
4161
  capturedBytes: preparationCountSchema
3945
4162
  }).strict();
3946
4163
  //#endregion
4164
+ //#region packages/application/src/journey/inventory/progress.ts
4165
+ /** State-only gate: the scope is confirmed and a selected Work still waits for preparation. */
4166
+ function preparationInProgress(state) {
4167
+ return state.consent !== null && state.snapshotId !== null && state.scope.status === "confirmed" && state.works.some((work) => work.status === "pending" && isSelectedWork(work));
4168
+ }
4169
+ /**
4170
+ * Capture counts cover only the selected Works' frozen parts, so Dropped Works never hold the
4171
+ * total open. Captured bytes can end below the frozen size at a complete record boundary.
4172
+ * Current Works are the pending selected Works whose newest attempt has no settlement, in
4173
+ * Work order; several prepare at once.
4174
+ */
4175
+ function projectPreparationProgress(state, families, captures, starts, settlements) {
4176
+ const selected = state.works.filter(isSelectedWork);
4177
+ const sizes = /* @__PURE__ */ new Map();
4178
+ for (const id of selected.flatMap((work) => work.rootSessionIds)) {
4179
+ const members = families.members.get(id);
4180
+ if (!members) throw new ApplicationError("CORRUPTED_STATE");
4181
+ for (const part of members.flatMap((session) => session.parts)) sizes.set(part.id, part.snapshot.size);
4182
+ }
4183
+ const captured = captures.filter((resource) => sizes.has(resource.partId));
4184
+ const settled = new Set(settlements.map((item) => item.id));
4185
+ return {
4186
+ currentWorkIds: selected.filter((work) => {
4187
+ if (work.status !== "pending") return false;
4188
+ const newest = starts.filter((start) => start.workId === work.id && start.inputRevision === work.inputRevision).reduce((latest, start) => !latest || start.sequence > latest.sequence ? start : latest, void 0);
4189
+ return newest !== void 0 && !settled.has(newest.id);
4190
+ }).map((work) => work.id),
4191
+ targetParts: sizes.size,
4192
+ capturedParts: captured.length,
4193
+ targetBytes: [...sizes.values()].reduce((sum, size) => sum + size, 0),
4194
+ capturedBytes: captured.reduce((sum, resource) => sum + resource.bytes, 0)
4195
+ };
4196
+ }
4197
+ //#endregion
3947
4198
  //#region packages/application/src/source/resolve.ts
3948
4199
  /** Queue-based ancestry resolution cannot leak deep descendants through a recursion cutoff. */
3949
4200
  function resolveParts(inventory, route) {
@@ -4857,6 +5108,31 @@ const journeyCaptureSchema = z.object({
4857
5108
  source: sourcePartSchema
4858
5109
  }).strict();
4859
5110
  const base = { journeyId: journeyIdSchema };
5111
+ const journeyOutputSchema = z.object({
5112
+ ...base,
5113
+ kind: z.literal("output"),
5114
+ workId: journeyIdSchema,
5115
+ revision: z.number().int().positive(),
5116
+ bundleId: journeyIdSchema,
5117
+ decisionDigest: journeyDigestSchema,
5118
+ primary: journeyFileSchema,
5119
+ companion: journeyFileSchema,
5120
+ finalMaskLedger: journeyFileSchema.extend({
5121
+ primarySha256: journeyDigestSchema,
5122
+ basePrimarySha256: journeyDigestSchema,
5123
+ workId: journeyIdSchema,
5124
+ inputRevision: z.number().int().positive(),
5125
+ decisionDigest: journeyDigestSchema,
5126
+ occurrences: z.number().int().nonnegative(),
5127
+ contributors: z.number().int().nonnegative(),
5128
+ categories: z.object({
5129
+ identity: z.number().int().nonnegative(),
5130
+ credentials: z.number().int().nonnegative(),
5131
+ internal: z.number().int().nonnegative(),
5132
+ private: z.number().int().nonnegative()
5133
+ }).strict()
5134
+ }).strict()
5135
+ }).strict();
4860
5136
  const journeyResourceSchema = z.discriminatedUnion("kind", [
4861
5137
  z.object({
4862
5138
  ...base,
@@ -4976,31 +5252,7 @@ const journeyResourceSchema = z.discriminatedUnion("kind", [
4976
5252
  bundleSourceId: z.string().min(1)
4977
5253
  }).strict())
4978
5254
  }).strict(),
4979
- z.object({
4980
- ...base,
4981
- kind: z.literal("output"),
4982
- workId: journeyIdSchema,
4983
- revision: z.number().int().positive(),
4984
- bundleId: journeyIdSchema,
4985
- decisionDigest: journeyDigestSchema,
4986
- primary: journeyFileSchema,
4987
- companion: journeyFileSchema,
4988
- finalMaskLedger: journeyFileSchema.extend({
4989
- primarySha256: journeyDigestSchema,
4990
- basePrimarySha256: journeyDigestSchema,
4991
- workId: journeyIdSchema,
4992
- inputRevision: z.number().int().positive(),
4993
- decisionDigest: journeyDigestSchema,
4994
- occurrences: z.number().int().nonnegative(),
4995
- contributors: z.number().int().nonnegative(),
4996
- categories: z.object({
4997
- identity: z.number().int().nonnegative(),
4998
- credentials: z.number().int().nonnegative(),
4999
- internal: z.number().int().nonnegative(),
5000
- private: z.number().int().nonnegative()
5001
- }).strict()
5002
- }).strict()
5003
- }).strict()
5255
+ journeyOutputSchema
5004
5256
  ]);
5005
5257
  const journeyResourceQuerySchema = z.union([
5006
5258
  z.object({
@@ -5057,40 +5309,37 @@ const journeyResourceQuerySchema = z.union([
5057
5309
  }).strict()
5058
5310
  ]);
5059
5311
  //#endregion
5060
- //#region packages/application/src/journey/inventory/progress.ts
5061
- /** State-only gate: the scope is confirmed and a selected Work still waits for preparation. */
5062
- function preparationInProgress(state) {
5063
- return state.consent !== null && state.snapshotId !== null && state.scope.status === "confirmed" && state.works.some((work) => work.status === "pending" && isSelectedWork(work));
5064
- }
5065
- /**
5066
- * Capture counts cover only the selected Works' frozen parts, so Dropped Works never hold the
5067
- * total open. Captured bytes can end below the frozen size at a complete record boundary.
5068
- * Current Works are the pending selected Works whose newest attempt has no settlement, in
5069
- * Work order; several prepare at once.
5070
- */
5071
- function projectPreparationProgress(state, plan, captures, starts, settlements) {
5072
- const families = reviewFamilies(plan.approval.inventory);
5073
- const selected = state.works.filter(isSelectedWork);
5074
- const sizes = /* @__PURE__ */ new Map();
5075
- for (const id of selected.flatMap((work) => work.rootSessionIds)) {
5076
- const members = families.members.get(id);
5077
- if (!members) throw new ApplicationError("CORRUPTED_STATE");
5078
- for (const part of members.flatMap((session) => session.parts)) sizes.set(part.id, part.snapshot.size);
5079
- }
5080
- const captured = captures.filter((resource) => sizes.has(resource.capture.partId));
5081
- const settled = new Set(settlements.map((item) => item.id));
5082
- return {
5083
- currentWorkIds: selected.filter((work) => {
5084
- if (work.status !== "pending") return false;
5085
- const newest = starts.filter((start) => start.workId === work.id && start.inputRevision === work.inputRevision).reduce((latest, start) => !latest || start.sequence > latest.sequence ? start : latest, void 0);
5086
- return newest !== void 0 && !settled.has(newest.id);
5087
- }).map((work) => work.id),
5088
- targetParts: sizes.size,
5089
- capturedParts: captured.length,
5090
- targetBytes: [...sizes.values()].reduce((sum, size) => sum + size, 0),
5091
- capturedBytes: captured.reduce((sum, resource) => sum + resource.capture.facts.byteLength, 0)
5092
- };
5093
- }
5312
+ //#region packages/application/src/journey/send/port.ts
5313
+ /** Storage validates current package approval before releasing one Work's frozen descriptor. */
5314
+ const sendOutputQuerySchema = z.object({
5315
+ journeyId: z.uuid(),
5316
+ workId: z.uuid(),
5317
+ revision: z.number().int().positive(),
5318
+ sessions: z.boolean()
5319
+ }).strict();
5320
+ const sendOutputSchema = z.object({
5321
+ output: journeyOutputSchema,
5322
+ extension: z.object({
5323
+ approval: z.string(),
5324
+ groups: z.array(z.array(z.string())),
5325
+ sources: z.array(z.object({
5326
+ session: z.string(),
5327
+ source: z.string(),
5328
+ part: sourcePartSchema
5329
+ })),
5330
+ outputs: z.array(z.object({
5331
+ workId: z.uuid(),
5332
+ revision: z.number().int(),
5333
+ sha256: z.string(),
5334
+ bundleId: z.string()
5335
+ }))
5336
+ }).strict().optional(),
5337
+ identities: z.array(z.object({
5338
+ archiveSessionId: z.string(),
5339
+ relativePath: z.string(),
5340
+ lastAt: z.iso.datetime()
5341
+ }).strict())
5342
+ }).strict();
5094
5343
  //#endregion
5095
5344
  //#region packages/application/src/journey/policy/port.ts
5096
5345
  const journeyPolicyRespondSchema = z.object({
@@ -5224,6 +5473,14 @@ function newJourneyWork(id, projectName, rootSessionIds, sourceWorkspaceIds, pla
5224
5473
  binding: null
5225
5474
  };
5226
5475
  }
5476
+ /** Stable blocked Work IDs per parent, so later failing roots join one instead of multiplying. */
5477
+ function isolatedWorkId(parentId, ordinal) {
5478
+ const bytes = createHash("sha256").update(`isolated-roots:${parentId}:${ordinal}`).digest().subarray(0, 16);
5479
+ bytes[6] = (bytes[6] ?? 0) & 15 | 64;
5480
+ bytes[8] = (bytes[8] ?? 0) & 63 | 128;
5481
+ const hex = bytes.toString("hex");
5482
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
5483
+ }
5227
5484
  //#endregion
5228
5485
  //#region packages/application/src/journey/scan-generation.ts
5229
5486
  /** Retire one scan generation while preserving the person's confirmed classification. */
@@ -5890,6 +6147,7 @@ function respondToJourney(state, action, source, now, decision, preferenceScope,
5890
6147
  reason: action.reason
5891
6148
  }];
5892
6149
  } else {
6150
+ if (source !== "panel") throw new ApplicationError("CONFIRMATION_REQUIRED");
5893
6151
  if (previous?.reason !== "retry-exhausted") throw new ApplicationError("INVALID_TRANSITION");
5894
6152
  nextHolds = holds.filter((item) => item.packId !== action.packId);
5895
6153
  }
@@ -6282,30 +6540,6 @@ async function readGroupItems(storage, value) {
6282
6540
  };
6283
6541
  }
6284
6542
  //#endregion
6285
- //#region packages/application/src/export/versions.ts
6286
- /** Current built-in admission, annotation and retention contracts; implementations share these. */
6287
- const nativeAdapterVersions = Object.freeze({
6288
- claude: "claude-native-export-v19",
6289
- codex: "codex-native-export-v16"
6290
- });
6291
- /** Shared metadata annotation/preparation semantics, independent of serialization formats. */
6292
- const metadataProcessingVersion = "metadata-annotations-v1";
6293
- //#endregion
6294
- //#region packages/application/src/journey/adapters.ts
6295
- /** The adapter contracts a Journey's snapshot is prepared under. */
6296
- const currentJourneyAdapters = () => ({
6297
- claude: `${nativeAdapterVersions.claude}/main-prose-source-scan-v2`,
6298
- codex: `${nativeAdapterVersions.codex}/main-prose-source-scan-v2`
6299
- });
6300
- /**
6301
- * An unfinished snapshot frozen under other adapter contracts (absent: an earlier release), or
6302
- * read by B review instead of dictionary review (ADR 0086), cannot render its Works (ADR 0076).
6303
- * A new scan replaces it unless it holds a Send, which the store keeps for the person to finish.
6304
- */
6305
- function obsoleteJourney(state) {
6306
- return state.phase !== "completed" && state.snapshotId !== null && (state.adapters?.claude !== currentJourneyAdapters().claude || state.adapters.codex !== currentJourneyAdapters().codex || state.reviewMethod !== "dictionary");
6307
- }
6308
- //#endregion
6309
6543
  //#region packages/application/src/journey/correction/anchors.ts
6310
6544
  /** Exact frozen-field validation only: no fuzzy relocation, context ownership or other unit. */
6311
6545
  function locateCorrectionAnchors(batch, anchors) {
@@ -6786,7 +7020,7 @@ async function joinRender(port, journeyId, workId, run, signal, retryConflict =
6786
7020
  }
6787
7021
  function createNativeJourney(storage, now = () => (/* @__PURE__ */ new Date()).toISOString(), local) {
6788
7022
  /** Callers present after their write is durable, so a concurrent commit must not turn it into an error. */
6789
- async function present(committed) {
7023
+ async function present(committed, includePreparationProgress = true) {
6790
7024
  let state = committed;
6791
7025
  for (let attempt = 1;; attempt++) {
6792
7026
  const view = journeyView(state, now());
@@ -6806,7 +7040,7 @@ function createNativeJourney(storage, now = () => (/* @__PURE__ */ new Date()).t
6806
7040
  review: null
6807
7041
  };
6808
7042
  }
6809
- const preparationProgress = preparationInProgress(state) ? await storage.readPreparationProgress({ journeyId: state.journeyId }) : null;
7043
+ const preparationProgress = includePreparationProgress && preparationInProgress(state) ? await storage.readPreparationProgress({ journeyId: state.journeyId }) : null;
6810
7044
  const classificationProgress = state.consent && state.snapshotId ? (await storage.resources({
6811
7045
  journeyId: state.journeyId,
6812
7046
  kind: "classification-progress",
@@ -6865,8 +7099,8 @@ function createNativeJourney(storage, now = () => (/* @__PURE__ */ new Date()).t
6865
7099
  const query = nativeGetSchema.parse(input);
6866
7100
  const state = await storage.current(query.journeyId);
6867
7101
  if (!state) return null;
6868
- const view = await present(state);
6869
- return audience === "agent" && state.valueOverrides ? {
7102
+ const view = await present(state, audience !== "review-helper");
7103
+ return audience !== "panel" && state.valueOverrides ? {
6870
7104
  ...view,
6871
7105
  valueOverrides: state.valueOverrides
6872
7106
  } : view;
@@ -6933,6 +7167,7 @@ function createNativeJourney(storage, now = () => (/* @__PURE__ */ new Date()).t
6933
7167
  };
6934
7168
  };
6935
7169
  if (current && current.phase !== "completed" && !current.abandonedAt && !obsoleteJourney(current)) return resume(current);
7170
+ const carried = current && !current.abandonedAt && obsoleteJourney(current) ? (current.instructions ?? []).filter((item) => item.actor === "human") : [];
6936
7171
  const state = {
6937
7172
  formatVersion: 10,
6938
7173
  classificationRevision: null,
@@ -6961,6 +7196,7 @@ function createNativeJourney(storage, now = () => (/* @__PURE__ */ new Date()).t
6961
7196
  exceptions: [],
6962
7197
  adapters: currentJourneyAdapters(),
6963
7198
  lastEvent: 0,
7199
+ ...carried.length ? { instructions: carried } : {},
6964
7200
  ...input.period?.since || input.period?.until ? { period: input.period } : {}
6965
7201
  };
6966
7202
  const result = await storage.commit({
@@ -7142,7 +7378,7 @@ function createNativeJourney(storage, now = () => (/* @__PURE__ */ new Date()).t
7142
7378
  const rows = await storage.events(input.journeyId, input.after);
7143
7379
  if (rows.length || Date.now() >= deadline) return {
7144
7380
  events: rows,
7145
- state: await get({ journeyId: input.journeyId })
7381
+ state: rows.length || !input.changesOnly ? await get({ journeyId: input.journeyId }) : null
7146
7382
  };
7147
7383
  await setTimeout$1(Math.min(1e3, Math.max(0, deadline - Date.now())), void 0, { signal });
7148
7384
  }
@@ -7445,6 +7681,14 @@ function createNativeJourney(storage, now = () => (/* @__PURE__ */ new Date()).t
7445
7681
  if (!local) throw new ApplicationError("INVALID_TRANSITION");
7446
7682
  return local.works.classificationRead(journeyClassificationReadSchema.parse(value), signal);
7447
7683
  },
7684
+ recoverIsolatedMetadata: async (value, signal = new AbortController().signal) => {
7685
+ if (!local) throw new ApplicationError("INVALID_TRANSITION");
7686
+ const result = await local.works.recoverIsolatedMetadata(isolatedMetadataRecoverySchema.parse(value), signal);
7687
+ return {
7688
+ ...result,
7689
+ state: await present(result.state)
7690
+ };
7691
+ },
7448
7692
  classificationSubmit: async (value, signal = new AbortController().signal) => {
7449
7693
  if (!local) throw new ApplicationError("INVALID_TRANSITION");
7450
7694
  const result = await local.works.classificationSubmit(journeyClassificationSubmitSchema.parse(value), signal);
@@ -7577,7 +7821,8 @@ function safeJourneySender(sender, now) {
7577
7821
  async get(input) {
7578
7822
  const result = await sender.get({
7579
7823
  journeyId: input.journeyId,
7580
- ...input.sendId ? { sendId: input.sendId } : {}
7824
+ ...input.sendId ? { sendId: input.sendId } : {},
7825
+ ...input.observedRevision !== void 0 ? { observedRevision: input.observedRevision } : {}
7581
7826
  });
7582
7827
  return result ? safe(result) : null;
7583
7828
  },
@@ -7605,6 +7850,8 @@ function safeJourneySender(sender, now) {
7605
7850
  async advance(input, signal = new AbortController().signal) {
7606
7851
  return safe(await sender.advance(input, signal));
7607
7852
  },
7853
+ uploadAssessments: (input) => sender.uploadAssessments(input),
7854
+ ownedPassport: (input, signal = new AbortController().signal) => sender.ownedPassport(input, signal),
7608
7855
  ownerProfile: (signal = new AbortController().signal) => sender.ownerProfile(signal),
7609
7856
  addressTaken: (input, signal = new AbortController().signal) => sender.addressTaken(input, signal),
7610
7857
  saveSentProfile: (input, signal = new AbortController().signal) => sender.saveSentProfile(input, signal)
@@ -14050,4 +14297,4 @@ function equivalenceDuplicates(batch) {
14050
14297
  return bindings.sort();
14051
14298
  }
14052
14299
  //#endregion
14053
- export { validateDetectionSummary as $, hideKeyId as $n, sendReplaceResultSchema as $r, journeyResourceSchema as $t, renewBeforeMs as A, scanGitSeedsResource as An, journeyPreviewSchema as Ar, obsoleteJourney as At, createApplication as B, journeySearchResultSchema as Bn, nativeRespondSchema as Br, classificationPartition as Bt, rebindReviewOverlay as C, selectFrozenConfiguration as Ci, mergeBRepair as Cn, preparationStartSchema as Cr, sendActionSchema as Ct, staticallyHiddenFindings as D, scanPreparationDigest as Dn, journeyClassificationSessionsSchema as Dr, sendStartSchema as Dt, guardedFindingText as E, scanCanonicalResourceSchema as En, validatePreparationFacts as Er, sendRequestSchema as Et, readAccountAvatarUrl as F, journeyInventoryQuerySchema as Fn, applyCardAnswers as Fr, journeyGuidance as Ft, validateInspectionRequest as G, journeyEventSchema as Gn, staticSessionId as Gr, journeyContextQuerySchema as Gt, inspectionStartSchema as H, searchScopeDigest as Hn, mergePrivacyTerms as Hr, retireScanGeneration as Ht, storedCredentialSchema as I, journeyInventoryReadSchema as In, assertJourneyPrivacyReady as Ir, journeyBatchReadSchema as It, validateInspectionFence as J, readConfirmedHideChange as Jn, agentSourceSchema as Jr, hideFinishSchema as Jt, inspectionQuerySchema as K, confirmedHideAdditions as Kn, staticSessionResourceSchema as Kr, journeyContextSchema as Kt, sourceIdentityEvidence as L, journeyInventorySchema as Ln, privacyDecisionDigest as Lr, journeyReviewStorageQuerySchema as Lt, deviceAuthorizationSchema as M, scanExclusionResourceSchema as Mn, journeyRenderSchema as Mr, nativeAdapterVersions as Mt, deviceProfileScopeSchema as N, validateScanExclusion as Nn, displayedScopeDigest as Nr, attemptBudgetCodePoints as Nt, createAccount as O, scanSessionResourceSchema as On, journeyFindingImpactSchema as Or, settleCorrections as Ot, profileUrlMatchesIdentity as P, resolveSourceSelection as Pn, requestedScope as Pr, validateAttemptAppend as Pt, validateInspectionContribution as Q, addHideIndexTokens as Qn, sendReceiptSchema as Qr, journeyResourceQuerySchema as Qt, withSourceEvidence as R, journeyPreparationProgressSchema as Rn, nativeEventsSchema as Rr, applyClassificationProposal as Rt, rebindReviewAlignment as S, freezeConfiguration as Si, bReviewDigest as Sn, preparationSettlementSchema as Sr, replaceSensitiveTermsSchema as St, reviewBatchReuse as T, scanAliasResourceSchema as Tn, preparationUpdateSchema as Tr, sendPrepareSchema as Tt, validateInspectionBatch as U, journeyCommitResultSchema as Un, hasCurrentStaticReview as Ur, newJourneyWork as Ut, inspectionCancelSchema as V, journeySearchSaveSchema as Vn, retryReviewActionSchema as Vr, classificationWorks as Vt, validateInspectionBatches as W, journeyCommitSchema as Wn, staticReviewDigest as Wr, reviewCompileSchema as Wt, validateInspectionInputs as X, settleConfirmedHides as Xn, journeySendSchema as Xr, journeyPolicyRespondSchema as Xt, validateInspectionHead as Y, renderedHideValue as Yn, agentSourcesSchema as Yr, hidePublishSchema as Yt, validateInspectionQuery as Z, termHideAdditions as Zn, sendArtifactSchema as Zr, projectPreparationProgress as Zt, changeJourney as _, sourceChangePolicy as _i, reviewCandidateInputSchema as _n, workPrivacyDecisions as _r, manualUploadStartSchema as _t, bCrossSegmentReviewSchema as a, isReadingComplete as ai, reviewAttemptsResultSchema as an, bTermMatcher as ar, appendSensitiveTerms as at, isGenericPublicTerm as b, effectiveTreatmentSchema as bi, reviewRepairResourceSchema as bn, preparationBeginSchema as br, maximumTermsFileBytes as bt, reconstructBFields as c, selectedWorks as ci, sessionReconciliationResourceSchema as cn, confirmedHideKey as cr, maximumAgentSetupSessions as ct, resolveGroupSplit as d, packageCommandSchema as di, sessionReviewInputSchema as dn, dictionaryHides as dr, validateFailureLocation as dt, sendResolutionSchema as ei, journeyIsolateSchema as en, maximumHideIndexTokens as er, inspectionInputs as et, selectedValueMembers as f, selectionBatchSchema as fi, sessionReviewQuerySchema as fn, journeyConfirmedHides as fr, manualUploadActionSchema as ft, semanticGroupKey as g, stateSchema as gi, sessionUsefulnessResourceSchema as gn, workDecisionDigest as gr, manualUploadSchema as gt, hideScopeDigest as h, producerVersion as hi, sessionUsefulnessInputSchema as hn, retireWorkDescription as hr, manualUploadPrepareSchema as ht, validateBCrossSegmentReview as i, isIncludedWork as ii, reviewAttemptsQuerySchema as in, bMaskedHits as ir, reviewInventory as it, accountProfileSchema as j, verifiedScanGitSeeds as jn, journeyRenderInputSchema as jr, metadataProcessingVersion as jt, renew as k, scanGitSeedsId as kn, journeyFindingsSchema as kr, currentJourneyAdapters as kt, chooseCheapPlacement as l, withReadingProgress as li, sessionRereadInputSchema as ln, confirmedHideKinds as lr, artifactFailureDetailSchema as lt, activeJourneyTerms as m, gitMetadataBudgetBytes as mi, sessionReviewStatusSchema as mn, syncTermGroups as mr, manualUploadChoiceSchema as mt, scanBatchEquivalenceDigest as n, hasCompleteWorkDescription as ni, sortingApplySchema as nn, bContainment as nr, settingsQuerySchema as nt, bRereadDigest as o, isSelectedWork as oi, sessionReconcileInputSchema as on, bWordBounded as or, classifyAgentSetup as ot, splitSelectorValues as p, selectionSchema as pi, sessionReviewResourceSchema as pn, maskedHitsStale as pr, manualUploadBindingSchema as pt, validateInspectionClaim as q, confirmedHideDeltaSchema as qn, agentSourcePathSegment as qr, hideBeginSchema as qt, locateTermEvidence as r, isClassifying as ri, reviewAttemptResourceSchema as rn, bExceptionRanges as rr, readWorkspaceOutcomes as rt, reconcileBSession as s, isSkippedWork as si, sessionReconcileResultSchema as sn, confirmedHideGroupIds as sr, defaultAgentSetupInclusion as st, scanBatchContextDigest as t, sendSettingsSchema as ti, journeyPlaceSchema as tn, packHideIndex as tr, settingsBatchSchema as tt, reviseGroupMembership as u, commandSchema as ui, sessionRereadResourceSchema as un, confirmedHideTerms as ur, resolveFailureLocation as ut, projectJourneyInventory as v, recommendParallelism as vi, reviewCandidateResourceSchema as vn, workCorrectionBinding as vr, candidateSortAvailable as vt, rebindReviewSubmit as w, staticCatalogRef as wi, planBRepair as wn, preparationStateSchema as wr, sendChoiceSchema as wt, bReviewScope as x, defaultScopedSettings as xi, reviewTransportBytes as xn, preparationPermissionSchema as xr, normalizeSensitiveTerms as xt, preparationScope as y, approvedTreatmentSchema as yi, reviewRepairInputSchema as yn, emptyPreparationFacts as yr, emptyTermsRevision as yt, agentSetupKey as z, applyClassification as zn, nativeGetSchema as zr, classificationCommitSchema as zt };
14300
+ export { validateDetectionSummary as $, maximumHideIndexTokens as $n, nativeAdapterVersions as $r, journeyPlaceSchema as $t, renewBeforeMs as A, stateSchema as Ai, scanExclusionResourceSchema as An, journeyRenderInputSchema as Ar, validateAttemptAppend as At, createApplication as B, journeySearchSaveSchema as Bn, nativeRespondSchema as Br, newJourneyWork as Bt, rebindReviewOverlay as C, withReadingProgress as Ci, scanAliasResourceSchema as Cn, preparationStateSchema as Cr, sendActionSchema as Ct, staticallyHiddenFindings as D, selectionSchema as Di, scanGitSeedsId as Dn, journeyFindingImpactSchema as Dr, sendStartSchema as Dt, guardedFindingText as E, selectionBatchSchema as Ei, scanSessionResourceSchema as En, journeyClassificationSessionsSchema as Er, sendRequestSchema as Et, readAccountAvatarUrl as F, defaultScopedSettings as Fi, journeyInventoryReadSchema as Fn, assertJourneyPrivacyReady as Fr, classificationCommitSchema as Ft, validateInspectionRequest as G, confirmedHideAdditions as Gn, currentJourneyAdapters as Gr, hideFinishSchema as Gt, inspectionStartSchema as H, journeyCommitResultSchema as Hn, retryReviewActionSchema as Hr, journeyContextQuerySchema as Ht, storedCredentialSchema as I, freezeConfiguration as Ii, journeyInventorySchema as In, privacyDecisionDigest as Ir, classificationPartition as It, validateInspectionFence as J, renderedHideValue as Jn, obsoleteJourney as Jr, sendOutputQuerySchema as Jt, inspectionQuerySchema as K, confirmedHideDeltaSchema as Kn, hostDrives as Kr, hidePublishSchema as Kt, sourceIdentityEvidence as L, selectFrozenConfiguration as Li, journeyPreparationProgressSchema as Ln, reconcileReaderKeeps as Lr, classificationWorks as Lt, deviceAuthorizationSchema as M, recommendParallelism as Mi, resolveSourceSelection as Mn, displayedScopeDigest as Mr, journeyBatchReadSchema as Mt, deviceProfileScopeSchema as N, approvedTreatmentSchema as Ni, projectPreparationProgress as Nn, requestedScope as Nr, journeyReviewStorageQuerySchema as Nt, createAccount as O, gitMetadataBudgetBytes as Oi, scanGitSeedsResource as On, journeyFindingsSchema as Or, settleCorrections as Ot, profileUrlMatchesIdentity as P, effectiveTreatmentSchema as Pi, journeyInventoryQuerySchema as Pn, applyCardAnswers as Pr, applyClassificationProposal as Pt, validateInspectionContribution as Q, hideKeyId as Qn, metadataProcessingVersion as Qr, journeyIsolateSchema as Qt, withSourceEvidence as R, staticCatalogRef as Ri, applyClassification as Rn, nativeEventsSchema as Rr, retireScanGeneration as Rt, rebindReviewAlignment as S, unfinishedPackagingCode as Si, planBRepair as Sn, preparationStartSchema as Sr, replaceSensitiveTermsSchema as St, reviewBatchReuse as T, packageCommandSchema as Ti, scanPreparationDigest as Tn, validatePreparationFacts as Tr, sendPrepareSchema as Tt, validateInspectionBatch as U, journeyCommitSchema as Un, advanceStepsSend as Ur, journeyContextSchema as Ut, inspectionCancelSchema as V, searchScopeDigest as Vn, nativeStartSchema as Vr, reviewCompileSchema as Vt, validateInspectionBatches as W, journeyEventSchema as Wn, awaitingPassport as Wr, hideBeginSchema as Wt, validateInspectionInputs as X, termHideAdditions as Xn, sendReachedPassport as Xr, journeyResourceQuerySchema as Xt, validateInspectionHead as Y, settleConfirmedHides as Yn, sendOwesPassport as Yr, sendOutputSchema as Yt, validateInspectionQuery as Z, addHideIndexTokens as Zn, sendsOnNextAdvance as Zr, journeyResourceSchema as Zt, changeJourney as _, isIncludedWork as _i, reviewRepairInputSchema as _n, workCorrectionBinding as _r, manualUploadStartSchema as _t, bCrossSegmentReviewSchema as a, agentSourcePathSegment as ai, sessionReconcileResultSchema as an, bWordBounded as ar, appendSensitiveTerms as at, isGenericPublicTerm as b, isSkippedWork as bi, bReviewDigest as bn, preparationPermissionSchema as br, maximumTermsFileBytes as bt, reconstructBFields as c, journeySendSchema as ci, sessionRereadResourceSchema as cn, confirmedHideKinds as cr, maximumAgentSetupSessions as ct, resolveGroupSplit as d, sendReplaceResultSchema as di, sessionReviewResourceSchema as dn, journeyConfirmedHides as dr, validateFailureLocation as dt, mergePrivacyTerms as ei, sortingApplySchema as en, packHideIndex as er, inspectionInputs as et, selectedValueMembers as f, sendResolutionSchema as fi, sessionReviewStatusSchema as fn, maskedHitsStale as fr, manualUploadActionSchema as ft, semanticGroupKey as g, isClassifying as gi, reviewCandidateResourceSchema as gn, workPrivacyDecisions as gr, manualUploadSchema as gt, hideScopeDigest as h, hasCompleteWorkDescription as hi, reviewCandidateInputSchema as hn, workDecisionDigest as hr, manualUploadPrepareSchema as ht, validateBCrossSegmentReview as i, staticSessionResourceSchema as ii, sessionReconcileInputSchema as in, bTermMatcher as ir, reviewInventory as it, accountProfileSchema as j, sourceChangePolicy as ji, validateScanExclusion as jn, journeyRenderSchema as jr, journeyGuidance as jt, renew as k, producerVersion as ki, verifiedScanGitSeeds as kn, journeyPreviewSchema as kr, attemptBudgetCodePoints as kt, chooseCheapPlacement as l, sendArtifactSchema as li, sessionReviewInputSchema as ln, confirmedHideTerms as lr, artifactFailureDetailSchema as lt, activeJourneyTerms as m, sendSettingsSchema as mi, sessionUsefulnessResourceSchema as mn, retireWorkDescription as mr, manualUploadChoiceSchema as mt, scanBatchEquivalenceDigest as n, staticReviewDigest as ni, reviewAttemptsQuerySchema as nn, bExceptionRanges as nr, settingsQuerySchema as nt, bRereadDigest as o, agentSourceSchema as oi, sessionReconciliationResourceSchema as on, confirmedHideGroupIds as or, classifyAgentSetup as ot, splitSelectorValues as p, sendSessionUploadSchema as pi, sessionUsefulnessInputSchema as pn, syncTermGroups as pr, manualUploadBindingSchema as pt, validateInspectionClaim as q, readConfirmedHideChange as qn, itemAtPassport as qr, journeyPolicyRespondSchema as qt, locateTermEvidence as r, staticSessionId as ri, reviewAttemptsResultSchema as rn, bMaskedHits as rr, readWorkspaceOutcomes as rt, reconcileBSession as s, agentSourcesSchema as si, sessionRereadInputSchema as sn, confirmedHideKey as sr, defaultAgentSetupInclusion as st, scanBatchContextDigest as t, hasCurrentStaticReview as ti, reviewAttemptResourceSchema as tn, bContainment as tr, settingsBatchSchema as tt, reviseGroupMembership as u, sendReceiptSchema as ui, sessionReviewQuerySchema as un, dictionaryHides as ur, resolveFailureLocation as ut, projectJourneyInventory as v, isReadingComplete as vi, reviewRepairResourceSchema as vn, emptyPreparationFacts as vr, candidateSortAvailable as vt, rebindReviewSubmit as w, commandSchema as wi, scanCanonicalResourceSchema as wn, preparationUpdateSchema as wr, sendChoiceSchema as wt, bReviewScope as x, selectedWorks as xi, mergeBRepair as xn, preparationSettlementSchema as xr, normalizeSensitiveTerms as xt, preparationScope as y, isSelectedWork as yi, reviewTransportBytes as yn, preparationBeginSchema as yr, emptyTermsRevision as yt, agentSetupKey as z, journeySearchResultSchema as zn, nativeGetSchema as zr, isolatedWorkId as zt };