@gitroll/tacitt-cli 0.6.4 → 0.6.5

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/cli.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { _ as permissionDiagnostic, a as readAgentPresence, d as guardDetachedStartup, f as createRenderActivity, g as longCommands, h as businessCommands, i as invoke, l as awaitingPassport, m as parseOptions, n as readOperation, o as createRuntime, p as helpText, r as waitOperation, s as executorEventSchema, t as cancelOperation, u as serveDetached, v as startupFailure, y as traceStartup } from "./query-BMvtisKu.mjs";
2
+ import { _ as permissionDiagnostic, a as readAgentPresence, d as guardDetachedStartup, f as createRenderActivity, g as longCommands, h as businessCommands, i as invoke, l as awaitingPassport, m as parseOptions, n as readOperation, o as createRuntime, p as helpText, r as waitOperation, s as executorEventSchema, t as cancelOperation, u as serveDetached, v as startupFailure, y as traceStartup } from "./query-CL2Y-w4C.mjs";
3
3
  import { nt as makePrivateDirectory, rt as openPrivateFile } from "./src-BRwicVza.mjs";
4
- import { A as createExecutionPort, j as startHost, k as readStateDump } from "./job-D4N5Pe91.mjs";
4
+ import { A as createExecutionPort, I as inBackgroundStatusPoll, j as startHost, k as readStateDump } from "./job-DZ0wrsWq.mjs";
5
5
  import { $t as safeField, Qt as safeCode, Xt as ApplicationError } from "./locate-CNU4z9G1.mjs";
6
6
  import { $n as reviewTransportBytes, ci as stateSchema, ct as resolveFailureLocation, tt as readWorkspaceOutcomes } from "./src-DmSIVU7-.mjs";
7
- import { _t as isCoordinationBusy } from "./heap-DQbsSUrB.mjs";
7
+ import { _t as isCoordinationBusy } from "./heap-lJNgbnRz.mjs";
8
8
  import { constants, createReadStream, write } from "node:fs";
9
9
  import { z } from "zod";
10
10
  import { lstat, mkdir, mkdtemp, open, readFile, readdir, realpath, rename, rm, writeFile } from "node:fs/promises";
