@gitroll/tacitt-cli 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agent-setup-B85GaVIz.mjs → agent-setup-B8DAiQ6Z.mjs} +2 -2
- package/dist/agent-setup-worker.mjs +5 -5
- package/dist/cli.mjs +108 -9
- package/dist/codex-title-worker.mjs +1 -1
- package/dist/configured-preview-worker.mjs +5 -5
- package/dist/configured-session-worker.mjs +4 -4
- package/dist/{frame-D1j9R8xX.mjs → frame-waS5FnN5.mjs} +1 -1
- package/dist/{heap-tfU61Ehy.mjs → heap-BHcvxWCw.mjs} +20 -8
- package/dist/inspection-worker.mjs +57 -0
- package/dist/{job--TceKk0l.mjs → job-J3NFw3MH.mjs} +2 -2
- package/dist/{locate-Bn32k2se.mjs → locate-U3-nkird.mjs} +29 -6
- package/dist/messages-D3m3bhva.mjs +40 -0
- package/dist/{model-7Nu7szNP.mjs → model-BJdTLNjT.mjs} +1 -1
- package/dist/operation-executor.mjs +3 -3
- package/dist/preview-worker.mjs +1 -1
- package/dist/privacy-validator.mjs +1 -1
- package/dist/{query-Da-KDbSV.mjs → query-BA0XCwnR.mjs} +486 -128
- package/dist/{run-CCATsHS2.mjs → run-BeLHsZWb.mjs} +4 -4
- package/dist/{src-DynBRDBc.mjs → src-B5SArpVY.mjs} +20 -9
- package/dist/{src-CPPjOyHZ.mjs → src-CC95LYYp.mjs} +271 -68
- package/dist/{src-BngGpFKd.mjs → src-k0Ya1Bri.mjs} +13 -7
- package/dist/store-database-worker.mjs +1 -1
- package/dist/web/assets/index-Bjos73wK.js +67 -0
- package/dist/web/assets/index-Bl4C2b2_.css +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/skills/tacitt/SKILL.md +13 -11
- package/skills/tacitt/references/b-method.md +1 -1
- package/skills/tacitt/references/classification.md +3 -3
- package/skills/tacitt/references/commands.md +6 -6
- package/skills/tacitt/references/journey.md +13 -11
- package/skills/tacitt/references/parallel-review.md +3 -3
- package/skills/tacitt/references/send.md +5 -5
- package/skills/tacitt/scripts/answer.mjs +29 -8
- package/skills/tacitt/scripts/journey-card-consolidation.d.mts +13 -4
- package/skills/tacitt/scripts/journey-card-consolidation.mjs +81 -18
- package/skills/tacitt/scripts/journey-classification-progress.mjs +2 -1
- package/skills/tacitt/scripts/journey-classification-validation.mjs +49 -28
- package/skills/tacitt/scripts/journey-consolidation-submit.mjs +42 -5
- package/skills/tacitt/scripts/journey-consolidation.d.mts +5 -0
- package/skills/tacitt/scripts/journey-consolidation.mjs +4 -1
- package/skills/tacitt/scripts/journey-state.d.mts +1 -0
- package/skills/tacitt/scripts/journey-state.mjs +29 -3
- package/skills/tacitt/scripts/journey-tasks.mjs +4 -2
- package/skills/tacitt/scripts/journey.d.mts +2 -0
- package/skills/tacitt/scripts/journey.mjs +154 -13
- package/skills/tacitt/scripts/privacy-validator.mjs +25 -6
- package/skills/tacitt/scripts/review.mjs +24 -3
- package/dist/web/assets/index-CWQ05PFl.js +0 -67
- package/dist/web/assets/index-J-AWt_cW.css +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as bCountSchema, $n as scalarAfter, $t as fileIdentitySchema, A as bDuplicateMirror, B as bEvidenceReader, Bn as validatePlan, Bt as sessionPeriodSchema, C as validateBUnit, Ct as cardsSubmitSchema, D as uncoveredBObligations, Dn as entityDictionaryVersion, Dt as privacyResolveSchema, E as bLiterals, En as cleanupImplementationVersion, Et as packageConfirmActionSchema, Ft as termTypeInfo, G as subtractBRanges, Gn as detectStatic, H as codePointLength, Ht as ApplicationError, I as bIssue, It as termTypeSchema, J as bRetainedGroupSchema, Jt as reviewFamilies, Kt as familyNeedsReview, L as bOverlaps, Ln as validateProfile, Lt as termTypes, M as bLegacyBindings, Mt as reviewTermsResultSchema, N as bUnitFragments, Nt as termAssessmentSchema, O as indexBRanges, Ot as privacyTermKey, P as bAdoptedObligations, Pt as termOverrideValueSchema, Q as bAnchorSchema, Qt as sourceSnapshotId, R as unownedBObligations, Rn as orderProfile, Rt as deselectOutsidePeriod, S as validateBFields, St as cardsConfirmActionSchema, T as bLiteralTerms, Tt as emptyJourneyPrivacy, U as codePointSlice, Ut as UnfinishedJourneyError, V as bDigest, Vn as copyData, Vt as classificationTitleMaskSchema, W as createCodePointIndex, Wt as safeCode, X as bSessionDecisionSchema, Xn as createEntityMatcher, Xt as sourceKey, Y as bReviewSubmissionSchema, Yt as sourceGraph, Z as bTermSchema, Zt as observeSource, _ as semanticFindingSchema, _n as gapReasons, _t as hideConfirmSchema, a as reviewChunkSchema, at as journeyExceptionSchema, b as validateBReview, bn as staticDefaults, bt as journeyConfigurationSchema, c as textDigest, ct as journeyPreferenceScopeSchema, dt as nativeJourneySchema, en as inventorySchema, er as scalarBefore, et as bIdSchema, f as reviewAlignmentAuditSchema, ft as journeyGuidanceSchema, g as validateReviewAlignment, h as reviewFindingsDigest, hn as inspectionSemanticVersions, ht as journeyDescribeSchema, i as reviewBatchSchema, in as nativeSourceIdentitySchema, it as journeyDigestSchema, jt as reviewTermsInputSchema, l as validateReview, lt as journeyProjectTypeSchema, m as reviewAlignmentSchema, mn as currentDetectorVersion, mt as delegatedDecisionSchema, n as compileBFindings, nn as sourcePartSchema, nt as journeyAccessSchema, o as reviewDigest, ot as journeyIdSchema, p as reviewAlignmentInputSchema, pt as journeyInstructionInputSchema, q as bRepresentationSchema, qn as staticCategories, qt as familySelected, r as reviewBatchChunks, rt as journeyChoiceSchema, s as reviewSubmitSchema, st as journeyKindSchema, tr as defaultDetectionLimits, tt as bMethod, u as findingReferenceKey, ut as journeyWorkTypeSchema, vt as hidePlanInputSchema, w as bLiteralAdmitted, x as createBAnalysisUnits, xn as staticOptions, xt as cardAnswerActionSchema, y as validateBClassification, yn as createStaticProcessor, yt as hidePlanResourceSchema, z as bAnchorKey } from "./locate-
|
|
1
|
+
import { $ as bCountSchema, $n as scalarAfter, $t as fileIdentitySchema, A as bDuplicateMirror, B as bEvidenceReader, Bn as validatePlan, Bt as sessionPeriodSchema, C as validateBUnit, Ct as cardsSubmitSchema, D as uncoveredBObligations, Dn as entityDictionaryVersion, Dt as privacyResolveSchema, E as bLiterals, En as cleanupImplementationVersion, Et as packageConfirmActionSchema, Ft as termTypeInfo, G as subtractBRanges, Gn as detectStatic, H as codePointLength, Ht as ApplicationError, I as bIssue, It as termTypeSchema, J as bRetainedGroupSchema, Jt as reviewFamilies, Kt as familyNeedsReview, L as bOverlaps, Ln as validateProfile, Lt as termTypes, M as bLegacyBindings, Mt as reviewTermsResultSchema, N as bUnitFragments, Nt as termAssessmentSchema, O as indexBRanges, Ot as privacyTermKey, P as bAdoptedObligations, Pt as termOverrideValueSchema, Q as bAnchorSchema, Qt as sourceSnapshotId, R as unownedBObligations, Rn as orderProfile, Rt as deselectOutsidePeriod, S as validateBFields, St as cardsConfirmActionSchema, T as bLiteralTerms, Tt as emptyJourneyPrivacy, U as codePointSlice, Ut as UnfinishedJourneyError, V as bDigest, Vn as copyData, Vt as classificationTitleMaskSchema, W as createCodePointIndex, Wt as safeCode, X as bSessionDecisionSchema, Xn as createEntityMatcher, Xt as sourceKey, Y as bReviewSubmissionSchema, Yt as sourceGraph, Z as bTermSchema, Zt as observeSource, _ as semanticFindingSchema, _n as gapReasons, _t as hideConfirmSchema, a as reviewChunkSchema, at as journeyExceptionSchema, b as validateBReview, bn as staticDefaults, bt as journeyConfigurationSchema, c as textDigest, ct as journeyPreferenceScopeSchema, dt as nativeJourneySchema, en as inventorySchema, er as scalarBefore, et as bIdSchema, f as reviewAlignmentAuditSchema, ft as journeyGuidanceSchema, g as validateReviewAlignment, h as reviewFindingsDigest, hn as inspectionSemanticVersions, ht as journeyDescribeSchema, i as reviewBatchSchema, in as nativeSourceIdentitySchema, it as journeyDigestSchema, jt as reviewTermsInputSchema, l as validateReview, lt as journeyProjectTypeSchema, m as reviewAlignmentSchema, mn as currentDetectorVersion, mt as delegatedDecisionSchema, n as compileBFindings, nn as sourcePartSchema, nt as journeyAccessSchema, o as reviewDigest, ot as journeyIdSchema, p as reviewAlignmentInputSchema, pt as journeyInstructionInputSchema, q as bRepresentationSchema, qn as staticCategories, qt as familySelected, r as reviewBatchChunks, rt as journeyChoiceSchema, s as reviewSubmitSchema, st as journeyKindSchema, tr as defaultDetectionLimits, tt as bMethod, u as findingReferenceKey, ut as journeyWorkTypeSchema, vt as hidePlanInputSchema, w as bLiteralAdmitted, x as createBAnalysisUnits, xn as staticOptions, xt as cardAnswerActionSchema, y as validateBClassification, yn as createStaticProcessor, yt as hidePlanResourceSchema, z as bAnchorKey } from "./locate-U3-nkird.mjs";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { createHash, createHmac, createSecretKey, randomUUID } from "node:crypto";
|
|
4
4
|
import { setTimeout as setTimeout$1 } from "node:timers/promises";
|
|
@@ -1330,8 +1330,6 @@ function mergePrivacyTerms(state, incoming) {
|
|
|
1330
1330
|
return {
|
|
1331
1331
|
...state.privacy,
|
|
1332
1332
|
terms: [...terms.values()],
|
|
1333
|
-
cards: [],
|
|
1334
|
-
confirmedAnswersRevision: null,
|
|
1335
1333
|
packageApproval: null
|
|
1336
1334
|
};
|
|
1337
1335
|
}
|
|
@@ -1344,9 +1342,16 @@ function activePrivacyTerms(state) {
|
|
|
1344
1342
|
function hasCompleteWorkDescription(work) {
|
|
1345
1343
|
return work.placement === "placed" && !!work.description.trim() && work.classificationRecommendation !== null;
|
|
1346
1344
|
}
|
|
1347
|
-
/**
|
|
1345
|
+
/**
|
|
1346
|
+
* Dropped Works are not AI-read; a Work emptied by repartition has nothing left to read, and
|
|
1347
|
+
* roots classification has not grouped yet are read once they join a Work (E2).
|
|
1348
|
+
*/
|
|
1348
1349
|
function isSelectedWork(work) {
|
|
1349
|
-
return work.access !== "drop" && work.rootSessionIds.length > 0;
|
|
1350
|
+
return work.access !== "drop" && work.rootSessionIds.length > 0 && work.placement !== "classifying";
|
|
1351
|
+
}
|
|
1352
|
+
/** Classification published some Works and is still grouping the remaining roots (E2). */
|
|
1353
|
+
function isClassifying(state) {
|
|
1354
|
+
return state.works.some((work) => work.placement === "classifying");
|
|
1350
1355
|
}
|
|
1351
1356
|
function selectedWorks(state) {
|
|
1352
1357
|
return state.works.filter(isSelectedWork);
|
|
@@ -1365,7 +1370,7 @@ function hasCertifiedNoBatchReview(work, snapshotId) {
|
|
|
1365
1370
|
}
|
|
1366
1371
|
/** Reading completes over selected Works once the person has confirmed the scan scope. */
|
|
1367
1372
|
function isReadingComplete(state) {
|
|
1368
|
-
return state.scope.status === "confirmed" && state.works.length > 0 && selectedWorks(state).every((work) => work.status !== "pending" && work.status !== "blocked" && (work.totalBatches > 0 || hasCertifiedNoBatchReview(work, state.snapshotId)) && work.completedBatches === work.totalBatches);
|
|
1373
|
+
return state.scope.status === "confirmed" && state.works.length > 0 && !isClassifying(state) && selectedWorks(state).every((work) => work.status !== "pending" && work.status !== "blocked" && (work.totalBatches > 0 || hasCertifiedNoBatchReview(work, state.snapshotId)) && work.completedBatches === work.totalBatches);
|
|
1369
1374
|
}
|
|
1370
1375
|
/** Recompute completion after a selection or reading change without leaving a paused/send phase. */
|
|
1371
1376
|
function withReadingProgress(state) {
|
|
@@ -1404,7 +1409,9 @@ const staticSessionResourceSchema = z.object({
|
|
|
1404
1409
|
result: staticFileSchema,
|
|
1405
1410
|
primary: staticFileSchema,
|
|
1406
1411
|
companion: staticFileSchema,
|
|
1407
|
-
masks: staticFileSchema
|
|
1412
|
+
masks: staticFileSchema,
|
|
1413
|
+
/** Model-facing image blocks this session's output leaves out; absent on older receipts. */
|
|
1414
|
+
imagesOmitted: count$12.optional()
|
|
1408
1415
|
}).strict();
|
|
1409
1416
|
const staticSessionId = (resource) => `${resource.workId}:${resource.inputRevision}:${resource.sessionId}`;
|
|
1410
1417
|
/** Binds one Work's complete static base to the exact session results it was sealed from. */
|
|
@@ -1512,7 +1519,11 @@ const day = z.string().regex(/^\d{4}-\d{2}-\d{2}$/u);
|
|
|
1512
1519
|
const journeyCatalogWorkSchema = z.object({
|
|
1513
1520
|
id: journeyIdSchema,
|
|
1514
1521
|
projectName: safeText,
|
|
1515
|
-
placement: z.enum([
|
|
1522
|
+
placement: z.enum([
|
|
1523
|
+
"placed",
|
|
1524
|
+
"unsorted",
|
|
1525
|
+
"classifying"
|
|
1526
|
+
]),
|
|
1516
1527
|
access: journeyAccessSchema,
|
|
1517
1528
|
projectType: journeyWorkTypeSchema.nullable(),
|
|
1518
1529
|
roots: count$11,
|
|
@@ -1808,7 +1819,45 @@ function assertJourneyPrivacyReady(state, packaging = false) {
|
|
|
1808
1819
|
assertJourneyStaticReady(state);
|
|
1809
1820
|
if (packaging && state.privacy.packageApproval !== privacyDecisionDigest(state)) throw new ApplicationError("CONFIRMATION_REQUIRED");
|
|
1810
1821
|
}
|
|
1822
|
+
/** Card batches start once the scan scope is confirmed (D3); they need not wait for reading. */
|
|
1823
|
+
function assertCardsAllowed(state) {
|
|
1824
|
+
if (!state.consent || state.scope.status !== "confirmed") throw new ApplicationError("SCOPE_NOT_READY");
|
|
1825
|
+
}
|
|
1826
|
+
/**
|
|
1827
|
+
* D3: a batch covers only Pending values no card covers yet. Values added to an existing card
|
|
1828
|
+
* take its answer at once when the person already answered it.
|
|
1829
|
+
*/
|
|
1830
|
+
function appendDecisionCards(state, input) {
|
|
1831
|
+
assertCardsAllowed(state);
|
|
1832
|
+
const existing = new Set(state.privacy.cards.map((card) => card.id));
|
|
1833
|
+
const coveredBefore = new Set(state.privacy.cards.flatMap((card) => card.termKeys));
|
|
1834
|
+
const open = new Set(activePrivacyTerms(state).filter((term) => term.disposition === "pending").map(privacyTermKey).filter((key) => !coveredBefore.has(key)));
|
|
1835
|
+
const extend = input.extend ?? [];
|
|
1836
|
+
const covered = [...input.cards.flatMap((card) => card.termKeys), ...extend.flatMap((item) => item.termKeys)];
|
|
1837
|
+
if (!covered.length || state.privacy.cards.length + input.cards.length > 20 || new Set(input.cards.map((card) => card.id)).size !== input.cards.length || input.cards.some((card) => existing.has(card.id)) || new Set(extend.map((item) => item.cardId)).size !== extend.length || extend.some((item) => !existing.has(item.cardId)) || new Set(covered).size !== covered.length || covered.some((key) => !open.has(key))) throw new ApplicationError("INVALID_SELECTION");
|
|
1838
|
+
const additions = new Map(extend.map((item) => [item.cardId, item.termKeys]));
|
|
1839
|
+
return applyCardAnswers({
|
|
1840
|
+
...retirePrivacyArtifacts(state),
|
|
1841
|
+
privacy: {
|
|
1842
|
+
...state.privacy,
|
|
1843
|
+
cards: [...state.privacy.cards.map((card) => {
|
|
1844
|
+
const added = additions.get(card.id);
|
|
1845
|
+
return added ? {
|
|
1846
|
+
...card,
|
|
1847
|
+
termKeys: [...card.termKeys, ...added]
|
|
1848
|
+
} : card;
|
|
1849
|
+
}), ...input.cards.map((card) => ({
|
|
1850
|
+
...card,
|
|
1851
|
+
answer: null
|
|
1852
|
+
}))],
|
|
1853
|
+
confirmedAnswersRevision: input.cards.length ? null : state.privacy.confirmedAnswersRevision,
|
|
1854
|
+
packageApproval: null
|
|
1855
|
+
}
|
|
1856
|
+
});
|
|
1857
|
+
}
|
|
1811
1858
|
function publishDecisionCards(state, input) {
|
|
1859
|
+
if (input.mode === "append") return appendDecisionCards(state, input);
|
|
1860
|
+
if (input.extend?.length) throw new ApplicationError("INVALID_SELECTION");
|
|
1812
1861
|
assertJourneyScanned(state);
|
|
1813
1862
|
const pending = new Set(activePrivacyTerms(state).filter((term) => term.disposition === "pending").map(privacyTermKey));
|
|
1814
1863
|
const covered = input.cards.flatMap((card) => card.termKeys);
|
|
@@ -1838,19 +1887,45 @@ function resolvePrivacyTerms(state, input) {
|
|
|
1838
1887
|
const resolutions = new Map(input.resolutions.map((term) => [privacyTermKey(term), term]));
|
|
1839
1888
|
const pending = new Set(activePrivacyTerms(state).filter((term) => term.disposition === "pending").map(privacyTermKey));
|
|
1840
1889
|
if (resolutions.size !== input.resolutions.length || [...resolutions.keys()].some((key) => !pending.has(key))) throw new ApplicationError("INVALID_SELECTION");
|
|
1841
|
-
|
|
1890
|
+
const terms = state.privacy.terms.map((term) => {
|
|
1842
1891
|
const resolution = resolutions.get(privacyTermKey(term));
|
|
1843
1892
|
return resolution ? {
|
|
1844
1893
|
...term,
|
|
1845
1894
|
...resolution
|
|
1846
1895
|
} : term;
|
|
1847
1896
|
});
|
|
1848
|
-
const
|
|
1897
|
+
for (const same of Map.groupBy(activePrivacyTerms({
|
|
1849
1898
|
...state,
|
|
1850
1899
|
privacy: {
|
|
1851
1900
|
...state.privacy,
|
|
1852
1901
|
terms
|
|
1853
1902
|
}
|
|
1903
|
+
}), (term) => term.value.normalize("NFC")).values()) if (same.some((term) => term.disposition === "pending") && input.resolutions.some((item) => item.value.normalize("NFC") === same[0]?.value.normalize("NFC"))) throw new ApplicationError("INVALID_SELECTION");
|
|
1904
|
+
return {
|
|
1905
|
+
...retirePrivacyArtifacts(state),
|
|
1906
|
+
privacy: {
|
|
1907
|
+
...state.privacy,
|
|
1908
|
+
terms: normalizeValues(state, terms),
|
|
1909
|
+
packageApproval: null
|
|
1910
|
+
}
|
|
1911
|
+
};
|
|
1912
|
+
}
|
|
1913
|
+
/** Keys of answered cards that took one option, leaving out values the person unticked. */
|
|
1914
|
+
function answeredKeys(state, optionId) {
|
|
1915
|
+
return new Set(state.privacy.cards.flatMap((card) => {
|
|
1916
|
+
if (!card.answer) return [];
|
|
1917
|
+
const excluded = new Set(card.answer.excludedTermKeys ?? []);
|
|
1918
|
+
return card.answer.optionId === optionId ? card.termKeys.filter((key) => !excluded.has(key)) : [...excluded];
|
|
1919
|
+
}));
|
|
1920
|
+
}
|
|
1921
|
+
/** One NFC value has one outcome across term types, cards and per-value rules. */
|
|
1922
|
+
function normalizeValues(state, input) {
|
|
1923
|
+
const active = activePrivacyTerms({
|
|
1924
|
+
...state,
|
|
1925
|
+
privacy: {
|
|
1926
|
+
...state.privacy,
|
|
1927
|
+
terms: input
|
|
1928
|
+
}
|
|
1854
1929
|
});
|
|
1855
1930
|
const overrides = /* @__PURE__ */ new Map();
|
|
1856
1931
|
for (const item of state.valueOverrides ?? []) {
|
|
@@ -1858,7 +1933,7 @@ function resolvePrivacyTerms(state, input) {
|
|
|
1858
1933
|
if (!overrides.has(value)) overrides.set(value, item);
|
|
1859
1934
|
}
|
|
1860
1935
|
const cardValues = (optionId) => {
|
|
1861
|
-
const keys =
|
|
1936
|
+
const keys = answeredKeys(state, optionId);
|
|
1862
1937
|
return new Set(state.privacy.terms.filter((term) => keys.has(privacyTermKey(term))).map((term) => term.value.normalize("NFC")));
|
|
1863
1938
|
};
|
|
1864
1939
|
const hideCardValues = cardValues("hide");
|
|
@@ -1866,7 +1941,6 @@ function resolvePrivacyTerms(state, input) {
|
|
|
1866
1941
|
const ownNames = workProjectNames(state);
|
|
1867
1942
|
const normalized = /* @__PURE__ */ new Map();
|
|
1868
1943
|
for (const same of Map.groupBy(active, (term) => term.value.normalize("NFC")).values()) {
|
|
1869
|
-
if (same.some((term) => term.disposition === "pending") && input.resolutions.some((item) => item.value.normalize("NFC") === same[0]?.value.normalize("NFC"))) throw new ApplicationError("INVALID_SELECTION");
|
|
1870
1944
|
if (same.some((term) => term.disposition === "pending")) continue;
|
|
1871
1945
|
const forcedHidden = same.some((term) => !termTypeInfo[term.type].asked);
|
|
1872
1946
|
const override = overrides.get(same[0]?.value.normalize("NFC") ?? "");
|
|
@@ -1879,51 +1953,79 @@ function resolvePrivacyTerms(state, input) {
|
|
|
1879
1953
|
reason: disposition === "hidden" && term.disposition !== "hidden" ? hideCard && !same.some((item) => item.disposition === "hidden") ? "A Hide card answer covering this value takes precedence over Keep." : "A Hidden judgment for this NFC keyword takes precedence across term types." : ownKeep && term.disposition !== "keep" ? OWN_PROJECT_KEEP_REASON : term.reason
|
|
1880
1954
|
});
|
|
1881
1955
|
}
|
|
1882
|
-
|
|
1956
|
+
return input.map((term) => {
|
|
1883
1957
|
const result = normalized.get(privacyTermKey(term));
|
|
1884
1958
|
return result ? {
|
|
1885
1959
|
...term,
|
|
1886
1960
|
...result
|
|
1887
1961
|
} : term;
|
|
1888
1962
|
});
|
|
1963
|
+
}
|
|
1964
|
+
/**
|
|
1965
|
+
* The CLI applies card answers itself (D3): Hide makes every covered value Hidden and Keep keeps
|
|
1966
|
+
* it, an unticked value takes the other option, then one value gets one outcome.
|
|
1967
|
+
*/
|
|
1968
|
+
function applyCardAnswers(state) {
|
|
1969
|
+
if (!state.privacy.cards.some((card) => card.answer)) return state;
|
|
1970
|
+
const hide = answeredKeys(state, "hide");
|
|
1971
|
+
const keep = answeredKeys(state, "keep");
|
|
1972
|
+
const terms = state.privacy.terms.map((term) => {
|
|
1973
|
+
const key = privacyTermKey(term);
|
|
1974
|
+
if (hide.has(key) && term.disposition !== "hidden") return {
|
|
1975
|
+
...term,
|
|
1976
|
+
disposition: "hidden",
|
|
1977
|
+
reason: "Hidden by your decision card answer."
|
|
1978
|
+
};
|
|
1979
|
+
if (keep.has(key) && !hide.has(key) && term.disposition !== "keep") return {
|
|
1980
|
+
...term,
|
|
1981
|
+
disposition: "keep",
|
|
1982
|
+
reason: "Kept by your decision card answer."
|
|
1983
|
+
};
|
|
1984
|
+
return term;
|
|
1985
|
+
});
|
|
1889
1986
|
return {
|
|
1890
|
-
...
|
|
1987
|
+
...state,
|
|
1891
1988
|
privacy: {
|
|
1892
1989
|
...state.privacy,
|
|
1893
|
-
terms,
|
|
1894
|
-
packageApproval: null
|
|
1990
|
+
terms: normalizeValues(state, terms)
|
|
1895
1991
|
}
|
|
1896
1992
|
};
|
|
1897
1993
|
}
|
|
1898
1994
|
function respondPrivacy(state, action, source) {
|
|
1899
1995
|
if (action.kind === "card-answer") {
|
|
1900
|
-
|
|
1996
|
+
assertCardsAllowed(state);
|
|
1997
|
+
if (state.phase === "sending" || state.phase === "completed") throw new ApplicationError("INVALID_TRANSITION");
|
|
1901
1998
|
const card = state.privacy.cards.find((item) => item.id === action.cardId);
|
|
1902
1999
|
const option = card?.options.find((item) => item.id === action.optionId);
|
|
1903
2000
|
if (!card || !option) throw new ApplicationError("UNKNOWN_ITEM");
|
|
2001
|
+
const excluded = action.excludedTermKeys ?? [];
|
|
1904
2002
|
const keys = new Set(card.termKeys);
|
|
1905
|
-
|
|
2003
|
+
if (new Set(excluded).size !== excluded.length || excluded.some((key) => !keys.has(key))) throw new ApplicationError("INVALID_SELECTION");
|
|
2004
|
+
const cards = state.privacy.cards.map((item) => item.id !== card.id ? item : {
|
|
2005
|
+
...item,
|
|
2006
|
+
answer: {
|
|
2007
|
+
optionId: option.id,
|
|
2008
|
+
rule: [option.rule, action.rule?.trim()].filter(Boolean).join("\n"),
|
|
2009
|
+
additionalRule: action.rule?.trim() ?? "",
|
|
2010
|
+
remember: action.remember,
|
|
2011
|
+
...excluded.length ? { excludedTermKeys: excluded } : {}
|
|
2012
|
+
}
|
|
2013
|
+
});
|
|
2014
|
+
const answersRevision = state.privacy.answersRevision + 1;
|
|
2015
|
+
return applyCardAnswers({
|
|
1906
2016
|
...retirePrivacyArtifacts(state),
|
|
1907
2017
|
privacy: {
|
|
1908
2018
|
...state.privacy,
|
|
1909
|
-
cards
|
|
1910
|
-
...item,
|
|
1911
|
-
answer: {
|
|
1912
|
-
optionId: option.id,
|
|
1913
|
-
rule: [option.rule, action.rule?.trim()].filter(Boolean).join("\n"),
|
|
1914
|
-
additionalRule: action.rule?.trim() ?? "",
|
|
1915
|
-
remember: action.remember
|
|
1916
|
-
}
|
|
1917
|
-
}),
|
|
2019
|
+
cards,
|
|
1918
2020
|
terms: state.privacy.terms.map((term) => keys.has(privacyTermKey(term)) ? {
|
|
1919
2021
|
...term,
|
|
1920
2022
|
disposition: "pending"
|
|
1921
2023
|
} : term),
|
|
1922
|
-
answersRevision
|
|
1923
|
-
confirmedAnswersRevision: null,
|
|
2024
|
+
answersRevision,
|
|
2025
|
+
confirmedAnswersRevision: cards.every((item) => item.answer) ? answersRevision : null,
|
|
1924
2026
|
packageApproval: null
|
|
1925
2027
|
}
|
|
1926
|
-
};
|
|
2028
|
+
});
|
|
1927
2029
|
}
|
|
1928
2030
|
if (action.kind === "cards-confirm") {
|
|
1929
2031
|
assertJourneyScanned(state);
|
|
@@ -1979,7 +2081,17 @@ const journeyClassificationSubmitSchema = z.object({
|
|
|
1979
2081
|
access: journeyAccessSchema,
|
|
1980
2082
|
reason: z.string().trim().min(1).max(200)
|
|
1981
2083
|
}).strict()
|
|
1982
|
-
}).strict()).min(1).max(1e3)
|
|
2084
|
+
}).strict()).min(1).max(1e3),
|
|
2085
|
+
/**
|
|
2086
|
+
* E2: roots classification has not grouped yet. They wait in one unread Work while the
|
|
2087
|
+
* listed Works are confirmed and read; a later submission without them completes it.
|
|
2088
|
+
*/
|
|
2089
|
+
pendingRootSessionIds: z.array(z.string().min(1).max(128)).max(1e4).optional(),
|
|
2090
|
+
/**
|
|
2091
|
+
* While roots are still being grouped, scan writes keep moving the revision: a later
|
|
2092
|
+
* submission is bound to the classification it replaces instead (E2).
|
|
2093
|
+
*/
|
|
2094
|
+
expectedClassificationRevision: count$10.optional()
|
|
1983
2095
|
}).strict();
|
|
1984
2096
|
const journeyClassificationSessionsSchema = z.object({
|
|
1985
2097
|
journeyId: journeyIdSchema,
|
|
@@ -4505,7 +4617,7 @@ function propagateGroups(state, action) {
|
|
|
4505
4617
|
/** Classification confirmation fixes visibility and scan membership for this journey. */
|
|
4506
4618
|
function confirmScope(state, now, decision) {
|
|
4507
4619
|
if (state.scope.status === "confirmed") return state;
|
|
4508
|
-
if (state.classificationRevision === null || !state.works.length || state.works.some((work) => work.placement !== "placed" || !(work.status === "blocked" && work.access === "drop" && work.accessConfirmed) && (!work.description.trim() || !work.projectType))) throw new ApplicationError("SCOPE_NOT_READY");
|
|
4620
|
+
if (state.classificationRevision === null || !state.works.length || state.works.some((work) => work.placement !== "placed" && work.placement !== "classifying" || work.placement === "placed" && !(work.status === "blocked" && work.access === "drop" && work.accessConfirmed) && (!work.description.trim() || !work.projectType))) throw new ApplicationError("SCOPE_NOT_READY");
|
|
4509
4621
|
return withReadingProgress({
|
|
4510
4622
|
...state,
|
|
4511
4623
|
scope: {
|
|
@@ -4513,7 +4625,7 @@ function confirmScope(state, now, decision) {
|
|
|
4513
4625
|
actor: decision ? "delegate" : "human",
|
|
4514
4626
|
at: now
|
|
4515
4627
|
},
|
|
4516
|
-
works: state.works.map((work) => work.accessConfirmed || !work.classificationRecommendation ? {
|
|
4628
|
+
works: state.works.map((work) => work.placement === "classifying" ? work : work.accessConfirmed || !work.classificationRecommendation ? {
|
|
4517
4629
|
...work,
|
|
4518
4630
|
accessConfirmed: true
|
|
4519
4631
|
} : {
|
|
@@ -4558,7 +4670,7 @@ function setWorkType(state, workId, type, decision) {
|
|
|
4558
4670
|
function setWorksAccess(state, workIds, access, decision) {
|
|
4559
4671
|
if (new Set(workIds).size !== workIds.length) throw new ApplicationError("INVALID_SELECTION");
|
|
4560
4672
|
if (workIds.some((id) => !state.works.some((work) => work.id === id))) throw new ApplicationError("UNKNOWN_WORKSPACE");
|
|
4561
|
-
if (state.scope.status === "confirmed") return
|
|
4673
|
+
if (state.scope.status === "confirmed") return changeConfirmedAccess(state, workIds, access, decision);
|
|
4562
4674
|
return withReadingProgress({
|
|
4563
4675
|
...state,
|
|
4564
4676
|
scope: {
|
|
@@ -4584,11 +4696,12 @@ function setWorksAccess(state, workIds, access, decision) {
|
|
|
4584
4696
|
});
|
|
4585
4697
|
}
|
|
4586
4698
|
/**
|
|
4587
|
-
*
|
|
4588
|
-
*
|
|
4699
|
+
* After confirmation the person, never a delegate, may still change any Work's visibility
|
|
4700
|
+
* (D2, superseding ADR 0162's lock and ADR 0188's blocked-only Drop). Drop stops that Work's
|
|
4701
|
+
* scan; a Work moved out of Drop is read again; reading progress is recomputed.
|
|
4589
4702
|
*/
|
|
4590
|
-
function
|
|
4591
|
-
if (decision ||
|
|
4703
|
+
function changeConfirmedAccess(state, workIds, access, decision) {
|
|
4704
|
+
if (decision || state.phase === "sending" || state.phase === "completed" || state.works.some((work) => workIds.includes(work.id) && work.access === access)) throw new ApplicationError("INVALID_TRANSITION");
|
|
4592
4705
|
return withReadingProgress({
|
|
4593
4706
|
...state,
|
|
4594
4707
|
privacy: {
|
|
@@ -4598,7 +4711,9 @@ function dropBlockedWorks(state, workIds, access, decision) {
|
|
|
4598
4711
|
works: state.works.map((work) => workIds.includes(work.id) ? {
|
|
4599
4712
|
...work,
|
|
4600
4713
|
revision: work.revision + 1,
|
|
4601
|
-
|
|
4714
|
+
artifact: null,
|
|
4715
|
+
status: work.status === "ready" ? "review" : work.status,
|
|
4716
|
+
access,
|
|
4602
4717
|
accessConfirmed: true,
|
|
4603
4718
|
accessOrigin: "explicit"
|
|
4604
4719
|
} : work)
|
|
@@ -4687,7 +4802,7 @@ function respondToJourney(state, action, source, now, decision, preferenceScope)
|
|
|
4687
4802
|
};
|
|
4688
4803
|
}
|
|
4689
4804
|
if (action.kind === "consent") {
|
|
4690
|
-
if (
|
|
4805
|
+
if (decision) throw new ApplicationError("CONFIRMATION_REQUIRED");
|
|
4691
4806
|
if (state.consent) return state;
|
|
4692
4807
|
if (!action.allow) return {
|
|
4693
4808
|
...state,
|
|
@@ -4801,7 +4916,7 @@ function pendingGroups(state) {
|
|
|
4801
4916
|
* It is never filtered by Work or relevance, so its digest proves which guidance was current.
|
|
4802
4917
|
*/
|
|
4803
4918
|
function journeyGuidance(state) {
|
|
4804
|
-
const rules = [...state.privacy.rememberedRules, ...state.privacy.cards.flatMap((card) => card.answer ? [card
|
|
4919
|
+
const rules = [...state.privacy.rememberedRules, ...state.privacy.cards.flatMap((card) => card.answer ? [answeredRule(card)] : [])];
|
|
4805
4920
|
const conditions = state.groups.map(({ id, kind, key, label, condition, choice, confirmed, origin }) => ({
|
|
4806
4921
|
groupId: id,
|
|
4807
4922
|
kind,
|
|
@@ -4841,6 +4956,17 @@ function journeyGuidance(state) {
|
|
|
4841
4956
|
rules
|
|
4842
4957
|
};
|
|
4843
4958
|
}
|
|
4959
|
+
/**
|
|
4960
|
+
* An answered card as scan children read it: the question with the answer, so a value that fits
|
|
4961
|
+
* the question takes that answer instead of staying Pending (E3).
|
|
4962
|
+
*/
|
|
4963
|
+
function answeredRule(card) {
|
|
4964
|
+
const answer = card.answer;
|
|
4965
|
+
if (!answer) return "";
|
|
4966
|
+
const label = card.options.find((option) => option.id === answer.optionId)?.label;
|
|
4967
|
+
const rule = `Answered question “${card.question}”: ${answer.optionId === "hide" ? "Hide" : "Keep"}${label ? ` (“${label}”)` : ""}. ${answer.rule}`;
|
|
4968
|
+
return rule.length <= 4001 ? rule : answer.rule;
|
|
4969
|
+
}
|
|
4844
4970
|
//#endregion
|
|
4845
4971
|
//#region packages/application/src/journey/review/agents.ts
|
|
4846
4972
|
/** A dispatch without a pack ID is its own analysis agent. */
|
|
@@ -5513,9 +5639,11 @@ function journeyView(state, now) {
|
|
|
5513
5639
|
},
|
|
5514
5640
|
works: state.works.map((work) => {
|
|
5515
5641
|
const localTitle = work.suggestion || work.explicitTitleId ? work.title : work.classificationMetadata?.title ?? work.title;
|
|
5642
|
+
const imagesOmitted = hasCurrentStaticReview(state, work) ? work.staticReview?.imagesOmitted ?? 0 : 0;
|
|
5516
5643
|
if (!work.classificationMetadata) return {
|
|
5517
5644
|
...work,
|
|
5518
|
-
localTitle
|
|
5645
|
+
localTitle,
|
|
5646
|
+
imagesOmitted
|
|
5519
5647
|
};
|
|
5520
5648
|
const metadata = work.classificationMetadata;
|
|
5521
5649
|
const displayed = {
|
|
@@ -5528,6 +5656,7 @@ function journeyView(state, now) {
|
|
|
5528
5656
|
...work,
|
|
5529
5657
|
...displayed,
|
|
5530
5658
|
localTitle,
|
|
5659
|
+
imagesOmitted,
|
|
5531
5660
|
projectType: work.projectType ? {
|
|
5532
5661
|
...work.projectType,
|
|
5533
5662
|
reason: work.projectType.origin === "model" ? displayed.reason : work.projectType.reason
|
|
@@ -5668,10 +5797,30 @@ function createNativeJourney(storage, now = () => (/* @__PURE__ */ new Date()).t
|
|
|
5668
5797
|
id: "current"
|
|
5669
5798
|
})).find((resource) => resource.kind === "classification-progress");
|
|
5670
5799
|
if (previous) {
|
|
5671
|
-
const contains = (next, prior) => prior.every((id) => next.includes(id));
|
|
5672
5800
|
const replacesObsoleteAttempt = previous.baselineRevision !== progress.baselineRevision && progress.baselineRevision === state.revision && progress.status === "running" && progress.stage === "classification" && progress.completedRootIds.length === 0 && progress.groupedRootIds.length === 0 && progress.aiCompletedRootIds.length === 0 && Date.parse(progress.startedAt) > Date.parse(previous.startedAt);
|
|
5673
5801
|
const restartsFailedAttempt = previous.status === "failed" && previous.baselineRevision === progress.baselineRevision && progress.baselineRevision === state.revision && progress.status === "running" && progress.stage === "classification" && progress.completedRootIds.length === 0 && progress.groupedRootIds.length === 0 && progress.aiCompletedRootIds.length === 0 && Date.parse(progress.startedAt) > Date.parse(previous.startedAt);
|
|
5674
|
-
if (!replacesObsoleteAttempt && !restartsFailedAttempt
|
|
5802
|
+
if (!replacesObsoleteAttempt && !restartsFailedAttempt) {
|
|
5803
|
+
if (previous.inputFingerprint !== progress.inputFingerprint || previous.baselineRevision !== progress.baselineRevision || previous.proposalRevision !== null && previous.proposalRevision !== progress.proposalRevision || previous.startedAt !== progress.startedAt) throw new ApplicationError("REVISION_CONFLICT");
|
|
5804
|
+
const union = (left, right) => [.../* @__PURE__ */ new Set([...left, ...right])].toSorted();
|
|
5805
|
+
const rank = {
|
|
5806
|
+
running: 0,
|
|
5807
|
+
paused: 0,
|
|
5808
|
+
failed: 1,
|
|
5809
|
+
complete: 2
|
|
5810
|
+
};
|
|
5811
|
+
await storage.saveResource({
|
|
5812
|
+
...progress,
|
|
5813
|
+
stage: previous.stage === "proposal" ? "proposal" : progress.stage,
|
|
5814
|
+
status: rank[previous.status] > rank[progress.status] ? previous.status : progress.status,
|
|
5815
|
+
proposalRevision: progress.proposalRevision ?? previous.proposalRevision,
|
|
5816
|
+
updatedAt: Date.parse(previous.updatedAt) > Date.parse(progress.updatedAt) ? previous.updatedAt : progress.updatedAt,
|
|
5817
|
+
elapsedMs: Math.max(previous.elapsedMs, progress.elapsedMs),
|
|
5818
|
+
completedRootIds: union(previous.completedRootIds, progress.completedRootIds),
|
|
5819
|
+
groupedRootIds: union(previous.groupedRootIds, progress.groupedRootIds),
|
|
5820
|
+
aiCompletedRootIds: union(previous.aiCompletedRootIds, progress.aiCompletedRootIds)
|
|
5821
|
+
});
|
|
5822
|
+
return { accepted: true };
|
|
5823
|
+
}
|
|
5675
5824
|
}
|
|
5676
5825
|
await storage.saveResource(progress);
|
|
5677
5826
|
return { accepted: true };
|
|
@@ -5806,16 +5955,29 @@ function createNativeJourney(storage, now = () => (/* @__PURE__ */ new Date()).t
|
|
|
5806
5955
|
state: await present(result.state)
|
|
5807
5956
|
};
|
|
5808
5957
|
}
|
|
5958
|
+
const rebase = source === "panel" && !input.decision && [
|
|
5959
|
+
"consent",
|
|
5960
|
+
"work-access",
|
|
5961
|
+
"works-access",
|
|
5962
|
+
"card-answer"
|
|
5963
|
+
].includes(input.action.kind);
|
|
5964
|
+
for (let attempt = 0;; attempt++) {
|
|
5965
|
+
const result = await commitResponse(input, source, rebase);
|
|
5966
|
+
if (result.status !== "stale" || !rebase || attempt >= 4) return result;
|
|
5967
|
+
}
|
|
5968
|
+
}
|
|
5969
|
+
async function commitResponse(input, source, rebase) {
|
|
5809
5970
|
const current = await storage.current(input.journeyId);
|
|
5810
5971
|
if (!current) throw new ApplicationError("UNKNOWN_ITEM");
|
|
5811
|
-
const
|
|
5972
|
+
const expectedRevision = rebase ? current.revision : input.expectedRevision;
|
|
5973
|
+
const state = current.revision === expectedRevision ? respondToJourney(current, input.action, source, now(), input.decision, input.preferenceScope) : current;
|
|
5812
5974
|
const groupIds = input.action.kind === "group" ? [input.action.groupId] : input.action.kind === "groups-hide" ? input.action.groupIds : [];
|
|
5813
5975
|
const preferenceScopes = input.decision ? [] : state.groups.flatMap((group) => groupIds.includes(group.id) && group.preferenceScope ? [{
|
|
5814
5976
|
groupId: group.id,
|
|
5815
5977
|
preferenceScope: group.preferenceScope
|
|
5816
5978
|
}] : []);
|
|
5817
5979
|
const result = await storage.commit({
|
|
5818
|
-
expectedRevision
|
|
5980
|
+
expectedRevision,
|
|
5819
5981
|
requestKey: input.idempotencyKey,
|
|
5820
5982
|
requestHash: digest$1(input),
|
|
5821
5983
|
state,
|
|
@@ -6051,11 +6213,19 @@ function createNativeJourney(storage, now = () => (/* @__PURE__ */ new Date()).t
|
|
|
6051
6213
|
}
|
|
6052
6214
|
async function privacyWrite(value, resolve) {
|
|
6053
6215
|
const input = resolve ? privacyResolveSchema.parse(value) : cardsSubmitSchema.parse(value);
|
|
6216
|
+
const rebase = "mode" in input && input.mode === "append";
|
|
6217
|
+
for (let attempt = 0;; attempt++) {
|
|
6218
|
+
const result = await commitPrivacy(input, rebase);
|
|
6219
|
+
if (result.status !== "stale" || !rebase || attempt >= 4) return result;
|
|
6220
|
+
}
|
|
6221
|
+
}
|
|
6222
|
+
async function commitPrivacy(input, rebase) {
|
|
6054
6223
|
const current = await storage.current(input.journeyId);
|
|
6055
6224
|
if (!current) throw new ApplicationError("UNKNOWN_ITEM");
|
|
6056
|
-
const
|
|
6225
|
+
const expectedRevision = rebase ? current.revision : input.expectedRevision;
|
|
6226
|
+
const state = current.revision !== expectedRevision ? current : "resolutions" in input ? resolvePrivacyTerms(current, input) : publishDecisionCards(current, input);
|
|
6057
6227
|
const result = await storage.commit({
|
|
6058
|
-
expectedRevision
|
|
6228
|
+
expectedRevision,
|
|
6059
6229
|
requestKey: input.idempotencyKey,
|
|
6060
6230
|
requestHash: digest$1(input),
|
|
6061
6231
|
state,
|
|
@@ -6298,6 +6468,8 @@ const sendItemSchema = z.object({
|
|
|
6298
6468
|
reservation: sendUploadInputSchema.nullable(),
|
|
6299
6469
|
receipt: savedSendReceiptSchema.nullable(),
|
|
6300
6470
|
previousReceipts: z.array(savedSendReceiptSchema),
|
|
6471
|
+
/** The receipt whose bytes were PUT but not yet completed: the next step completes it (BL-210). */
|
|
6472
|
+
uploadedReceiptId: journeyIdSchema.nullable().optional(),
|
|
6301
6473
|
status: z.enum([
|
|
6302
6474
|
"ready",
|
|
6303
6475
|
"target",
|
|
@@ -6417,6 +6589,9 @@ function safeJourneySender(sender, now) {
|
|
|
6417
6589
|
async resume(input) {
|
|
6418
6590
|
return safe(await sender.resume(input));
|
|
6419
6591
|
},
|
|
6592
|
+
async withdraw(input) {
|
|
6593
|
+
return safe(await sender.withdraw(input));
|
|
6594
|
+
},
|
|
6420
6595
|
async advance(input, signal = new AbortController().signal) {
|
|
6421
6596
|
return safe(await sender.advance(input, signal));
|
|
6422
6597
|
}
|
|
@@ -10009,6 +10184,28 @@ const validateInspectionClaim = (input) => decode(inspectionClaimSchema, input);
|
|
|
10009
10184
|
const validateInspectionHead = (input) => decode(inspectionHeadSchema, input);
|
|
10010
10185
|
const validateInspectionQuery = (input) => decode(inspectionQuerySchema, input);
|
|
10011
10186
|
//#endregion
|
|
10187
|
+
//#region packages/application/src/inspection/validation/request.ts
|
|
10188
|
+
/**
|
|
10189
|
+
* The inspection Worker receives its request across a thread boundary. A real inventory can exceed
|
|
10190
|
+
* the persisted-evidence decoding bounds, so this parses the host's own request unbounded.
|
|
10191
|
+
*/
|
|
10192
|
+
const inspectionRequestSchema = z.object({
|
|
10193
|
+
customTerms: z.object({
|
|
10194
|
+
revision: z.string().min(1).max(64),
|
|
10195
|
+
terms: z.array(z.string().max(1024)).max(1e5)
|
|
10196
|
+
}).optional(),
|
|
10197
|
+
inputs: inspectionInputsSchema,
|
|
10198
|
+
inventory: inventorySchema,
|
|
10199
|
+
cleanupBySession: z.record(z.string(), cleanupSelectionSchema)
|
|
10200
|
+
});
|
|
10201
|
+
const validateInspectionRequest = (input) => {
|
|
10202
|
+
const { customTerms, ...request } = inspectionRequestSchema.parse(input);
|
|
10203
|
+
return customTerms ? {
|
|
10204
|
+
...request,
|
|
10205
|
+
customTerms
|
|
10206
|
+
} : request;
|
|
10207
|
+
};
|
|
10208
|
+
//#endregion
|
|
10012
10209
|
//#region packages/application/src/inspection/validation/index.ts
|
|
10013
10210
|
const inspectionBatchSchema = z.object({
|
|
10014
10211
|
contributions: z.array(inspectionContributionSchema).max(128),
|
|
@@ -11025,7 +11222,7 @@ function profileUrlMatchesIdentity(profileUrl, identityUrl) {
|
|
|
11025
11222
|
}
|
|
11026
11223
|
const deviceProfileScopeSchema = z.string().max(256).refine((scope) => {
|
|
11027
11224
|
const scopes = new Set(scope.trim().split(/\s+/u));
|
|
11028
|
-
return scopes.size === 2 && scopes.has("openid") && scopes.has("profile");
|
|
11225
|
+
return scopes.size === (scopes.has("offline_access") ? 3 : 2) && scopes.has("openid") && scopes.has("profile");
|
|
11029
11226
|
});
|
|
11030
11227
|
/** Display data resolved together from the issued token's UserInfo response. */
|
|
11031
11228
|
const accountProfileSchema = z.object({
|
|
@@ -11052,6 +11249,8 @@ const storedCredentialSchema = accountProfileSchema.extend({
|
|
|
11052
11249
|
identityUrl: z.string().min(1).max(2048),
|
|
11053
11250
|
clientId: z.string().min(1).max(256),
|
|
11054
11251
|
accessToken: z.string().min(1).max(4096),
|
|
11252
|
+
/** Renews the access token without a new device approval (BL-210); absent when not issued. */
|
|
11253
|
+
refreshToken: z.string().min(1).max(4096).optional(),
|
|
11055
11254
|
tokenType: z.literal("Bearer"),
|
|
11056
11255
|
scope: deviceProfileScopeSchema,
|
|
11057
11256
|
issuedAt: z.string().min(1).max(64),
|
|
@@ -11113,7 +11312,7 @@ function createSharedAccount(ports) {
|
|
|
11113
11312
|
async function read() {
|
|
11114
11313
|
return update((state) => {
|
|
11115
11314
|
const saved = state.credential;
|
|
11116
|
-
if (saved && expired(saved.expiresAt, ports.now())) {
|
|
11315
|
+
if (saved && !saved.refreshToken && expired(saved.expiresAt, ports.now())) {
|
|
11117
11316
|
state.credential = null;
|
|
11118
11317
|
state.connection = null;
|
|
11119
11318
|
state.lastError = "SIGN_IN_EXPIRED";
|
|
@@ -11168,6 +11367,7 @@ function createSharedAccount(ports) {
|
|
|
11168
11367
|
avatarUrl: state.credential.avatarUrl,
|
|
11169
11368
|
profileUrl: state.credential.profileUrl,
|
|
11170
11369
|
expiresAt: state.credential.expiresAt,
|
|
11370
|
+
renews: Boolean(state.credential.refreshToken),
|
|
11171
11371
|
connection: state.connection ?? null
|
|
11172
11372
|
};
|
|
11173
11373
|
return {
|
|
@@ -11227,6 +11427,7 @@ function createSharedAccount(ports) {
|
|
|
11227
11427
|
avatarUrl: identity.avatarUrl,
|
|
11228
11428
|
profileUrl: identity.profileUrl,
|
|
11229
11429
|
accessToken: result.accessToken,
|
|
11430
|
+
...result.refreshToken ? { refreshToken: result.refreshToken } : {},
|
|
11230
11431
|
tokenType: "Bearer",
|
|
11231
11432
|
scope: result.scope,
|
|
11232
11433
|
issuedAt: ports.now(),
|
|
@@ -11287,7 +11488,8 @@ function createSharedAccount(ports) {
|
|
|
11287
11488
|
})).authorization?.id === id) await poll(id, signal, clientId);
|
|
11288
11489
|
} catch (error) {
|
|
11289
11490
|
if (signal.aborted) return;
|
|
11290
|
-
|
|
11491
|
+
const detail = typeof error === "object" && error !== null && "detail" in error ? ` (${String(error.detail)})` : "";
|
|
11492
|
+
console.error(`Account authorization failed: ${safeCode(error)}${detail}`);
|
|
11291
11493
|
await finish(id, safeCode(error));
|
|
11292
11494
|
throw error;
|
|
11293
11495
|
} finally {
|
|
@@ -12760,23 +12962,24 @@ function retireScanGeneration(state, workId) {
|
|
|
12760
12962
|
confirmedAnswersRevision: null,
|
|
12761
12963
|
packageApproval: null
|
|
12762
12964
|
},
|
|
12763
|
-
works: state.works.map((work) =>
|
|
12764
|
-
|
|
12765
|
-
|
|
12766
|
-
|
|
12767
|
-
|
|
12768
|
-
|
|
12769
|
-
|
|
12770
|
-
|
|
12771
|
-
|
|
12772
|
-
|
|
12773
|
-
|
|
12774
|
-
|
|
12775
|
-
|
|
12776
|
-
|
|
12777
|
-
|
|
12778
|
-
|
|
12965
|
+
works: state.works.map((work) => work.id === workId ? resetWorkScan(work) : work)
|
|
12966
|
+
};
|
|
12967
|
+
}
|
|
12968
|
+
/** The same Work with a new scan generation: it is read again from its first session. */
|
|
12969
|
+
function resetWorkScan(work) {
|
|
12970
|
+
const { emptyReview: _empty, excludedReview: _excluded, staticReview: _static, metadataReviewedDigest: _metadata, reviewReuseFrom: _reuse, renderFailure: _failure, ...retained } = work;
|
|
12971
|
+
return {
|
|
12972
|
+
...retained,
|
|
12973
|
+
revision: work.revision + 1,
|
|
12974
|
+
inputRevision: work.inputRevision + 1,
|
|
12975
|
+
status: "pending",
|
|
12976
|
+
suggestion: null,
|
|
12977
|
+
totalBatches: 0,
|
|
12978
|
+
completedBatches: 0,
|
|
12979
|
+
groupIds: [],
|
|
12980
|
+
blockedCodes: [],
|
|
12981
|
+
artifact: null
|
|
12779
12982
|
};
|
|
12780
12983
|
}
|
|
12781
12984
|
//#endregion
|
|
12782
|
-
export {
|
|
12985
|
+
export { validateDetectionSummary as $, reviewRepairResourceSchema as $n, sourceChangePolicy as $r, journeyPolicyRespondSchema as $t, createAccount as A, hideKeyId as An, hasCurrentStaticReview as Ar, sendReplaceResultSchema as At, createApplication as B, confirmedHideKinds as Bn, mergePrivacyTerms as Br, journeyGuidance as Bt, bReviewScope as C, confirmedHideAdditions as Cn, journeyClassificationSessionsSchema as Cr, sendActionSchema as Ct, reviewBatchReuse as D, settleConfirmedHides as Dn, nativeEventsSchema as Dr, journeySendSchema as Dt, rebindReviewSubmit as E, renderedHideValue as En, privacyDecisionDigest as Er, sendStartSchema as Et, readAccountAvatarUrl as F, bMaskedHits as Fn, isClassifying as Fr, obsoleteJourney as Ft, validateInspectionRequest as G, syncTermGroups as Gn, journeyRenderSchema as Gr, journeyContextQuerySchema as Gt, inspectionStartSchema as H, dictionaryHides as Hn, journeyFindingsSchema as Hr, journeyBatchReadSchema as Ht, storedCredentialSchema as I, bTermMatcher as In, isReadingComplete as Ir, metadataProcessingVersion as It, validateInspectionFence as J, workPrivacyDecisions as Jn, selectionBatchSchema as Jr, hideFinishSchema as Jt, inspectionQuerySchema as K, retireWorkDescription as Kn, commandSchema as Kr, journeyContextSchema as Kt, sourceIdentityEvidence as L, bWordBounded as Ln, isSelectedWork as Lr, nativeAdapterVersions as Lt, deviceAuthorizationSchema as M, packHideIndex as Mn, staticSessionId as Mr, sendSettingsSchema as Mt, deviceProfileScopeSchema as N, bContainment as Nn, staticSessionResourceSchema as Nr, settleCorrections as Nt, guardedFindingText as O, termHideAdditions as On, nativeGetSchema as Or, sendArtifactSchema as Ot, profileUrlMatchesIdentity as P, bExceptionRanges as Pn, hasCompleteWorkDescription as Pr, currentJourneyAdapters as Pt, validateInspectionContribution as Q, reviewRepairInputSchema as Qn, stateSchema as Qr, searchScopeDigest as Qt, withSourceEvidence as R, confirmedHideGroupIds as Rn, selectedWorks as Rr, attemptBudgetCodePoints as Rt, isGenericPublicTerm as S, journeyEventSchema as Sn, validatePreparationFacts as Sr, replaceSensitiveTermsSchema as St, rebindReviewOverlay as T, readConfirmedHideChange as Tn, assertJourneyPrivacyReady as Tr, sendPrepareSchema as Tt, validateInspectionBatch as U, journeyConfirmedHides as Un, journeyPreviewSchema as Ur, journeyReviewStorageQuerySchema as Ut, inspectionCancelSchema as V, confirmedHideTerms as Vn, journeyFindingImpactSchema as Vr, applyClassification as Vt, validateInspectionBatches as W, maskedHitsStale as Wn, journeyRenderInputSchema as Wr, reviewCompileSchema as Wt, validateInspectionInputs as X, reviewCandidateInputSchema as Xn, gitMetadataBudgetBytes as Xr, journeySearchResultSchema as Xt, validateInspectionHead as Y, workCorrectionBinding as Yn, selectionSchema as Yr, hidePublishSchema as Yt, validateInspectionQuery as Z, reviewCandidateResourceSchema as Zn, producerVersion as Zr, journeySearchSaveSchema as Zt, hideScopeDigest as _, sessionReviewStatusSchema as _n, journeyPreparationProgressSchema as _r, manualUploadStartSchema as _t, locateTermEvidence as a, selectFrozenConfiguration as ai, sortingApplySchema as an, scanCanonicalResourceSchema as ar, appendSensitiveTerms as at, projectJourneyInventory as b, journeyCommitResultSchema as bn, preparationSettlementSchema as br, maximumTermsFileBytes as bt, bRereadDigest as c, reviewAttemptsResultSchema as cn, scanGitSeedsId as cr, maximumAgentSetupSessions as ct, newJourneyWork as d, sessionReconciliationResourceSchema as dn, scanExclusionResourceSchema as dr, validateFailureLocation as dt, recommendParallelism as ei, projectPreparationProgress as en, reviewTransportBytes as er, inspectionInputs as et, reviseGroupMembership as f, sessionRereadInputSchema as fn, validateScanExclusion as fr, manualUploadActionSchema as ft, activeJourneyTerms as g, sessionReviewResourceSchema as gn, journeyInventorySchema as gr, manualUploadSchema as gt, splitSelectorValues as h, sessionReviewQuerySchema as hn, journeyInventoryReadSchema as hr, manualUploadPrepareSchema as ht, scanBatchEquivalenceDigest as i, freezeConfiguration as ii, journeyPlaceSchema as in, scanAliasResourceSchema as ir, reviewInventory as it, accountProfileSchema as j, maximumHideIndexTokens as jn, staticReviewDigest as jr, sendResolutionSchema as jt, staticallyHiddenFindings as k, addHideIndexTokens as kn, nativeRespondSchema as kr, sendReceiptSchema as kt, reconcileBSession as l, sessionReconcileInputSchema as ln, scanGitSeedsResource as lr, artifactFailureDetailSchema as lt, selectedValueMembers as m, sessionReviewInputSchema as mn, journeyInventoryQuerySchema as mr, manualUploadChoiceSchema as mt, retireScanGeneration as n, effectiveTreatmentSchema as ni, journeyResourceSchema as nn, mergeBRepair as nr, settingsQuerySchema as nt, validateBCrossSegmentReview as o, staticCatalogRef as oi, reviewAttemptResourceSchema as on, scanPreparationDigest as or, classifyAgentSetup as ot, resolveGroupSplit as p, sessionRereadResourceSchema as pn, resolveSourceSelection as pr, manualUploadBindingSchema as pt, validateInspectionClaim as q, workDecisionDigest as qn, packageCommandSchema as qr, hideBeginSchema as qt, scanBatchContextDigest as r, defaultScopedSettings as ri, journeyIsolateSchema as rn, planBRepair as rr, readWorkspaceOutcomes as rt, bCrossSegmentReviewSchema as s, reviewAttemptsQuerySchema as sn, scanSessionResourceSchema as sr, defaultAgentSetupInclusion as st, resetWorkScan as t, approvedTreatmentSchema as ti, journeyResourceQuerySchema as tn, bReviewDigest as tr, settingsBatchSchema as tt, reconstructBFields as u, sessionReconcileResultSchema as un, verifiedScanGitSeeds as ur, resolveFailureLocation as ut, semanticGroupKey as v, sessionUsefulnessInputSchema as vn, emptyPreparationFacts as vr, candidateSortAvailable as vt, rebindReviewAlignment as w, confirmedHideDeltaSchema as wn, applyCardAnswers as wr, sendChoiceSchema as wt, preparationScope as x, journeyCommitSchema as xn, preparationStartSchema as xr, normalizeSensitiveTerms as xt, changeJourney as y, sessionUsefulnessResourceSchema as yn, preparationBeginSchema as yr, emptyTermsRevision as yt, agentSetupKey as z, confirmedHideKey as zn, withReadingProgress as zr, validateAttemptAppend as zt };
|