priiisk 0.1.7 → 0.1.8

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.
@@ -28,7 +28,7 @@ import {
28
28
  makePlatform,
29
29
  makeRunMain,
30
30
  stdin
31
- } from "./chunk-JND6HOSJ.js";
31
+ } from "./chunk-W2ZL6LWM.js";
32
32
  import {
33
33
  BaseProto,
34
34
  __export,
@@ -112,7 +112,7 @@ import {
112
112
  write,
113
113
  zip,
114
114
  zipRight
115
- } from "./chunk-3V5SHVCX.js";
115
+ } from "./chunk-TZBPOE6G.js";
116
116
 
117
117
  // node_modules/.pnpm/@effect+platform-node@0.107.0_@effect+cluster@0.59.0_@effect+platform@0.96.2_effect@3.2_9535e05eb804fa0fb275ce283b448483/node_modules/@effect/platform-node/dist/esm/NodeContext.js
118
118
  var NodeContext_exports = {};
@@ -86,8 +86,8 @@ import {
86
86
  selectCampRun,
87
87
  styleCampUiTone,
88
88
  uniqueCampUiNames
89
- } from "./chunk-YOW4MMBD.js";
90
- import "./chunk-3V5SHVCX.js";
89
+ } from "./chunk-S7LCWMQY.js";
90
+ import "./chunk-TZBPOE6G.js";
91
91
  export {
92
92
  CAMP_UI_BASH_PREVIEW_LINES,
93
93
  CAMP_UI_DEFAULT_TOOL_PREVIEW_LINES,
@@ -20,10 +20,11 @@ import {
20
20
  layerNet,
21
21
  makeCampSurfaceName,
22
22
  resolveProjectScopeSync
23
- } from "./chunk-JND6HOSJ.js";
23
+ } from "./chunk-W2ZL6LWM.js";
24
24
  import {
25
25
  Clock_exports,
26
26
  Config_exports,
27
+ Console_exports,
27
28
  Context_exports,
28
29
  Data_exports,
29
30
  Deferred_exports,
@@ -37,7 +38,7 @@ import {
37
38
  Schedule_exports,
38
39
  Schema_exports,
39
40
  Stream_exports
40
- } from "./chunk-3V5SHVCX.js";
41
+ } from "./chunk-TZBPOE6G.js";
41
42
 
42
43
  // packages/cli/src/doctor/doctorModel.ts
43
44
  var DOCTOR_REPORT_SCHEMA_VERSION = 1;