@@ -305,9 +305,9 @@ async function serve(options, journeyId) {
305
305
  following = true;
306
306
  (async () => {
307
307
  const { journey: journeys, journeySend } = runtime.application;
308
- const journey = await journeys?.get({ journeyId });
308
+ const journey = await inBackgroundStatusPoll(async () => journeys?.get({ journeyId }));
309
309
  const ended = journey?.phase === "completed" || journey?.abandonedAt !== void 0;
310
- const send = (await journeys?.get({}))?.journeyId === journeyId ? (await journeySend?.get({ journeyId }))?.send : null;
310
+ const send = (await inBackgroundStatusPoll(async () => journeys?.get({})))?.journeyId === journeyId ? (await journeySend?.get({ journeyId }))?.send : null;
311
311
  const waiting = Boolean(send && awaitingPassport(send));
312
312
  const now = Date.now();
313
313
  endedAt = ended ? endedAt ?? now : void 0;
@@ -1,5 +1,5 @@
1
1
  import { et as safeError, h as captureConfiguredSessionJob, j as runConfiguredSessionJob, u as runConfiguredScanJob, z as gitSeedsProvider } from "./src-BRwicVza.mjs";
2
- import { d as runJourneyBaseJob, i as runJourneyOutputVerifyJob, n as runJourneyOutputJob, r as runJourneyOutputShardJob } from "./job-D4N5Pe91.mjs";
2
+ import { d as runJourneyBaseJob, i as runJourneyOutputVerifyJob, n as runJourneyOutputJob, r as runJourneyOutputShardJob } from "./job-DZ0wrsWq.mjs";
3
3
  import { Dn as createStaticProcessor, Qt as safeCode } from "./locate-CNU4z9G1.mjs";
4
4
  import { l as createNativeAdapters } from "./src-BgoSvnXe.mjs";
5
5
  import "./src-DmSIVU7-.mjs";
@@ -7,8 +7,8 @@ import { copyFile, link, lstat, mkdir, mkdtemp, open, readFile, realpath, rm, un
7
7
  import { isAbsolute, join, resolve } from "node:path";
8
8
  import { isDeepStrictEqual } from "node:util";
9
9
  import { createHash, randomBytes, randomUUID } from "node:crypto";
10
- import { tmpdir } from "node:os";
11
10
  import { AsyncLocalStorage } from "node:async_hooks";
11
+ import { tmpdir } from "node:os";
12
12
  import { DatabaseSync } from "node:sqlite";
13
13
  import { getHeapStatistics, setFlagsFromString } from "node:v8";
14
14
  //#region packages/local-host/src/store/error.ts
@@ -5407,6 +5407,83 @@ function finishSessionUsefulness(db, args) {
5407
5407
  return result;
5408
5408
  }
5409
5409
  //#endregion
5410
+ //#region packages/local-host/src/store/journey/reconciliation/status/snapshot.ts
5411
+ const tableSchema = z.enum([
5412
+ "journey_runs",
5413
+ "journey_current",
5414
+ "journey_work_inputs",
5415
+ "journey_batches",
5416
+ "journey_resources",
5417
+ "journey_receipts",
5418
+ "journey_review_overlays",
5419
+ "journey_finding_groups"
5420
+ ]);
5421
+ const rowSchema = z.record(z.string(), z.union([
5422
+ z.string(),
5423
+ z.number(),
5424
+ z.bigint(),
5425
+ z.null(),
5426
+ z.instanceof(Uint8Array)
5427
+ ]));
5428
+ const statusDatabaseSnapshotSchema = z.record(tableSchema, z.array(rowSchema));
5429
+ /**
5430
+ * Only materialize immutable SQL values while the live transaction owns the state claim.
5431
+ * No JSON parsing, header validation, grouping or projection runs here. Keep original
5432
+ * rowids: progress uses resource insertion order to distinguish newer attempts.
5433
+ */
5434
+ function captureStatusDatabase(db, query) {
5435
+ const rows = (table, columns, where, ...args) => db.prepare(`SELECT ${columns} FROM ${table} ${where} ORDER BY rowid`).all(...args);
5436
+ return {
5437
+ journey_runs: rows("journey_runs", "id,state_json", "WHERE id=? OR id=(SELECT journey_id FROM journey_current WHERE singleton=1)", query.journeyId),
5438
+ journey_current: rows("journey_current", "singleton,journey_id", ""),
5439
+ journey_work_inputs: rows("journey_work_inputs", "journey_id,work_id,input_revision", "WHERE journey_id=?", query.journeyId),
5440
+ journey_batches: rows("journey_batches", "*", "WHERE journey_id=?", query.journeyId),
5441
+ journey_resources: rows("journey_resources", "rowid AS __rowid,journey_id,kind,id,json", "WHERE journey_id=? AND kind IN ('b-candidate','b-repair','b-session','b-reread','b-reconciliation','b-usefulness','b-attempt')", query.journeyId),
5442
+ journey_receipts: rows("journey_receipts", "request_key,request_hash,journey_id", `WHERE journey_id=? AND request_key IN (
5443
+ SELECT id FROM journey_resources WHERE journey_id=? AND kind IN ('b-reconciliation','b-usefulness')
5444
+ UNION ALL SELECT CASE WHEN json_valid(review_ref_json)
5445
+ THEN json_extract(review_ref_json,'$.idempotencyKey') END FROM journey_batches
5446
+ WHERE journey_id=? AND ?<>'' AND review_ref_json IS NOT NULL
5447
+ )`, query.journeyId, query.journeyId, query.journeyId, query.sessionReviewId ?? ""),
5448
+ journey_review_overlays: rows("journey_review_overlays", "journey_id,batch_id,reconciliation_id,overlay_digest", `WHERE journey_id=? AND reconciliation_id IN (SELECT id FROM journey_resources WHERE journey_id=? AND kind='b-reconciliation')`, query.journeyId, query.journeyId),
5449
+ journey_finding_groups: query.sessionReviewId ? rows("journey_finding_groups", "journey_id,batch_id,finding_id,group_id", "WHERE journey_id=?", query.journeyId) : []
5450
+ };
5451
+ }
5452
+ const capturedTables = `
5453
+ CREATE TABLE journey_runs (id TEXT PRIMARY KEY, state_json TEXT NOT NULL);
5454
+ CREATE TABLE journey_current (singleton INTEGER PRIMARY KEY, journey_id TEXT NOT NULL);
5455
+ CREATE TABLE journey_work_inputs (journey_id TEXT NOT NULL, work_id TEXT NOT NULL, input_revision INTEGER NOT NULL, PRIMARY KEY(journey_id,work_id));
5456
+ CREATE TABLE journey_batches (id TEXT PRIMARY KEY, journey_id TEXT NOT NULL, work_id TEXT NOT NULL, input_revision INTEGER NOT NULL, ordinal INTEGER NOT NULL, digest TEXT NOT NULL, header_json TEXT NOT NULL, batch_ref_json TEXT NOT NULL, review_ref_json TEXT, review_sequence INTEGER, UNIQUE(journey_id,work_id,input_revision,ordinal));
5457
+ CREATE TABLE journey_resources (journey_id TEXT NOT NULL, kind TEXT NOT NULL, id TEXT NOT NULL, json TEXT NOT NULL, PRIMARY KEY(journey_id,kind,id));
5458
+ CREATE TABLE journey_receipts (request_key TEXT PRIMARY KEY, request_hash TEXT NOT NULL, journey_id TEXT NOT NULL);
5459
+ CREATE TABLE journey_review_overlays (journey_id TEXT NOT NULL, batch_id TEXT NOT NULL, reconciliation_id TEXT NOT NULL, overlay_digest TEXT NOT NULL, PRIMARY KEY(journey_id,batch_id,reconciliation_id));
5460
+ CREATE TABLE journey_finding_groups (journey_id TEXT NOT NULL, batch_id TEXT NOT NULL, finding_id TEXT NOT NULL, group_id TEXT NOT NULL, PRIMARY KEY(journey_id,batch_id,finding_id));
5461
+ `;
5462
+ /** Request-local, query-only computation; never a replacement for live state. */
5463
+ function projectStatusDatabase(snapshot, project) {
5464
+ const db = new DatabaseSync(":memory:");
5465
+ try {
5466
+ try {
5467
+ db.exec(capturedTables);
5468
+ db.exec("BEGIN");
5469
+ for (const table of tableSchema.options) {
5470
+ const first = snapshot[table][0];
5471
+ if (!first) continue;
5472
+ const keys = Object.keys(first);
5473
+ const columns = keys.map((key) => `"${(key === "__rowid" ? "rowid" : key).replaceAll("\"", "\"\"")}"`);
5474
+ const insert = db.prepare(`INSERT INTO ${table} (${columns.join(",")}) VALUES (${columns.map(() => "?").join(",")})`);
5475
+ for (const row of snapshot[table]) insert.run(...keys.map((key) => row[key] ?? null));
5476
+ }
5477
+ db.exec("COMMIT; PRAGMA query_only=ON");
5478
+ } catch (cause) {
5479
+ throw new ApplicationError("CORRUPTED_STATE", void 0, { cause });
5480
+ }
5481
+ return project(db);
5482
+ } finally {
5483
+ db.close();
5484
+ }
5485
+ }
5486
+ //#endregion
5410
5487
  //#region packages/local-host/src/store/journey/batch-metadata.ts
5411
5488
  const activeBatchMetadataQuery = `
5412
5489
  WITH batch_metadata AS MATERIALIZED (
@@ -6659,6 +6736,14 @@ function listDeliveries(db, runId, operationId) {
6659
6736
  }
6660
6737
  //#endregion
6661
6738
  //#region packages/local-host/src/store/worker/operations.ts
6739
+ const selectProjectionSchema = z.object({
6740
+ snapshot: statusDatabaseSnapshotSchema,
6741
+ query: sessionReviewQuerySchema
6742
+ });
6743
+ const finishProjectionSchema = z.object({
6744
+ snapshot: statusDatabaseSnapshotSchema,
6745
+ packet: finishStatusSchema
6746
+ });
6662
6747
  function define(write, args, run, decode) {
6663
6748
  return {
6664
6749
  write,
@@ -6666,6 +6751,15 @@ function define(write, args, run, decode) {
6666
6751
  decode
6667
6752
  };
6668
6753
  }
6754
+ function defineProjection(args, project, decode) {
6755
+ const execute = (value) => project(args.parse(value));
6756
+ return {
6757
+ write: false,
6758
+ project: execute,
6759
+ execute: (_db, value) => execute(value),
6760
+ decode
6761
+ };
6762
+ }
6669
6763
  function readControlState(db) {
6670
6764
  try {
6671
6765
  return readStoredState(db);
@@ -6730,10 +6824,11 @@ function decodeResources(value) {
6730
6824
  });
6731
6825
  }
6732
6826
  const operations = {
6827
+ "journey.session.status.project-select": defineProjection(selectProjectionSchema, ({ snapshot, query }) => statusSelectionSchema.parse(projectStatusDatabase(snapshot, (db) => selectStatus(db, query))), (value) => statusSelectionSchema.parse(value)),
6828
+ "journey.session.status.project-finish": defineProjection(finishProjectionSchema, ({ snapshot, packet }) => sessionReviewStatusSchema.parse(projectStatusDatabase(snapshot, (db) => finishStatus(db, packet))), (value) => sessionReviewStatusSchema.parse(value)),
6733
6829
  "journey.review.select-reuse": define(false, reuseQuerySchema, selectReviewReuse, (value) => reuseSelectionSchema.parse(value)),
6734
6830
  "journey.review.finish-reuse": define(true, finishReuseSchema, finishReviewReuse, nothing),
6735
- "journey.session.status.select": define(false, sessionReviewQuerySchema, selectStatus, (value) => statusSelectionSchema.parse(value)),
6736
- "journey.session.status.finish": define(false, finishStatusSchema, finishStatus, (value) => sessionReviewStatusSchema.parse(value)),
6831
+ "journey.session.status.capture": define(false, sessionReviewQuerySchema, captureStatusDatabase, (value) => statusDatabaseSnapshotSchema.parse(value)),
6737
6832
  "journey.review.select-session": define(false, sessionDependencyQuerySchema, selectSessionDependencies, (value) => sessionDependenciesSchema.parse(value)),
6738
6833
  "journey.review.finish-session-resource": define(true, finishSessionResourceSchema, finishSessionResource, nothing),
6739
6834
  "journey.review.finish-session-compile": define(false, finishSessionCompileSchema, finishSessionCompile, nothing),
@@ -6924,6 +7019,12 @@ const commandSchema = z.discriminatedUnion("type", [
6924
7019
  generation: z.number().int().nonnegative()
6925
7020
  })
6926
7021
  }),
7022
+ z.object({
7023
+ type: z.literal("project"),
7024
+ id,
7025
+ operation: z.string(),
7026
+ args: z.unknown()
7027
+ }),
6927
7028
  z.object({
6928
7029
  type: z.literal("run"),
6929
7030
  id,
@@ -6990,6 +7091,7 @@ const replySchema = z.discriminatedUnion("type", [
6990
7091
  const allowedReplies = {
6991
7092
  begin: ["begun", "failed"],
6992
7093
  run: ["done", "failed"],
7094
+ project: ["done", "failed"],
6993
7095
  "read-for-write": ["state", "failed"],
6994
7096
  save: ["done", "failed"],
6995
7097
  abort: ["aborted", "failed"],
@@ -7148,6 +7250,7 @@ function createExecutor(send, options = {}) {
7148
7250
  let result;
7149
7251
  if (step.type === "run" && isOperationName(step.operation)) {
7150
7252
  const definition = operations[step.operation];
7253
+ if (definition.project) throw new ProtocolError("PROJECT_DURING_TRANSACTION");
7151
7254
  if (definition.write !== begin.write) throw new ProtocolError("OPERATION_MODE");
7152
7255
  result = definition.execute(db, step.args);
7153
7256
  phase("action");
@@ -7234,6 +7337,32 @@ receive(input) {
7234
7337
  dropAnchor();
7235
7338
  return send({ type: "anchor-dropped" });
7236
7339
  }
7340
+ if (command.type === "project") {
7341
+ if (active) return violate(command.id, "PROJECT_DURING_TRANSACTION");
7342
+ if (!isOperationName(command.operation)) return violate(command.id, "UNKNOWN_PROJECT");
7343
+ const project = operations[command.operation].project;
7344
+ if (!project) return violate(command.id, "UNKNOWN_PROJECT");
7345
+ try {
7346
+ const result = project(command.args);
7347
+ send({
7348
+ type: "done",
7349
+ id: command.id,
7350
+ busyMs: busy(),
7351
+ phases: {},
7352
+ result
7353
+ });
7354
+ } catch (error) {
7355
+ send({
7356
+ type: "failed",
7357
+ id: command.id,
7358
+ busyMs: busy(),
7359
+ phases: {},
7360
+ error: encodeError(error),
7361
+ closed: true
7362
+ });
7363
+ }
7364
+ return;
7365
+ }
7237
7366
  if (command.type === "begin") {
7238
7367
  if (active) return violate(command.id, "CONCURRENT_TRANSACTION");
7239
7368
  active = true;
@@ -1,7 +1,7 @@
1
1
  import { A as renderJobDigest, D as prepareCollectionProduction, E as checkReusableBundle, L as privateCollectionDirectory, M as readCollectionIndex, N as parseCollectionWorkspaceSummary, V as writeLogicalJourneyOutput, W as readConfiguredOutputInfo, at as windowsOwnerOnly, b as writeLogicalJourneyBase, d as verifyOutputShard, f as writeOutputShard, nt as makePrivateDirectory, ot as isWindowsAclFailure, rt as openPrivateFile, w as readConfiguredSearchFields, z as gitSeedsProvider } from "./src-BRwicVza.mjs";
2
2
  import { $t as safeField, F as bClassificationKey, Ft as termTypeInfo, H as codePointLength, Ht as journeyProfileAddressActionSchema, K as utf16Offset, Kt as passportAddressSchema, N as bUnitFragments, Qt as safeCode, Ut as journeyProfileLinksActionSchema, V as bDigest, Xt as ApplicationError, b as validateBReview, c as textDigest, h as reviewFindingsDigest, ht as journeyDescribeSchema, jt as reviewTermsInputSchema, l as validateReview, n as compileBFindings, nn as reviewFamilies, r as reviewBatchChunks, s as reviewSubmitSchema, t as locateTerms, z as bAnchorKey, zt as filterInventoryByPeriod } from "./locate-CNU4z9G1.mjs";
3
3
  import { $ as settingsBatchSchema, $r as journeyPreviewSchema, B as inspectionStartSchema, C as rebindReviewOverlay, Ct as sendPrepareSchema, D as staticallyHiddenFindings, Dn as termHideAdditions, Dr as nativeGetSchema, E as guardedFindingText, Er as nativeEventsSchema, It as journeyReviewStorageQuerySchema, Ln as confirmedHideGroupIds, Mr as staticSessionResourceSchema, On as addHideIndexTokens, Or as nativeRespondSchema, Qn as reviewRepairResourceSchema, Qr as journeyFindingsSchema, Qt as journeyPolicyRespondSchema, S as rebindReviewAlignment, Sn as confirmedHideAdditions, Sr as journeyClassificationSessionsSchema, St as sendChoiceSchema, T as reviewBatchReuse, Tn as renderedHideValue, Tt as sendStartSchema, Un as maskedHitsStale, Ut as reviewCompileSchema, W as inspectionQuerySchema, Wt as journeyContextQuerySchema, Xn as reviewCandidateResourceSchema, Yn as reviewCandidateInputSchema, Zn as reviewRepairInputSchema, Zr as journeyFindingImpactSchema, _n as sessionUsefulnessInputSchema, a as bCrossSegmentReviewSchema, ai as selectionSchema, an as reviewAttemptResourceSchema, b as isGenericPublicTerm, bt as replaceSensitiveTermsSchema, c as reconstructBFields, ci as stateSchema, cn as sessionReconcileInputSchema, ct as resolveFailureLocation, dn as sessionRereadInputSchema, ei as journeyRenderInputSchema, en as journeyResourceQuerySchema, er as bReviewDigest, et as settingsQuerySchema, f as selectedValueMembers, ft as manualUploadChoiceSchema, hi as selectFrozenConfiguration, ht as manualUploadStartSchema, i as validateBCrossSegmentReview, ii as selectionBatchSchema, jn as packHideIndex, kn as hideKeyId, mi as freezeConfiguration, mn as sessionReviewQuerySchema, n as scanBatchEquivalenceDigest, ni as commandSchema, nr as planBRepair, o as bRereadDigest, p as splitSelectorValues, pi as defaultScopedSettings, pn as sessionReviewInputSchema, pr as journeyInventoryQuerySchema, pt as manualUploadPrepareSchema, r as locateTermEvidence, ri as packageCommandSchema, rn as journeyPlaceSchema, s as reconcileBSession, si as producerVersion, t as scanBatchContextDigest, ti as journeyRenderSchema, tt as readWorkspaceOutcomes, ut as manualUploadActionSchema, vt as maximumTermsFileBytes, w as rebindReviewSubmit, wn as readConfirmedHideChange, wt as sendRequestSchema, x as bReviewScope, xt as sendActionSchema, z as inspectionCancelSchema } from "./src-DmSIVU7-.mjs";
4
- 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, 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-DQbsSUrB.mjs";
4
+ 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, 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-lJNgbnRz.mjs";
5
5
  import { constants, write } from "node:fs";
6
6
  import { z } from "zod";
7
7
  import { copyFile, link, lstat, mkdir, mkdtemp, open, opendir, readFile, readdir, realpath, rename, rm, unlink, writeFile } from "node:fs/promises";
@@ -16,10 +16,10 @@ import { fastifyStatic } from "@fastify/static";
16
16
  import { fastifyRequestHandler, fastifyTRPCPlugin } from "@trpc/server/adapters/fastify";
17
17
  import { TRPCError, initTRPC } from "@trpc/server";
18
18
  import { getHTTPStatusCodeFromError } from "@trpc/server/http";
19
+ import { AsyncLocalStorage } from "node:async_hooks";
19
20
  import { ZipWriter } from "@zip.js/zip.js/index-native.js";
20
21
  import { tmpdir } from "node:os";
21
22
  import { pipeline } from "node:stream/promises";
22
- import { AsyncLocalStorage } from "node:async_hooks";
23
23
  import { DatabaseSync } from "node:sqlite";
24
24
  import { Worker } from "node:worker_threads";
25
25
  import { quote } from "shell-quote";
@@ -51,6 +51,27 @@ async function retrySharingViolation(operation) {
51
51
  }
52
52
  }
53
53
  //#endregion
54
+ //#region packages/local-host/src/store/lane.ts
55
+ const background = new AsyncLocalStorage();
56
+ /**
57
+ * Store accesses started inside `work` wait behind every waiting foreground access, like the
58
+ * shared pool's ordinary lane behind its priority lane (Track B behind Track A, ADR 0172).
59
+ */
60
+ function inBackgroundStoreLane(work) {
61
+ return background.run(true, work);
62
+ }
63
+ function isBackgroundStoreAccess() {
64
+ return background.getStore() === true;
65
+ }
66
+ const statusPoll = new AsyncLocalStorage();
67
+ /** Mark only recurring observation reads, never mutation or reviewStatus RPC work. */
68
+ function inBackgroundStatusPoll(work) {
69
+ return statusPoll.run(true, work);
70
+ }
71
+ function isBackgroundStatusPoll() {
72
+ return statusPoll.getStore() === true;
73
+ }
74
+ //#endregion
54
75
  //#region packages/local-host/src/workflow-events.ts
55
76
  /** One demand-driven read per host; consumers retain their own change detection/backpressure. */
56
77
  function createWorkflowEvents(read, stopping) {
@@ -606,8 +627,9 @@ const operation = z.enum([
606
627
  "journey.review.finish-usefulness",
607
628
  "journey.review.select-reuse",
608
629
  "journey.review.finish-reuse",
609
- "journey.session.status.select",
610
- "journey.session.status.finish",
630
+ "journey.session.status.project-select",
631
+ "journey.session.status.project-finish",
632
+ "journey.session.status.capture",
611
633
  "journey.batch.put",
612
634
  "journey.batch.read",
613
635
  "journey.review.attempts",
@@ -657,6 +679,7 @@ const phase = z.enum([
657
679
  "release",
658
680
  "executor.begin",
659
681
  "executor.run",
682
+ "executor.project",
660
683
  "executor.read-for-write",
661
684
  "executor.save",
662
685
  "executor.abort",
@@ -935,10 +958,10 @@ function createRouter(application, account, stopping, delivery, nativeInspection
935
958
  findings: t.procedure.input(journeyFindingsSchema).query(({ input, signal }) => native().findings(input, signal)),
936
959
  findingImpact: t.procedure.input(journeyFindingImpactSchema).query(({ input, signal }) => native().findingImpact(input, signal)),
937
960
  preview: t.procedure.input(journeyPreviewSchema).query(({ input, signal }) => native().preview(input, signal)),
938
- get: t.procedure.input(nativeGetSchema).query(({ input, signal }) => readThroughContention(() => native().get(input), signal)),
961
+ get: t.procedure.input(nativeGetSchema).query(({ input, signal }) => readThroughContention(() => inBackgroundStatusPoll(() => native().get(input)), signal)),
939
962
  presence: t.procedure.input(z.object({ journeyId: z.uuid() }).strict()).query(async ({ input }) => ({ agent: await agentPresence?.(input.journeyId) ?? null })),
940
963
  inventory: t.procedure.input(journeyInventoryQuerySchema).query(({ input }) => native().inventory(input)),
941
- events: t.procedure.input(nativeEventsSchema).query(({ input, signal }) => readThroughContention(() => native().events(input, signal), signal))
964
+ events: t.procedure.input(nativeEventsSchema).query(({ input, signal }) => readThroughContention(() => inBackgroundStatusPoll(() => native().events(input, signal)), signal))
942
965
  }),
943
966
  delivery: t.router({
944
967
  list: t.procedure.query(() => delivery?.list() ?? []),
@@ -2036,19 +2059,6 @@ function createStoreLifetime() {
2036
2059
  };
2037
2060
  }
2038
2061
  //#endregion
2039
- //#region packages/local-host/src/store/lane.ts
2040
- const background = new AsyncLocalStorage();
2041
- /**
2042
- * Store accesses started inside `work` wait behind every waiting foreground access, like the
2043
- * shared pool's ordinary lane behind its priority lane (Track B behind Track A, ADR 0172).
2044
- */
2045
- function inBackgroundStoreLane(work) {
2046
- return background.run(true, work);
2047
- }
2048
- function isBackgroundStoreAccess() {
2049
- return background.getStore() === true;
2050
- }
2051
- //#endregion
2052
2062
  //#region packages/local-host/src/store/access.ts
2053
2063
  function invalidResult(cause) {
2054
2064
  return new StoreError("STATE_IO_ERROR", "The state database returned an invalid result.", { cause });
@@ -2363,6 +2373,17 @@ function createStoreAccess(directory, owner, channel, invalidate = () => {}, onF
2363
2373
  }
2364
2374
  async function runOperation(fenced, name, args, cache) {
2365
2375
  const definition = operations[name];
2376
+ if (definition.project) {
2377
+ const reply = await channel.request({
2378
+ type: "project",
2379
+ id: nextId += 1,
2380
+ operation: name,
2381
+ args
2382
+ });
2383
+ if (reply.type === "failed") throw decodeError(reply.error);
2384
+ if (reply.type !== "done") throw new ProtocolError("UNEXPECTED_REPLY");
2385
+ return definition.decode(reply.result);
2386
+ }
2366
2387
  const finish = await fenced(definition.write, async ({ root, verified, checkpoint, request, transaction }) => {
2367
2388
  const load = () => transaction(async (id) => {
2368
2389
  const reply = await request({
@@ -3352,12 +3373,25 @@ function withTermExclusions(status, suggestions) {
3352
3373
  //#endregion
3353
3374
  //#region packages/local-host/src/store/journey/reconciliation/status/staged.ts
3354
3375
  async function readStagedStatus(leg, files, query, signal) {
3355
- const before = await leg.run("journey.session.status.select", sessionReviewQuerySchema.parse(query));
3376
+ const input = sessionReviewQuerySchema.parse(query);
3377
+ const selected = await leg.run("journey.session.status.capture", input);
3378
+ signal.throwIfAborted();
3379
+ const before = await leg.run("journey.session.status.project-select", {
3380
+ snapshot: selected,
3381
+ query: input
3382
+ });
3356
3383
  const loaded = await loadStatus(files, before, signal);
3357
- return withTermExclusions(await leg.run("journey.session.status.finish", {
3358
- before,
3359
- loaded
3360
- }), await loadTermExclusions(leg, files, before.query.journeyId, signal));
3384
+ const snapshot = await leg.run("journey.session.status.capture", input);
3385
+ signal.throwIfAborted();
3386
+ const status = await leg.run("journey.session.status.project-finish", {
3387
+ snapshot,
3388
+ packet: {
3389
+ before,
3390
+ loaded
3391
+ }
3392
+ });
3393
+ signal.throwIfAborted();
3394
+ return withTermExclusions(status, await loadTermExclusions(leg, files, before.query.journeyId, signal));
3361
3395
  }
3362
3396
  function createStagedStatus(access, files) {
3363
3397
  return (query) => access.staged((leg, signal) => readStagedStatus(leg, files, query, signal));
@@ -6281,4 +6315,4 @@ async function runJourneyOutputJob(job, live, signal, onPath) {
6281
6315
  };
6282
6316
  }
6283
6317
  //#endregion
6284
- export { createExecutionPort as A, saveRemoteState as C, createPackagingProgressPort as D, exportDelivery as E, preflight as F, loadDeliveryResults as I, retrySharingViolation as L, inBackgroundStoreLane as M, withStateMutex as N, createStore as O, createDeliveryService as P, readRemoteState as S, collectRemoteWorkers as T, staticBaseProduction as _, writeJourneyOutput as a, workApproval as b, mergeHideIndexTokens as c, runJourneyBaseJob as d, writeJourneyBase as f, staticBaseInputs as g, staticSessions as h, runJourneyOutputVerifyJob as i, startHost as j, readStateDump as k, packRenderHideIndex as l, saveStaticSession as m, runJourneyOutputJob as n, createHideIndexTokens as o, readStaticResult as p, runJourneyOutputShardJob as r, hideIndexTexts as s, journeyOutputJob as t, journeyBaseJob as u, readSelectedCaptures as v, journeyDirectory as w, isRemoteImport as x, prepareSourcePlan as y };
6318
+ export { createExecutionPort as A, saveRemoteState as C, createPackagingProgressPort as D, exportDelivery as E, loadDeliveryResults as F, inBackgroundStatusPoll as I, inBackgroundStoreLane as L, withStateMutex as M, createDeliveryService as N, createStore as O, preflight as P, isBackgroundStatusPoll as R, readRemoteState as S, collectRemoteWorkers as T, staticBaseProduction as _, writeJourneyOutput as a, workApproval as b, mergeHideIndexTokens as c, runJourneyBaseJob as d, writeJourneyBase as f, staticBaseInputs as g, staticSessions as h, runJourneyOutputVerifyJob as i, startHost as j, readStateDump as k, packRenderHideIndex as l, saveStaticSession as m, runJourneyOutputJob as n, createHideIndexTokens as o, readStaticResult as p, runJourneyOutputShardJob as r, hideIndexTexts as s, journeyOutputJob as t, journeyBaseJob as u, readSelectedCaptures as v, journeyDirectory as w, isRemoteImport as x, prepareSourcePlan as y, retrySharingViolation as z };
@@ -1,4 +1,4 @@
1
- import { c as executorRequestSchema, g as longCommands, i as invoke, m as parseOptions, n as readOperation, o as createRuntime, r as waitOperation, v as startupFailure } from "./query-BMvtisKu.mjs";
1
+ import { c as executorRequestSchema, g as longCommands, i as invoke, m as parseOptions, n as readOperation, o as createRuntime, r as waitOperation, v as startupFailure } from "./query-CL2Y-w4C.mjs";
2
2
  import { $t as safeField, Qt as safeCode, Xt as ApplicationError } from "./locate-CNU4z9G1.mjs";
3
3
  import "./src-DmSIVU7-.mjs";
4
4
  import { z } from "zod";
@@ -1,9 +1,9 @@
1
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-BRwicVza.mjs";
2
- import { A as createExecutionPort, C as saveRemoteState, D as createPackagingProgressPort, E as exportDelivery, F as preflight, I as loadDeliveryResults, L as retrySharingViolation, M as inBackgroundStoreLane, N as withStateMutex, O as createStore, P as createDeliveryService, 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 } from "./job-D4N5Pe91.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-DZ0wrsWq.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-CNU4z9G1.mjs";
4
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-BgoSvnXe.mjs";
5
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-DmSIVU7-.mjs";
6
- import { _t as isCoordinationBusy } from "./heap-DQbsSUrB.mjs";
6
+ import { _t as isCoordinationBusy } from "./heap-lJNgbnRz.mjs";
7
7
  import { t as createAgentSetupPort } from "./agent-setup-C7iqLMYm.mjs";
8
8
  import { t as workerMessageSchema } from "./messages-D3m3bhva.mjs";
9
9
  import { constants, write } from "node:fs";
@@ -1077,13 +1077,66 @@ function createJourneyTitles(storage, processing) {
1077
1077
  };
1078
1078
  }
1079
1079
  //#endregion
1080
+ //#region apps/cli/src/journey/status-poll.ts
1081
+ /** Bound distinct active and waiting polls; identical waiting queries share one promise. */
1082
+ const maximumStatusPolls = 16;
1083
+ /**
1084
+ * A read's elapsed time is mostly unclaimed Worker projection, so the cooldown is capped: a
1085
+ * full gap still exceeds one claim hold, and a panel read stays inside its 10 s timeout.
1086
+ */
1087
+ const maximumCooldownMs = 1e3;
1088
+ /** Only observation polls wait; a post-commit presentation must read fresh state immediately. */
1089
+ function paceSessionStatus(read, signal) {
1090
+ let tail = Promise.resolve();
1091
+ let nextAt = 0;
1092
+ let running = 0;
1093
+ const pending = /* @__PURE__ */ new Map();
1094
+ return (input) => {
1095
+ if (!isBackgroundStatusPoll()) return read(input);
1096
+ const key = JSON.stringify([
1097
+ input.journeyId,
1098
+ input.workId ?? null,
1099
+ input.sessionId ?? null,
1100
+ input.sessionReviewId ?? null,
1101
+ input.afterHit,
1102
+ input.limit
1103
+ ]);
1104
+ const existing = pending.get(key);
1105
+ if (existing) return existing;
1106
+ if (pending.size + running >= maximumStatusPolls) return Promise.reject(new ApplicationError("COORDINATION_BUSY"));
1107
+ const result = tail.then(async () => {
1108
+ signal?.throwIfAborted();
1109
+ while (performance.now() < nextAt) {
1110
+ const wait = Math.ceil(nextAt - performance.now());
1111
+ await setTimeout$1(Math.max(1, wait), void 0, { signal });
1112
+ }
1113
+ signal?.throwIfAborted();
1114
+ if (pending.get(key) === result) pending.delete(key);
1115
+ running++;
1116
+ const started = performance.now();
1117
+ try {
1118
+ return await read(input);
1119
+ } finally {
1120
+ running--;
1121
+ const finished = performance.now();
1122
+ nextAt = finished + Math.min(maximumCooldownMs, Math.max(0, finished - started));
1123
+ }
1124
+ }).finally(() => {
1125
+ if (pending.get(key) === result) pending.delete(key);
1126
+ });
1127
+ pending.set(key, result);
1128
+ tail = result.then(() => {}, () => {});
1129
+ return result;
1130
+ };
1131
+ }
1132
+ //#endregion
1080
1133
  //#region apps/cli/src/journey/destination.ts
1081
1134
  function check(state, destination) {
1082
1135
  if (state && state.destination !== destination) throw new ApplicationError("JOURNEY_DESTINATION_CHANGED");
1083
1136
  return state;
1084
1137
  }
1085
1138
  /** Bind stored consent to the actual configured owner API, not an agent-supplied label. */
1086
- function bindJourneyDestination(storage, destination) {
1139
+ function bindJourneyDestination(storage, destination, options = {}) {
1087
1140
  const verified = /* @__PURE__ */ new Set();
1088
1141
  const current = async (id) => {
1089
1142
  const state = check(await storage.current(id), destination);
@@ -1093,6 +1146,10 @@ function bindJourneyDestination(storage, destination) {
1093
1146
  const guard = async (id) => {
1094
1147
  if (!verified.has(id)) await current(id);
1095
1148
  };
1149
+ const readStatus = async (input) => {
1150
+ await guard(input.journeyId);
1151
+ return storage.sessionReviewStatus(input);
1152
+ };
1096
1153
  return {
1097
1154
  current,
1098
1155
  readInventory: (input) => storage.readInventory({
@@ -1208,10 +1265,7 @@ function bindJourneyDestination(storage, destination) {
1208
1265
  await guard(input.journeyId);
1209
1266
  return storage.reviewAttempts(input);
1210
1267
  },
1211
- async sessionReviewStatus(input) {
1212
- await guard(input.journeyId);
1213
- return storage.sessionReviewStatus(input);
1214
- },
1268
+ sessionReviewStatus: options.statusPolling ? paceSessionStatus(readStatus, options.signal) : readStatus,
1215
1269
  async submitReview(input) {
1216
1270
  await guard(input.journeyId);
1217
1271
  return storage.submitReview(input);
@@ -11373,7 +11427,11 @@ async function compose(options, callbacks, bundles) {
11373
11427
  onDiagnostic: producers.onHarnessDiagnostic
11374
11428
  });
11375
11429
  if (!store.journey || !store.journeySend || !store.manualUpload) throw new Error("CORRUPTED_STATE");
11376
- const journeyStorage = bindJourneyDestination(store.journey, options.passportApiUrl);
11430
+ const statusPolling = new AbortController();
11431
+ const journeyStorage = bindJourneyDestination(store.journey, options.passportApiUrl, {
11432
+ statusPolling: callbacks.servingHost === true,
11433
+ signal: statusPolling.signal
11434
+ });
11377
11435
  const sendStorage = bindSendDestination(store.journeySend, options.passportApiUrl);
11378
11436
  const sessionWorkers = {
11379
11437
  ...options.parallelism === void 0 ? {} : { parallelism: options.parallelism },
@@ -11530,6 +11588,7 @@ async function compose(options, callbacks, bundles) {
11530
11588
  });
11531
11589
  let closed;
11532
11590
  const close = () => closed ??= (async () => {
11591
+ statusPolling.abort();
11533
11592
  if (fatalStore.failed) await fatalStore.guardCleanup();
11534
11593
  const failures = [];
11535
11594
  const steps = [
@@ -1,4 +1,4 @@
1
- import { i as createExecutor, t as assertStoreHeap } from "./heap-DQbsSUrB.mjs";
1
+ import { i as createExecutor, t as assertStoreHeap } from "./heap-lJNgbnRz.mjs";
2
2
  import { parentPort } from "node:worker_threads";
3
3
  //#region packages/local-host/src/store/worker/entry.ts
4
4
  if (!parentPort) throw new Error("STORE_WORKER_REQUIRED");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitroll/tacitt-cli",
3
- "version": "0.6.4",
3
+ "version": "0.6.5",
4
4
  "description": "Private local session review and export for coding agents",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {