Skip to main content

Green Goods Ontology

The formal specification of the Green Goods shared vocabulary: the entities the protocol tracks, the controlled vocabularies each layer spells its own way, the EAS schemas, the constraints the contracts enforce, and the lifecycle state machines. The source of truth is the machine-readable sidecar packages/shared/src/ontology/green-goods-ontology.json; this page is generated from it and CI fails when either drifts from the code.

Entities

EntityStatusDefinitionLayers
GardenliveA community of gardeners rooted in a place, represented on-chain as an ERC-721 garden token whose ERC-6551 token-bound account holds the garden's treasury, role Hats, and metadata.contracts · indexer (Garden) · shared · docs
ActionliveA documented activity a gardener can perform — the unit of work template (e.g. "Plant native species", "Remove invasive growth").contracts · indexer (Action) · shared · docs
WorkliveOne documented instance of an Action performed by a gardener — media, notes, and metadata submitted as an EAS Work attestation for operator review; approval records a separate Work Approval attestation.contracts · shared · docs
AssessmentliveAn up-front baseline and strategy for a garden — domain, diagnosis, SMART outcome targets, selected Actions, reporting period — authored by an evaluator or operator before work begins, mirrored to a Karma GAP milestone when that module is active; explicitly not a review of submitted Work (that is Work Approval).contracts · shared · docs
HypercertliveAn on-chain claim of impact bundling approved Work into a fractional impact certificate. Funders hold fractions; gardeners hold contribution credit.contracts · indexer (Hypercert) · shared · docs
VaultliveThe garden's treasury. Funders deposit; the garden's Tokenbound Account holds; yield splits flow to operators / gardeners / community per configured ratios.contracts · indexer (GardenVault) · shared · docs
Cookie JarliveA garden-scoped emergency or discretionary fund with rate-limited withdrawals. Allowlisted members can claim within the configured cap.contracts · indexer (CampaignCookieJar) · shared · docs
AttestationliveAn EAS (Ethereum Attestation Service) record. Used for Work submissions, Assessment outcomes, and other off-chain-verifiable claims.contracts · shared · docs
HatliveA Hats Protocol role token. Determines on-chain authority — operator hats can approve Work; gardener hats can submit Work; evaluator hats can attest.contracts · indexer (Garden) · shared · docs
SeasonliveA bounded period (typically a quarter) during which a garden runs a coordinated set of Actions and Assessments. Pacing primitive — never a countdown.docs
Commitment PoolspecA garden-anchored (or protocol root-garden) pool that registers, curates, and reconciles commitments under a charter.spec
Commitment CyclespecA bounded run of a pool — a Season or Campaign — seeded with timing and an immutable six-role allocation snapshot at open.spec
CommitmentspecA module-native promise record (offer or request) with one accountable lead, an optional contributor roster, repeatable action requirements, direction-aware confirmation, unit accounting in a non-transferable register, and evidence/work linkage — deliberately not an EAS attestation.spec
Commitment ContributorspecA person on a commitment's roster whose approved Work or confirmed evidence can earn Hypercert recognition and a contributor payout; one roster member is the accountable lead.spec
Commitment Payout PlanspecA garden-managed split of a fulfilled commitment's declared support into an explicit garden-retained amount and contributor child payouts. Its complete recognition vector is hash-bound, payment weights derive from amounts, and explicit finalization freezes it before dispatch.spec

Personas

PersonaHatDefinition
GardenergardenerA person doing regenerative Work in a garden. Submits Work, holds gardener Hats, receives credit toward Hypercerts and yield splits.
OperatoroperatorA person who runs a garden — creates Actions, approves Work, configures Vault and Hat hierarchy. Holds operator Hats.
EvaluatorevaluatorA person who verifies submitted Work, makes Assessments, and attests impact. Often domain experts (botanists, soil scientists, community elders).
FunderfunderA person or org who deposits into a garden's Vault, holds Hypercert fractions, receives yield distributions per configured splits.
Community MembercommunityA local resident affected by a Garden's Work. Signals or attests that Work exists and is healthy, and helps prioritize future Actions through public signal and conviction flows.

The on-chain hat tree has six roles; the Owner hat carries full garden control but has no dedicated persona — owners act through the Operator surfaces.

Vocabularies

