signetai 0.199.1 → 0.199.2

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/mcp-stdio.js CHANGED
@@ -46150,11 +46150,22 @@ function requireStrictEpisodicSourceRefInTx(db, agentId, sourceRef) {
46150
46150
  }
46151
46151
  throw new OntologyProposalError(`Evidence source_ref was not found: ${resolved.sourceRef}`, 409);
46152
46152
  }
46153
+ function isDreamingAttentionEvidenceInTx(db, agentId, value) {
46154
+ const sourceRef = typeof value.source_ref === "string" ? value.source_ref.trim() : "";
46155
+ const sourceId = typeof value.source_id === "string" ? value.source_id.trim() : "";
46156
+ if (value.source_kind !== "attention" || value.source_root !== "dreaming_attention" || !/^attention:(?:\$\d+|[^:]+)$/.test(sourceRef) || sourceId.length === 0) {
46157
+ return false;
46158
+ }
46159
+ const row = db.prepare("SELECT id FROM dreaming_attention WHERE id = ? AND agent_id = ?").get(sourceId, agentId);
46160
+ return row !== undefined;
46161
+ }
46153
46162
  function validateProposalEvidenceSourcesInTx(db, agentId, evidence) {
46154
46163
  for (const value of evidence) {
46155
46164
  const ref3 = readOntologyEvidenceRef(value);
46156
46165
  if (ref3 === null || !isRecord3(ref3.reference) || !("source_ref" in ref3.reference))
46157
46166
  continue;
46167
+ if (isDreamingAttentionEvidenceInTx(db, agentId, ref3.reference))
46168
+ continue;
46158
46169
  requireStrictEpisodicSourceRefInTx(db, agentId, ref3.reference.source_ref);
46159
46170
  }
46160
46171
  }
