Skip to content

feat(gossip): echo-chamber attenuation with path vector - #2251

Closed
jjcav84 wants to merge 13 commits into
MemPalace:developfrom
jjcav84:feat/gossip-echo
Closed

feat(gossip): echo-chamber attenuation with path vector#2251
jjcav84 wants to merge 13 commits into
MemPalace:developfrom
jjcav84:feat/gossip-echo

Conversation

@jjcav84

@jjcav84 jjcav84 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Stacked on #2248 (feat/gossip-daemon).

Summary

Adds echo-chamber attenuation to the gossip protocol:

  • GossipMessage now carries a lightweight path vector (fixed-size hop history of chatter node ids).
  • child() appends the forwarding node_id to the path.
  • _should_forward checks prior visits. Each re-visit multiplies the forwarding probability by echo_chamber_attenuation (0.5). After echo_chamber_reinforcement_count (3) visits the node is suppressed entirely.
  • New config keys: echo_chamber_reinforcement_count, echo_chamber_attenuation, echo_chamber_similarity_threshold.
  • chatter_status returns the echo-chamber parameters.
  • New test verifies daemon attenuation and path preservation.

Test plan

  • tests/test_gossip.py passes (20 tests).
  • tests/test_mcp_server.py passes.
  • Full suite: 4317 passed, 31 skipped.

@jjcav84
jjcav84 marked this pull request as ready for review August 14, 2026 02:03
@jjcav84

jjcav84 commented Aug 14, 2026

Copy link
Copy Markdown
Contributor Author

Hi @milla-jovovich @igorls — this PR is rebased onto the latest "develop", the full test suite passes, and the design/context is documented in the body. Ready for review.

@jjcav84

jjcav84 commented Aug 14, 2026

Copy link
Copy Markdown
Contributor Author

@milla-jovovich @igorls this branch is up to date with develop and the full test suite passes. It is ready for final review and merge. @fatkobra if you have bandwidth, a look would be appreciated too.

@fatkobra fatkobra left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found two child-specific blockers in addition to this branch's dependency
on #2248.

1. echo_chamber_similarity_threshold is currently a dead setting

The configuration adds echo_chamber_similarity_threshold, and the PR
describes similarity-based echo-chamber control.

The forwarding decision currently uses path node IDs, reinforcement count,
attenuation, and randomness, but it never reads or applies the similarity
threshold. chatter_status also omits the setting.

Please either:

  • implement the documented similarity semantics and expose the active value
    in status; or
  • remove the setting and the similarity claim until that behaviour exists.

If implemented, regression coverage should demonstrate messages immediately
below and above the threshold, with deterministic forwarding outcomes.

2. The attenuation test passes even when attenuation has no effect

The current test accepts children_queued >= 0, which is true for every
possible result.

It then inspects child paths only when children happened to be produced.
Producing zero children therefore makes the entire test pass without proving
attenuation, reinforcement suppression, or path handling.

Please make the forwarding tests deterministic by controlling
random.random() and directly exercise the boundary cases:

  • no previous visits;
  • one previous visit at the attenuation boundary;
  • enough reinforcement to suppress forwarding;
  • forwarding permitted below the threshold;
  • forwarding rejected above the threshold.

Path preservation should be asserted separately from the forwarding
decision.

This branch is stacked on #2248. Final approval should wait until the queue
cap and exception-loss fixes from that parent have been rebased here.

@jjcav84

jjcav84 commented Aug 15, 2026

Copy link
Copy Markdown
Contributor Author

Hi @fatkobra — this branch is stacked on its parent gossip PR. I will rebase it once the parent lands and then re-request review. No action needed until then.

@jjcav84

jjcav84 commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author

Merged latest upstream/develop to resolve the UNSTABLE merge state. Branch is now up to date — ready for re-review/approval.

jjcav84 and others added 13 commits August 22, 2026 06:28
Implements mempalace/gossip.py with ChatterNode, GossipMessage,
GossipProtocol, default chatter-node config, topic/priority detection,
propagation through palace graph tunnels, and TTL-bounded derived KG triples.
Adds tests/test_gossip.py with 16 unit tests.

