openclaw-memory-atmem 2.2.6-beta.5 → 2.2.6-beta.6

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/README.md CHANGED
@@ -22,7 +22,7 @@ Existing AtMem 2.1 users run `atmem openclaw upgrade` after upgrading the Python
22
22
  package. This preserves the current memory mode and migration, verifies the new
23
23
  bridge with a self-test flight, and rolls back the bridge on failure.
24
24
 
25
- Bridge `2.2.6-beta.5` adds Spec 007 exact task-context delivery. When the host
25
+ Bridge `2.2.6-beta.6` adds Spec 007 exact task-context delivery. When the host
26
26
  supplies `taskId` in hook context, the bridge requests only that governed task,
27
27
  checks its byte digest, contributes it separately from recalled memory, and
28
28
  confirms exposure. With no `taskId`, task delivery stays off and existing
package/dist/index.js CHANGED
@@ -25,7 +25,7 @@ import { lstat, mkdir, readFile, realpath, rename, unlink, writeFile } from "nod
25
25
  import { spawnSync } from "node:child_process";
26
26
  import { AtmemClient } from "./src/rpc-client.js";
27
27
  import { runSetup } from "./src/setup.js";
28
- import { NOT_OWNER_MESSAGE, NO_IDENTITY_MESSAGE, describeDecision, isConversationOwner, ok, refusal, sessionIdentityForTool, } from "./src/task-tools.js";
28
+ import { NOT_OWNER_MESSAGE, NO_IDENTITY_MESSAGE, describeDecision, isConversationOwner, ok, resolveBoundTaskForTool, refusal, sessionIdentityForTool, } from "./src/task-tools.js";
29
29
  const TAG = "[memory-atmem]";
30
30
  const TAKEOVER_GUIDANCE = "<atmem_memory_provider>\n" +
31
31
  "AtMem is the active durable-memory provider. " +
@@ -809,7 +809,9 @@ function register(api) {
809
809
  task_id: taskPrepared.task_id ?? ctx.taskId,
810
810
  task_disposition: taskPrepared?.disposition ?? "withheld",
811
811
  task_revision: taskPrepared?.revision,
812
- task_context_sha256: taskPrepared?.context_sha256?.replace(/^sha256:/, ""),
812
+ ...(taskPrepared?.context_sha256
813
+ ? { task_context_sha256: taskPrepared.context_sha256.replace(/^sha256:/, "") }
814
+ : {}),
813
815
  task_reason_codes: taskPrepared?.reason_codes ?? [],
814
816
  });
815
817
  }
@@ -848,6 +850,10 @@ function register(api) {
848
850
  digest_profile: "atmem-context-envelope-canonical-json-v1",
849
851
  context_chars: (prepared.context ?? "").length,
850
852
  candidate_ids: prepared.candidate_ids ?? [],
853
+ candidates_considered: prepared.retrieval?.eligible_candidate_count ?? 0,
854
+ retrieval_support_class: prepared.retrieval?.decision?.support_class ?? "not_recorded",
855
+ retrieval_reason_codes: prepared.retrieval?.decision?.reason_codes ?? [],
856
+ retrieval_calibration_version: prepared.retrieval?.decision?.calibration_version,
851
857
  exposure_id: prepared.exposure_id,
852
858
  mode: prepared.mode,
853
859
  context_location: prepared.inject
@@ -1744,13 +1750,20 @@ function register(api) {
1744
1750
  required: ["item_id", "status", "base_revision"],
1745
1751
  },
1746
1752
  async execute(toolCallId, params) {
1747
- const identity = sessionIdentityForTool(toolCtx);
1748
- if (!identity)
1749
- return refusal(NO_IDENTITY_MESSAGE);
1750
- const result = (await callFor(toolCtx, "control_propose_task_delta", {
1753
+ const resolution = await resolveBoundTaskForTool(toolCtx, (identity) => callFor(toolCtx, "control_prepare_task_context", {
1751
1754
  ...identity,
1752
1755
  ...taskScope(toolCtx),
1753
- task_id: String(params.task_id ?? ""),
1756
+ host_run_id: toolCtx.runId,
1757
+ }));
1758
+ if (!resolution.ok) {
1759
+ return refusal(`${resolution.message} (${resolution.reasonCodes.join(", ")})`);
1760
+ }
1761
+ const result = (await callFor(toolCtx, "control_propose_task_delta", {
1762
+ ...resolution.identity,
1763
+ ...taskScope(toolCtx),
1764
+ // Redundant checked assertion. Authority came from the current
1765
+ // conversation focus above, never from the model's parameters.
1766
+ task_id: resolution.taskId,
1754
1767
  base_revision: Number(params.base_revision ?? 0),
1755
1768
  // Derived from stable host identifiers, never from payload content
1756
1769
  // or a clock, so a retried tool call collapses to one decision.
@@ -128,7 +128,7 @@ export class AtmemClient {
128
128
  capabilities: {},
129
129
  clientInfo: {
130
130
  name: "openclaw-memory-atmem",
131
- version: "2.2.6-beta.5",
131
+ version: "2.2.6-beta.6",
132
132
  },
133
133
  });
134
134
  this.notify("notifications/initialized", {});
@@ -30,6 +30,29 @@ export function sessionIdentityForTool(ctx) {
30
30
  session_epoch: sessionEpoch,
31
31
  };
32
32
  }
33
+ /** Resolve authority from the authenticated conversation, never model input. */
34
+ export async function resolveBoundTaskForTool(ctx, prepare) {
35
+ const identity = sessionIdentityForTool(ctx);
36
+ if (!identity) {
37
+ return { ok: false, message: NO_IDENTITY_MESSAGE, reasonCodes: ["host_identity_missing"] };
38
+ }
39
+ const prepared = (await prepare(identity));
40
+ if (prepared.disposition !== "injected" || !prepared.task_id) {
41
+ const reasons = (prepared.reason_codes ?? []).map(String);
42
+ return {
43
+ ok: false,
44
+ message: "This conversation has no active governed task focus. " +
45
+ "No task progress was recorded.",
46
+ reasonCodes: reasons.length ? reasons : ["task_context_selection_required"],
47
+ };
48
+ }
49
+ return {
50
+ ok: true,
51
+ identity,
52
+ taskId: String(prepared.task_id),
53
+ revision: prepared.revision,
54
+ };
55
+ }
33
56
  /** Absence is never permission. Only an explicit affirmative is the owner. */
34
57
  export function isConversationOwner(ctx) {
35
58
  return ctx.senderIsOwner === true;
@@ -2,7 +2,7 @@
2
2
  "id": "memory-atmem",
3
3
  "name": "Memory (atmem)",
4
4
  "description": "OpenClaw bridge installed and managed by the AtMem memory control plane.",
5
- "version": "2.2.6-beta.5",
5
+ "version": "2.2.6-beta.6",
6
6
  "commandAliases": ["memory-atmem"],
7
7
  "activation": {
8
8
  "onStartup": true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-memory-atmem",
3
- "version": "2.2.6-beta.5",
3
+ "version": "2.2.6-beta.6",
4
4
  "description": "OpenClaw Agent Black Box and memory control-plane bridge for AtMem",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",