@gitroll/tacitt-cli 0.4.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/{agent-setup-Bpsi-BCv.mjs → agent-setup-BZbgLgHg.mjs} +2 -2
  2. package/dist/agent-setup-worker.mjs +5 -5
  3. package/dist/cli.mjs +6 -5
  4. package/dist/codex-title-worker.mjs +1 -1
  5. package/dist/configured-preview-worker.mjs +5 -5
  6. package/dist/configured-session-worker.mjs +5 -5
  7. package/dist/{frame-IeDOLy1o.mjs → frame-DGun31Uc.mjs} +1 -1
  8. package/dist/{heap-DiOlSa8T.mjs → heap-NDnGBXH6.mjs} +3 -3
  9. package/dist/inspection-worker.mjs +4 -4
  10. package/dist/{job-BII94L2c.mjs → job-BO0a67HQ.mjs} +383 -8
  11. package/dist/{locate-CBiw-CJK.mjs → locate-JYtFmKu-.mjs} +115 -3
  12. package/dist/{model-DGTsARtV.mjs → model-CmHypB0p.mjs} +1 -1
  13. package/dist/operation-executor.mjs +3 -3
  14. package/dist/preview-worker.mjs +1 -1
  15. package/dist/privacy-validator.mjs +1 -1
  16. package/dist/{query-CVqWNFYf.mjs → query-BZvNsP1u.mjs} +458 -29
  17. package/dist/{run-BGlf-W0M.mjs → run-DvRM-NR8.mjs} +4 -4
  18. package/dist/{src-CBTvOa44.mjs → src-C1SjCDx0.mjs} +21 -3
  19. package/dist/{src-D4nrfC2S.mjs → src-CQeUBG2Y.mjs} +6 -5
  20. package/dist/{src-37kIclGK.mjs → src-xidy0yF7.mjs} +4 -4
  21. package/dist/store-database-worker.mjs +1 -1
  22. package/dist/web/assets/index-Bbck2aOB.css +1 -0
  23. package/dist/web/assets/{index-D3g_ATU-.js → index-D0j-mvf1.js} +2 -2
  24. package/dist/web/index.html +2 -2
  25. package/package.json +1 -1
  26. package/skills/tacitt/SKILL.md +2 -2
  27. package/skills/tacitt/references/INDEX.md +11 -10
  28. package/skills/tacitt/references/commands.md +13 -0
  29. package/skills/tacitt/references/journey.md +1 -1
  30. package/skills/tacitt/references/remote-workers.md +46 -0
  31. package/skills/tacitt/references/send.md +4 -0
  32. package/skills/tacitt/scripts/privacy-validator.mjs +76 -3
  33. package/dist/web/assets/index-D5DEG5Ue.css +0 -1
