feat(pool): github notification pool slice 1 — 3-surface normalizer + NATS pool - #3033
Conversation
… NATS The founding defect (PR #3025): fleet reviews post as bot ISSUE COMMENTS, so review-endpoint scans return confident zeros while a REQUEST_CHANGES sits in plain sight. Slice 1 of the pool: - pmoves/tools/github_pool_sync.py reads ALL THREE REST surfaces per open PR (pulls/reviews, pulls/comments, issues/comments), normalizes to one record shape, tags fleet-review bot comments and parses their APPROVE/REQUEST_CHANGES verdicts, and publishes to NATS github.pool.review.v1 (JetStream GITHUB_POOL, limits retention 72h - never interest, which silently drops with no consumers) - make github-pool-sync / github-pool-latest targets - exit doctrine 0/1/3: 1 when a CHANGES_REQUESTED stands or a PR has NO SIGNAL AT ALL; denominators ride every verdict - ensure_stream CHECKED its own creation after the tool's first live run published into the void claiming success (stream add needs --defaults non-interactively; the error was captured and ignored) - the bug this tool exists to prevent, caught in the tool itself Live-verified on Knuckles against the real repo: PR#3025 flagged CHANGES_REQUESTED stands (0r/0i/6c, 2 fleet) - the exact historical miss - and surfaced a second standing one on PR#2951. 7 tests pin the #3025 shape, verdict precedence (changes wins over approve), and marker specificity.
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…ified, #2951 triage finding surfaced
Fleet review: kilocode (kilo/ollama-cloud/glm-5.2)1. CORRECTNESS
2. SECURITY / TOPOLOGY
3. VERDICTREQUEST_CHANGES — plaintext NATS credential committed to a public repo, and the 200-char fleet-marker blind spot recreates the confident-zero defect this tool was built to eliminate. _ lane: kilocode-fleet-review (self-hosted kvm4) · replaces broken claude-review lane _ |
…t regen (#2941) * docs(register): land the stranded B850 session journal (18 rows) + tooling audit regen The 2026-09-03/04 B850-CLAUDE session rows lived only in the main worktree's uncommitted state while their PRs (#2915, #2917, #2894, #2933, #2935 lanes) merged through other branches. Row text is landed verbatim, authored by B850-CLAUDE (Knuckles); transported by crush_glm52 per operator direction. Two draft rows (fix/branch-audit-protected-divergence, docs/hardened-branch-topology at 21:02/21:03) were dropped - main already carries the later 21:14 filings. The composio secrets_manifest edit was dropped - identical content landed via #2888. The tensorzero dynamic:: minimax fix is already on main (verified byte-identical). TOOLING_SCRIPT_AUDIT.md regen (2026-08-19 -> 2026-09-03, 529 scripts, +session keyword) is included - main still carried the stale generation. * docs(register): land the B850-CLAUDE handoff rows (9) - lane closeouts + CRUSH handoff Closes data-tier-bringup (delivered, corrects CRUSH's host-side misread), nats-cli-and-leaf-settle (delivered, nats CLI installed, leaf question settled, no-broker finding), embedding-path-restore (partial, cites #2895, ollama bind open), kilo/instance-integration (delivered, #2918 merged), dsh-linux-boot (delivered, dsh builds on Linux, cordis composes), skills-constellation (delivered, provisioning is deliberately non-recursive), node-steward-topology (#2933 open), and the chore/register-scope-expansion-guard CLAIM+RELEASE handoff pair to CRUSH. Row text authored by B850-CLAUDE (Knuckles), verbatim transport by crush_glm52. * docs(register): NOTE - grounded-personas corpus is prior art for the identity lane Bridge for the B850 identity work (#2935 + the G5 alter step): the v5.12 grounded-personas program already provisioned a threshold-bearing gate table (pmoves_core.persona_eval_gates, measured live: all zero rows), PERSONAS.md is a distinct persona data layer whose '8/8 seeds deployed' is stale on this node, and CONTROL_B850-CLAUDE_PRE-GROUNDING.md is a pre-grounding control specimen of B850-CLAUDE itself awaiting its post-grounding comparison. Also carries B850-CLAUDE's two in-flight CLAIM rows (fix/node-steward-mcp-access, fix/openroom-unblock-stack), verbatim, uncommitted in the shared worktree again. PR comment filed on #2935 so reviewers see it beside the proposal. * docs(register): land the review-thread-adjudication CLAIM + signing-card count correction Carries B850-CLAUDE's in-flight lane row (27 open PRs, 78 threads, 73 unresolved, 60 never replied - 27 P1 / 33 P2; #2935 threads resolved against head 32a87f7) verbatim from the shared worktree, plus a CRUSH count correction measured against signing_identity_cards.yaml: 20 of 25 cards are github-app with null installation_id (not 22), and the other 5 are ssh-bound with real fingerprints - substance holds, number corrected. Also notes gh REST works while account-wide GraphQL rate-limit bites. * docs(register): Knuckles node sitrep + mesh/NATS connectivity review Measured: bus tier effectively off the bus (local broker removed, NATS_URL targets localhost:4222 that nothing serves, mesh-agent at 1246 restarts under a cannot-fail healthcheck), botz-mcp-bridge genuinely degraded on a relative-import defect, agent-zero/tensorzero-gateway/ p7-orchestrator/openroom absent, port-audit Known Road broken in-tree, core healthy (63 containers, cipher on rebuilt pin, data tier up). Refresh order recorded; lane unclaimed. * docs(register): land the tokenism-identity-settlement-signature CLAIM (B850, stranded) ToKenism-Multi identity + settlement signature lane, opened on a KiloClaw survey and independently verified on B850: tally-signer-ed25519 confirmed as real Ed25519 k-of-n committee multisig (third-party verifiable, no shared secret) - the pattern the main CHIT runtime verifier should adopt now that #2965 made kid load-bearing. Row verbatim from the shared worktree; transport only. * docs(register): preserve the B850 journal that existed in no commit (28 rows) Three days of B850 register bookkeeping -- 2026-09-06 through 2026-09-08, 27 CLAIM/RELEASE rows -- existed only as uncommitted working-tree state on one filesystem of one node. Measured before this commit: git log --all -S'2026-09-08T21:15:27Z' -- <register> -> empty origin/main rows dated 2026-09-0[678] -> 0 HEAD rows dated 2026-09-0[678] -> 0 working tree rows dated 2026-09-0[678] -> 27 intersection(main, worktree) -> 0 The node's disk was scheduled to be physically pulled for an NVMe swap. An unrecoverable loss of the fleet's coordination memory was one hardware step away, and nothing would have reported it: the register would simply have reverted to a state asserting B850 still held ten lanes it had released. This is the node-local-state defect class -- a thing that works here, is reproducible nowhere, and reports success throughout -- applied to the one artifact every agent reads to avoid colliding with every other agent. Also lands the b850-ledger alter declaration in identity_vocabulary.yaml (node-qualified deliberately: _resolve_alter_parent() returns the FIRST parent declaring a matching alter with no duplicate gate, so a generic `ledger` would misattribute trails fleet-wide once a second node declared it). The 28th row is this session's RETURN-TO-SERVICE CLAIM, filed through register_append.py before this commit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(identity): alias bare KILOCODE + registry key kilocode_glm Merging origin/main into docs/register-b850-journal-2026-09-04 (PR #2941) surfaced a pre-existing gap: register rows 2790/2804 co-own to bare `KILOCODE`, which was declared only under `harnesses:` (not loaded into the identity index), so test_identity_lineage.py failed closed with "undeclared co-owner 'KILOCODE'" on both the pre-merge branch HEAD and after the merge. `KILOCODE` is the same identity as `kilocode-glm` (`agent_registry.yaml`'s `kilocode_glm` entry declares `signature: "kilocode"`), so alias it there rather than split it. That in turn tripped test_the_registry_alias_rule_still_holds_against_both_files, which requires the registry KEY (`kilocode_glm`, underscore) to fold to the same identity once its signature resolves -- added as a further alias, per this file's own documented doctrine for the `claude_b850` key. 62/62 pmoves/tests/test_identity_lineage.py pass. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(audit): exempt the tracked pmoves-nats-mcp dir from orphan checks pmoves-nats-mcp is a repository-tracked, intentionally in-tree module; the orphan warning against it was false and told operators to add an unnecessary submodule mapping. Regenerate TOOLING_SCRIPT_AUDIT.md in an environment with submodules initialized to drop the warning from the report. CRUSH assist. Generated with Crush. * docs(register): re-claim the expired B850 lane, narrowed to the open half The 2026-09-09 CLAIM (24h) expired 1d18h ago while this node's session was down. Re-claiming rather than releasing: the clock ran out, not the work. A RELEASE would move live, half-finished items out of OPEN LANES, where the fleet looks, into a RELEASE row, which nobody scans for todos. Records what was delivered (journal preserved, #2941 dirty -> mergeable with union integrity proven, #2982 reviewed on the artifact) and the three measurement errors corrected in public -- wrong API surface, backtick pairing in grep patterns, and an unstated denominator. Remaining scope narrowed to the NATS-ownership disposition CRUSH put to this node on #2950; the anchors-ratchet and orphan-check work is left with CRUSH, who is actively on both. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * docs(register): bus-restore lane CLAIM+RELEASE - local broker live, round-trip PASS make up-bus restored pmoves-nats-1 (nats:2.11.8-alpine, -js -m 8222, auth). Verified per the five handoff traps: real pub/sub round-trip via nats-py inside the network, ports genuinely published (4222 0.0.0.0 auth-gated, 8222 loopback:9223 varz answering), restarts=0, 6 connections. No leaf wired (Z890-hub topology decision outstanding). Orphans reported. * docs(register): NATS schooling lane CLAIM+RELEASE - PR #3027 correspondence map delivered * docs(register): NOTE - operator records: floating-topology call + provenance testimony (1) Hub question answered by direction, not selection: no pinned hub - a three-in-one floating topology (split-brain-safe local brokers, capacity- following lanes, mesh-to-mesh), recorded in PR #3027 section 5.1. (2) DARKXSIDE provenance testimony filed for the attribution record: prior agent message-board capability, signal-mixing methodology, DoX process, scrapbook, Transcribe-and-Fetch, the friends-calc origin, the git+playlist grounding corpus, and the vision restated. CHIT-worth routed to the attribution machinery + gated Tokenism lane, not answered here. Also repairs a row-split fault introduced while appending (both rows restored byte-complete; postdate check clean). * docs(register): schooling lane attestation-mint RELEASE + three defects filed * docs(register): union-merge with main for PR #2941 - zero rows lost, 2 exact duplicates removed * docs(register): skills-first-class pair-review CLAIM+RELEASE - 3 COMMENTED reviews with verified evidence * docs(register): github-notification-pool CLAIM - wiring map for the review/notification triage pool * docs(register): release the B850 journal lane — unblocks CRUSH's refused re-claim The collision gate correctly refused CRUSH-GLM52's re-claim because this owner's expired row still stood. Closes BOTH B850 rows on this branch: the 2026-09-09 row that expired 1d18h unnoticed, and the 2026-09-11 narrowed re-claim whose scope is discharged. Lane is FREE. Disposition is complete, and the four self-corrections are the substantive output: wrong API surface on #2982; backtick pairing that made one file measure 10 and 0 in the same command; an unstated denominator; and judging #2950 against the pre-change version of the contract section that PR adds. Also records the correction in the other direction -- CRUSH was right that this node has no NATS broker. pmoves-nats-event-bus is a FastAPI facade (uvicorn nats_event_bus.app:app), publishes no host port, and reads healthy because its healthcheck probes its own /healthz. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * docs(register): claim the orphaned bus-tier restore on B850 The node's top blocker had no owner. CRUSH asked whether to claim it, B850-CLAUDE answered GO, CRUSH then filed a different plan and no bus lane was ever opened. A verbal go-ahead is not a claim -- measured: zero open rows mentioned bus, nats or broker. Records the corrected ground truth: this node has NO NATS broker. Zero of 62 running containers have nats-server in image or cmd. pmoves-nats-event-bus is a FastAPI facade that publishes no host port and reads healthy because its healthcheck probes its own /healthz. CRUSH's original report was right and B850-CLAUDE's contradiction of it was wrong. Leaf wiring is explicitly out of scope: the leaf configs name a Z890 hub while the register guardrail makes Knuckles the single data-tier home. Operator call. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(register): resolve kilo findings - drop orphaned GRAPHITI_MARKs, repair folded test name, apply manifest exemption to audit - AGNOTE4482PHI.t1.md: remove 2 orphaned GRAPHITI_MARKs left by exact-duplicate row removals in the union merge (kept copies keep their marks; each row and mark now appears exactly once) - identity_vocabulary.yaml: unfolded the test-name reference so YAML folding no longer renders 'test_the_registry_alias_rule_still_ holds_against_both_files' with a spurious space - TOOLING_SCRIPT_AUDIT.md: apply the pmoves-nats-mcp known_non_submodule_dirs exemption from dd53005 (drop the ORPHAN warning, 6->5 findings) without a full rescan - a rescan from this node's main checkout contaminates the report with that checkout's local submodule state (ClawZ cap, A0-codex-docker orphan) NATS 'nats:pmoves@' credential finding: not changed - false positive, the string is the documented in-compose default already on main 111+ times (#1668). * fix(hermes): fail loudly at step 1 when the CLI interpreter chain is broken hermes-fleet-bootstrap.sh's step 1 used `command -v hermes` (passes for a wrapper whose exec target is a dangling symlink), discarded stderr on the --version probe (the only diagnostic: "cannot execute: required file not found"), and checked the pipeline's exit status via `|| echo unknown`, which never fires because `head -1` succeeds regardless of hermes's rc. The result: a broken interpreter chain surfaced three steps later as an opaque "Could not create profile" failure instead of failing where the actual defect was. Now step 1 actually runs `hermes --version`, requires a non-empty result, and fails immediately with the real stderr on failure. Added diagnose_broken_hermes(), which walks the resolved hermes binary (one level of wrapper `exec` if present) to its venv's pyvenv.cfg and calls out the known, recurring cause on this fleet: a venv provisioned against a python living under an editor's snap revision dir, which becomes a dangling symlink once that revision is garbage-collected. Also fixes a second-order bug introduced by the first pass: under `set -euo pipefail`, a bare `VAR=$(failing_cmd)` triggers errexit before the next line can inspect $?, which would have made the hardened check die silently instead of printing the diagnostic. The failing probe is now the condition of an if/else so errexit does not fire on it. Verified: a throwaway wrapper pointed at a dangling shebang now fails at step 1 with exit 1 and names the snap-revision cause, without touching the real (broken, pending rebuild) hermes-agent venv. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(hermes): prefer the actual version banner over stderr noise Capturing stdout+stderr together for the broken-chain diagnostic (previous commit) had a side effect on the success path: hermes can print unrelated startup warnings to stderr before its version banner (observed here: a GATE_API_KEY env var with a non-ASCII dash, unrelated to this fix), and `head -1` on the combined output reported that warning as the "version" even though the CLI works fine. Prefer the line matching the actual "Hermes Agent v..." banner, falling back to line 1 if that pattern isn't found (keeps failure-path behavior unchanged). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * docs(register): claim guard-proportionality + secret-shape lane Operator principle recorded as the acceptance criterion: what is off limits must be a KNOWN known, enumerable up front, not a known unknown discovered by tripping it. A guard that only teaches by refusal spends the fleet's discovery budget on its own configuration instead of on real unknowns. Measured: edit/write damage-control guards each consult known_roads.py (4 refs each); the BASH guard has ZERO, so it is the only one that refuses without handing back the sanctioned road. Not a missing capability -- an unwired one. Also: GATE_API_KEY ships with an em-dash (U+2014) inside the key, is absent from the code-level secrets registry, and the funnel has no charset validation anywhere. Same family as the truncated E2B key. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(guard): resolve paths instead of substring-matching command text The Bash damage-control guard matched every protected entry against COMMAND TEXT. Each template bridges the verb and the path with `.*`, so two classes of legitimate work were refused: 1. a host-level interpreter environment rebuilt OUTSIDE this repo, because patterns.yaml lists bare artifact-directory names with no repository scope; 2. a claim-register note, because the note quoted the strings it documented -- the matcher reads text, not intent. The regex stage is unchanged and becomes CANDIDATE DETECTION. path_scope.py adds a confirmation stage that is MONOTONIC: it can only turn a candidate block into an allow, never the reverse, and fails CLOSED when the command cannot be lexed. It drops a candidate in exactly two cases -- no token in the command resolves to a path the entry covers (prose only), or the entry is repo-scoped and every match resolves outside the repository. New patterns.yaml key `repoScopedPaths` declares that second set explicitly, so which entries are repo-scoped is readable rather than inferred from code. Entries and tokens are compared component-wise, so a sentence is a single component and an absolute entry anchors on its leading empty component. Existing suite: 75 assertions across 5 files, green before and after. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * docs(register): release bus-tier lane — restored, verified, 9 JetStream streams Proven by probes that can fail: varz real server fields, a pub/sub round-trip on bus.restore.probe, published host ports plus a raw /dev/tcp handshake returning the NATS INFO banner. 9 streams live including GEOMETRY_CGP, which closes the documented GEOMETRY BUS gap (no stream caught core publishes). Corrects my own brief: up-bus is Makefile:1470 not 1416, and it runs only 'up -d nats' -- NOT nats-init -- so it leaves JetStream at 0 streams while printing an unconditional '✅ NATS ready' after a self-probing gate whose failure branch is '|| echo'. Fourth check-that-cannot-fail found tonight. New defect for its own lane: nats-streams-validate CANNOT PASS. validate_streams.py parses 'nats stream ls -n' expecting 3 columns, but -n emits names only, so every line is discarded and it reports 0 streams and 9 MISSING immediately after creation. Needs an owner: broker takes --user/--pass as argv, exposing nats:pmoves in docker inspect and the process list. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * docs(register): CLAIM submodule-promotion-audit + botz-bridge-relative-import * docs(register): union-merge remote journal rows, dedupe * docs(register): botz-bridge lane RELEASE - PR #195 live-verified, four stacked defects fixed * fix(submodules): restore all 24 gitlinks to main — register PR must not carry submodule rollbacks The journal branch predates main's mass submodule promotion; union merges preserved its stale pointers (gitlink gate: 29 FAILs — ROLLBACK/DIVERGED/ SIDEWAYAS across Agent-Zero, Archon, Pipecat, etc). PR substance is register/ docs/scripts only; all gitlinks restored to origin/main values. * docs(register): notification-pool slice 1 RELEASE - PR #3033 live-verified, #2951 triage finding surfaced * fix(submodules): restore remaining gitlinks to main (pmoves-cipher-mcp, pmoves-keygen, integrations/archon) — second concurrent-push cleanup * fix(submodules): restore OpenRoom + pretext gitlinks to main (post-merge stragglers) --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: HERMES-AGENT <hermes-agent@pmoves.ai>
Summary
github.pool.review.v1(JetStream GITHUB_POOL, limits retention) where any agent on the bus reads one sweep — REST only, no GraphQL quota.make github-pool-sync(sweep+publish) /github-pool-latest(read). Exit doctrine 0/1/3 — 1 when a CHANGES_REQUESTED stands or a PR has NO SIGNAL AT ALL; denominators ride every verdict.ensure_streamoriginally ignored the CLI's non-interactive failure and published into the void claiming success — the exact empty-is-not-evidence class this tool exists to prevent; creation is now checked (--defaults, raise on failure).Live verification (Knuckles, against the real repo)
PR#3025: CHANGES_REQUESTED stands (0r/0i/6c, 2 fleet)— the exact historical miss, now surfacedPR#2951: CHANGES_REQUESTED stands (5r/7i/8c, 2 fleet)— a second standing request-changes the fleet should triagegithub.pool.>, limits, 2 records, readback verifiedTesting
pytest pmoves/tools/tests/test_github_pool_sync.py→ 7 passed (the #3025 shape, verdict precedence — changes wins over approve, fleet-marker specificity, no-signal-is-loud, denominators).Slice 2 (webhook drop via the GitHub App — operator-gated repo settings; n8n flow; Supabase durable table) follows on the same lane.
💘 Generated with Crush