@cleocode/cleo 2026.4.130 → 2026.4.131

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/index.js CHANGED
@@ -363,13 +363,72 @@ var init_attachment_schema = __esm({
363
363
  });
364
364
 
365
365
  // packages/contracts/src/branch-lock.ts
366
+ var BRANCH_LOCK_ERROR_CODES;
366
367
  var init_branch_lock = __esm({
367
368
  "packages/contracts/src/branch-lock.ts"() {
368
369
  "use strict";
370
+ BRANCH_LOCK_ERROR_CODES = {
371
+ /** L2: git shim blocked a branch-mutating operation. */
372
+ E_GIT_OP_BLOCKED: "E_GIT_OP_BLOCKED",
373
+ /** L1: spawn attempted without a worktree handle. */
374
+ E_WORKTREE_REQUIRED: "E_WORKTREE_REQUIRED",
375
+ /** L1: worktree path does not exist or is not a valid git worktree. */
376
+ E_WORKTREE_INVALID: "E_WORKTREE_INVALID",
377
+ /** L1: cherry-pick failed during worktree.complete. */
378
+ E_CHERRY_PICK_FAILED: "E_CHERRY_PICK_FAILED",
379
+ /** L3: filesystem harden failed. */
380
+ E_FS_HARDEN_FAILED: "E_FS_HARDEN_FAILED",
381
+ /** L4a: HMAC token invalid or missing. */
382
+ E_OVERRIDE_TOKEN_INVALID: "E_OVERRIDE_TOKEN_INVALID",
383
+ /** L4b: caller has CLEO_AGENT_ROLE=worker|lead|subagent — override forbidden. */
384
+ E_OVERRIDE_FORBIDDEN_AGENT_ROLE: "E_OVERRIDE_FORBIDDEN_AGENT_ROLE",
385
+ /** L4c: override requires TTY but stdin/stderr is not a TTY. */
386
+ E_OVERRIDE_NEEDS_TTY: "E_OVERRIDE_NEEDS_TTY",
387
+ /** L4d: session override limit exceeded. */
388
+ E_OVERRIDE_RATE_LIMIT: "E_OVERRIDE_RATE_LIMIT"
389
+ };
369
390
  }
370
391
  });
371
392
 
372
393
  // packages/contracts/src/exit-codes.ts
394
+ function isErrorCode(code) {
395
+ return code >= 1 && code < 100;
396
+ }
397
+ function isSuccessCode(code) {
398
+ return code === 0 || code >= 100;
399
+ }
400
+ function isNoChangeCode(code) {
401
+ return code === 102 /* NO_CHANGE */;
402
+ }
403
+ function isRecoverableCode(code) {
404
+ const nonRecoverable = /* @__PURE__ */ new Set([
405
+ 3 /* FILE_ERROR */,
406
+ 5 /* DEPENDENCY_ERROR */,
407
+ 14 /* CIRCULAR_REFERENCE */,
408
+ 18 /* CASCADE_FAILED */,
409
+ 37 /* SESSION_CLOSE_BLOCKED */,
410
+ 46 /* VERIFICATION_LOCKED */,
411
+ 50 /* CONTEXT_WARNING */,
412
+ 51 /* CONTEXT_CAUTION */,
413
+ 52 /* CONTEXT_CRITICAL */,
414
+ 53 /* CONTEXT_EMERGENCY */,
415
+ 54 /* CONTEXT_STALE */,
416
+ 64 /* AUTONOMOUS_BOUNDARY */,
417
+ 65 /* HANDOFF_REQUIRED */,
418
+ 72 /* NEXUS_PERMISSION_DENIED */,
419
+ 75 /* NEXUS_REGISTRY_CORRUPT */,
420
+ 82 /* CIRCULAR_VALIDATION */,
421
+ 83 /* LIFECYCLE_TRANSITION_INVALID */,
422
+ 85 /* ARTIFACT_TYPE_UNKNOWN */,
423
+ 89 /* ARTIFACT_ROLLBACK_FAILED */,
424
+ 93 /* DIGEST_MISMATCH */
425
+ ]);
426
+ if (!isErrorCode(code)) return false;
427
+ return !nonRecoverable.has(code);
428
+ }
429
+ function getExitCodeName(code) {
430
+ return ExitCode[code] ?? "UNKNOWN";
431
+ }
373
432
  var ExitCode;
