@vostride/agent-qa-agent-local 0.2.3 → 0.2.4

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/index.cjs CHANGED
@@ -30,7 +30,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
- ALLOW_PRODUCTION_OPT_IN: () => import_agent_qa_schema.ALLOW_PRODUCTION_OPT_IN,
34
33
  BRIEF_CEILING: () => BRIEF_CEILING,
35
34
  BRIEF_FRACTION: () => BRIEF_FRACTION,
36
35
  BuildOrdinalReservationError: () => import_agent_qa_runner_local4.BuildOrdinalReservationError,
@@ -47,25 +46,32 @@ __export(index_exports, {
47
46
  EMBEDDER_WORKER_TERM_GRACE_MS: () => import_agent_qa_knowledge_local.EMBEDDER_WORKER_TERM_GRACE_MS,
48
47
  ENTITY_INDEX_SWEEP_INTERVAL_MS: () => import_agent_qa_knowledge_local.ENTITY_INDEX_SWEEP_INTERVAL_MS,
49
48
  EmbedderWorkerTimeoutError: () => import_agent_qa_knowledge_local.EmbedderWorkerTimeoutError,
49
+ FsMarkLedger: () => FsMarkLedger,
50
50
  GLOBAL_RECORD_CAP: () => GLOBAL_RECORD_CAP,
51
+ HANDOFF_FILE: () => import_agent_qa_runner_local6.HANDOFF_FILE,
51
52
  InvalidChatSessionIdError: () => InvalidChatSessionIdError,
52
53
  JOB_RECOVERY_MAX_RESUMED_JOBS: () => JOB_RECOVERY_MAX_RESUMED_JOBS,
53
54
  LOCAL_CURATION_CAPABILITIES: () => LOCAL_CURATION_CAPABILITIES,
54
55
  LOCAL_DAEMON_CAPABILITIES: () => LOCAL_DAEMON_CAPABILITIES,
55
56
  LOCAL_KNOWLEDGE_PROBES: () => LOCAL_KNOWLEDGE_PROBES,
56
57
  LocalAgentClosedError: () => LocalAgentClosedError,
58
+ MARKS_LEDGER_FILE: () => MARKS_LEDGER_FILE,
59
+ MARKS_LEDGER_LOCK_FILE: () => MARKS_LEDGER_LOCK_FILE,
60
+ MARK_INTENT_FILE: () => MARK_INTENT_FILE,
57
61
  MIN_BRIEF: () => MIN_BRIEF,
58
62
  MIN_CAUTION: () => MIN_CAUTION,
59
63
  MIN_MEMORY_TOOL_CONTEXT_WINDOW: () => MIN_MEMORY_TOOL_CONTEXT_WINDOW,
64
+ MarkIntentUnusableError: () => MarkIntentUnusableError,
65
+ MarkLedgerBusyError: () => MarkLedgerBusyError,
66
+ MarkLedgerCorruptError: () => MarkLedgerCorruptError,
67
+ MarkLedgerNoRunError: () => MarkLedgerNoRunError,
60
68
  QUARANTINE_CLASS_DISPOSITIONS: () => import_reader3.QUARANTINE_CLASS_DISPOSITIONS,
61
69
  QUARANTINE_FLOOR_ELIGIBILITY: () => import_reader3.QUARANTINE_FLOOR_ELIGIBILITY,
62
70
  READ_BODY_FRACTION: () => READ_BODY_FRACTION,
63
- REFUSED_RUN_REQUEST_FIELDS: () => REFUSED_RUN_REQUEST_FIELDS,
64
- RunDeniedError: () => RunDeniedError,
71
+ RUNS_SUBDIR: () => import_agent_qa_runner_local6.RUNS_SUBDIR,
65
72
  RunIdAlreadyInUseError: () => RunIdAlreadyInUseError,
66
73
  RunIdNotMintedError: () => RunIdNotMintedError,
67
74
  RunProducedNoEventsError: () => RunProducedNoEventsError,
68
- RunRequestFieldRefusedError: () => RunRequestFieldRefusedError,
69
75
  SUITE_LIFECYCLE_LANE: () => SUITE_LIFECYCLE_LANE,
70
76
  SYSTEM_CLOCK: () => SYSTEM_CLOCK,
71
77
  SuiteBoundaryWhileLiveError: () => SuiteBoundaryWhileLiveError,
@@ -74,7 +80,6 @@ __export(index_exports, {
74
80
  WEAK_MODEL_CAP_SCALE: () => WEAK_MODEL_CAP_SCALE,
75
81
  applyKnowledgeChange: () => applyKnowledgeChange,
76
82
  buildMemberRunConfig: () => buildMemberRunConfig,
77
- buildProductionRefusal: () => import_agent_qa_schema.buildProductionRefusal,
78
83
  buildRunPorts: () => buildRunPorts,
79
84
  buildScreenshotCompressor: () => buildScreenshotCompressor,
80
85
  buildSuiteMemberExecutor: () => buildSuiteMemberExecutor,
@@ -94,15 +99,17 @@ __export(index_exports, {
94
99
  createRunsReader: () => createRunsReader,
95
100
  createSuiteLifecycle: () => createSuiteLifecycle,
96
101
  latestBuildOrdinal: () => import_agent_qa_runner_local4.latestBuildOrdinal,
102
+ latestMarkReceiptFor: () => latestMarkReceiptFor,
103
+ latestMarkReceiptsPerAddress: () => latestMarkReceiptsPerAddress,
97
104
  listSessions: () => listSessions,
105
+ loadCompletedRunHandoff: () => import_agent_qa_runner_local6.loadCompletedRunHandoff,
98
106
  lookupEvidenceBlob: () => lookupEvidenceBlob,
99
107
  mapVerdictToExitCode: () => import_agent_qa_runner3.mapVerdictToExitCode,
100
108
  memoryToolGate: () => memoryToolGate,
101
109
  mintChatSessionId: () => mintChatSessionId,
102
110
  openRunKnowledgeComposition: () => openRunKnowledgeComposition,
111
+ purgeActionCache: () => import_agent_qa_runner_local7.purgeActionCache,
103
112
  readEvidenceBlobBytes: () => readEvidenceBlobBytes,
104
- refuseProductionWithoutOptIn: () => refuseProductionWithoutOptIn,
105
- refuseUnavailableRunId: () => refuseUnavailableRunId,
106
113
  registerAdapterLiveStream: () => registerAdapterLiveStream,
107
114
  reserveBuildOrdinalForProducts: () => import_agent_qa_runner_local4.reserveBuildOrdinalForProducts,
108
115
  resolveBuildTag: () => import_agent_qa_runner_local5.resolveBuildTag,
@@ -189,7 +196,6 @@ function createFrozenKnowledgeReader(reader) {
189
196
  }
190
197
  function constructKnowledgeReader(input) {
191
198
  return createFrozenKnowledgeReader((0, import_reader.openKnowledgeReader)({
192
- ...input.resolveTrustPriors === void 0 ? {} : { priors: input.resolveTrustPriors() },
193
199
  knowledgeRoot: input.knowledgeRoot,
194
200
  ...input.product === void 0 ? {} : { product: input.product },
195
201
  scopeDefaults: {
@@ -220,7 +226,6 @@ function openRunKnowledgeComposition(input) {
220
226
  recordCap: scaledRecordCap(input.capabilities)
221
227
  };
222
228
  const reader = constructKnowledgeReader({
223
- ...input.resolveTrustPriors === void 0 ? {} : { resolveTrustPriors: input.resolveTrustPriors },
224
229
  knowledgeRoot: input.knowledgeRoot,
225
230
  ...input.product === void 0 ? {} : { product: input.product },
226
231
  ...input.parentScopes === void 0 ? {} : { parentScopes: input.parentScopes },
@@ -471,8 +476,7 @@ function buildMemberRunConfig(input) {
471
476
  cache: input.cache,
472
477
  workingMemory: input.workingMemory,
473
478
  storageState: input.storageState,
474
- // CTXB-06: model's canonical compaction (compactLogs for log bursts, guardBlob
475
- // otherwise) replaces the runner-local ceiling fallback on every tool-output value.
479
+ // The model's canonical compaction applies to every tool-output value.
476
480
  guardBlob: import_agent_qa_model.guardToolOutput,
477
481
  compressor: input.compressor,
478
482
  knowledgeReader: input.knowledgeReader,
@@ -527,24 +531,6 @@ function buildMemberRunConfig(input) {
527
531
  var import_node_fs = require("node:fs");
528
532
  var import_node_path2 = require("node:path");
529
533
  var import_agent_qa_runner2 = require("@vostride/agent-qa-runner");
530
-
531
- // src/composition/run-risk.ts
532
- var import_agent_qa_schema = require("@vostride/agent-qa-schema");
533
-
534
- // src/composition/run-invocation-core.ts
535
- var REFUSED_RUN_REQUEST_FIELDS = [
536
- "scope",
537
- "executionContext"
538
- ];
539
- var RunRequestFieldRefusedError = class extends Error {
540
- constructor(refusedFields) {
541
- super(
542
- `agent-qa cannot start a run with: ${refusedFields.join(", ")}. scope resolves from the config the run is started against, and executionContext is supplied by the composition that owns the door \u2014 a caller-named execution context would be a caller relabelling where its run came from.`
543
- );
544
- this.refusedFields = refusedFields;
545
- this.name = "RunRequestFieldRefusedError";
546
- }
547
- };
548
534
  var RunIdNotMintedError = class extends Error {
549
535
  constructor(runId) {
550
536
  super(
@@ -563,22 +549,6 @@ var RunIdAlreadyInUseError = class extends Error {
563
549
  this.name = "RunIdAlreadyInUseError";
564
550
  }
565
551
  };
566
- var RunDeniedError = class extends Error {
567
- constructor(runId, reason) {
568
- super(reason);
569
- this.runId = runId;
570
- this.reason = reason;
571
- this.name = "RunDeniedError";
572
- this.neutralReason = reason;
573
- }
574
- neutralReason;
575
- };
576
- function refuseProductionWithoutOptIn(runId, declaration) {
577
- const production = declaration.productionTargetNames.length > 0 || declaration.targetClass === "production";
578
- if (!production || declaration.allowProduction === true) return;
579
- const reason = (0, import_agent_qa_schema.buildProductionRefusal)(declaration.productionTargetNames);
580
- throw new RunDeniedError(runId, reason);
581
- }
582
552
  function refuseUnavailableRunId(input) {
583
553
  if (!input.isMintedRunId(input.runId)) throw new RunIdNotMintedError(input.runId);
584
554
  if ((0, import_node_fs.existsSync)(runDirFor({ configDir: input.configDir, runId: input.runId }))) {
@@ -589,8 +559,6 @@ function createRunInvocationCore(options) {
589
559
  const configDir = (0, import_node_path2.dirname)(options.agentQaRoot);
590
560
  return {
591
561
  async execute(request) {
592
- const refused = REFUSED_RUN_REQUEST_FIELDS.filter((field) => request[field] !== void 0);
593
- if (refused.length > 0) throw new RunRequestFieldRefusedError(refused);
594
562
  if (request.runId !== void 0) {
595
563
  refuseUnavailableRunId({
596
564
  configDir,
@@ -599,9 +567,6 @@ function createRunInvocationCore(options) {
599
567
  });
600
568
  }
601
569
  const runId = request.runId ?? options.mintRunId();
602
- const declaration = await options.resolveTargetDeclaration(request);
603
- const targetClass = declaration.targetClass;
604
- refuseProductionWithoutOptIn(runId, declaration);
605
570
  await options.afterRefusal?.();
606
571
  const ports = buildRunPorts({ configDir, runId });
607
572
  const postVerdict = options.postVerdict?.({ runId, configDir });
@@ -614,8 +579,7 @@ function createRunInvocationCore(options) {
614
579
  ...postVerdict === void 0 ? {} : { postVerdict }
615
580
  },
616
581
  configDir,
617
- configPath: request.configPath ?? options.configPath,
618
- targetClass
582
+ configPath: request.configPath ?? options.configPath
619
583
  });
620
584
  const session = (0, import_agent_qa_runner2.startRun)({
621
585
  ...assembled,
@@ -679,12 +643,12 @@ function readEvidenceBlobBytes(input, runId, sha) {
679
643
  }
680
644
 
681
645
  // src/composition/quarantine-snapshot.ts
682
- var import_agent_qa_schema2 = require("@vostride/agent-qa-schema");
646
+ var import_agent_qa_schema = require("@vostride/agent-qa-schema");
683
647
  var import_reader2 = require("@vostride/agent-qa-knowledge-local/reader");
684
648
  function resolveRunQuarantineSnapshot(input) {
685
649
  const warn = input.warn ?? (() => {
686
650
  });
687
- const product = (0, import_agent_qa_schema2.slugBranch)(input.product);
651
+ const product = (0, import_agent_qa_schema.slugBranch)(input.product);
688
652
  let read;
689
653
  try {
690
654
  read = (0, import_reader2.readQuarantineLedger)(input.knowledgeRoot);
@@ -722,7 +686,7 @@ var import_agent_qa_knowledge_local = require("@vostride/agent-qa-knowledge-loca
722
686
  var import_agent_qa_runner4 = require("@vostride/agent-qa-runner");
723
687
  var import_agent_qa_safety = require("@vostride/agent-qa-safety");
724
688
  var import_agent_qa_runner_local3 = require("@vostride/agent-qa-runner-local");
725
- var import_agent_qa_schema10 = require("@vostride/agent-qa-schema");
689
+ var import_agent_qa_schema9 = require("@vostride/agent-qa-schema");
726
690
 
727
691
  // src/composition/knowledge-review-reader.ts
728
692
  var import_reader4 = require("@vostride/agent-qa-knowledge-local/reader");
@@ -735,31 +699,20 @@ function createKnowledgeReaderPort(input) {
735
699
  }
736
700
  }
737
701
  return {
738
- // 2026-09-07, 417 D-01: forward the candidate DATA verbatim. Since 441-41 (D-06) nothing here
739
- // scans it; the chat and MCP doors mask declared values in every op result.
740
- async candidateInjection({ candidateId }) {
741
- return (0, import_reader4.candidateInjectionFor)({
742
- ...input.resolveTrustPriors === void 0 ? {} : { priors: input.resolveTrustPriors() },
743
- knowledgeRoot: await input.resolveKnowledgeRoot(),
744
- candidateId
745
- });
746
- },
747
- // 416 D-17: the caller supplied the identity; forward the reader's answer verbatim.
702
+ // The caller supplied the identity; forward the reader's answer verbatim.
748
703
  async gateReceipts({ candidateId }) {
749
704
  return (0, import_reader4.gateReceiptsFor)({
750
705
  knowledgeRoot: await input.resolveKnowledgeRoot(),
751
- candidateId,
752
- resolvePromotionPosture: await input.resolvePromotionPosture?.()
706
+ candidateId
753
707
  });
754
708
  },
755
709
  async listBundles() {
756
- const rows = (0, import_reader4.listBundles)(await input.resolveKnowledgeRoot(), input.resolveTrustPriors?.());
710
+ const rows = (0, import_reader4.listBundles)(await input.resolveKnowledgeRoot());
757
711
  await sight(rows.map((row) => row.bundleId));
758
712
  return rows;
759
713
  },
760
714
  async inspectRecords({ filter }) {
761
715
  const records = (0, import_reader4.inspectRecords)({
762
- ...input.resolveTrustPriors === void 0 ? {} : { priors: input.resolveTrustPriors() },
763
716
  knowledgeRoot: await input.resolveKnowledgeRoot(),
764
717
  filter
765
718
  });
@@ -776,7 +729,6 @@ function createKnowledgeReaderPort(input) {
776
729
  },
777
730
  async showRecord({ recordId }) {
778
731
  const result = (0, import_reader4.showRecord)({
779
- ...input.resolveTrustPriors === void 0 ? {} : { priors: input.resolveTrustPriors() },
780
732
  knowledgeRoot: await input.resolveKnowledgeRoot(),
781
733
  recordId
782
734
  });
@@ -788,19 +740,7 @@ function createKnowledgeReaderPort(input) {
788
740
  async showRecords({ recordIds }) {
789
741
  return (0, import_reader4.showRecords)({ knowledgeRoot: await input.resolveKnowledgeRoot(), recordIds });
790
742
  },
791
- /**
792
- * 407 D-08: what became of the canary lines one run served.
793
- *
794
- * Resolved per call like its four siblings, and NOT sighted. The caller already holds every
795
- * candidate id in the tuples it passes — it read them off its own run's evidence — so a
796
- * sighting here would record that the reader was handed ids rather than that an entity was
797
- * surfaced to anyone, which is the distinction the ledger exists to keep.
798
- *
799
- * The reader entry's answer is forwarded VERBATIM, `skippedBundles` included (407-19, REVIEW
800
- * WR-03). This binding neither counts nor interprets: how much of the store went unread is a
801
- * fact only the walk knows, and a composition that dropped it here would hand the op a
802
- * clean-looking answer over a half-read store.
803
- */
743
+ // Not sighted; `skippedBundles` is forwarded verbatim so a half-read store never looks clean.
804
744
  async canaryAttributions({ runId, tuples }) {
805
745
  return (0, import_reader4.canaryAttributionsFor)({
806
746
  knowledgeRoot: await input.resolveKnowledgeRoot(),
@@ -815,7 +755,7 @@ function createKnowledgeReaderPort(input) {
815
755
  var import_node_fs3 = require("node:fs");
816
756
  var import_node_crypto2 = require("node:crypto");
817
757
  var import_node_path4 = require("node:path");
818
- var import_agent_qa_schema3 = require("@vostride/agent-qa-schema");
758
+ var import_agent_qa_schema2 = require("@vostride/agent-qa-schema");
819
759
  var ANALYSIS_STAGE_PREFIX = "analysis.json";
820
760
  function fsyncFile(file) {
821
761
  const fd = (0, import_node_fs3.openSync)(file, "r");
@@ -829,7 +769,7 @@ function writeAnalysisArtifact(path, artifact) {
829
769
  const dir = (0, import_node_path4.dirname)(path);
830
770
  const staged = (0, import_node_path4.join)(dir, `.${ANALYSIS_STAGE_PREFIX}.${(0, import_node_crypto2.randomUUID)()}.tmp`);
831
771
  try {
832
- (0, import_node_fs3.writeFileSync)(staged, `${(0, import_agent_qa_schema3.canonicalJson)(artifact)}
772
+ (0, import_node_fs3.writeFileSync)(staged, `${(0, import_agent_qa_schema2.canonicalJson)(artifact)}
833
773
  `, { encoding: "utf8", mode: 384 });
834
774
  fsyncFile(staged);
835
775
  (0, import_node_fs3.renameSync)(staged, path);
@@ -843,16 +783,16 @@ function writeAnalysisArtifact(path, artifact) {
843
783
  var import_node_fs5 = require("node:fs");
844
784
  var import_node_path6 = require("node:path");
845
785
  var import_agent_qa_agent2 = require("@vostride/agent-qa-agent");
846
- var import_agent_qa_schema6 = require("@vostride/agent-qa-schema");
786
+ var import_agent_qa_schema5 = require("@vostride/agent-qa-schema");
847
787
 
848
788
  // src/store/job-checkpoint-store.ts
849
789
  var import_node_crypto3 = require("node:crypto");
850
790
  var import_node_fs4 = require("node:fs");
851
791
  var import_node_path5 = require("node:path");
852
- var import_agent_qa_schema5 = require("@vostride/agent-qa-schema");
792
+ var import_agent_qa_schema4 = require("@vostride/agent-qa-schema");
853
793
 
854
794
  // src/store/store-errors.ts
855
- var import_agent_qa_schema4 = require("@vostride/agent-qa-schema");
795
+ var import_agent_qa_schema3 = require("@vostride/agent-qa-schema");
856
796
  var import_agent_qa_agent = require("@vostride/agent-qa-agent");
857
797
  var JobStoreSchemaVersionError = class extends Error {
858
798
  constructor(path, expectedVersion, observedVersion) {
@@ -885,7 +825,7 @@ var InvalidJobCheckpointIdError = class extends Error {
885
825
  var JobCheckpointSchemaVersionError = class extends Error {
886
826
  constructor(path, observedVersion) {
887
827
  super(
888
- `Agent job checkpoint ${path} was written at schema version ${String(observedVersion)}, but this build reads version ${import_agent_qa_schema4.JOB_CHECKPOINT_SCHEMA_VERSION}. There is no migration machinery by design \u2014 clear agent job queue state and re-enqueue.`
828
+ `Agent job checkpoint ${path} was written at schema version ${String(observedVersion)}, but this build reads version ${import_agent_qa_schema3.JOB_CHECKPOINT_SCHEMA_VERSION}. There is no migration machinery by design \u2014 clear agent job queue state and re-enqueue.`
889
829
  );
890
830
  this.path = path;
891
831
  this.observedVersion = observedVersion;
@@ -938,10 +878,10 @@ function readEnvelopeOn(fs, root, jobId, checkpointId) {
938
878
  throw error;
939
879
  }
940
880
  const raw = JSON.parse(text);
941
- if (raw?.schemaVersion !== import_agent_qa_schema5.JOB_CHECKPOINT_SCHEMA_VERSION) {
881
+ if (raw?.schemaVersion !== import_agent_qa_schema4.JOB_CHECKPOINT_SCHEMA_VERSION) {
942
882
  throw new JobCheckpointSchemaVersionError(file, raw?.schemaVersion);
943
883
  }
944
- const envelope = import_agent_qa_schema5.jobCheckpointEnvelopeSchema.parse(raw);
884
+ const envelope = import_agent_qa_schema4.jobCheckpointEnvelopeSchema.parse(raw);
945
885
  if (envelope.jobId !== jobId || envelope.checkpointId !== checkpointId) {
946
886
  throw new TypeError("Agent job checkpoint envelope does not match its address");
947
887
  }
@@ -984,8 +924,8 @@ function createJobCheckpointStoreOn(fs, options) {
984
924
  publish(jobId, checkpointId, payload) {
985
925
  const file = pathFor(jobId, checkpointId);
986
926
  const envelope = {
987
- schemaVersion: import_agent_qa_schema5.JOB_CHECKPOINT_SCHEMA_VERSION,
988
- jobId: (0, import_agent_qa_schema5.asJobId)(jobId),
927
+ schemaVersion: import_agent_qa_schema4.JOB_CHECKPOINT_SCHEMA_VERSION,
928
+ jobId: (0, import_agent_qa_schema4.asJobId)(jobId),
989
929
  checkpointId,
990
930
  payload
991
931
  };
@@ -994,7 +934,7 @@ function createJobCheckpointStoreOn(fs, options) {
994
934
  let fd;
995
935
  try {
996
936
  fd = fs.openSync(temporary, "wx");
997
- fs.writeFileSync(fd, `${(0, import_agent_qa_schema5.canonicalJson)(envelope)}
937
+ fs.writeFileSync(fd, `${(0, import_agent_qa_schema4.canonicalJson)(envelope)}
998
938
  `, "utf8");
999
939
  fs.fsyncSync(fd);
1000
940
  fs.closeSync(fd);
@@ -1088,10 +1028,10 @@ function guardHeader(sessionId, line) {
1088
1028
  throw new ChatSessionHeaderError(sessionId, "its header line is not an object");
1089
1029
  }
1090
1030
  const header = parsed;
1091
- if (header.schemaVersion !== import_agent_qa_schema6.CURRENT_CHAT_SESSION_SCHEMA_VERSION) {
1031
+ if (header.schemaVersion !== import_agent_qa_schema5.CURRENT_CHAT_SESSION_SCHEMA_VERSION) {
1092
1032
  throw new ChatSessionHeaderError(
1093
1033
  sessionId,
1094
- `it declares schemaVersion ${String(header.schemaVersion)} and this build reads ` + String(import_agent_qa_schema6.CURRENT_CHAT_SESSION_SCHEMA_VERSION)
1034
+ `it declares schemaVersion ${String(header.schemaVersion)} and this build reads ` + String(import_agent_qa_schema5.CURRENT_CHAT_SESSION_SCHEMA_VERSION)
1095
1035
  );
1096
1036
  }
1097
1037
  if (header.sessionId !== sessionId) {
@@ -1290,16 +1230,12 @@ function createJsonlSessionLogOn(fs, options) {
1290
1230
  const createdAt = options.now();
1291
1231
  const id = mintChatSessionId(createdAt, random);
1292
1232
  const header = {
1293
- schemaVersion: import_agent_qa_schema6.CURRENT_CHAT_SESSION_SCHEMA_VERSION,
1233
+ schemaVersion: import_agent_qa_schema5.CURRENT_CHAT_SESSION_SCHEMA_VERSION,
1294
1234
  sessionId: id,
1295
1235
  createdAt,
1296
1236
  model: options.model(),
1297
1237
  toolsetHash: options.toolsetHash(),
1298
- // CONDITIONALLY SPREAD, on the composition's own idiom (400-01) and for its reason: an
1299
- // unconditional `surface: options.surface` would put `"surface":undefined` through
1300
- // `JSON.stringify` — which drops it — but would also make an explicit `undefined` and an
1301
- // unsupplied option two spellings of one state at every call site above. Absent here means
1302
- // the option was never given, and that is exactly the pre-400 population's meaning.
1238
+ // Spread conditionally, so absent means the option is not given.
1303
1239
  ...options.surface === void 0 ? {} : { surface: options.surface }
1304
1240
  };
1305
1241
  const created = fs.openSync(pathFor(id), "wx");
@@ -1321,20 +1257,20 @@ function createJsonlSessionLogOn(fs, options) {
1321
1257
  var import_node_fs8 = require("node:fs");
1322
1258
  var import_node_path9 = require("node:path");
1323
1259
  var import_node_sqlite3 = require("node:sqlite");
1324
- var import_agent_qa_schema9 = require("@vostride/agent-qa-schema");
1260
+ var import_agent_qa_schema8 = require("@vostride/agent-qa-schema");
1325
1261
 
1326
1262
  // src/store/sqlite-job-store.ts
1327
1263
  var import_node_fs7 = require("node:fs");
1328
1264
  var import_node_path8 = require("node:path");
1329
1265
  var import_node_sqlite2 = require("node:sqlite");
1330
1266
  var import_agent_qa_agent3 = require("@vostride/agent-qa-agent");
1331
- var import_agent_qa_schema8 = require("@vostride/agent-qa-schema");
1267
+ var import_agent_qa_schema7 = require("@vostride/agent-qa-schema");
1332
1268
 
1333
1269
  // src/store/logical-dump.ts
1334
1270
  var import_node_fs6 = require("node:fs");
1335
1271
  var import_node_path7 = require("node:path");
1336
1272
  var import_node_sqlite = require("node:sqlite");
1337
- var import_agent_qa_schema7 = require("@vostride/agent-qa-schema");
1273
+ var import_agent_qa_schema6 = require("@vostride/agent-qa-schema");
1338
1274
  var SAFE_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
1339
1275
  function requireIdentifier(value) {
1340
1276
  if (!SAFE_IDENTIFIER.test(value)) {
@@ -1391,7 +1327,7 @@ function checkpointDigests(checkpointsRoot) {
1391
1327
  }
1392
1328
  found.push({
1393
1329
  path: (0, import_node_path7.relative)(checkpointsRoot, path).split(import_node_path7.sep).join("/"),
1394
- digest: (0, import_agent_qa_schema7.sha256hex)((0, import_node_fs6.readFileSync)(path, "utf8"))
1330
+ digest: (0, import_agent_qa_schema6.sha256hex)((0, import_node_fs6.readFileSync)(path, "utf8"))
1395
1331
  });
1396
1332
  }
1397
1333
  }
@@ -1406,7 +1342,7 @@ function createLogicalDump(input) {
1406
1342
  };
1407
1343
  }
1408
1344
  function canonicalLogicalDump(dump) {
1409
- return (0, import_agent_qa_schema7.canonicalJson)(dump);
1345
+ return (0, import_agent_qa_schema6.canonicalJson)(dump);
1410
1346
  }
1411
1347
 
1412
1348
  // src/store/sqlite-job-store.ts
@@ -1429,22 +1365,14 @@ var SCHEMA_STATEMENTS = [
1429
1365
  -- Nullable because most rows never fail; written only by recordFailure.
1430
1366
  last_failure_kind TEXT,
1431
1367
  last_failure_reason TEXT,
1432
- -- When somebody asked this job to stop (D-19). A column rather than a status, for the
1433
- -- same reason the claim is one: the job status vocabulary describes lifecycle stages,
1434
- -- and "still queued, but asked to stop" is a fact about a request, not a stage.
1435
- -- Appended LAST deliberately - a column inserted in the middle would move every
1436
- -- positional read of this table for no gain.
1368
+ -- A stop request, not a lifecycle stage. New columns go last, or positional reads would move.
1437
1369
  cancel_requested_at TEXT,
1438
- -- The instant this row was FIRST claimed, kept after the lease is released (425). The
1439
- -- claim column answers who holds the row now; no column answered how long the work took.
1440
- -- Written once by the claim, cleared only by the operator requeue. Appended last, as above.
1370
+ -- When the row was first claimed; survives lease release, cleared only by operator requeue.
1441
1371
  started_at TEXT,
1442
- -- 444.1 D-23: a retrying row is not claimable before this instant. Appended last, as above.
1372
+ -- A retrying row is not claimable before this instant.
1443
1373
  not_before TEXT
1444
1374
  )`,
1445
- // D-08's dedupe is THIS line. Making it a store-level constraint rather than a check the
1446
- // caller performs is what turns "two enqueues of the same work produce one job" from a
1447
- // convention into something no caller, in any process, can get wrong.
1375
+ // The dedupe is this unique index, so no caller in any process can enqueue the same work twice.
1448
1376
  `CREATE UNIQUE INDEX IF NOT EXISTS jobs_kind_idempotency_key
1449
1377
  ON jobs (kind, idempotency_key)`,
1450
1378
  `CREATE TABLE IF NOT EXISTS job_store_fence (
@@ -1464,18 +1392,13 @@ var SCHEMA_STATEMENTS = [
1464
1392
  epoch INTEGER NOT NULL,
1465
1393
  PRIMARY KEY (job_id, attempt, checkpoint_id)
1466
1394
  )`,
1467
- // 388 D-09: the chain-terminal record, beside the jobs it summarizes rather than in a
1468
- // second durable medium. `created_at` is written from the injected clock like every other
1469
- // timestamp in this file — a SQL-side default would leak host time into the D-03 dump and
1470
- // make two identical histories compare unequal.
1395
+ // `created_at` comes from the injected clock; a SQL default would leak host time into the dump.
1471
1396
  `CREATE TABLE IF NOT EXISTS notifications (
1472
1397
  run_id TEXT NOT NULL,
1473
1398
  payload TEXT NOT NULL,
1474
1399
  created_at TEXT NOT NULL
1475
1400
  )`,
1476
- // D-10's dedupe is THIS line, and it is the same idiom as the jobs index above for the same
1477
- // reason: a crash-replayed chain terminal re-attempts the insert, and "one notification per
1478
- // run, ever" has to be something no caller — in this process or the next — can get wrong.
1401
+ // One notification per run, ever: a crash-replayed terminal hits this unique index.
1479
1402
  `CREATE UNIQUE INDEX IF NOT EXISTS notifications_run_id
1480
1403
  ON notifications (run_id)`
1481
1404
  ];
@@ -1484,7 +1407,7 @@ var UNREADABLE_KIND_CONCLUSION = "unreadable_kind";
1484
1407
  var QUARANTINED_UNREADABLE_KIND_REASON = "agent job quarantined at claim: this build does not read the kind recorded for this row, so the row was landed permanently without being parsed. The original kind, id and payload are preserved in the row for inspection.";
1485
1408
  var QUARANTINE_SCAN_BOUND = 1e3;
1486
1409
  function isUnreadableKindRow(row) {
1487
- return !(0, import_agent_qa_schema8.isJobKind)(String(row.kind));
1410
+ return !(0, import_agent_qa_schema7.isJobKind)(String(row.kind));
1488
1411
  }
1489
1412
  function quarantineConclusionOf(row) {
1490
1413
  if (!isUnreadableKindRow(row)) return void 0;
@@ -1666,7 +1589,7 @@ function createSqliteJobStore(options) {
1666
1589
  if (row === void 0) {
1667
1590
  throw new UnknownJobRowError("<missing>");
1668
1591
  }
1669
- return import_agent_qa_schema8.jobSchema.parse({
1592
+ return import_agent_qa_schema7.jobSchema.parse({
1670
1593
  id: String(row.id),
1671
1594
  kind: String(row.kind),
1672
1595
  status: String(row.status),
@@ -1724,8 +1647,7 @@ function createSqliteJobStore(options) {
1724
1647
  attempts: toNumber(row.attempts),
1725
1648
  claimed: row.claimed_at !== null,
1726
1649
  cancelRequested: row.cancel_requested_at !== null,
1727
- // 422 D-16: OMITTED rather than `undefined` when there is nothing to say, so a reader that
1728
- // serializes this row does not publish an empty conclusion key for every ordinary job.
1650
+ // Omitted rather than `undefined`, so a serialized row publishes no empty conclusion key.
1729
1651
  ...conclusionKind === void 0 ? {} : { conclusionKind },
1730
1652
  createdAt: String(row.created_at),
1731
1653
  updatedAt: String(row.updated_at)
@@ -1847,15 +1769,7 @@ function createSqliteJobStore(options) {
1847
1769
  markCancelHonoured.run(now, String(jobId));
1848
1770
  });
1849
1771
  },
1850
- // The 413-13 gap closure, and the checkpoint forget is its load-bearing half.
1851
- //
1852
- // Phase 413's pump composed with no post-run capabilities, so the kind registry selected
1853
- // the STAND-IN analyze-run handler: nineteen rows recorded a `verdicts-authored`
1854
- // checkpoint and reached `done` with nothing authored. Resetting the status alone would
1855
- // not undo that, it would REPEAT it — `selectLatestCheckpoint` reads
1856
- // `ORDER BY attempt DESC`, so the real handler's next attempt would resume on the
1857
- // stand-in's recorded value, author nothing again, and report completion again. So the
1858
- // rows go with the status, inside the same transaction, and the files follow the rows.
1772
+ // Checkpoint rows go with the status, or the real handler resumes on the stand-in's value.
1859
1773
  async requeueTerminal(jobId, fence) {
1860
1774
  const now = clock.now();
1861
1775
  const decided = inTransaction(() => {
@@ -1885,8 +1799,8 @@ function createSqliteJobStore(options) {
1885
1799
  },
1886
1800
  async publishCheckpoint(jobId, checkpointId, payload, fence) {
1887
1801
  const now = clock.now();
1888
- const payloadJson = (0, import_agent_qa_schema8.canonicalJson)(payload);
1889
- const payloadDigest = (0, import_agent_qa_schema8.sha256hex)(payloadJson);
1802
+ const payloadJson = (0, import_agent_qa_schema7.canonicalJson)(payload);
1803
+ const payloadDigest = (0, import_agent_qa_schema7.sha256hex)(payloadJson);
1890
1804
  inTransaction(() => {
1891
1805
  requireFence(fence);
1892
1806
  requireRow(String(jobId));
@@ -1915,7 +1829,7 @@ function createSqliteJobStore(options) {
1915
1829
  try {
1916
1830
  const projection = checkpoints.read(String(jobId), checkpointId);
1917
1831
  if (!projection.found) return authoritative;
1918
- const projectionDigest = (0, import_agent_qa_schema8.sha256hex)((0, import_agent_qa_schema8.canonicalJson)(projection.payload));
1832
+ const projectionDigest = (0, import_agent_qa_schema7.sha256hex)((0, import_agent_qa_schema7.canonicalJson)(projection.payload));
1919
1833
  return projectionDigest === String(row.payload_digest) ? projection : authoritative;
1920
1834
  } catch {
1921
1835
  return authoritative;
@@ -1933,7 +1847,7 @@ function createSqliteJobStore(options) {
1933
1847
  async listNotifications() {
1934
1848
  return selectNotifications.all().map((row) => ({
1935
1849
  runId: String(row.run_id),
1936
- payload: (0, import_agent_qa_schema8.guardRunNotification)(JSON.parse(String(row.payload))),
1850
+ payload: (0, import_agent_qa_schema7.guardRunNotification)(JSON.parse(String(row.payload))),
1937
1851
  createdAt: String(row.created_at)
1938
1852
  }));
1939
1853
  },
@@ -1976,13 +1890,13 @@ function readCurationSnapshot(db, root, ids, runId) {
1976
1890
  if (row === void 0) return void 0;
1977
1891
  try {
1978
1892
  const authoritative = JSON.parse(String(row.payload_json));
1979
- if ((0, import_agent_qa_schema9.sha256hex)((0, import_agent_qa_schema9.canonicalJson)(authoritative)) !== row.payload_digest) {
1893
+ if ((0, import_agent_qa_schema8.sha256hex)((0, import_agent_qa_schema8.canonicalJson)(authoritative)) !== row.payload_digest) {
1980
1894
  throw new CurationSnapshotReadError();
1981
1895
  }
1982
1896
  let payload = authoritative;
1983
1897
  try {
1984
1898
  const cached = readJobCheckpointEnvelope({ root }, String(ids.curateMemory), checkpointId);
1985
- if (cached.found && (0, import_agent_qa_schema9.sha256hex)((0, import_agent_qa_schema9.canonicalJson)(cached.envelope.payload)) === row.payload_digest) {
1899
+ if (cached.found && (0, import_agent_qa_schema8.sha256hex)((0, import_agent_qa_schema8.canonicalJson)(cached.envelope.payload)) === row.payload_digest) {
1986
1900
  payload = cached.envelope.payload;
1987
1901
  }
1988
1902
  } catch {
@@ -1993,7 +1907,7 @@ function readCurationSnapshot(db, root, ids, runId) {
1993
1907
  if (value.curationSnapshot === void 0) return void 0;
1994
1908
  const job = db.prepare("SELECT kind, idempotency_key, payload, attempts FROM jobs WHERE id = ?").get(String(ids.curateMemory));
1995
1909
  if (job === void 0 || job.kind !== "curate-memory" || job.idempotency_key !== `${ids.analyzeRun}->curate-memory` || Number(job.attempts) < Number(checkpoint.attempt) || recordOf(JSON.parse(String(job.payload))).runId !== runId || value.runId !== runId) throw new CurationSnapshotReadError();
1996
- return import_agent_qa_schema9.CurationSnapshotSchema.parse(value.curationSnapshot);
1910
+ return import_agent_qa_schema8.CurationSnapshotSchema.parse(value.curationSnapshot);
1997
1911
  } catch {
1998
1912
  throw new CurationSnapshotReadError();
1999
1913
  }
@@ -2003,7 +1917,7 @@ function toNumber2(value) {
2003
1917
  }
2004
1918
  function toRow(row) {
2005
1919
  if (row === void 0) return void 0;
2006
- const conclusionKind = !(0, import_agent_qa_schema9.isJobKind)(String(row.kind)) && row.status === "failed" && row.last_failure_kind === "permanent" && row.last_failure_reason === QUARANTINED_UNREADABLE_KIND_REASON ? "unreadable_kind" : void 0;
1920
+ const conclusionKind = !(0, import_agent_qa_schema8.isJobKind)(String(row.kind)) && row.status === "failed" && row.last_failure_kind === "permanent" && row.last_failure_reason === QUARANTINED_UNREADABLE_KIND_REASON ? "unreadable_kind" : void 0;
2007
1921
  return {
2008
1922
  status: String(row.status),
2009
1923
  claimed: row.claimed_at !== null,
@@ -2044,15 +1958,11 @@ function createPostProcessingReader(options) {
2044
1958
  const curateMemory = toRow(
2045
1959
  selectJob.get(String(ids.curateMemory))
2046
1960
  );
2047
- const proposeImprovements = toRow(
2048
- selectJob.get(String(ids.proposeImprovements))
2049
- );
2050
- const notification = notificationRow === void 0 ? void 0 : (0, import_agent_qa_schema9.guardRunNotification)(JSON.parse(String(notificationRow.payload)));
1961
+ const notification = notificationRow === void 0 ? void 0 : (0, import_agent_qa_schema8.guardRunNotification)(JSON.parse(String(notificationRow.payload)));
2051
1962
  const curationSnapshot = readCurationSnapshot(db, options.agentQaRoot, ids, runId);
2052
1963
  return {
2053
1964
  ...analyzeRun === void 0 ? {} : { analyzeRun },
2054
1965
  ...curateMemory === void 0 ? {} : { curateMemory },
2055
- ...proposeImprovements === void 0 ? {} : { proposeImprovements },
2056
1966
  ...notification === void 0 ? {} : { notification },
2057
1967
  ...curationSnapshot === void 0 ? {} : { curationSnapshot }
2058
1968
  };
@@ -2101,7 +2011,7 @@ var LOCAL_DAEMON_CAPABILITIES = Object.freeze({
2101
2011
  verifyEmbedderWorkerIncarnation: import_agent_qa_knowledge_local.verifyEmbedderWorkerIncarnation,
2102
2012
  resolveProcessIncarnation: import_agent_qa_knowledge_local.resolveProcessIncarnation,
2103
2013
  removeEmbedderWorkerRegistration: import_agent_qa_knowledge_local.removeEmbedderWorkerRegistration,
2104
- resetEmbedderCapability: () => (0, import_agent_qa_knowledge_local.resetEmbedderCapability)(import_agent_qa_schema10.DEFAULT_EMBEDDING_PROFILE),
2014
+ resetEmbedderCapability: () => (0, import_agent_qa_knowledge_local.resetEmbedderCapability)(import_agent_qa_schema9.DEFAULT_EMBEDDING_PROFILE),
2105
2015
  pinLocalHeadlessExecutionContext: () => {
2106
2016
  (0, import_agent_qa_safety.setActiveExecutionContextResolver)(() => "local-headless");
2107
2017
  }
@@ -2112,8 +2022,6 @@ function receiptWriter(input) {
2112
2022
  executionContext: input.executionContext,
2113
2023
  writerLeaseId: input.lease.leaseId,
2114
2024
  epoch: input.lease.epoch,
2115
- ...input.resolveTrustPriors === void 0 ? {} : { resolveTrustPriors: input.resolveTrustPriors },
2116
- ...input.resolvePromotionPosture === void 0 ? {} : { resolvePromotionPosture: input.resolvePromotionPosture },
2117
2025
  ...input.sourceBuildOrdinal === void 0 ? {} : { sourceBuildOrdinal: input.sourceBuildOrdinal },
2118
2026
  ...input.sourceRunId === void 0 ? {} : { sourceRunId: input.sourceRunId }
2119
2027
  });
@@ -2162,10 +2070,6 @@ var LOCAL_CURATION_CAPABILITIES = Object.freeze({
2162
2070
  reconcileRunOutcomesProjection: import_agent_qa_knowledge_local.reconcileRunOutcomesProjection,
2163
2071
  enqueueCurationCandidateProjection: import_agent_qa_knowledge_local.enqueueCurationCandidateProjection,
2164
2072
  readCanonicalBundleAnchors: import_agent_qa_knowledge_local.readCanonicalBundleAnchors,
2165
- readCanonicalBundleStateDigests: import_agent_qa_knowledge_local.readCanonicalBundleStateDigests,
2166
- readCanaryPostureFacts: import_agent_qa_knowledge_local.canaryPostureFactsFor,
2167
- readStandingGateReceipts: import_agent_qa_knowledge_local.standingReceiptDigestsFor,
2168
- readLowerTrustShares: import_agent_qa_knowledge_local.lowerTrustSharesFor,
2169
2073
  runOutcomesProjectionVersion: import_agent_qa_knowledge_local.RUN_OUTCOMES_PROJECTION_VERSION,
2170
2074
  canaryOutcomeObservationId: import_reader5.canaryOutcomeObservationId,
2171
2075
  maintenance: Object.freeze({
@@ -2189,21 +2093,11 @@ function isTargetName(value) {
2189
2093
  return typeof value === "string" && value.trim().length > 0;
2190
2094
  }
2191
2095
  function recordedTargetsOf(artifact) {
2192
- const source = isRecord(artifact) ? artifact.source : void 0;
2193
- if (!isRecord(source)) return { status: "unknown" };
2194
- if (source.kind === "test") {
2195
- const target = isRecord(source.resolvedDefinition) ? source.resolvedDefinition.target : void 0;
2196
- return isTargetName(target) ? { status: "recorded", names: [target] } : { status: "unknown" };
2197
- }
2198
- if (source.kind !== "suite" || !Array.isArray(source.members)) return { status: "unknown" };
2199
- const names = /* @__PURE__ */ new Set();
2200
- for (const member of source.members) {
2201
- if (!isRecord(member)) return { status: "unknown" };
2202
- if (member.target === void 0 || member.target === null) continue;
2203
- if (!isTargetName(member.target)) return { status: "unknown" };
2204
- names.add(member.target);
2205
- }
2206
- return names.size === 0 ? { status: "unknown" } : { status: "recorded", names: [...names].sort() };
2096
+ const targets = isRecord(artifact) ? artifact.targets : void 0;
2097
+ if (!Array.isArray(targets) || targets.length === 0 || !targets.every(isTargetName)) {
2098
+ return { status: "unknown" };
2099
+ }
2100
+ return { status: "recorded", names: [...new Set(targets)].sort() };
2207
2101
  }
2208
2102
  function createRunsReader(agentQaRoot) {
2209
2103
  function enumerate() {
@@ -2226,25 +2120,11 @@ function createRunsReader(agentQaRoot) {
2226
2120
  list() {
2227
2121
  return Promise.resolve(enumerate());
2228
2122
  },
2229
- /**
2230
- * Resolution runs over the ENUMERATED run documents and matches on the recorded `runId`,
2231
- * never by joining the caller's string onto a path (T-384-08): a `runId` of `../../etc` can
2232
- * therefore address nothing outside the runs directory, because it is never used to build a
2233
- * path at all.
2234
- */
2123
+ // Matches the recorded `runId` over enumerated documents, so `../../etc` addresses nothing.
2235
2124
  get(runId) {
2236
2125
  return Promise.resolve(enumerate().find((document) => document.runId === runId));
2237
2126
  },
2238
- /**
2239
- * Deep replay of one run's `events.jsonl` through the SAME concrete store the v49 bus appends
2240
- * with, so a replayed stream is byte-for-byte what the run emitted.
2241
- *
2242
- * Two cases are deliberately distinct. An absent or empty log is an ordinary empty replay —
2243
- * nothing was recorded, so nothing was lost. A log whose earliest surviving seq is ABOVE the
2244
- * requested resume point means events the caller asked for existed and are gone; that is
2245
- * reported with the bus's own `ReplayIncompleteError` carrying the floor, never papered over
2246
- * by returning the surviving suffix (D-07/D-08).
2247
- */
2127
+ // A resume point below the earliest surviving seq throws `ReplayIncompleteError`.
2248
2128
  readEvents(runId, fromSeq) {
2249
2129
  const recorded = [...new import_agent_qa_runner_local3.FsEventLog({ root: agentQaRoot, runId }).read(0)].sort((left, right) => left.seq - right.seq);
2250
2130
  if (recorded.length === 0) return Promise.resolve([]);
@@ -2254,22 +2134,7 @@ function createRunsReader(agentQaRoot) {
2254
2134
  }
2255
2135
  return Promise.resolve(recorded.filter((event) => event.seq >= fromSeq));
2256
2136
  },
2257
- /**
2258
- * One step's persisted evidence, read back out of the run's own handoff document
2259
- * (387 KREV-02 / D-15).
2260
- *
2261
- * Through `loadCompletedRunHandoff` — the version guard — and NOT through a raw JSON read,
2262
- * which is the load-bearing half. 387-02 gave the guard a present-implies-valid clause for
2263
- * the retrieval trace, so a document whose trace is present but malformed is refused here
2264
- * rather than reaching the why-verb looking well-formed.
2265
- *
2266
- * The ambiguity check is the never-guess law at this seam. `stepIndex` numbers steps per
2267
- * MEMBER TEST, so a run with two tests has two step 0s; when the address does not name a
2268
- * test and more than one candidate answers to it, this reports the candidates rather than
2269
- * picking whichever test the document happened to list first. Picking would have produced a
2270
- * confident, wrong answer to a question that was never asked — and a why-verb that does
2271
- * that is worse than one that refuses, because its answer looks exactly like a right one.
2272
- */
2137
+ // Read through the version guard; an ambiguous step reports its candidates instead of guessing.
2273
2138
  readStepEvidence(runId, address) {
2274
2139
  const document = enumerate().find((candidate) => candidate.runId === runId);
2275
2140
  if (document === void 0) return Promise.resolve({ kind: "run-not-recorded" });
@@ -2287,12 +2152,7 @@ function createRunsReader(agentQaRoot) {
2287
2152
  evidence === void 0 ? { kind: "step-not-found" } : { kind: "found", evidence }
2288
2153
  );
2289
2154
  },
2290
- /**
2291
- * Resolved over the ENUMERATED run directories (T-384-08, T-431-01): the caller's id is only
2292
- * ever compared, never joined onto a path, and the directory must hold a completed handoff
2293
- * recording that same id, so one run's snapshot can never answer for another. A snapshot that
2294
- * is absent, unreadable or gone since `list()` answered is `unknown`, never an error.
2295
- */
2155
+ // The caller's id is compared, never joined onto a path; an absent snapshot is `unknown`.
2296
2156
  getRecordedTargets(runId) {
2297
2157
  const runsDir = (0, import_node_path10.join)(agentQaRoot, import_agent_qa_runner_local3.RUNS_SUBDIR);
2298
2158
  if (!(0, import_node_fs9.existsSync)(runsDir)) return Promise.resolve({ status: "unknown" });
@@ -2312,11 +2172,9 @@ function createRunsReader(agentQaRoot) {
2312
2172
  }
2313
2173
  };
2314
2174
  }
2315
- function createKnowledgeReader(resolveKnowledgeRoot, sightMemoryEntities, resolvePromotionPosture, resolveTrustPriors) {
2175
+ function createKnowledgeReader(resolveKnowledgeRoot, sightMemoryEntities) {
2316
2176
  return createKnowledgeReaderPort({
2317
2177
  resolveKnowledgeRoot,
2318
- ...resolveTrustPriors === void 0 ? {} : { resolveTrustPriors },
2319
- ...resolvePromotionPosture === void 0 ? {} : { resolvePromotionPosture },
2320
2178
  ...sightMemoryEntities === void 0 ? {} : { sightMemoryEntities }
2321
2179
  });
2322
2180
  }
@@ -2350,10 +2208,7 @@ function createKnowledgeReview(input) {
2350
2208
  return next;
2351
2209
  }
2352
2210
  return {
2353
- // 432-12 (D-04/D-05/D-09): one explicit change, applied in the call through the direct writer
2354
- // (432-06). Nothing is filed: the change is committed under the lease, handed to a live
2355
- // holder, or refused by type. A missing identity is minted here, once per call, and returned on
2356
- // the receipt so the caller can retry the same change.
2211
+ // A missing identity is minted once per call and returned, so a retry is the same change.
2357
2212
  change: (request) => serialized(async () => {
2358
2213
  const { knowledgeRoot } = await roots();
2359
2214
  const operationId = request.operationId ?? (0, import_node_crypto4.randomUUID)();
@@ -2367,18 +2222,14 @@ function createKnowledgeReview(input) {
2367
2222
  // `knowledge.reject` or `knowledge.forget`, which is the verb's own op id.
2368
2223
  opId: `knowledge.${request.verb}`,
2369
2224
  executionContext: (input.resolveExecutionContext ?? import_agent_qa_safety.getActiveExecutionContext)(),
2370
- ...input.resolveTrustPriors === void 0 ? {} : { resolveTrustPriors: input.resolveTrustPriors },
2371
- ...input.resolvePromotionPosture === void 0 ? {} : { resolvePromotionPosture: input.resolvePromotionPosture },
2372
2225
  ...input.knowledgeChangeDelegate === void 0 ? {} : { delegate: input.knowledgeChangeDelegate },
2373
2226
  ...authority === void 0 ? {} : { writerAuthority: authority }
2374
2227
  });
2375
2228
  return knowledgeChangeOutput(request.verb, operationId, result);
2376
2229
  })
2377
- // 2026-10-01 (432-17, D-05/D-22): `propose` and `apply` are deleted with the proposal inbox.
2378
2230
  };
2379
2231
  }
2380
2232
  async function applyKnowledgeChange(input) {
2381
- const posture = await input.resolvePromotionPosture?.();
2382
2233
  const ledger = (0, import_agent_qa_knowledge_local.openAddressingLedger)({
2383
2234
  path: (0, import_node_path10.join)(input.agentQaRoot, import_agent_qa_knowledge_local.ADDRESSING_LEDGER_DB_FILE)
2384
2235
  });
@@ -2391,8 +2242,6 @@ async function applyKnowledgeChange(input) {
2391
2242
  opId: input.opId,
2392
2243
  executionContext: input.executionContext,
2393
2244
  resolveBundleShortId: (shortId) => ledger.lookupByShortId(shortId)?.machineId,
2394
- ...input.resolveTrustPriors === void 0 ? {} : { resolveTrustPriors: input.resolveTrustPriors },
2395
- ...posture === void 0 ? {} : { resolvePromotionPosture: posture },
2396
2245
  ...input.delegate === void 0 ? {} : { delegate: input.delegate },
2397
2246
  ...input.writerAuthority === void 0 ? {} : { writerAuthority: input.writerAuthority }
2398
2247
  });
@@ -2425,9 +2274,6 @@ async function withEntityResolutionDeps(input, body) {
2425
2274
  return await body({
2426
2275
  ledger,
2427
2276
  entityIndex,
2428
- // One kind is wired by the tracer. 387-03 registers the remaining sources here and
2429
- // neither the resolver nor the ops change — which is the property the tracer exists
2430
- // to establish before anything expands.
2431
2277
  sources: [(0, import_agent_qa_knowledge_local.createMemorySightingSource)(() => knowledgeRoot)]
2432
2278
  });
2433
2279
  } finally {
@@ -2449,7 +2295,7 @@ async function sweepEntityIndexProjection(input) {
2449
2295
  let embedded = 0;
2450
2296
  const acquire = input.acquireEmbedderCapability ?? import_agent_qa_knowledge_local.acquireEmbedder;
2451
2297
  const capability = await acquire({
2452
- preferredProfile: import_agent_qa_schema10.DEFAULT_EMBEDDING_PROFILE,
2298
+ preferredProfile: import_agent_qa_schema9.DEFAULT_EMBEDDING_PROFILE,
2453
2299
  allowDownload: false,
2454
2300
  agentQaRoot: input.agentQaRoot
2455
2301
  });
@@ -2560,16 +2406,9 @@ function createDraftEvaluation(input) {
2560
2406
  elementsForTest: (filePath, testName) => fingerprints().elements.get(draftIdentityKey({ filePath, testName })) ?? []
2561
2407
  },
2562
2408
  textCorpus,
2563
- // D-19: the gitignored per-draft receipt store, bound over `agentQaRoot` beside the
2564
- // proposals inbox and for its reason — a receipt is machine-local working state under the
2565
- // runtime root, not a committed artifact a pull request has any business showing.
2409
+ // Receipts are machine-local working state under the runtime root, not committed artifacts.
2566
2410
  receipts: (0, import_agent_qa_knowledge_local.createDraftReceiptsStore)({ resolveAgentQaRoot: () => input.agentQaRoot }),
2567
- // D-14's live arm (394-17, step c). `product` is the SAME `observedProduct` gate 3's index
2568
- // is opened against — read off the first gate-run acknowledgment, never derived from
2569
- // configuration — so the stability read and the suite index can never be asking about two
2570
- // different applications. Before any run is acknowledged it is `undefined` and the
2571
- // consultation is skipped; D-04 forbids short-circuiting, so a flip cannot be observed
2572
- // until at least one run has been.
2411
+ // `product` is gate 3's observed product: stability and the index ask about one app.
2573
2412
  suiteStability: {
2574
2413
  port: input.authoringFunnel,
2575
2414
  product: () => observedProduct
@@ -2590,7 +2429,7 @@ var SYSTEM_CLOCK = Object.freeze({
2590
2429
  now: () => (/* @__PURE__ */ new Date()).toISOString()
2591
2430
  });
2592
2431
  var digestJobIdSource = {
2593
- jobIdFor: (kind, idempotencyKey) => (0, import_agent_qa_schema10.asJobId)(`job_${(0, import_agent_qa_schema10.sha256hex16)(`${kind} ${idempotencyKey}`)}`)
2432
+ jobIdFor: (kind, idempotencyKey) => (0, import_agent_qa_schema9.asJobId)(`job_${(0, import_agent_qa_schema9.sha256hex16)(`${kind} ${idempotencyKey}`)}`)
2594
2433
  };
2595
2434
  var DIGEST_JOB_ID_SOURCE = Object.freeze(digestJobIdSource);
2596
2435
  var LocalAgentClosedError = class extends Error {
@@ -2603,10 +2442,7 @@ var LocalAgentClosedError = class extends Error {
2603
2442
  name = "LocalAgentClosedError";
2604
2443
  };
2605
2444
  var UNCLAIMABLE_BY_PROSE_POSTURE = Object.freeze({
2606
- // Frozen to the same depth it is read at (WR-11). The shallow freeze every sibling table
2607
- // here uses is not enough for this one: the VALUES are the arrays the queue claims
2608
- // against, so an unfrozen inner array is a writable disclosure guard reachable from any
2609
- // module that can import the table.
2445
+ // Frozen deep, because the inner arrays are what the queue claims against.
2610
2446
  "masker-active": Object.freeze([]),
2611
2447
  "no-masker": Object.freeze(["curate-memory"])
2612
2448
  });
@@ -2716,7 +2552,7 @@ function createProjectionRecurrenceProvider(resolveKnowledgeRoot, now) {
2716
2552
  function createAnalysisArtifactReader(agentQaRoot) {
2717
2553
  return {
2718
2554
  getArtifact(runId) {
2719
- const path = (0, import_node_path10.join)(agentQaRoot, import_agent_qa_runner_local3.RUNS_SUBDIR, (0, import_agent_qa_runner_local3.slugBranch)(runId), import_agent_qa_schema10.ANALYSIS_FILE);
2555
+ const path = (0, import_node_path10.join)(agentQaRoot, import_agent_qa_runner_local3.RUNS_SUBDIR, (0, import_agent_qa_runner_local3.slugBranch)(runId), import_agent_qa_schema9.ANALYSIS_FILE);
2720
2556
  let bytes;
2721
2557
  try {
2722
2558
  bytes = (0, import_node_fs9.readFileSync)(path, "utf8");
@@ -2724,71 +2560,32 @@ function createAnalysisArtifactReader(agentQaRoot) {
2724
2560
  if (error.code === "ENOENT") return void 0;
2725
2561
  throw error;
2726
2562
  }
2727
- const admission = (0, import_agent_qa_schema10.admitAnalysisArtifactForRun)(
2728
- (0, import_agent_qa_schema10.guardRunAnalysisArtifact)(JSON.parse(bytes)),
2563
+ const admission = (0, import_agent_qa_schema9.admitAnalysisArtifactForRun)(
2564
+ (0, import_agent_qa_schema9.guardRunAnalysisArtifact)(JSON.parse(bytes)),
2729
2565
  runId
2730
2566
  );
2731
2567
  return admission.kind === "admitted" ? admission.artifact : void 0;
2732
2568
  }
2733
2569
  };
2734
2570
  }
2735
- function postRunCapabilities(input, knowledgeRoot, analysisTokenBudget, jobStore, proposeGate1MaxPerJob) {
2571
+ function postRunCapabilities(input, knowledgeRoot, analysisTokenBudget) {
2736
2572
  const postRun = input.postRun;
2737
2573
  if (postRun === void 0) return void 0;
2738
2574
  return {
2739
- // 422 D-14: ONE narrow read — this job's own durable Gate-1 charge, addressed by its own id,
2740
- // through the authoritative `readCheckpoint` the store already publishes. The handler is
2741
- // handed no store, no checkpoint reader and no path; the shape check is `agent`'s, beside
2742
- // the shape it checks, so two hosts cannot disagree about what a readable charge is.
2743
- ...jobStore === void 0 ? {} : {
2744
- readProposeGate1Allowance: async (jobId) => (0, import_agent_qa_agent4.parseProposeGate1Allowance)(
2745
- await jobStore.readCheckpoint((0, import_agent_qa_schema10.asJobId)(jobId), import_agent_qa_agent4.PROPOSE_GATE1_ALLOWANCE_CHECKPOINT)
2746
- )
2747
- },
2748
2575
  loadCompletedRunHandoff: (runId) => (0, import_agent_qa_runner_local3.loadCompletedRunHandoff)(
2749
2576
  (0, import_node_path10.join)(input.agentQaRoot, import_agent_qa_runner_local3.RUNS_SUBDIR, (0, import_agent_qa_runner_local3.slugBranch)(runId), import_agent_qa_runner_local3.HANDOFF_FILE)
2750
2577
  ),
2751
2578
  curateRun: postRun.curateRun,
2752
- // 422 D-13: spread on the conditional idiom this file uses throughout, so an unbound port
2753
- // is an ABSENT member rather than a present `undefined` — the handler decides on presence,
2754
- // in one place, and a host that declined to bind cannot be mistaken for one that bound a
2755
- // hole.
2756
- ...postRun.stageAdversarialProposal === void 0 ? {} : { stageAdversarialProposal: postRun.stageAdversarialProposal },
2757
- // 422-09 (D-14): the Gate-1 leg's four ports and its bound, forwarded on the same
2758
- // presence-spread idiom one line up. The handler's own `screenGate1` requires ALL FOUR before
2759
- // it screens anything, so a host that binds three of them is a host that screens nothing —
2760
- // which is why they are forwarded one by one rather than as a bundle a caller could
2761
- // half-populate without noticing.
2762
- ...postRun.runReplayGate === void 0 ? {} : { runReplayGate: postRun.runReplayGate },
2763
- ...postRun.listBundles === void 0 ? {} : { listBundles: postRun.listBundles },
2764
- ...postRun.gateReceiptsFor === void 0 ? {} : { gateReceiptsFor: postRun.gateReceiptsFor },
2765
- ...postRun.readProposeCorpusPosture === void 0 ? {} : { readProposeCorpusPosture: postRun.readProposeCorpusPosture },
2766
- ...postRun.readMisdirectionRootPosture === void 0 ? {} : { readMisdirectionRootPosture: postRun.readMisdirectionRootPosture },
2767
- ...proposeGate1MaxPerJob === void 0 ? {} : { proposeGate1MaxPerJob },
2768
- // 389 D-09: the artifact's path is DERIVED from the artifact's own runId through the
2769
- // same `runs/<slug>/` law as the handoff read above — `slugBranch` is the traversal
2770
- // guard (T-389-01), and a job payload never carries a path.
2579
+ // Derived from the artifact's own `runId` through `slugBranch`; a payload carries no path.
2771
2580
  persistAnalysis: (artifact) => writeAnalysisArtifact(
2772
- (0, import_node_path10.join)(input.agentQaRoot, import_agent_qa_runner_local3.RUNS_SUBDIR, (0, import_agent_qa_runner_local3.slugBranch)(artifact.runId), import_agent_qa_schema10.ANALYSIS_FILE),
2581
+ (0, import_node_path10.join)(input.agentQaRoot, import_agent_qa_runner_local3.RUNS_SUBDIR, (0, import_agent_qa_runner_local3.slugBranch)(artifact.runId), import_agent_qa_schema9.ANALYSIS_FILE),
2773
2582
  artifact
2774
2583
  ),
2775
- // Plan 02's read side over the derived projection, keyed the projection's way —
2776
- // (product, filePath, testName), the stable identity, NEVER a per-run explicit id.
2777
- // The query arrives already keyed by the author callback; this binding only reads.
2584
+ // Keyed by the stable identity (product, filePath, testName), never a per-run id; read-only.
2778
2585
  readTestHistory: (query) => readProjectedTestHistory(knowledgeRoot, query),
2779
- // D-02's sha-addressed screenshot bytes: the SAME CASS-02 store the runner writes.
2780
- // `FsEvidenceArtifactStore.getBlob` validates the lowercase 64-hex shape BEFORE any
2781
- // path use (T-389-14) and answers ENOENT as honest absence; the runId becomes a path
2782
- // segment only through `slugBranch` inside the store's own constructor.
2783
- //
2784
- // 405-05: THROUGH THE SHARED RULE, not a lambda of its own. `runs.artifact` binds a port over
2785
- // the same `lookupEvidenceBlob` below, and two lambdas over one store would be two answers to
2786
- // where a run's blobs live — agreeing on the day the second is written and diverging the first
2787
- // time either side changes a root. This job wants only the found bytes, so the three-arm
2788
- // lookup collapses here; the SPLIT is what the op needs and what this caller does not.
2586
+ // Through the shared `lookupEvidenceBlob`, so `runs.artifact` and this job agree on blobs.
2789
2587
  readEvidenceBlob: (runId, sha) => readEvidenceBlobBytes({ agentQaRoot: input.agentQaRoot }, runId, sha),
2790
- // Host-resolved and passed through untouched (386 D-15): the budget derives from the
2791
- // same profile resolution as the job model, and this composition adds no knob of its own.
2588
+ // Host-resolved from the job model's profile; this composition adds no knob.
2792
2589
  ...analysisTokenBudget === void 0 ? {} : { analysisTokenBudget }
2793
2590
  };
2794
2591
  }
@@ -2806,7 +2603,7 @@ function chatToolsetIds(registry) {
2806
2603
  }
2807
2604
  function chatToolsetHash(registry) {
2808
2605
  if (registry === void 0) return "unbound";
2809
- return (0, import_agent_qa_schema10.sha256hex16)(chatToolsetIds(registry).join("\n"));
2606
+ return (0, import_agent_qa_schema9.sha256hex16)(chatToolsetIds(registry).join("\n"));
2810
2607
  }
2811
2608
  function projectChatMembers(value, rules, mask) {
2812
2609
  return Object.fromEntries(Object.entries(value).map(([key, member]) => {
@@ -2814,11 +2611,11 @@ function projectChatMembers(value, rules, mask) {
2814
2611
  if (rule === "as-written") return [key, member];
2815
2612
  if (typeof rule === "function") return [key, rule(member, mask)];
2816
2613
  if (rule === "text" && typeof member === "string") return [key, mask(member)];
2817
- return [key, (0, import_agent_qa_schema10.maskPayloadTree)(member, mask)];
2614
+ return [key, (0, import_agent_qa_schema9.maskPayloadTree)(member, mask)];
2818
2615
  }));
2819
2616
  }
2820
2617
  var eachChatRecord = (rules) => (value, mask) => {
2821
- const project = (entry) => isRecord(entry) ? projectChatMembers(entry, rules, mask) : (0, import_agent_qa_schema10.maskPayloadTree)(entry, mask);
2618
+ const project = (entry) => isRecord(entry) ? projectChatMembers(entry, rules, mask) : (0, import_agent_qa_schema9.maskPayloadTree)(entry, mask);
2822
2619
  return Array.isArray(value) ? value.map(project) : project(value);
2823
2620
  };
2824
2621
  var CHAT_EVENT_BASE = {
@@ -2902,7 +2699,6 @@ function composeLocalAgent(input) {
2902
2699
  // which is also what its header will say. A container seeded from another session's override
2903
2700
  // would make one conversation's verb the next conversation's opening posture.
2904
2701
  state: (0, import_agent_qa_agent4.createChatState)({ activeModel: composedChatModelName })
2905
- // 432-13 (D-14): no pin holder. `/pin` left chat resolution with the op gate it tightened.
2906
2702
  };
2907
2703
  chatScopes.set(sessionId, scope);
2908
2704
  return scope;
@@ -2913,11 +2709,7 @@ function composeLocalAgent(input) {
2913
2709
  const chatSessionLog = createJsonlSessionLog({
2914
2710
  root: input.agentQaRoot,
2915
2711
  now: () => clock.now(),
2916
- // THE COMPOSED MODEL, not a session's override, and the difference is a leak this keying closes.
2917
- // This thunk is read when a header is WRITTEN, which happens exactly once per session and only
2918
- // for a session that has not existed until now — so no `/model` can have run in it. Answering
2919
- // with a live override would stamp one conversation's switch onto the opening header of every
2920
- // conversation opened after it. 441 GAP3-D4: written and listed through the declared mask.
2712
+ // The composed model, masked: a live override would stamp one session's switch on later ones.
2921
2713
  model: () => input.mask(composedChatModelName),
2922
2714
  toolsetHash: () => chatToolsetHash(composedRegistry)
2923
2715
  });
@@ -2968,14 +2760,7 @@ function composeLocalAgent(input) {
2968
2760
  stage = (0, import_agent_qa_agent4.createPlannerStage)({
2969
2761
  model: chatModelsByName.get(activeName) ?? input.chatModel,
2970
2762
  tools: (0, import_agent_qa_agent4.projectPlannerTools)(composedRegistry, CHAT_PLANNER_CALLER),
2971
- // Read PER REQUEST — not per turn and not per stage (392 plan 13, CR-02). A stage
2972
- // is shared by every session planning under the same model name, so a context
2973
- // thunk taking no argument had exactly one conversation to answer with, and on
2974
- // two interleaved turns it answered with whichever one published last. Taking the
2975
- // requesting session's id makes "the conversation this request replays" a fact
2976
- // about the call. The read is still LIVE, so a `/model` override still moves what
2977
- // the prompt states without the stage being rebuilt, and the conversation block
2978
- // still carries what compaction left rather than a second replay of the log.
2763
+ // Read per request: a stage is shared by every session planning under one model.
2979
2764
  context: (contextRequest) => {
2980
2765
  const scope = chatScopeFor(contextRequest.sessionId).state.read();
2981
2766
  return { activeModel: scope.activeModel, conversation: scope.conversation };
@@ -2989,41 +2774,22 @@ function composeLocalAgent(input) {
2989
2774
  const chatCompaction = input.chatAccounting === void 0 ? void 0 : (0, import_agent_qa_agent4.createChatCompactionHook)({
2990
2775
  accounting: input.chatAccounting,
2991
2776
  now: () => clock.now(),
2992
- // 392-06's flagged consumer, wired: what compaction leaves IS the conversation the
2993
- // prompt renders, and it lands in the live state on EVERY turn rather than only on a
2994
- // triggered pass — a sink that fired only when a pass ran would leave the prompt holding
2995
- // a stale conversation on every quiet turn. Into the SESSION'S OWN container (plan 13):
2996
- // the id is the compacted turn's, so a pruned history cannot land in another
2997
- // conversation however many turns are in flight.
2777
+ // What compaction leaves is the conversation the prompt renders, kept per session.
2998
2778
  onConversation: (messages, sessionId) => {
2999
2779
  chatScopeFor(sessionId).state.setConversation(messages);
3000
2780
  }
3001
2781
  });
3002
2782
  const chatTurn = (0, import_agent_qa_agent4.createTurnEngine)({
3003
2783
  table: import_agent_qa_agent4.CHAT_RESOLVER_TABLE,
3004
- // 392 plan 02, D-09: the real conjunction grammar, quote-aware. The tracer's
3005
- // whole-utterance placeholder is gone; this is the seam filled, not widened.
2784
+ // The real conjunction grammar, quote-aware.
3006
2785
  split: import_agent_qa_agent4.splitClauses,
3007
2786
  reconcile: input.chatReconcile ?? import_agent_qa_agent4.deterministicOverrideStrategy,
3008
2787
  sessionLog: trackedChatSessionLog,
3009
- // RESEARCH Pitfall 1: per-STAGE minting, because origin is a per-call fact. A deterministic
3010
- // table hit is a person typing and mints `human`; a planner-planned call mints `agent`, and the
3011
- // turn's receipts record which.
3012
- // 2026-10-01 (432-21, D-12): NOT STAMPED WITH THE SESSION ANY MORE. The session id rode the
3013
- // caller for the gate's deny overlay (plan 13, W-03) and the overlay is deleted (432-13/18/19);
3014
- // nothing reads `FunctionCaller.sessionId`. The session still reaches the ops that record it
3015
- // through the turn's own session facts, not through the caller.
2788
+ // Minted per stage: a table hit is a person typing (`human`); a planned call is `agent`.
3016
2789
  mint: {
3017
2790
  forStage: (stage) => stage === "resolver" ? CHAT_RESOLVER_CALLER : CHAT_PLANNER_CALLER
3018
2791
  },
3019
- // 399.1 D-01/D-03/D-05: the classified envelope, built HERE because this closure is the one
3020
- // place in the system holding both the registry and the invoke call. The chat subtree cannot
3021
- // reach a spec by construction (384 FUNC-03), so the verdict and the render fold have to arrive
3022
- // as data on this return — which is what `ChatInvokeAnswer` is. `foldFunctionResult` owns the
3023
- // fail-closed rule so both composition roots get the same one rather than a copy each.
3024
- //
3025
- // invokeFunction validates canonical output; it does not promise masking. Classify those
3026
- // original bytes before projecting the answer into results[] and the durable clause_result.
2792
+ // Classify the original bytes before projecting: `invokeFunction` does not mask.
3027
2793
  invoke: async (functionId, invokeInput, caller) => {
3028
2794
  if (composedRegistry === void 0) {
3029
2795
  throw new TypeError("a chat turn ran before its registry finished composing");
@@ -3034,24 +2800,9 @@ function composeLocalAgent(input) {
3034
2800
  },
3035
2801
  ...chatPlanner === void 0 ? {} : { planner: chatPlanner },
3036
2802
  ...chatCompaction === void 0 ? {} : { compaction: chatCompaction },
3037
- // 392 plan 08: the directive handlers, which is what turns the engine's
3038
- // `directive recognised but no handler` refusal from the shipped behaviour into an
3039
- // unreachable arm on this host. `/help` and `/quit` are REPL chrome and answer in prose;
3040
- // `/model` changes what the session is and returns the EFFECT it had. (432-13: `/pin` is gone.)
3041
- //
3042
- // RESOLVED PER SESSION (plan 13, CR-02 / W-03). Each one acts on a conversation rather than the
3043
- // project, so the handler set is built over the scope of the session running the turn:
3044
- // `/model` moves that conversation's model and `/quit` asks that loop to end.
2803
+ // Resolved per session: `/model` and `/quit` act on the conversation running the turn.
3045
2804
  directives: (sessionId) => ({
3046
- // THE BATCH PRE-FLIGHT (392-14, E3/E3b). The engine asks this of EVERY directive of a turn
3047
- // before it applies the first one, so a refused later directive leaves an earlier one
3048
- // unapplied.
3049
- //
3050
- // IT APPLIES NOTHING. `/model` RESOLVES the model and caches it under its name — a cache is
3051
- // not the session's state, and the session's own `activeModel` is left exactly where it was.
3052
- // The resolution is also the only part of `/model` that can fail, so caching it here is what
3053
- // makes the later apply unable to throw after an earlier directive has already been carried
3054
- // out.
2805
+ // Applies nothing: `/model` resolves and caches by name, so the apply cannot throw midway.
3055
2806
  validate: async (directive, argument) => {
3056
2807
  if (directive === "model" && argument !== void 0 && input.chatModelFor !== void 0) {
3057
2808
  chatModelsByName.set(argument, await input.chatModelFor(argument));
@@ -3073,17 +2824,7 @@ function composeLocalAgent(input) {
3073
2824
  }
3074
2825
  }),
3075
2826
  state: (sessionId) => chatScopeFor(sessionId).state,
3076
- // D-04: the configuration RE-READ, per turn and PER SESSION. A thunk rather than a captured
3077
- // value, because the drift worth detecting is precisely the one that happens underneath a
3078
- // running session — a model resolved differently by the host, or a build whose registry
3079
- // reaches further than the one this session opened against. The engine folds the log for what
3080
- // was last recorded and emits `model_change` / `active_tools_change` on the difference.
3081
- //
3082
- // THE MODEL IT REPORTS IS THE ASKING SESSION'S (plan 13). A composition-wide read would answer
3083
- // one conversation's `/model` override for every conversation, and the per-turn diff would
3084
- // then write a `model_change` into sessions nobody had switched.
3085
- //
3086
- // 441 GAP3-D4: masked, because the log it is compared with is masked on append.
2827
+ // Re-read per turn and per session, and masked like the log it is compared with.
3087
2828
  config: (sessionId) => {
3088
2829
  const ids = chatToolsetIds(composedRegistry);
3089
2830
  return {
@@ -3091,20 +2832,9 @@ function composeLocalAgent(input) {
3091
2832
  toolset: { hash: chatToolsetHash(composedRegistry), ids }
3092
2833
  };
3093
2834
  },
3094
- // 395-08 D-14/D-15 · CFGM-05: the target vocabulary the PRE-DISPATCH write_test route reads.
3095
- // Bound off the SAME host verb `authoringRead.configuredTargetNames` uses, so the seam that
3096
- // decides whether to offer a scaffold and the loop that later checks what a model emitted are
3097
- // reading one answer rather than two. A host that cannot name its targets binds nothing and the
3098
- // route never runs, which leaves the shipped dispatch and the loop's own backstop exactly as
3099
- // they were.
3100
- // BOUND ONLY WHERE THE LOOP IS. A host that cannot author has nothing for this route to route,
3101
- // and binding it anyway would answer an empty vocabulary — which the route reads as the
3102
- // from-zero case and refuses, reporting the wrong cause for a host whose real problem is that
3103
- // `authoring.draft.write` is unbound. Absent leaves the shipped dispatch untouched.
2835
+ // Bound only where the loop is; elsewhere an empty vocabulary refuses with the wrong cause.
3104
2836
  ...input.draftAuthoring !== void 0 && input.runExecution !== void 0 ? { configuredTargets: () => input.draftAuthoring.configuredTargetNames() } : {},
3105
- // 395-13 D-14: where the scaffold proposal is rendered before the in-turn apply is invoked.
3106
- // Conditionally spread on the exact idiom above, so a host that binds no surface leaves the
3107
- // field ABSENT and the engine's own "renders nothing" posture is what answers — in one place.
2837
+ // Spread conditionally, so a host binding no surface leaves `present` absent.
3108
2838
  ...input.chatPresent === void 0 ? {} : { present: input.chatPresent },
3109
2839
  now: () => clock.now(),
3110
2840
  mintTurnId: () => `turn-${(0, import_node_crypto4.randomUUID)()}`
@@ -3120,19 +2850,7 @@ function composeLocalAgent(input) {
3120
2850
  ...input.resolveWriterAuthority === void 0 ? {} : { resolveWriterAuthority: input.resolveWriterAuthority }
3121
2851
  }).list()
3122
2852
  },
3123
- // D-14's history half, over the run-outcome projection's own read side (394-17, step b).
3124
- //
3125
- // ONE CONNECTION PER VERB, opened read-only and closed in `finally`, on the shape
3126
- // `readProjectedTestHistory` above already takes. An absent database, a store predating the
3127
- // projection tables and an identity nothing has counted all answer EMPTY — which
3128
- // `assessSuiteStability` turns into the honest `no-history` posture rather than into a clean
3129
- // bill of health. Any other read failure propagates: a corrupt store is not "no history".
3130
- //
3131
- // THE OUTCOME WORDS. The durable window keeps one boolean per build (`last_outcomes_json`),
3132
- // which is what the fold reduced each member's outcome to, so this spells it back with the two
3133
- // words it was reduced FROM. Nothing downstream compares those strings against a member list —
3134
- // `assessSuiteStability` counts DISTINCT values — so a flip in the window is a flip here, and
3135
- // no vocabulary is invented beyond what the projection actually kept.
2853
+ // One read-only connection per verb; absent data answers empty, other failures propagate.
3136
2854
  outcomes: {
3137
2855
  testsIn: async (product, filePath) => {
3138
2856
  const knowledgeRoot = await input.knowledgeRoot();
@@ -3166,145 +2884,47 @@ function composeLocalAgent(input) {
3166
2884
  return runsReader.get(runId);
3167
2885
  }
3168
2886
  },
3169
- // 387 D-01: this host's list verbs are live sighting sites. Every entity a listing,
3170
- // an inspect, a diff or a show surfaces gets its permanent address the first time it
3171
- // is surfaced — which is what "pre-existing entities get IDs the day they are first
3172
- // referenced" means in practice, and it costs the creation paths nothing.
2887
+ // List verbs are live sighting sites: an entity gets its address when first surfaced.
3173
2888
  knowledge: createKnowledgeReader(
3174
2889
  input.knowledgeRoot,
3175
- createMemorySightingHook(entityResolutionInput),
3176
- input.resolvePromotionPosture,
3177
- input.resolveTrustPriors
2890
+ createMemorySightingHook(entityResolutionInput)
3178
2891
  ),
3179
2892
  config: input.config,
3180
2893
  entities: createEntityDirectory(entityResolutionInput),
3181
- // 387-08 KREV-01: the WRITE half, and it is present in every local composition because a
3182
- // local host owns the knowledge root it serves from. It stays an OPTIONAL dep so a host
3183
- // that is genuinely read-only — a listing, a remote surface — reports the four mutating
3184
- // verbs as `unbound` BY NAME rather than as a hole in the catalogue.
2894
+ // Optional, so a read-only host reports the mutating verbs as `unbound` by name.
3185
2895
  knowledgeReview: createKnowledgeReview({
3186
- ...input.resolveTrustPriors === void 0 ? {} : { resolveTrustPriors: input.resolveTrustPriors },
3187
- ...input.resolvePromotionPosture === void 0 ? {} : { resolvePromotionPosture: input.resolvePromotionPosture },
3188
2896
  agentQaRoot: input.agentQaRoot,
3189
2897
  resolveKnowledgeRoot: input.knowledgeRoot,
3190
2898
  ...input.knowledgeChangeDelegate === void 0 ? {} : { knowledgeChangeDelegate: input.knowledgeChangeDelegate },
3191
2899
  ...input.resolveWriterAuthority === void 0 ? {} : { resolveWriterAuthority: input.resolveWriterAuthority },
3192
- // 432-12: the host's own context, so a direct change is recorded under the context it was
3193
- // actually made in. (432-39: the registry no longer receives it; this is its one reader.)
2900
+ // The host's own context, so a direct change records the context it is made in.
3194
2901
  ...input.resolveExecutionContext === void 0 ? {} : { resolveExecutionContext: input.resolveExecutionContext }
3195
2902
  }),
3196
- // 388 D-14: chip truth, on EVERY local host and not gated on `postRun`. The two are
3197
- // different questions and conflating them would be the bug: `postRun` says whether this
3198
- // host can DO the chain's work, while this says whether it can SEE what the chain did —
3199
- // and a host that never drains anything (a status query, a listing, the CLI after a
3200
- // handed-off tail) is exactly the caller that most needs to read durable state.
3201
- //
3202
- // Given the SAME id source the queue below is built with, so the rows projected are the
3203
- // rows enqueued. It opens nothing here: the reader constructs no handle until it is asked
3204
- // a question, and never one that could create the database (Pitfall 4).
2903
+ // On every host, unlike `postRun`: a host that never drains still reads what the chain did.
3205
2904
  postProcessing: createPostProcessingReader({
3206
2905
  agentQaRoot: input.agentQaRoot,
3207
2906
  idSource: input.idSource ?? DIGEST_JOB_ID_SOURCE
3208
2907
  }),
3209
- // 405 D-03: the run-detail projection read, conditionally spread on the house rule — an
3210
- // absent port must be an ABSENT field and not a present `undefined` one, because the
3211
- // registry reads exactly this record to decide what the capability LISTS as. Unlike
3212
- // `postProcessing` above it is NOT present on every local host: chip truth is readable from
3213
- // `agentQaRoot` alone, but a run's projected step tree lives in a dashboard database that
3214
- // only the dashboard process holds.
3215
- // 423 D-04: runs.evidence shares this reader with runs.detail and the blob reader
3216
- // below. The registry requires both for evidence without narrowing detail availability.
2908
+ // An absent port must be an absent field: the registry lists capabilities off this record.
3217
2909
  ...input.runDetail === void 0 ? {} : { runDetail: input.runDetail },
3218
- // 405-05 D-12/D-13: the run-scoped evidence-blob read, on EVERY local host and NOT
3219
- // conditionally spread — unlike `runDetail` one line up, which needs a dashboard database
3220
- // this host may not hold, every local composition has a runtime root and therefore has the
3221
- // run directories these blobs live in. It is the SAME reader the analysis job's
3222
- // `readEvidenceBlob` is built over, so "resolve this ref" and "diet this evidence" cannot
3223
- // disagree about where a blob is.
2910
+ // On every host, and the same reader the analysis job uses, so both agree where a blob is.
3224
2911
  evidenceBlobs: createEvidenceBlobReader({ agentQaRoot: input.agentQaRoot }),
3225
- // Present iff this host can execute a run. The registry reads the SAME record to
3226
- // decide what `runs.start` lists as, so the declaration and the dispatch cannot
3227
- // disagree about whether this composition can run it (D-16).
2912
+ // Present only if this host can run; the registry lists `runs.start` from the same record.
3228
2913
  ...input.runExecution === void 0 ? {} : {
3229
2914
  runInvocation: createLocalRunInvocation({
3230
2915
  agentQaRoot: input.agentQaRoot,
3231
2916
  execution: input.runExecution
3232
2917
  })
3233
2918
  },
3234
- // 389 D-10/D-11: the artifact read `analysis.get` binds through, and the D-08
3235
- // recurrence join the one renderer consults. Both are bindable from `agentQaRoot`
3236
- // and the knowledge root alone, so every local composition carries them — a host
3237
- // with no artifact on disk serves the floor, and a host with no recorded history
3238
- // renders the explicit no-history clause; neither is a refusal (plan 05's law).
2919
+ // Bindable from the roots alone, so every host serves the floor or the no-history clause.
3239
2920
  analysis: createAnalysisArtifactReader(input.agentQaRoot),
3240
2921
  recurrence: recurrence.provider,
3241
- // 398 D-09 (dated 2026-08-17): the catalog port `agent.explain` binds through, handed
3242
- // straight through from the host. Conditionally spread rather than assigned, on the
3243
- // `runInvocation` precedent: an absent port must be an ABSENT field and not a present
3244
- // `undefined` one, because the registry reads exactly this record to decide what the
3245
- // capability LISTS as — so the declaration and the dispatch cannot disagree about whether
3246
- // this composition can explain itself (D-16).
2922
+ // Spread conditionally so `agent.explain` lists `unbound` where no catalog is handed in.
3247
2923
  ...input.capabilityCatalog === void 0 ? {} : { capabilityCatalog: input.capabilityCatalog },
3248
- // 403 D-03: the live-view mint seam, conditionally spread on the same rule — an absent port
3249
- // must be an ABSENT field, so `runs.liveurl` declares `unbound` where no origin is served.
2924
+ // Spread conditionally, so `runs.liveurl` declares `unbound` where no origin is served.
3250
2925
  ...input.liveView === void 0 ? {} : { liveView: input.liveView },
3251
- // 390 D-12/D-13: the three quarantine verbs, bound HERE and therefore on BOTH hosts —
3252
- // the CLI tail and 386's daemon compose the same root, which is the whole point of
3253
- // 385 D-15 (a second binding site is a second answer to "what is quarantined").
3254
- //
3255
- // Present in every local composition for the same reason the knowledge WRITE half is: a
3256
- // local host owns the committed knowledge root the ledger lives at. It stays an OPTIONAL
3257
- // dep so a genuinely read-only or remote composition reports all three `unbound` BY NAME
3258
- // rather than answering an empty list about a ledger it has never been able to open.
3259
- //
3260
- // The port takes the root as a FACTORY (the CLI resolves it asynchronously) and the clock
3261
- // as an argument, so this composition supplies both and the implementation reads neither
3262
- // of its own accord. Nothing opens here: the first byte is read when a verb is invoked.
3263
- //
3264
- // 390-09 / CR-03: the SAME `resolveWriterAuthority` the apply path consumes three bindings
3265
- // above, and it is what lands each host on the correct lease arm with zero daemon changes.
3266
- // The daemon supplies it (`cli/src/daemon/host.ts:1839`) because it acquired the lease at
3267
- // startup and holds it for its lifetime, so the verbs ride that authority instead of asking
3268
- // for a lease the process cannot be granted twice; the CLI in-process host supplies nothing,
3269
- // so the verbs acquire and release per call. Conditionally spread like its neighbour rather
3270
- // than assigned through: an absent authority must be an ABSENT field, not a present
3271
- // `undefined` one, so the implementation's `?.()` arm distinguishes the two hosts.
3272
- //
3273
- // 390-12 / D-01: the identity mint is handed straight through, REQUIRED and unspread. The
3274
- // verbs key the committed ledger on `filePath` and every reader compares those bytes with
3275
- // `===`, so a host that supplied nothing would be back to storing whatever a human typed —
3276
- // the round-2 regression. Unlike the authority above there is no host without a checkout
3277
- // root, so the absent case is a compile error rather than a second posture.
3278
- // 394-07 D-12 / WTST-05: the honesty funnel's reads, bound HERE and therefore on BOTH hosts,
3279
- // which is the whole point of 385 D-15 — a second binding site would be a second answer to
3280
- // "how many drafts did this session keep", and that number is the one WTST-05 exists to keep
3281
- // honest.
3282
- //
3283
- // UNCONDITIONAL, unlike the loop's two halves above it, and the asymmetry is the point: the
3284
- // funnel is a READ over records this host owns by owning `agentQaRoot`, so every local
3285
- // composition can answer it whether or not it can author anything. An empty receipts
3286
- // directory and an absent one are the same answer, and nothing opens here — the first byte
3287
- // is read when the verb is invoked.
3288
- //
3289
- // THE RECEIPTS PORT IS THE READ HALF ONLY. The evaluator one binding below is handed the
3290
- // same store's `put`; this bundle names `list` and nothing else, so the projection is
3291
- // structurally unable to write the records it reports on. Two narrow mirrors over one store
3292
- // rather than one wide port.
3293
- //
3294
- // 2026-10-01 (432-17, D-06): the bundle no longer reads the proposals inbox. 2026-10-02
3295
- // (quick 261002-ctr): the terminal stage is `writeEligible`, read off the receipts this
3296
- // bundle lists (see `projectAuthoringFunnel`).
3297
- //
3298
- // `outcomes` IS BOUND (394-17, step b): the port's two verbs now LEAD with `product`, so the
3299
- // binding reads the run-outcome projection on its own primary key instead of guessing a
3300
- // partition or serving every product's history under one file path.
3301
- //
3302
- // ASSEMBLED ABOVE rather than inline, because the gate-2 flip path is handed the SAME
3303
- // bundle: one composition-level answer to "what does this project know about this suite",
3304
- // reached by the funnel read op and by the evaluator's consultation alike.
2926
+ // The funnel reads records this host owns, so it is unconditional; its receipts port lists.
3305
2927
  authoringFunnel,
3306
- // 2026-10-01 (432-17, D-05/D-22): the proposals inbox (391 PROP-03) is not bound — it is deleted
3307
- // with its ops. Old files under `<agentQaRoot>/proposals/` are never opened again.
3308
2928
  ...input.feedback === void 0 ? {} : { feedback: input.feedback },
3309
2929
  ...input.feedbackReads === void 0 ? {} : { feedbackReads: input.feedbackReads },
3310
2930
  quarantine: (0, import_agent_qa_knowledge_local.createQuarantineOperations)({
@@ -3313,24 +2933,13 @@ function composeLocalAgent(input) {
3313
2933
  mintIdentityPath: input.mintQuarantineIdentityPath,
3314
2934
  ...input.resolveWriterAuthority === void 0 ? {} : { resolveWriterAuthority: input.resolveWriterAuthority }
3315
2935
  }),
3316
- // 392 D-24: the turn engine assembled above. Bound HERE and therefore on BOTH hosts, so
3317
- // `agent.ask` is a real capability wherever the composition root runs — and unbound nowhere,
3318
- // which is what lets 397's parity suite read it off the registry with no chat-specific case.
2936
+ // Bound here, so `agent.ask` is a real capability on every host.
3319
2937
  chatTurn: {
3320
2938
  // The engine also echoes authored clause text on receipts and refusal answers. Mask
3321
2939
  // the complete outward projection after execution, never the message it dispatches.
3322
2940
  runTurn: async (turnInput) => projectChatMembers(await chatTurn.runTurn(turnInput), CHAT_TURN_RESULT_RULES, input.mask)
3323
2941
  },
3324
- // 393 D-01 / D-15: the keep-gate evaluator's two host halves, bound HERE and therefore on
3325
- // BOTH hosts — the CLI and 386's daemon compose this same root, which is the whole point of
3326
- // 385 D-15 (a second binding site would be a second answer to "is this draft worth keeping",
3327
- // and the two would disagree about a decision that gets written into a durable receipt).
3328
- //
3329
- // Conditionally spread on BOTH halves, because a capability that can parse but cannot run is
3330
- // not a degraded evaluator — it is a host that must say `unbound` by name. `runs.start` is
3331
- // dispatched through the registry this very call is about to produce, which is the same
3332
- // deferred reference the chat engine takes and is safe for the same reason: no op can run
3333
- // before the registry it is registered in has been built.
2942
+ // Both halves spread conditionally: a host that can parse but not run says `unbound`.
3334
2943
  ...input.draftAuthoring === void 0 || input.runExecution === void 0 ? {} : {
3335
2944
  draftEvaluation: createDraftEvaluation({
3336
2945
  authoring: input.draftAuthoring,
@@ -3351,50 +2960,7 @@ function composeLocalAgent(input) {
3351
2960
  }
3352
2961
  })
3353
2962
  },
3354
- // 394 D-01 / WTST-01: the authoring LOOP's two halves, bound HERE and therefore on BOTH
3355
- // hosts, under the SAME condition the evaluator above is bound under — the loop's stage 4
3356
- // dispatches `authoring.draft.verify`, so a host that cannot verify a draft cannot author
3357
- // one either, and a third answer to "can this host author" would be a third thing to keep
3358
- // in step.
3359
- //
3360
- // THE READ HALF IS `getAuthoringBrief`'S FIRST PRODUCTION CALLER. The port has been
3361
- // implemented and unbound since v51 (`knowledge-local/src/serving/authoring-reader.ts`),
3362
- // which means every field of its contract is crossing a real seam for the first time here;
3363
- // a mismatch surfaces at this binding rather than in a surface. The reader is built PER
3364
- // CALL over a freshly resolved knowledge root, on the standing-approval reader's stated
3365
- // reasoning — the CLI resolves its root asynchronously and per call, and a root captured
3366
- // once would serve a brief out of a knowledge tree the invocation is not serving from. No
3367
- // `product` is bound: the composition does not own one, and the SCOPE arrives on the op's
3368
- // input, which is the honest half of the pair the reader filters on.
3369
- //
3370
- // `suiteTextCorpus` is the SAME host walk gate 3's degraded lane already consumes, reached
3371
- // here for stage 2's pre-authoring screen. One walk, one notion of what a suite test's text
3372
- // is; a second enumeration would let the screen and the gate disagree about the same pair.
3373
- //
3374
- // THE WRITE HALF bundles the model, the shelf and the verify dispatch, because none of the
3375
- // three is independently bindable: a host with a model and no shelf cannot author, one with
3376
- // a shelf and no model has nothing to author with, and one that can do both but cannot
3377
- // verify would produce a test and have nothing to say about whether it is worth keeping.
3378
- // The model is a FACTORY, resolved at most once and only when a draft is actually compiled,
3379
- // the same idiom `openJobs` uses — binding this capability must not construct a client for a
3380
- // host that never authors.
3381
- //
3382
- // WHY THE ROUTER (plan 05) WILL READ `DraftRunPortLike.get`'s `CompletedRunHandoff` AND NOT
3383
- // `runs.get`'s PROJECTION. D-08 routes on run EVIDENCE — step terminations, planning
3384
- // failure, cycle flags, the per-step sub-action record — and `runs.get` projects a
3385
- // `RunDetail` in which none of that survives (`stepCount` is its only step-shaped field).
3386
- // This is `createDraftEvaluation`'s own posture, stated one layer out: the op is reached for
3387
- // what an op owns, and the reader is read for evidence no projection carries. A router built
3388
- // on the projection would have to infer a mechanics failure from a member verdict, and
3389
- // inferring an app defect out of a bare member verdict is precisely the cardinal error D-08
3390
- // exists to make unreachable.
3391
- //
3392
- // A NOTE FOR WHOEVER EDITS THIS PARAGRAPH. The arch dependency scan reads import specifiers
3393
- // out of this file's RAW BYTES, comments included, so any prose shaped like an import's
3394
- // trailing clause — the keyword, then a quoted phrase — is reported as an undeclared
3395
- // external dependency of this package. Two drafts of this comment tripped it, once on a
3396
- // sentence about verdicts and once on the sentence explaining the first. Keep quoted phrases
3397
- // away from that keyword here.
2963
+ // The arch import scan reads comments too: never put a quote after the word `from`.
3398
2964
  ...authoringLoopHost === void 0 ? {} : {
3399
2965
  authoringRead: {
3400
2966
  async getAuthoringBrief(intent, scope) {
@@ -3402,35 +2968,21 @@ function composeLocalAgent(input) {
3402
2968
  return (0, import_agent_qa_knowledge_local.createAuthoringReader)({ knowledgeRoot }).getAuthoringBrief(intent, scope);
3403
2969
  },
3404
2970
  suiteTextCorpus: () => authoringLoopHost.suiteTextCorpus(),
3405
- // 394-33 · WR-07: the `target` vocabulary stage 3's compile prompt serves. Bound off the
3406
- // SAME port the brief and the corpus come from, so a host that can run the loop's read
3407
- // stages can name its own targets by construction — see the port's own doc.
2971
+ // Off the same port as the brief and corpus, so a loop host names its own targets.
3408
2972
  configuredTargetNames: () => authoringLoopHost.configuredTargetNames()
3409
2973
  },
3410
- // 394-26 · WINDOWS 110: the scope an intent-only call is authored at, bound HERE and so on
3411
- // BOTH hosts, off the same port the read and compile halves come from. Its own deps key
3412
- // rather than a third verb on `authoringRead`, because deriving a scope needs the resolved
3413
- // config and the workspace while the brief needs a knowledge index — a host can have one
3414
- // without the other, and the op refuses on THIS key by name when a scope-less call arrives
3415
- // at a composition that never bound it.
2974
+ // Its own key: a scope needs config and workspace, the brief needs an index.
3416
2975
  authoringScope: {
3417
2976
  deriveDefault: () => authoringLoopHost.deriveDefaultScope()
3418
2977
  },
3419
2978
  draftShelf: {
3420
2979
  model: async () => await input.model(),
3421
2980
  write: (contents) => authoringLoopHost.stageDraft(contents),
3422
- // 394-06 D-09/D-20: the ONE RFC-6902 applier, reached at the host because it needs the
3423
- // yaml CST and neither `agent` nor this package may depend on `core`. Same seam,
3424
- // same reason and same shape as `stageDraft` right above it.
2981
+ // The one RFC 6902 applier, at the host because it needs `core`'s yaml CST.
3425
2982
  applyPatches: (draft, patchSet) => authoringLoopHost.applyPatchesToDraft(draft, patchSet),
3426
- // 432 D-06/D-07: the direct writer the loop's final write and the edit op reach. Same seam
3427
- // and same reason as the two verbs above: the boundary check needs `core`.
2983
+ // Same seam as the verbs above: the boundary check needs `core`.
3428
2984
  publish: (request) => authoringLoopHost.publishDraft(request),
3429
- // 394-06: stage 5's evidence reader and the repair arm's probe runner. The reader is
3430
- // the same `runsReader` the gate evaluator is bound to — a second reader would be a
3431
- // second answer to what one run recorded — and the starter dispatches the REGISTERED
3432
- // `runs.start` on the gate-run caller, so a probe is marker-stamped exactly as a gate
3433
- // run is and is excluded from outcomes for the same reason.
2985
+ // The evaluator's reader; probes use the gate-run caller, so outcomes exclude them.
3434
2986
  runs: {
3435
2987
  start: async (request) => {
3436
2988
  if (composedRegistry === void 0) {
@@ -3445,8 +2997,6 @@ function composeLocalAgent(input) {
3445
2997
  },
3446
2998
  get: (runId) => runsReader.get(runId)
3447
2999
  },
3448
- // 2026-10-01 (432-18/432-19, D-15): no dispatch-scoped grant exists. The authoring loop
3449
- // runs its dispatch directly, and no gate run it starts consults any approval.
3450
3000
  verifyDraft: async (verifyInput) => {
3451
3001
  if (composedRegistry === void 0) {
3452
3002
  throw new TypeError("a draft was verified before its registry finished composing");
@@ -3459,28 +3009,13 @@ function composeLocalAgent(input) {
3459
3009
  );
3460
3010
  }
3461
3011
  }
3462
- // 2026-10-01 (432-17, D-06): no authoring proposal writer is bound; an authored test is
3463
- // written in its own call through the shelf's direct writer.
3464
3012
  },
3465
- // 432-16 (D-07): no test-draft or config commit port and no undo source is bound — agent-qa
3466
- // makes no git commits. The final authored test is written through `draftShelf.publish`.
3467
- //
3468
- // 395-01 D-01/D-03/D-17 · CFGM-01/03/04: the config editor's host half, each spread on its
3469
- // OWN condition rather than as one bundle, so a host missing one reports that one `unbound`.
3013
+ // Each config-editor half spreads on its own condition, so a missing one reads `unbound`.
3470
3014
  ...input.configFiles === void 0 ? {} : { configFiles: input.configFiles },
3471
3015
  ...input.configValidate === void 0 ? {} : { configValidate: input.configValidate },
3472
3016
  ...input.scaffoldContent === void 0 ? {} : { scaffoldContent: input.scaffoldContent },
3473
3017
  ...input.configWrite === void 0 ? {} : { configWrite: input.configWrite }
3474
- // 2026-10-14 (441-39, D-15): a config change is not scanned for secrets, so no scan is bound.
3475
- // 2026-10-01 (432-17, D-05): no config proposal filer is bound; the six config ops write in
3476
- // the call through `configWrite`.
3477
3018
  }
3478
- // 2026-10-15 (441-28, D-15): no audit sink; the guardrail audit went with the guardrails.
3479
- // 432-13 (D-14/D-15): no standing-approval reader, confirm port or session deny overlay reaches
3480
- // the registry — `invokeFunction` asks nobody. 432-18 deleted the grant reader with the ledger.
3481
- // 2026-10-02 (432-39, D-12): the host's execution-context answer is no longer forwarded here.
3482
- // The registry's option was retired and unread since 432-13 and is deleted; the same answer
3483
- // still reaches the knowledge review above, which records a direct change under it.
3484
3019
  });
3485
3020
  composedRegistry = registry;
3486
3021
  let opened;
@@ -3492,7 +3027,6 @@ function composeLocalAgent(input) {
3492
3027
  const model = await input.model();
3493
3028
  const knowledgeRoot = await input.knowledgeRoot();
3494
3029
  const analysisTokenBudget = input.analysisTokenBudget === void 0 ? void 0 : await input.analysisTokenBudget();
3495
- const proposeGate1MaxPerJob = input.postRun?.proposeGate1MaxPerJob === void 0 ? void 0 : await input.postRun.proposeGate1MaxPerJob();
3496
3030
  const store = createSqliteJobStore({
3497
3031
  path: (0, import_node_path10.join)(input.agentQaRoot, AGENT_JOB_STORE_DB_FILE),
3498
3032
  clock,
@@ -3501,7 +3035,7 @@ function composeLocalAgent(input) {
3501
3035
  let jobs;
3502
3036
  try {
3503
3037
  const kinds = input.jobKinds ?? (0, import_agent_qa_agent4.createRealJobKindRegistry)(
3504
- postRunCapabilities(input, knowledgeRoot, analysisTokenBudget, store, proposeGate1MaxPerJob)
3038
+ postRunCapabilities(input, knowledgeRoot, analysisTokenBudget)
3505
3039
  );
3506
3040
  const idSource = input.idSource ?? DIGEST_JOB_ID_SOURCE;
3507
3041
  const unclaimableKinds = UNCLAIMABLE_BY_PROSE_POSTURE[input.postRun?.candidateProse ?? "no-masker"];
@@ -3584,13 +3118,324 @@ function composeLocalAgent(input) {
3584
3118
  var import_agent_qa_runner_local4 = require("@vostride/agent-qa-runner-local");
3585
3119
  var import_agent_qa_runner_local5 = require("@vostride/agent-qa-runner-local");
3586
3120
 
3587
- // src/composition/compose-job-recovery.ts
3121
+ // src/store/mark-ledger.ts
3122
+ var import_node_fs11 = require("node:fs");
3123
+ var import_node_path12 = require("node:path");
3124
+ var import_agent_qa_schema10 = require("@vostride/agent-qa-schema");
3125
+ var import_zod2 = require("zod");
3126
+
3127
+ // src/composition/run-layout.ts
3128
+ var import_agent_qa_runner_local6 = require("@vostride/agent-qa-runner-local");
3129
+
3130
+ // src/store/mark-lock.ts
3131
+ var import_node_crypto5 = require("node:crypto");
3132
+ var import_node_fs10 = require("node:fs");
3588
3133
  var import_node_path11 = require("node:path");
3134
+ var import_zod = require("zod");
3135
+ var ownerSchema = import_zod.z.object({
3136
+ schemaVersion: import_zod.z.literal(2),
3137
+ kind: import_zod.z.literal("mark-ledger-lock"),
3138
+ pid: import_zod.z.number().int().positive(),
3139
+ token: import_zod.z.uuid(),
3140
+ runId: import_zod.z.string().min(1)
3141
+ }).strict();
3142
+ function syncDirectory(path) {
3143
+ const fd = (0, import_node_fs10.openSync)(path, "r");
3144
+ try {
3145
+ (0, import_node_fs10.fsyncSync)(fd);
3146
+ } finally {
3147
+ (0, import_node_fs10.closeSync)(fd);
3148
+ }
3149
+ }
3150
+ function readOwner(path, runId) {
3151
+ try {
3152
+ const directory = (0, import_node_fs10.lstatSync)(path);
3153
+ if (!directory.isDirectory() || directory.isSymbolicLink()) return void 0;
3154
+ const ownerFile = (0, import_node_path11.join)(path, "owner.json");
3155
+ const file = (0, import_node_fs10.lstatSync)(ownerFile);
3156
+ if (!file.isFile() || file.isSymbolicLink()) return void 0;
3157
+ const parsed = ownerSchema.safeParse(JSON.parse((0, import_node_fs10.readFileSync)(ownerFile, "utf8")));
3158
+ return parsed.success && parsed.data.runId === runId ? parsed.data : void 0;
3159
+ } catch {
3160
+ return void 0;
3161
+ }
3162
+ }
3163
+ function positivelyDead(pid) {
3164
+ try {
3165
+ process.kill(pid, 0);
3166
+ return false;
3167
+ } catch (error) {
3168
+ return error.code === "ESRCH";
3169
+ }
3170
+ }
3171
+ async function acquireMarkLock(lock, runId, busy) {
3172
+ const owner = { schemaVersion: 2, kind: "mark-ledger-lock", pid: process.pid, token: (0, import_node_crypto5.randomUUID)(), runId };
3173
+ const candidate = `${lock}.candidate-${owner.token}`;
3174
+ (0, import_node_fs10.mkdirSync)(candidate);
3175
+ const fd = (0, import_node_fs10.openSync)((0, import_node_path11.join)(candidate, "owner.json"), "wx", 384);
3176
+ try {
3177
+ (0, import_node_fs10.writeFileSync)(fd, JSON.stringify(owner));
3178
+ (0, import_node_fs10.fsyncSync)(fd);
3179
+ } finally {
3180
+ (0, import_node_fs10.closeSync)(fd);
3181
+ }
3182
+ syncDirectory(candidate);
3183
+ const started = Date.now();
3184
+ let acquired = false;
3185
+ try {
3186
+ while (!acquired) {
3187
+ try {
3188
+ (0, import_node_fs10.mkdirSync)(lock);
3189
+ (0, import_node_fs10.renameSync)((0, import_node_path11.join)(candidate, "owner.json"), (0, import_node_path11.join)(lock, "owner.json"));
3190
+ syncDirectory(lock);
3191
+ syncDirectory((0, import_node_path11.dirname)(lock));
3192
+ (0, import_node_fs10.rmSync)(candidate, { recursive: true });
3193
+ acquired = true;
3194
+ } catch (error) {
3195
+ if (!["EEXIST", "ENOTEMPTY", "ENOTDIR", "EISDIR", "EPERM", "EACCES"].includes(error.code ?? "")) throw error;
3196
+ const current = readOwner(lock, runId);
3197
+ if (current !== void 0 && positivelyDead(current.pid)) {
3198
+ try {
3199
+ (0, import_node_fs10.renameSync)(lock, `${lock}.dead-${current.token}`);
3200
+ syncDirectory((0, import_node_path11.dirname)(lock));
3201
+ continue;
3202
+ } catch (recoveryError) {
3203
+ if (recoveryError.code === "ENOENT") continue;
3204
+ if (!["EEXIST", "ENOTEMPTY", "ENOTDIR", "EISDIR", "EPERM", "EACCES"].includes(recoveryError.code ?? "")) throw recoveryError;
3205
+ }
3206
+ }
3207
+ const remaining = 1e4 - (Date.now() - started);
3208
+ if (remaining <= 0) throw busy();
3209
+ await new Promise((resolve2) => setTimeout(resolve2, Math.min(50, remaining)));
3210
+ }
3211
+ }
3212
+ } finally {
3213
+ if (!acquired) (0, import_node_fs10.rmSync)(candidate, { recursive: true, force: true });
3214
+ }
3215
+ return () => {
3216
+ if (readOwner(lock, runId)?.token !== owner.token) return;
3217
+ const released = `${lock}.released-${owner.token}`;
3218
+ (0, import_node_fs10.renameSync)(lock, released);
3219
+ syncDirectory((0, import_node_path11.dirname)(lock));
3220
+ (0, import_node_fs10.rmSync)(released, { recursive: true });
3221
+ syncDirectory((0, import_node_path11.dirname)(lock));
3222
+ };
3223
+ }
3224
+
3225
+ // src/store/mark-ledger.ts
3226
+ var MARKS_LEDGER_FILE = "marks.jsonl";
3227
+ var MARKS_LEDGER_LOCK_FILE = "marks.jsonl.lock";
3228
+ var MARK_INTENT_FILE = "mark-intent.json";
3229
+ var MARK_INTENT_STAGES = ["prepared", "evidence", "applied"];
3230
+ var intentSchema = import_zod2.z.object({
3231
+ schemaVersion: import_zod2.z.literal(2),
3232
+ mark: import_agent_qa_schema10.MarkReceiptSchema,
3233
+ stage: import_zod2.z.enum(MARK_INTENT_STAGES),
3234
+ operationId: import_zod2.z.uuid(),
3235
+ plan: import_agent_qa_schema10.ImprovementPlanSchema.optional()
3236
+ }).strict().superRefine((intent, ctx) => {
3237
+ if (intent.stage === "applied" && intent.mark.disposition.kind === "drafted") {
3238
+ ctx.addIssue({ code: "custom", path: ["mark", "disposition"], message: "a mark applies its fix; it never files a draft" });
3239
+ }
3240
+ });
3241
+ function atomicPublish(path, text) {
3242
+ const staged = `${path}.pending`;
3243
+ const fd = (0, import_node_fs11.openSync)(staged, "w", 384);
3244
+ try {
3245
+ (0, import_node_fs11.writeFileSync)(fd, text);
3246
+ (0, import_node_fs11.fsyncSync)(fd);
3247
+ } finally {
3248
+ (0, import_node_fs11.closeSync)(fd);
3249
+ }
3250
+ (0, import_node_fs11.renameSync)(staged, path);
3251
+ }
3252
+ var MarkLedgerBusyError = class extends Error {
3253
+ constructor() {
3254
+ super("Mark ledger is busy; retry the mark after the current transaction finishes");
3255
+ this.name = "MarkLedgerBusyError";
3256
+ }
3257
+ };
3258
+ var MarkLedgerCorruptError = class extends Error {
3259
+ constructor(line) {
3260
+ super(`Mark ledger is corrupt at line ${line}`);
3261
+ this.line = line;
3262
+ this.name = "MarkLedgerCorruptError";
3263
+ }
3264
+ };
3265
+ var MarkIntentUnusableError = class extends Error {
3266
+ constructor(intentPath, reason) {
3267
+ const what = reason === "earlier-version" ? "was written by an earlier agent-qa version, which this version does not read" : reason === "unreadable" ? "is unreadable" : "does not match this run's mark ledger";
3268
+ super(`The unfinished-mark record ${intentPath} ${what}; nothing was marked. Remove that file, then mark again.`);
3269
+ this.intentPath = intentPath;
3270
+ this.reason = reason;
3271
+ this.name = "MarkIntentUnusableError";
3272
+ }
3273
+ };
3274
+ function isEarlierVersionIntent(value) {
3275
+ if (value === null || typeof value !== "object") return false;
3276
+ const intent = value;
3277
+ return "proposalUuid" in intent || "testDraft" in intent || intent["stage"] === "drafted";
3278
+ }
3279
+ function latestMarkReceiptsPerAddress(receipts) {
3280
+ const latest = /* @__PURE__ */ new Map();
3281
+ for (const receipt of receipts) {
3282
+ const key = (0, import_agent_qa_schema10.markAddressKey)(receipt);
3283
+ if ((latest.get(key)?.ordinal ?? 0) < receipt.ordinal) latest.set(key, receipt);
3284
+ }
3285
+ return [...latest.values()].sort(
3286
+ (a, b) => a.testIndex - b.testIndex || (a.stepIndex ?? -1) - (b.stepIndex ?? -1)
3287
+ );
3288
+ }
3289
+ function latestMarkReceiptFor(receipts, runId, address) {
3290
+ if (address.runId !== runId) return void 0;
3291
+ return latestMarkReceiptsPerAddress(receipts).find((receipt) => (0, import_agent_qa_schema10.markAddressKey)(receipt) === (0, import_agent_qa_schema10.markAddressKey)(address) && (address.testId === void 0 || receipt.testId === address.testId));
3292
+ }
3293
+ var MarkLedgerNoRunError = class extends Error {
3294
+ constructor() {
3295
+ super("run-not-found: mark ledger requires a completed run handoff");
3296
+ this.name = "MarkLedgerNoRunError";
3297
+ }
3298
+ };
3299
+ var FsMarkLedger = class {
3300
+ dir;
3301
+ file;
3302
+ lock;
3303
+ runId;
3304
+ runSlug;
3305
+ inTransaction = false;
3306
+ intentValue;
3307
+ constructor(config) {
3308
+ this.runId = config.runId;
3309
+ this.runSlug = (0, import_agent_qa_schema10.slugBranch)(config.runId);
3310
+ this.dir = (0, import_node_path12.join)(config.root, import_agent_qa_runner_local6.RUNS_SUBDIR, this.runSlug);
3311
+ this.file = (0, import_node_path12.join)(this.dir, MARKS_LEDGER_FILE);
3312
+ this.lock = (0, import_node_path12.join)(this.dir, MARKS_LEDGER_LOCK_FILE);
3313
+ }
3314
+ read() {
3315
+ let text;
3316
+ try {
3317
+ text = (0, import_node_fs11.readFileSync)(this.file, "utf8");
3318
+ } catch (error) {
3319
+ if (error.code === "ENOENT") return [];
3320
+ throw error;
3321
+ }
3322
+ if (text === "") return [];
3323
+ const lines = text.split("\n");
3324
+ if (lines.pop() !== "") throw new MarkLedgerCorruptError(lines.length + 1);
3325
+ return lines.map((line, index) => {
3326
+ try {
3327
+ const receipt = import_agent_qa_schema10.MarkReceiptSchema.parse(JSON.parse(line));
3328
+ if (receipt.ordinal !== index + 1 || receipt.runId !== this.runId || receipt.runSlug !== this.runSlug) {
3329
+ throw new Error("ledger identity or ordinal mismatch");
3330
+ }
3331
+ return receipt;
3332
+ } catch {
3333
+ throw new MarkLedgerCorruptError(index + 1);
3334
+ }
3335
+ });
3336
+ }
3337
+ latestPerAddress() {
3338
+ return latestMarkReceiptsPerAddress(this.read());
3339
+ }
3340
+ latestFor(address) {
3341
+ if (address.runId !== this.runId) return void 0;
3342
+ return latestMarkReceiptFor(this.read(), this.runId, address);
3343
+ }
3344
+ /** Private resumable state is admitted only while this run's existing lock is held. */
3345
+ prepareIntent(mark, operationId) {
3346
+ if (!this.inTransaction) throw new Error("mark intent requires the run transaction");
3347
+ const prior = this.intentValue;
3348
+ if (prior !== void 0) {
3349
+ const request = (value) => ({
3350
+ runId: value.runId,
3351
+ testIndex: value.testIndex,
3352
+ testId: value.testId,
3353
+ stepIndex: value.stepIndex,
3354
+ kind: value.kind,
3355
+ note: value.note
3356
+ });
3357
+ if ((0, import_agent_qa_schema10.canonicalJson)(request(prior.mark)) !== (0, import_agent_qa_schema10.canonicalJson)(request(mark))) {
3358
+ throw new Error("An unfinished mark must be retried with its original address, kind and note");
3359
+ }
3360
+ return prior;
3361
+ }
3362
+ return this.checkpointIntent({ schemaVersion: 2, mark, operationId, stage: "prepared" });
3363
+ }
3364
+ checkpointIntent(value) {
3365
+ if (!this.inTransaction) throw new Error("mark intent requires the run transaction");
3366
+ const intent = intentSchema.parse(value);
3367
+ if (intent.mark.runId !== this.runId || intent.mark.runSlug !== this.runSlug || intent.mark.ordinal !== this.read().length + 1) throw new MarkLedgerCorruptError(intent.mark.ordinal);
3368
+ atomicPublish((0, import_node_path12.join)(this.dir, MARK_INTENT_FILE), `${(0, import_agent_qa_schema10.canonicalJson)(intent)}
3369
+ `);
3370
+ this.intentValue = intent;
3371
+ return intent;
3372
+ }
3373
+ async transact(fn) {
3374
+ if (!(0, import_node_fs11.existsSync)((0, import_node_path12.join)(this.dir, import_agent_qa_runner_local6.HANDOFF_FILE))) throw new MarkLedgerNoRunError();
3375
+ const release = await acquireMarkLock(this.lock, this.runId, () => new MarkLedgerBusyError());
3376
+ try {
3377
+ const receipts = this.read();
3378
+ const nextOrdinal = receipts.length + 1;
3379
+ const intentPath = (0, import_node_path12.join)(this.dir, MARK_INTENT_FILE);
3380
+ this.intentValue = void 0;
3381
+ if ((0, import_node_fs11.existsSync)(intentPath)) {
3382
+ let raw;
3383
+ try {
3384
+ raw = JSON.parse((0, import_node_fs11.readFileSync)(intentPath, "utf8"));
3385
+ } catch {
3386
+ throw new MarkIntentUnusableError(intentPath, "unreadable");
3387
+ }
3388
+ const parsed = intentSchema.safeParse(raw);
3389
+ if (!parsed.success) {
3390
+ throw new MarkIntentUnusableError(
3391
+ intentPath,
3392
+ isEarlierVersionIntent(raw) ? "earlier-version" : "unreadable"
3393
+ );
3394
+ }
3395
+ const intent = parsed.data;
3396
+ if (intent.mark.runId !== this.runId || intent.mark.runSlug !== this.runSlug) {
3397
+ throw new MarkIntentUnusableError(intentPath, "mismatched");
3398
+ }
3399
+ if (intent.mark.ordinal === nextOrdinal) this.intentValue = intent;
3400
+ else if ((0, import_agent_qa_schema10.canonicalJson)(receipts[intent.mark.ordinal - 1]) === (0, import_agent_qa_schema10.canonicalJson)(intent.mark)) (0, import_node_fs11.unlinkSync)(intentPath);
3401
+ else throw new MarkIntentUnusableError(intentPath, "mismatched");
3402
+ }
3403
+ this.inTransaction = true;
3404
+ const record = await fn(nextOrdinal);
3405
+ if (record === void 0) return void 0;
3406
+ const receipt = import_agent_qa_schema10.MarkReceiptSchema.parse({ ...record, ordinal: nextOrdinal });
3407
+ if (receipt.runId !== this.runId || receipt.runSlug !== this.runSlug) {
3408
+ throw new Error("mark receipt does not belong to this run ledger");
3409
+ }
3410
+ if (this.intentValue !== void 0 && (this.intentValue.stage !== "applied" || (0, import_agent_qa_schema10.canonicalJson)(this.intentValue.mark) !== (0, import_agent_qa_schema10.canonicalJson)(receipt))) {
3411
+ throw new MarkLedgerCorruptError(nextOrdinal);
3412
+ }
3413
+ const before = (0, import_node_fs11.existsSync)(this.file) ? (0, import_node_fs11.readFileSync)(this.file, "utf8") : "";
3414
+ atomicPublish(this.file, `${before}${(0, import_agent_qa_schema10.canonicalJson)(receipt)}
3415
+ `);
3416
+ if (this.intentValue !== void 0) (0, import_node_fs11.unlinkSync)(intentPath);
3417
+ return receipt;
3418
+ } finally {
3419
+ this.inTransaction = false;
3420
+ this.intentValue = void 0;
3421
+ release();
3422
+ }
3423
+ }
3424
+ append(record) {
3425
+ return this.transact(async () => record);
3426
+ }
3427
+ };
3428
+
3429
+ // src/composition/action-cache.ts
3430
+ var import_agent_qa_runner_local7 = require("@vostride/agent-qa-runner-local");
3431
+
3432
+ // src/composition/compose-job-recovery.ts
3433
+ var import_node_path13 = require("node:path");
3589
3434
  var import_agent_qa_agent5 = require("@vostride/agent-qa-agent");
3590
3435
  var JOB_RECOVERY_MAX_RESUMED_JOBS = 64;
3591
3436
  function composeJobRecovery(input) {
3592
3437
  const store = createSqliteJobStore({
3593
- path: (0, import_node_path11.join)(input.agentQaRoot, AGENT_JOB_STORE_DB_FILE),
3438
+ path: (0, import_node_path13.join)(input.agentQaRoot, AGENT_JOB_STORE_DB_FILE),
3594
3439
  clock: input.clock,
3595
3440
  checkpoints: createJobCheckpointStore({ root: input.agentQaRoot })
3596
3441
  });
@@ -3711,7 +3556,6 @@ function createMemorySessionLog(options) {
3711
3556
  }
3712
3557
  // Annotate the CommonJS export names for ESM import in node:
3713
3558
  0 && (module.exports = {
3714
- ALLOW_PRODUCTION_OPT_IN,
3715
3559
  BRIEF_CEILING,
3716
3560
  BRIEF_FRACTION,
3717
3561
  BuildOrdinalReservationError,
@@ -3728,25 +3572,32 @@ function createMemorySessionLog(options) {
3728
3572
  EMBEDDER_WORKER_TERM_GRACE_MS,
3729
3573
  ENTITY_INDEX_SWEEP_INTERVAL_MS,
3730
3574
  EmbedderWorkerTimeoutError,
3575
+ FsMarkLedger,
3731
3576
  GLOBAL_RECORD_CAP,
3577
+ HANDOFF_FILE,
3732
3578
  InvalidChatSessionIdError,
3733
3579
  JOB_RECOVERY_MAX_RESUMED_JOBS,
3734
3580
  LOCAL_CURATION_CAPABILITIES,
3735
3581
  LOCAL_DAEMON_CAPABILITIES,
3736
3582
  LOCAL_KNOWLEDGE_PROBES,
3737
3583
  LocalAgentClosedError,
3584
+ MARKS_LEDGER_FILE,
3585
+ MARKS_LEDGER_LOCK_FILE,
3586
+ MARK_INTENT_FILE,
3738
3587
  MIN_BRIEF,
3739
3588
  MIN_CAUTION,
3740
3589
  MIN_MEMORY_TOOL_CONTEXT_WINDOW,
3590
+ MarkIntentUnusableError,
3591
+ MarkLedgerBusyError,
3592
+ MarkLedgerCorruptError,
3593
+ MarkLedgerNoRunError,
3741
3594
  QUARANTINE_CLASS_DISPOSITIONS,
3742
3595
  QUARANTINE_FLOOR_ELIGIBILITY,
3743
3596
  READ_BODY_FRACTION,
3744
- REFUSED_RUN_REQUEST_FIELDS,
3745
- RunDeniedError,
3597
+ RUNS_SUBDIR,
3746
3598
  RunIdAlreadyInUseError,
3747
3599
  RunIdNotMintedError,
3748
3600
  RunProducedNoEventsError,
3749
- RunRequestFieldRefusedError,
3750
3601
  SUITE_LIFECYCLE_LANE,
3751
3602
  SYSTEM_CLOCK,
3752
3603
  SuiteBoundaryWhileLiveError,
@@ -3755,7 +3606,6 @@ function createMemorySessionLog(options) {
3755
3606
  WEAK_MODEL_CAP_SCALE,
3756
3607
  applyKnowledgeChange,
3757
3608
  buildMemberRunConfig,
3758
- buildProductionRefusal,
3759
3609
  buildRunPorts,
3760
3610
  buildScreenshotCompressor,
3761
3611
  buildSuiteMemberExecutor,
@@ -3775,15 +3625,17 @@ function createMemorySessionLog(options) {
3775
3625
  createRunsReader,
3776
3626
  createSuiteLifecycle,
3777
3627
  latestBuildOrdinal,
3628
+ latestMarkReceiptFor,
3629
+ latestMarkReceiptsPerAddress,
3778
3630
  listSessions,
3631
+ loadCompletedRunHandoff,
3779
3632
  lookupEvidenceBlob,
3780
3633
  mapVerdictToExitCode,
3781
3634
  memoryToolGate,
3782
3635
  mintChatSessionId,
3783
3636
  openRunKnowledgeComposition,
3637
+ purgeActionCache,
3784
3638
  readEvidenceBlobBytes,
3785
- refuseProductionWithoutOptIn,
3786
- refuseUnavailableRunId,
3787
3639
  registerAdapterLiveStream,
3788
3640
  reserveBuildOrdinalForProducts,
3789
3641
  resolveBuildTag,