@agfpd/iapeer 0.2.77 → 0.2.78

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.
Files changed (113) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +2 -2
  3. package/package.json +21 -2
  4. package/src/cli/index.ts +47 -48
  5. package/src/connect/index.ts +4 -4
  6. package/src/core/constants.ts +3 -3
  7. package/src/core/normalize.ts +2 -2
  8. package/src/create/index.ts +1 -1
  9. package/src/daemon/index.ts +5 -5
  10. package/src/daemon/main.ts +9 -9
  11. package/src/enable/index.ts +19 -18
  12. package/src/enable/provisionCommand.ts +10 -10
  13. package/src/identity/index.ts +2 -2
  14. package/src/identity/profileStandard.ts +8 -8
  15. package/src/init/index.ts +10 -10
  16. package/src/install/index.ts +2 -2
  17. package/src/install/signing.ts +3 -4
  18. package/src/launch/adapters/claude.ts +7 -7
  19. package/src/launch/adapters/codex.ts +5 -6
  20. package/src/launch/canary.ts +8 -8
  21. package/src/launch/cmdlog.ts +3 -3
  22. package/src/launch/composeSystemPrompt.ts +2 -1
  23. package/src/launch/index.ts +5 -6
  24. package/src/launch/invocation.ts +1 -1
  25. package/src/launch/launchd.ts +14 -15
  26. package/src/launch/launchdRun.ts +6 -6
  27. package/src/launch/nativeMemory.ts +9 -9
  28. package/src/launch/ptyHost.ts +1 -1
  29. package/src/launch/readyGateModel.ts +3 -3
  30. package/src/launch/types.ts +7 -7
  31. package/src/lifecycle/eventlog.ts +2 -2
  32. package/src/lifecycle/index.ts +21 -21
  33. package/src/lifecycle/queue.ts +1 -1
  34. package/src/onboard/index.ts +19 -13
  35. package/src/onboard/memory.ts +5 -5
  36. package/src/onboard/steps.ts +8 -9
  37. package/src/provision/index.ts +2 -3
  38. package/src/runtime/deploy.ts +2 -2
  39. package/src/runtime/index.ts +4 -4
  40. package/src/shadow/gate.ts +6 -6
  41. package/src/shadow/index.ts +2 -2
  42. package/src/status/index.ts +11 -11
  43. package/src/storage/index.ts +1 -1
  44. package/src/supervisor/daemon.ts +14 -8
  45. package/src/transport/index.ts +11 -11
  46. package/src/update/index.ts +4 -4
  47. package/src/cli/cli.test.ts +0 -603
  48. package/src/cli/listTui.test.ts +0 -71
  49. package/src/codec/codec.test.ts +0 -271
  50. package/src/connect/connect.test.ts +0 -163
  51. package/src/core/constants.test.ts +0 -32
  52. package/src/core/normalize.test.ts +0 -98
  53. package/src/create/create.test.ts +0 -143
  54. package/src/daemon/daemon-http.test.ts +0 -114
  55. package/src/daemon/daemon.test.ts +0 -267
  56. package/src/daemon/main.test.ts +0 -413
  57. package/src/enable/enable.test.ts +0 -95
  58. package/src/enable/provisionCommand.test.ts +0 -107
  59. package/src/identity/identity.test.ts +0 -279
  60. package/src/identity/profileStandard.test.ts +0 -204
  61. package/src/init/init.test.ts +0 -215
  62. package/src/init/runtime-resolve.test.ts +0 -49
  63. package/src/install/install.test.ts +0 -66
  64. package/src/install/signing.test.ts +0 -84
  65. package/src/launch/bootdeliver.test.ts +0 -108
  66. package/src/launch/bootstrap.test.ts +0 -56
  67. package/src/launch/canary.test.ts +0 -346
  68. package/src/launch/cmdlog.test.ts +0 -94
  69. package/src/launch/codexHooksTrust.test.ts +0 -248
  70. package/src/launch/composeSystemPrompt.layers.test.ts +0 -445
  71. package/src/launch/composeSystemPrompt.test.ts +0 -145
  72. package/src/launch/hostComposerOccupied.test.ts +0 -63
  73. package/src/launch/invocation.test.ts +0 -174
  74. package/src/launch/launch.test.ts +0 -359
  75. package/src/launch/launchd.test.ts +0 -499
  76. package/src/launch/nativeMemory.test.ts +0 -193
  77. package/src/launch/ptyHost.test.ts +0 -38
  78. package/src/launch/readyGateModel.test.ts +0 -72
  79. package/src/launch/sockdir.test.ts +0 -74
  80. package/src/lifecycle/eventlog.test.ts +0 -114
  81. package/src/lifecycle/lifecycle.test.ts +0 -1056
  82. package/src/lifecycle/queue.test.ts +0 -185
  83. package/src/onboard/memory.test.ts +0 -157
  84. package/src/onboard/onboard.test.ts +0 -39
  85. package/src/onboard/steps.test.ts +0 -201
  86. package/src/provision/provision.test.ts +0 -288
  87. package/src/registry/registry.test.ts +0 -432
  88. package/src/runtime/runtime.test.ts +0 -226
  89. package/src/runtime/update.test.ts +0 -192
  90. package/src/shadow/enumerate-skip.test.ts +0 -67
  91. package/src/shadow/gate.test.ts +0 -286
  92. package/src/shadow/install.test.ts +0 -153
  93. package/src/shadow/shadow.test.ts +0 -42
  94. package/src/status/status.test.ts +0 -208
  95. package/src/storage/peers-home.test.ts +0 -34
  96. package/src/storage/rotatelog.test.ts +0 -44
  97. package/src/storage/storage.test.ts +0 -65
  98. package/src/supervisor/attached-marker.test.ts +0 -84
  99. package/src/supervisor/boot.test.ts +0 -66
  100. package/src/supervisor/client.attach.test.ts +0 -107
  101. package/src/supervisor/daemon.test.ts +0 -213
  102. package/src/supervisor/deliver.test.ts +0 -58
  103. package/src/supervisor/panelog.test.ts +0 -95
  104. package/src/supervisor/protocol.test.ts +0 -222
  105. package/src/supervisor/selfargv.test.ts +0 -22
  106. package/src/supervisor/spinner-strip.test.ts +0 -52
  107. package/src/transport/compactDone.test.ts +0 -144
  108. package/src/transport/composerQueue.test.ts +0 -204
  109. package/src/transport/hostControl.test.ts +0 -87
  110. package/src/transport/hostDeliver.test.ts +0 -137
  111. package/src/transport/hostLive.test.ts +0 -50
  112. package/src/transport/routesend-wake.test.ts +0 -357
  113. package/src/update/update.test.ts +0 -208
