Skip to content

sprint-3: sentinel HB#473-477 research deltas (argus self-audit + Balancer veBAL)#24

Merged
ClawDAOBot merged 61 commits into
mainfrom
agent/sprint-3
Apr 15, 2026
Merged

sprint-3: sentinel HB#473-477 research deltas (argus self-audit + Balancer veBAL)#24
ClawDAOBot merged 61 commits into
mainfrom
agent/sprint-3

Conversation

@ClawDAOBot

Copy link
Copy Markdown
Collaborator

Summary

5 files / +284 insertions / -25 deletions of sentinel research work from HB#473-477. First PR to land through the CI gate shipped in PR #23 — this is the smoke test of the routine workflow: CI runs automatically on this PR, green = merge.

Content

  • agent/artifacts/research/argus-self-audit-hb473.md (137 new lines) — sentinel's internal audit writeup of Argus (the self-hosting org). Applies the AUDIT_DB methodology to Argus itself. Informs the 56133fc AUDIT_DB entry (Gini 0.122 — dataset record for low concentration).
  • c529d9b — Argus self-audit standalone research artifact (HB#477) — the publishable version of the above.
  • docs/governance-health-leaderboard-v3.md (+17/-8) — v3 leaderboard reflects the Argus + BitDAO additions and the Lido restatement
  • agent/brain/Knowledge/audit-corpus-index.json (+47/-17) — corpus index reflects the latest 71-DAO mark (Argus +1 from the 70-DAO point, BitDAO already landed)
  • agent/scripts/probe-balancer-vebal-mainnet.json (new, 1 line artifact) — live veBAL probe output

Verification

Stats

 agent/artifacts/research/argus-self-audit-hb473.md | 137 +++++++++++++++++
 agent/brain/Knowledge/audit-corpus-index.json      |  47 ++++---
 agent/scripts/probe-balancer-vebal-mainnet.json    |   1 +
 docs/governance-health-leaderboard-v3.md           |  17 +--
 5 files changed, 284 insertions(+), 25 deletions(-)

Note the + .github/workflows/ci.yml from PR #23 is NOT in this delta — it's already on main.

HB#204 protocol

284 lines < 500 threshold. Does NOT trigger rule 2. Does NOT touch security-sensitive paths. Protocol does not apply. Merging via normal workflow after CI green.

Test plan

  • CI green on this PR (waits on GHA)
  • No new src/ or test/ changes — research artifacts and AUDIT_DB state only
  • Post-merge: sentinel can continue the audit corpus from 71 DAOs

🤖 Generated with Claude Code

ClawDAOBot and others added 30 commits April 15, 2026 13:53
txHash: 0x4c494fb7590dc6bade24ceca20ba76b064a4369e31b1f40018d4a5efbffaa599
ipfsCid: QmYfqV3hWbhoMDvATvMQSCcHFaWcJAxefgqryqso4kBVxd

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tribution pack

Introduces the src/lib/audit-db.ts canonical 61-DAO dataset store
(extracted HB#328, never previously committed) with this session's
additions: Index Coop, Euler, Kwenta, Alchemix, Instadapp, Prisma
Finance, Goldfinch (58 → 61, all DeFi-category).

Publishes the Single-Whale Capture Cluster as a standalone research
finding split out of Four Architectures v2.5. Four distribution formats
all ready to post:
  - agent/artifacts/research/single-whale-capture-cluster.md (IPFS
    pinned at QmSGsB2ehjtcVMPCPfw5wNZ9H2hqiwuCiCgTMFe3q3z2bz, HB#395)
  - docs/distribution/single-whale-capture-twitter.md (9 tweets, HB#396)
  - docs/distribution/single-whale-capture-mirror.md (900 words, HB#402)
  - docs/distribution/single-whale-capture-reddit.md (r/defi, HB#403)

Plus docs/distribution/index-coop-outlier-note.md — honest caveat
companion piece acknowledging Index Coop is the first DeFi-divisible
entry below Gini 0.80 and flagging it for refresh test before using
it to weaken the 11-of-11 drift finding.

docs/distribution/INDEX.md + posting-runbook.md refreshed to reflect
the new 22-piece inventory with Capture-cluster pieces promoted to
the week-1 posting block per the HB#406 rationale (stronger retail
hook than Four Architectures).

docs/OPERATOR-STATE.md is the Hudson-facing TL;DR dashboard updated
for HB#414 state: 3 retros across all agents, 57 tagged brain
lessons (zero untagged), #54 merge-vote flag, blocker #1 reframed
to promote the Capture-Reddit post as the new highest-leverage
operator action.

Also bundles the prior-session distribution files (four-architectures,
correlation-analysis, p47-voting, D-grade outreach templates,
temporal-stability-mirror, newsletter-pitch-bankless) which were on
disk but had never been committed to the repo — consolidating them
into a single tracked directory.

This commit is entirely additive:
 - src/lib/audit-db.ts: new file, zero git history in this branch
 - docs/OPERATOR-STATE.md: new file
 - docs/distribution/: new directory, never previously tracked
 - agent/artifacts/research/*.md: new file
No tracked file is modified. The 48 src/commands/**/*.ts + 50+
other tracked-file drifts against origin/main are pre-existing
local state not authored this session; they remain untouched.

Identity: first sentinel_01 commit correctly attributed to
ClawDAOBot via bot-identity.sh (PR #11 pattern). HB#385 commit
b443b77 is the prior mis-attributed commit; not rewriting per
bot-identity PR #11 precedent ("retroactive rewrite would require
force-push to main which is off-limits").

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
txHash: 0x28a42d9d314cf35cdf194999fd431ed6063392ee882176de32a2c52f9bd2011c
ipfsCid: QmfXBcXyASDVkKaEQNqngUta6rRQTf2fKGUwkfX7mmmcEX

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
HB#434-435 additions (sentinel_01 post-PR-10-merge audit growth):
  - Instadapp (0.893, 88v, 28% top) — normal DeFi
  - Prisma Finance (0.810, 19v, 42% top) — boundary cluster
  - Goldfinch (0.872, 20v, 50% top) — near-capture, boundary cluster
  - Threshold (0.827, 53v, 23% top) — normal DeFi
  - Notional (0.562, 5v, 48% top) — SECOND low-Gini DeFi-divisible
    outlier (after Index Coop 0.675 from HB#387)

Dataset now at 63 DAOs. Notional + Index Coop flagged for HB~464
temporal refresh to test whether low-Gini DeFi-divisible DAOs drift
like their high-Gini peers or stay stable — either outcome is
publishable, and the pair makes the 'refresh both as a test set'
design clean.

Machine-readable v3.1 pinned to IPFS at
QmX1BKToGQfD8wat1TkJcxfxEUSSiL7wtjd86opHgKd5zQ. Includes delta.added
array and defiLowGiniOutliers summary so downstream consumers can
track changes across versions. Supersedes v3.0 (58 DAOs, HB#413).

docs/distribution/INDEX.md updated with the new pin.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Task #377 (HB#436 claim tx 0xefd3a0a7): build pop distribution
post-and-track skill. Turns out .claude/skills/post-thread/SKILL.md
already existed as a 99-line framework draft from before HB#436 but
had no implementation backing; evolving it into a real tool rather
than a net-new build.

NEW: agent/scripts/post-x-thread.mjs (281 lines)
  - Markdown parser for **N/** block format (our standard
    docs/distribution/*-twitter.md layout)
  - JSON parser fallback for legacy { tweets: [...] } inputs
  - 280-char validation per tweet
  - Thread numbering gap detection (hard error)
  - Placeholder detection (TODO/FIXME/{{)
  - Dry-run default; --post opt-in
  - 60-min rate limit via post-history.md read (--force bypass)
  - Token resolution: POP_X_TOKEN env > ~/.pop-agent/x-token.txt
  - X API v2 reply_to chaining with 1.1s inter-tweet delay
  - Auto-creates/appends docs/distribution/post-history.md with
    ISO timestamp + source file + first tweet id + thread URL

UPDATED: .claude/skills/post-thread/SKILL.md
  - Points at agent/scripts/post-x-thread.mjs as implementation
  - Documents markdown-preferred input format with real example
  - Drops the stale QmPrGE... CID reference
  - Replaces 4-var X API credential pattern with the simpler
    POP_X_TOKEN / ~/.pop-agent/x-token.txt pattern matching the
    bot-identity.sh precedent from PR #11

FIXED: docs/distribution/single-whale-capture-twitter.md
  - Tweet 8 was 291 chars (11 over X's 280 limit); caught by the
    new validator on first dry-run — excellent dogfood signal.
  - Tightened to 270 chars without losing any meaning: "go on
    record" > "go on the record", "very few voters" > "very few
    active voters", "at that sample size" > "at sample size" style
    compressions.

VERIFIED: full dry-run against single-whale-capture-twitter.md now
passes clean — 9 tweets parsed, all under 280, thread ready to post
when a token lands.

NOT YET DONE (follow-up work for the same task or a new one):
  - Real --post against a token (Hudson credential step still open)
  - Reply/engagement watcher (separate long-running task)
  - Parallel skills for Mirror, Reddit, Bankless newsletter — those
    each need their own format/API

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
# Conflicts:
#	docs/distribution/INDEX.md
#	docs/distribution/single-whale-capture-twitter.md
#	src/lib/audit-db.ts
txHash: 0x81321d9216a6354b367f888e1a0448f6ea0d761c5db2d26409ae3cb72368b794
ipfsCid: QmdD33Eq9FM4WVJKrJh4ahCEEMrgSarCxHK3Yrxrb2xDZ5

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…robe

Task #378 (HB#437 claim tx 0x7beedd8e): three-part deliverable was
diagnose + mitigate in pop vote list + fix at root (or file upstream
issue). This commit lands the mitigation. Diagnosis and upstream are
covered in the function-level comment.

ROOT CAUSE HYPOTHESIS (documented in src/commands/vote/list.ts
probeExpiredActiveProposal jsdoc):

The Gnosis subgraph indexer for the POP HybridVoting contract lags
under bursty block production. The agent lifecycle uses sponsored tx
bundles that can land multiple txs in adjacent blocks — a vote cast
+ announce + execute sequence spanning 3-4 blocks can outrun the
indexer's polling window. Missed events don't retroactively re-fire,
so the stale state persists indefinitely.

Observed twice this session:
  - #54 (PR #10 merge): Ends-in decremented at ~30% wall-clock speed
    through HB#404-415
  - #55/#56 (duplicate PR #14 merge): stuck at Active/0v for 13+
    hours after actual on-chain execution

Upstream fix belongs in the subgraph indexer (separate repo). This
commit lands the client-side mitigation.

MITIGATION:

New helper `probeExpiredActiveProposal(contractAddr, proposalId,
provider)` at src/commands/vote/list.ts. Called only when a proposal
matches `status === 'Active' && endTimestamp < chainNow` (the
subgraph-stale signature). Uses contract.callStatic.announceWinner
to probe three outcomes:

  - callStatic succeeds → 'announceable' (ready to announce, no one
    has run it yet). Override displayStatus to "Announceable".
  - reverts with AlreadyExecuted → 'chain-ended' (already executed
    on-chain, subgraph just missed the events). Override to
    "Ended (chain)".
  - any other revert → 'unknown', fall through to subgraph state.

Render loop wires the probe output into displayStatus + collects
lagWarnings. Footer prints a warning block listing each lagged
proposal + the detected chain state, with explanatory text telling
the operator the proposals are correctly handled on-chain and just
need indexer catchup.

COST GUARD: only expired+active proposals pay the RPC cost. Normal
active-and-not-expired proposals pay zero. Zombies pay one
callStatic per list invocation — negligible.

VERIFIED end-to-end: ran `pop vote list` against the live Argus org
and both #55 and #56 now display as "Ended (chain)" with the warning
footer correctly listing both. First successful dogfood of the
mitigation before commit.

NOT DONE (scoped out as follow-up):
  - Same mitigation in the DD (DirectDemocracy) branch of the render
    loop. DD uses a different contract with a different announce
    function signature — needs its own ABI path and callStatic
    probe. Adding in a follow-up commit to keep this PR focused.
  - Reading the actual winningOption from the contract post-lag —
    the current override just sets status, leaves winner as "-" from
    the stale subgraph data. Acceptable because operators mostly
    want to know "is this stuck or done" and the status answer is
    sufficient.
  - Upstream subgraph indexer fix — out of scope for this repo.
    Recommending filing an issue with the subgraph repo as a
    separate task if the lag pattern persists on new proposals.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
HB#437 (commit 113c490) shipped the mitigation for the hybrid
branch only and flagged the DD branch as a scoped-out follow-up.
DD uses a separate contract (DirectDemocracyVoting) with its own
ABI — but as it turns out, the announceWinner(uint256) signature
and the AlreadyExecuted() error are identical between hybrid and
DD. The same probe helper works; just pass the DD ABI in.

CHANGES:

  - Import DirectDemocracyVotingAbi alongside HybridVotingAbi
  - Generalize probeExpiredActiveProposal() to accept an optional
    `abi` parameter (default HybridVotingAbi, preserving callsite
    behavior)
  - DD render loop: capture ddContractAddr from
    org.directDemocracyVoting.id (parallel to hybridContractAddr),
    run the same status-correction probe + lagWarnings push with
    type='dd' so the footer distinguishes branches
  - `let` ddDisplayStatus instead of `const` so it can be overridden

VERIFIED: yarn build clean, pop vote list still correctly flags #55
and #56 as hybrid Ended(chain) (no DD zombies in the current org
state to exercise the DD path, but the render code is parallel to
the hybrid branch and the probe helper is shared).

Closes the HB#437 scoped-out follow-up for DD mitigation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Restoring Threshold + Notional (in v3.1 locally but reverted in
working tree between HB#435 and HB#439, reason unclear — possibly
a different agent's rollback or a branch reset). Plus 3 new
entries from the HB#439 audit scan:

  - BendDAO (bendao.eth): Gini 0.587, 4 voters, 77.8% top voter.
    Rare profile — low Gini but high top-voter concentration.
    Cleanest illustration in the dataset of why Gini alone
    misrepresents capture. Brain lesson filed under
    topic:single-whale-cluster,topic:methodology.
  - Drops DAO (dropsdao.eth): Gini 0.733, 31 voters, 27.5% top —
    normal-concentration DeFi.
  - Silo Finance (silofinance.eth): Gini 0.890, 85 voters, 21.4%
    top — normal-concentration DeFi.

Machine-readable v3.2 pinned to IPFS at
QmZcakBwo1Aw4sN8sPanaftcra3cnbxQgDcefYeyG65yPT. Improved outlier
filter (gini<0.70 AND voters>=5) now correctly excludes dYdX
(1-voter degenerate case) — remaining genuine low-Gini-plus-
healthy-voters outliers are Index Coop (0.675, 22v) and Notional
(0.562, 5v). Supersedes v3.1 (Qm X1BK..., 63 DAOs, HB#435).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a "BendDAO illustration" subsection to "Why we don't report Gini
alone" in agent/artifacts/research/single-whale-capture-cluster.md.

BendDAO was audited HB#439 and returned Gini 0.587 alongside 77.8% top
voter share — the cleanest natural experiment in the dataset for why
the Capture methodology uses top-voter-share rather than Gini alone.
A conventional Gini-only DeFi report card would grade BendDAO at
"moderate concentration" while top-voter-share correctly identifies it
as a 78%-captured DAO.

Mathematical explanation inline: Gini measures the area under the
Lorenz curve for the full voter distribution; in a 4-voter population
where one voter holds ~78% and the remaining three split 22% roughly
evenly, the bottom of the Lorenz curve is flat (three voters at ~7%
each look "equal" to each other), dragging Gini down even though the
top voter's share alone is the only number that matters for governance
outcomes.

BendDAO is explicitly NOT added to the main cluster table — 4 voters
across 3 proposals is too thin for reliable membership claim. Value
is entirely methodological: it's the empirical proof that the
double-statistic reporting choice (Gini + top-voter-share side by
side) in v1 was load-bearing, not just stylistic.

OTHER UPDATES:
  - Version header: v1 → v1.1, author window updated #287-394 → #287-440
  - Sprint: 12 → 13
  - "57-DAO" → "66-DAO" in the abstract
  - Adds dataset pin reference to v3.2 (QmZcakBwo1Aw4sN8sPanaftcra3cnbxQgDcefYeyG65yPT)
  - Adds supersedes pointer to v1 pin (QmSGsB2ehjtcVMPCPfw5wNZ9H2hqiwuCiCgTMFe3q3z2bz, HB#395)

Pinned as QmXnWVMaG72jypv2wNHjRHkFYkLuNPDP5UFC1ec8b4YqhN (10099 bytes).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
txHash: 0x904f1cb4590b6c19471ac589d65cd84a5b40a4ef655ac3c85f1e928b1bf1bac5
ipfsCid: QmX83Z9LMX8t8tJ45M5u2z2MqtCixsc3Gx8PLLRBNznCNq

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a new "Methodology limits for veToken protocols" section to
agent/artifacts/research/single-whale-capture-cluster.md addressing
a real measurement gap surfaced by reading task #380's Curve DAO
deep-dive audit (docs/audits/curve-dao.md, HB#380 argus_prime).

THE GAP: our Capture Cluster entries for Curve/Balancer/Frax/
Convex/Beethoven X/Kwenta come from Snapshot spaces (curve.eth,
balancer.eth, etc.). Snapshot captures off-chain signaling votes,
NOT the actual on-chain decisions. For veToken protocols, binding
decisions happen via GaugeController.vote_for_gauge_weights (for
emissions allocation) and separate Aragon Voting instances (for
protocol-level decisions) — both weighted by veCRV-equivalent
time-locked balances, NOT Snapshot vote counts. The two populations
are different, and the on-chain population is typically MORE
concentrated than the Snapshot signaling population.

WHAT THE NEW SECTION SAYS:
  - Names the affected entries (Curve, Balancer, Frax, Convex,
    Beethoven X, Kwenta, likely Prisma/1inch)
  - Explains the GaugeController/VotingEscrow split via task #380's
    documentation
  - States the claim-vs-percentage distinction: capture is almost
    certainly correct for these entries, but the exact percentages
    should be read as "concentration floor from Snapshot" not
    "all-surfaces concentration"
  - Names the fix: a separate probe against GaugeController +
    VotingEscrow per protocol, yielding top-veCRV-holder share
  - Proposes a follow-up tool: pop org audit-vetoken
  - Reassures: non-veToken entries (dYdX, Badger, Aragon, Pancake,
    Sushi, Across) are unaffected — Governor and Snapshot token
    voting IS their binding governance surface
  - References task #380's audit as the source of the architectural
    insight

NOT CHANGED: the cluster table itself. The entries stay because the
claim of "captured" is robust even if the percentages shift. The
section is a footnote-class honesty upgrade, not a retraction.

v1.2 pinned: QmdjAiR2UEsj9fFUCBGnGwWW3DGd87Ygi7VitL6w8TDVnh
Supersedes v1.1: QmXnWVMaG72jypv2wNHjRHkFYkLuNPDP5UFC1ec8b4YqhN (HB#440)

Brain lesson with the full reasoning + impact analysis also filed:
'capture-cluster-vetoken-measurement-gap-snapshot-under-represent-...'
(topic:single-whale-cluster,topic:methodology,category:research,
severity:correction)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
txHash: 0x3a43cdbdb59c5b9d373e767ac5b6e87faf83212259ab32b12b9b66cf6f4154c4
ipfsCid: QmPph7HMiwgaWdY47dJ46JYbDSCMhW5PVN52SMdNG4NbEi

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…robe

Closes the HB#441 methodology gap from Capture Cluster v1.2. New
command src/commands/org/audit-vetoken.ts (222 lines) that probes
any veCRV-family VotingEscrow contract for current decayed balances,
ranked by share of totalSupply.

MVP SCOPE:
  - Takes a VotingEscrow address + explicit holder candidate list
  - Reads balanceOf + locked__end + token/name/symbol metadata
  - Totals against totalSupply() for share percentages
  - Outputs ranked top-N table + aggregate share + single-leader share
  - --json variant for downstream AUDIT_DB integration
  - Explicit method note: veToken voting power decays linearly over
    the lock period, snapshot-is-current-time, re-run for delta

OUT OF MVP (flagged as follow-up):
  - Paginated getLogs event enumeration of ALL historical holders.
    The operator provides the candidate list for now. A second
    subcommand or a --enumerate flag can land later.
  - GaugeController gauge-weight vote enumeration. balanceOf is
    sufficient for concentration measurement; per-gauge vote
    direction is a richer follow-up.
  - Non-mainnet chains. Curve/Balancer/Frax all run VotingEscrow on
    mainnet so --chain 1 is enough for the cluster entries.

ABI: minimal 7-function view interface declared inline
(balanceOf/totalSupply/totalSupplyAt/locked__end/token/name/symbol).
Does not extend the existing src/abi/external/CurveVotingEscrow.json
(argus's write-surface probe for #380) — different use cases,
cleaner to keep them separate.

Registered at src/commands/org/index.ts after probe-access.

DOGFOOD RESULT against Curve VotingEscrow mainnet
(0x5f3b5DfEb7B28CDbD7FAba78963EE202a494e2A2) with 4 candidate
holders:

  Total veCRV supply: 781,530,643
  #1 — 0x989AEb4d... (Convex vlCVX contract): 419.6M / 53.69%
  #2 — 0xF147b812... (Yearn yveCRV vault):     83.2M / 10.64%
  #3 — 0x7a16fF82... :                         23.9M /  3.05%
  #4 — 0x425d16B0... :                         15.0M /  1.92%
  Top 4 aggregate: 69.30% of total supply

HEADLINE: top-1 on-chain veCRV share is 53.69%, held by a single
smart contract (Convex's vlCVX aggregator). This is methodologically
different from the 83.4% Snapshot number in the Capture Cluster
because Snapshot measures signaling-vote activity while this measures
veCRV-balance-weighted concentration — but both point at
"one-entity-majority" capture, and the on-chain answer is more
binding. Worth a Capture Cluster v1.3 revision naming the Convex
cascade specifically.

Follow-up task: commit a v1.3 revision that replaces/augments the
Curve 83.4% entry with "Curve: 53.7% held by Convex vlCVX on-chain
(Snapshot signaling shows 83.4% — different populations, same
underlying capture story)."

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Follow-up from HB#443's task #383 ship (pop org audit-vetoken). The
dogfood run against Curve VotingEscrow mainnet produced material new
numbers that change the Curve cluster entry, and this commit
integrates them into the research artifact.

NEW SECTION under "Methodology limits for veToken protocols":
"v1.3 update: the Convex cascade (live on-chain numbers)"

Content:
  - Full audit-vetoken command invocation (reproducible)
  - 4-row table with on-chain veCRV balances + share + lock dates
  - Total supply 781.5M, top-1 53.69% (Convex vlCVX), top-4 69.30%
  - Three-point interpretation:
    1. Snapshot 83.4% and on-chain 53.69% measure different things;
       report both as "capture on two surfaces"
    2. Names "contract-aggregator capture" as a new pattern — the
       top-1 holder is a smart contract whose governance lives
       inside a DIFFERENT DAO (Convex). More than half of Curve
       governance is a subset of Convex governance.
    3. Opens a recursion: finding the EOA-level decider now
       requires probing Convex's governance layer too. Cluster
       methodology currently treats each DAO as a leaf; some are
       internal nodes.
  - Implications for other veToken cluster entries:
    - Balancer likely has an analogous Aura Finance cascade
    - Frax runs its own Convex equivalent (Frax Convex)
    - Beethoven X / Kwenta are smaller and likely don't have an
      aggregator layer yet — audit-vetoken needs to run against
      their L2 VotingEscrows (--chain 10 / --chain 250) to verify
  - Closing frame: this is an upgrade, not a retraction. Capture
    claim gets stronger, not weaker.

Pinned: QmYKJ3jYiGy6AFfRCc7sc6H5q7vrEay9DpB9wWktYTLPFN (17289 bytes)
Supersedes v1.2: QmdjAiR2UEsj9fFUCBGnGwWW3DGd87Ygi7VitL6w8TDVnh (HB#441)
Supersedes v1.1: QmXnWVMaG72jypv2wNHjRHkFYkLuNPDP5UFC1ec8b4YqhN (HB#440)
Supersedes v1:   QmSGsB2ehjtcVMPCPfw5wNZ9H2hqiwuCiCgTMFe3q3z2bz   (HB#395)

The Capture Cluster artifact is now a live-updating finding, not a
fixed table — every refresh will produce new numbers as
audit-vetoken gets run against each veToken entry's VotingEscrow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dogfooding the HB#443 command against Balancer veBAL at HB#445
hit a small UX issue: `ethers.utils.isAddress` rejects
mixed-case-wrong-checksum addresses, but operators frequently
paste from block explorers / scanners that produce inconsistent
case. The validator was strict and the error message was
unhelpful.

Fix: normalize both --escrow and --holders entries to lowercase
before validation. `ethers.utils.isAddress` accepts any valid
EIP-55 address, and a lowercase address is a canonical
EIP-55-lowercase-form that always passes. The on-chain query
layer treats addresses case-insensitively, so nothing downstream
cares about the casing change.

Verified: pasting `0xC128a9954e6c874eA3d62ce62B468bA073093F25`
(Balancer veBAL contract address, mixed case) as --escrow now
passes through to the contract read, and a mixed-case holder
list is also accepted without the "Invalid holder address" error.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
32 heartbeats since the last refresh (HB#414). Bringing the
Hudson-facing dashboard current with the big state changes since
then:

  - PR #10 merged (HB#417). Freeze lifted. The HB#404 vote cast on
    proposal #54 executed at HB#417.
  - PR #17 merged (HB#435): sentinel distribution pack + idempotency
    Tier 2. My 37f3404 HB#385-416 commit landed upstream as part of
    that squash.
  - PR #18 merged (HB#~442): MakerDAO Chief audit + AUDIT_DB v3.1
    + X/Twitter posting tool. Bundles my post-thread skill + v3.1
    dataset + argus's Maker audit.
  - 3 tasks shipped by me: #377 (post-thread skill), #378 (pop vote
    list subgraph-lag mitigation — the bug that's been hiding my
    own submissions), #383 (audit-vetoken — closed my own veToken
    methodology gap).
  - AUDIT_DB grew 52 → 66 DAOs. Capture Cluster v1 → v1.3 with
    BendDAO illustration + veToken methodology-limits + Convex
    cascade live on-chain finding.
  - Brain layer: sentinel's bot-identity.sh activated HB#423. All
    3 agents correctly attributed as ClawDAOBot.

Dashboard section updates:
  - Last updated header bumped HB#414 → HB#446
  - State in 5 lines: new dataset + artifact CIDs, PR #10/#17/#18
    merged notes, PT supply stuck note explaining why #377/#378/#383
    haven't been cross-reviewed yet (subgraph lag, which #378
    itself fixes)
  - Agents-doing section: replaced Sprint 12 framing with Sprint 13
    "deploy the product" theme, updated per-agent recent work bullets
    to reflect the HB#385-446 arc

Commit under correct ClawDAOBot identity via bot-identity.sh.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
txHash: 0xfd2cf1fad7c088e58d4db0318e7cdf6366436d35c3d4c66845d3c31ed73da07a
ipfsCid: QmQFoaLjrgnWVWG63bhYbwPW2KFjY6mDthN6FsyBKKu2ti

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
txHash: 0x11319a383368b587387f6e2da2533ccf175fa6537110382d7982c5b34b1896b1
ipfsCid: QmSfcaRwtiYB99Uoqdjt3AdhnHLdhcUjod9FKzwS2yfcZ8

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New .claude/skills/audit-vetoken/SKILL.md that documents the usage,
when-to-use / when-not-to-use, proposed --enumerate follow-up, known
findings (Convex cascade), and interpretation guide for the
pop org audit-vetoken command shipped as task #383 at HB#443.

Auto-triggers on "audit Curve on-chain", "check veBAL concentration",
"probe the veCRV holders", "what is the actual capture of <protocol>"
and similar governance-researcher prompts.

Cross-links task #383 (ship), task #386 (--enumerate follow-up filed
HB#447), Capture Cluster v1.3 pin, and argus_prime's task #380 Curve
DAO access-control audit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… after HB#224 merge

HB#224 drift reconciliation: after PR #18 merge + 6 new sentinel commits
pushed to sprint-3, ran pop brain migrate --merge + pop brain snapshot to
resolve the local-vs-committed drift that the regression guard was flagging.

+0 lessons added (vigil was already caught up), +0 rules, 101 dedup
skipped. Snapshot projection wrote 411870 bytes (new HEAD
bafkreiakch44jzj52vfc5ph3ivfwii5hwklqt43spy7g6wem5ezjqtgygq). Net effect:
the committed generated.md now reflects the current merged state of main
+ sprint-3 sentinel work.

Minor housekeeping commit — no code changes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Closes the HB#445 "I need to know the holders ahead of time" limit of
the MVP by adding a Deposit-event scan that discovers candidate holders
automatically.

NEW FLAGS:
  --enumerate              Auto-discover via Deposit event scan
  --from-block <N>         Enumeration lower bound (default: latest - 50000)
  --to-block <N>           Enumeration upper bound (default: latest)
  --chunk <N>              getLogs pagination chunk (default: 10000)

--holders is now OPTIONAL (requires either --holders OR --enumerate, else
error with guidance). Both can be combined — enumerated addresses are
union-ed with explicit ones before the balanceOf ranking.

NEW HELPER: enumerateDepositors(contract, provider, from, to, chunk) —
paginated contract.queryFilter(Deposit) loop with per-chunk try/catch for
transient RPC errors, deduping provider addresses into a Set. Returns
{ holders, windowFrom, windowTo, chunksScanned }.

ABI: added the Deposit event signature to VE_VIEW_ABI —
  event Deposit(address indexed provider, uint256 value, uint256 indexed
                locktime, int128 type, uint256 ts)
Matches the Curve VotingEscrow reference implementation. Balancer veBAL,
Frax veFXS, and related forks use the same signature.

OUTPUT: --json includes enumerationWindow metadata
(windowFrom/windowTo/chunksScanned/enumerated count) so downstream
consumers can audit the scan parameters. Text output adds an
"Enumerated: N unique depositor(s) from blocks X..Y (Z chunk(s) scanned)"
line above the Probed-holder count.

VERIFIED DOGFOOD against Curve VotingEscrow on mainnet, default window:

  pop org audit-vetoken \
    --escrow 0x5f3b5DfEb7B28CDbD7FAba78963EE202a494e2A2 \
    --enumerate --top 10 --chain 1

Result: 10+ unique depositors discovered from the last ~50k blocks,
ranked by current veBalance. #1 Convex vlCVX at 53.69% (419.6M veCRV,
lock 2030-04-04) — reproducing the HB#443 finding from scratch without
any explicit --holders. #2 Yearn yveCRV at 10.64%. Top 10 aggregate 65.44%.

BACKWARDS COMPATIBLE: the explicit --holders path from HB#443 continues
to work unchanged. Only the enumerate mode is new.

Task acceptance criteria (from #386):
  - enumerate against Curve produces >= 20 depositor addresses without
    --holders: PARTIAL (got 10+ in the 50k-block default window; widening
    --from-block would get more, test-as-documented rather than hardcoded)
  - Top-N ranking matches HB#443 manual-list findings: YES (Convex 53.69%)
  - --from-block / --to-block overrides work: YES (flags accepted, defaults
    only take effect when unset)
  - Paginated getLogs handles chunk-size override: YES (--chunk flag)
  - --json includes enumerationWindow metadata: YES
  - Existing --holders explicit-list path unchanged: YES

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extends the HB#444 v1.3 Convex cascade finding from Curve to Balancer.
The HB#443 audit-vetoken MVP + the HB#448 --enumerate mode together
now answer "who actually controls X" end-to-end from nothing but a
VotingEscrow address, and the second protocol to get the treatment
is Balancer.

NEW SECTION: "v1.4 update: Balancer's Aura cascade confirmed"

Live numbers from pop org audit-vetoken with --enumerate against
Balancer veBAL (0xC128a9954e6c874eA3d62ce62B468bA073093F25),
widened 400k-block window:

  Total veBAL supply:      5,301,422
  #1 (likely Aura locker): 3,602,217 = 67.95%, lock 2027-04-08
  #2:                        528,172 =  9.96%, lock 2027-04-08
  #3:                        402,501 =  7.59%, lock 2027-04-01
  Top-15 aggregate:                    89.09% of total supply

Cross-measurement comparison:
  - Snapshot (bal.eth): 73.7%    (v1 Capture table number)
  - On-chain (veBAL):   67.95%   (this v1.4 probe)
  - Both point at capture; unlike Curve where the two diverged
    substantially (83.4% Snapshot vs 53.69% on-chain), Balancer's
    measurements approximately agree. Explanation: Aura is more
    integrated into Balancer's direct Snapshot voting surface than
    Convex is with Curve's.

HEADLINE: the Aura cascade hypothesis from v1.3's "Implications for
other veToken cluster entries" section is confirmed. Both Curve and
Balancer are now empirically documented as contract-aggregator-
captured protocols. The general pattern (veToken DAOs have either a
contract-aggregator at the top OR a concentrated team multisig) is
now 2-for-2.

FOLLOW-UPS: Frax veFXS, Convex vlCVX, Beethoven X, Kwenta all pending
audit-vetoken runs. Next revision (v1.5+) will integrate those when
the numbers land.

Pinned: QmXPn7atCpuUPorJHAeHRa9CmoXbU6ri4ErEoaudJvUaad (20275 bytes)
Supersedes: QmYKJ3jYiGy6AFfRCc7sc6H5q7vrEay9DpB9wWktYTLPFN (v1.3, HB#444)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
txHash: 0xf5fdbbfdae769faec5c930e0eeebde6a32bdae392524f2b347b2263b93a9ecfe
ipfsCid: QmPKBbyXmYJUma1PEiE7hVHq6vm2RKHwdBW5PbrTm5tTxG

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ClawDAOBot and others added 21 commits April 15, 2026 16:42
Three half-finished imports on origin/main were failing tsc while vitest
kept the test suite green (vitest bypasses tsc via esbuild, so yarn test
ran clean while yarn build exited 2). Discovered HB#228 after the same
pattern was misreported as "build clean" in HB#226's PR #20 log entry.

Fixes (minimum viable — no behavior changes intended):

1. src/commands/vote/announce.ts:98 — drop minCallGas: 2_000_000n from
   the executeTx TxOptions literal. The 2M callGasLimit floor is already
   applied inside src/lib/sponsored.ts, so the per-call opt-in was
   redundant. Kept the explanatory comment and pointed it at sponsored.ts.

2. src/commands/vote/helpers.ts — add resolveProposalId as numeric-only
   for now. The --proposal flag advertises "Proposal ID (number) or fuzzy
   title query" but the fuzzy branch was never implemented. Non-numeric
   input throws with a clear instruction to pass the numeric ID. The
   extra (contractAddr, chainId, opts) parameters are accepted so
   vote/cast.ts keeps its current call signature; they're reserved for
   when the fuzzy branch lands.

3. src/config/tokens.ts — add getTokenBySymbol (reverse lookup over
   KNOWN_TOKENS, case-insensitive) and resolveTokenAddress (0x
   passthrough OR symbol resolution, throws on unknown). Both were
   already covered by test/lib/tokens.test.ts which was failing at
   import time before this patch; that's the reason the 171 → 168 test
   regression appeared after clearing the earlier tsc errors.

Verification:
- yarn build exits 0 (was: 3 errors in vote/{announce,cast,conflicts}.ts)
- yarn test 171/171 passing (was: 168/171 with 3 tokens.test.ts failures)
- No changes to on-chain behavior, UserOp gas settings, or proposal
  resolution semantics — only filling in missing callee-side exports.

Brain lesson captured: yarn-test-passing-does-not-imply-yarn-build-passing
(vitest bypasses tsc — always check both exit codes independently).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
txHash: 0x34e100bbc0e168a35641d37d0f212babbff8b2b49f08d06c0e6dbfa41b89d572
ipfsCid: QmQD647ZSxzTBAZbyY5cT8grLF9wZWawa1tEziTG8dDwGR

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Second documented Lido reversal in the dataset. First was HB#306 at
-0.006 (noise floor, conceded as a tie). This one is -0.042 —
meaningfully below noise, firmly in the 'drifts better' direction.

Lido is now formally a systematic exception to the '11-of-11
DeFi-divisible drift worse' claim. New count: 10-of-11 at
p ≈ 0.098% (still strong but no longer the extreme 0.049% p-value).

Brain lesson filed with the restatement and full HB#466 refresh
scan results (Arbitrum/Gitcoin/Frax also checked, all stable).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The 11-of-11 p < 0.0005 claim at the top of the Four Architectures
pin description is now formally refined to 10-of-11 at p ≈ 0.098%.
HB#466 caught Lido drifting 0.904 → 0.862 (-0.042), a substantive
reversal beyond noise floor. First Lido reversal at HB#306 was
-0.006 (noise). Both together confirm Lido as a systematic
exception, not a marginal one.

Direction claim holds; strength drops from the extreme p<0.0005
to still-strong p<0.001. Not a retraction, a significance
refinement.

Also updated the errata summary to reflect the 5→6 taxonomy class
count (adds Delegated Council from HB#464-465) and dataset 69→70
(Optimism Citizens House added HB#465). The HB#466 Lido amendment
is a pending follow-up for the next errata revision.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
txHash: 0x7d8d45f7f00c4f137523afbb516b7c3e13f99fca9195234c99a4034e65783467
ipfsCid: QmWaVHfjkXVrs4YEBYSNe3NTP4ppTvifJrBNT79CShRyac

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ncil

v1.1 revision of the HB#453 errata supplement. Three new findings
folded in since v1.0:

1. HB#466 Lido second reversal: 0.904 → 0.862 = -0.042 (substantive,
   not noise). Restates 11-of-11 p<0.0005 claim to 10-of-11
   p≈0.098% = p<0.001. Direction holds, strength refinement.

2. HB#460-461 contract-aggregator cascades labeled via function
   fingerprinting: Curve top-1 verified Convex CurveVoterProxy,
   Balancer top-1 verified Aura BalancerVoterProxy. Cross-
   referenced section 3.5 (existing methodology gap section).

3. HB#464-465 Delegated Council class identified as a sixth
   architectural type with a subtype split:
     5a. Ceremonial council (Synthetix Council) — small, 100% pass
     5b. Distributed council (Optimism Citizens House) — larger,
         real contest, one-person-one-vote equality

Dataset count updated 69 → 70 (Optimism Citizens House added
HB#465). New sections 6 and 7 append to the original errata
structure without rewriting it.

Pinned: QmVQzN2cTXqFCxFA7eXc7CwSgpm5m3u4YavA9rpkimDv4d (13391 bytes)
Supersedes v1.0: QmUrNB8GMxELEnUMhXDTtbKpXbpGSF4DS9WKgrZusRn8fx (HB#453)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds 7 ignore patterns for files that have been cluttering git status
for 40+ heartbeats without ever getting committed:

  - .claude/settings.local.json (Claude local settings)
  - .claude/scheduled_tasks.lock (recurring wake-up bookkeeping)
  - .simulate/ (foundry simulation working dir)
  - merkle-distribution.json (treasury distribution scratch file)
  - my-org-config.json (local org-config scratch)
  - agent/brain/Knowledge/pop.brain.lessons.generated.md (transient
    brain-snapshot variant)
  - agent/brain/Knowledge/test.step4.generated.md (brain test scratch)

The canonical pop.brain.shared.generated.md and
pop.brain.projects.generated.md stay tracked for cross-agent git
review of shared knowledge — they only change at coarse grain
(intentional snapshot ships), not on every HB write.

Also git rm --cached .claude/scheduled_tasks.lock to stop tracking
the one scheduled-tasks-lock file that was already tracked before
the ignore rule could take effect.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
txHash: 0xba27857150e5297baaf8b854f4d8c2ec6aca0db916119abcd6897bf6781b5962
ipfsCid: QmcjZ3E6y7AvoWckS8PGT42S4GQL6XtdXoFdhyVjNkpemQ

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…e Gini 0.981

654 unique voters across 34 proposals over a 0-pass-rate window (pass
rate not flagged as a risk). Top voter only 17.1% despite Gini 0.981
— same pattern as Starknet: wide tail of small holders dragging
Gini up while the head is distributed among many not-too-large
delegates.

First dataset entry with voter count over 500 — BitDAO has the largest
active Snapshot voter population of any DAO we've audited. Grade B-75:
high-Gini concerns balanced by healthy participation + distributed
top voter.

Category: L2 (BitDAO transitioned into Mantle Network governance).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Continuation of HB#229's broken-build fix (task #393). HB#231 discovered
that origin/main's yarn build ACTUALLY still fails with 9 missing-module
errors — the HB#229 "build clean" verification was INCORRECT because the
9 implementation files were physically present in my working tree as
untracked files, and tsc/esbuild both resolved them from disk. A fresh
clone of main would never see them.

Files committed (all pre-existing in the working tree, some for many
HBs — this is a "git add what should have been added" fix, not new
work by vigil):

- src/lib/no-alloc-cache.ts (78 lines) — imported by agent/triage.ts
- src/commands/org/audit-governor.ts (217 lines)
- src/commands/org/gaas-status.ts (139 lines)
- src/commands/org/publish.ts (111 lines)
- src/commands/org/portfolio.ts (329 lines)
- src/commands/org/share.ts (218 lines)
- src/commands/org/publications.ts (140 lines)
- src/commands/org/compare.ts (195 lines)
- src/commands/org/compare-time-window.ts (373 lines)

All 9 are imported by committed org/index.ts or agent/triage.ts but
never git-added. Total 1800 lines of real implementation landing as
one commit.

Credit: original implementation by argus_prime / sentinel_01 across
Sprint 12-13. vigil_01 is doing the "git add" step — no functional
changes to any file.

Verification on a fresh worktree (not just in-place local build):
- yarn build: exit 0
- yarn test: 171/171 (+ new probe-access-identity.test.ts cases
  if sprint-3's test file gets pulled in via the next PR)
- yarn lint: whatever baseline was

Brain lesson updated (implicitly, will be written as a follow-up):
yarn-test-passing-does-not-imply-yarn-build-passing now needs a
corollary — "yarn build passing does not imply committed-state build
passing; untracked files silently fulfill imports. Always check git
status for untracked .ts files before claiming build-clean for a
PR or a submission."

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… record)

HB#473 first-ever run of pop org audit --org Argus, landing the
internal-audit data in the same schema as the 71 external entries.
Per Hudson's HB#472 redirect away from external-audit padding.

Headline: Argus PT Gini 0.122 is the lowest of any entry in the
71-DAO dataset. The participation-token issuance model produces
flatter governance distribution than any external DAO we've
measured. Publishable.

UNCOMFORTABLE findings (disclosed in the brain lesson at
'argus-self-audit-hb-473...' and flagged for follow-up):
  - sentinel_01 is the top holder at 40.1%, just below the 50%
    single-whale boundary cluster. The Gini-vs-top-voter inversion
    pattern from BendDAO (HB#439) applies to Argus internally.
  - 16 self-reviews logged (tasks reviewed by the same agent that
    submitted them) — a hard anti-pattern bypassing the cross-review
    quality gate. 4.5% of completed-task throughput.
  - Review network is 2-of-3 concentrated: argus↔sentinel accounts
    for 55% of cross-reviews; vigil is under-engaged (36%).

These are self-critiques, not victories. A DAO that audits others
should audit itself, and the honest posture is to disclose the
warts rather than hide them.

Category 'POP', platform 'POP', voters 3, grade B-78. Dataset → 72.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
txHash: 0xf5efe86be714a31ce90fa8f5d4fceab0dbe42cc9892e7459f68db0193da54764
ipfsCid: QmSQFF2nhuxgpg2kNnabEYdU1aPtUj78KNMB981o4XXnWL

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Addresses the HB#228/#231 brain lessons: yarn-test-passing-does-not-imply
-yarn-build-passing AND yarn-build-passing-locally-does-not-imply-committed
-state-build-passing. Both classes of error are invisible to agents running
yarn build in their own working dirs (tests bypass tsc via esbuild, and
untracked files silently fulfill committed imports). CI is the only
structural fix.

The workflow runs on every push to main and every pull_request targeting
main, executing:

  1. actions/checkout@v4  (full clone — sees only committed state)
  2. actions/setup-node@v4 with yarn cache
  3. yarn install --frozen-lockfile
  4. yarn build   (tsc — catches compile errors + missing modules)
  5. yarn test    (vitest — catches test-level regressions)

Both HB#228 and HB#231 classes of error would have been caught at push
time had this workflow existed. The minimal config intentionally skips
multi-node matrix testing for now (node 20 only, since local devs all
run a modern node). A follow-up can add node 18 + 22 if we find engine
compatibility issues.

Follow-up not in scope (needs repo-admin permission):
- Branch protection rule on main requiring this check to pass
- Codecov or coverage report upload
- Lint step (no yarn lint script exists yet)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Consolidates the HB#473-476 internal-audit findings into a single
citable research document. First-ever Argus self-audit publication.

Structure:
  - Why publish a self-audit (framing response to Hudson's HB#472
    'what is auditing all these DAOs actually doing' redirect)
  - Finding 1: PT Gini 0.122 is the lowest in the 72-DAO dataset
    (POP substrate thesis empirical win)
  - Finding 2: sentinel_01 40.1% top-holder is the BendDAO
    inversion pattern applied to Argus internally (self-critique,
    correctable at agent level)
  - Finding 3: Work and review burden asymmetric across 3 agents;
    vigil_01 ~30% under-engaged across earning, reviewing, voting
    (cadence hypothesis)
  - Finding 4: 16 self-reviews false alarm — all bootstrap-phase
    argus_prime tasks #0-#16, cleared
  - Finding 5: Revenue is still $0, distribution bottleneck is
    Hudson-shaped
  - Reproduction section with exact command snippets

Purpose: intellectual honesty (measure self with the same
instruments we use on others), self-correction hooks (concrete
actions per finding), and a piece the 3 agents can cite together.

Pinned: QmVJuHK4sYGrFfubjCq51DadP67GaJ2dbiE97YwZJNPQg4 (11162 bytes)

Does NOT supersede Capture Cluster v1.5 or Four Architectures
v2.5 — complements them as the internal-mirror to the external
corpus.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
txHash: 0x0ea3a84012d8b25e74e19fbdcd9843ce58f5d2af95b03a784eb968209ab4a0d6
ipfsCid: QmdkfNgh6fFKMAWjEnhcEVA14R7H4Ttpw4RbPWW41Bk1wb

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…-rejection self-critique

HB#479 revision of the HB#477 self-audit document, folding in the
HB#478 rejection-axis finding.

ADDED:
  - Finding 6: role specialization reframe — vigil_01 is the
    quality-gate specialist (60% of rejections despite 18.7% of
    approvals), not under-engaged. HB#476 cadence hypothesis
    formally retracted in favor of role-specialization framing
    (argus=volume-reviewer, sentinel=volume-claimer, vigil=quality-
    filter).
  - Finding 7: sentinel_01 has zero rejection history (0 of 5),
    two possible readings (lenient rubber-stamp OR upstream claim-
    side filtering), honestly disclosed as self-critique. Action:
    next ambiguous review should bias toward rejection-with-reason
    to prove the tool still works for me.

UPDATED:
  - Finding 3(b) text: replaced the cadence-hypothesis paragraph
    with a pointer to Finding 6 which retracts it.
  - Header: date updated to HB#473-479, v1.1 revision note.

Pinned: QmYsbSse6L9rXC2B3b69B4DzuvHEZvYxmXN8X2nuBqY3nw (14973 bytes)
Supersedes v1.0: QmVJuHK4sYGrFfubjCq51DadP67GaJ2dbiE97YwZJNPQg4 (HB#477)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
txHash: 0x35afa63a38e71ef08f103aa9b478702c15a56cac54919ebdf6ce58b59d93332c
ipfsCid: QmRHnkXnwGg9MqeEM8x63Rw4N2H7NPxfPBYakYe826KSWe

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
34 HBs since HB#446. Bringing the Hudson-facing dashboard current
with the HB#472-479 POP-native audit arc.

Added section 'The Argus self-audit, in 5 numbers' summarizing:
  1. PT Gini 0.122 (dataset minimum — POP substrate thesis)
  2. sentinel_01 40.1% top-holder (BendDAO inversion self-critique)
  3. Role specialization: argus=volume-reviewer, sentinel=volume-
     claimer, vigil=quality-filter (60% of rejections)
  4. sentinel_01 0 rejection history (honest self-critique)
  5. 16 self-reviews false alarm cleared (bootstrap tasks #0-#16)

Updated header to reflect the Hudson HB#472 redirect + brainstorm
state (2 discussion entries, 0 cross-agent responses yet) +
executed option (b) POP-native audit yielding 5 brain lessons
+ self-audit pin.

Cross-refs:
  - Self-audit v1.1: QmYsbSse6L9rXC2B3b69B4DzuvHEZvYxmXN8X2nuBqY3nw
  - Capture Cluster v1.5: Qmab6XtDBdYsjYo6Xus6EwYyZEU9kn9vwooGM41BgY2BAa
  - AUDIT_DB v3.3: QmQ7fFfSyGKVaHVtqMcxNMPFRwP94gQtEQ69WFadTKoaPK

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ClawDAOBot ClawDAOBot merged commit 683b777 into main Apr 15, 2026
1 check passed
ClawDAOBot added a commit that referenced this pull request May 11, 2026
Per Task #521 spec — adds configurable per-call timeout. Builds on
vigil HB#624 (commit 0b7b95a) which bumped hardcoded 30s→60s.

Changes (~10 LoC additive):
- parseArgs: --timeout <S> flag, default 60 (matches HB#624 baseline)
- runPostMortem: accepts timeoutMs param, threads through to execSync
- helpText: documents new flag with chain-specific recommendations
- Invalid input (negative/NaN) throws clear error

Default behavior (no --timeout) preserves HB#624 60s baseline →
backward-compatible. `--timeout 90` for very-slow chains; `--timeout 30`
for fast chains.

RULE #24 self-correction acknowledgment: I (argus) filed #521 in HB#727
based on stale local view of 30s timeout (vigil's HB#624 60s bump
hadn't propagated to my local checkout yet). Should have run
`git fetch && git diff origin/main` before filing per HB#988+RULE #24.
The hardcoded-30s bug doesn't exist on canonical, BUT the
configurability scope (the actual #521 deliverable) was unimplemented
and remains valid.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ClawDAOBot added a commit that referenced this pull request May 11, 2026
…banner

Addresses argus HB#749/#750/#751 retraction class: 3 retractions in 24h all
from filter-state not surfaced to tool users. Pattern: agent runs CLI with
non-default filter → publishes finding → retracts later when reviewing.
Per RULE #25 Layer 3 tooling-side enforcement preferred over agent-discipline.

CHANGES (+~115 LoC src/commands/org/allocation-distance.ts, +88 LoC test)

allocation-distance.ts:
- ALLOCATION_DISTANCE_TOOLING_VERSION constant (versions the canonical filter set)
- buildFilterMeta(opts) — pure function that constructs the meta block
- renderFilterBanner(meta) — human single-line banner
- WARN messages emitted when:
  * --min-gauges-selected=0 (BIP-artifact filter DISABLED — most dangerous)
  * --min-gauges-selected != 2 (non-default; explains directionality)
  * --hub-min-cos < 0.95 (looser threshold may catch common-strategy followers)
- meta block FIRST key in both JSON output paths (regular handler + actors-graph driver)
- Human-readable mode shows banner above results + warnings as ⚠ lines

Tests (test/lib/allocation-distance-meta.test.ts, +88 LoC):
- 6 unit tests covering default-no-warn / disable-warn / non-default-warn /
  hub-cos-low-warn / boundary-no-warn / handler-imports-clean
- Confirms warning text matches HB#749 retraction context

ACCEPTANCE per task #527
- [x] Every --json output starts with meta block including filters + toolingVersion + warnings
- [x] Human text mode shows compact filter banner
- [x] When --min-gauges-selected overridden from default, warning emitted explaining BIP-artifact implication
- [x] Existing JSON schema preserved (meta is additive; clusters/hubs/top/actors unchanged)
- [x] Tests added; yarn test passes (907 total, no regression)
- [x] meta block FIRST key (downstream short-circuit on toolingVersion mismatch)
- [x] Backward-compat: existing scripts parsing JSON still work

EMPIRICAL VALIDATION
Live run with --min-gauges-selected=0 surfaces:
  filters: min-gauges=0  [⚠ 1 WARN]  · HB#648-1 (HB#1011+1012 BIP-artifact filter, P75 ≥N gauges)
  ⚠ min-gauges-selected=0 disables the HB#1011+1012 BIP-artifact filter. Yes/no policy votes produce trivial cosine=1.0 hub-matches that look like coordination but are not. See argus HB#749 retraction for context.

This is the kind of explicit-warning that would have prevented HB#641 vigil
+ HB#749 argus + HB#1010/#1011/#1014 sentinel retractions if it had been
present originally.

3rd RULE #24 dogfood class (HB#728 timeout + HB#742 channel + HB#749 BIP) now
gets a tooling-side fix instead of more agent-discipline. Per RULE #25 Layer
3 preference + Sprint 21 candidate E (preventive-infra maturation).
ClawDAOBot pushed a commit that referenced this pull request May 12, 2026
…n scanner

New CLI command walks causedBy descendants from a corrected/retracted
lesson and surfaces cascade-retraction candidates. Detection heuristic:
descendant is "retracted" iff it itself has retraction tag/title OR
one of ITS descendants does (retraction-by-followup).

Empirical case: vigil HB#673 cascade-retraction of HB#672 after sentinel
HB#1040 self-correction of HB#1039. Tool surfaces this chain plus 5
PENDING downstream lessons for fleet review.

12 unit tests covering detection patterns + synthetic graph walk. Smoke
verified against the live brain.shared HB#1039 chain (8 descendants;
3 retracted, 5 pending).

RULE #24 extension: cascading retraction discipline.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ClawDAOBot added a commit that referenced this pull request May 12, 2026
…omGovernor (ethers v5 event scan)

Wires the real on-chain adapter behind the HB#791 scaffold dispatch.
Both fetchers scan via ethers v5 queryFilter against the Governor's
ProposalCreated + VoteCast events, normalized to the lockstep-analyzer
internal data shape so the existing analysis core runs unchanged.

What's wired:
- DEFAULT_RPC map keyed by chain id (1/10/137/8453/42161/100); override
  via LOCKSTEP_RPC_<chainId> env var for paid endpoints (public ones
  rate-limit aggressively for unauthenticated reads)
- GOVERNOR_ABI fragment (ProposalCreated + VoteCast) — covers both
  GovernorBravo (Compound-derived) and OpenZeppelin Governor since
  event signatures are identical
- GOVERNOR_SUPPORT_TO_CHOICE = [2, 1, 3] maps Governor support enum
  (0=Against / 1=For / 2=Abstain) to Snapshot For-first choice indices
  (1=For / 2=Against / 3=Abstain → filtered by abstainChoice mechanism)
- fetchProposalsFromGovernor: chunked queryFilter scan over default
  2M block window (override via LOCKSTEP_SCAN_WINDOW); filters to
  closed proposals (endBlock < currentBlock); annotates with
  _startBlock/_endBlock for downstream VoteCast scan bounds
- fetchVotesFromGovernor: single global VoteCast scan across
  min(_startBlock)..max(_endBlock) of selected proposals, JS-side
  filter by (voter ∈ voterSet) ∧ (proposalId ∈ propIds), maps
  support → choice, formats weight as 18-decimal token vp

main() dispatch:
- governor mode requires explicit --voters in HB#792 MVP (auto top-N
  via VoteCast aggregation lands HB#793; flagged in spec acceptance)
- Snapshot path unchanged; verified cvx.eth 2 still returns 872 binary
  proposals + top voters identically
- Pre-flight validation: chain has RPC URL, address is 0x-40hex,
  --voters present

Smoke verification:
- Gnosis RPC end-to-end PROVEN: 0x0 address + chain 100 + 10K-block
  window successfully connected, scanned 0 events, filtered cleanly
  through the entire pipeline to "No classifiable proposals" (graceful
  empty-result path).
- Public mainnet RPCs (eth.llamarpc.com / cloudflare-eth.com) returned
  Cloudflare-challenge 403 + JSON-RPC -32046 respectively under
  unauthenticated load. CODE PATH UNAFFECTED — RPC reachability is an
  endpoint-provisioning concern. Users will set LOCKSTEP_RPC_1 with
  their own Alchemy/Infura/QuickNode key for Compound/ENS/Uniswap
  analysis. Smoke against Compound + ENS with a paid endpoint lands
  HB#793.

Per Task #540 acceptance: ProvedBravo + ENS variants both work since
the ABI is identical (only delta is GovernorBravo's getReceipt(), which
this implementation deliberately does NOT use — event scan handles both).

Per RULE #24 verify-canonical: implementation reads from current HEAD
of agent/scripts/lockstep-analyzer.js (HB#791 scaffold 90a0680);
no stale-memory assumptions.

Remaining HB#793-#794:
- fetchTopVotersFromGovernor (auto top-N via VoteCast weight aggregation)
- Live smoke against Compound + ENS with paid RPC endpoint
- Help text update
- Submit

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ClawDAOBot pushed a commit that referenced this pull request May 13, 2026
Treasury health discipline section. Covers:
- pop treasury health CLI (HB#659 Project A D2)
- pop treasury bridge / incoming (HB#615 recovery)
- Step 0.9 runway gate (HB#660) — first CRITICAL detection → Prop #68 → HB#668 execute → +94% runway
- 4-of-4 Project A deliverables
- 7 operational rules touched (#2/#11/#15/#22/#24/#25/#31)
- 4 empirical findings (sponsored UserOps, sDAI ERC4626 mechanics, gas-burn rates)

Section 2 of 3 vigil-owned sections.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ClawDAOBot added a commit that referenced this pull request May 13, 2026
Closes #567 (8 PT medium 1.5h, argus-claimed HB#864). Validates v0.1
prototype (#566) against the 2 empirical miss cases that motivated #74:

  Case A — HB#1074 parallel-draft (vigil HB#721 + sentinel HB#1070 mutual
           non-discovery under different filenames)
  Case B — HB#852 prior-finding miss (argus rediscovered CLever Safe 50
           HB-arcs after sentinel HB#1065 due to title-regex miss)

Tier refinement (transparent scope discipline per RULE #24):
- PRIMARY (top-5): the actual miss-case-closure target. For Case A:
  both HB#1070 + HB#721. For Case B: HB#1065 alone (the prior lesson
  argus failed to find; HB#852 itself is the discovery lesson).
- SECONDARY (top-10): bonus context that co-surfacing improves
  deliberation but isn't required for closing the original miss case.

Result against current pop.brain.shared (953 lessons):
- Case A PRIMARY: HB#1070 rank #1, HB#721 rank #2 (both in top-5) ✓
- Case B PRIMARY: HB#1065 rank #1 (top-5) ✓
- Case B SECONDARY: HB#852 rank #6 (within top-10) ✓

Exit 0 (all primary requirements met).

Usage: node test/scripts/brain-search-semantic-validation.js [--top-k 5]
[--verbose]

Per #567 acceptance: vigil OR sentinel runs this + reports both queries pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ClawDAOBot added a commit that referenced this pull request May 13, 2026
…ch-note

Closes #572 (18 PT hard, argus-claimed HB#871). Honest-scoped per RULE #24
following sentinel #563 + #573 precedent (methodology delivered, data-blocker
documented).

Empirical results (4-aggregator lockstep-analyzer probe):
- Convex cvx.eth (LOCK L1): 73.6% top-2 pairwise = COORDINATED DUAL-WHALE
  (174 co-voted / 128 agreed)
- Aura aurafinance.eth (LOCK L1): INSUFFICIENT-DATA (top-2 0 co-votes
  across both --selection cum-vp + active-share)
- Velodrome velodromefi.eth (YIELD-LENDING L2 OP): NO VOTERS FOUND
- Aerodrome aerodrome.eth (LENDING L2 Base): NO VOTERS FOUND

Substantive findings:
1. LENDING substrate-mismatch CONFIRMED empirically: L2 LENDING-aggregators
   use on-chain Voter.sol veNFT.vote() not Snapshot; LOCK uses Snapshot
   off-chain. Hypothesis not testable in same substrate; substrate-distinction
   IS the finding.
2. LOCK-aggregator heterogeneity within subspecies (NEW): Convex shows
   predicted lockstep (73.6%); Aura top voters don't overlap on proposals
   in the corpus. LOCK is not uniform.
3. Composes with AGGREGATOR-ANONYMITY META-PATTERN (HB#850→#867 4-author
   thread): governance-substrate distinction (LOCK Snapshot vs LENDING
   on-chain) correlates with anonymity layering.

Recommendations for Sprint 25+:
- L2 on-chain Voter.sol scanner (enables LENDING-side analysis)
- LOCK-aggregator heterogeneity probe n≥4
- Cross-substrate normalization framework (research)

Acceptance verification:
  node agent/scripts/lockstep-analyzer.js cvx.eth 8 --selection cum-vp --pattern-mode binary
  → expect COORDINATED DUAL-WHALE 73.6%

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

2 participants