@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.
- package/README.md +4 -0
- package/bin/INDEX.md +6 -4
- package/bin/tacitt.cjs +1 -0
- package/dist/{agent-setup-DdfF3zch.mjs → agent-setup-B12VbvN_.mjs} +2 -2
- package/dist/agent-setup-worker.mjs +5 -5
- package/dist/cli.mjs +28 -28
- package/dist/codex-title-worker.mjs +2 -2
- package/dist/configured-preview-worker.mjs +5 -5
- package/dist/configured-session-worker.mjs +23 -25
- package/dist/{frame-Bq2zRh-i.mjs → frame-B3He21G8.mjs} +1 -1
- package/dist/{heap-CV8Eca8V.mjs → heap-Blrat--4.mjs} +260 -23
- package/dist/inspection-worker.mjs +4 -4
- package/dist/{job-BKsifhyv.mjs → job-CBuIMTQ0.mjs} +24 -9
- package/dist/{locate-Cx52Zqxv.mjs → locate-D-ZaHpI0.mjs} +5 -0
- package/dist/{model-C1UXkHh9.mjs → model-DR9odhWP.mjs} +1 -1
- package/dist/operation-executor.mjs +3 -3
- package/dist/preview-worker.mjs +1 -1
- package/dist/privacy-validator.mjs +28 -8
- package/dist/{query-AMZerUh8.mjs → query-BYDcNKy2.mjs} +1614 -679
- package/dist/{run-CaPktPhH.mjs → run-DQ9xyKSt.mjs} +4 -4
- package/dist/session-process.mjs +20 -0
- package/dist/{src-wZx_v0Ih.mjs → src-CKQlTA2Z.mjs} +4 -4
- package/dist/{src-DlVbGB32.mjs → src-DeNJ8vOD.mjs} +465 -107
- package/dist/{src-D1iONla3.mjs → src-Do-qzuMn.mjs} +377 -130
- package/dist/store-database-worker.mjs +1 -1
- package/dist/web/assets/index-BgDdPL1c.js +172 -0
- package/dist/web/index.html +2 -1
- package/package.json +2 -1
- package/skills/INDEX.md +6 -4
- package/skills/tacitt/INDEX.md +7 -6
- package/skills/tacitt/SKILL.md +5 -5
- package/skills/tacitt/references/INDEX.md +14 -11
- package/skills/tacitt/references/b-method.md +4 -4
- package/skills/tacitt/references/bootstrap.md +17 -3
- package/skills/tacitt/references/classification.md +1 -1
- package/skills/tacitt/references/commands.md +24 -6
- package/skills/tacitt/references/journey.md +4 -4
- package/skills/tacitt/references/parallel-review.md +13 -7
- package/skills/tacitt/references/send.md +7 -3
- package/skills/tacitt/scripts/INDEX.md +40 -37
- package/skills/tacitt/scripts/answer.mjs +19 -1
- package/skills/tacitt/scripts/journey-card-consolidation.mjs +1 -1
- package/skills/tacitt/scripts/journey-classification-tasks.mjs +28 -8
- package/skills/tacitt/scripts/journey-panel-host.d.mts +2 -0
- package/skills/tacitt/scripts/journey-panel-host.mjs +25 -2
- package/skills/tacitt/scripts/journey-scan-timing.d.mts +4 -0
- package/skills/tacitt/scripts/journey-scan-timing.mjs +12 -0
- package/skills/tacitt/scripts/journey-state.mjs +11 -0
- package/skills/tacitt/scripts/journey-tasks.mjs +12 -5
- package/skills/tacitt/scripts/journey.mjs +10 -2
- package/skills/tacitt/scripts/privacy-validator.mjs +28 -7
- package/skills/tacitt/scripts/review.mjs +399 -99
- 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-
|
|
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:
|
|
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
|
-
/**
|
|
1662
|
-
function
|
|
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)
|
|
1671
|
-
const
|
|
1672
|
-
const
|
|
1673
|
-
const disposition = !termTypeInfo[term.type].asked
|
|
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
|
|
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
|
|
2200
|
-
const
|
|
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:
|
|
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 =
|
|
2294
|
-
|
|
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
|
-
|
|
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/
|
|
5061
|
-
/**
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
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
|
|
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 $,
|
|
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 };
|