@agfpd/iapeer-memory 0.1.1 → 0.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agfpd/iapeer-memory",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "iapeer-memory — peer memory for the iapeer ecosystem: vault, memoryd (index/search/MCP-http), layer-5 context fragments, role doctrines. The package IS the system; the claude/codex plugins are thin session sockets (docs/10-distribution.md, ADR-009).",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -20,14 +20,14 @@
20
20
  "release": "npm version patch --workspaces-update=false && npm run release:finish",
21
21
  "release:minor": "npm version minor --workspaces-update=false && npm run release:finish",
22
22
  "release:major": "npm version major --workspaces-update=false && npm run release:finish",
23
- "release:finish": "V=$(bun -e 'console.log(JSON.parse(require(\"fs\").readFileSync(\"package.json\",\"utf-8\")).version)') && git -C .. commit -m \"$V\" && git -C .. tag \"v$V\" && (cd ../core && npm publish) && npm publish && git push --follow-tags",
23
+ "release:finish": "V=$(bun -e 'console.log(JSON.parse(require(\"fs\").readFileSync(\"package.json\",\"utf-8\")).version)') && git -C .. commit -m \"$V\" && git -C .. tag -a \"v$V\" -m \"$V\" && (cd ../core && npm publish) && npm publish && git push --follow-tags",
24
24
  "prepublishOnly": "test -z \"$(git status --porcelain)\" || (echo 'release: working tree is dirty — commit or stash before release' >&2 && exit 1)"
25
25
  },
26
26
  "publishConfig": {
27
27
  "access": "public"
28
28
  },
29
29
  "dependencies": {
30
- "@agfpd/iapeer-memory-core": "0.1.1"
30
+ "@agfpd/iapeer-memory-core": "0.1.2"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/bun": "^1.2.0",
@@ -337,10 +337,17 @@ export async function cmdInit(argv: string[]): Promise<number> {
337
337
  step("sweep", "skipped (--skip-ecosystem)");
338
338
  } else {
339
339
  const sweep = run([flags.iapeerBin, "native-memory", "off", "--all"]);
340
+ // One line per peer-runtime — summarise ALL peers, not the last line
341
+ // (e2e §A finding: ".pop()" named one peer while three were swept).
342
+ const sweepLines = sweep.stdout.trim().split("\n").filter(Boolean);
343
+ const sweptPeers = [
344
+ ...new Set(sweepLines.map((l) => l.split(" ")[0].replace(/:$/, "")).filter(Boolean)),
345
+ ];
340
346
  step(
341
347
  "sweep",
342
348
  sweep.exitCode === 0
343
- ? `native auto-memory off across the fleet (${sweep.stdout.trim().split("\n").pop() ?? "ok"})`
349
+ ? `native auto-memory off across the fleet (${sweptPeers.length} peer(s): ` +
350
+ `${sweptPeers.slice(0, 8).join(", ")}${sweptPeers.length > 8 ? ", …" : ""})`
344
351
  : `soft-skip: core verb unavailable (${sweep.stderr.trim().slice(0, 120) || `exit ${sweep.exitCode}`}) — upgrade the iapeer core and re-run`,
345
352
  );
346
353
  }
package/src/watcher.ts CHANGED
@@ -4,10 +4,14 @@
4
4
  * registration.ts/peerProfileStore.ts + live run):
5
5
  *
6
6
  * - the REGISTRANT is the IAP envelope's from-personality:
7
- * `iapeer send watcher --from index` puts the trigger into
7
+ * `iapeer send watcher --from claude-index` puts the trigger into
8
8
  * `<index-cwd>/.iapeer/peer-profile.json` → `notifier.triggers[]`,
9
9
  * owner=index (writing into a foreign profile is impossible by
10
10
  * invariant). We register from INDEX — the consumer of memoryd events.
11
+ * `--from` takes the full IDENTITY `<runtime>-<personality>` (iapeer
12
+ * cli fact, verified by e2e §A: bare "index" → exit 1 «invalid --from
13
+ * identity»); the durable trigger's `owner` stays the parsed
14
+ * PERSONALITY ("index") — readWatcherTrigger matching is unaffected.
11
15
  * - replies (✓ registered / teaching errors / list) go to the
12
16
  * from-personality SESSION, never to this script — so registration
13
17
  * success is verified by READING THE STATE, not the reply:
@@ -78,16 +82,26 @@ export function registrationMessage(opts: {
78
82
 
79
83
  export type IapSendResult = { ok: boolean; detail: string };
80
84
 
85
+ /** Default registrant personality (trigger owner + event target). */
86
+ const DEFAULT_REGISTRANT = "index";
87
+ /** Role peers are claude-runtime sessions (init creates them via `iapeer create`). */
88
+ const DEFAULT_FROM_RUNTIME = "claude";
89
+
90
+ /** `--from` wants the full identity `<runtime>-<personality>`, never a bare name. */
91
+ export function fromIdentity(personality: string, runtime = DEFAULT_FROM_RUNTIME): string {
92
+ return `${runtime}-${personality}`;
93
+ }
94
+
81
95
  function iapSend(opts: {
82
96
  message: string;
83
- from: string;
97
+ fromIdentity: string;
84
98
  iapeerBin?: string;
85
99
  }): IapSendResult {
86
100
  const bin = opts.iapeerBin ?? "iapeer";
87
101
  let proc: ReturnType<typeof Bun.spawnSync>;
88
102
  try {
89
103
  proc = Bun.spawnSync(
90
- [bin, "send", "watcher", "--from", opts.from, "--message", opts.message],
104
+ [bin, "send", "watcher", "--from", opts.fromIdentity, "--message", opts.message],
91
105
  { stdout: "pipe", stderr: "pipe" },
92
106
  );
93
107
  } catch (err) {
@@ -108,29 +122,34 @@ function iapSend(opts: {
108
122
 
109
123
  export function registerWatcher(opts: {
110
124
  launcherPath: string;
111
- from?: string;
125
+ /** Registrant PERSONALITY (owner of the durable trigger + default target). */
126
+ registrant?: string;
127
+ /** Runtime prefix of the registrant's identity (claude for role peers). */
128
+ runtime?: string;
112
129
  target?: string;
113
130
  id?: string;
114
131
  iapeerBin?: string;
115
132
  }): IapSendResult {
133
+ const registrant = opts.registrant ?? DEFAULT_REGISTRANT;
116
134
  return iapSend({
117
- from: opts.from ?? "index",
135
+ fromIdentity: fromIdentity(registrant, opts.runtime),
118
136
  iapeerBin: opts.iapeerBin,
119
137
  message: registrationMessage({
120
138
  script: opts.launcherPath,
121
- target: opts.target ?? opts.from ?? "index",
139
+ target: opts.target ?? registrant,
122
140
  id: opts.id,
123
141
  }),
124
142
  });
125
143
  }
126
144
 
127
145
  export function unregisterWatcher(opts: {
128
- from?: string;
146
+ registrant?: string;
147
+ runtime?: string;
129
148
  id?: string;
130
149
  iapeerBin?: string;
131
150
  }): IapSendResult {
132
151
  return iapSend({
133
- from: opts.from ?? "index",
152
+ fromIdentity: fromIdentity(opts.registrant ?? DEFAULT_REGISTRANT, opts.runtime),
134
153
  iapeerBin: opts.iapeerBin,
135
154
  message: JSON.stringify({ cmd: "unregister", id: opts.id ?? WATCHER_TRIGGER_ID }),
136
155
  });