@@ -1,16 +1,17 @@
1
- import { $ as createCleanup, B as parallelismLimits, C as readOriginalSearchFields, E as checkReusableBundle, F as SessionWorkerError, G as processJourneyMetadataFields, H as privateJourneyDirectory, I as sessionWorkerFailure, K as staticMaskCategory, L as privateCollectionDirectory, M as readCollectionIndex, N as parseCollectionWorkspaceSummary, 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-D4nrfC2S.mjs";
2
- import { Bt as sessionPeriodSchema, Dn as entityDictionaryVersion, F as bClassificationKey, Fn as frameRecords, Ft as termTypeInfo, Gt as safeField, H as codePointLength, Ht as ApplicationError, Jt as reviewFamilies, K as utf16Offset, N as bUnitFragments, Ot as privacyTermKey, Qn as admitGitName, T as bLiteralTerms, Ut as UnfinishedJourneyError, V as bDigest, Wt as safeCode, Xn as createEntityMatcher, Zn as admitCustomTerm, Zt as observeSource, b as validateBReview, c as textDigest, h as reviewFindingsDigest, ht as journeyDescribeSchema, jt as reviewTermsInputSchema, l as validateReview, mn as currentDetectorVersion, n as compileBFindings, r as reviewBatchChunks, s as reviewSubmitSchema, t as locateTerms, yn as createStaticProcessor, z as bAnchorKey } from "./locate-CBiw-CJK.mjs";
3
- 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-37kIclGK.mjs";
4
- import { $ as settingsQuerySchema, $r as packageCommandSchema, A as deviceProfileScopeSchema, B as validateInspectionBatch, Bn as journeyConfirmedHides, Br as hasCompleteWorkDescription, Bt as newJourneyWork, C as rebindReviewSubmit, Cr as privacyDecisionDigest, Ct as sendStartSchema, D as createAccount, Dr as hasCurrentStaticReview, E as staticallyHiddenFindings, Er as nativeRespondSchema, Et as obsoleteJourney, Fn as confirmedHideGroupIds, Fr as sendArtifactSchema, Gr as withReadingProgress, Hr as isReadingComplete, Ht as journeyContextQuerySchema, Ir as sendReceiptSchema, Jn as reviewCandidateResourceSchema, Jr as journeyFindingsSchema, Kn as workCorrectionBinding, L as createApplication, Ln as confirmedHideKinds, Lr as sendReplaceResultSchema, Lt as classificationPartition, M as readAccountAvatarUrl, Mr as agentSourceSchema, Mt as applyClassification, N as storedCredentialSchema, Nn as bTermMatcher, Nr as agentSourcesSchema, O as accountProfileSchema, Or as staticReviewDigest, Pr as journeySendSchema, Pt as journeyReviewStorageQuerySchema, Q as settingsBatchSchema, Qn as bReviewDigest, Qr as commandSchema, Qt as journeyResourceQuerySchema, R as inspectionCancelSchema, Rr as sendResolutionSchema, Rt as classificationWorks, S as rebindReviewOverlay, Sn as readConfirmedHideChange, Sr as assertJourneyPrivacyReady, St as sendPrepareSchema, T as guardedFindingText, Tn as termHideAdditions, Tr as nativeGetSchema, Tt as currentJourneyAdapters, U as inspectionQuerySchema, Un as retireWorkDescription, Ur as isSelectedWork, Vn as maskedHitsStale, Vr as isClassifying, Vt as reviewCompileSchema, Wn as workDecisionDigest, Xn as reviewRepairResourceSchema, Xr as journeyRenderInputSchema, Xt as journeyPolicyRespondSchema, Yn as reviewRepairInputSchema, Yr as journeyPreviewSchema, Yt as searchScopeDigest, Zr as journeyRenderSchema, _t as maximumTermsFileBytes, a as bCrossSegmentReviewSchema, ar as scanGitSeedsId, b as bReviewScope, bn as confirmedHideAdditions, br as journeyClassificationSessionsSchema, bt as sendActionSchema, c as reconstructBFields, cr as scanExclusionResourceSchema, ct as validateFailureLocation, d as selectedValueMembers, dn as sessionReviewInputSchema, dr as journeyInventoryQuerySchema, dt as manualUploadChoiceSchema, ei as selectionBatchSchema, er as planBRepair, et as readWorkspaceOutcomes, f as splitSelectorValues, fn as sessionReviewQuerySchema, ft as manualUploadPrepareSchema, g as changeJourney, gt as emptyTermsRevision, hn as sessionUsefulnessInputSchema, hr as emptyPreparationFacts, i as validateBCrossSegmentReview, ii as stateSchema, ir as scanSessionResourceSchema, j as profileUrlMatchesIdentity, k as deviceAuthorizationSchema, ln as sessionRereadInputSchema, lt as manualUploadActionSchema, m as hideScopeDigest, mt as manualUploadStartSchema, n as scanBatchEquivalenceDigest, nt as appendSensitiveTerms, o as bRereadDigest, oi as recommendParallelism, on as sessionReconcileInputSchema, or as scanGitSeedsResource, ot as artifactFailureDetailSchema, p as activeJourneyTerms, pt as manualUploadSchema, qn as reviewCandidateInputSchema, qr as journeyFindingImpactSchema, qt as journeySearchResultSchema, r as locateTermEvidence, ri as producerVersion, rn as reviewAttemptResourceSchema, rr as scanPreparationDigest, s as reconcileBSession, sr as verifiedScanGitSeeds, st as resolveFailureLocation, t as scanBatchContextDigest, ti as selectionSchema, tn as journeyPlaceSchema, vt as normalizeSensitiveTerms, w as reviewBatchReuse, wr as nativeEventsSchema, x as rebindReviewAlignment, xt as sendChoiceSchema, y as isGenericPublicTerm, yt as replaceSensitiveTermsSchema, z as inspectionStartSchema, zr as sendSettingsSchema, zt as retireScanGeneration } from "./src-CBTvOa44.mjs";
5
- import { $ as checkVersion, A as resourceSelectionQuerySchema, B as termReuseQuerySchema, C as loadAcceptedReview, D as aggregateUsefulness, E as loadPrivateResource, F as validateUnitCandidate, G as requireActiveBatch, H as batchHeader, I as reuseQuerySchema, J as validateDatabase, K as initializeAndClaim, L as batchQuery, M as evaluateUnitEvidence, N as sameCandidateRequest, O as sessionUsefulnessRecommendation, P as validateCandidateAttempt, Q as validateState, R as isPrivateResourceKind, S as validateSessionBindings, T as loadBatch, U as createJourneyPayloadFiles, V as privateReviewHash, W as validateBatchBody, X as readBundleDirectory, Y as withDatabase, Z as readStoredState, _ as loadReconciliation, _t as isCoordinationBusy, a as decodeError, at as hasResetMarker, b as validatePreparationSelection, c as dropsAnchor, ct as privatePath, d as parseDelivery, dt as stateDirectory, et as schemaVersion, f as validateCandidate, ft as syncDirectory, g as loadPreparedBodies, gt as errorCode$1, h as loadPreparation, ht as StoreError, i as createExecutor, it as finishReset, j as inspectionQuerySchema$1, k as sessionQuery, l as replySchema, lt as readResetMarker, m as loadStatus, mt as withFileCheckTimings, n as releaseInheritedHeapFlags, nt as createDatabaseFile, o as ProtocolError, ot as inspectStateFiles, p as classificationJourneyCommit, pt as withStateSnapshot, q as ownership, r as storeHeapLimits, rt as databaseName, s as allowedReplies, st as present, tt as beginReset, u as operations, ut as recheckPrivatePath, v as loadRereadBodies, vt as isSqliteCorruption, w as loadAuthenticatedReview, x as validateSessionReconciliation, y as loadSessionBodies, z as privateResourceHeader } from "./heap-DiOlSa8T.mjs";
6
- import { _ as staticBaseProduction, a as writeJourneyOutput, 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 prepareSourcePlan, y as workApproval } from "./job-BII94L2c.mjs";
7
- import { t as createAgentSetupPort } from "./agent-setup-Bpsi-BCv.mjs";
1
+ import { $ as createCleanup, B as parallelismLimits, C as readOriginalSearchFields, E as checkReusableBundle, F as SessionWorkerError, G as processJourneyMetadataFields, H as privateJourneyDirectory, I as sessionWorkerFailure, K as staticMaskCategory, L as privateCollectionDirectory, M as readCollectionIndex, N as parseCollectionWorkspaceSummary, 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-CQeUBG2Y.mjs";
2
+ import { $t as safeField, Bt as sessionPeriodSchema, Dn as createStaticProcessor, F as bClassificationKey, Fn as entityDictionaryVersion, Ft as termTypeInfo, Gt as ownerProfileSchema, H as codePointLength, Ht as journeyProfileAddressActionSchema, K as utf16Offset, Kt as passportAddressSchema, N as bUnitFragments, Ot as privacyTermKey, Qt as safeCode, Sn as currentDetectorVersion, T as bLiteralTerms, Un as frameRecords, Ut as journeyProfileLinksActionSchema, V as bDigest, Wt as mergeOwnerProfile, Xt as ApplicationError, Zt as UnfinishedJourneyError, an as observeSource, ar as admitCustomTerm, b as validateBReview, c as textDigest, h as reviewFindingsDigest, ht as journeyDescribeSchema, ir as createEntityMatcher, jt as reviewTermsInputSchema, l as validateReview, n as compileBFindings, nn as reviewFamilies, or as admitGitName, qt as profileHasChoices, r as reviewBatchChunks, s as reviewSubmitSchema, t as locateTerms, tn as familySelected, z as bAnchorKey, zt as filterInventoryByPeriod } from "./locate-JYtFmKu-.mjs";
3
+ 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-xidy0yF7.mjs";
4
+ import { $ as settingsQuerySchema, $r as packageCommandSchema, A as deviceProfileScopeSchema, B as validateInspectionBatch, Bn as journeyConfirmedHides, Br as hasCompleteWorkDescription, Bt as newJourneyWork, C as rebindReviewSubmit, Cr as privacyDecisionDigest, Ct as sendStartSchema, D as createAccount, Dr as hasCurrentStaticReview, E as staticallyHiddenFindings, Er as nativeRespondSchema, Et as obsoleteJourney, Fn as confirmedHideGroupIds, Fr as sendArtifactSchema, Gr as withReadingProgress, Hr as isReadingComplete, Ht as journeyContextQuerySchema, Ir as sendReceiptSchema, Jn as reviewCandidateResourceSchema, Jr as journeyFindingsSchema, Kn as workCorrectionBinding, L as createApplication, Ln as confirmedHideKinds, Lr as sendReplaceResultSchema, Lt as classificationPartition, M as readAccountAvatarUrl, Mr as agentSourceSchema, Mt as applyClassification, N as storedCredentialSchema, Nn as bTermMatcher, Nr as agentSourcesSchema, O as accountProfileSchema, Or as staticReviewDigest, Pr as journeySendSchema, Pt as journeyReviewStorageQuerySchema, Q as settingsBatchSchema, Qn as bReviewDigest, Qr as commandSchema, Qt as journeyResourceQuerySchema, R as inspectionCancelSchema, Rr as sendResolutionSchema, Rt as classificationWorks, S as rebindReviewOverlay, Sn as readConfirmedHideChange, Sr as assertJourneyPrivacyReady, St as sendPrepareSchema, T as guardedFindingText, Tn as termHideAdditions, Tr as nativeGetSchema, Tt as currentJourneyAdapters, U as inspectionQuerySchema, Un as retireWorkDescription, Ur as isSelectedWork, Vn as maskedHitsStale, Vr as isClassifying, Vt as reviewCompileSchema, Wn as workDecisionDigest, Xn as reviewRepairResourceSchema, Xr as journeyRenderInputSchema, Xt as journeyPolicyRespondSchema, Yn as reviewRepairInputSchema, Yr as journeyPreviewSchema, Yt as searchScopeDigest, Zr as journeyRenderSchema, _t as maximumTermsFileBytes, a as bCrossSegmentReviewSchema, ar as scanGitSeedsId, b as bReviewScope, bn as confirmedHideAdditions, br as journeyClassificationSessionsSchema, bt as sendActionSchema, c as reconstructBFields, cr as scanExclusionResourceSchema, ct as validateFailureLocation, d as selectedValueMembers, dn as sessionReviewInputSchema, dr as journeyInventoryQuerySchema, dt as manualUploadChoiceSchema, ei as selectionBatchSchema, er as planBRepair, et as readWorkspaceOutcomes, f as splitSelectorValues, fn as sessionReviewQuerySchema, ft as manualUploadPrepareSchema, g as changeJourney, gt as emptyTermsRevision, hn as sessionUsefulnessInputSchema, hr as emptyPreparationFacts, i as validateBCrossSegmentReview, ii as stateSchema, ir as scanSessionResourceSchema, j as profileUrlMatchesIdentity, k as deviceAuthorizationSchema, ln as sessionRereadInputSchema, lt as manualUploadActionSchema, m as hideScopeDigest, mt as manualUploadStartSchema, n as scanBatchEquivalenceDigest, nt as appendSensitiveTerms, o as bRereadDigest, oi as recommendParallelism, on as sessionReconcileInputSchema, or as scanGitSeedsResource, ot as artifactFailureDetailSchema, p as activeJourneyTerms, pt as manualUploadSchema, qn as reviewCandidateInputSchema, qr as journeyFindingImpactSchema, qt as journeySearchResultSchema, r as locateTermEvidence, ri as producerVersion, rn as reviewAttemptResourceSchema, rr as scanPreparationDigest, s as reconcileBSession, sr as verifiedScanGitSeeds, st as resolveFailureLocation, t as scanBatchContextDigest, ti as selectionSchema, tn as journeyPlaceSchema, vt as normalizeSensitiveTerms, w as reviewBatchReuse, wr as nativeEventsSchema, x as rebindReviewAlignment, xt as sendChoiceSchema, y as isGenericPublicTerm, yt as replaceSensitiveTermsSchema, z as inspectionStartSchema, zr as sendSettingsSchema, zt as retireScanGeneration } from "./src-C1SjCDx0.mjs";
5
+ import { $ as checkVersion, A as resourceSelectionQuerySchema, B as termReuseQuerySchema, C as loadAcceptedReview, D as aggregateUsefulness, E as loadPrivateResource, F as validateUnitCandidate, G as requireActiveBatch, H as batchHeader, I as reuseQuerySchema, J as validateDatabase, K as initializeAndClaim, L as batchQuery, M as evaluateUnitEvidence, N as sameCandidateRequest, O as sessionUsefulnessRecommendation, P as validateCandidateAttempt, Q as validateState, R as isPrivateResourceKind, S as validateSessionBindings, T as loadBatch, U as createJourneyPayloadFiles, V as privateReviewHash, W as validateBatchBody, X as readBundleDirectory, Y as withDatabase, Z as readStoredState, _ as loadReconciliation, _t as isCoordinationBusy, a as decodeError, at as hasResetMarker, b as validatePreparationSelection, c as dropsAnchor, ct as privatePath, d as parseDelivery, dt as stateDirectory, et as schemaVersion, f as validateCandidate, ft as syncDirectory, g as loadPreparedBodies, gt as errorCode$1, h as loadPreparation, ht as StoreError, i as createExecutor, it as finishReset, j as inspectionQuerySchema$1, k as sessionQuery, l as replySchema, lt as readResetMarker, m as loadStatus, mt as withFileCheckTimings, n as releaseInheritedHeapFlags, nt as createDatabaseFile, o as ProtocolError, ot as inspectStateFiles, p as classificationJourneyCommit, pt as withStateSnapshot, q as ownership, r as storeHeapLimits, rt as databaseName, s as allowedReplies, st as present, tt as beginReset, u as operations, ut as recheckPrivatePath, v as loadRereadBodies, vt as isSqliteCorruption, w as loadAuthenticatedReview, x as validateSessionReconciliation, y as loadSessionBodies, z as privateResourceHeader } from "./heap-NDnGBXH6.mjs";
6
+ import { C as journeyDirectory, S as saveRemoteState, _ as staticBaseProduction, a as writeJourneyOutput, b as isRemoteImport, 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 prepareSourcePlan, w as collectRemoteWorkers, x as readRemoteState, y as workApproval } from "./job-BO0a67HQ.mjs";
7
+ import { t as createAgentSetupPort } from "./agent-setup-BZbgLgHg.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";
11
11
  import { copyFile, link, lstat, mkdir, mkdtemp, open, opendir, readFile, readdir, realpath, rename, rm, unlink, writeFile } from "node:fs/promises";
12
12
  import { execFile, spawn } from "node:child_process";
13
- import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
13
+ import { basename, dirname, isAbsolute, join, posix, relative, resolve, sep } from "node:path";
14
+ import { createInterface } from "node:readline";
14
15
  import { Writable } from "node:stream";
15
16
  import { parseArgs, promisify, types } from "node:util";
16
17
  import { createHash, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
@@ -27,6 +28,7 @@ import { pipeline } from "node:stream/promises";
27
28
  import { AsyncLocalStorage } from "node:async_hooks";
28
29
  import { DatabaseSync } from "node:sqlite";
29
30
  import { Worker } from "node:worker_threads";
31
+ import { parse } from "shell-quote";
30
32
  import { rgPath } from "@vscode/ripgrep";
31
33
  import { pino } from "pino";
32
34
  import { SeverityNumber } from "@opentelemetry/api-logs";
@@ -858,7 +860,9 @@ const nativePanelRespondSchema = z.object({
858
860
  z.object({
859
861
  kind: z.literal("retry-work"),
860
862
  workId: z.uuid()
861
- }).strict()
863
+ }).strict(),
864
+ journeyProfileAddressActionSchema,
865
+ journeyProfileLinksActionSchema
862
866
  ])
863
867
  }).strict();
864
868
  function createRouter(application, account, stopping, delivery, nativeInspection, agentPresence) {
@@ -932,7 +936,10 @@ function createRouter(application, account, stopping, delivery, nativeInspection
932
936
  pause: t.procedure.input(sendActionSchema).mutation(({ input }) => sending().pause(input)),
933
937
  resume: t.procedure.input(sendActionSchema).mutation(({ input }) => sending().resume(input)),
934
938
  withdraw: t.procedure.input(sendActionSchema).mutation(({ input }) => sending().withdraw(input)),
935
- advance: t.procedure.input(sendAddress).mutation(({ input }) => sending().advance(input, stopping))
939
+ advance: t.procedure.input(sendAddress).mutation(({ input }) => sending().advance(input, stopping)),
940
+ ownerProfile: t.procedure.query(({ signal }) => sending().ownerProfile(signal ?? stopping)),
941
+ addressTaken: t.procedure.input(z.object({ address: passportAddressSchema }).strict()).query(({ input, signal }) => sending().addressTaken(input, signal ?? stopping)),
942
+ saveSentProfile: t.procedure.input(z.object({ journeyId: z.uuid() }).strict()).mutation(({ input }) => sending().saveSentProfile(input, stopping))
936
943
  }),
937
944
  manualUpload: t.router({
938
945
  get: t.procedure.input(z.object({ uploadId: z.uuid().optional() }).strict()).query(({ input }) => uploading().get(input.uploadId)),
@@ -5345,6 +5352,7 @@ const businessCommands = [
5345
5352
  "send.resume",
5346
5353
  "send.advance",
5347
5354
  "journey.start",
5355
+ "journey.remoteWorkers",
5348
5356
  "journey.serve",
5349
5357
  "journey.get",
5350
5358
  "journey.groupItems",
@@ -5634,6 +5642,334 @@ function helpText(source = sourceCheckout) {
5634
5642
  return source ? fullHelp : fullHelp.replace(/^ {2}--dev .*\n/m, "");
5635
5643
  }
5636
5644
  //#endregion
5645
+ //#region apps/cli/src/remote/dispatch.ts
5646
+ function balancedQuotes(command) {
5647
+ let quote = "";
5648
+ let escaped = false;
5649
+ for (const character of command) {
5650
+ if (escaped) {
5651
+ escaped = false;
5652
+ continue;
5653
+ }
5654
+ if (character === "\\" && quote !== "'") escaped = true;
5655
+ else if (quote === character) quote = "";
5656
+ else if (!quote && (character === "'" || character === "\"")) quote = character;
5657
+ }
5658
+ return !quote && !escaped;
5659
+ }
5660
+ /** Parse inert simple commands. Expansions and unsupported compound syntax fail closed. */
5661
+ function commands$1(command) {
5662
+ if (Buffer.byteLength(command) > 65536 || /`|\$\(|[\0\r]/u.test(command) || !balancedQuotes(command)) return [];
5663
+ try {
5664
+ const segments = [[]];
5665
+ let redirect = false;
5666
+ for (const token of parse(command.replaceAll("\n", ";"), () => "\0")) if (typeof token === "string") {
5667
+ if (token.includes("\0")) return [];
5668
+ if (redirect) redirect = false;
5669
+ else segments.at(-1)?.push(token);
5670
+ } else if ("comment" in token) continue;
5671
+ else if ("op" in token && [
5672
+ ">",
5673
+ ">>",
5674
+ "<",
5675
+ ">&",
5676
+ "<&"
5677
+ ].includes(token.op)) {
5678
+ if (redirect) return [];
5679
+ redirect = true;
5680
+ } else if ("op" in token && [
5681
+ ";",
5682
+ "&&",
5683
+ "||",
5684
+ "|",
5685
+ "&"
5686
+ ].includes(token.op)) segments.push([]);
5687
+ else return [];
5688
+ return redirect ? [] : segments.filter((words) => words.length > 0);
5689
+ } catch {
5690
+ return [];
5691
+ }
5692
+ }
5693
+ function agent(words) {
5694
+ const executable = posix.basename(words[0] ?? "");
5695
+ if (words.some((word) => [
5696
+ "--help",
5697
+ "-h",
5698
+ "--version"
5699
+ ].includes(word))) return null;
5700
+ if (executable === "codex" && words[1] === "exec") return "codex";
5701
+ if (executable === "claude" && words.slice(1).some((word) => word === "-p" || word === "--print")) return "claude";
5702
+ return null;
5703
+ }
5704
+ const validHost = (host) => /^(?:[a-zA-Z0-9_][a-zA-Z0-9_.-]*@)?(?:[a-zA-Z0-9_][a-zA-Z0-9_.-]*|\[[a-fA-F0-9:]+\])$/u.test(host);
5705
+ /** Consent and import identity include every retained connection selector. */
5706
+ function endpoint(host, transport, args) {
5707
+ return transport === "ssh" && args.length === 1 ? host : `${host} (${transport}: ${args.join(" ")})`;
5708
+ }
5709
+ function ssh(words) {
5710
+ const args = [];
5711
+ let index = 1;
5712
+ for (; index < words.length; index++) {
5713
+ const word = words[index] ?? "";
5714
+ if (word === "--") {
5715
+ index++;
5716
+ break;
5717
+ }
5718
+ if (!word.startsWith("-")) break;
5719
+ if (word === "--help" || /^-[^-]*[NVGQOW]/u.test(word)) return null;
5720
+ if (/^-[pLlIiFJoObcDEeRSwWQ]/u.test(word)) {
5721
+ const flag = word.slice(0, 2);
5722
+ const value = word.length > 2 ? word.slice(2) : words[++index];
5723
+ if (!value) return null;
5724
+ if (flag === "-p" && /^\d{1,5}$/u.test(value)) args.push(flag, value);
5725
+ if (flag === "-l" && /^[a-zA-Z0-9_.-]+$/u.test(value)) args.push(flag, value);
5726
+ } else if (!/^-[46AaCfKkMnqsTtVvXxYy]+$/u.test(word)) return null;
5727
+ }
5728
+ const host = words[index];
5729
+ if (!host || !validHost(host) || index + 1 >= words.length) return null;
5730
+ return {
5731
+ host,
5732
+ transport: "ssh",
5733
+ args: [...args, host],
5734
+ command: words.slice(index + 1).join(" ")
5735
+ };
5736
+ }
5737
+ function gcloud(words) {
5738
+ if (words[1] !== "compute" || words[2] !== "ssh") return null;
5739
+ let host;
5740
+ let command;
5741
+ const selectors = [];
5742
+ for (let index = 3; index < words.length; index++) {
5743
+ const word = words[index] ?? "";
5744
+ if (word === "--help" || word === "-h" || word === "--dry-run") return null;
5745
+ if (word === "--command" || word.startsWith("--command=")) command = word === "--command" ? words[++index] : word.slice(10);
5746
+ else if (["--zone", "--project"].some((flag) => word === flag || word.startsWith(`${flag}=`))) {
5747
+ const separator = word.indexOf("=");
5748
+ const flag = separator === -1 ? word : word.slice(0, separator);
5749
+ const value = separator === -1 ? words[++index] : word.slice(separator + 1);
5750
+ if (!value || !/^[a-zA-Z0-9_.:-]+$/u.test(value)) return null;
5751
+ selectors.push(`${flag}=${value}`);
5752
+ } else if (word === "--tunnel-through-iap" || word === "--internal-ip") selectors.push(word);
5753
+ else if (word === "--quiet" || word === "-q") continue;
5754
+ else if (!word.startsWith("-") && !host) host = word;
5755
+ else return null;
5756
+ }
5757
+ if (!host || !validHost(host) || !command) return null;
5758
+ return {
5759
+ host,
5760
+ transport: "gcloud",
5761
+ args: [host, ...selectors],
5762
+ command
5763
+ };
5764
+ }
5765
+ /** Matches executables at shell command positions, never mentions in prose or other commands. */
5766
+ function parseRemoteDispatch(command) {
5767
+ return commands$1(command).flatMap((words) => {
5768
+ const executable = posix.basename(words[0] ?? "");
5769
+ const remote = executable === "ssh" ? ssh(words) : executable === "gcloud" ? gcloud(words) : null;
5770
+ if (!remote) return [];
5771
+ return [...new Set(commands$1(remote.command).map(agent))].flatMap((harness) => harness ? [{
5772
+ host: endpoint(remote.host, remote.transport, remote.args),
5773
+ harness,
5774
+ transport: remote.transport,
5775
+ args: remote.args
5776
+ }] : []);
5777
+ });
5778
+ }
5779
+ //#endregion
5780
+ //#region apps/cli/src/remote/scan.ts
5781
+ function object(value) {
5782
+ return typeof value === "object" && value !== null && !Array.isArray(value);
5783
+ }
5784
+ function timestamp(value) {
5785
+ return typeof value === "string" && Number.isFinite(Date.parse(value)) ? new Date(value).toISOString() : null;
5786
+ }
5787
+ function commands(row) {
5788
+ const payload = row["payload"];
5789
+ if (row["type"] === "response_item" && object(payload) && payload["type"] === "function_call" && typeof payload["name"] === "string" && [
5790
+ "exec_command",
5791
+ "shell_command",
5792
+ "shell"
5793
+ ].includes(payload["name"])) {
5794
+ let args = payload["arguments"];
5795
+ if (typeof args === "string") try {
5796
+ args = JSON.parse(args);
5797
+ } catch {
5798
+ return [];
5799
+ }
5800
+ if (!object(args)) return [];
5801
+ const command = args["cmd"] ?? args["command"];
5802
+ return typeof command === "string" ? [{
5803
+ id: typeof payload["call_id"] === "string" ? payload["call_id"] : "",
5804
+ command
5805
+ }] : [];
5806
+ }
5807
+ const message = row["message"];
5808
+ if (row["type"] !== "assistant" || !object(message) || !Array.isArray(message["content"])) return [];
5809
+ return message["content"].flatMap((block) => {
5810
+ if (!object(block) || block["type"] !== "tool_use" || block["name"] !== "Bash" || !object(block["input"]) || typeof block["input"]["command"] !== "string") return [];
5811
+ return [{
5812
+ id: typeof block["id"] === "string" ? block["id"] : "",
5813
+ command: block["input"]["command"]
5814
+ }];
5815
+ });
5816
+ }
5817
+ function resultIds(row) {
5818
+ const payload = row["payload"];
5819
+ if (object(payload) && payload["type"] === "function_call_output" && typeof payload["call_id"] === "string") return [payload["call_id"]];
5820
+ const message = row["message"];
5821
+ if (!object(message) || !Array.isArray(message["content"])) return [];
5822
+ return message["content"].flatMap((block) => object(block) && block["type"] === "tool_result" && typeof block["tool_use_id"] === "string" ? [block["tool_use_id"]] : []);
5823
+ }
5824
+ /** Tool executable positions only. Source bytes stay inside this deterministic CLI scanner. */
5825
+ async function scanRemoteDispatches(sessions, signal) {
5826
+ const windows = [];
5827
+ for (const session of sessions) {
5828
+ const pending = /* @__PURE__ */ new Map();
5829
+ for (const part of session.parts) {
5830
+ signal.throwIfAborted();
5831
+ if (part.representation !== "jsonl") throw new Error("REMOTE_SOURCE_FORMAT_UNSUPPORTED");
5832
+ const file = await open(part.path, constants.O_RDONLY | constants.O_NOFOLLOW);
5833
+ try {
5834
+ const before = await file.stat({ bigint: true });
5835
+ if (String(before.dev) !== part.snapshot.dev || String(before.ino) !== part.snapshot.ino || before.size !== BigInt(part.snapshot.size) || String(before.mtimeNs) !== part.snapshot.mtimeNs || String(before.ctimeNs) !== part.snapshot.ctimeNs) throw new Error("REMOTE_SOURCE_CHANGED");
5836
+ if (!part.snapshot.size) continue;
5837
+ const stream = file.createReadStream({
5838
+ autoClose: false,
5839
+ start: 0,
5840
+ end: part.snapshot.size - 1,
5841
+ signal
5842
+ });
5843
+ const lines = createInterface({
5844
+ input: stream,
5845
+ crlfDelay: Infinity
5846
+ });
5847
+ try {
5848
+ for await (const line of lines) {
5849
+ signal.throwIfAborted();
5850
+ if (line.length > 16777216) throw new Error("REMOTE_SOURCE_RECORD_TOO_LARGE");
5851
+ if (!line.trim()) continue;
5852
+ const row = JSON.parse(line);
5853
+ if (!object(row)) continue;
5854
+ const at = timestamp(row["timestamp"]);
5855
+ if (!at) continue;
5856
+ for (const id of resultIds(row)) {
5857
+ for (const window of pending.get(id) ?? []) if (at >= window.start) window.end = at;
5858
+ pending.delete(id);
5859
+ }
5860
+ for (const command of commands(row)) {
5861
+ const end = timestamp(session.lastInteractionAt);
5862
+ const found = parseRemoteDispatch(command.command).map((dispatch) => ({
5863
+ ...dispatch,
5864
+ sourceSessionId: session.id,
5865
+ start: at,
5866
+ end: end && end >= at ? end : at
5867
+ }));
5868
+ windows.push(...found);
5869
+ pending.set(command.id, found);
5870
+ }
5871
+ }
5872
+ const after = await file.stat({ bigint: true });
5873
+ if (after.mtimeNs !== before.mtimeNs || after.size !== before.size) throw new Error("REMOTE_SOURCE_CHANGED");
5874
+ } finally {
5875
+ lines.close();
5876
+ stream.destroy();
5877
+ }
5878
+ } finally {
5879
+ await file.close();
5880
+ }
5881
+ }
5882
+ }
5883
+ return windows;
5884
+ }
5885
+ //#endregion
5886
+ //#region apps/cli/src/remote/preflight.ts
5887
+ const inputSchema = z.object({
5888
+ journeyId: z.uuid(),
5889
+ confirmations: z.record(z.string(), z.boolean()).optional()
5890
+ }).strict();
5891
+ function createRemotePreflight(options) {
5892
+ return async (value, signal = new AbortController().signal) => {
5893
+ const input = inputSchema.parse(value);
5894
+ const current = await options.storage.current(input.journeyId);
5895
+ if (!current?.consent) throw new ApplicationError("CONFIRMATION_REQUIRED");
5896
+ if (current.phase === "paused") throw new ApplicationError("OPERATION_CANCELED");
5897
+ if (current.snapshotId) return {
5898
+ hosts: [],
5899
+ copied: 0,
5900
+ failures: [],
5901
+ skipped: "already-frozen"
5902
+ };
5903
+ const lease = await options.execution.tryAcquire("workflow");
5904
+ if (!lease) throw new ApplicationError("DISCOVERY_BUSY");
5905
+ try {
5906
+ const admitted = await options.storage.current(input.journeyId);
5907
+ if (!admitted?.consent || admitted.phase === "paused") throw new ApplicationError("OPERATION_CANCELED");
5908
+ if (admitted.snapshotId) return {
5909
+ hosts: [],
5910
+ copied: 0,
5911
+ failures: [],
5912
+ skipped: "already-frozen"
5913
+ };
5914
+ let state = await readRemoteState(options.stateDir, input.journeyId);
5915
+ if (!state) {
5916
+ const discovered = await options.harnesses.discover(signal);
5917
+ if (!discovered.complete) throw new ApplicationError("SCOPE_NOT_READY");
5918
+ const inventory = filterInventoryByPeriod(discovered, current.period ?? {});
5919
+ const families = reviewFamilies(inventory);
5920
+ const sessions = inventory.sessions.filter((session) => familySelected(inventory, families, session) && !session.warnings.includes("NON_INTERACTIVE_LAUNCH") && session.parts.every((part) => !isRemoteImport(part.path)));
5921
+ state = {
5922
+ windows: [],
5923
+ decisions: {},
5924
+ parents: Object.fromEntries(sessions.map((session) => [session.id, session.sourceKey])),
5925
+ copied: [],
5926
+ failures: []
5927
+ };
5928
+ for (const session of sessions) try {
5929
+ state.windows.push(...await scanRemoteDispatches([session], signal));
5930
+ } catch (error) {
5931
+ signal.throwIfAborted();
5932
+ options.reportFailure(error);
5933
+ state.failures.push("source-scan");
5934
+ }
5935
+ await saveRemoteState(options.stateDir, input.journeyId, state);
5936
+ }
5937
+ const decisions = input.confirmations ?? {};
5938
+ const known = new Set(state.windows.map((window) => window.host));
5939
+ if (Object.keys(decisions).some((host) => !known.has(host))) throw new ApplicationError("INVALID_ARGUMENTS");
5940
+ const fresh = {};
5941
+ for (const [host, allow] of Object.entries(decisions)) {
5942
+ if (Object.hasOwn(state.decisions, host)) continue;
5943
+ fresh[host] = allow;
5944
+ state.decisions[host] = allow;
5945
+ }
5946
+ await saveRemoteState(options.stateDir, input.journeyId, state);
5947
+ if (Object.keys(fresh).length) {
5948
+ const collected = await collectRemoteWorkers(state.windows, fresh, options.home, options.transport, (_host, error) => options.reportFailure(new Error("REMOTE_COLLECTION_FAILED", { cause: error })), options.roots);
5949
+ state.copied.push(...collected.copied);
5950
+ state.failures.push(...collected.failures);
5951
+ await saveRemoteState(options.stateDir, input.journeyId, state);
5952
+ }
5953
+ return result(state);
5954
+ } finally {
5955
+ await lease.release();
5956
+ }
5957
+ };
5958
+ }
5959
+ function result(state) {
5960
+ return {
5961
+ hosts: [...new Set(state.windows.map((window) => window.host))].filter((host) => !Object.hasOwn(state.decisions, host)).map((host) => ({
5962
+ host,
5963
+ windows: state.windows.filter((window) => window.host === host).map(({ start, end }) => ({
5964
+ start,
5965
+ end
5966
+ }))
5967
+ })),
5968
+ copied: state.copied.length,
5969
+ failures: state.failures
5970
+ };
5971
+ }
5972
+ //#endregion
5637
5973
  //#region apps/cli/src/journey/confirmed-hides.ts
5638
5974
  /** The Work's explicit exception values; an occurrence inside one stays visible (ADR 0069). */
5639
5975
  const workExceptions = (state, workId) => state.exceptions.filter((item) => item.workId === workId).map((item) => item.value);
@@ -7193,22 +7529,6 @@ async function prepareStaticWork(options) {
7193
7529
  });
7194
7530
  }
7195
7531
  //#endregion
7196
- //#region apps/cli/src/journey/directory.ts
7197
- async function journeyDirectory(stateDir, journeyId) {
7198
- let path = stateDir;
7199
- for (const name of ["journeys", journeyId]) {
7200
- path = join(path, name);
7201
- try {
7202
- await makePrivateDirectory(path);
7203
- } catch (cause) {
7204
- if (!(cause instanceof Error && "code" in cause && cause.code === "EEXIST")) throw cause;
7205
- }
7206
- const stat = await lstat(path, { bigint: true });
7207
- if (!stat.isDirectory() || stat.isSymbolicLink() || await realpath(path) !== path || (process.platform === "win32" ? !await windowsOwnerOnly(path, "directory") : stat.uid !== BigInt(process.getuid?.() ?? -1) || (stat.mode & 63n) !== 0n)) throw new ApplicationError("UNSAFE_STATE_PATH");
7208
- }
7209
- return path;
7210
- }
7211
- //#endregion
7212
7532
  //#region apps/cli/src/journey/observe.ts
7213
7533
  /** Observe whole-journey pause while a single large Work is still being processed. */
7214
7534
  function observeJourneyPause(storage, journeyId, processing, onFailure, requireConfirmedScope = false) {
@@ -7396,7 +7716,7 @@ function createJourneyPreparation(options) {
7396
7716
  revision: "empty",
7397
7717
  terms: []
7398
7718
  };
7399
- const plan = await prepareSourcePlan(storage, options.harnesses, journeyId, terms, abort.signal, current.period);
7719
+ const plan = await prepareSourcePlan(storage, options.harnesses, journeyId, terms, abort.signal, current.period, options.stateDir);
7400
7720
  const initial = await storage.current(journeyId);
7401
7721
  if (!initial?.consent) throw new ApplicationError("CONFIRMATION_REQUIRED");
7402
7722
  const formed = initial.snapshotId ? [] : namedJourneyWorks(formJourneyWorks(plan.approval, options.processing.environment), options.processing, abort.signal);
@@ -10374,6 +10694,22 @@ function createJourneyOwnerClient(options) {
10374
10694
  const { headers } = await requestWithHeaders("/me/profile", publicProfileSchema, signal);
10375
10695
  return { parallelCompletes: (headers.get("passport-capabilities") ?? "").split(",").some((token) => token.trim() === "parallel-completes") };
10376
10696
  },
10697
+ readProfile(signal) {
10698
+ return request("/me/profile", ownerProfileSchema, signal, void 0, "GET");
10699
+ },
10700
+ async saveProfile(profile, signal) {
10701
+ await request("/me/profile", ownerProfileSchema, signal, profile, "PUT");
10702
+ },
10703
+ async addressTaken(address, signal) {
10704
+ const path = `/addresses/${encodeURIComponent(passportAddressSchema.parse(address))}`;
10705
+ try {
10706
+ await request(path, z.object({ publicId: z.string() }).strict(), signal, void 0, "GET");
10707
+ return true;
10708
+ } catch (error) {
10709
+ if (error instanceof JourneyRemoteError && error.status === 404) return false;
10710
+ throw error;
10711
+ }
10712
+ },
10377
10713
  resolve(input, signal) {
10378
10714
  return request("/me/work-bundles/resolve", sendResolutionSchema.refine((value) => value.logicalWorkId === input.logicalWorkId), signal, input);
10379
10715
  },
@@ -10963,7 +11299,13 @@ function resumeState(send) {
10963
11299
  status: "sign-in",
10964
11300
  error: null
10965
11301
  };
10966
- const profileRequired = ["paused", "sign-in"].includes(send.status) || send.subject === null || ["ACCOUNT_PROFILE_UNAVAILABLE", "ACCOUNT_CHANGED"].includes(send.error ?? "") || send.status === "blocked" && send.items.some((item) => [
11302
+ const profileRequired = ["paused", "sign-in"].includes(send.status) || send.subject === null || [
11303
+ "ACCOUNT_PROFILE_UNAVAILABLE",
11304
+ "ACCOUNT_CHANGED",
11305
+ "PASSPORT_ADDRESS_TAKEN",
11306
+ "PASSPORT_ADDRESS_RESERVED",
11307
+ "PASSPORT_ADDRESS_LIMIT"
11308
+ ].includes(send.error ?? "") || send.status === "blocked" && send.items.some((item) => [
10967
11309
  "ready",
10968
11310
  "uploading",
10969
11311
  "assessing",
@@ -11047,7 +11389,42 @@ async function prepareProfile(dependencies, snapshot, connection, signal) {
11047
11389
  assertScope(latest.journey, latest.send);
11048
11390
  signal.throwIfAborted();
11049
11391
  }
11050
- return captureProfile(connection, guard, signal, dependencies.failure);
11392
+ const captured = await captureProfile(connection, guard, signal, dependencies.failure);
11393
+ const chosen = snapshot.journey.profile;
11394
+ if (captured.status !== "sending" || !chosen || !profileHasChoices(chosen)) return captured;
11395
+ return writeProfile(connection, chosen, guard, signal, dependencies.failure, captured);
11396
+ }
11397
+ /** Passport's refusal of the chosen address, as the code that re-shows the address card. */
11398
+ const addressRefusals = {
11399
+ address_taken: "PASSPORT_ADDRESS_TAKEN",
11400
+ address_reserved: "PASSPORT_ADDRESS_RESERVED",
11401
+ address_limit_reached: "PASSPORT_ADDRESS_LIMIT"
11402
+ };
11403
+ /**
11404
+ * The Journey's address and links over the owner's current settings, saved before the first
11405
+ * Work upload (ADR 0246). A refused address blocks the Send until the person keeps another.
11406
+ */
11407
+ async function writeProfile(connection, chosen, guard, signal, failure, captured) {
11408
+ try {
11409
+ const current = await connection.readProfile(signal);
11410
+ await guard();
11411
+ await connection.saveProfile(mergeOwnerProfile(current.profile, chosen), signal);
11412
+ await guard();
11413
+ return captured;
11414
+ } catch (error) {
11415
+ if (signal.aborted) throw error;
11416
+ if (error instanceof JourneyRemoteError && error.status === 409 && addressRefusals[error.code]) return {
11417
+ status: "blocked",
11418
+ error: addressRefusals[error.code] ?? null
11419
+ };
11420
+ if (error instanceof ApplicationError) throw error;
11421
+ const unavailable = new ApplicationError("ACCOUNT_PROFILE_UNAVAILABLE", void 0, { cause: error });
11422
+ failure(unavailable.code, unavailable);
11423
+ return {
11424
+ status: "blocked",
11425
+ error: unavailable.code
11426
+ };
11427
+ }
11051
11428
  }
11052
11429
  /** Shared by native Send and Manual upload; `guard` rechecks the caller's own scope. */
11053
11430
  async function captureProfile(connection, guard, signal, failure) {
@@ -12951,6 +13328,45 @@ function createJourneySender(dependencies, phases = 3) {
12951
13328
  get(address) {
12952
13329
  return dependencies.storage.loadSend(address.journeyId, address.sendId);
12953
13330
  },
13331
+ /** The owner's current address, links and account email; null while signed out. */
13332
+ async ownerProfile(signal) {
13333
+ const connection = await dependencies.auth.connect(signal);
13334
+ if (!connection) return null;
13335
+ const { profile, accountEmail } = await connection.readProfile(signal);
13336
+ return {
13337
+ address: profile.address,
13338
+ links: profile.links,
13339
+ accountEmail
13340
+ };
13341
+ },
13342
+ /** A best-effort availability check for the address card; Send's save decides. */
13343
+ async addressTaken(input, signal) {
13344
+ const address = passportAddressSchema.parse(input.address);
13345
+ const connection = await dependencies.auth.connect(signal);
13346
+ if (!connection) return null;
13347
+ return { taken: await connection.addressTaken(address, signal) };
13348
+ },
13349
+ /**
13350
+ * The address or links chosen on the Sent page, after the Send reached Passport (ADR 0246,
13351
+ * BL-230): an explicit Keep or Add saves them at once over the current settings.
13352
+ */
13353
+ async saveSentProfile(input, signal) {
13354
+ const latest = requireSend(await dependencies.storage.loadSend(input.journeyId));
13355
+ const chosen = latest.journey.profile;
13356
+ if (latest.send.status !== "completed" || !chosen || !profileHasChoices(chosen)) throw new ApplicationError("INVALID_TRANSITION");
13357
+ const connection = await dependencies.auth.connect(signal);
13358
+ if (!connection) throw new ApplicationError("ACCOUNT_SIGNED_OUT");
13359
+ if (latest.send.subject !== connection.subject) throw new ApplicationError("IDENTITY_REJECTED");
13360
+ try {
13361
+ const current = await connection.readProfile(signal);
13362
+ await connection.saveProfile(mergeOwnerProfile(current.profile, chosen), signal);
13363
+ } catch (error) {
13364
+ if (signal.aborted || error instanceof ApplicationError) throw error;
13365
+ const code = error instanceof JourneyRemoteError && error.status === 409 ? addressRefusals[error.code] : void 0;
13366
+ if (code) throw new ApplicationError(code);
13367
+ throw new ApplicationError("ACCOUNT_PROFILE_UNAVAILABLE", void 0, { cause: error });
13368
+ }
13369
+ },
12954
13370
  async prepare(raw, signal) {
12955
13371
  const input = sendPrepareSchema.parse(raw);
12956
13372
  const snapshot = await dependencies.storage.loadSend(input.journeyId);
@@ -14986,6 +15402,18 @@ async function compose(options, callbacks, bundles) {
14986
15402
  })();
14987
15403
  return {
14988
15404
  application,
15405
+ remoteWorkers: createRemotePreflight({
15406
+ storage: journeyStorage,
15407
+ harnesses,
15408
+ execution,
15409
+ stateDir,
15410
+ home: homedir(),
15411
+ roots: {
15412
+ codexHome: options.codexHome,
15413
+ claudeHome: options.claudeHome
15414
+ },
15415
+ reportFailure: (error) => diagnostics.onFailure("remote-workers", error)
15416
+ }),
14989
15417
  nativeInspection: {
14990
15418
  originals: createOriginalView(journeyStorage, stateDir),
14991
15419
  output: createOutputView(journeyStorage, processing),
@@ -15090,6 +15518,7 @@ async function invoke(runtime, command, value, signal) {
15090
15518
  const app = runtime.application;
15091
15519
  markAgentPresence(runtime.stateDir, value);
15092
15520
  switch (command) {
15521
+ case "journey.remoteWorkers": return runtime.remoteWorkers(value, signal);
15093
15522
  case "send.get": return app.journeySend?.get(sendAddress.partial({ sendId: true }).parse(value));
15094
15523
  case "send.prepare": return app.journeySend?.prepare(sendPrepareSchema.parse(value));
15095
15524
  case "send.start": return app.journeySend?.start(sendStartSchema.parse(value));
@@ -1,7 +1,7 @@
1
- import { tn as sessionSchema } from "./locate-CBiw-CJK.mjs";
2
- import { t as createZstdFrameCheck$1 } from "./frame-IeDOLy1o.mjs";
3
- import "./src-CBTvOa44.mjs";
4
- import { a as isRecord } from "./model-DGTsARtV.mjs";
1
+ import { ln as sessionSchema } from "./locate-JYtFmKu-.mjs";
2
+ import { t as createZstdFrameCheck$1 } from "./frame-DGun31Uc.mjs";
3
+ import "./src-C1SjCDx0.mjs";
4
+ import { a as isRecord } from "./model-CmHypB0p.mjs";
5
5
  import { constants } from "node:fs";
6
6
  import { z } from "zod";
7
7
  import { lstat, open, stat } from "node:fs/promises";