@gitroll/tacitt-cli 0.6.7 → 0.6.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/README.md +1 -1
  2. package/dist/{agent-setup-YlFIJz-h.mjs → agent-setup-CODlN6zl.mjs} +1 -1
  3. package/dist/agent-setup-worker.mjs +4 -4
  4. package/dist/cli.mjs +5 -5
  5. package/dist/codex-title-worker.mjs +1 -1
  6. package/dist/configured-preview-worker.mjs +4 -4
  7. package/dist/configured-session-worker.mjs +4 -4
  8. package/dist/{heap-DsE74_-n.mjs → heap-Dt3-d27v.mjs} +2 -2
  9. package/dist/inspection-worker.mjs +3 -3
  10. package/dist/{job-CeSf9UCC.mjs → job-BQXssW46.mjs} +3 -3
  11. package/dist/{model-f_QnDyyb.mjs → model-CSx2dP_P.mjs} +1 -1
  12. package/dist/operation-executor.mjs +2 -2
  13. package/dist/preview-worker.mjs +1 -1
  14. package/dist/{query-Bb72w2DX.mjs → query-CfhcS4gd.mjs} +194 -134
  15. package/dist/{run-RA_8zZsL.mjs → run-xlOaKCk8.mjs} +2 -2
  16. package/dist/{src-BBjnljUs.mjs → src-BgsEnMsy.mjs} +3 -3
  17. package/dist/{src-d7n58sbH.mjs → src-DzKuzGVH.mjs} +183 -147
  18. package/dist/{src-p_uJNjV3.mjs → src-V9GHLZQs.mjs} +1 -1
  19. package/dist/store-database-worker.mjs +1 -1
  20. package/dist/web/assets/{index-B6kJ6XXF.js → index-9UfCT_2C.js} +1 -1
  21. package/dist/web/index.html +1 -1
  22. package/package.json +1 -1
  23. package/skills/tacitt/SKILL.md +3 -3
  24. package/skills/tacitt/references/commands.md +50 -11
  25. package/skills/tacitt/references/journey.md +1 -1
  26. package/skills/tacitt/references/parallel-review.md +21 -0
  27. package/skills/tacitt/scripts/INDEX.md +39 -36
  28. package/skills/tacitt/scripts/journey-scan-timing.d.mts +15 -0
  29. package/skills/tacitt/scripts/journey-scan-timing.mjs +153 -1
  30. package/skills/tacitt/scripts/journey.mjs +15 -0
  31. package/skills/tacitt/scripts/review.mjs +280 -36
  32. package/LICENSE +0 -11
@@ -1,10 +1,10 @@
1
- import { $ as createCleanup, B as parallelismLimits, C as readOriginalSearchFields, F as SessionWorkerError, G as processJourneyMetadataFields, H as privateJourneyDirectory, I as sessionWorkerFailure, K as staticMaskCategory, O as captureLogicalJourneySources, P as createSharedSessionPool, Q as removeNamedTemporarySpools, R as defaultParallelism, T as createCollectionArtifacts, U as readLogicalJourneyFinalMasks, W as readConfiguredOutputInfo, Z as createTemporary, _ as processJourneyMetadata, a as scanReviewFields, at as windowsOwnerOnly, c as readSessionScanRecords, g as readCapturedOriginalRows, i as buildWorkScanBatches, it as restrictToOwner, j as runConfiguredSessionJob, k as capturedJourneyScope, l as scanPreparedSession, m as openConfiguredUpload, n as verifyPreparedSessionSources, nt as makePrivateDirectory, o as createWorkPieces, ot as isWindowsAclFailure, p as configuredSessionUploads, q as readWorkspacePair, r as prepareSessionScans, rt as openPrivateFile, s as readSessionScanFields, st as windowsAclCodes, t as preparedScanConfiguration, v as readStaticSessionMasks, w as readConfiguredSearchFields, y as staticSessionJobs, z as gitSeedsProvider } from "./src-p_uJNjV3.mjs";
2
- import { A as createExecutionPort, C as saveRemoteState, D as createPackagingProgressPort, E as exportDelivery, F as loadDeliveryResults, L as inBackgroundStoreLane, M as withStateMutex, N as createDeliveryService, O as createStore, P as preflight, R as isBackgroundStatusPoll, S as readRemoteState, T as collectRemoteWorkers, _ as staticBaseProduction, a as writeJourneyOutput, b as workApproval, c as mergeHideIndexTokens, f as writeJourneyBase, g as staticBaseInputs, h as staticSessions, l as packRenderHideIndex, m as saveStaticSession, o as createHideIndexTokens, p as readStaticResult, s as hideIndexTexts, t as journeyOutputJob, u as journeyBaseJob, v as readSelectedCaptures, w as journeyDirectory, x as isRemoteImport, y as prepareSourcePlan, z as retrySharingViolation } from "./job-CeSf9UCC.mjs";
1
+ import { $ as createCleanup, B as parallelismLimits, C as readOriginalSearchFields, F as SessionWorkerError, G as processJourneyMetadataFields, H as privateJourneyDirectory, I as sessionWorkerFailure, K as staticMaskCategory, O as captureLogicalJourneySources, P as createSharedSessionPool, Q as removeNamedTemporarySpools, R as defaultParallelism, T as createCollectionArtifacts, U as readLogicalJourneyFinalMasks, W as readConfiguredOutputInfo, Z as createTemporary, _ as processJourneyMetadata, a as scanReviewFields, at as windowsOwnerOnly, c as readSessionScanRecords, g as readCapturedOriginalRows, i as buildWorkScanBatches, it as restrictToOwner, j as runConfiguredSessionJob, k as capturedJourneyScope, l as scanPreparedSession, m as openConfiguredUpload, n as verifyPreparedSessionSources, nt as makePrivateDirectory, o as createWorkPieces, ot as isWindowsAclFailure, p as configuredSessionUploads, q as readWorkspacePair, r as prepareSessionScans, rt as openPrivateFile, s as readSessionScanFields, st as windowsAclCodes, t as preparedScanConfiguration, v as readStaticSessionMasks, w as readConfiguredSearchFields, y as staticSessionJobs, z as gitSeedsProvider } from "./src-V9GHLZQs.mjs";
2
+ import { A as createExecutionPort, C as saveRemoteState, D as createPackagingProgressPort, E as exportDelivery, F as loadDeliveryResults, L as inBackgroundStoreLane, M as withStateMutex, N as createDeliveryService, O as createStore, P as preflight, R as isBackgroundStatusPoll, S as readRemoteState, T as collectRemoteWorkers, _ as staticBaseProduction, a as writeJourneyOutput, b as workApproval, c as mergeHideIndexTokens, f as writeJourneyBase, g as staticBaseInputs, h as staticSessions, l as packRenderHideIndex, m as saveStaticSession, o as createHideIndexTokens, p as readStaticResult, s as hideIndexTexts, t as journeyOutputJob, u as journeyBaseJob, v as readSelectedCaptures, w as journeyDirectory, x as isRemoteImport, y as prepareSourcePlan, z as retrySharingViolation } from "./job-BQXssW46.mjs";
3
3
  import { $t as safeField, Bt as sessionPeriodSchema, Dn as createStaticProcessor, Fn as entityDictionaryVersion, Ft as termTypeInfo, Gt as ownerProfileSchema, Kt as passportAddressSchema, Ot as privacyTermKey, Qt as safeCode, Sn as currentDetectorVersion, T as bLiteralTerms, Un as frameRecords, Wt as mergeOwnerProfile, Xt as ApplicationError, Zt as UnfinishedJourneyError, an as observeSource, ar as admitCustomTerm, c as textDigest, ir as createEntityMatcher, nn as reviewFamilies, or as admitGitName, qt as profileHasChoices, tn as familySelected, ur as ProcessingError, zt as filterInventoryByPeriod } from "./locate-BWkblijS.mjs";
