Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions docs/integrators/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,19 @@ The guides are complementary to:

## Index

| Guide | Mechanism | Mechanism type | Status |
|---|---|---|---|
| [m001-enh.md](m001-enh.md) | Credit Class Approval Voting | Scoring (0-1000 composite, 3-way recommendation) | ✅ Written |
| [m012.md](m012.md) | Fixed Cap Dynamic Supply | Supply dynamics (BigInt arithmetic, phase-gated multipliers) | ✅ Written |
| [m014.md](m014.md) | Authority Validator Governance | Validator performance (re-normalized weighted score) | ✅ Written |
| m008.md | Data Attestation Bonding | Scoring | ⏳ TODO — follow m001-enh template |
| m009.md | Service Provision Escrow | Dual-guard scoring (score AND confidence) | ⏳ TODO — follow m001-enh template |
| m010.md | Reputation Signal | Stake-weighted endorsement + challenge lifecycle | ⏳ TODO |
| m011.md | Marketplace Curation | 7-factor quality scoring + collections | ⏳ TODO |
| m013.md | Value-Based Fee Routing | Fee computation + pool distribution | ⏳ TODO — follow m012 template |
| m015.md | Contribution-Weighted Rewards | Stability + activity tiers | ⏳ TODO |
| Guide | Mechanism | Mechanism type |
|---|---|---|
| [m001-enh.md](m001-enh.md) | Credit Class Approval Voting | Scoring (0-1000 composite, 3-way recommendation) |
| [m008.md](m008.md) | Data Attestation Bonding | Scoring (4-factor, no recommendation) |
| [m009.md](m009.md) | Service Provision Escrow | Dual-guard scoring (score AND confidence) |
| [m010.md](m010.md) | Reputation Signal | Event-driven decay-weighted average |
| [m011.md](m011.md) | Marketplace Curation | 7-factor quality scoring + collections |
| [m012.md](m012.md) | Fixed Cap Dynamic Supply | Supply dynamics (BigInt arithmetic, phase-gated multipliers) |
| [m013.md](m013.md) | Value-Based Fee Routing | Fee computation + pool distribution with Fee Conservation |
| [m014.md](m014.md) | Authority Validator Governance | Validator performance (re-normalized weighted score) |
| [m015.md](m015.md) | Contribution-Weighted Rewards | Activity score + stability tier allocation |

**All 9 mechanism guides are written.** Future additions (new mechanisms, upgraded versions of existing mechanisms) should follow the same five-section template.

## Guide structure

Expand Down
132 changes: 132 additions & 0 deletions docs/integrators/m008.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Integrator guide: m008 Data Attestation Bonding

**Mechanism:** Data Attestation Bonding
**Canonical spec:** [`mechanisms/m008-attestation-bonding/SPEC.md`](../../mechanisms/m008-attestation-bonding/SPEC.md)
**Reference implementation:** [`mechanisms/m008-attestation-bonding/reference-impl/m008_score.js`](../../mechanisms/m008-attestation-bonding/reference-impl/m008_score.js)

## 1. What this mechanism does

m008 scores bonded attestations on a 0-1000 composite. An attestation is a signed claim about ecological data (methodology validation, credit issuance, baseline measurement, project boundary) backed by a REGEN bond. The score reflects how trustworthy the attestation is *as evidence* — it combines the adequacy of the bond, the attester's reputation, the completeness of the evidence document, and the inherent risk of the attestation type. An integrator uses m008 to decide whether to accept an attestation into a registry, flag it for challenge, or reject it outright.

Four weighted factors drive the composite:

- `bond_adequacy` × 0.30 — bond amount relative to the minimum for this attestation type
- `attester_reputation` × 0.30 — attester's M010 reputation (default 300 when no history, matching the cautious default in `mechanisms/m008-attestation-bonding/SPEC.md` §5.2)
- `evidence_completeness` × 0.25 — completeness of the supporting evidence document
- `type_risk` × 0.15 — risk factor assigned to the attestation type (higher = more risky)

Unlike m001-enh, m008 does NOT return a recommendation — it's a pure score. The integrator decides the threshold.

## 2. What you give it

```js
import { computeM008Score } from "./m008_score.js";

const result = computeM008Score({
attestation: {
attestation_id: "att-001",
attestation_type: "BaselineMeasurement", // ProjectBoundary / BaselineMeasurement / CreditIssuanceClaim / MethodologyValidation
attestation_iri: "koi://attestation/soil-baseline-plot-42",
bond: { amount: "1500", denom: "uregen" },
},
factors: {
// Scoring inputs — each 0..1000, clamped. Defaults:
// bond_adequacy: 0, attester_reputation: 300, evidence: 0, type_risk: 0
bond_adequacy: 750,
attester_reputation: 680,
evidence_completeness: 1000,
type_risk: 600,

// Confidence flags. Note: iri_resolvable and type_recognized default to
// TRUE when unset (the check is `!== false`, not === true), while
// reputation_available and has_prior_attestations default to FALSE
// (the check is truthy).
reputation_available: true,
iri_resolvable: true,
has_prior_attestations: true,
type_recognized: true,
},
});
```

**Schemas:** [`m008_attestation.schema.json`](../../mechanisms/m008-attestation-bonding/schemas/m008_attestation.schema.json) and [`m008_quality_score.schema.json`](../../mechanisms/m008-attestation-bonding/schemas/m008_quality_score.schema.json).

## 3. What you get back

```js
{
score: 769, // 0..1000 composite, clamped (225 + 204 + 250 + 90)
confidence: 1000, // 0..1000, derived from availability flags
factors: { // clamped factor values echoed back
bond_adequacy: 750,
attester_reputation: 680,
evidence_completeness: 1000,
type_risk: 600,
},
}
```

There is **no `recommendation` field**. m008 is advisory-only at the scoring layer — the integrator decides what to do at each score tier. The SPEC suggests the following rule of thumb:

| Score | Interpretation |
|---|---|
| `>= 700` | Strong evidence — acceptable without further review |
| `400..699` | Moderate — flag for human review |
| `< 400` | Weak — consider challenge or reject |

This is a guideline, not enforcement. Downstream tooling can apply its own threshold.

## 4. Common error modes

### 4a. Missing attester history

If the attester has no prior attestations, `attester_reputation` defaults to **300** (below neutral, reflecting that the agent has no basis to trust the attester). Set `reputation_available: false` so confidence drops from 1000 to 750 (3/4 flags). If the evidence is strong despite the unknown attester, the composite can still clear the 700 threshold purely on `bond_adequacy + evidence_completeness` contributions.

### 4b. Unresolvable IRI

Set `iri_resolvable: false`. This is one of only two confidence flags that explicitly respects `false` — the guard is `!== false`, so leaving it unset counts as available. This means:

- `iri_resolvable: true` → counts (confidence gains 250)
- `iri_resolvable` undefined → counts (default is "available")
- `iri_resolvable: false` → does NOT count

The same asymmetry applies to `type_recognized`. Pinned by [`vector_v0_empty_factors_defaults`](../../mechanisms/m008-attestation-bonding/reference-impl/test_vectors/vector_v0_empty_factors_defaults.input.json).

### 4c. Bond-heavy attack vector

A well-funded attacker might try to "buy" a high score by pouring REGEN into a bonded attestation with no real evidence. With `bond_adequacy = 1000` and `type_risk = 1000` (MethodologyValidation) but zero reputation and zero evidence, the composite is `0.30×1000 + 0×0.30 + 0×0.25 + 0.15×1000 = 450` — well below the 700 threshold. Bond alone cannot carry the composite into the "strong evidence" tier. Pinned by [`vector_v0_bond_heavy_evidence_zero`](../../mechanisms/m008-attestation-bonding/reference-impl/test_vectors/vector_v0_bond_heavy_evidence_zero.input.json).

### 4d. Explicit `0` vs missing

An explicit `attester_reputation: 0` is preserved — the nullish-coalescing default of 300 only fires when the key is `null` or `undefined`, not when it's `0`. This is different from the `||` operator's behavior. If you're migrating from a data source that returns 0 ambiguously, normalize upstream.

### 4e. Type risk is a known-type lookup, not a computed value

`type_risk` in the input is the final 0..1000 factor score, not the raw attestation type. The SPEC table maps types to fixed values:

| Type | type_risk |
|---|---|
| `MethodologyValidation` | 1000 |
| `CreditIssuanceClaim` | 800 |
| `BaselineMeasurement` | 600 |
| `ProjectBoundary` | 400 |

The reference impl exports `getTypeRiskFactor(type)` and `getMinBond(type)` helpers for this — use them when you're computing factors upstream.

## 5. Runnable example

The reference implementation ships with 7 test vectors (1 sample + 6 edge cases covering the zero floor, maximum ceiling, overflow clamping, empty-factors defaults, type-contribution isolation, and the bond-heavy attack vector). The self-test discovers every vector in `test_vectors/` automatically:

```bash
node mechanisms/m008-attestation-bonding/reference-impl/m008_score.js
```

Expected output:

```
m008_score self-test: PASS (11 attestations across 7 vectors)
```

---

Canonical spec: [`mechanisms/m008-attestation-bonding/SPEC.md`](../../mechanisms/m008-attestation-bonding/SPEC.md) §5.
120 changes: 120 additions & 0 deletions docs/integrators/m009.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# Integrator guide: m009 Service Provision Escrow

**Mechanism:** Service Provision Escrow
**Canonical spec:** [`mechanisms/m009-service-escrow/SPEC.md`](../../mechanisms/m009-service-escrow/SPEC.md)
**Reference implementation:** [`mechanisms/m009-service-escrow/reference-impl/m009_score.js`](../../mechanisms/m009-service-escrow/reference-impl/m009_score.js)

## 1. What this mechanism does

m009 reviews milestone deliverables inside a service escrow agreement and returns one of three recommendations: **APPROVE**, **NEEDS_REVISION**, or **FLAG_FOR_CLIENT**. A service escrow agreement locks client funds against a set of milestones; each milestone must be reviewed before the escrowed funds are released. An integrator uses m009 to provide a consistent first-pass review of a milestone submission, letting a human arbiter focus attention on the cases the agent can't auto-approve.

Unlike m001-enh (which has a single-guard REJECT branch), m009 uses a **dual-guard** recommendation model: APPROVE requires BOTH a high score AND high confidence, while FLAG_FOR_CLIENT fires when EITHER score is low OR confidence is low. This asymmetry protects both sides of the deal — the client never has a low-confidence submission auto-approved, and the provider never has a thin-evidence review auto-rejected.

Four weighted factors drive the composite:

- `deliverable_quality` × 0.40 — methodology compliance and technical quality of the submission
- `evidence_completeness` × 0.25 — completeness of the supporting evidence package
- `milestone_consistency` × 0.20 — consistency with prior milestones in the same agreement
- `provider_reputation` × 0.15 — provider's M010 reputation (default 300 when no history)

## 2. What you give it

```js
import { computeM009Score } from "./m009_score.js";

const result = computeM009Score({
milestone: {
milestone_id: "ms-001",
escrow_id: "escrow-001",
provider: "regen1provider001",
amount: { amount: "1000", denom: "uregen" },
},
factors: {
// Scoring inputs — each 0..1000, clamped. Defaults:
// quality: 0, evidence: 0, consistency: 0, provider_reputation: 300
deliverable_quality: 850,
evidence_completeness: 800,
milestone_consistency: 750,
provider_reputation: 700,

// Confidence flags — all use strict `=== true` (unlike m008 which
// uses `!== false` for two of its flags). This means UNSET counts
// as FALSE for m009. Set every flag explicitly if you want it to
// count.
reputation_available: true,
iri_resolvable: true,
has_prior_milestones: true,
spec_available: true,
},
});
```

**Schemas:** [`m009_milestone_review.schema.json`](../../mechanisms/m009-service-escrow/schemas/m009_milestone_review.schema.json) and the agreement lifecycle schema in the same directory.

## 3. What you get back

```js
{
score: 795, // 0..1000 composite, clamped (340 + 200 + 150 + 105)
confidence: 1000, // 0..1000 (count of `=== true` flags / 4)
recommendation: "APPROVE", // APPROVE | NEEDS_REVISION | FLAG_FOR_CLIENT
factors: { // clamped factor values echoed back
deliverable_quality: 850,
evidence_completeness: 800,
milestone_consistency: 750,
provider_reputation: 700,
},
}
```

**Recommendation rules — read carefully, the branches are NOT symmetric:**

| Condition | Recommendation |
|---|---|
| `score >= 700` AND `confidence >= 750` | `APPROVE` |
| `score < 400` OR `confidence < 250` | `FLAG_FOR_CLIENT` |
| otherwise | `NEEDS_REVISION` |

- APPROVE requires BOTH conditions (a conjunction). A perfect score with low confidence does NOT auto-approve — it falls through to NEEDS_REVISION for human review.
- FLAG_FOR_CLIENT fires when EITHER side of the OR is true. A perfect 1000 score with zero confidence flags FIRES — the client must review it manually, and the provider does not get auto-approved on evidence the system cannot verify.
- Everything else is NEEDS_REVISION — the middle state where neither guard wants to auto-decide.

## 4. Common error modes

### 4a. High score, low confidence → NEEDS_REVISION, not APPROVE

A submission with a perfect 1000 score but only 2 of 4 flags true (confidence 500) does NOT auto-approve. The APPROVE branch requires confidence `>= 750`. The submission falls through to NEEDS_REVISION — human review required. Pinned by [`vector_v0_high_score_low_confidence_revision`](../../mechanisms/m009-service-escrow/reference-impl/test_vectors/vector_v0_high_score_low_confidence_revision.input.json).

### 4b. High score, zero confidence → FLAG_FOR_CLIENT

A submission with score 800 but zero confidence flags (confidence 0) does NOT approve — it fires FLAG_FOR_CLIENT because the confidence guard on the FLAG branch is `< 250`. This protects the client from an agent approving a "high quality" submission the system cannot verify at all. Pinned by [`vector_v0_confidence_floor_forces_flag`](../../mechanisms/m009-service-escrow/reference-impl/test_vectors/vector_v0_confidence_floor_forces_flag.input.json).

### 4c. Score exactly at 400 is NEEDS_REVISION, not FLAG

The FLAG_FOR_CLIENT predicate is `score < 400` — strict inequality. A score of exactly 400 does NOT fire the flag. It falls through to NEEDS_REVISION. A future refactor that changes `<` to `<=` would silently flip this boundary, which is why [`vector_v0_boundary_revision_exact_400`](../../mechanisms/m009-service-escrow/reference-impl/test_vectors/vector_v0_boundary_revision_exact_400.input.json) pins it.

### 4d. Unlike m008, the `=== true` guard is strict

All four m009 confidence flags use strict `=== true`. Unset flags count as FALSE, not TRUE. If you're porting from m008 (which uses `!== false` for two of its flags), re-audit your flag-setting code — `iri_resolvable: undefined` counts in m008 but NOT in m009.

### 4e. First-time provider gets the reputation default

`provider_reputation` defaults to **300** when unset, not 500. This is lower than m008's attester default because the SPEC treats first-time providers as higher risk in escrow agreements. Set `reputation_available: false` to also drop the confidence contribution.

## 5. Runnable example

The reference implementation ships with 7 test vectors covering the happy path (sample), the dual-guard APPROVE boundary at (700, 750), the score-high/confidence-low fallback, the exact 399 FLAG boundary, the exact 400 REVISION boundary, the confidence-floor-forces-flag case, and the overflow clamp. The self-test discovers every vector in `test_vectors/` automatically:

```bash
node mechanisms/m009-service-escrow/reference-impl/m009_score.js
```

Expected output:

```
m009_score self-test: PASS (11 milestones across 7 vectors)
```

---

Canonical spec: [`mechanisms/m009-service-escrow/SPEC.md`](../../mechanisms/m009-service-escrow/SPEC.md) §5.
Loading
Loading