@agfpd/iapeer 0.2.45 → 0.2.46

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",
3
- "version": "0.2.45",
3
+ "version": "0.2.46",
4
4
  "description": "Foundation core for the iapeer multi-agent ecosystem: identity, registry, storage, codec.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -476,10 +476,27 @@ describe('add-runtime / default-runtime (fleet-switch levers)', () => {
476
476
  expect(prof.runtime).toBe('claude') // default_runtime NOT flipped
477
477
  const rec = findPeer(readPeersIndex({ env: e }), 'aud1')!
478
478
  expect(rec.runtimes).toContain('codex')
479
+ expect(rec.runtime).toBe('claude') // registry default NOT flipped (capability ≠ routing; live-caught: upsert's «args.runtime wins» needed the reindex heal)
479
480
  // idempotent
480
481
  expect((await addRuntime('codex', { peer: 'aud1', env: e }))[0].action).toBe('already')
481
482
  })
482
483
 
484
+ test('add-runtime works from INSIDE another peer session (poisoned PEER_* env) — live-caught 12.06', async () => {
485
+ const e = env()
486
+ e.PEER_PERSONALITY = 'iapeer' // the caller's own identity must not poison the target's init
487
+ e.PEER_RUNTIME = 'claude'
488
+ e.PEER_IDENTITY = 'claude-iapeer'
489
+ const cwd = join(root, 'peers', 'aud3')
490
+ mkdirSync(cwd, { recursive: true })
491
+ await upsertPeer({ personality: 'aud3', runtime: 'claude', cwd, intelligence: 'artificial' }, { rootDir: root })
492
+ const { initPeer } = await import('../init/index.ts')
493
+ const cleanE = { ...e }
494
+ delete cleanE.PEER_PERSONALITY; delete cleanE.PEER_RUNTIME; delete cleanE.PEER_IDENTITY
495
+ await initPeer({ cwd, runtime: 'claude', env: cleanE })
496
+ const outcomes = await addRuntime('codex', { peer: 'aud3', env: e })
497
+ expect(outcomes[0].action).toBe('added')
498
+ })
499
+
483
500
  test('add-runtime refuses an infra runtime as the argument', async () => {
484
501
  await register('x1')
485
502
  await expect(addRuntime('telegram', { peer: 'x1', env: env() })).rejects.toThrow('infra runtime')
package/src/cli/index.ts CHANGED
@@ -303,6 +303,14 @@ export async function addRuntime(
303
303
  const index = readPeersIndex({ env })
304
304
  const targets = opts.all === true ? index.peers : index.peers.filter(p => p.personality === opts.peer)
305
305
  if (targets.length === 0) throw new Error(opts.peer ? `peer "${opts.peer}" is not registered` : 'no targets — pass --peer <p> or --all')
306
+ // CROSS-PEER operation: strip the CALLER's identity env (PEER_*) — an operator
307
+ // (or an agent peer) running this from inside their own session would otherwise
308
+ // poison the TARGET's ensurePeerProfile identity check (live-caught on the very
309
+ // first 0.2.45 probe: PEER_PERSONALITY="iapeer" vs target "twpar" → failed).
310
+ const cleanEnv: NodeJS.ProcessEnv = { ...env }
311
+ delete cleanEnv.PEER_PERSONALITY
312
+ delete cleanEnv.PEER_RUNTIME
313
+ delete cleanEnv.PEER_IDENTITY
306
314
  const { initPeer } = await import('../init/index.ts')
307
315
  const out: AddRuntimeOutcome[] = []
308
316
  for (const p of targets) {
@@ -316,12 +324,18 @@ export async function addRuntime(
316
324
  }
317
325
  try {
318
326
  const warns: string[] = []
319
- await initPeer({ cwd: p.cwd, runtime: runtime as Runtime, env, warn: m => warns.push(m) })
327
+ await initPeer({ cwd: p.cwd, runtime: runtime as Runtime, env: cleanEnv, warn: m => warns.push(m) })
320
328
  out.push({ personality: p.personality, action: 'added', detail: warns.length ? warns.join(' | ') : undefined })
321
329
  } catch (e) {
322
330
  out.push({ personality: p.personality, action: 'failed', detail: e instanceof Error ? e.message : String(e) })
323
331
  }
324
332
  }
333
+ // Self-heal the registry from the locals: provisionPeer's upsert sets the record's
334
+ // default to the PROVISIONED runtime («args.runtime wins» — right for births, wrong
335
+ // here: add-runtime is capability-only and must NOT flip routing). The reindex
336
+ // REPLACE projection restores the local profile's untouched default (live-caught
337
+ // on the 0.2.45 probe: registry default flipped to codex while the local kept claude).
338
+ if (out.some(o => o.action === 'added')) await reindexFromLocals({ env })
325
339
  return out
326
340
  }
327
341