@@ -46203,6 +46214,8 @@ function derivedMemorySourcesForProposalInTx(db, proposal) {
46203
46214
  const evidence = ref3.reference;
46204
46215
  if (!("source_ref" in evidence))
46205
46216
  continue;
46217
+ if (isDreamingAttentionEvidenceInTx(db, proposal.agent_id, evidence))
46218
+ continue;
46206
46219
  const source = requireStrictEpisodicSourceRefInTx(db, proposal.agent_id, evidence.source_ref);
46207
46220
  sources.push({
46208
46221
  sourceKind: source.kind,
@@ -47709,7 +47722,113 @@ var DREAMING_ONTOLOGY_OPERATION_SCHEMA = exports_external.discriminatedUnion("op
47709
47722
  operation("decline_attention")
47710
47723
  ]);
47711
47724
 
47725
+ // ../../platform/daemon/src/system-pressure.ts
47726
+ var CLEAR_COOLDOWN_MS = 5000;
47727
+ var currentLevel = "normal";
47728
+ var lastLagAt = 0;
47729
+ var startupGraceUntil = 0;
47730
+ var recoveryOutcome = "not_observed";
47731
+ var EVENT_LOOP_WEDGE_COOLDOWN_MS = 10 * 60 * 1000;
47732
+ function tickPressureState() {
47733
+ const now2 = Date.now();
47734
+ if (startupGraceUntil !== 0 && now2 >= startupGraceUntil) {
47735
+ startupGraceUntil = 0;
47736
+ }
47737
+ if (currentLevel !== "normal" && now2 >= startupGraceUntil && now2 - lastLagAt > CLEAR_COOLDOWN_MS) {
47738
+ currentLevel = "normal";
47739
+ recoveryOutcome = "recovered";
47740
+ }
47741
+ }
47742
+ function getSystemPressure() {
47743
+ return currentLevel;
47744
+ }
47745
+ function isSystemPressureHigh() {
47746
+ return currentLevel !== "normal";
47747
+ }
47748
+ async function awaitPressureClear(timeoutMs = 30000) {
47749
+ if (currentLevel === "normal")
47750
+ return true;
47751
+ const deadline = Date.now() + timeoutMs;
47752
+ while (Date.now() < deadline) {
47753
+ await new Promise((resolve) => setTimeout(resolve, 500));
47754
+ tickPressureState();
47755
+ if (getSystemPressure() === "normal")
47756
+ return true;
47757
+ }
47758
+ recoveryOutcome = "still_degraded";
47759
+ logger.warn("system-pressure", `Pressure did not clear within ${timeoutMs}ms — proceeding`);
47760
+ return false;
47761
+ }
47762
+
47763
+ // ../../platform/daemon/src/yielding-writes.ts
47764
+ var yieldToEventLoop = () => new Promise((resolve) => setTimeout(resolve, 0));
47765
+ async function writeBatch(accessor, processBatch) {
47766
+ if (accessor.withWriteTxAsync) {
47767
+ return accessor.withWriteTxAsync(processBatch);
47768
+ }
47769
+ return accessor.withWriteTx(processBatch);
47770
+ }
47771
+ async function runWriteBatches(accessor, items, processItem, options) {
47772
+ const maxPerTx = typeof options.maxPerTx === "number" && Number.isFinite(options.maxPerTx) ? Math.max(1, Math.floor(options.maxPerTx)) : 50;
47773
+ const maxTxDurationMs = typeof options.maxTxDurationMs === "number" && Number.isFinite(options.maxTxDurationMs) ? Math.max(1, options.maxTxDurationMs) : Number.POSITIVE_INFINITY;
47774
+ const yieldEvery = typeof options.yieldEvery === "number" && Number.isFinite(options.yieldEvery) ? Math.max(1, Math.floor(options.yieldEvery)) : 1;
47775
+ const maxTotal = Math.min(items.length, typeof options.maxTotal === "number" && Number.isFinite(options.maxTotal) ? Math.max(0, Math.floor(options.maxTotal)) : items.length);
47776
+ const results = [];
47777
+ let processed = 0;
47778
+ let batches = 0;
47779
+ let paused = 0;
47780
+ while (processed < maxTotal) {
47781
+ if (!options.skipPressure && isSystemPressureHigh()) {
47782
+ paused++;
47783
+ await awaitPressureClear();
47784
+ }
47785
+ let batch;
47786
+ try {
47787
+ batch = await writeBatch(accessor, (db) => {
47788
+ const startedAt = performance.now();
47789
+ const batchResults = [];
47790
+ for (const item of items.slice(processed, maxTotal)) {
47791
+ batchResults.push(processItem(db, item));
47792
+ if (batchResults.length >= maxPerTx)
47793
+ break;
47794
+ if (performance.now() - startedAt >= maxTxDurationMs)
47795
+ break;
47796
+ }
47797
+ return batchResults;
47798
+ });
47799
+ } catch (error51) {
47800
+ const message = error51 instanceof Error ? error51.message : String(error51);
47801
+ logger.warn("yielding-writes", `${options.label}: write batch failed after ${processed} committed items`, {
47802
+ processed,
47803
+ batches,
47804
+ error: message
47805
+ });
47806
+ return { items: results, processed, batches, paused, stopped: "failed", error: message };
47807
+ }
47808
+ if (batch.length === 0)
47809
+ throw new Error(`${options.label}: write batch made no progress`);
47810
+ results.push(...batch);
47811
+ processed += batch.length;
47812
+ batches++;
47813
+ if (batches % yieldEvery === 0)
47814
+ await yieldToEventLoop();
47815
+ }
47816
+ if (processed < items.length) {
47817
+ logger.debug("yielding-writes", `${options.label}: hit maxTotal cap (${maxTotal})`, { processed, batches });
47818
+ }
47819
+ return {
47820
+ items: results,
47821
+ processed,
47822
+ batches,
47823
+ paused,
47824
+ stopped: processed < items.length ? "capped" : "exhausted"
47825
+ };
47826
+ }
47827
+
47712
47828
  // ../../platform/daemon/src/pipeline/dreaming-operations.ts
47829
+ var DREAMING_MAX_OPERATIONS_PER_REQUEST = 100;
47830
+ var DREAMING_WRITE_MAX_OPERATIONS_PER_TX = 10;
47831
+ var DREAMING_WRITE_MAX_TX_DURATION_MS = 50;
47713
47832
  var FLAG_OP = "flag";
47714
47833
  var DECLINE_ATTENTION_OP = "decline_attention";
47715
47834
  var HYGIENE_ARCHIVE_OPS = new Set([
@@ -47777,30 +47896,30 @@ function asStringRecord(value) {
47777
47896
  }
47778
47897
  return Object.keys(record5).length > 0 ? record5 : undefined;
47779
47898
  }
47780
- function mintFlags(accessor, agentId, operations) {
47781
- const minted = new Map;
47782
- accessor.withWriteTx((db) => {
47783
- for (let index = 0;index < operations.length; index += 1) {
47784
- const operation2 = operations[index];
47785
- if (operation2.operation !== FLAG_OP)
47786
- continue;
47787
- const subjectRef = typeof operation2.payload.subjectRef === "string" ? operation2.payload.subjectRef.trim() : "";
47788
- if (!subjectRef)
47789
- continue;
47790
- const priority3 = typeof operation2.payload.priority === "number" ? operation2.payload.priority : undefined;
47791
- const attentionId = enqueueDreamingAttentionInTx(db, {
47792
- agentId,
47793
- kind: "hygiene",
47794
- subjectRef,
47795
- details: asStringRecord(operation2.payload.details),
47796
- priority: priority3
47797
- });
47798
- minted.set(index, attentionId);
47799
- }
47899
+ async function mintFlags(accessor, agentId, operations) {
47900
+ const flagged = operations.flatMap((operation2, index) => operation2.operation === FLAG_OP ? [{ index, operation: operation2 }] : []);
47901
+ const result = await runWriteBatches(accessor, flagged, (db, entry) => {
47902
+ const subjectRef = typeof entry.operation.payload.subjectRef === "string" ? entry.operation.payload.subjectRef.trim() : "";
47903
+ if (!subjectRef)
47904
+ return { index: entry.index, attentionId: null };
47905
+ const priority3 = typeof entry.operation.payload.priority === "number" ? entry.operation.payload.priority : undefined;
47906
+ const attentionId = enqueueDreamingAttentionInTx(db, {
47907
+ agentId,
47908
+ kind: "hygiene",
47909
+ subjectRef,
47910
+ details: asStringRecord(entry.operation.payload.details),
47911
+ priority: priority3
47912
+ });
47913
+ return { index: entry.index, attentionId };
47914
+ }, {
47915
+ label: "dreaming attention flags",
47916
+ maxPerTx: DREAMING_MAX_OPERATIONS_PER_REQUEST
47800
47917
  });
47801
- return minted;
47918
+ if (result.stopped === "failed")
47919
+ throw new Error(result.error ?? "Dreaming attention flag write failed");
47920
+ return new Map(result.items.flatMap((entry) => entry.attentionId === null ? [] : [[entry.index, entry.attentionId]]));
47802
47921
  }
47803
- function attentionProvenance(accessor, agentId, operation2, mintedById) {
47922
+ function attentionProvenance(accessor, agentId, operation2, mintedById, operations, operationIndex) {
47804
47923
  const reference = operation2.provenance?.trim();
47805
47924
  if (!reference?.startsWith("attention:"))
47806
47925
  return null;
@@ -47810,7 +47929,10 @@ function attentionProvenance(accessor, agentId, operation2, mintedById) {
47810
47929
  let attention = null;
47811
47930
  const sameBatch = reference.match(/^attention:\$(\d+)$/);
47812
47931
  if (sameBatch !== null) {
47813
- const attentionId = mintedById.get(Number.parseInt(sameBatch[1], 10));
47932
+ const flagIndex = sameBatchFlagIndex(accessor, agentId, operations, operationIndex, operation2);
47933
+ if (flagIndex === null)
47934
+ return null;
47935
+ const attentionId = mintedById.get(flagIndex);
47814
47936
  if (attentionId !== undefined)
47815
47937
  attention = getDreamingAttentionById(accessor, { agentId, id: attentionId });
47816
47938
  } else {
@@ -47820,28 +47942,7 @@ function attentionProvenance(accessor, agentId, operation2, mintedById) {
47820
47942
  }
47821
47943
  if (attention === null || attention.kind !== "hygiene")
47822
47944
  return null;
47823
- let expectedTarget = false;
47824
- if (operation2.operation === "archive_entity") {
47825
- expectedTarget = pinnedTarget(payload2, attention, "entity:", "entityId");
47826
- } else if (operation2.operation === "archive_aspect") {
47827
- expectedTarget = pinnedTarget(payload2, attention, "aspect:", "aspectId");
47828
- } else if (operation2.operation === "archive_claim_value") {
47829
- expectedTarget = pinnedTarget(payload2, attention, "attribute:", "attributeId");
47830
- } else if (operation2.operation === "archive_link") {
47831
- expectedTarget = pinnedTarget(payload2, attention, "link:", "linkId");
47832
- } else if (operation2.operation === "merge_entities") {
47833
- const targets = Array.isArray(payload2.targets) ? payload2.targets.filter((value) => typeof value === "string") : [];
47834
- const survivor = typeof payload2.survivor === "string" ? payload2.survivor : "";
47835
- const canonicalName = attention.details.canonicalName ?? pinnedBySubjectRef(attention.subjectRef, "duplicate:") ?? "";
47836
- const groupIds = semanticDuplicateIds(accessor, agentId, canonicalName);
47837
- expectedTarget = canonicalName.length > 0 && attention.subjectRef === `duplicate:${canonicalName}` && groupIds.size > 1 && groupIds.has(survivor) && targets.length >= 2 && targets.every((id) => groupIds.has(id)) && targets.includes(survivor) && targets.some((id) => id !== survivor);
47838
- } else if (operation2.operation === "merge_aspects") {
47839
- const sources = Array.isArray(payload2.sources) ? payload2.sources.filter((value) => typeof value === "string") : [];
47840
- const pinnedAspect = pinnedBySubjectRef(attention.subjectRef, "aspect:");
47841
- const detailAgrees = pinnedAspect !== null && (attention.details.aspectId === undefined || attention.details.aspectId === pinnedAspect);
47842
- expectedTarget = detailAgrees && typeof payload2.target === "string" && sources.length >= 1 && pinnedAspect !== null && sources.includes(pinnedAspect);
47843
- }
47844
- if (!expectedTarget)
47945
+ if (!hasExpectedAttentionTarget(accessor, agentId, operation2, attention))
47845
47946
  return null;
47846
47947
  return {
47847
47948
  provenance: {
@@ -47850,6 +47951,7 @@ function attentionProvenance(accessor, agentId, operation2, mintedById) {
47850
47951
  source_ref: reference,
47851
47952
  source_kind: "attention",
47852
47953
  source_id: attention.id,
47954
+ source_root: "dreaming_attention",
47853
47955
  subject_ref: attention.subjectRef,
47854
47956
  details: attention.details
47855
47957
  }
@@ -47868,6 +47970,81 @@ function pinnedBySubjectRef(subjectRef, prefix) {
47868
47970
  const id = subjectRef.slice(prefix.length);
47869
47971
  return id.length > 0 ? id : null;
47870
47972
  }
47973
+ function hasExpectedAttentionTarget(accessor, agentId, operation2, attention) {
47974
+ const payload2 = operation2.payload;
47975
+ if (operation2.operation === "archive_entity") {
47976
+ return pinnedTarget(payload2, attention, "entity:", "entityId");
47977
+ }
47978
+ if (operation2.operation === "archive_aspect") {
47979
+ return pinnedTarget(payload2, attention, "aspect:", "aspectId");
47980
+ }
47981
+ if (operation2.operation === "archive_claim_value") {
47982
+ return pinnedTarget(payload2, attention, "attribute:", "attributeId");
47983
+ }
47984
+ if (operation2.operation === "archive_link") {
47985
+ return pinnedTarget(payload2, attention, "link:", "linkId");
47986
+ }
47987
+ if (operation2.operation === "merge_entities") {
47988
+ const targets = Array.isArray(payload2.targets) ? payload2.targets.filter((value) => typeof value === "string") : [];
47989
+ const survivor = typeof payload2.survivor === "string" ? payload2.survivor : "";
47990
+ const canonicalName = attention.details.canonicalName ?? pinnedBySubjectRef(attention.subjectRef, "duplicate:") ?? "";
47991
+ const groupIds = semanticDuplicateIds(accessor, agentId, canonicalName);
47992
+ return canonicalName.length > 0 && attention.subjectRef === `duplicate:${canonicalName}` && groupIds.size > 1 && groupIds.has(survivor) && targets.length >= 2 && targets.every((id) => groupIds.has(id)) && targets.includes(survivor) && targets.some((id) => id !== survivor);
47993
+ }
47994
+ if (operation2.operation === "merge_aspects") {
47995
+ const sources = Array.isArray(payload2.sources) ? payload2.sources.filter((value) => typeof value === "string") : [];
47996
+ const pinnedAspect = pinnedBySubjectRef(attention.subjectRef, "aspect:");
47997
+ const detailAgrees = pinnedAspect !== null && (attention.details.aspectId === undefined || attention.details.aspectId === pinnedAspect);
47998
+ return detailAgrees && typeof payload2.target === "string" && sources.length >= 1 && pinnedAspect !== null && sources.includes(pinnedAspect);
47999
+ }
48000
+ return false;
48001
+ }
48002
+ function sameBatchFlagIndex(accessor, agentId, operations, operationIndex, operation2) {
48003
+ const reference = operation2.provenance?.trim();
48004
+ const sameBatch = reference?.match(/^attention:\$(\d+)$/);
48005
+ if (sameBatch === undefined || sameBatch === null)
48006
+ return null;
48007
+ const indexText = sameBatch[1];
48008
+ if (indexText === undefined)
48009
+ return null;
48010
+ const referencedIndex = Number.parseInt(indexText, 10);
48011
+ if (referencedIndex < 0 || referencedIndex >= operations.length)
48012
+ return null;
48013
+ const referenced = operations[referencedIndex];
48014
+ if (referencedIndex < operationIndex && referenced?.operation === FLAG_OP) {
48015
+ const subjectRef = stringField(referenced.payload, "subjectRef");
48016
+ if (subjectRef === null)
48017
+ return null;
48018
+ const attention = {
48019
+ id: `preflight:${referencedIndex}`,
48020
+ kind: "hygiene",
48021
+ subjectRef,
48022
+ details: asStringRecord(referenced.payload.details) ?? {},
48023
+ priority: 0,
48024
+ createdAt: ""
48025
+ };
48026
+ return hasExpectedAttentionTarget(accessor, agentId, operation2, attention) ? referencedIndex : null;
48027
+ }
48028
+ for (let index = operationIndex - 1;index >= 0; index -= 1) {
48029
+ const candidate = operations[index];
48030
+ if (candidate?.operation !== FLAG_OP)
48031
+ continue;
48032
+ const subjectRef = stringField(candidate.payload, "subjectRef");
48033
+ if (subjectRef === null)
48034
+ continue;
48035
+ const attention = {
48036
+ id: `continuation:${index}`,
48037
+ kind: "hygiene",
48038
+ subjectRef,
48039
+ details: asStringRecord(candidate.payload.details) ?? {},
48040
+ priority: 0,
48041
+ createdAt: ""
48042
+ };
48043
+ if (hasExpectedAttentionTarget(accessor, agentId, operation2, attention))
48044
+ return index;
48045
+ }
48046
+ return null;
48047
+ }
47871
48048
  function pinnedTarget(payload2, attention, prefix, detailKey) {
47872
48049
  const target2 = typeof payload2.target === "string" ? payload2.target : null;
47873
48050
  const pinned = target2 !== null ? pinnedBySubjectRef(attention.subjectRef, prefix) : null;
@@ -48049,6 +48226,47 @@ function toApplicatorPayload(accessor, agentId, operation2, payload2) {
48049
48226
  return payload2;
48050
48227
  }
48051
48228
  }
48229
+ function validateRequestBeforeWrites(params) {
48230
+ for (const [index, operation2] of params.operations.entries()) {
48231
+ if (operation2.operation === FLAG_OP) {
48232
+ if (stringField(operation2.payload, "subjectRef") === null)
48233
+ return "flag requires payload.subjectRef";
48234
+ continue;
48235
+ }
48236
+ if (operation2.operation === DECLINE_ATTENTION_OP) {
48237
+ const attentionId = stringField(operation2.payload, "attentionId");
48238
+ if (attentionId === null)
48239
+ return "decline_attention requires payload.attentionId";
48240
+ const pending = params.accessor.withReadDb((db) => db.prepare(`SELECT 1 FROM dreaming_attention
48241
+ WHERE id = ? AND agent_id = ? AND resolved_at IS NULL`).get(attentionId, params.agentId));
48242
+ if (pending == null)
48243
+ return "Attention record is not pending in this agent scope";
48244
+ continue;
48245
+ }
48246
+ if (toApplicatorPayload(params.accessor, params.agentId, operation2.operation, operation2.payload) === null) {
48247
+ return `Could not resolve operation target: ${operation2.operation}`;
48248
+ }
48249
+ if (HYGIENE_ARCHIVE_OPS.has(operation2.operation)) {
48250
+ const reference = operation2.provenance?.trim();
48251
+ const sameBatch = reference?.match(/^attention:\$(\d+)$/);
48252
+ if (sameBatch) {
48253
+ if (sameBatchFlagIndex(params.accessor, params.agentId, params.operations, index, operation2) === null) {
48254
+ return "Hygiene archives require attention provenance (attention:$<index> or attention:<uuid>)";
48255
+ }
48256
+ continue;
48257
+ }
48258
+ if (attentionProvenance(params.accessor, params.agentId, operation2, new Map, params.operations, index) === null) {
48259
+ return "Hygiene archives require attention provenance (attention:$<index> or attention:<uuid>)";
48260
+ }
48261
+ continue;
48262
+ }
48263
+ const evidenceResult = provenanceForEvidence(params.accessor, params.agentId, operation2);
48264
+ if (evidenceResult.provenance === null) {
48265
+ return evidenceResult.scopeMismatch ?? "Every operation must cite an exact quote from scoped episodic evidence";
48266
+ }
48267
+ }
48268
+ return null;
48269
+ }
48052
48270
  function existingReviewProposalId(db, params) {
48053
48271
  const row = db.prepare(`SELECT id FROM ontology_proposals
48054
48272
  WHERE agent_id = ? AND operation = ? AND status IN ('pending', 'applied', 'rejected')
@@ -48056,9 +48274,118 @@ function existingReviewProposalId(db, params) {
48056
48274
  ORDER BY updated_at DESC LIMIT 1`).get(params.agentId, params.operation, JSON.stringify(params.payload), JSON.stringify(params.evidence));
48057
48275
  return typeof row?.id === "string" ? row.id : null;
48058
48276
  }
48059
- function applyDreamingOperations(params) {
48277
+ function applyValidatedOperationBody(db, entry, params) {
48278
+ if (entry.input === null) {
48279
+ if (entry.decline === true && entry.attentionId !== null) {
48280
+ const pending = db.prepare(`SELECT 1 FROM dreaming_attention
48281
+ WHERE id = ? AND agent_id = ? AND resolved_at IS NULL`).get(entry.attentionId, params.agentId);
48282
+ if (pending == null) {
48283
+ return {
48284
+ index: entry.index,
48285
+ ok: false,
48286
+ error: "Attention record is not pending in this agent scope"
48287
+ };
48288
+ }
48289
+ db.prepare(`UPDATE dreaming_attention
48290
+ SET resolved_at = datetime('now'), resolved_by_pass_id = ?
48291
+ WHERE id = ? AND agent_id = ? AND resolved_at IS NULL`).run(params.passId ?? null, entry.attentionId, params.agentId);
48292
+ return { index: entry.index, ok: true, result: { attentionId: entry.attentionId } };
48293
+ }
48294
+ return { index: entry.index, ok: true, result: { attentionId: entry.attentionId } };
48295
+ }
48296
+ if (entry.reviewOnly) {
48297
+ const existingId = existingReviewProposalId(db, {
48298
+ agentId: params.agentId,
48299
+ operation: entry.input.operation,
48300
+ payload: entry.input.payload,
48301
+ evidence: entry.input.evidence ?? []
48302
+ });
48303
+ if (existingId !== null) {
48304
+ return {
48305
+ index: entry.index,
48306
+ ok: true,
48307
+ result: { reviewRequired: true, deduped: true, proposalId: existingId }
48308
+ };
48309
+ }
48310
+ const created = createOntologyProposalsInTx(db, [
48311
+ {
48312
+ agentId: params.agentId,
48313
+ operation: entry.input.operation,
48314
+ payload: entry.input.payload,
48315
+ confidence: entry.input.confidence,
48316
+ rationale: entry.input.reason,
48317
+ evidence: entry.input.evidence,
48318
+ risk: entry.input.risk,
48319
+ sourceKind: entry.input.sourceKind,
48320
+ sourceId: entry.input.sourceId,
48321
+ sourcePath: entry.input.sourcePath,
48322
+ sourceRoot: entry.input.sourceRoot,
48323
+ createdBy: params.actor
48324
+ }
48325
+ ]);
48326
+ return {
48327
+ index: entry.index,
48328
+ ok: true,
48329
+ proposal: created.items[0],
48330
+ result: { reviewRequired: true }
48331
+ };
48332
+ }
48333
+ if (entry.attentionId !== null) {
48334
+ const pending = db.prepare(`SELECT 1 FROM dreaming_attention
48335
+ WHERE id = ? AND agent_id = ? AND resolved_at IS NULL`).get(entry.attentionId, params.agentId);
48336
+ if (pending == null) {
48337
+ return {
48338
+ index: entry.index,
48339
+ ok: false,
48340
+ error: "Attention already consumed by an earlier operation in this batch"
48341
+ };
48342
+ }
48343
+ }
48344
+ const batch = applyOntologyOperationBatchInTx(db, {
48345
+ agentId: params.agentId,
48346
+ actor: params.actor,
48347
+ operations: [entry.input],
48348
+ writeCaps: params.writeCaps
48349
+ });
48350
+ if (entry.attentionId !== null) {
48351
+ db.prepare(`UPDATE dreaming_attention
48352
+ SET resolved_at = datetime('now'), resolved_by_pass_id = ?
48353
+ WHERE id = ? AND agent_id = ? AND resolved_at IS NULL`).run(params.passId ?? null, entry.attentionId, params.agentId);
48354
+ }
48355
+ return {
48356
+ index: entry.index,
48357
+ ok: true,
48358
+ proposal: batch.items[0]?.proposal,
48359
+ result: batch.items[0]?.result
48360
+ };
48361
+ }
48362
+ function applyValidatedOperationInTx(db, entry, params) {
48363
+ const savepoint = `signet_dream_op_${entry.index}`;
48364
+ db.exec(`SAVEPOINT ${savepoint}`);
48365
+ try {
48366
+ const result = applyValidatedOperationBody(db, entry, params);
48367
+ db.exec(`RELEASE SAVEPOINT ${savepoint}`);
48368
+ return result;
48369
+ } catch (error51) {
48370
+ db.exec(`ROLLBACK TO SAVEPOINT ${savepoint}`);
48371
+ db.exec(`RELEASE SAVEPOINT ${savepoint}`);
48372
+ return {
48373
+ index: entry.index,
48374
+ ok: false,
48375
+ error: error51 instanceof Error ? error51.message : String(error51)
48376
+ };
48377
+ }
48378
+ }
48379
+ async function applyDreamingOperations(params) {
48060
48380
  if (params.operations.length === 0)
48061
48381
  return { ok: false, items: [], error: "operations are required" };
48382
+ if (params.operations.length > DREAMING_MAX_OPERATIONS_PER_REQUEST) {
48383
+ return {
48384
+ ok: false,
48385
+ items: [],
48386
+ error: `operations cannot exceed ${DREAMING_MAX_OPERATIONS_PER_REQUEST} items`
48387
+ };
48388
+ }
48062
48389
  const allowedOperations = new Set(DREAMING_OPERATION_IDS);
48063
48390
  for (const operation2 of params.operations) {
48064
48391
  if (!allowedOperations.has(operation2.operation)) {
@@ -48068,13 +48395,15 @@ function applyDreamingOperations(params) {
48068
48395
  return { ok: false, items: [], error: "confidence must be a finite number between 0 and 1" };
48069
48396
  }
48070
48397
  }
48071
- const minted = mintFlags(params.accessor, params.agentId, params.operations);
48398
+ const validationError = validateRequestBeforeWrites(params);
48399
+ if (validationError !== null)
48400
+ return { ok: false, items: [], error: validationError };
48401
+ const minted = await mintFlags(params.accessor, params.agentId, params.operations);
48072
48402
  const validated = [];
48073
- for (let index = 0;index < params.operations.length; index += 1) {
48074
- const operation2 = params.operations[index];
48403
+ for (const [index, operation2] of params.operations.entries()) {
48075
48404
  if (operation2.operation === FLAG_OP) {
48076
48405
  const attentionId2 = minted.get(index) ?? null;
48077
- validated.push({ input: null, attentionId: attentionId2 });
48406
+ validated.push({ index, input: null, attentionId: attentionId2 });
48078
48407
  continue;
48079
48408
  }
48080
48409
  if (operation2.operation === DECLINE_ATTENTION_OP) {
@@ -48082,13 +48411,13 @@ function applyDreamingOperations(params) {
48082
48411
  if (attentionId2 === null) {
48083
48412
  return { ok: false, items: [], error: "decline_attention requires payload.attentionId" };
48084
48413
  }
48085
- validated.push({ input: null, attentionId: attentionId2, decline: true });
48414
+ validated.push({ index, input: null, attentionId: attentionId2, decline: true });
48086
48415
  continue;
48087
48416
  }
48088
48417
  let provenance = null;
48089
48418
  let attentionId = null;
48090
48419
  if (HYGIENE_ARCHIVE_OPS.has(operation2.operation)) {
48091
- const resolved = attentionProvenance(params.accessor, params.agentId, operation2, minted);
48420
+ const resolved = attentionProvenance(params.accessor, params.agentId, operation2, minted, params.operations, index);
48092
48421
  if (resolved !== null) {
48093
48422
  provenance = resolved.provenance;
48094
48423
  attentionId = resolved.attentionId;
@@ -48116,6 +48445,7 @@ function applyDreamingOperations(params) {
48116
48445
  return { ok: false, items: [], error: `Could not resolve operation target: ${operation2.operation}` };
48117
48446
  }
48118
48447
  validated.push({
48448
+ index,
48119
48449
  input: {
48120
48450
  operation: operation2.operation,
48121
48451
  payload: payload2,
@@ -48132,101 +48462,21 @@ function applyDreamingOperations(params) {
48132
48462
  reviewOnly: operation2.risk === "review_required" && !HYGIENE_ARCHIVE_OPS.has(operation2.operation)
48133
48463
  });
48134
48464
  }
48135
- const items = [];
48136
- params.accessor.withWriteTx((db) => {
48137
- for (let index = 0;index < validated.length; index += 1) {
48138
- const entry = validated[index];
48139
- if (entry.input === null) {
48140
- if (entry.decline === true && entry.attentionId !== null) {
48141
- const pending = db.prepare(`SELECT 1 FROM dreaming_attention
48142
- WHERE id = ? AND agent_id = ? AND resolved_at IS NULL`).get(entry.attentionId, params.agentId);
48143
- if (pending == null) {
48144
- items.push({
48145
- index,
48146
- ok: false,
48147
- error: "Attention record is not pending in this agent scope"
48148
- });
48149
- continue;
48150
- }
48151
- db.prepare(`UPDATE dreaming_attention
48152
- SET resolved_at = datetime('now'), resolved_by_pass_id = ?
48153
- WHERE id = ? AND agent_id = ? AND resolved_at IS NULL`).run(params.passId ?? null, entry.attentionId, params.agentId);
48154
- items.push({ index, ok: true, result: { attentionId: entry.attentionId } });
48155
- continue;
48156
- }
48157
- items.push({ index, ok: true, result: { attentionId: entry.attentionId } });
48158
- continue;
48159
- }
48160
- if (entry.reviewOnly) {
48161
- const existingId = existingReviewProposalId(db, {
48162
- agentId: params.agentId,
48163
- operation: entry.input.operation,
48164
- payload: entry.input.payload,
48165
- evidence: entry.input.evidence ?? []
48166
- });
48167
- if (existingId !== null) {
48168
- items.push({ index, ok: true, result: { reviewRequired: true, deduped: true, proposalId: existingId } });
48169
- continue;
48170
- }
48171
- const created = createOntologyProposalsInTx(db, [
48172
- {
48173
- agentId: params.agentId,
48174
- operation: entry.input.operation,
48175
- payload: entry.input.payload,
48176
- confidence: entry.input.confidence,
48177
- rationale: entry.input.reason,
48178
- evidence: entry.input.evidence,
48179
- risk: entry.input.risk,
48180
- sourceKind: entry.input.sourceKind,
48181
- sourceId: entry.input.sourceId,
48182
- sourcePath: entry.input.sourcePath,
48183
- sourceRoot: entry.input.sourceRoot,
48184
- createdBy: params.actor
48185
- }
48186
- ]);
48187
- items.push({
48188
- index,
48189
- ok: true,
48190
- proposal: created.items[0],
48191
- result: { reviewRequired: true }
48192
- });
48193
- continue;
48194
- }
48195
- if (entry.attentionId !== null) {
48196
- const pending = db.prepare(`SELECT 1 FROM dreaming_attention
48197
- WHERE id = ? AND agent_id = ? AND resolved_at IS NULL`).get(entry.attentionId, params.agentId);
48198
- if (pending == null) {
48199
- items.push({
48200
- index,
48201
- ok: false,
48202
- error: "Attention already consumed by an earlier operation in this batch"
48203
- });
48204
- continue;
48205
- }
48206
- }
48207
- const savepoint = `signet_dream_op_${index}`;
48208
- db.exec(`SAVEPOINT ${savepoint}`);
48209
- try {
48210
- const batch = applyOntologyOperationBatchInTx(db, {
48211
- agentId: params.agentId,
48212
- actor: params.actor,
48213
- operations: [entry.input],
48214
- writeCaps: params.writeCaps
48215
- });
48216
- db.exec(`RELEASE SAVEPOINT ${savepoint}`);
48217
- if (entry.attentionId !== null) {
48218
- db.prepare(`UPDATE dreaming_attention
48219
- SET resolved_at = datetime('now'), resolved_by_pass_id = ?
48220
- WHERE id = ? AND agent_id = ? AND resolved_at IS NULL`).run(params.passId ?? null, entry.attentionId, params.agentId);
48221
- }
48222
- items.push({ index, ok: true, proposal: batch.items[0]?.proposal, result: batch.items[0]?.result });
48223
- } catch (error51) {
48224
- db.exec(`ROLLBACK TO SAVEPOINT ${savepoint}`);
48225
- db.exec(`RELEASE SAVEPOINT ${savepoint}`);
48226
- items.push({ index, ok: false, error: error51 instanceof Error ? error51.message : String(error51) });
48227
- }
48228
- }
48465
+ const result = await runWriteBatches(params.accessor, validated, (db, entry) => applyValidatedOperationInTx(db, entry, params), {
48466
+ label: "dreaming ontology operations",
48467
+ maxPerTx: DREAMING_WRITE_MAX_OPERATIONS_PER_TX,
48468
+ maxTxDurationMs: DREAMING_WRITE_MAX_TX_DURATION_MS
48229
48469
  });
48470
+ const items = result.items;
48471
+ if (result.stopped === "failed") {
48472
+ return {
48473
+ ok: false,
48474
+ items,
48475
+ error: result.error ?? "Dreaming ontology write batch failed",
48476
+ retryFrom: result.processed,
48477
+ retryable: true
48478
+ };
48479
+ }
48230
48480
  const ok = items.some((item) => item.ok);
48231
48481
  return { ok, items, ...ok ? {} : { error: "No ontology operations applied" } };
48232
48482
  }
@@ -48880,12 +49130,12 @@ function createDreamingCapabilities(params) {
48880
49130
  })
48881
49131
  };
48882
49132
  }),
48883
- capability("apply_ontology_ops", "Apply ontology operations", 'Apply every semantic write through the daemon audit seam in one batch, in one agent scope (pass the agentId whose graph you are maintaining — hygiene attention records belong to the agent that flagged them). Ops are processed in array order. Hygiene ops (flag, archive_*, merge_entities) cite provenance: "attention:$<index>" for a flag earlier in the same batch, or "attention:<uuid>" from a prior batch. decline_attention closes a pending attention record you inspected and judged to keep. Content-bearing ops cite evidence with exact quotes from canonical episodic evidence in that scope.', false, exports_external.object({
49133
+ capability("apply_ontology_ops", "Apply ontology operations", 'Apply every semantic write through the daemon audit seam in one ordered request, in one agent scope (pass the agentId whose graph you are maintaining — hygiene attention records belong to the agent that flagged them). The daemon validates every input, citation, and resolvable target before creating flags or applying bounded, yielding writer transactions; each operation and its provenance resolution remains atomic, while an individual operation failure does not block later operations. If a writer transaction fails after earlier transactions committed, the result has `retryable: true` and `retryFrom`; retry only the uncommitted suffix. Do not replay returned items, and replace any earlier `attention:$<index>` references with `attention:<uuid>` built from the flag result `result.attentionId` before retrying. Hygiene ops (flag, archive_*, merge_entities) cite provenance: "attention:$<index>" for a flag earlier in the request, or "attention:<uuid>" from a prior request. decline_attention closes a pending attention record you inspected and judged to keep. Content-bearing ops cite evidence with exact quotes from canonical episodic evidence in that scope.', false, exports_external.object({
48884
49134
  agentId: exports_external.string().min(1),
48885
- operations: exports_external.array(DREAMING_ONTOLOGY_OPERATION_SCHEMA).min(1).max(100)
49135
+ operations: exports_external.array(DREAMING_ONTOLOGY_OPERATION_SCHEMA).min(1).max(DREAMING_MAX_OPERATIONS_PER_REQUEST)
48886
49136
  }), async ({ agentId: scopeId, operations }) => {
48887
49137
  params.onOperationsAboutToApply?.(operations, scopeId);
48888
- const result = applyDreamingOperations({
49138
+ const result = await applyDreamingOperations({
48889
49139
  accessor,
48890
49140
  agentId: scopeId,
48891
49141
  actor,
@@ -48894,7 +49144,13 @@ function createDreamingCapabilities(params) {
48894
49144
  writeCaps: params.writeCaps
48895
49145
  });
48896
49146
  params.onOperationsApplied?.(result, operations, scopeId);
48897
- return { ok: result.ok, ...result.error ? { error: result.error } : {}, items: result.items };
49147
+ return {
49148
+ ok: result.ok,
49149
+ ...result.error ? { error: result.error } : {},
49150
+ ...result.retryable === true ? { retryable: true } : {},
49151
+ ...result.retryFrom !== undefined ? { retryFrom: result.retryFrom } : {},
49152
+ items: result.items
49153
+ };
48898
49154
  })
48899
49155
  ];
48900
49156
  }
@@ -1,43 +1,43 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "version": "0.199.1",
3
+ "version": "0.199.2",
4
4
  "assets": [
5
5
  {
6
6
  "name": "signet-darwin-arm64",
7
7
  "platform": "darwin-arm64",
8
- "sha256": "3318cdc47c5c2b7ab0c383fba202133ef2245526c8c177cf7331019083bcb170",
9
- "size": 125218336
8
+ "sha256": "13d1e9ed36079a4e88f09c9d485cecff247609c291206c848028625dbc21b062",
9
+ "size": 125234848
10
10
  },
11
11
  {
12
12
  "name": "signet-darwin-x64",
13
13
  "platform": "darwin-x64",
14
- "sha256": "6c869689f7c48db42622ff7328928d08f13ff65b87d3e8be4e8e81e755c4d718",
14
+ "sha256": "4711bf757ae5e4c8a73d47da9a0473e3007239cdc75d4d23995f3517165c2bed",
15
15
  "size": 130206272
16
16
  },
17
17
  {
18
18
  "name": "signet-linux-arm64",
19
19
  "platform": "linux-arm64",
20
- "sha256": "cf12e274b871e2091449163b63f0998353f4fcbb856a496d93f9ae0bb78f7526",
21
- "size": 169772708
20
+ "sha256": "fe2ea2d1c3e81f2d9ef3e865613190a7f7b3757ed0edc2b0033c49e968a4141f",
21
+ "size": 169782828
22
22
  },
23
23
  {
24
24
  "name": "signet-linux-x64",
25
25
  "platform": "linux-x64",
26
- "sha256": "ebf7c3ab73c46b6aa186e8d510b68d97df671f345e7e6cfe548e405477763ada",
27
- "size": 172147290
26
+ "sha256": "a5bd885fa4ae0635f41360d64a6303038fe61d2fc5e1925e6fd00741ea2a12ab",
27
+ "size": 172157410
28
28
  },
29
29
  {
30
30
  "name": "signet-win32-x64.exe",
31
31
  "platform": "win32-x64",
32
- "sha256": "ac6486fea32dc1391b11300c0957a1d8ea44fac32c0eabb7c2b4fd4a796726db",
33
- "size": 180273664
32
+ "sha256": "ab57a2c94f49c13bef1e93e9e734a61cecfe32c4576c0c013203d6bc80258d5b",
33
+ "size": 180283392
34
34
  }
35
35
  ],
36
36
  "components": {
37
37
  "connectors": {
38
- "url": "signet-connectors-0.199.1.tar.gz",
39
- "sha256": "79348a9f0e1f35b37f2ddf3759b2f110edda1f630f5d8bfbf6327725bf210bd6",
40
- "size": 21672
38
+ "url": "signet-connectors-0.199.2.tar.gz",
39
+ "sha256": "72f74c5fdda2fb644ef55cc3e80a05a7ff365c0a3ab34953cecb3372c8c3c734",
40
+ "size": 21666
41
41
  }
42
42
  }
43
43
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "signetai",
3
- "version": "0.199.1",
3
+ "version": "0.199.2",
4
4
  "description": "Signet native CLI installer wrapper",
5
5
  "type": "module",
6
6
  "bin": {
@@ -65,10 +65,10 @@
65
65
  "access": "public"
66
66
  },
67
67
  "optionalDependencies": {
68
- "signetai-darwin-arm64": "https://github.com/Signet-AI/signetai/releases/download/v0.199.1/signetai-darwin-arm64-0.199.1.tgz",
69
- "signetai-darwin-x64": "https://github.com/Signet-AI/signetai/releases/download/v0.199.1/signetai-darwin-x64-0.199.1.tgz",
70
- "signetai-linux-arm64": "https://github.com/Signet-AI/signetai/releases/download/v0.199.1/signetai-linux-arm64-0.199.1.tgz",
71
- "signetai-linux-x64": "https://github.com/Signet-AI/signetai/releases/download/v0.199.1/signetai-linux-x64-0.199.1.tgz",
72
- "signetai-win32-x64": "https://github.com/Signet-AI/signetai/releases/download/v0.199.1/signetai-win32-x64-0.199.1.tgz"
68
+ "signetai-darwin-arm64": "https://github.com/Signet-AI/signetai/releases/download/v0.199.2/signetai-darwin-arm64-0.199.2.tgz",
69
+ "signetai-darwin-x64": "https://github.com/Signet-AI/signetai/releases/download/v0.199.2/signetai-darwin-x64-0.199.2.tgz",
70
+ "signetai-linux-arm64": "https://github.com/Signet-AI/signetai/releases/download/v0.199.2/signetai-linux-arm64-0.199.2.tgz",
71
+ "signetai-linux-x64": "https://github.com/Signet-AI/signetai/releases/download/v0.199.2/signetai-linux-x64-0.199.2.tgz",
72
+ "signetai-win32-x64": "https://github.com/Signet-AI/signetai/releases/download/v0.199.2/signetai-win32-x64-0.199.2.tgz"
73
73
  }
74
74
  }