374
433
  var init_exit_codes = __esm({
375
434
  "packages/contracts/src/exit-codes.ts"() {
@@ -471,6 +530,18 @@ var init_exit_codes = __esm({
471
530
  });
472
531
 
473
532
  // packages/contracts/src/errors.ts
533
+ function normalizeError(error, fallbackMessage = "An unexpected error occurred") {
534
+ if (error instanceof Error) {
535
+ return error;
536
+ }
537
+ if (typeof error === "string") {
538
+ return new Error(error);
539
+ }
540
+ if (error !== null && typeof error === "object" && "message" in error && typeof error.message === "string") {
541
+ return new Error(error.message);
542
+ }
543
+ return new Error(fallbackMessage);
544
+ }
474
545
  function getErrorMessage(error, fallback = "Unknown error") {
475
546
  if (error instanceof Error) {
476
547
  return error.message;
@@ -483,10 +554,87 @@ function getErrorMessage(error, fallback = "Unknown error") {
483
554
  }
484
555
  return fallback;
485
556
  }
557
+ function formatError(error, context, includeStack = false) {
558
+ const message = getErrorMessage(error);
559
+ const prefix = context ? `[${context}] ` : "";
560
+ let result = `${prefix}${message}`;
561
+ if (includeStack && error instanceof Error && error.stack) {
562
+ result += `
563
+ ${error.stack}`;
564
+ }
565
+ return result;
566
+ }
567
+ function isErrorType(error, codeOrName) {
568
+ if (error instanceof Error) {
569
+ if (error.name === codeOrName) {
570
+ return true;
571
+ }
572
+ if ("code" in error && error.code === codeOrName) {
573
+ return true;
574
+ }
575
+ }
576
+ return false;
577
+ }
578
+ function createErrorResult(error) {
579
+ return {
580
+ success: false,
581
+ error: getErrorMessage(error)
582
+ };
583
+ }
584
+ function createSuccessResult() {
585
+ return { success: true };
586
+ }
587
+ function isErrorResult(result) {
588
+ return !result.success;
589
+ }
590
+ var ThinAgentViolationError, LifecycleScopeDeniedError;
486
591
  var init_errors = __esm({
487
592
  "packages/contracts/src/errors.ts"() {
488
593
  "use strict";
489
594
  init_exit_codes();
595
+ ThinAgentViolationError = class extends Error {
596
+ /**
597
+ * @param agentId - The offending agent's unique identifier.
598
+ * @param role - The offending agent's declared role (lead, worker, etc.).
599
+ * @param attemptedAction - The spawn action that was blocked.
600
+ */
601
+ constructor(agentId, role, attemptedAction) {
602
+ super(
603
+ `E_THIN_AGENT_VIOLATION: agent '${agentId}' (role=${role}) attempted '${attemptedAction}'. Only orchestrators may spawn. Escalate via playbook approval gate.`
604
+ );
605
+ this.agentId = agentId;
606
+ this.role = role;
607
+ this.attemptedAction = attemptedAction;
608
+ this.name = "ThinAgentViolationError";
609
+ }
610
+ agentId;
611
+ role;
612
+ attemptedAction;
613
+ /** Stable LAFS error code string for envelope emission. */
614
+ code = "E_THIN_AGENT_VIOLATION";
615
+ /** Numeric exit code aligned with {@link ExitCode.THIN_AGENT_VIOLATION}. */
616
+ exitCode = 68 /* THIN_AGENT_VIOLATION */;
617
+ };
618
+ LifecycleScopeDeniedError = class extends Error {
619
+ /**
620
+ * @param epicId - The epic whose lifecycle mutation was blocked.
621
+ * @param sessionScope - Human-readable description of the current session scope.
622
+ */
623
+ constructor(epicId, sessionScope) {
624
+ super(
625
+ `E_LIFECYCLE_SCOPE_DENIED: lifecycle stage advancement for epic '${epicId}' requires a session scoped to that epic or an owner override. Current session scope: ${sessionScope}. Use CLEO_OWNER_OVERRIDE=1 if this is an authorized operation.`
626
+ );
627
+ this.epicId = epicId;
628
+ this.sessionScope = sessionScope;
629
+ this.name = "LifecycleScopeDeniedError";
630
+ }
631
+ epicId;
632
+ sessionScope;
633
+ /** Stable LAFS error code string for envelope emission. */
634
+ code = "E_LIFECYCLE_SCOPE_DENIED";
635
+ /** Numeric exit code aligned with {@link ExitCode.TASK_NOT_IN_SCOPE} (34). */
636
+ exitCode = 34 /* TASK_NOT_IN_SCOPE */;
637
+ };
490
638
  }
491
639
  });
492
640
 
@@ -553,13 +701,49 @@ var init_evidence_record_schema = __esm({
553
701
  });
554
702
 
555
703
  // packages/contracts/src/facade.ts
704
+ var BRAIN_OBSERVATION_TYPES, AGENT_INSTANCE_STATUSES, AGENT_TYPES;
556
705
  var init_facade = __esm({
557
706
  "packages/contracts/src/facade.ts"() {
558
707
  "use strict";
708
+ BRAIN_OBSERVATION_TYPES = [
709
+ "discovery",
710
+ "change",
711
+ "feature",
712
+ "bugfix",
713
+ "decision",
714
+ "refactor",
715
+ "diary"
716
+ ];
717
+ AGENT_INSTANCE_STATUSES = [
718
+ "starting",
719
+ "active",
720
+ "idle",
721
+ "error",
722
+ "crashed",
723
+ "stopped"
724
+ ];
725
+ AGENT_TYPES = [
726
+ "orchestrator",
727
+ "executor",
728
+ "researcher",
729
+ "architect",
730
+ "validator",
731
+ "documentor",
732
+ "custom"
733
+ ];
559
734
  }
560
735
  });
561
736
 
562
737
  // packages/contracts/src/lafs.ts
738
+ function isLafsSuccess(envelope) {
739
+ return envelope.success === true;
740
+ }
741
+ function isLafsError(envelope) {
742
+ return envelope.success === false;
743
+ }
744
+ function isGatewayEnvelope(envelope) {
745
+ return "_meta" in envelope && envelope._meta !== void 0;
746
+ }
563
747
  var init_lafs = __esm({
564
748
  "packages/contracts/src/lafs.ts"() {
565
749
  "use strict";
@@ -720,6 +904,10 @@ var init_worktree = __esm({
720
904
  });
721
905
 
722
906
  // packages/contracts/src/operations/index.ts
907
+ var operations_exports = {};
908
+ __export(operations_exports, {
909
+ paramsToCittyArgs: () => paramsToCittyArgs
910
+ });
723
911
  var init_operations = __esm({
724
912
  "packages/contracts/src/operations/index.ts"() {
725
913
  "use strict";
@@ -745,6 +933,21 @@ var init_operations = __esm({
745
933
  });
746
934
 
747
935
  // packages/contracts/src/peer.ts
936
+ function isPeerIdentity(value) {
937
+ if (typeof value !== "object" || value === null) return false;
938
+ const v = value;
939
+ return typeof v["peerId"] === "string" && v["peerId"].length > 0 && typeof v["peerKind"] === "string" && ["orchestrator", "lead", "worker", "subagent"].includes(v["peerKind"]) && typeof v["cantFile"] === "string" && v["cantFile"].length > 0 && typeof v["displayName"] === "string" && typeof v["description"] === "string";
940
+ }
941
+ function assertPeerIdentity(value) {
942
+ if (!isPeerIdentity(value)) {
943
+ throw new TypeError(
944
+ `Expected PeerIdentity { peerId, peerKind, cantFile, displayName, description } \u2014 got: ${JSON.stringify(value)}`
945
+ );
946
+ }
947
+ }
948
+ function filterPeerIdentities(values) {
949
+ return values.filter(isPeerIdentity);
950
+ }
748
951
  var init_peer = __esm({
749
952
  "packages/contracts/src/peer.ts"() {
750
953
  "use strict";
@@ -752,9 +955,69 @@ var init_peer = __esm({
752
955
  });
753
956
 
754
957
  // packages/contracts/src/session.ts
958
+ var SessionView;
755
959
  var init_session2 = __esm({
756
960
  "packages/contracts/src/session.ts"() {
757
961
  "use strict";
962
+ SessionView = class _SessionView {
963
+ _sessions;
964
+ constructor(sessions2) {
965
+ this._sessions = sessions2;
966
+ }
967
+ /** Create a SessionView from a Session array. */
968
+ static from(sessions2) {
969
+ return new _SessionView(sessions2);
970
+ }
971
+ /** All sessions in the view (readonly). */
972
+ get all() {
973
+ return this._sessions;
974
+ }
975
+ /** Number of sessions. */
976
+ get length() {
977
+ return this._sessions.length;
978
+ }
979
+ /** Find the currently active session (if any). */
980
+ findActive() {
981
+ return this._sessions.find((s) => s.status === "active");
982
+ }
983
+ /** Find a session by ID. */
984
+ findById(id) {
985
+ return this._sessions.find((s) => s.id === id);
986
+ }
987
+ /** Filter sessions by one or more statuses. */
988
+ filterByStatus(...statuses) {
989
+ return this._sessions.filter((s) => statuses.includes(s.status));
990
+ }
991
+ /** Find sessions matching a scope type and optional rootTaskId. */
992
+ findByScope(type2, rootTaskId) {
993
+ return this._sessions.filter((s) => {
994
+ if (s.scope?.type !== type2) return false;
995
+ if (rootTaskId && s.scope?.rootTaskId !== rootTaskId) return false;
996
+ return true;
997
+ });
998
+ }
999
+ /** Sort sessions by a date field. Returns a new array (does not mutate). */
1000
+ sortByDate(field, descending = true) {
1001
+ return [...this._sessions].sort((a, b) => {
1002
+ const aDate = new Date(a[field] || "").getTime();
1003
+ const bDate = new Date(b[field] || "").getTime();
1004
+ return descending ? bDate - aDate : aDate - bDate;
1005
+ });
1006
+ }
1007
+ /** Get the most recently started session. */
1008
+ mostRecent() {
1009
+ if (this._sessions.length === 0) return void 0;
1010
+ return this.sortByDate("startedAt", true)[0];
1011
+ }
1012
+ /** Convert back to a plain Session array (shallow copy). */
1013
+ toArray() {
1014
+ return [...this._sessions];
1015
+ }
1016
+ /** Support for-of iteration. */
1017
+ [Symbol.iterator]() {
1018
+ return this._sessions[Symbol.iterator]();
1019
+ }
1020
+ };
758
1021
  }
759
1022
  });
760
1023
 
@@ -819,10 +1082,95 @@ var init_session_journal = __esm({
819
1082
  });
820
1083
 
821
1084
  // packages/contracts/src/status-registry.ts
822
- var TASK_STATUS_SYMBOLS_UNICODE, TASK_STATUS_SYMBOLS_ASCII;
1085
+ function isValidStatus(entityType, value) {
1086
+ return STATUS_REGISTRY[entityType].includes(value);
1087
+ }
1088
+ var TASK_STATUSES, SESSION_STATUSES, LIFECYCLE_PIPELINE_STATUSES, LIFECYCLE_STAGE_STATUSES, ADR_STATUSES, GATE_STATUSES, MANIFEST_STATUSES, TERMINAL_TASK_STATUSES, TERMINAL_PIPELINE_STATUSES, TERMINAL_STAGE_STATUSES, STATUS_REGISTRY, PIPELINE_STATUS_ICONS, STAGE_STATUS_ICONS, TASK_STATUS_SYMBOLS_UNICODE, TASK_STATUS_SYMBOLS_ASCII;
823
1089
  var init_status_registry = __esm({
824
1090
  "packages/contracts/src/status-registry.ts"() {
825
1091
  "use strict";
1092
+ TASK_STATUSES = [
1093
+ "pending",
1094
+ "active",
1095
+ "blocked",
1096
+ "done",
1097
+ "cancelled",
1098
+ "archived",
1099
+ "proposed"
1100
+ ];
1101
+ SESSION_STATUSES = ["active", "ended", "orphaned", "suspended"];
1102
+ LIFECYCLE_PIPELINE_STATUSES = [
1103
+ "active",
1104
+ "completed",
1105
+ "blocked",
1106
+ "failed",
1107
+ "cancelled",
1108
+ "aborted"
1109
+ ];
1110
+ LIFECYCLE_STAGE_STATUSES = [
1111
+ "not_started",
1112
+ "in_progress",
1113
+ "blocked",
1114
+ "completed",
1115
+ "skipped",
1116
+ "failed"
1117
+ ];
1118
+ ADR_STATUSES = ["proposed", "accepted", "superseded", "deprecated"];
1119
+ GATE_STATUSES = ["pending", "passed", "failed", "waived"];
1120
+ MANIFEST_STATUSES = ["completed", "partial", "blocked", "archived"];
1121
+ TERMINAL_TASK_STATUSES = /* @__PURE__ */ new Set([
1122
+ "done",
1123
+ "cancelled",
1124
+ "archived"
1125
+ ]);
1126
+ TERMINAL_PIPELINE_STATUSES = /* @__PURE__ */ new Set([
1127
+ "completed",
1128
+ "failed",
1129
+ "cancelled",
1130
+ "aborted"
1131
+ ]);
1132
+ TERMINAL_STAGE_STATUSES = /* @__PURE__ */ new Set([
1133
+ "completed",
1134
+ "skipped",
1135
+ "failed"
1136
+ ]);
1137
+ STATUS_REGISTRY = {
1138
+ task: TASK_STATUSES,
1139
+ session: SESSION_STATUSES,
1140
+ lifecycle_pipeline: LIFECYCLE_PIPELINE_STATUSES,
1141
+ lifecycle_stage: LIFECYCLE_STAGE_STATUSES,
1142
+ adr: ADR_STATUSES,
1143
+ gate: GATE_STATUSES,
1144
+ manifest: MANIFEST_STATUSES
1145
+ };
1146
+ PIPELINE_STATUS_ICONS = {
1147
+ active: "\u25B6",
1148
+ // pipeline is running
1149
+ completed: "\u2713",
1150
+ // all stages done successfully
1151
+ blocked: "\u23F8",
1152
+ // cannot advance; waiting
1153
+ failed: "\u2717",
1154
+ // terminal failure
1155
+ cancelled: "\u2298",
1156
+ // user-initiated abandonment
1157
+ aborted: "\u23F9"
1158
+ // system-forced termination
1159
+ };
1160
+ STAGE_STATUS_ICONS = {
1161
+ not_started: "\u23F9",
1162
+ // not yet entered
1163
+ in_progress: "\u25B6",
1164
+ // actively running
1165
+ blocked: "\u23F8",
1166
+ // paused / waiting
1167
+ completed: "\u2713",
1168
+ // finished successfully
1169
+ skipped: "\u23ED",
1170
+ // intentionally bypassed
1171
+ failed: "\u2717"
1172
+ // terminal failure
1173
+ };
826
1174
  TASK_STATUS_SYMBOLS_UNICODE = {
827
1175
  pending: "\u25CB",
828
1176
  // ○ not yet started
@@ -908,6 +1256,90 @@ var init_task_evidence = __esm({
908
1256
  });
909
1257
 
910
1258
  // packages/contracts/src/index.ts
1259
+ var src_exports = {};
1260
+ __export(src_exports, {
1261
+ ADR_STATUSES: () => ADR_STATUSES,
1262
+ AGENT_INSTANCE_STATUSES: () => AGENT_INSTANCE_STATUSES,
1263
+ AGENT_TYPES: () => AGENT_TYPES,
1264
+ BRAIN_OBSERVATION_TYPES: () => BRAIN_OBSERVATION_TYPES,
1265
+ BRANCH_LOCK_ERROR_CODES: () => BRANCH_LOCK_ERROR_CODES,
1266
+ ExitCode: () => ExitCode,
1267
+ GATE_STATUSES: () => GATE_STATUSES,
1268
+ LIFECYCLE_PIPELINE_STATUSES: () => LIFECYCLE_PIPELINE_STATUSES,
1269
+ LIFECYCLE_STAGE_STATUSES: () => LIFECYCLE_STAGE_STATUSES,
1270
+ LifecycleScopeDeniedError: () => LifecycleScopeDeniedError,
1271
+ MANIFEST_STATUSES: () => MANIFEST_STATUSES,
1272
+ PIPELINE_STATUS_ICONS: () => PIPELINE_STATUS_ICONS,
1273
+ SESSION_JOURNAL_SCHEMA_VERSION: () => SESSION_JOURNAL_SCHEMA_VERSION,
1274
+ SESSION_STATUSES: () => SESSION_STATUSES,
1275
+ STAGE_STATUS_ICONS: () => STAGE_STATUS_ICONS,
1276
+ STATUS_REGISTRY: () => STATUS_REGISTRY,
1277
+ SessionView: () => SessionView,
1278
+ TASK_STATUSES: () => TASK_STATUSES,
1279
+ TASK_STATUS_SYMBOLS_ASCII: () => TASK_STATUS_SYMBOLS_ASCII,
1280
+ TASK_STATUS_SYMBOLS_UNICODE: () => TASK_STATUS_SYMBOLS_UNICODE,
1281
+ TERMINAL_PIPELINE_STATUSES: () => TERMINAL_PIPELINE_STATUSES,
1282
+ TERMINAL_STAGE_STATUSES: () => TERMINAL_STAGE_STATUSES,
1283
+ TERMINAL_TASK_STATUSES: () => TERMINAL_TASK_STATUSES,
1284
+ ThinAgentViolationError: () => ThinAgentViolationError,
1285
+ acceptanceArraySchema: () => acceptanceArraySchema,
1286
+ acceptanceGateResultSchema: () => acceptanceGateResultSchema,
1287
+ acceptanceGateSchema: () => acceptanceGateSchema,
1288
+ acceptanceItemSchema: () => acceptanceItemSchema,
1289
+ assertPeerIdentity: () => assertPeerIdentity,
1290
+ attachmentMetadataSchema: () => attachmentMetadataSchema,
1291
+ attachmentRefSchema: () => attachmentRefSchema,
1292
+ attachmentSchema: () => attachmentSchema,
1293
+ blobAttachmentSchema: () => blobAttachmentSchema,
1294
+ commandGateSchema: () => commandGateSchema,
1295
+ commandOutputEvidenceSchema: () => commandOutputEvidenceSchema,
1296
+ commandOutputRecordSchema: () => commandOutputRecordSchema,
1297
+ createErrorResult: () => createErrorResult,
1298
+ createSuccessResult: () => createSuccessResult,
1299
+ evidenceRecordSchema: () => evidenceRecordSchema,
1300
+ fileAssertionSchema: () => fileAssertionSchema,
1301
+ fileEvidenceSchema: () => fileEvidenceSchema,
1302
+ fileGateSchema: () => fileGateSchema,
1303
+ filterPeerIdentities: () => filterPeerIdentities,
1304
+ formatError: () => formatError,
1305
+ gateBaseSchema: () => gateBaseSchema,
1306
+ gateResultDetailsSchema: () => gateResultDetailsSchema,
1307
+ getErrorMessage: () => getErrorMessage,
1308
+ getExitCodeName: () => getExitCodeName,
1309
+ httpGateSchema: () => httpGateSchema,
1310
+ implDiffRecordSchema: () => implDiffRecordSchema,
1311
+ isErrorCode: () => isErrorCode,
1312
+ isErrorResult: () => isErrorResult,
1313
+ isErrorType: () => isErrorType,
1314
+ isGatewayEnvelope: () => isGatewayEnvelope,
1315
+ isLafsError: () => isLafsError,
1316
+ isLafsSuccess: () => isLafsSuccess,
1317
+ isNoChangeCode: () => isNoChangeCode,
1318
+ isPeerIdentity: () => isPeerIdentity,
1319
+ isRecoverableCode: () => isRecoverableCode,
1320
+ isSuccessCode: () => isSuccessCode,
1321
+ isValidStatus: () => isValidStatus,
1322
+ lintGateSchema: () => lintGateSchema,
1323
+ lintReportRecordSchema: () => lintReportRecordSchema,
1324
+ llmsTxtAttachmentSchema: () => llmsTxtAttachmentSchema,
1325
+ llmtxtDocAttachmentSchema: () => llmtxtDocAttachmentSchema,
1326
+ localFileAttachmentSchema: () => localFileAttachmentSchema,
1327
+ logEvidenceSchema: () => logEvidenceSchema,
1328
+ manualGateSchema: () => manualGateSchema,
1329
+ normalizeError: () => normalizeError,
1330
+ ops: () => operations_exports,
1331
+ paramsToCittyArgs: () => paramsToCittyArgs,
1332
+ screenshotEvidenceSchema: () => screenshotEvidenceSchema,
1333
+ sessionJournalDebriefSummarySchema: () => sessionJournalDebriefSummarySchema,
1334
+ sessionJournalDoctorSummarySchema: () => sessionJournalDoctorSummarySchema,
1335
+ sessionJournalEntrySchema: () => sessionJournalEntrySchema,
1336
+ taskEvidenceSchema: () => taskEvidenceSchema,
1337
+ testGateSchema: () => testGateSchema,
1338
+ testOutputEvidenceSchema: () => testOutputEvidenceSchema,
1339
+ testOutputRecordSchema: () => testOutputRecordSchema,
1340
+ urlAttachmentSchema: () => urlAttachmentSchema,
1341
+ validateSpecCheckRecordSchema: () => validateSpecCheckRecordSchema
1342
+ });
911
1343
  var init_src = __esm({
912
1344
  "packages/contracts/src/index.ts"() {
913
1345
  init_acceptance_gate_schema();
@@ -9068,6 +9500,18 @@ async function sessionStart(projectRoot, params) {
9068
9500
  ...previousDebrief && { previousDebrief },
9069
9501
  ...previousHandoff && { previousHandoff }
9070
9502
  };
9503
+ import("@cleocode/core/sessions/session-journal.js").then(async ({ appendSessionJournalEntry }) => {
9504
+ const { SESSION_JOURNAL_SCHEMA_VERSION: SESSION_JOURNAL_SCHEMA_VERSION2 } = await Promise.resolve().then(() => (init_src(), src_exports));
9505
+ await appendSessionJournalEntry(projectRoot, {
9506
+ schemaVersion: SESSION_JOURNAL_SCHEMA_VERSION2,
9507
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
9508
+ sessionId,
9509
+ eventType: "session_start",
9510
+ agentIdentifier: agentIdentifier ?? void 0,
9511
+ scope: params.scope
9512
+ });
9513
+ }).catch(() => {
9514
+ });
9071
9515
  return { success: true, data: enrichedSession };
9072
9516
  } catch {
9073
9517
  return engineError("E_NOT_INITIALIZED", "Task database not initialized");
@@ -9128,6 +9572,38 @@ async function sessionEnd(projectRoot, notes, params) {
9128
9572
  }
9129
9573
  } catch {
9130
9574
  }
9575
+ try {
9576
+ const { appendSessionJournalEntry } = await import("@cleocode/core/sessions/session-journal.js");
9577
+ const { SESSION_JOURNAL_SCHEMA_VERSION: SESSION_JOURNAL_SCHEMA_VERSION2 } = await Promise.resolve().then(() => (init_src(), src_exports));
9578
+ let doctorSummary;
9579
+ try {
9580
+ const { scanBrainNoise } = await import("@cleocode/core/memory/brain-doctor.js");
9581
+ const scanResult = await scanBrainNoise(projectRoot);
9582
+ doctorSummary = {
9583
+ isClean: scanResult.isClean,
9584
+ findingsCount: scanResult.findings.length,
9585
+ patterns: scanResult.findings.map((f) => f.pattern),
9586
+ totalScanned: scanResult.totalScanned
9587
+ };
9588
+ } catch {
9589
+ }
9590
+ const agentIdentifier = process.env.CLEO_AGENT_ID ?? process.env.CLAUDE_CODE_AGENT_ID ?? void 0;
9591
+ const duration = Math.floor(
9592
+ (Date.now() - new Date(activeSession.startedAt).getTime()) / 1e3
9593
+ );
9594
+ await appendSessionJournalEntry(projectRoot, {
9595
+ schemaVersion: SESSION_JOURNAL_SCHEMA_VERSION2,
9596
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
9597
+ sessionId,
9598
+ eventType: "session_end",
9599
+ agentIdentifier,
9600
+ providerId: activeSession.providerId ?? void 0,
9601
+ duration,
9602
+ tasksCompleted: activeSession.tasksCompleted ?? [],
9603
+ ...doctorSummary !== void 0 ? { doctorSummary } : {}
9604
+ });
9605
+ } catch {
9606
+ }
9131
9607
  return {
9132
9608
  success: true,
9133
9609
  data: { sessionId, ended: true, ...memoryPrompt && { memoryPrompt } }
@@ -25983,8 +26459,8 @@ var init_runtime = __esm({
25983
26459
  });
25984
26460
 
25985
26461
  // packages/playbooks/src/index.ts
25986
- var src_exports = {};
25987
- __export(src_exports, {
26462
+ var src_exports2 = {};
26463
+ __export(src_exports2, {
25988
26464
  DEFAULT_POLICY_RULES: () => DEFAULT_POLICY_RULES,
25989
26465
  E_APPROVAL_ALREADY_DECIDED: () => E_APPROVAL_ALREADY_DECIDED,
25990
26466
  E_APPROVAL_NOT_FOUND: () => E_APPROVAL_NOT_FOUND,
@@ -26937,7 +27413,7 @@ async function handleApproveGate(params, startTime) {
26937
27413
  );
26938
27414
  }
26939
27415
  const db = await acquirePlaybookDb();
26940
- const { approveGate: approveGate2 } = await Promise.resolve().then(() => (init_src2(), src_exports));
27416
+ const { approveGate: approveGate2 } = await Promise.resolve().then(() => (init_src2(), src_exports2));
26941
27417
  const updated = approveGate2(db, resumeToken, approver, reason);
26942
27418
  return {
26943
27419
  meta: dispatchMeta("mutate", "orchestrate", "approve", startTime),
@@ -27027,7 +27503,7 @@ async function handleRejectGate(params, startTime) {
27027
27503
  );
27028
27504
  }
27029
27505
  const db = await acquirePlaybookDb();
27030
- const { rejectGate: rejectGate2 } = await Promise.resolve().then(() => (init_src2(), src_exports));
27506
+ const { rejectGate: rejectGate2 } = await Promise.resolve().then(() => (init_src2(), src_exports2));
27031
27507
  const updated = rejectGate2(db, resumeToken, approver, reason);
27032
27508
  return {
27033
27509
  meta: dispatchMeta("mutate", "orchestrate", "reject", startTime),