4
- import { a as mainTextChunks, c as previewInWorker, i as nearestSortingRepository, l as createNativeAdapters, n as createProjectEvidenceCollector, o as mainTextFields, r as sortingRepositoryId, s as textChunks, t as createHarnesses, u as createGitNameSeedProvider } from "./src-BBjnljUs.mjs";
5
- import { $ as settingsBatchSchema, A as deviceAuthorizationSchema, Ar as staticReviewDigest, B as inspectionStartSchema, Br as sendResolutionSchema, Bt as classificationWorks, Ct as sendPrepareSchema, Dt as currentJourneyAdapters, Fn as bTermMatcher, Fr as agentSourcesSchema, Gn as retireWorkDescription, Gr as isReadingComplete, Hn as journeyConfirmedHides, Hr as hasCompleteWorkDescription, Ht as newJourneyWork, Ir as journeySendSchema, Jn as workCorrectionBinding, Kn as workDecisionDigest, Kr as isSelectedWork, Lr as sendArtifactSchema, M as profileUrlMatchesIdentity, N as readAccountAvatarUrl, O as createAccount, Ot as obsoleteJourney, P as storedCredentialSchema, Pr as agentSourceSchema, Pt as applyClassification, R as createApplication, Rr as sendReceiptSchema, St as sendChoiceSchema, Tr as privacyDecisionDigest, Tt as sendStartSchema, Ur as isClassifying, V as validateInspectionBatch, Vr as sendSettingsSchema, Vt as retireScanGeneration, W as inspectionQuerySchema, Wr as isIncludedWork, Yr as withReadingProgress, Yt as journeySearchResultSchema, Zt as searchScopeDigest, _ as changeJourney, _r as emptyPreparationFacts, _t as emptyTermsRevision, ai as selectionSchema, ar as scanPreparationDigest, bt as replaceSensitiveTermsSchema, cr as scanGitSeedsResource, et as settingsQuerySchema, ft as manualUploadChoiceSchema, h as hideScopeDigest, ht as manualUploadStartSchema, ii as selectionBatchSchema, j as deviceProfileScopeSchema, k as accountProfileSchema, kr as hasCurrentStaticReview, lr as verifiedScanGitSeeds, lt as validateFailureLocation, m as activeJourneyTerms, mt as manualUploadSchema, ni as commandSchema, or as scanSessionResourceSchema, pt as manualUploadPrepareSchema, ri as packageCommandSchema, rt as appendSensitiveTerms, si as producerVersion, sr as scanGitSeedsId, st as artifactFailureDetailSchema, ui as recommendParallelism, ur as scanExclusionResourceSchema, ut as manualUploadActionSchema, wr as assertJourneyPrivacyReady, wt as sendRequestSchema, xt as sendActionSchema, yt as normalizeSensitiveTerms, z as inspectionCancelSchema, zn as confirmedHideKinds, zr as sendReplaceResultSchema, zt as classificationPartition } from "./src-d7n58sbH.mjs";
6
- import { _t as isCoordinationBusy } from "./heap-DsE74_-n.mjs";
7
- import { t as createAgentSetupPort } from "./agent-setup-YlFIJz-h.mjs";
4
+ import { a as mainTextChunks, c as previewInWorker, i as nearestSortingRepository, l as createNativeAdapters, n as createProjectEvidenceCollector, o as mainTextFields, r as sortingRepositoryId, s as textChunks, t as createHarnesses, u as createGitNameSeedProvider } from "./src-BgsEnMsy.mjs";
5
+ import { $ as settingsBatchSchema, $r as isReadingComplete, A as deviceAuthorizationSchema, B as inspectionStartSchema, Bt as classificationWorks, Ct as sendPrepareSchema, Dt as currentJourneyAdapters, Fn as bTermMatcher, Gn as retireWorkDescription, Gr as sendArtifactSchema, Hn as journeyConfirmedHides, Hr as agentSourceSchema, Ht as newJourneyWork, Jn as workCorrectionBinding, Jr as sendResolutionSchema, Kn as workDecisionDigest, Kr as sendReceiptSchema, Lr as hasCurrentStaticReview, M as profileUrlMatchesIdentity, Mr as privacyDecisionDigest, N as readAccountAvatarUrl, O as createAccount, Or as displayedScopeDigest, Ot as obsoleteJourney, P as storedCredentialSchema, Pt as applyClassification, Qr as isIncludedWork, R as createApplication, Rr as staticReviewDigest, St as sendChoiceSchema, Tt as sendStartSchema, Ur as agentSourcesSchema, V as validateInspectionBatch, Vt as retireScanGeneration, W as inspectionQuerySchema, Wr as journeySendSchema, Xr as hasCompleteWorkDescription, Yr as sendSettingsSchema, Yt as journeySearchResultSchema, Zr as isClassifying, Zt as searchScopeDigest, _ as changeJourney, _r as emptyPreparationFacts, _t as emptyTermsRevision, ai as packageCommandSchema, ar as scanPreparationDigest, bt as replaceSensitiveTermsSchema, cr as scanGitSeedsResource, ei as isSelectedWork, et as settingsQuerySchema, fi as recommendParallelism, ft as manualUploadChoiceSchema, h as hideScopeDigest, ht as manualUploadStartSchema, ii as commandSchema, j as deviceProfileScopeSchema, jr as assertJourneyPrivacyReady, k as accountProfileSchema, kr as requestedScope, li as producerVersion, lr as verifiedScanGitSeeds, lt as validateFailureLocation, m as activeJourneyTerms, mt as manualUploadSchema, oi as selectionBatchSchema, or as scanSessionResourceSchema, pt as manualUploadPrepareSchema, qr as sendReplaceResultSchema, ri as withReadingProgress, rt as appendSensitiveTerms, si as selectionSchema, sr as scanGitSeedsId, st as artifactFailureDetailSchema, ur as scanExclusionResourceSchema, ut as manualUploadActionSchema, wt as sendRequestSchema, xt as sendActionSchema, yt as normalizeSensitiveTerms, z as inspectionCancelSchema, zn as confirmedHideKinds, zt as classificationPartition } from "./src-DzKuzGVH.mjs";
6
+ import { _t as isCoordinationBusy } from "./heap-Dt3-d27v.mjs";
7
+ import { t as createAgentSetupPort } from "./agent-setup-CODlN6zl.mjs";
8
8
  import { t as workerMessageSchema } from "./messages-D3m3bhva.mjs";
9
9
  import { constants, write } from "node:fs";
10
10
  import { z } from "zod";
@@ -2603,18 +2603,24 @@ function createJourneyPreparation(options) {
2603
2603
  const scanWorks = scanRequested && state.scope.status === "confirmed" ? state.works : [];
2604
2604
  if (scanWorks.length) run = await runWorkers(options.workers);
2605
2605
  const frozen = state;
2606
- const blockWork = (work, error) => changeJourney(storage, journeyId, "snapshot", (before) => {
2607
- if (before.phase === "paused") throw new ApplicationError("OPERATION_CANCELED");
2608
- if (before.phase === "sending" || before.phase === "completed") return before;
2609
- return withReadingProgress({
2610
- ...before,
2611
- works: before.works.map((item) => item.id === work.id && item.inputRevision === work.inputRevision && !item.blockedCodes.includes("PRIVACY_CHANGE_PENDING") ? {
2612
- ...item,
2613
- status: "blocked",
2614
- blockedCodes: blockedCodes(error, safeCode(error))
2615
- } : item)
2616
- });
2617
- }, 100);
2606
+ const blockedForRetry = new Set(state.works.filter((work) => work.status === "blocked").map((work) => `${work.id}:${work.inputRevision}`));
2607
+ const deferredForHide = /* @__PURE__ */ new Set();
2608
+ const blockWork = async (work, error) => {
2609
+ const blocked = await changeJourney(storage, journeyId, "snapshot", (before) => {
2610
+ if (before.phase === "paused") throw new ApplicationError("OPERATION_CANCELED");
2611
+ if (before.phase === "sending" || before.phase === "completed") return before;
2612
+ return withReadingProgress({
2613
+ ...before,
2614
+ works: before.works.map((item) => item.id === work.id && item.inputRevision === work.inputRevision && !item.blockedCodes.includes("PRIVACY_CHANGE_PENDING") ? {
2615
+ ...item,
2616
+ status: "blocked",
2617
+ blockedCodes: blockedCodes(error, safeCode(error))
2618
+ } : item)
2619
+ });
2620
+ }, 100);
2621
+ if (blocked.works.some((item) => item.id === work.id && item.inputRevision === work.inputRevision && item.status === "blocked")) blockedForRetry.add(`${work.id}:${work.inputRevision}`);
2622
+ return blocked;
2623
+ };
2618
2624
  const retryLimit = options.retryLimit ?? workRetryDelaysMs.length;
2619
2625
  const generation = (work) => `${work.id}:${work.inputRevision}`;
2620
2626
  let serialAdmission = Promise.resolve();
@@ -2638,11 +2644,14 @@ function createJourneyPreparation(options) {
2638
2644
  await (options.retryDelay ?? waitForWorkRetry)(delay, abort.signal);
2639
2645
  abort.signal.throwIfAborted();
2640
2646
  let resumed = false;
2641
- await changeJourney(storage, journeyId, "snapshot", (before) => {
2647
+ let deferred = false;
2648
+ const committed = await changeJourney(storage, journeyId, "snapshot", (before) => {
2642
2649
  resumed = false;
2650
+ deferred = false;
2643
2651
  const target = before.works.find((item) => item.id === work.id);
2644
2652
  if (before.phase === "sending" || before.phase === "completed" || before.phase === "paused" || !target || !isSelectedWork(target) || target.inputRevision !== work.inputRevision || target.status !== "blocked" || target.blockedCodes.includes("PRIVACY_CHANGE_PENDING")) return before;
2645
2653
  resumed = !before.pendingHideId;
2654
+ deferred = !resumed;
2646
2655
  return withReadingProgress({
2647
2656
  ...before,
2648
2657
  privacy: {
@@ -2656,6 +2665,7 @@ function createJourneyPreparation(options) {
2656
2665
  } : item)
2657
2666
  });
2658
2667
  }, 100);
2668
+ if (deferred && committed.pendingHideId && committed.works.some((item) => generation(item) === generation(work) && item.status === "pending")) deferredForHide.add(generation(work));
2659
2669
  return resumed;
2660
2670
  };
2661
2671
  const readRetries = /* @__PURE__ */ new Map();
@@ -2693,6 +2703,7 @@ function createJourneyPreparation(options) {
2693
2703
  "reading",
2694
2704
  "review"
2695
2705
  ].includes(work.status)) return false;
2706
+ blockedForRetry.delete(generation(work));
2696
2707
  prepared.add(generation(work));
2697
2708
  await prepareClassificationMetadata(storage, latest, work, options.processing, abort.signal, plan);
2698
2709
  let failures = collectPreparationFailures(plan.approval.inventory, work.rootSessionIds, {
@@ -2802,7 +2813,15 @@ function createJourneyPreparation(options) {
2802
2813
  abort.abort(error);
2803
2814
  };
2804
2815
  const statics = [];
2816
+ const priorStatics = /* @__PURE__ */ new Map();
2805
2817
  const reads = [];
2818
+ const activeReads = /* @__PURE__ */ new Set();
2819
+ const activeStatics = /* @__PURE__ */ new Set();
2820
+ let workSettled = Promise.withResolvers();
2821
+ const notifySettled = () => {
2822
+ workSettled.resolve();
2823
+ workSettled = Promise.withResolvers();
2824
+ };
2806
2825
  const pass = async (works) => {
2807
2826
  let submittedWorks = 0;
2808
2827
  const submitted = Promise.withResolvers();
@@ -2826,6 +2845,7 @@ function createJourneyPreparation(options) {
2826
2845
  releaseAdmission.set(planned.id, () => released.resolve());
2827
2846
  const onSubmitted = submission();
2828
2847
  const read = async () => {
2848
+ await priorStatics.get(planned.id);
2829
2849
  if (!run.pool) await previous;
2830
2850
  if (fatal) {
2831
2851
  onSubmitted();
@@ -2840,25 +2860,45 @@ function createJourneyPreparation(options) {
2840
2860
  onSubmitted();
2841
2861
  released.resolve();
2842
2862
  }
2843
- statics.push(retryContention(() => staticWork(planned, passSubmitted), (error) => options.onFailure(error), abort.signal).catch(stop));
2863
+ activeStatics.add(planned.id);
2864
+ const staticResult = retryContention(() => staticWork(planned, passSubmitted), (error) => options.onFailure(error), abort.signal).catch(stop).finally(() => {
2865
+ activeStatics.delete(planned.id);
2866
+ notifySettled();
2867
+ });
2868
+ priorStatics.set(planned.id, staticResult);
2869
+ statics.push(staticResult);
2844
2870
  };
2845
- reads.push(read());
2871
+ activeReads.add(planned.id);
2872
+ reads.push(read().finally(() => {
2873
+ activeReads.delete(planned.id);
2874
+ notifySettled();
2875
+ }));
2846
2876
  }
2847
2877
  await Promise.all(admissions);
2848
2878
  };
2849
- /** Selected Works this run has not prepared yet, waiting while grouping continues (E2). */
2879
+ /** Admit newly grouped and explicitly retried Works until both read and static work drain. */
2850
2880
  const later = async () => {
2851
2881
  for (;;) {
2852
2882
  abort.signal.throwIfAborted();
2883
+ const settled = workSettled.promise;
2853
2884
  const latest = await storage.current(journeyId);
2854
2885
  if (!latest || latest.phase === "paused" || latest.scope.status !== "confirmed") return [];
2886
+ for (const work of latest.works) if (work.status === "blocked") blockedForRetry.add(generation(work));
2855
2887
  const ready = latest.works.filter((work) => isSelectedWork(work) && [
2856
2888
  "pending",
2857
2889
  "reading",
2858
2890
  "review"
2859
- ].includes(work.status) && !prepared.has(`${work.id}:${work.inputRevision}`));
2860
- if (ready.length || !isClassifying(latest)) return ready;
2861
- await setTimeout$1(laterWorksPollMs, void 0, { signal: abort.signal }).catch(() => abort.signal.throwIfAborted());
2891
+ ].includes(work.status) && !activeReads.has(work.id) && !activeStatics.has(work.id) && !deferredForHide.has(generation(work)) && (!prepared.has(generation(work)) && !hasCurrentStaticReview(latest, work) || work.status === "pending" && blockedForRetry.has(generation(work))));
2892
+ if (ready.length || !isClassifying(latest) && !activeReads.size && !activeStatics.size) return ready;
2893
+ const polling = new AbortController();
2894
+ try {
2895
+ await Promise.race([settled, setTimeout$1(laterWorksPollMs, void 0, { signal: AbortSignal.any([abort.signal, polling.signal]) })]);
2896
+ } catch (error) {
2897
+ abort.signal.throwIfAborted();
2898
+ throw error;
2899
+ } finally {
2900
+ polling.abort();
2901
+ }
2862
2902
  }
2863
2903
  };
2864
2904
  try {
@@ -2971,7 +3011,16 @@ async function packageBase(storage, state, work, processing, directory, signal,
2971
3011
  if (after.phase === "paused") throw new ApplicationError("OPERATION_CANCELED");
2972
3012
  assertJourneyPrivacyReady(after, true);
2973
3013
  }
2974
- await assertCurrent();
3014
+ try {
3015
+ await assertCurrent();
3016
+ } catch (error) {
3017
+ await Promise.all([
3018
+ base.primary,
3019
+ base.companion,
3020
+ base.maskLedger
3021
+ ].map((file) => rm(file.path, { force: true })));
3022
+ throw error;
3023
+ }
2975
3024
  try {
2976
3025
  await storage.saveResource(base);
2977
3026
  return base;
@@ -6928,7 +6977,7 @@ function retryDelay(error, fallback, now) {
6928
6977
  const delay = Number.isFinite(seconds) ? seconds * 1e3 : Date.parse(header) - now;
6929
6978
  return Number.isFinite(delay) ? Math.max(fallback, delay) : fallback;
6930
6979
  }
6931
- /** Reconcile first; only failed transfers that consumed bytes charge the durable budget. */
6980
+ /** Reconcile retained intents; only byte-started failures charge the durable budget. */
6932
6981
  async function attemptSession({ dependencies, original, session, key, remote, signal, guard, checkpoint }) {
6933
6982
  const previous = original.sessionUpload?.key === key && original.sessionUpload.sha256 === session.sha256 ? original.sessionUpload : null;
6934
6983
  let failures = previous?.attempt ?? 0;
@@ -6967,8 +7016,31 @@ async function attemptSession({ dependencies, original, session, key, remote, si
6967
7016
  await guard();
6968
7017
  await save();
6969
7018
  let lastReported = 0;
7019
+ const reserveUploadComplete = async () => {
7020
+ await guard();
7021
+ const reservation = await remote.reserve(input, signal);
7022
+ if (reservation.state === "awaiting_upload") {
7023
+ await guard();
7024
+ transfer.attempt = failures + 1;
7025
+ await session.upload(reservation, signal, async (bytes) => {
7026
+ const sent = Math.min(session.byteLength, Math.max(transfer.bytesSent, bytes));
7027
+ transfer.bytesAttempted += sent - transfer.bytesSent;
7028
+ transfer.bytesSent = sent;
7029
+ if (Date.now() - lastReported >= 250 || sent === session.byteLength) {
7030
+ report();
7031
+ lastReported = Date.now();
7032
+ }
7033
+ });
7034
+ await guard();
7035
+ await remote.complete({
7036
+ ...input,
7037
+ metadata: session.metadata
7038
+ }, signal);
7039
+ }
7040
+ };
6970
7041
  try {
6971
- try {
7042
+ if (previous === null) await reserveUploadComplete();
7043
+ else try {
6972
7044
  await remote.complete({
6973
7045
  ...input,
6974
7046
  metadata: session.metadata
@@ -6976,26 +7048,7 @@ async function attemptSession({ dependencies, original, session, key, remote, si
6976
7048
  } catch (error) {
6977
7049
  if (!(error instanceof JourneyRemoteError) || error.status !== 409 || error.code !== "upload_incomplete") throw error;
6978
7050
  if (failures >= 3) throw new ApplicationError("SESSION_UPLOAD_EXHAUSTED");
6979
- await guard();
6980
- const reservation = await remote.reserve(input, signal);
6981
- if (reservation.state === "awaiting_upload") {
6982
- await guard();
6983
- transfer.attempt = failures + 1;
6984
- await session.upload(reservation, signal, async (bytes) => {
6985
- const sent = Math.min(session.byteLength, Math.max(transfer.bytesSent, bytes));
6986
- transfer.bytesAttempted += sent - transfer.bytesSent;
6987
- transfer.bytesSent = sent;
6988
- if (Date.now() - lastReported >= 250 || sent === session.byteLength) {
6989
- report();
6990
- lastReported = Date.now();
6991
- }
6992
- });
6993
- await guard();
6994
- await remote.complete({
6995
- ...input,
6996
- metadata: session.metadata
6997
- }, signal);
6998
- }
7051
+ await reserveUploadComplete();
6999
7052
  }
7000
7053
  transfer.bytesAcknowledged = session.byteLength;
7001
7054
  await guard();
@@ -7197,10 +7250,10 @@ function usesSessionSend(dependencies, send) {
7197
7250
  if (send.items.some((item) => item.sessionUpload !== void 0 || item.sessionMembership || item.sessionAssembly)) return true;
7198
7251
  return !send.items.some((item) => item.receipt || item.reservation || item.previousReceipts.length > 0);
7199
7252
  }
7200
- async function saveSend(dependencies, snapshot, next, action) {
7253
+ async function saveSend(dependencies, snapshot, next, action, expectedJourneyRevision = action?.expectedJourneyRevision ?? snapshot.journey.revision) {
7201
7254
  return dependencies.storage.commitSend({
7202
7255
  journeyId: snapshot.journey.journeyId,
7203
- expectedJourneyRevision: action?.expectedJourneyRevision ?? snapshot.journey.revision,
7256
+ expectedJourneyRevision,
7204
7257
  expectedSendRevision: action?.expectedSendRevision ?? (snapshot.send?.id === next.id ? snapshot.send.revision : null),
7205
7258
  requestKey: action?.idempotencyKey ?? randomUUID(),
7206
7259
  requestHash: hash$1(action ?? next),
@@ -9240,89 +9293,91 @@ const sendRecoveryCodes = [
9240
9293
  ];
9241
9294
  //#endregion
9242
9295
  //#region apps/cli/src/account/journey/request.ts
9243
- /** Artifact-independent authorization: packaging progress cannot expand this scope. */
9244
- function requestedScope(journey) {
9245
- return hash$1({
9246
- privacy: privacyDecisionDigest(journey),
9247
- configurationId: journey.configurationId,
9248
- confirmedHideRevision: journey.confirmedHideRevision ?? 0,
9249
- consent: journey.consent,
9250
- profile: journey.profile,
9251
- works: journey.works.map((work) => ({
9252
- id: work.id,
9253
- inputRevision: work.inputRevision,
9254
- access: work.access,
9255
- accessConfirmed: work.accessConfirmed,
9256
- included: isIncludedWork(work),
9257
- placement: work.placement,
9258
- suggestion: work.suggestion
9259
- }))
9260
- });
9261
- }
9262
9296
  function requestMatches(send, journey) {
9263
9297
  return send.request?.scopeDigest === requestedScope(journey) && !journey.pendingHideId && journey.phase !== "paused" && !journey.abandonedAt;
9264
9298
  }
9265
9299
  async function requestSend(dependencies, raw, hostId, source) {
9266
9300
  const input = sendRequestSchema.parse(raw);
9267
- const current = await dependencies.storage.loadSend(input.journeyId);
9268
- if (!current) throw new ApplicationError("UNKNOWN_ITEM");
9269
- const recorded = current.send?.id === input.idempotencyKey ? current : await dependencies.storage.loadSend(input.journeyId, input.idempotencyKey);
9270
- if (recorded?.send) return dependencies.storage.commitSend({
9271
- journeyId: input.journeyId,
9272
- expectedJourneyRevision: input.expectedJourneyRevision,
9273
- expectedSendRevision: null,
9274
- requestKey: input.idempotencyKey,
9275
- requestHash: hash$1(input),
9276
- state: recorded.send,
9277
- at: dependencies.now()
9278
- });
9279
- if (current.journey.revision !== input.expectedJourneyRevision) return {
9280
- ...current,
9281
- status: "stale"
9282
- };
9283
- assertJourneyPrivacyReady(current.journey);
9284
- if (current.journey.pendingHideId || current.journey.phase === "paused") throw new ApplicationError("SCOPE_NOT_READY");
9285
- if (current.send && ([
9286
- "awaiting-packaging",
9287
- "sending",
9288
- "waiting",
9289
- "sign-in",
9290
- "review"
9291
- ].includes(current.send.status) || current.send.items.some((item) => item.recoveryReview) || current.send.status === "paused" && current.send.confirmedAt !== null && current.send.scopeDigest === scopeDigest(current.journey))) throw new ApplicationError("INVALID_TRANSITION");
9292
- if (!hostId) throw new ApplicationError("INVALID_TRANSITION");
9293
- const included = current.journey.works.filter(isIncludedWork);
9294
- if (!sameIds$1(input.included.map((work) => work.workId), included.map((work) => work.id)) || !input.included.every((item) => included.some((work) => work.id === item.workId && work.access === item.access && work.accessConfirmed)) || !sameIds$1(input.omittedWorkIds, current.journey.works.filter((work) => !isIncludedWork(work)).map((work) => work.id))) throw new ApplicationError("CONFIRMATION_REQUIRED");
9295
- const subject = (await dependencies.auth.connect(new AbortController().signal))?.subject ?? null;
9296
- const at = dependencies.now();
9297
- return dependencies.storage.commitSend({
9298
- journeyId: input.journeyId,
9299
- expectedJourneyRevision: input.expectedJourneyRevision,
9300
- expectedSendRevision: null,
9301
- requestKey: input.idempotencyKey,
9302
- requestHash: hash$1(input),
9303
- state: {
9304
- id: input.idempotencyKey,
9301
+ let expectedScope = input.displayedScopeDigest;
9302
+ let binding;
9303
+ let firstSendId = null;
9304
+ for (let attempt = 0;; attempt += 1) {
9305
+ const current = await dependencies.storage.loadSend(input.journeyId);
9306
+ if (!current) throw new ApplicationError("UNKNOWN_ITEM");
9307
+ if (attempt === 0) firstSendId = current.send?.id ?? null;
9308
+ const recorded = current.send?.id === input.idempotencyKey ? current : await dependencies.storage.loadSend(input.journeyId, input.idempotencyKey);
9309
+ if (recorded?.send) return dependencies.storage.commitSend({
9305
9310
  journeyId: input.journeyId,
9306
- revision: 0,
9307
- scopeDigest: requestedScope(current.journey),
9308
- subject,
9309
- confirmedAt: null,
9310
- status: "awaiting-packaging",
9311
- items: [],
9312
- omitted: [],
9313
- error: null,
9314
- request: {
9315
- requestedAt: at,
9316
- subject,
9317
- hostId,
9318
- source,
9311
+ expectedJourneyRevision: input.expectedJourneyRevision,
9312
+ expectedSendRevision: null,
9313
+ requestKey: input.idempotencyKey,
9314
+ requestHash: hash$1(input),
9315
+ state: recorded.send,
9316
+ at: dependencies.now()
9317
+ });
9318
+ if (attempt > 0 && (current.send?.id ?? null) !== firstSendId) return {
9319
+ ...current,
9320
+ status: "stale"
9321
+ };
9322
+ if (expectedScope === void 0) {
9323
+ if (current.journey.revision !== input.expectedJourneyRevision) return {
9324
+ ...current,
9325
+ status: "stale"
9326
+ };
9327
+ expectedScope = displayedScopeDigest(current.journey);
9328
+ }
9329
+ if (displayedScopeDigest(current.journey) !== expectedScope) return {
9330
+ ...current,
9331
+ status: "stale"
9332
+ };
9333
+ assertJourneyPrivacyReady(current.journey);
9334
+ if (current.journey.pendingHideId || current.journey.phase === "paused") throw new ApplicationError("SCOPE_NOT_READY");
9335
+ if (current.send && ([
9336
+ "awaiting-packaging",
9337
+ "sending",
9338
+ "waiting",
9339
+ "sign-in",
9340
+ "review"
9341
+ ].includes(current.send.status) || current.send.items.some((item) => item.recoveryReview) || current.send.status === "paused" && current.send.confirmedAt !== null && scopeDigest(current.journey) === current.send.scopeDigest)) throw new ApplicationError("INVALID_TRANSITION");
9342
+ if (!hostId) throw new ApplicationError("INVALID_TRANSITION");
9343
+ const included = current.journey.works.filter(isIncludedWork);
9344
+ if (!sameIds$1(input.included.map((work) => work.workId), included.map((work) => work.id)) || !input.included.every((item) => included.some((work) => work.id === item.workId && work.access === item.access && work.accessConfirmed)) || !sameIds$1(input.omittedWorkIds, current.journey.works.filter((work) => !isIncludedWork(work)).map((work) => work.id))) throw new ApplicationError("CONFIRMATION_REQUIRED");
9345
+ if (!binding) binding = {
9346
+ subject: (await dependencies.auth.connect(new AbortController().signal))?.subject ?? null,
9347
+ at: dependencies.now()
9348
+ };
9349
+ const { subject, at } = binding;
9350
+ const result = await dependencies.storage.commitSend({
9351
+ journeyId: input.journeyId,
9352
+ expectedJourneyRevision: current.journey.revision,
9353
+ expectedSendRevision: null,
9354
+ requestKey: input.idempotencyKey,
9355
+ requestHash: hash$1(input),
9356
+ state: {
9357
+ id: input.idempotencyKey,
9358
+ journeyId: input.journeyId,
9359
+ revision: 0,
9319
9360
  scopeDigest: requestedScope(current.journey),
9320
- included: input.included,
9321
- omittedWorkIds: input.omittedWorkIds
9322
- }
9323
- },
9324
- at
9325
- });
9361
+ subject,
9362
+ confirmedAt: null,
9363
+ status: "awaiting-packaging",
9364
+ items: [],
9365
+ omitted: [],
9366
+ error: null,
9367
+ request: {
9368
+ requestedAt: at,
9369
+ subject,
9370
+ hostId,
9371
+ source,
9372
+ scopeDigest: requestedScope(current.journey),
9373
+ included: input.included,
9374
+ omittedWorkIds: input.omittedWorkIds
9375
+ }
9376
+ },
9377
+ at
9378
+ });
9379
+ if (result.status !== "stale" || attempt === 1) return result;
9380
+ }
9326
9381
  }
9327
9382
  /**
9328
9383
  * Previously sent Works with unchanged access remain part of the displayed authorization. Keep
@@ -9484,7 +9539,7 @@ function createJourneySender(dependencies, phases = 3, host = {
9484
9539
  const snapshot = await dependencies.storage.loadSend(input.journeyId);
9485
9540
  sessionFacts.retain(input.journeyId, snapshot?.send ?? null);
9486
9541
  if (!snapshot) throw new ApplicationError("UNKNOWN_ITEM");
9487
- if (snapshot.journey.revision !== input.expectedJourneyRevision) return {
9542
+ if (input.displayedScopeDigest ? displayedScopeDigest(snapshot.journey) !== input.displayedScopeDigest : snapshot.journey.revision !== input.expectedJourneyRevision) return {
9488
9543
  ...snapshot,
9489
9544
  status: "stale"
9490
9545
  };
@@ -9526,7 +9581,7 @@ function createJourneySender(dependencies, phases = 3, host = {
9526
9581
  await connection.assertCurrent(signal);
9527
9582
  }
9528
9583
  }
9529
- const canReuseExistingSend = !(snapshot.send?.confirmedAt && ["blocked", "paused"].includes(snapshot.send.status)) && !recover && snapshot.send?.scopeDigest === draft.scopeDigest && snapshot.send.subject === draft.subject;
9584
+ const canReuseExistingSend = !(snapshot.send?.confirmedAt && ["blocked", "paused"].includes(snapshot.send.status)) && !recover && snapshot.send && scopeDigest(snapshot.journey) === snapshot.send.scopeDigest && snapshot.send.subject === draft.subject;
9530
9585
  const next = pending ? {
9531
9586
  ...draft,
9532
9587
  id: pending.id,
@@ -9538,7 +9593,7 @@ function createJourneySender(dependencies, phases = 3, host = {
9538
9593
  } : draft;
9539
9594
  const result = await dependencies.storage.commitSend({
9540
9595
  journeyId: input.journeyId,
9541
- expectedJourneyRevision: input.expectedJourneyRevision,
9596
+ expectedJourneyRevision: snapshot.journey.revision,
9542
9597
  expectedSendRevision: pending?.revision ?? (canReuseExistingSend && snapshot.send ? snapshot.send.revision : null),
9543
9598
  requestKey: input.idempotencyKey,
9544
9599
  requestHash: hash$1(input),
@@ -9551,7 +9606,12 @@ function createJourneySender(dependencies, phases = 3, host = {
9551
9606
  async start(raw, signal) {
9552
9607
  const input = sendStartSchema.parse(raw);
9553
9608
  const snapshot = await load(input);
9554
- if (!matchesAction(snapshot, input)) return saveSend(dependencies, snapshot, snapshot.send, input);
9609
+ if (snapshot.send.revision !== input.expectedSendRevision || !input.displayedScopeDigest && snapshot.journey.revision !== input.expectedJourneyRevision) return saveSend(dependencies, snapshot, snapshot.send, input);
9610
+ if (input.displayedScopeDigest && displayedScopeDigest(snapshot.journey) !== input.displayedScopeDigest) return {
9611
+ ...snapshot,
9612
+ status: "stale"
9613
+ };
9614
+ const saveStart = (next) => saveSend(dependencies, snapshot, next, input, snapshot.journey.revision);
9555
9615
  if (pendingElsewhere(snapshot.send)) return {
9556
9616
  ...snapshot,
9557
9617
  status: "applied"
@@ -9560,7 +9620,7 @@ function createJourneySender(dependencies, phases = 3, host = {
9560
9620
  if (snapshot.send.request && !snapshot.send.confirmedAt && (authorizationError || !requestMatches(snapshot.send, snapshot.journey))) return block(snapshot, snapshot.send, authorizationError ?? "REVISION_CONFLICT");
9561
9621
  assertScope(snapshot.journey, snapshot.send);
9562
9622
  if (!sameIds$1(input.confirmedWorkIds, snapshot.send.items.map((item) => item.workId)) || !sameIds$1(input.confirmedOmittedWorkIds, snapshot.send.omitted.map((item) => item.workId)) || input.scopeDigest !== snapshot.send.scopeDigest || snapshot.send.items.length === 0) throw new ApplicationError("CONFIRMATION_REQUIRED");
9563
- if (snapshot.send.confirmedAt !== null) return saveSend(dependencies, snapshot, snapshot.send, input);
9623
+ if (snapshot.send.confirmedAt !== null) return saveStart(snapshot.send);
9564
9624
  const connection = await dependencies.auth.connect(signal);
9565
9625
  if (snapshot.send.request && (connection?.subject ?? null) !== snapshot.send.request.subject) return saveSend(dependencies, snapshot, {
9566
9626
  ...snapshot.send,
@@ -9576,18 +9636,18 @@ function createJourneySender(dependencies, phases = 3, host = {
9576
9636
  if (connection) try {
9577
9637
  profile = await prepareProfile(dependencies, snapshot, connection, signal);
9578
9638
  } catch (error) {
9579
- if (error instanceof ApplicationError && error.code === "REVISION_CONFLICT") return saveSend(dependencies, snapshot, snapshot.send, input);
9639
+ if (error instanceof ApplicationError && error.code === "REVISION_CONFLICT") return saveStart(snapshot.send);
9580
9640
  throw error;
9581
9641
  }
9582
9642
  signal.throwIfAborted();
9583
9643
  const finalAuthorizationError = await requestError(dependencies, snapshot.send, hostId, signal);
9584
9644
  if (finalAuthorizationError) return block(snapshot, snapshot.send, finalAuthorizationError);
9585
- return saveSend(dependencies, snapshot, {
9645
+ return saveStart({
9586
9646
  ...snapshot.send,
9587
9647
  subject: connection?.subject ?? snapshot.send.subject,
9588
9648
  confirmedAt: snapshot.send.request && !connection ? null : dependencies.now(),
9589
9649
  ...profile
9590
- }, input);
9650
+ });
9591
9651
  },
9592
9652
  async respond(raw) {
9593
9653
  const input = sendChoiceSchema.parse(raw);
@@ -1,7 +1,7 @@
1
1
  import { ln as sessionSchema } from "./locate-BWkblijS.mjs";
2
2
  import { t as createZstdFrameCheck$1 } from "./frame-Dj5Zs6UW.mjs";
3
- import "./src-d7n58sbH.mjs";
4
- import { a as isRecord } from "./model-f_QnDyyb.mjs";
3
+ import "./src-DzKuzGVH.mjs";
4
+ import { a as isRecord } from "./model-CSx2dP_P.mjs";
5
5
  import { constants } from "node:fs";
6
6
  import { z } from "zod";
7
7
  import { lstat, open, stat } from "node:fs/promises";
@@ -1,7 +1,7 @@
1
1
  import { Bn as nativeItems, En as walkNativeFields, Nn as parseNativeRecord, Rn as nativeBoolean, Vn as nativeText, Wn as retainedMainTextNodes, Xn as defaultLimits, an as observeSource, on as sourceSnapshotId, ur as ProcessingError, zn as nativeField } from "./locate-BWkblijS.mjs";
2
- import { At as nativeAdapterVersions, nt as reviewInventory, oi as gitMetadataBudgetBytes } from "./src-d7n58sbH.mjs";
3
- import { a as isRecord, i as errorCode, n as checkDiscoveryAbort, o as unresolvedMetadata, r as discoveryBounds, t as DiscoveryWarnings } from "./model-f_QnDyyb.mjs";
4
- import { c as previewLimits, d as checkOpenSource, f as checkSource, h as openSource, i as pageFits, l as previewSourceVersion, m as noSymlinks, p as fileSnapshot, r as previewHeapLimits, s as previewMessageSchema, u as createZstdFrameCheck } from "./run-RA_8zZsL.mjs";
2
+ import { At as nativeAdapterVersions, ci as gitMetadataBudgetBytes, nt as reviewInventory } from "./src-DzKuzGVH.mjs";
3
+ import { a as isRecord, i as errorCode, n as checkDiscoveryAbort, o as unresolvedMetadata, r as discoveryBounds, t as DiscoveryWarnings } from "./model-CSx2dP_P.mjs";
4
+ import { c as previewLimits, d as checkOpenSource, f as checkSource, h as openSource, i as pageFits, l as previewSourceVersion, m as noSymlinks, p as fileSnapshot, r as previewHeapLimits, s as previewMessageSchema, u as createZstdFrameCheck } from "./run-xlOaKCk8.mjs";
5
5
  import { a as titleHintLimits, n as titleHeapLimits, o as titleInputSchema, r as decodeTitleError, s as titleReplySchema } from "./heap-1FYhGds4.mjs";
6
6
  import { constants } from "node:fs";
7
7
  import { lstat, open, opendir, readFile, readdir, realpath, stat } from "node:fs/promises";