@@ -4,7 +4,7 @@
4
4
  // by the PROVIDER's own init/uninstall — the core only ever READS it. An absent or
5
5
  // unreadable file is the EMPTY slot — a fully valid state (bare core), never an
6
6
  // error (fail-open). The core never acts on heartbeat staleness — it only REPORTS
7
- // it (healing the provider's daemon is the provider's job, their ADR-010).
7
+ // it (healing the provider's daemon is the provider's job).
8
8
 
9
9
  import { closeSync, openSync, readFileSync, statSync } from 'fs'
10
10
  import { join } from 'path'
@@ -18,18 +18,18 @@ import { iapeerBinPath } from '../install/index.ts'
18
18
  export const MEMORY_PROVIDER_FILE = 'memory-provider.json'
19
19
 
20
20
  // NB: the v1.1 `plugin` block (MemoryProviderPlugin + its parser) was REMOVED
21
- // 11.06 (provider's ADR-017 retired the plugin form ecosystem-wide; contract
22
- // §Плагин провайдера is a tombstone). An unknown `plugin` key in a legacy
21
+ // (the plugin form was retired ecosystem-wide; contract §Плагин провайдера is a
22
+ // tombstone). An unknown `plugin` key in a legacy
23
23
  // declaration is simply ignored — the same fail-open as any unknown block.
24
24
 
25
25
  /** The provider's provision command (declaration v1.2, контракт §Provision
26
- * провайдера — ADR-009 inversion, решение Артура 10.06 + дизайн-консенсус
27
- * сторон). The slot declares not surfaces but a COMMAND the core shells into at
28
- * the lifecycle joints (birth / verb sweeps / remove); surface forms and their
29
- * uninstall accounting live entirely with the provider. The `command` must be
30
- * ABSOLUTE (the daemon runs under launchd's minimal PATH); `args` get PER-ARG
31
- * placeholder substitution ({cwd}/{runtime}/{personality}/{occasion}) and are
32
- * spawned WITHOUT a shell (injection/quoting class — бэктик-грабли 10.06). */
26
+ * провайдера — inversion of the surface-list model). The slot declares not
27
+ * surfaces but a COMMAND the core shells into at the lifecycle joints (birth /
28
+ * verb sweeps / remove); surface forms and their uninstall accounting live
29
+ * entirely with the provider. The `command` must be ABSOLUTE (the daemon runs
30
+ * under launchd's minimal PATH); `args` get PER-ARG placeholder substitution
31
+ * ({cwd}/{runtime}/{personality}/{occasion}) and are spawned WITHOUT a shell
32
+ * (injection/quoting class). */
33
33
  export interface MemoryProviderProvision {
34
34
  /** Absolute path to the provider's executable. */
35
35
  command: string
@@ -179,7 +179,7 @@ export function formatHostStatus(s: HostStatus): string {
179
179
  const daemon = s.daemon.healthy
180
180
  ? `healthy${s.daemon.url ? ` @ ${s.daemon.url}` : ''}${s.daemon.sock ? ` + ${s.daemon.sock}` : ''}`
181
181
  : 'NOT healthy (socket not accepting connections)'
182
- // Heartbeat interpretation (slot contract, provider semantics agreed 10.06):
182
+ // Heartbeat interpretation (slot contract, provider semantics):
183
183
  // file REMOVED on graceful shutdown → declared-but-absent = daemon not running;
184
184
  // present = age shown. The core only REPORTS — staleness healing is the
185
185
  // provider's own job (its verify/repair), never the core's.
@@ -4,7 +4,7 @@
4
4
  // peers.ts (resolveGlobalRoot/resolvePeersPaths/ensureGlobalIapScaffold) +
5
5
  // identity.ts (ensureLocalIapScaffold/ensureLocalRuntimeScopes/peerProfilePath).
6
6
  //
7
- // Structural invariant (#3, boris adversarial-review): peers-profiles.json is
7
+ // Structural invariant (#3): peers-profiles.json is
8
8
  // the registry's exclusive, locked write target. `writeFileAtomic` REFUSES that
9
9
  // basename so no module can write the registry file out from under the lock by
10
10
  // reaching for the generic atomic-write primitive. The registry keeps its own
@@ -27,11 +27,17 @@ import { modelToPlainText } from '../shadow/render.ts'
27
27
  import { codexAdapter } from '../launch/adapters/codex.ts'
28
28
  import { claudeAdapter } from '../launch/adapters/claude.ts'
29
29
 
30
- /** Known runtime launchers; `tick` is a deterministic test stream (no TUI noise) for hermetic
31
- * spawn/attach/reattach tests — it never needs a real claude/codex on the box. */
32
- const KNOWN: Record<string, string> = {
33
- claude: '/Users/macmini/.local/bin/claude',
34
- codex: '/opt/homebrew/bin/codex',
30
+ /** Resolve a runtime launcher from the host AT CALL TIME — env override (IAPEER_<RT>_BIN, the same
31
+ * knob the rest of the foundation uses) → PATH lookup — never a baked machine-specific path. Returns
32
+ * undefined for an unknown runtime, incl. the hermetic `tick` test stream (which uses TICK_CMD, so the
33
+ * spawn/attach/reattach tests never need a real claude/codex on the box). */
34
+ function knownLauncher(runtime: string): string | undefined {
35
+ const override =
36
+ runtime === 'claude' ? process.env.IAPEER_CLAUDE_BIN
37
+ : runtime === 'codex' ? process.env.IAPEER_CODEX_BIN
38
+ : undefined
39
+ if (override?.trim()) return override.trim()
40
+ return Bun.which(runtime) ?? undefined
35
41
  }
36
42
  const TICK_CMD = ['sh', '-c', 'i=0; while true; do printf "STREAMTICK_%d\\r\\n" "$i"; i=$((i+1)); sleep 0.3; done']
37
43
 
@@ -84,7 +90,7 @@ export interface SupervisorDaemonOptions {
84
90
  runDir: string
85
91
  /** Child working directory (default: runDir — a throwaway scratch for dark validation). */
86
92
  cwd?: string
87
- /** Override the runtime launcher (else KNOWN[runtime] if it exists, else the bare name). */
93
+ /** Override the runtime launcher (else resolved from env override / PATH, else the bare name). */
88
94
  bin?: string
89
95
  /** SERVING SEAM (slice b): the composed runtime argv (buildLaunchInvocation). When set, the daemon
90
96
  * serves THIS verbatim instead of the bare [bin] — the supervisor is a HOST, not a composer
@@ -127,7 +133,7 @@ export function runSupervisorDaemon(opts: SupervisorDaemonOptions): void {
127
133
  const ser = new SerializeAddon()
128
134
  xterm.loadAddon(ser)
129
135
 
130
- const bin = opts.bin ?? (KNOWN[runtime] && existsSync(KNOWN[runtime]!) ? KNOWN[runtime]! : runtime)
136
+ const bin = opts.bin ?? knownLauncher(runtime) ?? runtime
131
137
  // SERVING SEAM (slice b): opts.argv (launch-composed, carries the system-prompt swap + PEER_START_ARGS)
132
138
  // is served verbatim; else the bare conduit ([bin], or the deterministic tick stream for tests).
133
139
  const CMD = opts.argv ?? (runtime === 'tick' ? TICK_CMD : [bin])
@@ -170,7 +176,7 @@ export function runSupervisorDaemon(opts: SupervisorDaemonOptions): void {
170
176
  /* */
171
177
  }
172
178
  }
173
- // CRASH-ROBUSTNESS (boris): a crashed predecessor daemon skips shutdown-cleanup, so a STALE
179
+ // CRASH-ROBUSTNESS: a crashed predecessor daemon skips shutdown-cleanup, so a STALE
174
180
  // `.attached` could survive into this fresh daemon — and a stale-present marker would make the
175
181
  // warm-deliver gate believe a human is attached when none is, holding deliveries forever (the
176
182
  // anti-bug inverted). A fresh daemon has ZERO clients, so clear the marker on START (idempotent).
@@ -8,7 +8,7 @@
8
8
  // ViaTmux byte layout) is ported BYTE-FOR-BYTE — it is the validated 0.7.6
9
9
  // deterministic submit and must not be refactored (anti-regression of the
10
10
  // Enter-swallow flap; blueprint §5 "submit-надёжность"). The ONLY contract-
11
- // sanctioned change (07.06 refactor, docs/Рантайм-адаптеры): the prompt glyphs /
11
+ // sanctioned change (docs/Рантайм-адаптеры): the prompt glyphs /
12
12
  // paste patterns are no longer a hardcoded union here — they come from the target
13
13
  // runtime's adapter.deliveryMarkers. The poll/re-press logic is untouched; only the
14
14
  // marker SOURCE moved, so the timing behaviour is identical.
@@ -38,7 +38,7 @@ import {
38
38
  import { buildEnvelope } from '../codec/index.ts'
39
39
  import { findPeer, readPeersIndex, type PeerRecord } from '../registry/index.ts'
40
40
  import type { ResolvedCaller } from '../identity/index.ts'
41
- // Delivery markers are OWNED by the runtime adapter (07.06 refactor). transport
41
+ // Delivery markers are OWNED by the runtime adapter. transport
42
42
  // reads them from getAdapter(target.runtime) for the tui submit path. One-way
43
43
  // dependency: launch does NOT import transport, so no cycle.
44
44
  import { getAdapter } from '../launch/index.ts'
@@ -480,7 +480,7 @@ export function deliverViaTmux(target: DeliveryTarget, envelope: string, cwd?: s
480
480
  // transcript — only a model turn does), so an advance afterwards proves a busy
481
481
  // session is alive. null proxy / no cwd → 0 (the advance check is skipped below).
482
482
  const baselineMtime = cwd ? adapter.newestActivityMtime(cwd) ?? 0 : 0
483
- // Submit markers come from the target runtime's adapter (07.06 refactor).
483
+ // Submit markers come from the target runtime's adapter.
484
484
  const confirmed = submitIntoTui(target.socketPath, target.address, envelope, adapter.deliveryMarkers)
485
485
  tmux(target.socketPath, 'delete-buffer', '-b', bufferName)
486
486
  if (confirmed) return ok(undefined) // idle session accepted the submit
@@ -794,8 +794,8 @@ function compactReadyGraceMs(env: NodeJS.ProcessEnv | undefined): number {
794
794
  * Idle-composer (`isInputReady`) is treated as a FAST-PATH confirmation, NOT a
795
795
  * requirement. A healthy large-context session auto-continues into a working turn
796
796
  * right after compact — its composer is legitimately busy (not idle) for a while, so
797
- * requiring idle here false-failed a finished compact (live incident 15.06, boris:
798
- * marker at 12:14:58, first post-compact idle only ~232s later, past the ~290s gate).
797
+ * requiring idle here false-failed a finished compact (marker seen, but the first
798
+ * post-compact idle only arrived hundreds of seconds later, past the ~290s gate).
799
799
  * Therefore: marker seen + composer idle → 'transcript+ready' (clean); marker seen +
800
800
  * composer still busy past a short grace → 'transcript' (busy-but-done, still SUCCESS).
801
801
  *
@@ -1079,8 +1079,8 @@ export interface RouteDeps {
1079
1079
  * wake, so it held «the topic the session woke with», while the resolver's
1080
1080
  * semantics want «the topic the session last worked on». A long-lived executor
1081
1081
  * that took live-delivered messages of topic B all day then false-FRESHED on
1082
- * stop→start→wake with topic B (live incident 11.06, claude-iapeer: a day of
1083
- * context lost to cause=idle-reaped-new-topic). Injected so transport never
1082
+ * stop→start→wake with topic B (a day of context lost to
1083
+ * cause=idle-reaped-new-topic). Injected so transport never
1084
1084
  * imports lifecycle (layering — main.ts is where the two meet); call sites
1085
1085
  * swallow hook errors (a hook must never fail a delivered message). */
1086
1086
  noteLiveTopic?: (identity: string, topic: string) => void
@@ -1324,12 +1324,12 @@ function validateAttachments(value: readonly string[] = []): Result<string[]> {
1324
1324
  return ok(out)
1325
1325
  }
1326
1326
 
1327
- // ─── Telegram-domain sender policy (defect track 11.06, sanctioned by Артур) ─
1327
+ // ─── Telegram-domain sender policy ─
1328
1328
 
1329
1329
  /** A SENDER face in the telegram domain: a non-empty interfaces.telegram.bot (the
1330
1330
  * bot machine-key) in the peer's registry passport. Deliberately bot-ONLY, not
1331
- * bot|user_id — the bridge picks the SENDING bot from the sender's bot key
1332
- * (owner fact, telegram-runtime сверка 11.06): a user_id grants a receive/operator
1331
+ * bot|user_id — the bridge picks the SENDING bot from the sender's bot key:
1332
+ * a user_id grants a receive/operator
1333
1333
  * identity but no ability to send, so a user_id-only sender passing the guard
1334
1334
  * would still die at the bridge — a late asynchronous failure where the guard
1335
1335
  * exists to give a synchronous one. The guard passes exactly what the bridge can
@@ -1360,7 +1360,7 @@ function telegramSenderGuard(
1360
1360
  if (targetRuntime !== 'telegram') return ok(undefined)
1361
1361
  if (hasTelegramPresence(caller.record)) return ok(undefined)
1362
1362
  return err(
1363
- `telegram policy: sender "${caller.personality}" has no telegram face (no interfaces.telegram.bot in its passport) — message to "${targetPersonality}" NOT delivered; route via a telegram-faced peer (e.g. boris) or provision a bot for this sender`,
1363
+ `telegram policy: sender "${caller.personality}" has no telegram face (no interfaces.telegram.bot in its passport) — message to "${targetPersonality}" NOT delivered; route via a peer that has a telegram bot in its passport, or provision a bot for this sender`,
1364
1364
  )
1365
1365
  }
1366
1366
 
@@ -17,7 +17,7 @@
17
17
  // Scope: the foundation ONLY (the @agfpd/iapeer binary + its daemon + launchd
18
18
  // registrations of foundation-owned infra jobs that point at that binary). It never
19
19
  // rewrites those plists, never updates runtime packages (telegram-runtime /
20
- // notifier-runtime / MergeMind), and never touches foreign / persistent-peer fleet
20
+ // notifier-runtime / capability plugins), and never touches foreign / persistent-peer fleet
21
21
  // plists — only sentinel-marked foundation-owned com.iapeer.* jobs are recycled.
22
22
  //
23
23
  // updateIapeer takes its three side-effects as INJECTED deps so the version-gate is
@@ -184,7 +184,7 @@ function defaultResolveVersion(spec: string, env: NodeJS.ProcessEnv): string | n
184
184
  * install) npx resolves that bin NAME to the COMPILED binary already on PATH and
185
185
  * runs ITS `install` — which cannot rebuild itself from source (`bun build --compile`
186
186
  * gets a `/$bunfs/root` entrypoint → FileNotFound) — instead of fetching + running the
187
- * freshly-published source. Verified reproducible (09.06, 0.2.8 deploy): with NO
187
+ * freshly-published source. Verified reproducible: with NO
188
188
  * `iapeer` on PATH the same npx invocation prints `command not found` — it never
189
189
  * installs the package — so this is a structural bin-name collision, NOT the
190
190
  * publish-propagation transient (waiting/retry does not cure it).
@@ -287,8 +287,8 @@ export function updateIapeer(deps: UpdateDeps = {}): UpdateResult {
287
287
  if (!runInstall(desired, env)) {
288
288
  // NB: the installer is the DETERMINISTIC pack+build path (no npx — see
289
289
  // defaultRunInstall); the most common cause right after a publish is the npm
290
- // CDN tarball lagging the version metadata (live-hit 10.06: `npm view` already
291
- // showed the version, `npm pack` still failed; a retry ~1 min later succeeded).
290
+ // CDN tarball lagging the version metadata (`npm view` can already show the
291
+ // version while `npm pack` still fails; a retry ~1 min later succeeds).
292
292
  return {
293
293
  status: 'failed',
294
294
  from,