feat(gossip): echo-chamber attenuation with path vector - #2251
Conversation
|
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. |
|
@milla-jovovich @igorls this branch is up to date with |
fatkobra
left a comment
There was a problem hiding this comment.
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.
ab13249 to
0a28eab
Compare
|
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. |
|
Merged latest |
ca0db35 to
8f7215b
Compare
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
8f7215b to
a5d1370
Compare
|
@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. |
|
Closing — stacked on #2239 which was just closed. See comment there for rationale. |
Stacked on #2248 (feat/gossip-daemon).
Summary
Adds echo-chamber attenuation to the gossip protocol:
GossipMessagenow carries a lightweightpathvector (fixed-size hop history of chatter node ids).child()appends the forwardingnode_idto the path._should_forwardchecks prior visits. Each re-visit multiplies the forwarding probability byecho_chamber_attenuation(0.5). Afterecho_chamber_reinforcement_count(3) visits the node is suppressed entirely.echo_chamber_reinforcement_count,echo_chamber_attenuation,echo_chamber_similarity_threshold.chatter_statusreturns the echo-chamber parameters.Test plan
tests/test_gossip.pypasses (20 tests).tests/test_mcp_server.pypasses.