Skip to content

feat: proposal lifecycle + agent-native pivot + officer bootstrap#50

Merged
Skanislav merged 1 commit into
devfrom
fix/audit-remediations-and-optimizations
Apr 24, 2026
Merged

feat: proposal lifecycle + agent-native pivot + officer bootstrap#50
Skanislav merged 1 commit into
devfrom
fix/audit-remediations-and-optimizations

Conversation

@Skanislav

Copy link
Copy Markdown
Contributor

🤖 Linear

Closes lin-XXX

Description

Omnibus branch landing three months of work: audit remediation, the full proposal/objection lifecycle, the agent-native pivot, and today's readable-tensions + officer/agent-identity bootstrap UI. 25 commits, 171 files, +19,055/-3,627.

1. Proposal + objection lifecycle (specs/05)

  • MeetingFactory gains full lifecycle: createProposalraiseObjection / resolveObjectionadopt / discard (feat: governance proposal + objection lifecycle #45 merge)
  • executeGovernance deleted along with backward-compat scaffolding
  • Ponder handlers + indexing-client queries + agent-sdk write methods
  • Public permalink + open-proposals panel on hola-modern

2. Agent-native pivot (specs/99-agent-native-divergence.md)

  • Attribution-only proposer model: proposerRoleId=0 means "propose as member"; contract still emits the roleId for indexer distinction
  • MAX_PROPOSAL_AGE per-org configurable (default 7d, bounds [1h, 30d]); frontend reads from chain
  • Meeting UX reframed around async proposal queue rather than synchronous ritual
  • ERC-8004 agent identity: OrganizationInstance.linkAgentIdentity(agentRegistry, agentId)

3. Audit remediation + gas opts

  • Holacracy-compliance fixes, admin-safety invariants (OrganizationInstance_LastAdmin), gas optimizations
  • RoleDataRegistry simplified via OZ Initializable + EnumerableSet
  • Composition patterns via OZ libraries across contract set

4. Readable tensions + officer/agent bootstrap (today)

  • createProposalWithTension(...) publishes plaintext via ProposalTensionPublished event; keccak256 derived on-chain so tensionHash stays canonical. Legacy hash-only path retained.
  • isFacilitatorElected / isSecretaryElected views expose election-lock state — UI greys out locked admin setters instead of learning via revert
  • New AgentIdentityCard (self-serve ERC-8004 link, Members tab) + FacilitatorsCard (admin bootstrap)
  • GovernanceView pivots from meeting-centric to proposal-queue-health ({open, expiringSoon<2d, expired}); ritual steps collapse behind a disclosure
  • New hooks: useAgentIdentity, useCircleOfficerLocks, useSet{CircleFacilitator,CircleSecretary,ProposalMaxAge}

Other

  • EIP-5792 batch org creation + expand-role-to-circle
  • Encrypted role content refs + Sepolia deploy tooling
  • UX audit batch 1 (2 critical + 5 polish)
  • Objection lifecycle UI (raise / resolve / discard)

Checklist before requesting a review

  • I have conducted a self-review of my code.
  • I have conducted a QA.
  • If it is a core feature, I have included comprehensive tests.

Test plan

  • pnpm test passes across all workspaces
  • forge test -vvv — proposal lifecycle, objection lifecycle, officer-election lock flips, tension plaintext hash parity
  • pnpm --filter hola-modern test:e2e — proposal wizard (hash + plaintext paths), objection UI, agent identity link, admin facilitator/secretary set
  • Manual: deploy against Sepolia, walk through create-proposal → raise-objection → resolve → adopt with both plaintext and hash-only tensions
  • Manual: verify GovernanceView expiry stats match indexer truth against a fresh org
  • Manual: ERC-8004 link flow with a real agent NFT on Sepolia
  • Manual: admin bootstrap of Facilitator/Secretary, then adopt an Election and verify the setter locks

🤖 Generated with Claude Code

Turn proposals into first-class readable objects and wire the two
missing agent-native surfaces from specs/99.

contracts
- createProposalWithTension(...) publishes plaintext via a new
  ProposalTensionPublished event; hash is derived on-chain
  (keccak256) so tensionHash stays the canonical content address
- legacy createProposal(...) retained for the hash-only path
- isFacilitatorElected / isSecretaryElected views expose election
  lock state so the UI can disable admin bootstrap setters instead
  of learning via revert
- unit tests cover both new views + hash/event parity

indexer
- proposal.tensionText (nullable) persisted on ProposalTensionPublished;
  null still resolves via the storage backend indicated by tensionHash
- ABI, schema, and indexing-client types updated end-to-end

hola-modern
- proposal wizard gains a Tension textarea (280 chars) and routes to
  createProposalWithTension when non-empty, createProposal + zeroHash
  otherwise
- wizard exposes caller's led roles so §5.3 attribution is pickable,
  not guessable
- GovernanceView pivots from meeting-centric to proposal-queue-health
  ({open, expiringSoon<2d, expired}); ritual steps collapse behind a
  disclosure
- new AgentIdentityCard (ERC-8004 §4) self-serve link on Members tab
- new FacilitatorsCard admin bootstrap for Facilitator/Secretary per
  circle, with lock-state greyed out
- hooks: useAgentIdentity, useCircleOfficerLocks, useSetCircleFacilitator,
  useSetCircleSecretary, useSetProposalMaxAge (clamped to [1h, 30d])
- PublicOrgView / PublicProposalView / OpenProposalsPanel render
  tensionText when present, hash fallback otherwise

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Skanislav
Skanislav merged commit 88ecc0b into dev Apr 24, 2026
6 checks passed
@Skanislav
Skanislav deleted the fix/audit-remediations-and-optimizations branch April 24, 2026 10:55
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.

1 participant