Each vocabulary has one canonical member list and a declared expected spelling per layer. The drift gate compares every representation against its source file; deviations are either declared here (layer conventions like the indexer's UNKNOWN sentinel) or recorded in the burn-down baseline.

capital

Eight Forms of Capital used to tag actions and assessments by the kind of value they create.

Canonical members: SOCIAL (0) · MATERIAL (1) · FINANCIAL (2) · LIVING (3) · INTELLECTUAL (4) · EXPERIENTIAL (5) · SPIRITUAL (6) · CULTURAL (7)

RepresentationLayerSourceExpected membersNote
soliditysoliditypackages/contracts/src/registries/Action.sol · CapitalSOCIAL, MATERIAL, FINANCIAL, LIVING, INTELLECTUAL, EXPERIENTIAL, SPIRITUAL, CULTURAL
indexerindexerpackages/indexer/schema.graphql · CapitalSOCIAL, MATERIAL, FINANCIAL, LIVING, INTELLECTUAL, EXPERIENTIAL, SPIRITUAL, CULTURAL, UNKNOWNUNKNOWN is the indexer's permanent fallback sentinel for unmapped on-chain values — declared, not drift.
shared-enumsharedpackages/shared/src/types/domain.ts · CapitalSOCIAL=0, MATERIAL=1, FINANCIAL=2, LIVING=3, INTELLECTUAL=4, EXPERIENTIAL=5, SPIRITUAL=6, CULTURAL=7
capital-typesharedpackages/shared/src/types/hypercerts.ts · CapitalTypesocial, material, financial, living, intellectual, experiential, spiritual, culturalOrdered deliberately: the union is declared here in canonical machine order because index-based bridges between Capital and CapitalType lists are a live bug risk. The current file deviates (living-first presentational order) — baselined until reordered or a mapping function lands.
  • Mapping capital-enum-to-capital-type (shared-enum → capital-type; explicit; total; bijective): SOCIAL → social, MATERIAL → material, FINANCIAL → financial, LIVING → living, INTELLECTUAL → intellectual, EXPERIENTIAL → experiential, SPIRITUAL → spiritual, CULTURAL → cultural.
    • Code anchor: none — no runtime mapping function exists yet.
    • No runtime mapping function exists yet — see known_issues.missing-capital-mapping-fn.

domain

Category of regenerative work — where the work happens. Four production domains; a domain is neither an outcome nor a capital.

Canonical members: SOLAR (0) · AGRO (1) · EDU (2) · WASTE (3)

RepresentationLayerSourceExpected membersNote
soliditysoliditypackages/contracts/src/registries/Action.sol · DomainSOLAR, AGRO, EDU, WASTE
indexerindexerpackages/indexer/schema.graphql · DomainSOLAR, AGRO, EDU, WASTE, UNKNOWNUNKNOWN is the indexer's permanent fallback sentinel — declared, not drift.
shared-enumsharedpackages/shared/src/types/domain.ts · DomainSOLAR=0, AGRO=1, EDU=2, WASTE=3
action-domainsharedpackages/shared/src/types/hypercerts.ts · ActionDomainsolar, waste, agroforestry, education, mutual_creditLong-form lowercase spellings used in hypercert metadata. mutual_credit is a product concept ahead of the on-chain enum (deferred Domain 5) — declared, not drift.
slug-prefixsharedpackages/shared/src/hooks/action/useActionForm.ts · DOMAIN_SLUG_PREFIXsolar, agro, edu, wasteShort lowercase prefixes baked into immutable on-chain action slugs (agro., edu.).
  • Mapping domain-to-action-domain (solidity → action-domain; explicit; total; unmapped on the right: mutual_credit): SOLAR → solar, AGRO → agroforestry, EDU → education, WASTE → waste.

    • Code anchor: packages/shared/src/modules/data/hypercerts-filters.ts
  • Mapping action-domain-vs-slug-prefix (action-domain → slug-prefix; identity; partial; unmapped on the left: mutual_credit): identity (same spelling on both sides).

    • Code anchor: none — no runtime mapping function exists yet.
    • The two lowercase spellings of the same domain must converge on one word per member; agroforestry/education vs agro/edu currently diverge — baselined.

garden-role

The six per-garden Hats roles that gate every protocol permission.

Canonical members: Gardener (0) · Evaluator (1) · Operator (2) · Owner (3) · Funder (4) · Community (5)

RepresentationLayerSourceExpected membersNote
soliditysoliditypackages/contracts/src/interfaces/IHatsModule.sol · GardenRoleGardener, Evaluator, Operator, Owner, Funder, Community
shared-idssharedpackages/shared/src/utils/blockchain/garden-roles.ts · GARDEN_ROLE_IDSgardener=0, evaluator=1, operator=2, owner=3, funder=4, community=5Key order and numeric ids must track the Solidity enum exactly — these ids go into contract calls.

transfer-restriction

Garden NFT transfer mode.

Canonical members: Unrestricted (0) · OwnerOnly (1) · Locked (2)

RepresentationLayerSourceExpected membersNote
soliditysoliditypackages/contracts/src/tokens/Garden.sol · TransferRestrictionUnrestricted, OwnerOnly, Locked

badge-rule

GreenWill badge eligibility rule kinds, proven from on-chain state at claim time.

Canonical members: None (0) · Hat (1) · WorkAttestation (2) · VaultShares (3)

RepresentationLayerSourceExpected membersNote
soliditysoliditypackages/contracts/src/registries/GreenWill.sol · BadgeRuleNone, Hat, WorkAttestation, VaultShares

ens-name-type

Kind of *.greengoods.eth subname being registered.

Canonical members: Gardener (0) · Garden (1)

RepresentationLayerSourceExpected membersNote
soliditysoliditypackages/contracts/src/registries/ENS.sol · NameTypeGardener, Garden

weight-scheme

Conviction-voting weight scheme selected immutably at garden mint.

Canonical members: Linear (0) · Exponential (1) · Power (2)

RepresentationLayerSourceExpected membersNote
soliditysoliditypackages/contracts/src/interfaces/IGardensModule.sol · WeightSchemeLinear, Exponential, Power
indexerindexerpackages/indexer/schema.graphql · WeightSchemeLINEAR, EXPONENTIAL, POWER
sharedsharedpackages/shared/src/types/gardens-community.ts · WeightSchemeLinear=0, Exponential=1, Power=2Genuine raw uint8 decode path (Number(weightSchemeRaw) as WeightScheme) — ordering is load-bearing and correct.

signal-pool-type

Name collision

Solidity carries two unrelated PoolType enums: the live Gardens V2 signal-pool vocabulary (signal-pool-type, ActionSignal/HypercertSignal) and the commitment-pooling anchor vocabulary (commitment-pool-type, Garden/Protocol). They are separate vocabularies in this ontology — never merge or cross-map them.

Kind of Gardens V2 conviction signal pool attached to a garden. Distinct from the commitment-pooling PoolType (Garden/Protocol) — same Solidity identifier, different vocabulary; never merge them.

Canonical members: ActionSignal (0) · HypercertSignal (1)

RepresentationLayerSourceExpected membersNote
soliditysoliditypackages/contracts/src/interfaces/IGardensModule.sol · PoolTypeActionSignal, HypercertSignal
indexerindexerpackages/indexer/schema.graphql · PoolTypeACTION_SIGNAL, HYPERCERT_SIGNALCurrently {HYPERCERT, ACTION} — inverted vs chain and referenced by zero entity fields (dead surface). Baselined; fix direction is deletion or correction alongside the shared enum.
sharedsharedpackages/shared/src/types/gardens-community.ts · PoolTypeActionSignal=0, HypercertSignal=1Currently {Hypercert = 0, Action = 1} — inverted vs chain. Verified latent, not live: pool types are assigned by address identity (annotateGardenSignalPools), never decoded from a raw uint8. Baselined with a mandatory blast-radius re-check before burn-down.

vault-event-type

Vault history event kinds recorded by the indexer.

Canonical members: DEPOSIT · WITHDRAW · HARVEST · EMERGENCY_PAUSED

RepresentationLayerSourceExpected membersNote
indexerindexerpackages/indexer/schema.graphql · VaultEventTypeDEPOSIT, WITHDRAW, HARVEST, EMERGENCY_PAUSED
sharedsharedpackages/shared/src/types/vaults.ts · VaultEventTypeDEPOSIT, WITHDRAW, HARVEST, EMERGENCY_PAUSED

hypercert-status

Lifecycle status of an indexed hypercert.

Canonical members: ACTIVE · CLAIMED · SOLD · UNKNOWN

RepresentationLayerSourceExpected membersNote
indexerindexerpackages/indexer/schema.graphql · HypercertStatusACTIVE, CLAIMED, SOLD, UNKNOWNSOLD is declared but never assigned by any handler (marketplace is outside the indexing boundary).
sharedsharedpackages/shared/src/types/hypercerts.ts · HypercertStatusactive, claimed, sold, unknown

work-display-status

Canonical display status for work items across the UI — protocol states plus client-derived offline/sync states.

Canonical members: approved · rejected · pending · syncing · uploading · sync_failed · offline

RepresentationLayerSourceExpected membersNote
shared-unionsharedpackages/shared/src/types/domain.ts · WorkDisplayStatusapproved, rejected, pending, syncing, uploading, sync_failed, offline
enhanced-work-approvalsharedpackages/shared/src/hooks/work/useWorkApprovals.ts · EnhancedWorkApproval.statusapproved, rejected, pending, syncing, uploading, sync_failed, offlineDeclared as the canonical union; the current file carries a divergent five-value list (failed instead of sync_failed; missing uploading/offline) — baselined.
offline-work-itemsharedpackages/shared/src/types/offline.ts · OfflineWorkItem.statusapproved, rejected, pending, syncing, uploading, sync_failed, offlineDeclared as the canonical union; the current file carries a divergent four-value list — baselined pending status-union consolidation.
hypercert-sync-statussharedpackages/shared/src/hooks/hypercerts/useHypercerts.ts · HypercertSyncStatusapproved, rejected, pending, syncing, uploading, sync_failed, offlineDeclared as the canonical union; the current file carries a divergent four-value sync list — baselined pending status-union consolidation.

cynefin-phase

Cynefin complexity phase classifying an assessment's operating environment.

Canonical members: CLEAR (0) · COMPLICATED (1) · COMPLEX (2) · CHAOTIC (3)

RepresentationLayerSourceExpected membersNote
sharedsharedpackages/shared/src/types/domain.ts · CynefinPhaseCLEAR=0, COMPLICATED=1, COMPLEX=2, CHAOTIC=3

confidence

Four-value verification confidence carried on work approvals (on-chain uint8, bounded to 3).

Canonical members: NONE (0) · LOW (1) · MEDIUM (2) · HIGH (3)

RepresentationLayerSourceExpected membersNote
sharedsharedpackages/shared/src/types/domain.ts · ConfidenceNONE=0, LOW=1, MEDIUM=2, HIGH=3

verification-method

Verification method bitmask flags on work approvals (uint8, bounded to 15).

Canonical members: HUMAN · IOT · ONCHAIN · AGENT

Values are explicit (not index-derived) for this vocabulary.

RepresentationLayerSourceExpected membersNote
sharedsharedpackages/shared/src/types/domain.ts · VerificationMethodHUMAN=1, IOT=2, ONCHAIN=4, AGENT=8Bitmask members declared with shift expressions (1 << n) in source; the extractor evaluates them.

action-type

Action archetype tags used in hypercert metadata and filtering.

Canonical members: hub_session · workshop · node_deployment · cleanup · recycling · composting · planting · nursery · maintenance · training · certification · commitment · exchange

RepresentationLayerSourceExpected membersNote
sharedsharedpackages/shared/src/types/hypercerts.ts · ActionTypehub_session, workshop, node_deployment, cleanup, recycling, composting, planting, nursery, maintenance, training, certification, commitment, exchange

job-kind

Offline job-queue mutation kinds (the write-ahead ledger's vocabulary).

Canonical members: work · approval

RepresentationLayerSourceExpected membersNote
sharedsharedpackages/shared/src/types/job-queue.ts · JobKindMapwork, approval

Commitment Pooling Vocabularies (spec — not deployed)

Locked vocabulary from the commitment-pooling contract spec, encoded ahead of implementation so the August lanes consume one canonical definition. No code cross-checks run until the planned anchors land; the gate then forces each entry to flip to live.

commitment-pool-type

Name collision

Solidity carries two unrelated PoolType enums: the live Gardens V2 signal-pool vocabulary (signal-pool-type, ActionSignal/HypercertSignal) and the commitment-pooling anchor vocabulary (commitment-pool-type, Garden/Protocol). They are separate vocabularies in this ontology — never merge or cross-map them.

Commitment-pooling pool anchor kind. Name-collides with the live Gardens V2 signal-pool PoolType — the sidecar keeps them as separate vocabularies on purpose.

Canonical members: Garden (0) · Protocol (1)

Spec-only — planned anchor packages/contracts/src/interfaces/ICommitmentPoolingModule.sol · PoolType. The drift gate flags arrival so the status flips to live with declared representations.

pool-state

Commitment pool lifecycle — every state is on-chain.

Canonical members: None (0) · NotReady (1) · Ready (2) · Open (3) · Paused (4) · Closed (5) · Composted (6)

Spec-only — planned anchor packages/contracts/src/interfaces/ICommitmentPoolingModule.sol · PoolState. The drift gate flags arrival so the status flips to live with declared representations.

cycle-type

Cycle kinds: one open Season per pool; Campaigns may overlap.

Canonical members: Season (0) · Campaign (1)

Spec-only — planned anchor packages/contracts/src/interfaces/ICommitmentPoolingModule.sol · CycleType. The drift gate flags arrival so the status flips to live with declared representations.

cycle-state

On-chain cycle states; Draft lives in app IndexedDB and InProgress/Reviewing are derived from events.

Canonical members: None (0) · Seeded (1) · Open (2) · Reconciled (3) · Composted (4) · Cancelled (5)

Derived states (never stored): Draft · InProgress · Reviewing

Spec-only — planned anchor packages/contracts/src/interfaces/ICommitmentPoolingModule.sol · CycleState. The drift gate flags arrival so the status flips to live with declared representations.

commitment-direction

Whether a commitment offers capacity or requests it; drives the direction-aware default confirmer.

Canonical members: Offer (0) · Request (1)

Spec-only — planned anchor packages/contracts/src/interfaces/ICommitmentPoolingModule.sol · CommitmentDirection. The drift gate flags arrival so the status flips to live with declared representations.

commitment-type

Commitment archetypes; DomainImpact keeps the full Work → WorkApproval path, the others confirm via counterparty.

Canonical members: DomainImpact (0) · SupportService (1) · SeasonCampaign (2) · StewardCaptured (3)

Spec-only — planned anchor packages/contracts/src/interfaces/ICommitmentPoolingModule.sol · CommitmentType. The drift gate flags arrival so the status flips to live with declared representations.

commitment-state

On-chain commitment states; Draft is app-side and Active/EvidenceSubmitted/PartiallyApproved/Reconciled are derived from module events.

Canonical members: None (0) · Offered (1) · Requested (2) · Accepted (3) · ReadyForConfirmation (4) · Fulfilled (5) · Cancelled (6) · Expired (7) · Disputed (8)

Derived states (never stored): Draft · Active · EvidenceSubmitted · PartiallyApproved · Reconciled

Spec-only — planned anchor packages/contracts/src/interfaces/ICommitmentPoolingModule.sol · CommitmentState. The drift gate flags arrival so the status flips to live with declared representations.

claim-type

Immutable claimant-eligibility class set at commitment creation; runtime claim kind must equal it.

Canonical members: Garden (0) · Individual (1)

Spec-only — planned anchor packages/contracts/src/interfaces/ICommitmentPoolingModule.sol · ClaimType. The drift gate flags arrival so the status flips to live with declared representations.

contributor-policy

How contributor membership is established before the commitment roster freezes.

Canonical members: Open (0) · LeadManaged (1)

Spec-only — planned anchor packages/contracts/src/interfaces/ICommitmentPoolingModule.sol · ContributorPolicy. The drift gate flags arrival so the status flips to live with declared representations.

claim-mode

Whether claiming transitions immediately (Open) or awaits operator acceptance (ApprovalGated).

Canonical members: Open (0) · ApprovalGated (1)

Spec-only — planned anchor packages/contracts/src/interfaces/ICommitmentPoolingModule.sol · ClaimMode. The drift gate flags arrival so the status flips to live with declared representations.

dispute-resolution

Steward-only dispute outcomes; RestorePrevious replays the stored pre-dispute state.

Canonical members: RestorePrevious (0) · Fulfilled (1) · Cancelled (2) · Expired (3)

Spec-only — planned anchor packages/contracts/src/interfaces/ICommitmentPoolingModule.sol · DisputeResolution. The drift gate flags arrival so the status flips to live with declared representations.

reward-rail

Reward reference rail: ArbitrumExternal records operator-paid jar/treasury rewards; CeloSettlement is consumed only by the SettlementModule.

Canonical members: None (0) · ArbitrumExternal (1) · CeloSettlement (2)

Spec-only — planned anchor packages/contracts/src/interfaces/ICommitmentPoolingModule.sol · RewardRail. The drift gate flags arrival so the status flips to live with declared representations.

accounting-state

CommitmentRegister unit-class accounting states (non-transferable, ERC-1155-style).

Canonical members: Registered (0) · Committed (1) · Released (2) · Fulfilled (3)

Spec-only — planned anchor packages/contracts/src/interfaces/ICommitmentRegister.sol · AccountingState. The drift gate flags arrival so the status flips to live with declared representations.

commitment-payout-plan-status

Derived progress of a frozen commitment payout plan across its contributor child disbursements.

Canonical members: Draft (0) · Pending (1) · Partial (2) · Complete (3) · Failed (4)

Spec-only — planned anchor packages/contracts/src/interfaces/ISettlementModule.sol · PayoutPlanStatus. The drift gate flags arrival so the status flips to live with declared representations.

EAS Schemas

assessment — Green Goods Assessment v2

status: live · revocable: false · resolver: packages/contracts/src/resolvers/Assessment.sol

FieldType
titlestring
descriptionstring
assessmentConfigCIDstring
domainuint8
startDateuint256
endDateuint256
locationstring

work — Green Goods Work Submission

status: live · revocable: false · resolver: packages/contracts/src/resolvers/Work.sol

FieldType
actionUIDuint256
titlestring
feedbackstring
metadatastring
mediastring[]

workApproval — Green Goods Work Approval

status: live · revocable: false · resolver: packages/contracts/src/resolvers/WorkApproval.sol

FieldType
actionUIDuint256
workUIDbytes32
approvedbool
feedbackstring
confidenceuint8
verificationMethoduint8
reviewNotesCIDstring

badge — GreenGoodsBadge

status: live · revocable: true · resolver: none

Registered via the standalone badge-schemas path outside config/schemas.json; the only revocable Green Goods schema, with no resolver.

FieldType
badgeTypestring
recipientaddress
earnedAtuint40
evidenceUristring
tieruint8

assessmentV3 — Green Goods Assessment v3

status: spec · revocable: false · resolver: none

Assessment v2 fields plus assessmentKind, cycleId, and baselineUID; one of exactly two new EAS registrations in the commitment-pooling track.

FieldType
titlestring
descriptionstring
assessmentConfigCIDstring
domainuint8
startDateuint256
endDateuint256
locationstring
assessmentKinduint8
cycleIduint256
baselineUIDbytes32

communityTestimony — Green Goods Community Testimony

status: spec · revocable: false · resolver: none

Community-Hat-gated testimony attached to a commitment; the second of exactly two new EAS registrations.

FieldType
commitmentIduint256
titlestring
testimonyCIDstring

need — Green Goods Need

status: spec · revocable: true · planned resolver: CommunityNeedsResolver

Root Needs use EAS recipient as the canonical garden, refUID zero, and expirationTime zero. CommunityNeedsResolver authorizes the attester through the recipient garden's Community role.

FieldType
statementCIDstring
desiredOutcomeCIDstring
horizonuint8
mediaCIDstring

needSignal — Green Goods Need Signal

status: spec · revocable: true · planned resolver: CommunityNeedsResolver

Child signal records use EAS recipient as the garden, refUID as the exact live same-garden Need, and expirationTime zero. Readers derive one current direction per attester through the canonical latest-winner rule.

FieldType
supportbool

needStatus — Green Goods Need Status

status: spec · revocable: false · planned resolver: CommunityNeedsResolver

Operator-authored child moderation records use EAS recipient as the garden, refUID as the exact live same-garden Need, and expirationTime zero. mergedIntoNeedUID remains custom data because it is a second Need relationship.

FieldType
statusuint8
domainsuint8[]
mergedIntoNeedUIDbytes32
noteCIDstring

fundingAttribution — Green Goods Funding Attribution

status: spec · revocable: false · planned resolver: FundingAttributionResolver

Ungated child funding records use EAS recipient as the garden, refUID as the exact live same-garden Need, and expirationTime zero. FundingAttributionResolver remains separate from CommunityNeedsResolver and the joined reader verifies canonical receipts before display.

FieldType
chainIduint256
txHashbytes32
tokenaddress
amountuint256
railuint8

Constraints

Cross-layer invariants and where they are enforced. This catalog is documentation-grade: the drift gate verifies the anchors exist, not the semantics — the contracts and their tests own the semantics.

  • domain-closed-set · closed-set · live — Action domains form a closed four-member set; resolvers reject domain values above 3 and garden domain masks are validated as 4-bit. (enforced at: packages/contracts/src/registries/Action.sol:28-34, packages/contracts/src/resolvers/Assessment.sol:134-136)
  • work-attester-role · domain-range · live — A Work attestation's attester must be a gardener or operator of the recipient garden, and the referenced action must exist, be started, not be expired, and belong to a domain enabled on that garden. (enforced at: packages/contracts/src/resolvers/Work.sol:87-139)
  • approval-operator-only · domain-range · live — Only an operator of the garden may attest a Work Approval, and the approval's actionUID and recipient must match the referenced Work attestation. (enforced at: packages/contracts/src/resolvers/WorkApproval.sol:115-177)
  • approval-no-self-attestation · disjoint · live — The approver and the work attester must be different accounts — self-approval reverts. (enforced at: packages/contracts/src/resolvers/WorkApproval.sol:153-156)
  • assessment-author-role · domain-range · live — An Assessment attester must be an evaluator or operator of the recipient garden. (enforced at: packages/contracts/src/resolvers/Assessment.sol:118-122)
  • yield-split-sum · sum · live — The three-way yield split (CookieJar / Hypercert fractions / Juicebox) must sum to exactly 10000 bps. (enforced at: packages/contracts/src/resolvers/Yield.sol:107,373)
  • garden-nft-transfer-restriction · non-transferable · live — Garden NFT transfers obey the TransferRestriction mode (Unrestricted / OwnerOnly / Locked); minting is always allowed. (enforced at: packages/contracts/src/tokens/Garden.sol:43-48,513-518)
  • resolver-schema-pinning · existence · live — Each core resolver validates that incoming attestations use its pinned schema UID. (enforced at: packages/contracts/src/resolvers/Work.sol:87-95, packages/contracts/src/resolvers/WorkApproval.sol:115-123, packages/contracts/src/resolvers/Assessment.sol:98-106)
    • ⚠️ Hole: Schema validation is skipped while the stored schemaUID is zero (the deployment window) — a documented gap the commitment-pooling spec explicitly refuses to inherit (its module deploys fail-closed). (packages/contracts/src/resolvers/Work.sol:60-62, packages/contracts/src/resolvers/WorkApproval.sol:81-83, packages/contracts/src/resolvers/Assessment.sol:71-73)
  • pooling-allocation-bps-sum · sum · spec — The six-role allocation snapshot stored at cycle open must sum to exactly 10000 bps and is immutable for the cycle. (enforced at: .plans/active/commitment-pooling/contract-spec.md)
  • pooling-provider-confirmation-disjoint · disjoint · spec — Every member of a commitment's accountable lead/contributor team is excluded from every fulfillment-confirmation path, including the steward fallback; confirmation defaults are direction-aware (Offer → recipient, Request → creator). (enforced at: .plans/active/commitment-pooling/contract-spec.md)
  • pooling-recognition-allocation-sum · sum · spec — The gardener-class recognition budget is fully allocated only after every fulfilled commitment has an eligible contributor: equal budget per fulfilled commitment, then the immutable cycle-open RecognitionPolicy allocates its equal-participation and verified-contribution components through separate deterministic remainder passes before the row results are added. The protocol default and immutable cycle-less preset are 20% equal / 80% verified, but an opened cycle may select any two values summing to 10000 bps. Zero eligible contributors block certificate expansion; there is no lead fallback. (enforced at: .plans/active/commitment-pooling/contract-spec.md)
  • pooling-payout-plan-conservation · sum · spec — An explicitly finalized commitment payout plan conserves the declared support amount exactly: garden-retained amount plus all contributor child amounts equals the parent amount. A zero-child all-retained plan completes at finalization without a transfer. (enforced at: .plans/active/commitment-pooling/settlement-spec.md)
  • pooling-payout-plan-integrity · functional · spec — Each fulfilled commitment has at most one stable payout-plan pointer. The complete recognition vector matches its snapshot hash, payment weights derive from the atomic amount vector, finalization precedes dispatch, and child or batch cancellation never clears the parent pointer. (enforced at: .plans/active/commitment-pooling/settlement-spec.md)
  • pooling-one-open-season · functional · spec — A pool may have at most one open Season at a time (O(1) openSeasonCycleId guard); Campaigns may overlap freely. (enforced at: .plans/active/commitment-pooling/contract-spec.md)
  • commitment-register-non-transferable · non-transferable · spec — CommitmentRegister unit classes are non-transferable by construction — no transfer, approval, or custody surface; balances move only via the module. (enforced at: .plans/active/commitment-pooling/contract-spec.md)
  • needs-eas-envelope-reference · domain-range · spec — All four Needs schemas use EAS recipient as the canonical garden and expirationTime zero; a Need is a root with refUID zero, while NeedSignal, NeedStatus, and FundingAttribution use refUID to reference an exact live same-garden Need. (enforced at: .plans/active/community-interface/spec.md)
  • need-signal-latest-winner · functional · spec — For each Need and attester, readers first select the greatest unsigned (timeCreated, uid) NeedSignal tuple and then apply revocation and expiry; a revoked or expired winner clears the signal without restoring an older record, and support and non-support remain separate counts. (enforced at: .plans/active/community-interface/spec.md)
  • needs-resolver-trust-boundaries · closed-set · spec — Exactly four Needs schemas route through two resolvers: CommunityNeedsResolver accepts only Need, NeedSignal, and NeedStatus with schema-specific Community or Operator authorization, while the ungated FundingAttribution schema routes through FundingAttributionResolver; unknown schema branches fail closed. (enforced at: .plans/active/community-interface/spec.md)

State Machines

work-display-status

The union in types/domain.ts documents itself as the single source of truth: pending/approved/rejected reflect protocol state; syncing/uploading/sync_failed/offline are client-derived from the offline job queue.

StateStorage
pendingprotocol
approvedprotocol
rejectedprotocol
syncingclient-derived
uploadingclient-derived
sync_failedclient-derived
offlineclient-derived

Commitment pooling (spec — not deployed)

Transcribed from the locked contract spec: "on-chain" means a named module function performs the transition and emits the listed event; "derived" means the indexer/app computes the state from events and the chain never stores it.

commitment-pool

Every pool state is on-chain; transitions are rare operator-console actions.

StateStorage
NotReadyon-chain
Readyon-chain
Openon-chain
Pausedon-chain
Closedon-chain
Compostedon-chain
FromToLayerMechanism
(create)NotReadyon-chainonGardenMinted (GardenToken-only, idempotent) or registerPool → PoolRegistered
NotReadyReadyon-chainmarkPoolReady — requires non-empty charter CID and a non-zero provider open-commitment cap → PoolReady
ReadyOpenon-chainopenPool → PoolOpened
OpenPausedon-chainpausePool with mandatory reasonCID → PoolPaused; resumePool returns to Open
Open | PausedClosedon-chainclosePool → PoolClosed
ClosedCompostedon-chaincompostPool → PoolComposted
CompostedReady | Openon-chainreopenPool(toOpen) → PoolReopened

commitment-cycle

One open Season per pool (openSeasonCycleId guard); Campaigns overlap freely. Succession between cycles is derived by pool ordering — no on-chain predecessor pointer.

StateStorage
Draftoff-chain
Seededon-chain
Openon-chain
InProgressderived
Reviewingderived
Reconciledon-chain
Compostedon-chain
Cancelledon-chain
FromToLayerMechanism
DraftSeededon-chainseedCycle(poolId, cycleType, startTime, endTime, metadataCID) → CycleSeeded; no allocation stored yet
SeededOpenon-chainopenCycle(cycleId, allocation, recognitionPolicy) — six-role allocation bps and two-part recognition bps each sum to 10000, both store immutably → CycleOpened
OpenInProgressderivedfirst CommitmentAccepted for the cycle OR block time ≥ startTime
InProgressReviewingderivedblock time > endTime, OR all cycle commitments terminal or ReadyForConfirmation; new evidence/work flips back
ReviewingReconciledon-chaincloseCycle (the reconcile act) requires liveCommitmentCount = 0 → CycleClosed; commitment-level Reconciled derives from this event
ReconciledCompostedon-chaincompostCycle → CycleComposted
Seeded | OpenCancelledon-chaincancelCycle(reasonCID) requires liveCommitmentCount = 0 → CycleCancelled; Draft is discarded off-chain

commitment

Direction-aware fulfillment: the party receiving the team's work confirms by default (Offer → recipient, Request → creator); every lead/contributor self-confirmation path is blocked; evidence/Work credit records only while Accepted and unfrozen; the contributor roster and credit ledger freeze atomically on the transition to ReadyForConfirmation or before a direct Fulfilled dispute resolution; Ready requires pre-freeze totalVerifiedCredits > 0, while recognition additionally requires Fulfilled plus an opened cycle policy or the immutable cycle-less 20/80 default; disputes restore an explicitly stored prior state.

StateStorage
Draftoff-chain
Offeredon-chain
Requestedon-chain
Acceptedon-chain
Activederived
EvidenceSubmittedderived
PartiallyApprovedderived
ReadyForConfirmationon-chain
Fulfilledon-chain
Reconciledderived
Cancelledon-chain
Expiredon-chain
Disputedon-chain
FromToLayerMechanism
DraftOffered | Requestedon-chaincreateCommitment → CommitmentCreated (direction sets the initial state)
Offered | RequestedAcceptedon-chainclaimCommitment (runtime kind must equal immutable claimType; Open mode transitions immediately, ApprovalGated waits for operator acceptClaim) → CommitmentAccepted; register records committed units
AcceptedActivederivedfirst WorkLinked or EvidenceAttached after acceptance
ActiveEvidenceSubmittedderivedany EvidenceAttached or WorkLinked event
EvidenceSubmittedPartiallyApprovedderivedApprovedWorkCounted with some requirement counters below their required counts
ReadyForConfirmationon-chainautomatic once every repeatable action requirement is met and any declared assessment attached; submitForConfirmation for evidence-only types requires evidenceCount ≥ 1; steward markReadyForConfirmation with reason; every path requires an Open cycle when scoped or the immutable cycle-less 20/80 policy plus pre-freeze totalVerifiedCredits > 0; contributor roster and credit ledger freeze atomically before the ready event
ReadyForConfirmationFulfilledon-chainconfirmFulfillment by named confirmer or direction-aware default; threshold N → CommitmentFulfilled; register converts units; every lead/contributor on the already-frozen roster is excluded from every confirmation path
FulfilledReconciledderivedCycleClosed for the commitment's cycle (or PoolClosed when cycle-less)
Cancelledon-chaincancelCommitment(reasonCID) — creator or steward pre-acceptance, steward-only after; Accepted releases committed units
Expiredon-chainexpireCommitment — permissionless once past dueDate (or cycle endTime); releases still-committed units
Accepted | ReadyForConfirmation | ExpiredDisputedon-chainraiseDispute(reasonCID) — module stores the exact prior state in preDisputeState → CommitmentDisputed
Disputedprevious | Fulfilled | Cancelled | Expiredon-chainresolveDispute steward-only; RestorePrevious replays preDisputeState; an Expired prior state can never resolve Fulfilled; a direct Fulfilled resolution requires an available recognition policy and verified contributor, then freezes an unfrozen roster before DisputeResolved

Known Issues

  • report-orphan-term — v1-0.mdx §16.1 defines a "Report" entity (aggregated bundle of approved work for grants/Hypercert minting) that is absent from the canonical entity set, the ERD, and the code. Formalize or retire the term when the reporting feature is actually designed — it overlaps Hypercert bundling today. (docs/docs/builders/specs/v1-0.mdx)
  • erd-stale-assessment-fields — The ERD's GardenAssessment shape lists only notes and mediaURIs, while the shipped assessment carries the full strategy kernel (domain, diagnosis, SMART outcomes, selected action UIDs, reporting period, assessmentConfigCID). (docs/docs/builders/architecture/erd.mdx)
  • missing-capital-mapping-fn — No runtime mapping function exists between the numeric Capital enum and the lowercase CapitalType union; index-based bridges are unsafe because the two declared orders currently differ. (packages/shared/src/types/domain.ts, packages/shared/src/types/hypercerts.ts)

Deliberately excluded from v1

  • Impact-axes taxonomy — canon is maintained outside the repo; this public file carries only the four production action domains.
  • ModuleDependency and ModuleSchemaKind from the commitment-pooling spec — module wiring plumbing, not domain vocabulary.

How this page stays honest

bun run check:ontology cross-checks the sidecar against the Solidity enums, the indexer GraphQL schema, the shared TypeScript vocabularies, the EAS schema config, and the glossary tables on every relevant change. Known drift lives in scripts/data/ontology-drift-baseline.json with an owner, an expiry, and a note — new drift fails CI immediately, and fixed drift fails until its baseline entry is deleted. To change the ontology, edit the sidecar and run bun run ontology:generate.