Full suite: 4261 passed, 31 skipped.
- Make DEFAULT_GOSSIP_CONFIG neutral/empty; add EXAMPLE_GOSSIP_CONFIG for tests.
- Add config parameter to GossipProtocol and gossip() for explicit setup.
- Report attempted/successful/failed targets and only mark a node propagated when at least one write succeeds.
- Add mempalace_gossip to service.WRITE_TOOLS and invariant test.

Refs MemPalace#2239
Add a rooms field to ChatterNode and match hallway co-occurrence rooms against
node rooms rather than hall names. Regression test uses a room (audit_report)
that differs from the node hall (security) to prove the namespaces are no
longer conflated.

Refs MemPalace#2247
…mPalace#2221)

The MemPalace#2221 fix reached develop through MemPalace#2228 at an earlier revision of the
branch, so three guards and their tests did not come with it. One of the
three is a regression the gate that did land introduced.

sweep_directory: the new gate probes the file type with f.stat() inside a
try, and its except OSError printed SKIP and continued. A dangling symlink,
a symlink loop and a file unlinked between rglob and the gate all raise
there. Before the gate existed each of them reached sweep(), raised, and was
appended to failures — so the gate turned "could not read this transcript"
into a silent skip and a successful exit. A probe that FAILS is an error,
not a benign file type: log it, print WARNING, book it in failures. A probe
that succeeds and reports a non-regular file still skips silently.

_parse_gradle: the is_file() gate sat in front of the try whose except
OSError the parser already had, so a manifest under a directory with r but
no x raised PermissionError out of a call that used to answer "no manifest
name". The gate moves inside that try. _collect_manifest_names stats with
os.path.isfile, which reports instead of raising, matching the parsers it
guards.

split_file: the type gate in main() covers the files the glob listed, but
split_file builds its output names itself, so a pre-existing FIFO at one of
them wedged write_text in the kernel waiting for a reader. Output names that
are anything but a regular file are skipped.

That gate asks os.path.lexists, not os.path.exists. exists() follows the
link, so a DANGLING symlink at an output name reads as "nothing there" and
the write goes through it, creating the target — a chunk landing wherever
the link points rather than in the output directory. Measured: the two calls
differ on that one case and agree on every other (regular file, symlink to a
file, missing name, FIFO, symlink to FIFO, directory).

test_gather_origin_samples_survives_an_unreadable_directory broke under root
rather than passing vacuously: CAP_DAC_OVERRIDE walks into the 0o444
directory, the walled-off file stays readable, and the count assertion sees
two samples instead of one. It now carries the same needs_unprivileged_posix
gate as the three new permission tests.

miner._read_text_no_follow: comment fix only. F_SETLEASE on a FIFO fails
EINVAL, not ENXIO — measured on Linux 6.18 / glibc 2.39. The code branches
on EAGAIN and is unaffected.
Per-message try/except so one failing message does not discard unprocessed
siblings or prior children. Requeue children while holding the lock and
reserve capacity against concurrent callers.

Refs MemPalace#2248
- Encode the original predicate in the gossip source_file so viral_facts can
  group by the source fact identity instead of the destination predicate.
- Use one reference timestamp for all as_of metrics (active and expired).
- Format the default reference as canonical UTC to satisfy KG validation.

Refs MemPalace#2249
@jjcav84

jjcav84 commented Aug 22, 2026

Copy link
Copy Markdown
Contributor Author

@fatkobra thanks for the detailed review — the blockers are noted. As you pointed out, these are stacked on #2239 and should wait for the parent to be resolved first.

Opened #2335 to make the design case for derived routing vs KG mutation per your review on #2239. Once there's sign-off on the derived-view approach (no KG writes, sidecar for routing state), I'll rewrite the stack with the fixes for your specific blockers on this PR.

@jjcav84

jjcav84 commented Aug 23, 2026

Copy link
Copy Markdown
Contributor Author

Closing — stacked on #2239 which was just closed. See comment there for rationale.

@jjcav84 jjcav84 closed this Aug 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants