@adhdev/daemon-standalone 1.0.58-rc.30 → 1.0.58-rc.31

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/index.js CHANGED
@@ -36885,10 +36885,10 @@ var require_dist3 = __commonJS({
36885
36885
  }
36886
36886
  function getDaemonBuildInfo() {
36887
36887
  if (cached2) return cached2;
36888
- const commit = readInjected(true ? "2b2c70723e15856b63170cd9496e217fe6d8e02a" : void 0) ?? "unknown";
36889
- const commitShort = readInjected(true ? "2b2c7072" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
36890
- const version2 = readInjected(true ? "1.0.58-rc.30" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
36891
- const builtAt = readInjected(true ? "2026-08-28T01:12:45.223Z" : void 0);
36888
+ const commit = readInjected(true ? "d999ca9754d675f6c465f5bab1ff747fc444f7c6" : void 0) ?? "unknown";
36889
+ const commitShort = readInjected(true ? "d999ca97" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
36890
+ const version2 = readInjected(true ? "1.0.58-rc.31" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
36891
+ const builtAt = readInjected(true ? "2026-08-28T04:19:17.942Z" : void 0);
36892
36892
  cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
36893
36893
  return cached2;
36894
36894
  }
@@ -43741,7 +43741,8 @@ child.on('exit', () => process.exit(0));
43741
43741
  "command_result",
43742
43742
  "error",
43743
43743
  "agent_event",
43744
- "log"
43744
+ "log",
43745
+ "beacon_vectors"
43745
43746
  ];
43746
43747
  SERVER_TO_DAEMON_WS_MSGS = [
43747
43748
  "auth_ok",
@@ -43753,7 +43754,8 @@ child.on('exit', () => process.exit(0));
43753
43754
  "force_update_required",
43754
43755
  "command",
43755
43756
  "agent_command",
43756
- "resolve_action"
43757
+ "resolve_action",
43758
+ "beacon_vectors_result"
43757
43759
  ];
43758
43760
  }
43759
43761
  });
@@ -50985,7 +50987,7 @@ The instruction it carried was never delivered to anyone. If it still matters, r
50985
50987
  // bound a hostile peer streams arbitrarily many distinct in-range chunks into
50986
50988
  // one map. 64 MiB = 256 × MAX_FRAME_BYTES; the largest library-bounded
50987
50989
  // legitimate body is a ring-tail SNAP of RING_DEFAULT (500) rows ×
50988
- // MAX_ROW_BYTES (65_536) ≈ 32 MiB, ≈ 43.7 MiB after base64 — comfortably
50990
+ // MAX_ROW_BYTES (65_536) = 31.25 MiB, ≈ 41.7 MiB after base64 — comfortably
50989
50991
  // under. Hosts serving bigger (policy-unbounded) view tables raise this.
50990
50992
  MAX_REASSEMBLY_BYTES: 67108864,
50991
50993
  INFLIGHT_CREDITS: 4,
@@ -51910,27 +51912,47 @@ The instruction it carried was never delivered to anyone. If it still matters, r
51910
51912
  var init_beacon = __esm2({
51911
51913
  "../../vendor/seqscribe/dist/beacon.js"() {
51912
51914
  "use strict";
51915
+ init_encoding();
51913
51916
  init_errors3();
51914
51917
  BeaconHub = class {
51915
51918
  deps;
51916
51919
  known = [];
51917
51920
  transport = null;
51918
51921
  debounceTimer = null;
51919
- stopped = false;
51922
+ // Node-level teardown (proposals-v3.5 P28). Terminal and distinct from an
51923
+ // arming's stop(): a BeaconHub that outlived its owning node's close() must
51924
+ // never push again, so this is the one latch that is genuinely one-way.
51925
+ closed = false;
51926
+ hostHints = null;
51927
+ // Monotonic arming id. stop() is a PAUSE — the hub is re-startable, matching
51928
+ // the shape of start() itself (a handle you can stop() reads as something you
51929
+ // can start() again) and the reconnect-scoped re-arm hosts actually write.
51930
+ // Handles are per-arming: a stale handle's stop() must not tear down a LATER
51931
+ // arming, which is why stop() compares its own generation before acting.
51932
+ armGen = 0;
51920
51933
  constructor(deps) {
51921
51934
  this.deps = deps;
51922
51935
  }
51923
- start(t) {
51936
+ start(t, o) {
51937
+ if (this.closed)
51938
+ throw misuse("beacon closed \u2014 the node is closed");
51924
51939
  if (this.transport)
51925
51940
  throw misuse("beacon already started");
51941
+ const gen = ++this.armGen;
51926
51942
  this.transport = t;
51943
+ this.hostHints = o?.hints ?? null;
51927
51944
  this.push();
51928
51945
  return {
51929
51946
  stop: () => {
51930
- this.stopped = true;
51931
- if (this.debounceTimer !== null)
51947
+ if (this.armGen !== gen)
51948
+ return;
51949
+ this.armGen++;
51950
+ if (this.debounceTimer !== null) {
51932
51951
  this.deps.timers.clearTimeout(this.debounceTimer);
51952
+ this.debounceTimer = null;
51953
+ }
51933
51954
  this.transport = null;
51955
+ this.hostHints = null;
51934
51956
  }
51935
51957
  };
51936
51958
  }
@@ -51938,16 +51960,18 @@ The instruction it carried was never delivered to anyone. If it still matters, r
51938
51960
  // core.vectors() when it fires, so node.close() must cancel it like every
51939
51961
  // other hub timer rather than rely on the host calling the handle's stop().
51940
51962
  close() {
51941
- this.stopped = true;
51963
+ this.closed = true;
51964
+ this.armGen++;
51942
51965
  if (this.debounceTimer !== null) {
51943
51966
  this.deps.timers.clearTimeout(this.debounceTimer);
51944
51967
  this.debounceTimer = null;
51945
51968
  }
51946
51969
  this.transport = null;
51970
+ this.hostHints = null;
51947
51971
  }
51948
51972
  // called from the applied fan-out — 5 s debounce after append (§5.7)
51949
51973
  notifyApplied() {
51950
- if (!this.transport || this.stopped || this.debounceTimer !== null)
51974
+ if (!this.transport || this.closed || this.debounceTimer !== null)
51951
51975
  return;
51952
51976
  this.debounceTimer = this.deps.timers.setTimeout(() => {
51953
51977
  this.debounceTimer = null;
@@ -51990,17 +52014,73 @@ The instruction it carried was never delivered to anyone. If it still matters, r
51990
52014
  }
51991
52015
  return out;
51992
52016
  }
52017
+ // §5.7 hints (P27). `hintKeys` is the per-topic opt-in gate: a topic that has
52018
+ // not set it contributes nothing and, if the host names it anyway, is dropped
52019
+ // — the SPEC wire format implies the gate, and honoring it is what stops a
52020
+ // "hash" declaration from leaking plaintext keys by omission.
52021
+ // "plain" — the key as authored
52022
+ // "hash" — sha256 hex of the key, so a board operator sees change activity
52023
+ // without learning key names
52024
+ // Host-supplied entries are merged OVER library-derived ones for the same
52025
+ // topic: the host asked for a specific advertisement, so it wins.
52026
+ buildHints() {
52027
+ const out = {};
52028
+ const modeOf = (topic) => {
52029
+ try {
52030
+ return this.deps.topics.get(topic).policy.hintKeys;
52031
+ } catch {
52032
+ return void 0;
52033
+ }
52034
+ };
52035
+ const add = (topic, mode, raw) => {
52036
+ const dst = out[topic] ??= {};
52037
+ for (const [key2, at] of Object.entries(raw))
52038
+ dst[mode === "hash" ? sha256HexUtf8(key2) : key2] = at;
52039
+ };
52040
+ const registers = this.deps.registers;
52041
+ if (registers)
52042
+ for (const topic of this.deps.topics.list()) {
52043
+ const mode = modeOf(topic);
52044
+ if (mode === void 0)
52045
+ continue;
52046
+ if (this.deps.topics.get(topic).policy.kind !== "register")
52047
+ continue;
52048
+ add(topic, mode, registers.hintsFor(topic));
52049
+ }
52050
+ if (this.hostHints) {
52051
+ let supplied;
52052
+ try {
52053
+ supplied = this.hostHints();
52054
+ } catch {
52055
+ supplied = {};
52056
+ }
52057
+ for (const [topic, raw] of Object.entries(supplied)) {
52058
+ const mode = modeOf(topic);
52059
+ if (mode === void 0)
52060
+ continue;
52061
+ add(topic, mode, raw);
52062
+ }
52063
+ }
52064
+ for (const topic of Object.keys(out))
52065
+ if (Object.keys(out[topic]).length === 0)
52066
+ delete out[topic];
52067
+ return Object.keys(out).length > 0 ? out : void 0;
52068
+ }
51993
52069
  push() {
51994
52070
  const t = this.transport;
51995
- if (!t || this.stopped)
52071
+ if (!t || this.closed)
51996
52072
  return;
52073
+ const gen = this.armGen;
51997
52074
  const report = {
51998
52075
  node: this.deps.writerId,
51999
52076
  at: new Date(this.deps.clock()).toISOString(),
52000
52077
  vectors: this.deps.core.vectors()
52001
52078
  };
52079
+ const hints = this.buildHints();
52080
+ if (hints)
52081
+ report.hints = hints;
52002
52082
  void t.put(report).then(() => t.get()).then((reports) => {
52003
- if (!this.stopped)
52083
+ if (!this.closed && this.armGen === gen)
52004
52084
  this.known = reports;
52005
52085
  }).catch(() => {
52006
52086
  });
@@ -53593,6 +53673,38 @@ The instruction it carried was never delivered to anyone. If it still matters, r
53593
53673
  ownerOf(topic, key2) {
53594
53674
  return this.topicState(topic).keys.get(key2)?.owner ?? null;
53595
53675
  }
53676
+ // §5.7 pre-write warning source (proposals-v3.5 P27): the latest change this
53677
+ // node knows about per key, as the [writer, seq] shape BeaconReport.hints
53678
+ // declares. Sourced from the MATERIALIZED winner, NOT from scopeTails —
53679
+ // scopeTails is the §11.2 own-uncommitted tail and is deleted as each own
53680
+ // write materializes (and never holds a peer's write at all), so it is empty
53681
+ // in exactly the steady state a hint has to describe. `winner` is the fold's
53682
+ // per-key judgment over the total order, which is what "latest known change
53683
+ // to this key" means, and it covers peer writes and own writes alike.
53684
+ //
53685
+ // Member-only keys (a set with no scalar winner) report their highest member
53686
+ // entry: under §11.5 mirror rules such a key never has a `winner`, but an
53687
+ // add/remove is still a change a concurrent editor would overwrite.
53688
+ hintsFor(topic) {
53689
+ const out = {};
53690
+ for (const [key2, ks] of this.topicState(topic).keys) {
53691
+ let best;
53692
+ let bestOrder;
53693
+ if (ks.winner && ks.winnerOrder) {
53694
+ best = [ks.winner[1], ks.winner[2]];
53695
+ bestOrder = ks.winnerOrder;
53696
+ }
53697
+ for (const ms of ks.members.values()) {
53698
+ if (bestOrder !== void 0 && orderCompare(ms.order, bestOrder) <= 0)
53699
+ continue;
53700
+ best = [ms.entry[1], ms.entry[2]];
53701
+ bestOrder = ms.order;
53702
+ }
53703
+ if (best)
53704
+ out[key2] = best;
53705
+ }
53706
+ return out;
53707
+ }
53596
53708
  pendingRequests(topic, now) {
53597
53709
  const cutoff = (now ?? this.deps.clock()) - this.deps.constants.REQUEST_TTL_MS;
53598
53710
  const out = [];
@@ -57362,7 +57474,15 @@ CREATE TABLE IF NOT EXISTS sq_archive (
57362
57474
  sync.setSnapshotHub(snapshots);
57363
57475
  const archive = new ArchiveHub({ core: core2, store, topics, views, registers, constants: constants2, clock, emitAnomaly });
57364
57476
  consumers.setOnAdvance((topic) => archive.onConsumerAdvance(topic));
57365
- const beaconHub = new BeaconHub({ core: core2, topics, writerId: opts.writerId, constants: constants2, timers, clock });
57477
+ const beaconHub = new BeaconHub({
57478
+ core: core2,
57479
+ topics,
57480
+ writerId: opts.writerId,
57481
+ constants: constants2,
57482
+ timers,
57483
+ clock,
57484
+ registers
57485
+ });
57366
57486
  finalityHub.setOnAccepted((cert) => {
57367
57487
  views.notifyApplied(cert.topic);
57368
57488
  sync.onCertAccepted();
@@ -57407,7 +57527,7 @@ CREATE TABLE IF NOT EXISTS sq_archive (
57407
57527
  vectors: () => core2.vectors(),
57408
57528
  setKnownVectors: (v) => beaconHub.setKnownVectors(v),
57409
57529
  staleness: (topic, key2) => beaconHub.staleness(topic, key2),
57410
- beacon: (t) => beaconHub.start(t),
57530
+ beacon: (t, o) => beaconHub.start(t, o),
57411
57531
  finality: (topic) => finalityHub.finality(topic),
57412
57532
  proposeFinality: (topic) => finalityHub.proposeFinality(topic),
57413
57533
  ingestFinality: (cert) => finalityHub.ingestFinality(cert),
@@ -96908,6 +97028,7 @@ ${e?.stderr || ""}`;
96908
97028
  ASSISTANT_JOURNAL_TOPIC: () => ASSISTANT_JOURNAL_TOPIC,
96909
97029
  AcpProviderInstance: () => AcpProviderInstance,
96910
97030
  AgentStreamPoller: () => AgentStreamPoller,
97031
+ BEACON_ENV: () => BEACON_ENV,
96911
97032
  BUILD_CHANNEL_ENV_VAR: () => BUILD_CHANNEL_ENV_VAR,
96912
97033
  BUILTIN_CHAT_MESSAGE_KINDS: () => BUILTIN_CHAT_MESSAGE_KINDS,
96913
97034
  CANONICAL_MESH_TOOL_COUNT: () => CANONICAL_MESH_TOOL_COUNT,
@@ -96988,6 +97109,7 @@ ${e?.stderr || ""}`;
96988
97109
  LowDiskSpaceError: () => LowDiskSpaceError,
96989
97110
  MAGI_NEEDS_VERIFICATION_PREVIEW_CAP: () => MAGI_NEEDS_VERIFICATION_PREVIEW_CAP,
96990
97111
  MAGI_RAW_ANSWER_CAP: () => MAGI_RAW_ANSWER_CAP,
97112
+ MAX_BEACON_GET_QUERIES: () => MAX_BEACON_GET_QUERIES,
96991
97113
  MAX_CAPTURE_LOG_GENERATIONS: () => MAX_CAPTURE_LOG_GENERATIONS,
96992
97114
  MAX_CAPTURE_LOG_SIZE: () => MAX_CAPTURE_LOG_SIZE,
96993
97115
  MAX_INFLIGHT: () => MAX_INFLIGHT,
@@ -97100,7 +97222,9 @@ ${e?.stderr || ""}`;
97100
97222
  appendLedgerEntry: () => appendLedgerEntry,
97101
97223
  appendRecentActivity: () => appendRecentActivity,
97102
97224
  appendRemoteLedgerEntries: () => appendRemoteLedgerEntries,
97225
+ armBeacon: () => armBeacon,
97103
97226
  assertNoDependencyCycle: () => assertNoDependencyCycle,
97227
+ assertNoPlaintextHintTopics: () => assertNoPlaintextHintTopics,
97104
97228
  assistantJournalPolicy: () => assistantJournalPolicy,
97105
97229
  backfillMeshEventShadow: () => backfillMeshEventShadow,
97106
97230
  baseTopicDefinitions: () => baseTopicDefinitions,
@@ -97208,6 +97332,7 @@ ${e?.stderr || ""}`;
97208
97332
  daemonIdsEquivalent: () => daemonIdsEquivalent,
97209
97333
  decideMissingSessionAttempt: () => decideMissingSessionAttempt2,
97210
97334
  declareWorkspaceIntents: () => declareWorkspaceIntents,
97335
+ defaultBeaconTopicScope: () => defaultBeaconTopicScope,
97211
97336
  delegatedWorkerAutoApproveSettings: () => delegatedWorkerAutoApproveSettings,
97212
97337
  deleteDirectDispatchesByTaskId: () => deleteDirectDispatchesByTaskId,
97213
97338
  deleteMesh: () => deleteMesh,
@@ -97472,6 +97597,7 @@ ${e?.stderr || ""}`;
97472
97597
  printQuotaInstallError: () => printQuotaInstallError2,
97473
97598
  printQuotaRefreshOutcome: () => printQuotaRefreshOutcome2,
97474
97599
  probeCdpPort: () => probeCdpPort,
97600
+ projectBeaconReport: () => projectBeaconReport,
97475
97601
  projectGraphPublicPolicy: () => projectGraphPublicPolicy,
97476
97602
  projectMeshLedgerEntry: () => projectMeshLedgerEntry,
97477
97603
  pruneOperatingNotes: () => pruneOperatingNotes,
@@ -97538,6 +97664,7 @@ ${e?.stderr || ""}`;
97538
97664
  resolveAllowSendKeysDestructive: () => resolveAllowSendKeysDestructive,
97539
97665
  resolveAutoConvergeCodeChange: () => resolveAutoConvergeCodeChange,
97540
97666
  resolveBackoffMs: () => resolveBackoffMs,
97667
+ resolveBeaconMode: () => resolveBeaconMode,
97541
97668
  resolveBuildTrack: () => resolveBuildTrack,
97542
97669
  resolveChatMessageKind: () => resolveChatMessageKind,
97543
97670
  resolveConsoleSymbols: () => resolveConsoleSymbols,
@@ -147984,10 +148111,22 @@ data: ${JSON.stringify(msg.data)}
147984
148111
  "Seqscribe",
147985
148112
  `node open writer=${writerId} topics=${defs.length} authority=${authority ? "on" : "off"}${opts.isCoordinator ? " role=coordinator" : ""}`
147986
148113
  );
148114
+ const closeCallbacks = [];
147987
148115
  let closed = false;
147988
148116
  const close = async () => {
147989
148117
  if (closed) return;
147990
148118
  closed = true;
148119
+ while (closeCallbacks.length > 0) {
148120
+ const fn = closeCallbacks.shift();
148121
+ try {
148122
+ fn();
148123
+ } catch (err) {
148124
+ LOG2.warn(
148125
+ "Seqscribe",
148126
+ `close callback failed: ${err instanceof Error ? err.message : String(err)}`
148127
+ );
148128
+ }
148129
+ }
147991
148130
  try {
147992
148131
  finalityLoop?.stop();
147993
148132
  } catch {
@@ -148018,6 +148157,16 @@ data: ${JSON.stringify(msg.data)}
148018
148157
  topics: defs,
148019
148158
  authorityEnabled: authority !== null,
148020
148159
  finalityLoop,
148160
+ onClose: (fn) => {
148161
+ if (closed) {
148162
+ try {
148163
+ fn();
148164
+ } catch {
148165
+ }
148166
+ return;
148167
+ }
148168
+ closeCallbacks.push(fn);
148169
+ },
148021
148170
  close
148022
148171
  };
148023
148172
  }
@@ -149415,6 +149564,279 @@ ${upgradeFailureNotice.notice}${supersededHint}`);
149415
149564
  \u2717 ${message}
149416
149565
  `));
149417
149566
  }
149567
+ init_logger();
149568
+ init_topics2();
149569
+ var BEACON_ENV = "ADHDEV_SEQSCRIBE_BEACON";
149570
+ function resolveBeaconMode(env2 = process.env) {
149571
+ const raw = env2[BEACON_ENV]?.trim().toLowerCase();
149572
+ if (!raw) return "on";
149573
+ if (raw === "off") return "off";
149574
+ if (raw === "on") return "on";
149575
+ warnOnce4(
149576
+ `unrecognized ${BEACON_ENV}=${raw}; treating as 'on'. Valid values are 'on' (default) and 'off'.`
149577
+ );
149578
+ return "on";
149579
+ }
149580
+ var warnedUnrecognized = false;
149581
+ function warnOnce4(message) {
149582
+ if (warnedUnrecognized) return;
149583
+ warnedUnrecognized = true;
149584
+ LOG2.warn("Seqscribe", message);
149585
+ }
149586
+ var CHAIN_RE2 = /^[0-9a-f]{64}$/;
149587
+ var WRITER_ID_RE = /^[A-Za-z0-9._:-]{1,128}$/;
149588
+ var TOPIC_RE2 = /^[A-Za-z0-9._*-]{1,160}$/;
149589
+ var MAX_TOPICS_PER_REPORT = 512;
149590
+ var MAX_WRITERS_PER_TOPIC = 512;
149591
+ function finiteCount(v) {
149592
+ return typeof v === "number" && Number.isFinite(v) && v >= 0 ? Math.floor(v) : void 0;
149593
+ }
149594
+ function hash64(v) {
149595
+ return typeof v === "string" && CHAIN_RE2.test(v) ? v : void 0;
149596
+ }
149597
+ function projectWriterEntry(raw) {
149598
+ if (!raw || typeof raw !== "object") return null;
149599
+ const v = raw;
149600
+ const rgen = finiteCount(v.rgen);
149601
+ if (v.retired === true) {
149602
+ const finalSeq = finiteCount(v.finalSeq);
149603
+ const finalChain = hash64(v.finalChain);
149604
+ if (finalSeq === void 0 || finalChain === void 0 || rgen === void 0) return null;
149605
+ return { retired: true, finalSeq, finalChain, rgen };
149606
+ }
149607
+ const contig = finiteCount(v.contig);
149608
+ const chain = hash64(v.chain);
149609
+ if (contig === void 0 || chain === void 0) return null;
149610
+ return rgen === void 0 ? { contig, chain } : { contig, chain, rgen };
149611
+ }
149612
+ function projectBeaconReport(raw) {
149613
+ if (!raw || typeof raw !== "object") return null;
149614
+ const v = raw;
149615
+ const node = typeof v.node === "string" && WRITER_ID_RE.test(v.node) ? v.node : null;
149616
+ if (!node) return null;
149617
+ const at = typeof v.at === "string" && !Number.isNaN(Date.parse(v.at)) ? new Date(v.at).toISOString() : (/* @__PURE__ */ new Date(0)).toISOString();
149618
+ const vectors = {};
149619
+ const rawVectors = v.vectors;
149620
+ if (rawVectors && typeof rawVectors === "object") {
149621
+ let topicCount = 0;
149622
+ for (const [topic, vec] of Object.entries(rawVectors)) {
149623
+ if (topicCount >= MAX_TOPICS_PER_REPORT) break;
149624
+ if (!TOPIC_RE2.test(topic)) continue;
149625
+ if (!vec || typeof vec !== "object") continue;
149626
+ const rawWriters = vec.writers;
149627
+ if (!rawWriters || typeof rawWriters !== "object") continue;
149628
+ const writers = {};
149629
+ let writerCount = 0;
149630
+ for (const [writerId, entry] of Object.entries(rawWriters)) {
149631
+ if (writerCount >= MAX_WRITERS_PER_TOPIC) break;
149632
+ if (!WRITER_ID_RE.test(writerId)) continue;
149633
+ const clean2 = projectWriterEntry(entry);
149634
+ if (!clean2) continue;
149635
+ writers[writerId] = clean2;
149636
+ writerCount++;
149637
+ }
149638
+ if (writerCount === 0) continue;
149639
+ const fgen = finiteCount(vec.fgen);
149640
+ vectors[topic] = fgen === void 0 ? { writers } : { fgen, writers };
149641
+ topicCount++;
149642
+ }
149643
+ }
149644
+ return { node, at, vectors };
149645
+ }
149646
+ function assertNoPlaintextHintTopics(defs) {
149647
+ const offenders = defs.filter((d) => d.policy.hintKeys === "plain").map((d) => d.topic);
149648
+ if (offenders.length === 0) return;
149649
+ throw new Error(
149650
+ `seqscribe beacon: topic(s) ${offenders.join(", ")} declare hintKeys:'plain'. Only 'hash' (or omitting the field) is permitted \u2014 plaintext register keys on the server exceed the approved Beacon content-boundary exception (CLAUDE.md).`
149651
+ );
149652
+ }
149653
+ function defaultBeaconTopicScope(vectors) {
149654
+ return Object.keys(vectors).filter(
149655
+ (topic) => topic === FLEET_STATUS_TOPIC || meshIdFromEventsTopic(topic) !== null
149656
+ );
149657
+ }
149658
+ function emptyCounters() {
149659
+ return {
149660
+ put: 0,
149661
+ putFailed: 0,
149662
+ get: 0,
149663
+ getFailed: 0,
149664
+ truncated: 0,
149665
+ rejected: 0,
149666
+ splitRetries: 0
149667
+ };
149668
+ }
149669
+ var MAX_BEACON_GET_QUERIES = 16;
149670
+ function mergeBeaconReportsByNode(left, right) {
149671
+ const byNode = /* @__PURE__ */ new Map();
149672
+ const unkeyed = [];
149673
+ const ingest2 = (report) => {
149674
+ const node = report && typeof report === "object" && typeof report.node === "string" ? report.node : void 0;
149675
+ if (!node) {
149676
+ unkeyed.push(report);
149677
+ return;
149678
+ }
149679
+ const existing = byNode.get(node);
149680
+ if (!existing) {
149681
+ byNode.set(node, report);
149682
+ return;
149683
+ }
149684
+ const existingAt = existing.at;
149685
+ const candidateAt = report.at;
149686
+ const existingTime = typeof existingAt === "string" ? Date.parse(existingAt) : NaN;
149687
+ const candidateTime = typeof candidateAt === "string" ? Date.parse(candidateAt) : NaN;
149688
+ if (!Number.isNaN(candidateTime) && (Number.isNaN(existingTime) || candidateTime > existingTime)) {
149689
+ byNode.set(node, report);
149690
+ }
149691
+ };
149692
+ for (const r of left) ingest2(r);
149693
+ for (const r of right) ingest2(r);
149694
+ return [...byNode.values(), ...unkeyed];
149695
+ }
149696
+ function armBeacon(handle, transport, opts = {}) {
149697
+ const mode = resolveBeaconMode(opts.env ?? process.env);
149698
+ if (mode === "off") {
149699
+ LOG2.info("Seqscribe", `beacon disabled (${BEACON_ENV}=off)`);
149700
+ return null;
149701
+ }
149702
+ assertNoPlaintextHintTopics(handle.topics);
149703
+ const counters5 = emptyCounters();
149704
+ const scopeOf = opts.topicScope ?? defaultBeaconTopicScope;
149705
+ let stopped = false;
149706
+ let lastScope = [];
149707
+ const doPut = async (rawReport) => {
149708
+ const projected = projectBeaconReport(rawReport);
149709
+ if (!projected) {
149710
+ counters5.rejected++;
149711
+ LOG2.warn("Seqscribe", "beacon report failed the content projection; not sent");
149712
+ return;
149713
+ }
149714
+ lastScope = scopeOf(projected.vectors);
149715
+ try {
149716
+ await transport.put(projected);
149717
+ counters5.put++;
149718
+ } catch (err) {
149719
+ counters5.putFailed++;
149720
+ LOG2.info(
149721
+ "Seqscribe",
149722
+ `beacon put failed (advisory, ignored): ${err instanceof Error ? err.message : String(err)}`
149723
+ );
149724
+ throw err;
149725
+ }
149726
+ };
149727
+ const rawQuery = async (topics) => {
149728
+ try {
149729
+ const res = await transport.get(topics);
149730
+ counters5.get++;
149731
+ return res;
149732
+ } catch (err) {
149733
+ counters5.getFailed++;
149734
+ LOG2.info(
149735
+ "Seqscribe",
149736
+ `beacon get failed (advisory, ignored): ${err instanceof Error ? err.message : String(err)}`
149737
+ );
149738
+ throw err;
149739
+ }
149740
+ };
149741
+ const queryWithSplitRetry = async (topics, queriesUsed) => {
149742
+ if (queriesUsed.count >= MAX_BEACON_GET_QUERIES) {
149743
+ return { reports: [], truncated: topics.length };
149744
+ }
149745
+ queriesUsed.count++;
149746
+ const res = await rawQuery(topics);
149747
+ const truncated = typeof res?.truncated === "number" ? res.truncated : 0;
149748
+ const reports = Array.isArray(res?.reports) ? res.reports : [];
149749
+ if (truncated === 0 || topics.length <= 1) {
149750
+ return { reports, truncated };
149751
+ }
149752
+ if (queriesUsed.count + 2 > MAX_BEACON_GET_QUERIES) {
149753
+ return { reports, truncated };
149754
+ }
149755
+ const mid = Math.ceil(topics.length / 2);
149756
+ const left = topics.slice(0, mid);
149757
+ const right = topics.slice(mid);
149758
+ counters5.splitRetries++;
149759
+ const [leftRes, rightRes] = await Promise.all([
149760
+ queryWithSplitRetry(left, queriesUsed),
149761
+ queryWithSplitRetry(right, queriesUsed)
149762
+ ]);
149763
+ return {
149764
+ reports: mergeBeaconReportsByNode(leftRes.reports, rightRes.reports),
149765
+ truncated: leftRes.truncated + rightRes.truncated
149766
+ };
149767
+ };
149768
+ const doGet = async () => {
149769
+ const queriesUsed = { count: 0 };
149770
+ let truncated = 0;
149771
+ let reports = [];
149772
+ try {
149773
+ const res = await queryWithSplitRetry(lastScope, queriesUsed);
149774
+ reports = res.reports;
149775
+ truncated = res.truncated;
149776
+ } catch (err) {
149777
+ counters5.getFailed++;
149778
+ LOG2.info(
149779
+ "Seqscribe",
149780
+ `beacon get failed (advisory, ignored): ${err instanceof Error ? err.message : String(err)}`
149781
+ );
149782
+ throw err;
149783
+ }
149784
+ if (truncated > 0) {
149785
+ counters5.truncated += truncated;
149786
+ LOG2.info(
149787
+ "Seqscribe",
149788
+ `beacon get: ${truncated} peer report(s) remained truncated after split-retry (${queriesUsed.count} quer${queriesUsed.count === 1 ? "y" : "ies"})`
149789
+ );
149790
+ }
149791
+ const clean2 = reports.map((r) => projectBeaconReport(r)).filter((r) => r !== null);
149792
+ LOG2.info(
149793
+ "Seqscribe",
149794
+ `beacon get writer=${handle.writerId} peers=${clean2.length} topics=${lastScope.length}`
149795
+ );
149796
+ return clean2;
149797
+ };
149798
+ const libHandle = handle.node.beacon({
149799
+ async put(rawReport) {
149800
+ if (stopped) return;
149801
+ await doPut(rawReport);
149802
+ },
149803
+ async get() {
149804
+ if (stopped) return [];
149805
+ return await doGet();
149806
+ }
149807
+ });
149808
+ LOG2.info("Seqscribe", `beacon armed writer=${handle.writerId}`);
149809
+ const beaconHandle = {
149810
+ stop() {
149811
+ if (stopped) return;
149812
+ stopped = true;
149813
+ try {
149814
+ libHandle.stop();
149815
+ } catch {
149816
+ }
149817
+ LOG2.info(
149818
+ "Seqscribe",
149819
+ `beacon stopped writer=${handle.writerId} put=${counters5.put}/${counters5.put + counters5.putFailed} get=${counters5.get}/${counters5.get + counters5.getFailed} splitRetries=${counters5.splitRetries} truncated=${counters5.truncated} rejected=${counters5.rejected}`
149820
+ );
149821
+ },
149822
+ counters: () => ({ ...counters5 }),
149823
+ async pushNow() {
149824
+ if (stopped) return;
149825
+ try {
149826
+ await doPut({
149827
+ node: handle.writerId,
149828
+ at: (/* @__PURE__ */ new Date()).toISOString(),
149829
+ vectors: handle.node.vectors()
149830
+ });
149831
+ const board = await doGet();
149832
+ if (!stopped) handle.node.setKnownVectors(board);
149833
+ } catch {
149834
+ }
149835
+ }
149836
+ };
149837
+ handle.onClose(() => beaconHandle.stop());
149838
+ return beaconHandle;
149839
+ }
149418
149840
  init_topics2();
149419
149841
  init_authority();
149420
149842
  init_mesh_dual_write();