@@ -111,9 +112,12 @@ var CliSurfaceSelectionError = class extends Data_exports.TaggedError("CliSurfac
111
112
  import { randomUUID } from "node:crypto";
112
113
 
113
114
  // packages/cli/src/domain/cliVersion.ts
114
- var PRIIISK_CLI_VERSION = "0.1.7";
115
+ var PRIIISK_CLI_VERSION = "0.1.8";
115
116
 
116
117
  // packages/cli/src/client/campRpcConnection.ts
118
+ var reportRetry = (options, diagnostic) => options.onRetry === void 0 ? Console_exports.error(
119
+ `[retry] ${diagnostic.operation}: \u043F\u043E\u043F\u044B\u0442\u043A\u0430 ${String(diagnostic.attempt)}, \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0430\u044F \u0432 ${String(diagnostic.nextRetryAt)} \u2014 ${diagnostic.message}`
120
+ ).pipe(Effect_exports.ignore) : options.onRetry(diagnostic);
117
121
  var PRIIISK_CONTROLLER_ID_ENV = "PRIIISK_CONTROLLER_ID";
118
122
  var PRIIISK_CONSUMER_ID_ENV = "PRIIISK_CONSUMER_ID";
119
123
  var protocolRetrySchedule = Schedule_exports.exponential("50 millis").pipe(
@@ -151,12 +155,12 @@ var makeCampProtocolLayer = (socketPath, options) => Effect_exports.gen(function
151
155
  Effect_exports.flatMap(
152
156
  ({ attempt, cause }) => Clock_exports.currentTimeMillis.pipe(
153
157
  Effect_exports.flatMap(
154
- (now) => options.onRetry?.({
158
+ (now) => reportRetry(options, {
155
159
  operation: options.operation,
156
160
  attempt,
157
161
  nextRetryAt: now + 50 * 2 ** (attempt - 1),
158
162
  message: cause instanceof Error ? cause.message : String(cause)
159
- }) ?? Effect_exports.void
163
+ })
160
164
  )
161
165
  )
162
166
  )
@@ -3,7 +3,7 @@ const require = __priiiskCreateRequire(import.meta.url);
3
3
  import {
4
4
  FileSystem_exports,
5
5
  PRIIISK_PI_AGENT_DIR_ENV
6
- } from "./chunk-JND6HOSJ.js";
6
+ } from "./chunk-W2ZL6LWM.js";
7
7
  import {
8
8
  CampDeliveryPort,
9
9
  CampFailureCode,
@@ -30,7 +30,7 @@ import {
30
30
  __require,
31
31
  __toESM,
32
32
  campScopeClosedReason
33
- } from "./chunk-3V5SHVCX.js";
33
+ } from "./chunk-TZBPOE6G.js";
34
34
 
35
35
  // node_modules/.pnpm/undici@7.28.0/node_modules/undici/lib/core/symbols.js
36
36
  var require_symbols = __commonJS({
@@ -26557,14 +26557,30 @@ var makePiSessionRuntime = (options) => Effect_exports.gen(function* () {
26557
26557
  /*
26558
26558
  * Aborting ends the turn, not the session: the terminal signal stays
26559
26559
  * untouched, so the worker survives its interruption and the next
26560
- * message starts a new turn. Committing the cycle first keeps the late
26561
- * agent_end/agent_settled of the abandoned turn from settling it.
26560
+ * message starts a new turn. The cycle is committed first, because the
26561
+ * late agent_end/agent_settled of the abandoned turn must not settle it.
26562
+ *
26563
+ * An adapter that refuses the abort leaves the turn running, so the
26564
+ * commit is rolled back: otherwise the worker would keep working while
26565
+ * its own settled events were ignored as belonging to a finished cycle
26566
+ * (priiisk-nss.6.27).
26562
26567
  */
26563
26568
  abort: (sessionRef) => requireLive(sessionRef, PiSessionOperation.abort).pipe(
26564
26569
  Effect_exports.flatMap(
26565
- (live) => commitCurrentCycle(live).pipe(
26566
- Effect_exports.zipRight(
26567
- run(live, PiSessionOperation.abort, () => live.runtime.session.abort())
26570
+ (live) => Ref_exports.get(live.lifecycle).pipe(
26571
+ Effect_exports.flatMap(
26572
+ (before) => commitCurrentCycle(live).pipe(
26573
+ Effect_exports.zipRight(
26574
+ run(live, PiSessionOperation.abort, () => live.runtime.session.abort())
26575
+ ),
26576
+ Effect_exports.tapError(
26577
+ () => Ref_exports.update(live.lifecycle, (state) => ({
26578
+ cycle: state.cycle,
26579
+ providerAttempts: state.providerAttempts,
26580
+ ...before.committedCycle === void 0 ? {} : { committedCycle: before.committedCycle }
26581
+ }))
26582
+ )
26583
+ )
26568
26584
  )
26569
26585
  )
26570
26586
  )
@@ -12,7 +12,7 @@ import {
12
12
  Match_exports,
13
13
  Stream_exports,
14
14
  SubscriptionRef_exports
15
- } from "./chunk-3V5SHVCX.js";
15
+ } from "./chunk-TZBPOE6G.js";
16
16
 
17
17
  // packages/host-ui/src/backend/campUiBackend.ts
18
18
  var CampUiBackendError = class extends Data_exports.TaggedError("CampUiBackendError") {
@@ -8,13 +8,13 @@ import {
8
8
  makeDoctorReport,
9
9
  resolveCampSurface,
10
10
  withCampRpc
11
- } from "./chunk-ZUREJQA6.js";
11
+ } from "./chunk-FZQM7AKO.js";
12
12
  import {
13
13
  PI_RUNTIME_VERSION,
14
14
  PiModelCatalogIssueCode,
15
15
  inspectPiModelCatalog,
16
16
  makePiOperatorResources
17
- } from "./chunk-WEYE43UO.js";
17
+ } from "./chunk-OWFOOE7W.js";
18
18
  import {
19
19
  CampHealthComponentStatus,
20
20
  CampHealthOverallStatus,
@@ -48,13 +48,13 @@ import {
48
48
  resolveCredentialsPath,
49
49
  resolveProjectScope,
50
50
  resolveWorkerConfigPath
51
- } from "./chunk-JND6HOSJ.js";
51
+ } from "./chunk-W2ZL6LWM.js";
52
52
  import {
53
53
  Clock_exports,
54
54
  Effect_exports,
55
55
  Option_exports,
56
56
  Ref_exports
57
- } from "./chunk-3V5SHVCX.js";
57
+ } from "./chunk-TZBPOE6G.js";
58
58
 
59
59
  // packages/cli/src/doctor/environmentDoctor.ts
60
60
  import { dirname } from "node:path";
@@ -41892,6 +41892,15 @@ var CampWorkerInterrupted = class extends Data_exports.TaggedError("CampWorkerIn
41892
41892
  };
41893
41893
  var CampWorkerTerminated = class extends Data_exports.TaggedError("CampWorkerTerminated") {
41894
41894
  };
41895
+ var campTurnFailureReason = (outcome) => {
41896
+ if (outcome.stopReason !== CampTurnStopReason.error && outcome.failureCode === void 0) {
41897
+ return void 0;
41898
+ }
41899
+ return {
41900
+ code: outcome.failureCode === void 0 ? CampFailureCode.unknown : CampFailureCode.providerError,
41901
+ message: outcome.errorMessage ?? "turn ended with an error"
41902
+ };
41903
+ };
41895
41904
 
41896
41905
  // packages/kernel/src/domain/campTopology.ts
41897
41906
  var CampChildClosePolicy = { cascade: "cascade", detach: "detach" };
@@ -43396,9 +43405,11 @@ var handleSessionEvent = (runtime6, id3, event) => Effect_exports.gen(function*
43396
43405
  );
43397
43406
  return { kind: "retrying", worker: worker2, payload: event.payload };
43398
43407
  }
43408
+ const turnError = event.kind === CampSessionEventKind.turnCompleted ? campTurnFailureReason(event.payload.outcome) : void 0;
43399
43409
  const worker = yield* runtime6.registry.updateTimestamps(id3, {
43400
43410
  updatedAt,
43401
- lastActivityAt: updatedAt
43411
+ lastActivityAt: updatedAt,
43412
+ ...event.kind === CampSessionEventKind.turnCompleted ? { turnError: turnError ?? null } : {}
43402
43413
  });
43403
43414
  if (event.kind === CampSessionEventKind.activity) {
43404
43415
  return { kind: "activity", worker, payload: event.payload };
@@ -43910,13 +43921,15 @@ var makeRegistryLifecycleOperations = (stateRef) => ({
43910
43921
  if (isTerminalCampState(record4.state) || record4.state === CampWorkerState.interrupted) {
43911
43922
  return mutationFailure(registryInvalid("registry.updateTimestamps", { id: id3 }), state);
43912
43923
  }
43924
+ const carried = input.turnError === null ? Object.fromEntries(Object.entries(record4).filter(([key]) => key !== "error")) : record4;
43913
43925
  const next4 = {
43914
- ...record4,
43926
+ ...carried,
43915
43927
  updatedAt: input.updatedAt,
43916
43928
  version: record4.version + 1,
43917
43929
  ...input.admittedAt === void 0 ? {} : { admittedAt: input.admittedAt },
43918
43930
  ...input.startedAt === void 0 ? {} : { startedAt: input.startedAt },
43919
- ...input.lastActivityAt === void 0 ? {} : { lastActivityAt: input.lastActivityAt }
43931
+ ...input.lastActivityAt === void 0 ? {} : { lastActivityAt: input.lastActivityAt },
43932
+ ...input.turnError === void 0 || input.turnError === null ? {} : { error: input.turnError }
43920
43933
  };
43921
43934
  return mutationSuccess(next4, {
43922
43935
  ...state,
@@ -366,7 +366,7 @@ import {
366
366
  write,
367
367
  zipRight,
368
368
  zipRight2
369
- } from "./chunk-3V5SHVCX.js";
369
+ } from "./chunk-TZBPOE6G.js";
370
370
 
371
371
  // node_modules/.pnpm/detect-libc@2.1.2/node_modules/detect-libc/lib/process.js
372
372
  var require_process = __commonJS({
@@ -10678,7 +10678,7 @@ var describeDirectToolSandbox = (sandbox2) => sandbox2.kind === DirectToolSandbo
10678
10678
 
10679
10679
  // packages/protocol/src/domain/protocolVersion.ts
10680
10680
  var PRIIISK_PROTOCOL_VERSION = "11";
10681
- var PRIIISK_PROTOCOL_PACKAGE_VERSION = "0.1.7";
10681
+ var PRIIISK_PROTOCOL_PACKAGE_VERSION = "0.1.8";
10682
10682
  var ProtocolVersionSchema = Schema_exports.String.pipe(Schema_exports.minLength(1));
10683
10683
 
10684
10684
  // packages/protocol/src/domain/protocolIdentifiers.ts
@@ -13553,7 +13553,7 @@ var CampProtocol = class extends RpcGroup_exports.make(
13553
13553
  };
13554
13554
 
13555
13555
  // packages/camp-state/src/bootstrap/campHostVersion.ts
13556
- var PRIIISK_HOST_VERSION = "0.1.7";
13556
+ var PRIIISK_HOST_VERSION = "0.1.8";
13557
13557
 
13558
13558
  // packages/surface/src/domain/surfaceModel.ts
13559
13559
  var NonEmptyString7 = Schema_exports.String.pipe(Schema_exports.minLength(1));
@@ -14497,12 +14497,27 @@ var CampRunCatalogErrorCode = {
14497
14497
  notFound: "run_not_found",
14498
14498
  notResumable: "run_not_resumable",
14499
14499
  persistenceFailed: "persistence_failed",
14500
+ /**
14501
+ * Checkpoint написан другой версией схемы. Общий `persistence_failed` описывал
14502
+ * бы это как поломку хранилища, тогда как лечение другое и уже названо в
14503
+ * контракте recovery: свежий запуск либо обновление рантайма
14504
+ * (priiisk-nss.6.23).
14505
+ */
14506
+ checkpointUnsupported: "checkpoint_unsupported",
14500
14507
  scopeMismatch: "scope_mismatch"
14501
14508
  };
14502
14509
  var CampRunCatalogError = class extends Data_exports.TaggedError("CampRunCatalogError") {
14503
14510
  };
14504
14511
  var isCampRunResumable = (manifest) => manifest.workers.some((worker) => worker.session.lifecycle !== "pending");
14505
14512
 
14513
+ // packages/camp-state/src/history/campRunCatalogFailures.ts
14514
+ var manifestReadFailure = (operation, message, cause) => new CampRunCatalogError({
14515
+ operation,
14516
+ code: cause instanceof CampManifestVersionError ? CampRunCatalogErrorCode.checkpointUnsupported : CampRunCatalogErrorCode.persistenceFailed,
14517
+ message,
14518
+ ...cause === void 0 ? {} : { cause }
14519
+ });
14520
+
14506
14521
  // packages/camp-state/src/history/campRunCatalog.ts
14507
14522
  var catalogError = (operation, code, message, cause) => new CampRunCatalogError({
14508
14523
  operation,
@@ -14527,12 +14542,7 @@ var summary = (manifest, active) => ({
14527
14542
  });
14528
14543
  var loadRequired = (fs, path, operation) => loadCampManifest(fs, path).pipe(
14529
14544
  Effect_exports.mapError(
14530
- (cause) => catalogError(
14531
- operation,
14532
- CampRunCatalogErrorCode.persistenceFailed,
14533
- `\u043D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u0442\u044C camp run: ${path}`,
14534
- cause
14535
- )
14545
+ (cause) => manifestReadFailure(operation, `\u043D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u0442\u044C camp run: ${path}`, cause)
14536
14546
  ),
14537
14547
  Effect_exports.flatMap(
14538
14548
  Option_exports.match({
@@ -14556,12 +14566,7 @@ var pathExists = (fs, path, operation) => fs.exists(path).pipe(
14556
14566
  var listCampRuns = (fs, project, paths) => Effect_exports.gen(function* () {
14557
14567
  const active = yield* loadCampManifest(fs, paths.manifestPath).pipe(
14558
14568
  Effect_exports.mapError(
14559
- (cause) => catalogError(
14560
- "list",
14561
- CampRunCatalogErrorCode.persistenceFailed,
14562
- "\u043D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u0442\u044C active camp run",
14563
- cause
14564
- )
14569
+ (cause) => manifestReadFailure("list", "\u043D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u0442\u044C active camp run", cause)
14565
14570
  )
14566
14571
  );
14567
14572
  if (Option_exports.isSome(active)) yield* validateScope("list", project, active.value);
@@ -4,14 +4,14 @@ const require = __priiiskCreateRequire(import.meta.url);
4
4
  import {
5
5
  NodeContext_exports,
6
6
  NodeRuntime_exports
7
- } from "./chunk-7U7PROSV.js";
7
+ } from "./chunk-4V3HXXQ6.js";
8
8
  import {
9
9
  CampUiBackendError,
10
10
  CampUiHealthStatus,
11
11
  CampUiPlacement,
12
12
  CampUiRuntimeStatus,
13
13
  mountPiCampUi
14
- } from "./chunk-YOW4MMBD.js";
14
+ } from "./chunk-S7LCWMQY.js";
15
15
  import {
16
16
  PiTransport,
17
17
  makePiOperatorResources,
@@ -19,7 +19,7 @@ import {
19
19
  makePiTransportLayer,
20
20
  requirePiModelCatalog,
21
21
  require_undici
22
- } from "./chunk-WEYE43UO.js";
22
+ } from "./chunk-OWFOOE7W.js";
23
23
  import {
24
24
  AgentRole,
25
25
  AgentRoleSchema,
@@ -100,7 +100,7 @@ import {
100
100
  runningCampManifest,
101
101
  saveCampHealth,
102
102
  saveCampManifest
103
- } from "./chunk-JND6HOSJ.js";
103
+ } from "./chunk-W2ZL6LWM.js";
104
104
  import {
105
105
  CampAskRouter,
106
106
  CampCancellationCode,
@@ -193,7 +193,7 @@ import {
193
193
  withFiberRuntime,
194
194
  workerAliasIdentity,
195
195
  workerIdIdentity
196
- } from "./chunk-3V5SHVCX.js";
196
+ } from "./chunk-TZBPOE6G.js";
197
197
 
198
198
  // node_modules/.pnpm/ws@8.21.1/node_modules/ws/lib/constants.js
199
199
  var require_constants = __commonJS({
@@ -12788,23 +12788,38 @@ var stableJson = (value) => {
12788
12788
  const entries = Object.entries(value).filter(([, entry]) => entry !== void 0).sort(([left], [right]) => left.localeCompare(right));
12789
12789
  return `{${entries.map(([key, entry]) => `${JSON.stringify(key)}:${stableJson(entry)}`).join(",")}}`;
12790
12790
  };
12791
+ var durableFailureSummary = (cause) => {
12792
+ const code = cause?.code;
12793
+ if (typeof code === "string" && code !== "") return code;
12794
+ const name = cause instanceof Error ? cause.name : void 0;
12795
+ return name === void 0 || name === "" ? "unknown" : name;
12796
+ };
12791
12797
  var receiptPersistenceFailure = (operation, cause) => new CampCommandFailure({
12792
12798
  operation,
12793
12799
  code: CampReceiptFailureCode.persistenceFailed,
12794
- message: `command receipt could not be made durable: ${String(cause)}`,
12795
- retryable: true
12800
+ message: `command receipt could not be made durable (${durableFailureSummary(cause)})`,
12801
+ retryable: true,
12802
+ recoveryAction: "manual_recovery"
12796
12803
  });
12797
12804
  var loadCampReceipts = (fs, path, runId) => fs.exists(path).pipe(
12798
12805
  Effect_exports.flatMap((exists) => exists ? fs.readFileString(path) : Effect_exports.succeed(void 0)),
12799
12806
  Effect_exports.flatMap(
12800
- (contents) => contents === void 0 ? Effect_exports.succeed([]) : Effect_exports.try(() => JSON.parse(contents)).pipe(
12807
+ (contents) => contents === void 0 ? Effect_exports.succeed({ receipts: [] }) : Effect_exports.try(() => JSON.parse(contents)).pipe(
12801
12808
  Effect_exports.flatMap(decodeState),
12802
12809
  Effect_exports.map(
12803
- (state) => state.schemaVersion === CAMP_RECEIPT_SCHEMA_VERSION && state.runId === runId ? state.receipts : []
12810
+ (state) => state.schemaVersion === CAMP_RECEIPT_SCHEMA_VERSION && state.runId === runId ? { receipts: state.receipts } : {
12811
+ receipts: [],
12812
+ unreadable: state.runId === runId ? "unsupported_schema_version" : "foreign_run"
12813
+ }
12814
+ ),
12815
+ Effect_exports.catchAll(
12816
+ () => Effect_exports.succeed({ receipts: [], unreadable: "corrupt" })
12804
12817
  )
12805
12818
  )
12806
12819
  ),
12807
- Effect_exports.catchAll(() => Effect_exports.succeed([]))
12820
+ Effect_exports.catchAll(
12821
+ () => Effect_exports.succeed({ receipts: [], unreadable: "unreadable" })
12822
+ )
12808
12823
  );
12809
12824
  var saveCampReceipts = (fs, path, runId, receipts) => {
12810
12825
  const temporaryPath = `${path}.${randomUUID2()}.tmp`;
@@ -12888,9 +12903,15 @@ var makeCampCommandReceiptStoreLayer = (options) => Layer_exports.scoped(
12888
12903
  const retentionMillis = (options.retentionSeconds ?? CAMP_RECEIPT_DEFAULT_RETENTION_SECONDS) * 1e3;
12889
12904
  const restoredAt = yield* Clock_exports.currentTimeMillis;
12890
12905
  const restored = yield* loadCampReceipts(fs, options.statePath, journal.runId);
12891
- const state = yield* Ref_exports.make(campReceiptStateFromRecords(restored, restoredAt));
12906
+ const state = yield* Ref_exports.make(campReceiptStateFromRecords(restored.receipts, restoredAt));
12892
12907
  const inFlight = yield* Ref_exports.make(/* @__PURE__ */ new Map());
12893
- const lastFailure = yield* Ref_exports.make(void 0);
12908
+ const lastFailure = yield* Ref_exports.make(
12909
+ restored.unreadable === void 0 ? void 0 : receiptFailure(
12910
+ "restore",
12911
+ CampReceiptFailureCode.unreadable,
12912
+ `durable command receipts were not restored (${restored.unreadable})`
12913
+ )
12914
+ );
12894
12915
  const changes = yield* PubSub_exports.sliding(1);
12895
12916
  const lane = yield* Effect_exports.makeSemaphore(1);
12896
12917
  const publish = PubSub_exports.publish(changes, void 0).pipe(Effect_exports.asVoid);
@@ -22416,7 +22437,7 @@ var Client = class extends Protocol {
22416
22437
  };
22417
22438
 
22418
22439
  // packages/mcp-backend/src/connections/clientIdentity.ts
22419
- var backendVersion = "0.1.7";
22440
+ var backendVersion = "0.1.8";
22420
22441
 
22421
22442
  // packages/mcp-backend/src/connections/mcpFailure.ts
22422
22443
  var McpFailure = class extends Data_exports.TaggedError("McpFailure") {
@@ -25399,6 +25420,7 @@ var readSegmentText = (fs, path) => fs.readFileString(path).pipe(
25399
25420
  var loadJournalSegment = (fs, path, expected) => readSegmentText(fs, path).pipe(
25400
25421
  Effect_exports.flatMap((text) => {
25401
25422
  const totalBytes = Buffer.byteLength(text, "utf8");
25423
+ const endsWithNewline = text.endsWith("\n");
25402
25424
  const lines = text.split("\n");
25403
25425
  if (lines[lines.length - 1] === "") lines.pop();
25404
25426
  const headerLine = lines[0];
@@ -25408,7 +25430,8 @@ var loadJournalSegment = (fs, path, expected) => readSegmentText(fs, path).pipe(
25408
25430
  firstCursor: expected.firstCursor,
25409
25431
  events: [],
25410
25432
  validBytes: 0,
25411
- totalBytes
25433
+ totalBytes,
25434
+ truncatedTail: false
25412
25435
  });
25413
25436
  }
25414
25437
  const headerJson = parseJson(headerLine);
@@ -25419,7 +25442,9 @@ var loadJournalSegment = (fs, path, expected) => readSegmentText(fs, path).pipe(
25419
25442
  firstCursor: expected.firstCursor,
25420
25443
  events: [],
25421
25444
  validBytes: 0,
25422
- totalBytes
25445
+ totalBytes,
25446
+ /* Заголовок целиком записан, но нечитаем: это повреждение, не обрыв. */
25447
+ truncatedTail: lines.length === 1 && !endsWithNewline
25423
25448
  });
25424
25449
  }
25425
25450
  if (header.right.schemaVersion > CAMP_JOURNAL_SCHEMA_VERSION) {
@@ -25454,12 +25479,19 @@ var loadJournalSegment = (fs, path, expected) => readSegmentText(fs, path).pipe(
25454
25479
  }
25455
25480
  const events = [];
25456
25481
  let validBytes = lineBytes(headerLine);
25482
+ let stoppedAt;
25457
25483
  for (let index = 1; index < lines.length; index += 1) {
25458
25484
  const line = lines[index] ?? "";
25459
25485
  const parsed = parseJson(line);
25460
25486
  const decoded = parsed === void 0 ? void 0 : decodeEvent(parsed);
25461
- if (decoded === void 0 || Either_exports.isLeft(decoded)) break;
25462
- if (decoded.right.cursor !== expected.firstCursor + events.length) break;
25487
+ if (decoded === void 0 || Either_exports.isLeft(decoded)) {
25488
+ stoppedAt = index;
25489
+ break;
25490
+ }
25491
+ if (decoded.right.cursor !== expected.firstCursor + events.length) {
25492
+ stoppedAt = index;
25493
+ break;
25494
+ }
25463
25495
  events.push(decoded.right);
25464
25496
  validBytes += lineBytes(line);
25465
25497
  }
@@ -25468,7 +25500,14 @@ var loadJournalSegment = (fs, path, expected) => readSegmentText(fs, path).pipe(
25468
25500
  firstCursor: expected.firstCursor,
25469
25501
  events,
25470
25502
  validBytes,
25471
- totalBytes
25503
+ totalBytes,
25504
+ /*
25505
+ * Обрезать можно только оборванную последнюю запись: она одна осталась
25506
+ * после валидного префикса и не завершена переводом строки. Если после
25507
+ * сбойной записи есть другие или сама она дописана до конца, это
25508
+ * повреждение внутри файла, и обрезка стерла бы durable историю.
25509
+ */
25510
+ truncatedTail: stoppedAt === lines.length - 1 && !endsWithNewline
25472
25511
  });
25473
25512
  })
25474
25513
  );
@@ -25552,6 +25591,16 @@ var restoreCampJournal = (fs, options) => Effect_exports.gen(function* () {
25552
25591
  )
25553
25592
  );
25554
25593
  }
25594
+ if (!loaded.truncatedTail) {
25595
+ return yield* Effect_exports.fail(
25596
+ campJournalError(
25597
+ "open",
25598
+ CampJournalErrorCode.corrupted,
25599
+ "journal segment is damaged inside its last segment",
25600
+ { path }
25601
+ )
25602
+ );
25603
+ }
25555
25604
  yield* truncateSegment(fs, path, loaded.validBytes);
25556
25605
  }
25557
25606
  if (loaded.validBytes === 0) {
@@ -25683,10 +25732,9 @@ var makeCampJournalWriter = (fs, options, restored) => Effect_exports.gen(functi
25683
25732
  const event = CampEventDtoSchema.make({ ...draft, cursor });
25684
25733
  yield* writeLine(active.segment, journalEventLine(event));
25685
25734
  yield* SubscriptionRef_exports.update(state, (latest) => {
25686
- const { lastFailure: _lastFailure, ...healthy } = latest;
25687
25735
  const records = (active.segments[active.segments.length - 1]?.records ?? 0) + 1;
25688
25736
  return {
25689
- ...healthy,
25737
+ ...latest,
25690
25738
  segments: withRecords(active.segments, records),
25691
25739
  latestCursor: cursor
25692
25740
  };
@@ -26259,13 +26307,26 @@ var CampRpcHandlersLive = CampProtocol.toLayer(
26259
26307
  )
26260
26308
  )
26261
26309
  ),
26310
+ /*
26311
+ * Interrupt is a mutating command like the rest, so it goes through the
26312
+ * receipt: a repeat of the same `commandId` answers with the recorded
26313
+ * result instead of aborting a turn twice, and a stale generation is
26314
+ * refused before the side effect (priiisk-nss.6.24).
26315
+ */
26262
26316
  Interrupt: (request) => validateReady(request).pipe(
26263
26317
  Effect_exports.zipRight(
26264
- operations.interrupt(commandContext(request), workerIdentityFromDto(request.worker))
26265
- ),
26266
- Effect_exports.as({ accepted: true }),
26267
- Effect_exports.mapError(
26268
- (error2) => error2 instanceof ProtocolVersionMismatch || error2 instanceof ProjectScopeMismatch ? error2 : failureFromKernel("interrupt", error2)
26318
+ receipts.run(
26319
+ {
26320
+ identity: commandIdentity(request),
26321
+ operation: "interrupt",
26322
+ payload: { worker: request.worker },
26323
+ schema: CampAckSchema
26324
+ },
26325
+ operations.interrupt(commandContext(request), workerIdentityFromDto(request.worker)).pipe(
26326
+ Effect_exports.as(CampAckSchema.make({ accepted: true })),
26327
+ Effect_exports.mapError((error2) => failureFromKernel("interrupt", error2))
26328
+ )
26329
+ )
26269
26330
  )
26270
26331
  ),
26271
26332
  OpenWorker: (request) => validateReady(request).pipe(
@@ -26721,6 +26782,26 @@ var acquireLiveCampHost = (options = {}) => Effect_exports.gen(function* () {
26721
26782
  piResources.modelRegistry,
26722
26783
  { authDiagnosticCodes: piResources.authDiagnosticCodes ?? [] }
26723
26784
  );
26785
+ const reportStartupJournalFailure = (cause) => cause instanceof CampJournalError ? Clock_exports.currentTimeMillis.pipe(
26786
+ Effect_exports.flatMap(
26787
+ (now) => saveCampHealth(fs, paths.healthPath, {
26788
+ ...initialCampHealthSnapshot(project.hash, "startup", now),
26789
+ overallStatus: CampHealthOverallStatus.failed,
26790
+ components: [
26791
+ {
26792
+ id: CAMP_JOURNAL_HEALTH_COMPONENT,
26793
+ category: CampHealthComponentCategory.controller,
26794
+ status: CampHealthComponentStatus.failed,
26795
+ code: cause.code,
26796
+ operation: "controller.journal.open",
26797
+ message: cause.message,
26798
+ updatedAt: now
26799
+ }
26800
+ ]
26801
+ })
26802
+ ),
26803
+ Effect_exports.ignore
26804
+ ) : Effect_exports.void;
26724
26805
  const context = yield* Layer_exports.build(
26725
26806
  makeLiveCampHostLayer({
26726
26807
  project,
@@ -26740,7 +26821,7 @@ var acquireLiveCampHost = (options = {}) => Effect_exports.gen(function* () {
26740
26821
  receiptsPath: campRunPaths(paths, options.manifestRunId).receiptsPath
26741
26822
  }
26742
26823
  })
26743
- );
26824
+ ).pipe(Effect_exports.tapError(reportStartupJournalFailure));
26744
26825
  const kernel = Context_exports.get(context, CampKernel);
26745
26826
  const asks = Context_exports.get(context, CampAskRouter);
26746
26827
  const health = Context_exports.get(context, CampHostHealth);
package/dist/priiisk.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  fromReadable,
6
6
  layer,
7
7
  runMain
8
- } from "./chunk-7U7PROSV.js";
8
+ } from "./chunk-4V3HXXQ6.js";
9
9
  import {
10
10
  CliCampLifecycleError,
11
11
  CliEquipmentConflict,
@@ -23,7 +23,7 @@ import {
23
23
  resolveCampSurface,
24
24
  withCampRpc,
25
25
  withCampRpcSession
26
- } from "./chunk-ZUREJQA6.js";
26
+ } from "./chunk-FZQM7AKO.js";
27
27
  import {
28
28
  CampCommandFailure,
29
29
  CampHostReadiness,
@@ -58,7 +58,7 @@ import {
58
58
  resolveProjectScopeSync,
59
59
  saveCampManifest,
60
60
  startingCampManifest
61
- } from "./chunk-JND6HOSJ.js";
61
+ } from "./chunk-W2ZL6LWM.js";
62
62
  import {
63
63
  Cause_exports,
64
64
  CommitPrototype,
@@ -239,7 +239,7 @@ import {
239
239
  zipLeft,
240
240
  zipRight,
241
241
  zipWith
242
- } from "./chunk-3V5SHVCX.js";
242
+ } from "./chunk-TZBPOE6G.js";
243
243
 
244
244
  // node_modules/.pnpm/ini@4.1.3/node_modules/ini/lib/ini.js
245
245
  var require_ini = __commonJS({
@@ -18637,9 +18637,11 @@ var equipmentLines = (equipment, revision) => [
18637
18637
  ` mcp: ${mcpGrants(equipment.mcp)}`,
18638
18638
  ` skills: ${names([...equipment.skillNames])}`
18639
18639
  ];
18640
+ var WORKER_ERROR_LIMIT = 160;
18640
18641
  var formatWorker = (worker) => {
18641
18642
  const alias = worker.alias === void 0 ? "" : ` (${worker.alias})`;
18642
- const headline = `${worker.workerId}${alias}: ${worker.state}, session ${worker.sessionState}`;
18643
+ const failure2 = worker.error === void 0 ? "" : ` \u2014 \u043F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u0439 \u0445\u043E\u0434: ${worker.error.code}: ${worker.error.message.slice(0, WORKER_ERROR_LIMIT)}`;
18644
+ const headline = `${worker.workerId}${alias}: ${worker.state}, session ${worker.sessionState}${failure2}`;
18643
18645
  return worker.equipment === void 0 ? headline : [headline, ...equipmentLines(worker.equipment, worker.equipmentVersion)].join("\n");
18644
18646
  };
18645
18647
  var printWorkers = (json) => (effect) => effect.pipe(
@@ -19094,7 +19096,9 @@ var resolveMessageText = (operation, text11, file6) => {
19094
19096
  );
19095
19097
  }
19096
19098
  if (Option_exports.isSome(file6)) return readMessageFile(operation, file6.value);
19097
- if (Option_exports.isSome(text11)) return Effect_exports.succeed(text11.value);
19099
+ if (Option_exports.isSome(text11)) {
19100
+ return text11.value.trim().length === 0 ? Effect_exports.fail(failure(operation, "message_empty", "\u0422\u0435\u043A\u0441\u0442 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u044F \u043F\u0443\u0441\u0442")) : Effect_exports.succeed(text11.value);
19101
+ }
19098
19102
  return Effect_exports.fail(
19099
19103
  failure(operation, "message_source_missing", "\u041D\u0443\u0436\u0435\u043D \u0442\u0435\u043A\u0441\u0442 \u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u043E\u043C \u043B\u0438\u0431\u043E --file <path>")
19100
19104
  );
@@ -19948,7 +19952,7 @@ var campResumeListCommand = Command_exports.make(
19948
19952
  )
19949
19953
  ).pipe(Command_exports.withDescription("Lists saved runs of this project that resume can restore."));
19950
19954
  var runIdArgument = Args_exports.text({ name: "runId" }).pipe(Args_exports.optional);
19951
- var selectCampRunOnDemand = (items) => Effect_exports.promise(() => import("./chunk-VLP2ZKVV.js")).pipe(
19955
+ var selectCampRunOnDemand = (items) => Effect_exports.promise(() => import("./chunk-BXVX5A4M.js")).pipe(
19952
19956
  Effect_exports.flatMap((ui) => ui.selectCampRun({ items }))
19953
19957
  );
19954
19958
  var selectAndResume = (json) => {
@@ -20021,7 +20025,7 @@ var rootCommand = Command_exports.make(
20021
20025
  ).pipe(Command_exports.withDescription("Runs and observes a camp of collaborating workers."));
20022
20026
 
20023
20027
  // packages/cli/src/commands/doctorCommand.ts
20024
- var runDoctorOnDemand = Effect_exports.promise(() => import("./chunk-4VQ2KUN7.js")).pipe(
20028
+ var runDoctorOnDemand = Effect_exports.promise(() => import("./chunk-TGTG65RZ.js")).pipe(
20025
20029
  Effect_exports.flatMap((doctor) => doctor.runDoctor)
20026
20030
  );
20027
20031
  var statusLabel = {
@@ -20359,7 +20363,19 @@ var eventsCommand = Command_exports.make(
20359
20363
  if (follow) {
20360
20364
  yield* stream.pipe(
20361
20365
  Stream_exports.runForEach(
20362
- (event) => Console_exports.log(json ? JSON.stringify(event) : formatCampEvent(event))
20366
+ (event) => Console_exports.log(json ? JSON.stringify(event) : formatCampEvent(event)).pipe(
20367
+ Effect_exports.zipRight(
20368
+ ack ? client.AckEvents({
20369
+ ...leaseRequest,
20370
+ generation: event.generation,
20371
+ cursor: event.cursor
20372
+ }).pipe(Effect_exports.asVoid) : Effect_exports.void
20373
+ )
20374
+ )
20375
+ )
20376
+ ).pipe(
20377
+ Effect_exports.ensuring(
20378
+ release ? client.ReleaseConsumer(context).pipe(Effect_exports.ignore) : Effect_exports.void
20363
20379
  )
20364
20380
  );
20365
20381
  return [];
@@ -20719,7 +20735,7 @@ var command = rootCommand.pipe(
20719
20735
  );
20720
20736
  var cli = Command_exports.run(command, {
20721
20737
  name: "priiisk camp control",
20722
- version: "0.1.7"
20738
+ version: "0.1.8"
20723
20739
  });
20724
20740
  var runCliCommand = (argumentsList) => cli(argumentsList).pipe(
20725
20741
  Effect_exports.matchEffect({
package/package.json CHANGED
@@ -1,22 +1,22 @@
1
1
  {
2
2
  "name": "priiisk",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "CLI for running and observing a camp of collaborating agents",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "priiisk": "./dist/priiisk.js"
8
8
  },
9
9
  "files": [
10
- "dist/chunk-3V5SHVCX.js",
11
- "dist/chunk-4VQ2KUN7.js",
12
- "dist/chunk-7U7PROSV.js",
13
- "dist/chunk-JND6HOSJ.js",
14
- "dist/chunk-JND6HOSJ.js.LEGAL.txt",
15
- "dist/chunk-VLP2ZKVV.js",
16
- "dist/chunk-WEYE43UO.js",
17
- "dist/chunk-WEYE43UO.js.LEGAL.txt",
18
- "dist/chunk-YOW4MMBD.js",
19
- "dist/chunk-ZUREJQA6.js",
10
+ "dist/chunk-4V3HXXQ6.js",
11
+ "dist/chunk-BXVX5A4M.js",
12
+ "dist/chunk-FZQM7AKO.js",
13
+ "dist/chunk-OWFOOE7W.js",
14
+ "dist/chunk-OWFOOE7W.js.LEGAL.txt",
15
+ "dist/chunk-S7LCWMQY.js",
16
+ "dist/chunk-TGTG65RZ.js",
17
+ "dist/chunk-TZBPOE6G.js",
18
+ "dist/chunk-W2ZL6LWM.js",
19
+ "dist/chunk-W2ZL6LWM.js.LEGAL.txt",
20
20
  "dist/priiisk-host.js",
21
21
  "dist/priiisk.js",
22
22
  "profiles",