Minerval

← skills

Method skill

Sql

version 13 · since epoch 2026-11-responsive-funding

How to query the graph and the action ledger with read-only SQL: what each view holds, how they join, what is fast, and queries for the questions readers and agents most often ask.

Loaded: on demand, by any role it addresses; it claims no domain. Source: skills/sql/SKILL.md.

For every administrator

query_sql runs one read-only SELECT against views of the graph's public data. It is the way to ask questions the other reads can't: which important nodes have disputes waiting, what reassessments cost and how often they changed a verdict, what a mandate has funded and what it bought. To find nodes by meaning, use search_claims first and pass its ids in (WHERE n.id = ANY($1::uuid[])); SQL can't search by meaning.

Conventions. Ids are uuids. Times are UTC. Money is in owls. importance, contestation, confidence and credence run from 0 to 1. A status is one of verified, supported, inconclusive, doubtful, contradicted or unknown.

The views.

  • nodes: id, kind (claim, quantity, question), text, claim_type, state, merged_into, importance, contestation, steward_state, stewarded_at, proposed_by_person, tags (array of slugs), created_at, updated_at, steward_park_reason (null unless steward_state is 'error': the node is parked after failed Steward passes and will not be assessed until someone commissions a pass on it; one of credentials_fault, model_refusal, database_fault, tool_failure, provider_error, other)
  • assessments: id, node_id, status, confidence, credence, marginal_yield, is_current, assessed_at, trigger, summary, reasoning_head (the first 500 characters), relabeled_from (the retired label, contested or unsupported, a migration carried the status over from; set until the node is re-judged, so such a status is provisional, not a finding)
  • edges: id, parent_id, child_id, relation, reasoning, created_at
  • arguments: id, node_id, name, stance, shows, description, created_at, retired_at
  • tags: slug, name, description, status, node_count
  • sources: id, url, title, source_type, publisher, published_date, doi, retrieved_at
  • instances: where a claim is asserted. id, node_id, source_id, stance, speaker, publication, source_date, verbatim_head, created_at, detached_at
  • ledger: every piece of graph work. action_id, kind, variant, target_node_id, target_ref, label, status (open, running, finished, cancelled), spent_owls, opened_at, updated_at, waiting_on (null unless the row is open, a platform fault stopped its last attempt and the platform's next attempt is still ahead: one of credits_fault, the platform's account with a model provider is out of credits; credentials_fault, a provider rejected the platform's key; provider_unavailable, a provider or network failure that outlasted its retries), waiting_since, next_attempt_at (always in the future: once it has come all three are null and the row is due, a plain open row the platform picks when its turn comes). A row with waiting_on has not failed and is not cancelled: it stays funded, no attempt is charged, and the platform retries it on its own, so commissioning it again buys nothing. Its budget stays held meanwhile and counts against the mandate's pace from when it was placed, as any held budget does. extraction (null unless the row is a running ingest: queued, its source is waiting its turn to be read; extracting, a worker is reading it), extraction_started_at (when the current reading began; null while queued), queued_ahead (for a queued ingest, about how many extractions submitted before it are still waiting; the queue does not promise its order). A running ingest is not necessarily being read: say queued when it is
  • commissions: the money on each piece of work. commission_id, action_id, exclusion_group, payer_kind (mandate, person), payer_mandate_id, budget_owls, spent_owls, returned_owls, commissioned_by, brief, reason, parent_action_id (the run that paid, when an agent spent from its own budget), created_at, settled_at
  • messages: what was sent to a node's Steward. message_id, node_id, trigger, sender_kind, sender_node_id, paid, body, created_at, read_at, outcome (changed, no_change, disagree), outcome_note
  • mandates: mandate_id, title, objective, status, is_platform, pace (jsonb: {"kind":"as_needed"}, or {"kind":"steady","owls":…, "period_hours":…} for at most that much committed in any rolling window), reserve_owls and reserve_reason (what only the Grantmaker may commit, and why), escrow_owls, operating_policy, created_at
  • mandate_decisions: every commission, grant, refusal, decline and note a mandate's agents made. decision_id, mandate_id, decided_by, item_kind, decision, target, owls, reason, petition_id, action_id, created_at
  • plan_items: each item of a mandate's plan, as its page shows it, with the standing the plan materializer last wrote on it. mandate_id, item_index, plan_cursor (it stands past the last item whose work has run or is running; an item before it can still be waiting), action, node_id, url, partition, variant, focus, rationale, ledger_status, ledger_reason, action_id (the ledger row it names), exclusion_group, ledger_checked_at, proposed_kind, proposed_text, proposal_ref, node_ref, contribution_id, added_by (who put the item in the plan: grantmaker_draft, grantmaker_planning, grantmaker_chat with the funder, or grantmaker_review, its own pass whatever woke it), added_at and added_run_id (null on items added before these were recorded). Join action_id to ledger to check a plan against what ran: a named row that is missing, or whose status disagrees with ledger_status, is a plan out of step with its ledger. A propose item is a node the plan asked the graph to take in: proposed_kind and proposed_text are what it proposed, contribution_id the contribution it filed (join contributions), and node_id the node it became or landed on once accepted. An item with node_ref and no node_id is waiting on the proposal whose proposal_ref that is. An assess, reassess or deepen item is a standing order its mandate commissions: once placed, its money is the row in commissions on that action_id with commissioned_by plan. A ledger_status of waiting on one is an order the mandate's pace, its Grantmaker's reserve, or its escrow has no room for yet, and blocked one that could never fit, or one stored with no variant, which commissions nothing until its Grantmaker names a tier; ledger_reason gives the tier and the figures. cancelled with a ledger_reason beginning "withdrawn" is an item its Grantmaker withdrew before its pass began. A deepen item orders passes only on the node's children that carry no assessment.
  • petitions: petition_id, mandate_id, kind, asked_owls, granted_owls, requester_agent, requester_node_id, status, plan, reason, created_at, decided_at
  • contributions: contribution_id, node_id, type, review_status, submitted_at
  • requests: request_id, ask, why, state, keeper_kind, keeper_node_id, budget_owls, created_at, closed_at
  • changes: the change stream as one table. kind, node_id, at, summary. kind state_changed is a node archived, restored, merged or deprecated; its summary reads <from> -> <to> by <who>: <reason>, with the successors that carry on what the node stated, if any

What is fast. Ids, node_id and target_node_id on every view, tags (use = ANY or &&), importance, assessed_at and created_at. Filter on these first, join on ids, and aggregate in the query rather than returning rows to count. A query the planner prices too high is refused before it runs, with its estimate.

Queries for common questions.

Important nodes under a tag that have gone stale:

SELECT n.id, n.text, n.importance, a.assessed_at
  FROM nodes n JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE $1 = ANY(n.tags) AND n.importance >= 0.5
   AND a.assessed_at < now() - interval '60 days'
 ORDER BY n.importance DESC LIMIT 50;

Messages waiting longest on important nodes:

SELECT m.node_id, n.text, m.trigger, now() - m.created_at AS waiting
  FROM messages m JOIN nodes n ON n.id = m.node_id
 WHERE m.read_at IS NULL AND n.importance >= 0.6
 ORDER BY m.created_at LIMIT 50;

What each kind of work cost over the last 30 days, and how much of its budget it used:

SELECT l.kind, count(*) AS runs, sum(c.spent_owls) AS spent,
       round(avg(c.spent_owls / nullif(c.budget_owls, 0)), 2) AS budget_used,
       percentile_cont(0.8) WITHIN GROUP (ORDER BY c.spent_owls) AS p80
  FROM commissions c JOIN ledger l USING (action_id)
 WHERE c.settled_at > now() - interval '30 days'
 GROUP BY l.kind ORDER BY spent DESC;

Everything beneath a node, with the signals for deciding where work goes (a scope survey): standing, age, expected gain from another pass, and subclaims still waiting on a deepen. For a territory found by meaning, start from search_claims' ids instead of the subtree.

WITH RECURSIVE sub(id) AS (
  SELECT $1::uuid
  UNION SELECT e.child_id FROM edges e JOIN sub ON e.parent_id = sub.id)
SELECT n.id, n.text, n.importance, n.contestation, n.steward_state,
       n.steward_park_reason,
       a.status, now()::date - a.assessed_at::date AS days_since_assessed,
       a.marginal_yield,
       (SELECT count(*) FROM edges e JOIN nodes c ON c.id = e.child_id
         WHERE e.parent_id = n.id AND c.steward_state = 'deferred') AS deferred_subclaims
  FROM sub JOIN nodes n USING (id)
  LEFT JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;

Statuses carried over from a retired label and not yet re-judged, most important first, with the reassessment open on each and the budget already committed to it. Price what is left with the cost query above (kind reassess):

SELECT n.id, n.text, n.importance, a.status, a.relabeled_from, a.assessed_at,
       r.open_reassess, r.committed_owls
  FROM assessments a JOIN nodes n ON n.id = a.node_id
  LEFT JOIN LATERAL (
    SELECT count(DISTINCT l.action_id) AS open_reassess,
           coalesce(sum(c.budget_owls - c.spent_owls)
                      FILTER (WHERE c.settled_at IS NULL), 0) AS committed_owls
      FROM ledger l LEFT JOIN commissions c USING (action_id)
     WHERE l.target_node_id = n.id AND l.kind = 'reassess'
       AND l.status IN ('open', 'running')) r ON true
 WHERE a.is_current AND a.relabeled_from IS NOT NULL AND n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;

Funded work that is waiting on a platform fault, with what is held on it:

SELECT l.kind, l.waiting_on, count(DISTINCT l.action_id) AS rows,
       min(l.waiting_since) AS since, min(l.next_attempt_at) AS next_attempt,
       coalesce(sum(c.budget_owls - c.spent_owls), 0) AS held_owls
  FROM ledger l LEFT JOIN commissions c
    ON c.action_id = l.action_id AND c.settled_at IS NULL
 WHERE l.status = 'open' AND l.waiting_on IS NOT NULL
 GROUP BY l.kind, l.waiting_on ORDER BY since;

What is not here. Only public data: no emails, keys, balances or unfunded drafts, and no funder or contributor identities.

If a question needs something the views lack, say so with raise_issue.


Who receives which sections

Generated from the loader’s composition table (ROLE_VIEW in src/llm/prompts/skills.ts). A role receives the listed sections in document order; the solver is an instrument rather than an administrator and receives no constitution.

RoleSections received
Claim StewardFor every administrator; For the Claim Steward; For the Curator; For the Matcher; For the Extractor
Audit AgentFor every administrator; For the Claim Steward; For the Grantmaker; For the Contribution Reviewer and the Dispute Arbitrator; For the Audit Agent; For the Curator; For the Matcher; For the Extractor; Standards for judging
GrantmakerFor every administrator; For the Grantmaker
LookoutFor every administrator
CorrespondentFor every administrator
Program OfficerFor every administrator
Contribution ReviewerFor every administrator; For the Contribution Reviewer and the Dispute Arbitrator
Dispute ArbitratorFor every administrator; For the Contribution Reviewer and the Dispute Arbitrator
CuratorFor every administrator; For the Curator; For the Matcher
MatcherFor the Matcher
ExtractorFor the Extractor
ResearcherFor every administrator; For the researcher
Consistency CheckerFor every administrator; Standards for judging

What each role receives

The exact view each role receives when it loads this skill with load_skill (the Extractor’s is spliced into its prompt): the heading the agent can cite, one sentence of standing, and the role’s sections verbatim.

Claim Steward · 1 section · 11,187 characters
# Method skill: Sql (version 13)

This skill says how the constitution and your role apply to one kind of work. It never outranks either.

## For every administrator

query_sql runs one read-only SELECT against views of the graph's public
data. It is the way to ask questions the other reads can't: which important
nodes have disputes waiting, what reassessments cost and how often they
changed a verdict, what a mandate has funded and what it bought. To find
nodes by meaning, use search_claims first and pass its ids in
(`WHERE n.id = ANY($1::uuid[])`); SQL can't search by meaning.

**Conventions.** Ids are uuids. Times are UTC. Money is in owls.
importance, contestation, confidence and credence run from 0 to 1. A status
is one of verified, supported, inconclusive, doubtful, contradicted or
unknown.

**The views.**

- `nodes`: id, kind (claim, quantity, question), text, claim_type, state,
  merged_into, importance, contestation, steward_state, stewarded_at,
  proposed_by_person, tags (array of slugs), created_at, updated_at,
  steward_park_reason (null unless steward_state is 'error': the node is
  parked after failed Steward passes and will not be assessed until someone
  commissions a pass on it; one of credentials_fault, model_refusal,
  database_fault, tool_failure, provider_error, other)
- `assessments`: id, node_id, status, confidence, credence, marginal_yield,
  is_current, assessed_at, trigger, summary, reasoning_head (the first 500
  characters), relabeled_from (the retired label, contested or
  unsupported, a migration carried the status over from; set until the
  node is re-judged, so such a status is provisional, not a finding)
- `edges`: id, parent_id, child_id, relation, reasoning, created_at
- `arguments`: id, node_id, name, stance, shows, description, created_at,
  retired_at
- `tags`: slug, name, description, status, node_count
- `sources`: id, url, title, source_type, publisher, published_date, doi,
  retrieved_at
- `instances`: where a claim is asserted. id, node_id, source_id, stance,
  speaker, publication, source_date, verbatim_head, created_at, detached_at
- `ledger`: every piece of graph work. action_id, kind, variant,
  target_node_id, target_ref, label, status (open, running, finished,
  cancelled), spent_owls, opened_at, updated_at, waiting_on (null unless
  the row is open, a platform fault stopped its last attempt and the
  platform's next attempt is still ahead: one of
  credits_fault, the platform's account with a model provider is out of
  credits; credentials_fault, a provider rejected the platform's key;
  provider_unavailable, a provider or network failure that outlasted its
  retries), waiting_since, next_attempt_at (always in the future: once it
  has come all three are null and the row is due, a plain open row the
  platform picks when its turn comes). A row with waiting_on has not
  failed and is not cancelled: it stays funded, no attempt is charged, and
  the platform retries it on its own, so commissioning it again buys
  nothing. Its budget stays held meanwhile and counts against the
  mandate's pace from when it was placed, as any held budget does.
  extraction (null unless the row is a running ingest: queued, its source
  is waiting its turn to be read; extracting, a worker is reading it),
  extraction_started_at (when the current reading began; null while
  queued), queued_ahead (for a queued ingest, about how many extractions
  submitted before it are still waiting; the queue does not promise its
  order). A running ingest is not necessarily being read: say queued when
  it is
- `commissions`: the money on each piece of work. commission_id, action_id,
  exclusion_group, payer_kind (mandate, person), payer_mandate_id,
  budget_owls, spent_owls, returned_owls, commissioned_by, brief, reason,
  parent_action_id (the run that paid, when an agent spent from its own
  budget), created_at, settled_at
- `messages`: what was sent to a node's Steward. message_id, node_id,
  trigger, sender_kind, sender_node_id, paid, body, created_at, read_at,
  outcome (changed, no_change, disagree), outcome_note
- `mandates`: mandate_id, title, objective, status, is_platform, pace
  (jsonb: `{"kind":"as_needed"}`, or `{"kind":"steady","owls":…,
  "period_hours":…}` for at most that much committed in any rolling
  window), reserve_owls and reserve_reason (what only the Grantmaker may
  commit, and why), escrow_owls, operating_policy, created_at
- `mandate_decisions`: every commission, grant, refusal, decline and note
  a mandate's agents made. decision_id, mandate_id, decided_by, item_kind,
  decision, target, owls, reason, petition_id, action_id, created_at
- `plan_items`: each item of a mandate's plan, as its page shows it, with
  the standing the plan materializer last wrote on it. mandate_id,
  item_index, plan_cursor (it stands past the last item whose work has
  run or is running; an item before it can still be waiting), action,
  node_id, url, partition, variant, focus, rationale, ledger_status,
  ledger_reason, action_id (the ledger row it names), exclusion_group,
  ledger_checked_at, proposed_kind, proposed_text, proposal_ref, node_ref,
  contribution_id, added_by (who put the item in the plan:
  grantmaker_draft, grantmaker_planning, grantmaker_chat with the funder,
  or grantmaker_review, its own pass whatever woke it), added_at and
  added_run_id (null on items added before these were recorded). Join action_id to `ledger` to check a plan against
  what ran: a named row that is missing, or whose status disagrees with
  ledger_status, is a plan out of step with its ledger. A `propose` item
  is a node the plan asked the graph to take in: proposed_kind and
  proposed_text are what it proposed, contribution_id the contribution it
  filed (join `contributions`), and node_id the node it became or landed
  on once accepted. An item with node_ref and no node_id is waiting on the
  proposal whose proposal_ref that is.
  An `assess`, `reassess` or `deepen` item is a
  standing order its mandate commissions: once placed, its money is the
  row in `commissions` on that action_id with commissioned_by `plan`. A
  ledger_status of `waiting` on one is an order the mandate's pace, its
  Grantmaker's reserve, or its escrow has no room for yet, and `blocked` one
  that could never fit, or one stored with no variant, which commissions
  nothing until its Grantmaker names a tier; ledger_reason gives the tier
  and the figures. `cancelled` with a ledger_reason beginning "withdrawn" is
  an item its Grantmaker withdrew before its pass began. A deepen item
  orders passes only on the node's children that carry no assessment.
- `petitions`: petition_id, mandate_id, kind, asked_owls, granted_owls,
  requester_agent, requester_node_id, status, plan, reason, created_at,
  decided_at
- `contributions`: contribution_id, node_id, type, review_status,
  submitted_at
- `requests`: request_id, ask, why, state, keeper_kind, keeper_node_id,
  budget_owls, created_at, closed_at
- `changes`: the change stream as one table. kind, node_id, at, summary.
  kind `state_changed` is a node archived, restored, merged or deprecated;
  its summary reads `<from> -> <to> by <who>: <reason>`, with the
  successors that carry on what the node stated, if any

**What is fast.** Ids, node_id and target_node_id on every view, tags (use
`= ANY` or `&&`), importance, assessed_at and created_at. Filter on these
first, join on ids, and aggregate in the query rather than returning rows to
count. A query the planner prices too high is refused before it runs, with
its estimate.

**Queries for common questions.**

Important nodes under a tag that have gone stale:

```sql
SELECT n.id, n.text, n.importance, a.assessed_at
  FROM nodes n JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE $1 = ANY(n.tags) AND n.importance >= 0.5
   AND a.assessed_at < now() - interval '60 days'
 ORDER BY n.importance DESC LIMIT 50;
```

Messages waiting longest on important nodes:

```sql
SELECT m.node_id, n.text, m.trigger, now() - m.created_at AS waiting
  FROM messages m JOIN nodes n ON n.id = m.node_id
 WHERE m.read_at IS NULL AND n.importance >= 0.6
 ORDER BY m.created_at LIMIT 50;
```

What each kind of work cost over the last 30 days, and how much of its
budget it used:

```sql
SELECT l.kind, count(*) AS runs, sum(c.spent_owls) AS spent,
       round(avg(c.spent_owls / nullif(c.budget_owls, 0)), 2) AS budget_used,
       percentile_cont(0.8) WITHIN GROUP (ORDER BY c.spent_owls) AS p80
  FROM commissions c JOIN ledger l USING (action_id)
 WHERE c.settled_at > now() - interval '30 days'
 GROUP BY l.kind ORDER BY spent DESC;
```

Everything beneath a node, with the signals for deciding where work goes
(a scope survey): standing, age, expected gain from another pass, and
subclaims still waiting on a deepen. For a territory found by meaning,
start from search_claims' ids instead of the subtree.

```sql
WITH RECURSIVE sub(id) AS (
  SELECT $1::uuid
  UNION SELECT e.child_id FROM edges e JOIN sub ON e.parent_id = sub.id)
SELECT n.id, n.text, n.importance, n.contestation, n.steward_state,
       n.steward_park_reason,
       a.status, now()::date - a.assessed_at::date AS days_since_assessed,
       a.marginal_yield,
       (SELECT count(*) FROM edges e JOIN nodes c ON c.id = e.child_id
         WHERE e.parent_id = n.id AND c.steward_state = 'deferred') AS deferred_subclaims
  FROM sub JOIN nodes n USING (id)
  LEFT JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;
```

Statuses carried over from a retired label and not yet re-judged, most
important first, with the reassessment open on each and the budget already
committed to it. Price what is left with the cost query above (kind
`reassess`):

```sql
SELECT n.id, n.text, n.importance, a.status, a.relabeled_from, a.assessed_at,
       r.open_reassess, r.committed_owls
  FROM assessments a JOIN nodes n ON n.id = a.node_id
  LEFT JOIN LATERAL (
    SELECT count(DISTINCT l.action_id) AS open_reassess,
           coalesce(sum(c.budget_owls - c.spent_owls)
                      FILTER (WHERE c.settled_at IS NULL), 0) AS committed_owls
      FROM ledger l LEFT JOIN commissions c USING (action_id)
     WHERE l.target_node_id = n.id AND l.kind = 'reassess'
       AND l.status IN ('open', 'running')) r ON true
 WHERE a.is_current AND a.relabeled_from IS NOT NULL AND n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;
```

Funded work that is waiting on a platform fault, with what is held on it:

```sql
SELECT l.kind, l.waiting_on, count(DISTINCT l.action_id) AS rows,
       min(l.waiting_since) AS since, min(l.next_attempt_at) AS next_attempt,
       coalesce(sum(c.budget_owls - c.spent_owls), 0) AS held_owls
  FROM ledger l LEFT JOIN commissions c
    ON c.action_id = l.action_id AND c.settled_at IS NULL
 WHERE l.status = 'open' AND l.waiting_on IS NOT NULL
 GROUP BY l.kind, l.waiting_on ORDER BY since;
```

**What is not here.** Only public data: no emails, keys, balances or
unfunded drafts, and no funder or contributor identities.

If a question needs something the views lack, say so with raise_issue.
Audit Agent · 1 section · 11,187 characters
# Method skill: Sql (version 13)

This skill says how the constitution and your role apply to one kind of work. It never outranks either.

## For every administrator

query_sql runs one read-only SELECT against views of the graph's public
data. It is the way to ask questions the other reads can't: which important
nodes have disputes waiting, what reassessments cost and how often they
changed a verdict, what a mandate has funded and what it bought. To find
nodes by meaning, use search_claims first and pass its ids in
(`WHERE n.id = ANY($1::uuid[])`); SQL can't search by meaning.

**Conventions.** Ids are uuids. Times are UTC. Money is in owls.
importance, contestation, confidence and credence run from 0 to 1. A status
is one of verified, supported, inconclusive, doubtful, contradicted or
unknown.

**The views.**

- `nodes`: id, kind (claim, quantity, question), text, claim_type, state,
  merged_into, importance, contestation, steward_state, stewarded_at,
  proposed_by_person, tags (array of slugs), created_at, updated_at,
  steward_park_reason (null unless steward_state is 'error': the node is
  parked after failed Steward passes and will not be assessed until someone
  commissions a pass on it; one of credentials_fault, model_refusal,
  database_fault, tool_failure, provider_error, other)
- `assessments`: id, node_id, status, confidence, credence, marginal_yield,
  is_current, assessed_at, trigger, summary, reasoning_head (the first 500
  characters), relabeled_from (the retired label, contested or
  unsupported, a migration carried the status over from; set until the
  node is re-judged, so such a status is provisional, not a finding)
- `edges`: id, parent_id, child_id, relation, reasoning, created_at
- `arguments`: id, node_id, name, stance, shows, description, created_at,
  retired_at
- `tags`: slug, name, description, status, node_count
- `sources`: id, url, title, source_type, publisher, published_date, doi,
  retrieved_at
- `instances`: where a claim is asserted. id, node_id, source_id, stance,
  speaker, publication, source_date, verbatim_head, created_at, detached_at
- `ledger`: every piece of graph work. action_id, kind, variant,
  target_node_id, target_ref, label, status (open, running, finished,
  cancelled), spent_owls, opened_at, updated_at, waiting_on (null unless
  the row is open, a platform fault stopped its last attempt and the
  platform's next attempt is still ahead: one of
  credits_fault, the platform's account with a model provider is out of
  credits; credentials_fault, a provider rejected the platform's key;
  provider_unavailable, a provider or network failure that outlasted its
  retries), waiting_since, next_attempt_at (always in the future: once it
  has come all three are null and the row is due, a plain open row the
  platform picks when its turn comes). A row with waiting_on has not
  failed and is not cancelled: it stays funded, no attempt is charged, and
  the platform retries it on its own, so commissioning it again buys
  nothing. Its budget stays held meanwhile and counts against the
  mandate's pace from when it was placed, as any held budget does.
  extraction (null unless the row is a running ingest: queued, its source
  is waiting its turn to be read; extracting, a worker is reading it),
  extraction_started_at (when the current reading began; null while
  queued), queued_ahead (for a queued ingest, about how many extractions
  submitted before it are still waiting; the queue does not promise its
  order). A running ingest is not necessarily being read: say queued when
  it is
- `commissions`: the money on each piece of work. commission_id, action_id,
  exclusion_group, payer_kind (mandate, person), payer_mandate_id,
  budget_owls, spent_owls, returned_owls, commissioned_by, brief, reason,
  parent_action_id (the run that paid, when an agent spent from its own
  budget), created_at, settled_at
- `messages`: what was sent to a node's Steward. message_id, node_id,
  trigger, sender_kind, sender_node_id, paid, body, created_at, read_at,
  outcome (changed, no_change, disagree), outcome_note
- `mandates`: mandate_id, title, objective, status, is_platform, pace
  (jsonb: `{"kind":"as_needed"}`, or `{"kind":"steady","owls":…,
  "period_hours":…}` for at most that much committed in any rolling
  window), reserve_owls and reserve_reason (what only the Grantmaker may
  commit, and why), escrow_owls, operating_policy, created_at
- `mandate_decisions`: every commission, grant, refusal, decline and note
  a mandate's agents made. decision_id, mandate_id, decided_by, item_kind,
  decision, target, owls, reason, petition_id, action_id, created_at
- `plan_items`: each item of a mandate's plan, as its page shows it, with
  the standing the plan materializer last wrote on it. mandate_id,
  item_index, plan_cursor (it stands past the last item whose work has
  run or is running; an item before it can still be waiting), action,
  node_id, url, partition, variant, focus, rationale, ledger_status,
  ledger_reason, action_id (the ledger row it names), exclusion_group,
  ledger_checked_at, proposed_kind, proposed_text, proposal_ref, node_ref,
  contribution_id, added_by (who put the item in the plan:
  grantmaker_draft, grantmaker_planning, grantmaker_chat with the funder,
  or grantmaker_review, its own pass whatever woke it), added_at and
  added_run_id (null on items added before these were recorded). Join action_id to `ledger` to check a plan against
  what ran: a named row that is missing, or whose status disagrees with
  ledger_status, is a plan out of step with its ledger. A `propose` item
  is a node the plan asked the graph to take in: proposed_kind and
  proposed_text are what it proposed, contribution_id the contribution it
  filed (join `contributions`), and node_id the node it became or landed
  on once accepted. An item with node_ref and no node_id is waiting on the
  proposal whose proposal_ref that is.
  An `assess`, `reassess` or `deepen` item is a
  standing order its mandate commissions: once placed, its money is the
  row in `commissions` on that action_id with commissioned_by `plan`. A
  ledger_status of `waiting` on one is an order the mandate's pace, its
  Grantmaker's reserve, or its escrow has no room for yet, and `blocked` one
  that could never fit, or one stored with no variant, which commissions
  nothing until its Grantmaker names a tier; ledger_reason gives the tier
  and the figures. `cancelled` with a ledger_reason beginning "withdrawn" is
  an item its Grantmaker withdrew before its pass began. A deepen item
  orders passes only on the node's children that carry no assessment.
- `petitions`: petition_id, mandate_id, kind, asked_owls, granted_owls,
  requester_agent, requester_node_id, status, plan, reason, created_at,
  decided_at
- `contributions`: contribution_id, node_id, type, review_status,
  submitted_at
- `requests`: request_id, ask, why, state, keeper_kind, keeper_node_id,
  budget_owls, created_at, closed_at
- `changes`: the change stream as one table. kind, node_id, at, summary.
  kind `state_changed` is a node archived, restored, merged or deprecated;
  its summary reads `<from> -> <to> by <who>: <reason>`, with the
  successors that carry on what the node stated, if any

**What is fast.** Ids, node_id and target_node_id on every view, tags (use
`= ANY` or `&&`), importance, assessed_at and created_at. Filter on these
first, join on ids, and aggregate in the query rather than returning rows to
count. A query the planner prices too high is refused before it runs, with
its estimate.

**Queries for common questions.**

Important nodes under a tag that have gone stale:

```sql
SELECT n.id, n.text, n.importance, a.assessed_at
  FROM nodes n JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE $1 = ANY(n.tags) AND n.importance >= 0.5
   AND a.assessed_at < now() - interval '60 days'
 ORDER BY n.importance DESC LIMIT 50;
```

Messages waiting longest on important nodes:

```sql
SELECT m.node_id, n.text, m.trigger, now() - m.created_at AS waiting
  FROM messages m JOIN nodes n ON n.id = m.node_id
 WHERE m.read_at IS NULL AND n.importance >= 0.6
 ORDER BY m.created_at LIMIT 50;
```

What each kind of work cost over the last 30 days, and how much of its
budget it used:

```sql
SELECT l.kind, count(*) AS runs, sum(c.spent_owls) AS spent,
       round(avg(c.spent_owls / nullif(c.budget_owls, 0)), 2) AS budget_used,
       percentile_cont(0.8) WITHIN GROUP (ORDER BY c.spent_owls) AS p80
  FROM commissions c JOIN ledger l USING (action_id)
 WHERE c.settled_at > now() - interval '30 days'
 GROUP BY l.kind ORDER BY spent DESC;
```

Everything beneath a node, with the signals for deciding where work goes
(a scope survey): standing, age, expected gain from another pass, and
subclaims still waiting on a deepen. For a territory found by meaning,
start from search_claims' ids instead of the subtree.

```sql
WITH RECURSIVE sub(id) AS (
  SELECT $1::uuid
  UNION SELECT e.child_id FROM edges e JOIN sub ON e.parent_id = sub.id)
SELECT n.id, n.text, n.importance, n.contestation, n.steward_state,
       n.steward_park_reason,
       a.status, now()::date - a.assessed_at::date AS days_since_assessed,
       a.marginal_yield,
       (SELECT count(*) FROM edges e JOIN nodes c ON c.id = e.child_id
         WHERE e.parent_id = n.id AND c.steward_state = 'deferred') AS deferred_subclaims
  FROM sub JOIN nodes n USING (id)
  LEFT JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;
```

Statuses carried over from a retired label and not yet re-judged, most
important first, with the reassessment open on each and the budget already
committed to it. Price what is left with the cost query above (kind
`reassess`):

```sql
SELECT n.id, n.text, n.importance, a.status, a.relabeled_from, a.assessed_at,
       r.open_reassess, r.committed_owls
  FROM assessments a JOIN nodes n ON n.id = a.node_id
  LEFT JOIN LATERAL (
    SELECT count(DISTINCT l.action_id) AS open_reassess,
           coalesce(sum(c.budget_owls - c.spent_owls)
                      FILTER (WHERE c.settled_at IS NULL), 0) AS committed_owls
      FROM ledger l LEFT JOIN commissions c USING (action_id)
     WHERE l.target_node_id = n.id AND l.kind = 'reassess'
       AND l.status IN ('open', 'running')) r ON true
 WHERE a.is_current AND a.relabeled_from IS NOT NULL AND n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;
```

Funded work that is waiting on a platform fault, with what is held on it:

```sql
SELECT l.kind, l.waiting_on, count(DISTINCT l.action_id) AS rows,
       min(l.waiting_since) AS since, min(l.next_attempt_at) AS next_attempt,
       coalesce(sum(c.budget_owls - c.spent_owls), 0) AS held_owls
  FROM ledger l LEFT JOIN commissions c
    ON c.action_id = l.action_id AND c.settled_at IS NULL
 WHERE l.status = 'open' AND l.waiting_on IS NOT NULL
 GROUP BY l.kind, l.waiting_on ORDER BY since;
```

**What is not here.** Only public data: no emails, keys, balances or
unfunded drafts, and no funder or contributor identities.

If a question needs something the views lack, say so with raise_issue.
Grantmaker · 1 section · 11,187 characters
# Method skill: Sql (version 13)

This skill says how the constitution and your role apply to one kind of work. It never outranks either.

## For every administrator

query_sql runs one read-only SELECT against views of the graph's public
data. It is the way to ask questions the other reads can't: which important
nodes have disputes waiting, what reassessments cost and how often they
changed a verdict, what a mandate has funded and what it bought. To find
nodes by meaning, use search_claims first and pass its ids in
(`WHERE n.id = ANY($1::uuid[])`); SQL can't search by meaning.

**Conventions.** Ids are uuids. Times are UTC. Money is in owls.
importance, contestation, confidence and credence run from 0 to 1. A status
is one of verified, supported, inconclusive, doubtful, contradicted or
unknown.

**The views.**

- `nodes`: id, kind (claim, quantity, question), text, claim_type, state,
  merged_into, importance, contestation, steward_state, stewarded_at,
  proposed_by_person, tags (array of slugs), created_at, updated_at,
  steward_park_reason (null unless steward_state is 'error': the node is
  parked after failed Steward passes and will not be assessed until someone
  commissions a pass on it; one of credentials_fault, model_refusal,
  database_fault, tool_failure, provider_error, other)
- `assessments`: id, node_id, status, confidence, credence, marginal_yield,
  is_current, assessed_at, trigger, summary, reasoning_head (the first 500
  characters), relabeled_from (the retired label, contested or
  unsupported, a migration carried the status over from; set until the
  node is re-judged, so such a status is provisional, not a finding)
- `edges`: id, parent_id, child_id, relation, reasoning, created_at
- `arguments`: id, node_id, name, stance, shows, description, created_at,
  retired_at
- `tags`: slug, name, description, status, node_count
- `sources`: id, url, title, source_type, publisher, published_date, doi,
  retrieved_at
- `instances`: where a claim is asserted. id, node_id, source_id, stance,
  speaker, publication, source_date, verbatim_head, created_at, detached_at
- `ledger`: every piece of graph work. action_id, kind, variant,
  target_node_id, target_ref, label, status (open, running, finished,
  cancelled), spent_owls, opened_at, updated_at, waiting_on (null unless
  the row is open, a platform fault stopped its last attempt and the
  platform's next attempt is still ahead: one of
  credits_fault, the platform's account with a model provider is out of
  credits; credentials_fault, a provider rejected the platform's key;
  provider_unavailable, a provider or network failure that outlasted its
  retries), waiting_since, next_attempt_at (always in the future: once it
  has come all three are null and the row is due, a plain open row the
  platform picks when its turn comes). A row with waiting_on has not
  failed and is not cancelled: it stays funded, no attempt is charged, and
  the platform retries it on its own, so commissioning it again buys
  nothing. Its budget stays held meanwhile and counts against the
  mandate's pace from when it was placed, as any held budget does.
  extraction (null unless the row is a running ingest: queued, its source
  is waiting its turn to be read; extracting, a worker is reading it),
  extraction_started_at (when the current reading began; null while
  queued), queued_ahead (for a queued ingest, about how many extractions
  submitted before it are still waiting; the queue does not promise its
  order). A running ingest is not necessarily being read: say queued when
  it is
- `commissions`: the money on each piece of work. commission_id, action_id,
  exclusion_group, payer_kind (mandate, person), payer_mandate_id,
  budget_owls, spent_owls, returned_owls, commissioned_by, brief, reason,
  parent_action_id (the run that paid, when an agent spent from its own
  budget), created_at, settled_at
- `messages`: what was sent to a node's Steward. message_id, node_id,
  trigger, sender_kind, sender_node_id, paid, body, created_at, read_at,
  outcome (changed, no_change, disagree), outcome_note
- `mandates`: mandate_id, title, objective, status, is_platform, pace
  (jsonb: `{"kind":"as_needed"}`, or `{"kind":"steady","owls":…,
  "period_hours":…}` for at most that much committed in any rolling
  window), reserve_owls and reserve_reason (what only the Grantmaker may
  commit, and why), escrow_owls, operating_policy, created_at
- `mandate_decisions`: every commission, grant, refusal, decline and note
  a mandate's agents made. decision_id, mandate_id, decided_by, item_kind,
  decision, target, owls, reason, petition_id, action_id, created_at
- `plan_items`: each item of a mandate's plan, as its page shows it, with
  the standing the plan materializer last wrote on it. mandate_id,
  item_index, plan_cursor (it stands past the last item whose work has
  run or is running; an item before it can still be waiting), action,
  node_id, url, partition, variant, focus, rationale, ledger_status,
  ledger_reason, action_id (the ledger row it names), exclusion_group,
  ledger_checked_at, proposed_kind, proposed_text, proposal_ref, node_ref,
  contribution_id, added_by (who put the item in the plan:
  grantmaker_draft, grantmaker_planning, grantmaker_chat with the funder,
  or grantmaker_review, its own pass whatever woke it), added_at and
  added_run_id (null on items added before these were recorded). Join action_id to `ledger` to check a plan against
  what ran: a named row that is missing, or whose status disagrees with
  ledger_status, is a plan out of step with its ledger. A `propose` item
  is a node the plan asked the graph to take in: proposed_kind and
  proposed_text are what it proposed, contribution_id the contribution it
  filed (join `contributions`), and node_id the node it became or landed
  on once accepted. An item with node_ref and no node_id is waiting on the
  proposal whose proposal_ref that is.
  An `assess`, `reassess` or `deepen` item is a
  standing order its mandate commissions: once placed, its money is the
  row in `commissions` on that action_id with commissioned_by `plan`. A
  ledger_status of `waiting` on one is an order the mandate's pace, its
  Grantmaker's reserve, or its escrow has no room for yet, and `blocked` one
  that could never fit, or one stored with no variant, which commissions
  nothing until its Grantmaker names a tier; ledger_reason gives the tier
  and the figures. `cancelled` with a ledger_reason beginning "withdrawn" is
  an item its Grantmaker withdrew before its pass began. A deepen item
  orders passes only on the node's children that carry no assessment.
- `petitions`: petition_id, mandate_id, kind, asked_owls, granted_owls,
  requester_agent, requester_node_id, status, plan, reason, created_at,
  decided_at
- `contributions`: contribution_id, node_id, type, review_status,
  submitted_at
- `requests`: request_id, ask, why, state, keeper_kind, keeper_node_id,
  budget_owls, created_at, closed_at
- `changes`: the change stream as one table. kind, node_id, at, summary.
  kind `state_changed` is a node archived, restored, merged or deprecated;
  its summary reads `<from> -> <to> by <who>: <reason>`, with the
  successors that carry on what the node stated, if any

**What is fast.** Ids, node_id and target_node_id on every view, tags (use
`= ANY` or `&&`), importance, assessed_at and created_at. Filter on these
first, join on ids, and aggregate in the query rather than returning rows to
count. A query the planner prices too high is refused before it runs, with
its estimate.

**Queries for common questions.**

Important nodes under a tag that have gone stale:

```sql
SELECT n.id, n.text, n.importance, a.assessed_at
  FROM nodes n JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE $1 = ANY(n.tags) AND n.importance >= 0.5
   AND a.assessed_at < now() - interval '60 days'
 ORDER BY n.importance DESC LIMIT 50;
```

Messages waiting longest on important nodes:

```sql
SELECT m.node_id, n.text, m.trigger, now() - m.created_at AS waiting
  FROM messages m JOIN nodes n ON n.id = m.node_id
 WHERE m.read_at IS NULL AND n.importance >= 0.6
 ORDER BY m.created_at LIMIT 50;
```

What each kind of work cost over the last 30 days, and how much of its
budget it used:

```sql
SELECT l.kind, count(*) AS runs, sum(c.spent_owls) AS spent,
       round(avg(c.spent_owls / nullif(c.budget_owls, 0)), 2) AS budget_used,
       percentile_cont(0.8) WITHIN GROUP (ORDER BY c.spent_owls) AS p80
  FROM commissions c JOIN ledger l USING (action_id)
 WHERE c.settled_at > now() - interval '30 days'
 GROUP BY l.kind ORDER BY spent DESC;
```

Everything beneath a node, with the signals for deciding where work goes
(a scope survey): standing, age, expected gain from another pass, and
subclaims still waiting on a deepen. For a territory found by meaning,
start from search_claims' ids instead of the subtree.

```sql
WITH RECURSIVE sub(id) AS (
  SELECT $1::uuid
  UNION SELECT e.child_id FROM edges e JOIN sub ON e.parent_id = sub.id)
SELECT n.id, n.text, n.importance, n.contestation, n.steward_state,
       n.steward_park_reason,
       a.status, now()::date - a.assessed_at::date AS days_since_assessed,
       a.marginal_yield,
       (SELECT count(*) FROM edges e JOIN nodes c ON c.id = e.child_id
         WHERE e.parent_id = n.id AND c.steward_state = 'deferred') AS deferred_subclaims
  FROM sub JOIN nodes n USING (id)
  LEFT JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;
```

Statuses carried over from a retired label and not yet re-judged, most
important first, with the reassessment open on each and the budget already
committed to it. Price what is left with the cost query above (kind
`reassess`):

```sql
SELECT n.id, n.text, n.importance, a.status, a.relabeled_from, a.assessed_at,
       r.open_reassess, r.committed_owls
  FROM assessments a JOIN nodes n ON n.id = a.node_id
  LEFT JOIN LATERAL (
    SELECT count(DISTINCT l.action_id) AS open_reassess,
           coalesce(sum(c.budget_owls - c.spent_owls)
                      FILTER (WHERE c.settled_at IS NULL), 0) AS committed_owls
      FROM ledger l LEFT JOIN commissions c USING (action_id)
     WHERE l.target_node_id = n.id AND l.kind = 'reassess'
       AND l.status IN ('open', 'running')) r ON true
 WHERE a.is_current AND a.relabeled_from IS NOT NULL AND n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;
```

Funded work that is waiting on a platform fault, with what is held on it:

```sql
SELECT l.kind, l.waiting_on, count(DISTINCT l.action_id) AS rows,
       min(l.waiting_since) AS since, min(l.next_attempt_at) AS next_attempt,
       coalesce(sum(c.budget_owls - c.spent_owls), 0) AS held_owls
  FROM ledger l LEFT JOIN commissions c
    ON c.action_id = l.action_id AND c.settled_at IS NULL
 WHERE l.status = 'open' AND l.waiting_on IS NOT NULL
 GROUP BY l.kind, l.waiting_on ORDER BY since;
```

**What is not here.** Only public data: no emails, keys, balances or
unfunded drafts, and no funder or contributor identities.

If a question needs something the views lack, say so with raise_issue.
Lookout · 1 section · 11,187 characters
# Method skill: Sql (version 13)

This skill says how the constitution and your role apply to one kind of work. It never outranks either.

## For every administrator

query_sql runs one read-only SELECT against views of the graph's public
data. It is the way to ask questions the other reads can't: which important
nodes have disputes waiting, what reassessments cost and how often they
changed a verdict, what a mandate has funded and what it bought. To find
nodes by meaning, use search_claims first and pass its ids in
(`WHERE n.id = ANY($1::uuid[])`); SQL can't search by meaning.

**Conventions.** Ids are uuids. Times are UTC. Money is in owls.
importance, contestation, confidence and credence run from 0 to 1. A status
is one of verified, supported, inconclusive, doubtful, contradicted or
unknown.

**The views.**

- `nodes`: id, kind (claim, quantity, question), text, claim_type, state,
  merged_into, importance, contestation, steward_state, stewarded_at,
  proposed_by_person, tags (array of slugs), created_at, updated_at,
  steward_park_reason (null unless steward_state is 'error': the node is
  parked after failed Steward passes and will not be assessed until someone
  commissions a pass on it; one of credentials_fault, model_refusal,
  database_fault, tool_failure, provider_error, other)
- `assessments`: id, node_id, status, confidence, credence, marginal_yield,
  is_current, assessed_at, trigger, summary, reasoning_head (the first 500
  characters), relabeled_from (the retired label, contested or
  unsupported, a migration carried the status over from; set until the
  node is re-judged, so such a status is provisional, not a finding)
- `edges`: id, parent_id, child_id, relation, reasoning, created_at
- `arguments`: id, node_id, name, stance, shows, description, created_at,
  retired_at
- `tags`: slug, name, description, status, node_count
- `sources`: id, url, title, source_type, publisher, published_date, doi,
  retrieved_at
- `instances`: where a claim is asserted. id, node_id, source_id, stance,
  speaker, publication, source_date, verbatim_head, created_at, detached_at
- `ledger`: every piece of graph work. action_id, kind, variant,
  target_node_id, target_ref, label, status (open, running, finished,
  cancelled), spent_owls, opened_at, updated_at, waiting_on (null unless
  the row is open, a platform fault stopped its last attempt and the
  platform's next attempt is still ahead: one of
  credits_fault, the platform's account with a model provider is out of
  credits; credentials_fault, a provider rejected the platform's key;
  provider_unavailable, a provider or network failure that outlasted its
  retries), waiting_since, next_attempt_at (always in the future: once it
  has come all three are null and the row is due, a plain open row the
  platform picks when its turn comes). A row with waiting_on has not
  failed and is not cancelled: it stays funded, no attempt is charged, and
  the platform retries it on its own, so commissioning it again buys
  nothing. Its budget stays held meanwhile and counts against the
  mandate's pace from when it was placed, as any held budget does.
  extraction (null unless the row is a running ingest: queued, its source
  is waiting its turn to be read; extracting, a worker is reading it),
  extraction_started_at (when the current reading began; null while
  queued), queued_ahead (for a queued ingest, about how many extractions
  submitted before it are still waiting; the queue does not promise its
  order). A running ingest is not necessarily being read: say queued when
  it is
- `commissions`: the money on each piece of work. commission_id, action_id,
  exclusion_group, payer_kind (mandate, person), payer_mandate_id,
  budget_owls, spent_owls, returned_owls, commissioned_by, brief, reason,
  parent_action_id (the run that paid, when an agent spent from its own
  budget), created_at, settled_at
- `messages`: what was sent to a node's Steward. message_id, node_id,
  trigger, sender_kind, sender_node_id, paid, body, created_at, read_at,
  outcome (changed, no_change, disagree), outcome_note
- `mandates`: mandate_id, title, objective, status, is_platform, pace
  (jsonb: `{"kind":"as_needed"}`, or `{"kind":"steady","owls":…,
  "period_hours":…}` for at most that much committed in any rolling
  window), reserve_owls and reserve_reason (what only the Grantmaker may
  commit, and why), escrow_owls, operating_policy, created_at
- `mandate_decisions`: every commission, grant, refusal, decline and note
  a mandate's agents made. decision_id, mandate_id, decided_by, item_kind,
  decision, target, owls, reason, petition_id, action_id, created_at
- `plan_items`: each item of a mandate's plan, as its page shows it, with
  the standing the plan materializer last wrote on it. mandate_id,
  item_index, plan_cursor (it stands past the last item whose work has
  run or is running; an item before it can still be waiting), action,
  node_id, url, partition, variant, focus, rationale, ledger_status,
  ledger_reason, action_id (the ledger row it names), exclusion_group,
  ledger_checked_at, proposed_kind, proposed_text, proposal_ref, node_ref,
  contribution_id, added_by (who put the item in the plan:
  grantmaker_draft, grantmaker_planning, grantmaker_chat with the funder,
  or grantmaker_review, its own pass whatever woke it), added_at and
  added_run_id (null on items added before these were recorded). Join action_id to `ledger` to check a plan against
  what ran: a named row that is missing, or whose status disagrees with
  ledger_status, is a plan out of step with its ledger. A `propose` item
  is a node the plan asked the graph to take in: proposed_kind and
  proposed_text are what it proposed, contribution_id the contribution it
  filed (join `contributions`), and node_id the node it became or landed
  on once accepted. An item with node_ref and no node_id is waiting on the
  proposal whose proposal_ref that is.
  An `assess`, `reassess` or `deepen` item is a
  standing order its mandate commissions: once placed, its money is the
  row in `commissions` on that action_id with commissioned_by `plan`. A
  ledger_status of `waiting` on one is an order the mandate's pace, its
  Grantmaker's reserve, or its escrow has no room for yet, and `blocked` one
  that could never fit, or one stored with no variant, which commissions
  nothing until its Grantmaker names a tier; ledger_reason gives the tier
  and the figures. `cancelled` with a ledger_reason beginning "withdrawn" is
  an item its Grantmaker withdrew before its pass began. A deepen item
  orders passes only on the node's children that carry no assessment.
- `petitions`: petition_id, mandate_id, kind, asked_owls, granted_owls,
  requester_agent, requester_node_id, status, plan, reason, created_at,
  decided_at
- `contributions`: contribution_id, node_id, type, review_status,
  submitted_at
- `requests`: request_id, ask, why, state, keeper_kind, keeper_node_id,
  budget_owls, created_at, closed_at
- `changes`: the change stream as one table. kind, node_id, at, summary.
  kind `state_changed` is a node archived, restored, merged or deprecated;
  its summary reads `<from> -> <to> by <who>: <reason>`, with the
  successors that carry on what the node stated, if any

**What is fast.** Ids, node_id and target_node_id on every view, tags (use
`= ANY` or `&&`), importance, assessed_at and created_at. Filter on these
first, join on ids, and aggregate in the query rather than returning rows to
count. A query the planner prices too high is refused before it runs, with
its estimate.

**Queries for common questions.**

Important nodes under a tag that have gone stale:

```sql
SELECT n.id, n.text, n.importance, a.assessed_at
  FROM nodes n JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE $1 = ANY(n.tags) AND n.importance >= 0.5
   AND a.assessed_at < now() - interval '60 days'
 ORDER BY n.importance DESC LIMIT 50;
```

Messages waiting longest on important nodes:

```sql
SELECT m.node_id, n.text, m.trigger, now() - m.created_at AS waiting
  FROM messages m JOIN nodes n ON n.id = m.node_id
 WHERE m.read_at IS NULL AND n.importance >= 0.6
 ORDER BY m.created_at LIMIT 50;
```

What each kind of work cost over the last 30 days, and how much of its
budget it used:

```sql
SELECT l.kind, count(*) AS runs, sum(c.spent_owls) AS spent,
       round(avg(c.spent_owls / nullif(c.budget_owls, 0)), 2) AS budget_used,
       percentile_cont(0.8) WITHIN GROUP (ORDER BY c.spent_owls) AS p80
  FROM commissions c JOIN ledger l USING (action_id)
 WHERE c.settled_at > now() - interval '30 days'
 GROUP BY l.kind ORDER BY spent DESC;
```

Everything beneath a node, with the signals for deciding where work goes
(a scope survey): standing, age, expected gain from another pass, and
subclaims still waiting on a deepen. For a territory found by meaning,
start from search_claims' ids instead of the subtree.

```sql
WITH RECURSIVE sub(id) AS (
  SELECT $1::uuid
  UNION SELECT e.child_id FROM edges e JOIN sub ON e.parent_id = sub.id)
SELECT n.id, n.text, n.importance, n.contestation, n.steward_state,
       n.steward_park_reason,
       a.status, now()::date - a.assessed_at::date AS days_since_assessed,
       a.marginal_yield,
       (SELECT count(*) FROM edges e JOIN nodes c ON c.id = e.child_id
         WHERE e.parent_id = n.id AND c.steward_state = 'deferred') AS deferred_subclaims
  FROM sub JOIN nodes n USING (id)
  LEFT JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;
```

Statuses carried over from a retired label and not yet re-judged, most
important first, with the reassessment open on each and the budget already
committed to it. Price what is left with the cost query above (kind
`reassess`):

```sql
SELECT n.id, n.text, n.importance, a.status, a.relabeled_from, a.assessed_at,
       r.open_reassess, r.committed_owls
  FROM assessments a JOIN nodes n ON n.id = a.node_id
  LEFT JOIN LATERAL (
    SELECT count(DISTINCT l.action_id) AS open_reassess,
           coalesce(sum(c.budget_owls - c.spent_owls)
                      FILTER (WHERE c.settled_at IS NULL), 0) AS committed_owls
      FROM ledger l LEFT JOIN commissions c USING (action_id)
     WHERE l.target_node_id = n.id AND l.kind = 'reassess'
       AND l.status IN ('open', 'running')) r ON true
 WHERE a.is_current AND a.relabeled_from IS NOT NULL AND n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;
```

Funded work that is waiting on a platform fault, with what is held on it:

```sql
SELECT l.kind, l.waiting_on, count(DISTINCT l.action_id) AS rows,
       min(l.waiting_since) AS since, min(l.next_attempt_at) AS next_attempt,
       coalesce(sum(c.budget_owls - c.spent_owls), 0) AS held_owls
  FROM ledger l LEFT JOIN commissions c
    ON c.action_id = l.action_id AND c.settled_at IS NULL
 WHERE l.status = 'open' AND l.waiting_on IS NOT NULL
 GROUP BY l.kind, l.waiting_on ORDER BY since;
```

**What is not here.** Only public data: no emails, keys, balances or
unfunded drafts, and no funder or contributor identities.

If a question needs something the views lack, say so with raise_issue.
Correspondent · 1 section · 11,187 characters
# Method skill: Sql (version 13)

This skill says how the constitution and your role apply to one kind of work. It never outranks either.

## For every administrator

query_sql runs one read-only SELECT against views of the graph's public
data. It is the way to ask questions the other reads can't: which important
nodes have disputes waiting, what reassessments cost and how often they
changed a verdict, what a mandate has funded and what it bought. To find
nodes by meaning, use search_claims first and pass its ids in
(`WHERE n.id = ANY($1::uuid[])`); SQL can't search by meaning.

**Conventions.** Ids are uuids. Times are UTC. Money is in owls.
importance, contestation, confidence and credence run from 0 to 1. A status
is one of verified, supported, inconclusive, doubtful, contradicted or
unknown.

**The views.**

- `nodes`: id, kind (claim, quantity, question), text, claim_type, state,
  merged_into, importance, contestation, steward_state, stewarded_at,
  proposed_by_person, tags (array of slugs), created_at, updated_at,
  steward_park_reason (null unless steward_state is 'error': the node is
  parked after failed Steward passes and will not be assessed until someone
  commissions a pass on it; one of credentials_fault, model_refusal,
  database_fault, tool_failure, provider_error, other)
- `assessments`: id, node_id, status, confidence, credence, marginal_yield,
  is_current, assessed_at, trigger, summary, reasoning_head (the first 500
  characters), relabeled_from (the retired label, contested or
  unsupported, a migration carried the status over from; set until the
  node is re-judged, so such a status is provisional, not a finding)
- `edges`: id, parent_id, child_id, relation, reasoning, created_at
- `arguments`: id, node_id, name, stance, shows, description, created_at,
  retired_at
- `tags`: slug, name, description, status, node_count
- `sources`: id, url, title, source_type, publisher, published_date, doi,
  retrieved_at
- `instances`: where a claim is asserted. id, node_id, source_id, stance,
  speaker, publication, source_date, verbatim_head, created_at, detached_at
- `ledger`: every piece of graph work. action_id, kind, variant,
  target_node_id, target_ref, label, status (open, running, finished,
  cancelled), spent_owls, opened_at, updated_at, waiting_on (null unless
  the row is open, a platform fault stopped its last attempt and the
  platform's next attempt is still ahead: one of
  credits_fault, the platform's account with a model provider is out of
  credits; credentials_fault, a provider rejected the platform's key;
  provider_unavailable, a provider or network failure that outlasted its
  retries), waiting_since, next_attempt_at (always in the future: once it
  has come all three are null and the row is due, a plain open row the
  platform picks when its turn comes). A row with waiting_on has not
  failed and is not cancelled: it stays funded, no attempt is charged, and
  the platform retries it on its own, so commissioning it again buys
  nothing. Its budget stays held meanwhile and counts against the
  mandate's pace from when it was placed, as any held budget does.
  extraction (null unless the row is a running ingest: queued, its source
  is waiting its turn to be read; extracting, a worker is reading it),
  extraction_started_at (when the current reading began; null while
  queued), queued_ahead (for a queued ingest, about how many extractions
  submitted before it are still waiting; the queue does not promise its
  order). A running ingest is not necessarily being read: say queued when
  it is
- `commissions`: the money on each piece of work. commission_id, action_id,
  exclusion_group, payer_kind (mandate, person), payer_mandate_id,
  budget_owls, spent_owls, returned_owls, commissioned_by, brief, reason,
  parent_action_id (the run that paid, when an agent spent from its own
  budget), created_at, settled_at
- `messages`: what was sent to a node's Steward. message_id, node_id,
  trigger, sender_kind, sender_node_id, paid, body, created_at, read_at,
  outcome (changed, no_change, disagree), outcome_note
- `mandates`: mandate_id, title, objective, status, is_platform, pace
  (jsonb: `{"kind":"as_needed"}`, or `{"kind":"steady","owls":…,
  "period_hours":…}` for at most that much committed in any rolling
  window), reserve_owls and reserve_reason (what only the Grantmaker may
  commit, and why), escrow_owls, operating_policy, created_at
- `mandate_decisions`: every commission, grant, refusal, decline and note
  a mandate's agents made. decision_id, mandate_id, decided_by, item_kind,
  decision, target, owls, reason, petition_id, action_id, created_at
- `plan_items`: each item of a mandate's plan, as its page shows it, with
  the standing the plan materializer last wrote on it. mandate_id,
  item_index, plan_cursor (it stands past the last item whose work has
  run or is running; an item before it can still be waiting), action,
  node_id, url, partition, variant, focus, rationale, ledger_status,
  ledger_reason, action_id (the ledger row it names), exclusion_group,
  ledger_checked_at, proposed_kind, proposed_text, proposal_ref, node_ref,
  contribution_id, added_by (who put the item in the plan:
  grantmaker_draft, grantmaker_planning, grantmaker_chat with the funder,
  or grantmaker_review, its own pass whatever woke it), added_at and
  added_run_id (null on items added before these were recorded). Join action_id to `ledger` to check a plan against
  what ran: a named row that is missing, or whose status disagrees with
  ledger_status, is a plan out of step with its ledger. A `propose` item
  is a node the plan asked the graph to take in: proposed_kind and
  proposed_text are what it proposed, contribution_id the contribution it
  filed (join `contributions`), and node_id the node it became or landed
  on once accepted. An item with node_ref and no node_id is waiting on the
  proposal whose proposal_ref that is.
  An `assess`, `reassess` or `deepen` item is a
  standing order its mandate commissions: once placed, its money is the
  row in `commissions` on that action_id with commissioned_by `plan`. A
  ledger_status of `waiting` on one is an order the mandate's pace, its
  Grantmaker's reserve, or its escrow has no room for yet, and `blocked` one
  that could never fit, or one stored with no variant, which commissions
  nothing until its Grantmaker names a tier; ledger_reason gives the tier
  and the figures. `cancelled` with a ledger_reason beginning "withdrawn" is
  an item its Grantmaker withdrew before its pass began. A deepen item
  orders passes only on the node's children that carry no assessment.
- `petitions`: petition_id, mandate_id, kind, asked_owls, granted_owls,
  requester_agent, requester_node_id, status, plan, reason, created_at,
  decided_at
- `contributions`: contribution_id, node_id, type, review_status,
  submitted_at
- `requests`: request_id, ask, why, state, keeper_kind, keeper_node_id,
  budget_owls, created_at, closed_at
- `changes`: the change stream as one table. kind, node_id, at, summary.
  kind `state_changed` is a node archived, restored, merged or deprecated;
  its summary reads `<from> -> <to> by <who>: <reason>`, with the
  successors that carry on what the node stated, if any

**What is fast.** Ids, node_id and target_node_id on every view, tags (use
`= ANY` or `&&`), importance, assessed_at and created_at. Filter on these
first, join on ids, and aggregate in the query rather than returning rows to
count. A query the planner prices too high is refused before it runs, with
its estimate.

**Queries for common questions.**

Important nodes under a tag that have gone stale:

```sql
SELECT n.id, n.text, n.importance, a.assessed_at
  FROM nodes n JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE $1 = ANY(n.tags) AND n.importance >= 0.5
   AND a.assessed_at < now() - interval '60 days'
 ORDER BY n.importance DESC LIMIT 50;
```

Messages waiting longest on important nodes:

```sql
SELECT m.node_id, n.text, m.trigger, now() - m.created_at AS waiting
  FROM messages m JOIN nodes n ON n.id = m.node_id
 WHERE m.read_at IS NULL AND n.importance >= 0.6
 ORDER BY m.created_at LIMIT 50;
```

What each kind of work cost over the last 30 days, and how much of its
budget it used:

```sql
SELECT l.kind, count(*) AS runs, sum(c.spent_owls) AS spent,
       round(avg(c.spent_owls / nullif(c.budget_owls, 0)), 2) AS budget_used,
       percentile_cont(0.8) WITHIN GROUP (ORDER BY c.spent_owls) AS p80
  FROM commissions c JOIN ledger l USING (action_id)
 WHERE c.settled_at > now() - interval '30 days'
 GROUP BY l.kind ORDER BY spent DESC;
```

Everything beneath a node, with the signals for deciding where work goes
(a scope survey): standing, age, expected gain from another pass, and
subclaims still waiting on a deepen. For a territory found by meaning,
start from search_claims' ids instead of the subtree.

```sql
WITH RECURSIVE sub(id) AS (
  SELECT $1::uuid
  UNION SELECT e.child_id FROM edges e JOIN sub ON e.parent_id = sub.id)
SELECT n.id, n.text, n.importance, n.contestation, n.steward_state,
       n.steward_park_reason,
       a.status, now()::date - a.assessed_at::date AS days_since_assessed,
       a.marginal_yield,
       (SELECT count(*) FROM edges e JOIN nodes c ON c.id = e.child_id
         WHERE e.parent_id = n.id AND c.steward_state = 'deferred') AS deferred_subclaims
  FROM sub JOIN nodes n USING (id)
  LEFT JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;
```

Statuses carried over from a retired label and not yet re-judged, most
important first, with the reassessment open on each and the budget already
committed to it. Price what is left with the cost query above (kind
`reassess`):

```sql
SELECT n.id, n.text, n.importance, a.status, a.relabeled_from, a.assessed_at,
       r.open_reassess, r.committed_owls
  FROM assessments a JOIN nodes n ON n.id = a.node_id
  LEFT JOIN LATERAL (
    SELECT count(DISTINCT l.action_id) AS open_reassess,
           coalesce(sum(c.budget_owls - c.spent_owls)
                      FILTER (WHERE c.settled_at IS NULL), 0) AS committed_owls
      FROM ledger l LEFT JOIN commissions c USING (action_id)
     WHERE l.target_node_id = n.id AND l.kind = 'reassess'
       AND l.status IN ('open', 'running')) r ON true
 WHERE a.is_current AND a.relabeled_from IS NOT NULL AND n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;
```

Funded work that is waiting on a platform fault, with what is held on it:

```sql
SELECT l.kind, l.waiting_on, count(DISTINCT l.action_id) AS rows,
       min(l.waiting_since) AS since, min(l.next_attempt_at) AS next_attempt,
       coalesce(sum(c.budget_owls - c.spent_owls), 0) AS held_owls
  FROM ledger l LEFT JOIN commissions c
    ON c.action_id = l.action_id AND c.settled_at IS NULL
 WHERE l.status = 'open' AND l.waiting_on IS NOT NULL
 GROUP BY l.kind, l.waiting_on ORDER BY since;
```

**What is not here.** Only public data: no emails, keys, balances or
unfunded drafts, and no funder or contributor identities.

If a question needs something the views lack, say so with raise_issue.
Program Officer · 1 section · 11,187 characters
# Method skill: Sql (version 13)

This skill says how the constitution and your role apply to one kind of work. It never outranks either.

## For every administrator

query_sql runs one read-only SELECT against views of the graph's public
data. It is the way to ask questions the other reads can't: which important
nodes have disputes waiting, what reassessments cost and how often they
changed a verdict, what a mandate has funded and what it bought. To find
nodes by meaning, use search_claims first and pass its ids in
(`WHERE n.id = ANY($1::uuid[])`); SQL can't search by meaning.

**Conventions.** Ids are uuids. Times are UTC. Money is in owls.
importance, contestation, confidence and credence run from 0 to 1. A status
is one of verified, supported, inconclusive, doubtful, contradicted or
unknown.

**The views.**

- `nodes`: id, kind (claim, quantity, question), text, claim_type, state,
  merged_into, importance, contestation, steward_state, stewarded_at,
  proposed_by_person, tags (array of slugs), created_at, updated_at,
  steward_park_reason (null unless steward_state is 'error': the node is
  parked after failed Steward passes and will not be assessed until someone
  commissions a pass on it; one of credentials_fault, model_refusal,
  database_fault, tool_failure, provider_error, other)
- `assessments`: id, node_id, status, confidence, credence, marginal_yield,
  is_current, assessed_at, trigger, summary, reasoning_head (the first 500
  characters), relabeled_from (the retired label, contested or
  unsupported, a migration carried the status over from; set until the
  node is re-judged, so such a status is provisional, not a finding)
- `edges`: id, parent_id, child_id, relation, reasoning, created_at
- `arguments`: id, node_id, name, stance, shows, description, created_at,
  retired_at
- `tags`: slug, name, description, status, node_count
- `sources`: id, url, title, source_type, publisher, published_date, doi,
  retrieved_at
- `instances`: where a claim is asserted. id, node_id, source_id, stance,
  speaker, publication, source_date, verbatim_head, created_at, detached_at
- `ledger`: every piece of graph work. action_id, kind, variant,
  target_node_id, target_ref, label, status (open, running, finished,
  cancelled), spent_owls, opened_at, updated_at, waiting_on (null unless
  the row is open, a platform fault stopped its last attempt and the
  platform's next attempt is still ahead: one of
  credits_fault, the platform's account with a model provider is out of
  credits; credentials_fault, a provider rejected the platform's key;
  provider_unavailable, a provider or network failure that outlasted its
  retries), waiting_since, next_attempt_at (always in the future: once it
  has come all three are null and the row is due, a plain open row the
  platform picks when its turn comes). A row with waiting_on has not
  failed and is not cancelled: it stays funded, no attempt is charged, and
  the platform retries it on its own, so commissioning it again buys
  nothing. Its budget stays held meanwhile and counts against the
  mandate's pace from when it was placed, as any held budget does.
  extraction (null unless the row is a running ingest: queued, its source
  is waiting its turn to be read; extracting, a worker is reading it),
  extraction_started_at (when the current reading began; null while
  queued), queued_ahead (for a queued ingest, about how many extractions
  submitted before it are still waiting; the queue does not promise its
  order). A running ingest is not necessarily being read: say queued when
  it is
- `commissions`: the money on each piece of work. commission_id, action_id,
  exclusion_group, payer_kind (mandate, person), payer_mandate_id,
  budget_owls, spent_owls, returned_owls, commissioned_by, brief, reason,
  parent_action_id (the run that paid, when an agent spent from its own
  budget), created_at, settled_at
- `messages`: what was sent to a node's Steward. message_id, node_id,
  trigger, sender_kind, sender_node_id, paid, body, created_at, read_at,
  outcome (changed, no_change, disagree), outcome_note
- `mandates`: mandate_id, title, objective, status, is_platform, pace
  (jsonb: `{"kind":"as_needed"}`, or `{"kind":"steady","owls":…,
  "period_hours":…}` for at most that much committed in any rolling
  window), reserve_owls and reserve_reason (what only the Grantmaker may
  commit, and why), escrow_owls, operating_policy, created_at
- `mandate_decisions`: every commission, grant, refusal, decline and note
  a mandate's agents made. decision_id, mandate_id, decided_by, item_kind,
  decision, target, owls, reason, petition_id, action_id, created_at
- `plan_items`: each item of a mandate's plan, as its page shows it, with
  the standing the plan materializer last wrote on it. mandate_id,
  item_index, plan_cursor (it stands past the last item whose work has
  run or is running; an item before it can still be waiting), action,
  node_id, url, partition, variant, focus, rationale, ledger_status,
  ledger_reason, action_id (the ledger row it names), exclusion_group,
  ledger_checked_at, proposed_kind, proposed_text, proposal_ref, node_ref,
  contribution_id, added_by (who put the item in the plan:
  grantmaker_draft, grantmaker_planning, grantmaker_chat with the funder,
  or grantmaker_review, its own pass whatever woke it), added_at and
  added_run_id (null on items added before these were recorded). Join action_id to `ledger` to check a plan against
  what ran: a named row that is missing, or whose status disagrees with
  ledger_status, is a plan out of step with its ledger. A `propose` item
  is a node the plan asked the graph to take in: proposed_kind and
  proposed_text are what it proposed, contribution_id the contribution it
  filed (join `contributions`), and node_id the node it became or landed
  on once accepted. An item with node_ref and no node_id is waiting on the
  proposal whose proposal_ref that is.
  An `assess`, `reassess` or `deepen` item is a
  standing order its mandate commissions: once placed, its money is the
  row in `commissions` on that action_id with commissioned_by `plan`. A
  ledger_status of `waiting` on one is an order the mandate's pace, its
  Grantmaker's reserve, or its escrow has no room for yet, and `blocked` one
  that could never fit, or one stored with no variant, which commissions
  nothing until its Grantmaker names a tier; ledger_reason gives the tier
  and the figures. `cancelled` with a ledger_reason beginning "withdrawn" is
  an item its Grantmaker withdrew before its pass began. A deepen item
  orders passes only on the node's children that carry no assessment.
- `petitions`: petition_id, mandate_id, kind, asked_owls, granted_owls,
  requester_agent, requester_node_id, status, plan, reason, created_at,
  decided_at
- `contributions`: contribution_id, node_id, type, review_status,
  submitted_at
- `requests`: request_id, ask, why, state, keeper_kind, keeper_node_id,
  budget_owls, created_at, closed_at
- `changes`: the change stream as one table. kind, node_id, at, summary.
  kind `state_changed` is a node archived, restored, merged or deprecated;
  its summary reads `<from> -> <to> by <who>: <reason>`, with the
  successors that carry on what the node stated, if any

**What is fast.** Ids, node_id and target_node_id on every view, tags (use
`= ANY` or `&&`), importance, assessed_at and created_at. Filter on these
first, join on ids, and aggregate in the query rather than returning rows to
count. A query the planner prices too high is refused before it runs, with
its estimate.

**Queries for common questions.**

Important nodes under a tag that have gone stale:

```sql
SELECT n.id, n.text, n.importance, a.assessed_at
  FROM nodes n JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE $1 = ANY(n.tags) AND n.importance >= 0.5
   AND a.assessed_at < now() - interval '60 days'
 ORDER BY n.importance DESC LIMIT 50;
```

Messages waiting longest on important nodes:

```sql
SELECT m.node_id, n.text, m.trigger, now() - m.created_at AS waiting
  FROM messages m JOIN nodes n ON n.id = m.node_id
 WHERE m.read_at IS NULL AND n.importance >= 0.6
 ORDER BY m.created_at LIMIT 50;
```

What each kind of work cost over the last 30 days, and how much of its
budget it used:

```sql
SELECT l.kind, count(*) AS runs, sum(c.spent_owls) AS spent,
       round(avg(c.spent_owls / nullif(c.budget_owls, 0)), 2) AS budget_used,
       percentile_cont(0.8) WITHIN GROUP (ORDER BY c.spent_owls) AS p80
  FROM commissions c JOIN ledger l USING (action_id)
 WHERE c.settled_at > now() - interval '30 days'
 GROUP BY l.kind ORDER BY spent DESC;
```

Everything beneath a node, with the signals for deciding where work goes
(a scope survey): standing, age, expected gain from another pass, and
subclaims still waiting on a deepen. For a territory found by meaning,
start from search_claims' ids instead of the subtree.

```sql
WITH RECURSIVE sub(id) AS (
  SELECT $1::uuid
  UNION SELECT e.child_id FROM edges e JOIN sub ON e.parent_id = sub.id)
SELECT n.id, n.text, n.importance, n.contestation, n.steward_state,
       n.steward_park_reason,
       a.status, now()::date - a.assessed_at::date AS days_since_assessed,
       a.marginal_yield,
       (SELECT count(*) FROM edges e JOIN nodes c ON c.id = e.child_id
         WHERE e.parent_id = n.id AND c.steward_state = 'deferred') AS deferred_subclaims
  FROM sub JOIN nodes n USING (id)
  LEFT JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;
```

Statuses carried over from a retired label and not yet re-judged, most
important first, with the reassessment open on each and the budget already
committed to it. Price what is left with the cost query above (kind
`reassess`):

```sql
SELECT n.id, n.text, n.importance, a.status, a.relabeled_from, a.assessed_at,
       r.open_reassess, r.committed_owls
  FROM assessments a JOIN nodes n ON n.id = a.node_id
  LEFT JOIN LATERAL (
    SELECT count(DISTINCT l.action_id) AS open_reassess,
           coalesce(sum(c.budget_owls - c.spent_owls)
                      FILTER (WHERE c.settled_at IS NULL), 0) AS committed_owls
      FROM ledger l LEFT JOIN commissions c USING (action_id)
     WHERE l.target_node_id = n.id AND l.kind = 'reassess'
       AND l.status IN ('open', 'running')) r ON true
 WHERE a.is_current AND a.relabeled_from IS NOT NULL AND n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;
```

Funded work that is waiting on a platform fault, with what is held on it:

```sql
SELECT l.kind, l.waiting_on, count(DISTINCT l.action_id) AS rows,
       min(l.waiting_since) AS since, min(l.next_attempt_at) AS next_attempt,
       coalesce(sum(c.budget_owls - c.spent_owls), 0) AS held_owls
  FROM ledger l LEFT JOIN commissions c
    ON c.action_id = l.action_id AND c.settled_at IS NULL
 WHERE l.status = 'open' AND l.waiting_on IS NOT NULL
 GROUP BY l.kind, l.waiting_on ORDER BY since;
```

**What is not here.** Only public data: no emails, keys, balances or
unfunded drafts, and no funder or contributor identities.

If a question needs something the views lack, say so with raise_issue.
Contribution Reviewer · 1 section · 11,187 characters
# Method skill: Sql (version 13)

This skill says how the constitution and your role apply to one kind of work. It never outranks either.

## For every administrator

query_sql runs one read-only SELECT against views of the graph's public
data. It is the way to ask questions the other reads can't: which important
nodes have disputes waiting, what reassessments cost and how often they
changed a verdict, what a mandate has funded and what it bought. To find
nodes by meaning, use search_claims first and pass its ids in
(`WHERE n.id = ANY($1::uuid[])`); SQL can't search by meaning.

**Conventions.** Ids are uuids. Times are UTC. Money is in owls.
importance, contestation, confidence and credence run from 0 to 1. A status
is one of verified, supported, inconclusive, doubtful, contradicted or
unknown.

**The views.**

- `nodes`: id, kind (claim, quantity, question), text, claim_type, state,
  merged_into, importance, contestation, steward_state, stewarded_at,
  proposed_by_person, tags (array of slugs), created_at, updated_at,
  steward_park_reason (null unless steward_state is 'error': the node is
  parked after failed Steward passes and will not be assessed until someone
  commissions a pass on it; one of credentials_fault, model_refusal,
  database_fault, tool_failure, provider_error, other)
- `assessments`: id, node_id, status, confidence, credence, marginal_yield,
  is_current, assessed_at, trigger, summary, reasoning_head (the first 500
  characters), relabeled_from (the retired label, contested or
  unsupported, a migration carried the status over from; set until the
  node is re-judged, so such a status is provisional, not a finding)
- `edges`: id, parent_id, child_id, relation, reasoning, created_at
- `arguments`: id, node_id, name, stance, shows, description, created_at,
  retired_at
- `tags`: slug, name, description, status, node_count
- `sources`: id, url, title, source_type, publisher, published_date, doi,
  retrieved_at
- `instances`: where a claim is asserted. id, node_id, source_id, stance,
  speaker, publication, source_date, verbatim_head, created_at, detached_at
- `ledger`: every piece of graph work. action_id, kind, variant,
  target_node_id, target_ref, label, status (open, running, finished,
  cancelled), spent_owls, opened_at, updated_at, waiting_on (null unless
  the row is open, a platform fault stopped its last attempt and the
  platform's next attempt is still ahead: one of
  credits_fault, the platform's account with a model provider is out of
  credits; credentials_fault, a provider rejected the platform's key;
  provider_unavailable, a provider or network failure that outlasted its
  retries), waiting_since, next_attempt_at (always in the future: once it
  has come all three are null and the row is due, a plain open row the
  platform picks when its turn comes). A row with waiting_on has not
  failed and is not cancelled: it stays funded, no attempt is charged, and
  the platform retries it on its own, so commissioning it again buys
  nothing. Its budget stays held meanwhile and counts against the
  mandate's pace from when it was placed, as any held budget does.
  extraction (null unless the row is a running ingest: queued, its source
  is waiting its turn to be read; extracting, a worker is reading it),
  extraction_started_at (when the current reading began; null while
  queued), queued_ahead (for a queued ingest, about how many extractions
  submitted before it are still waiting; the queue does not promise its
  order). A running ingest is not necessarily being read: say queued when
  it is
- `commissions`: the money on each piece of work. commission_id, action_id,
  exclusion_group, payer_kind (mandate, person), payer_mandate_id,
  budget_owls, spent_owls, returned_owls, commissioned_by, brief, reason,
  parent_action_id (the run that paid, when an agent spent from its own
  budget), created_at, settled_at
- `messages`: what was sent to a node's Steward. message_id, node_id,
  trigger, sender_kind, sender_node_id, paid, body, created_at, read_at,
  outcome (changed, no_change, disagree), outcome_note
- `mandates`: mandate_id, title, objective, status, is_platform, pace
  (jsonb: `{"kind":"as_needed"}`, or `{"kind":"steady","owls":…,
  "period_hours":…}` for at most that much committed in any rolling
  window), reserve_owls and reserve_reason (what only the Grantmaker may
  commit, and why), escrow_owls, operating_policy, created_at
- `mandate_decisions`: every commission, grant, refusal, decline and note
  a mandate's agents made. decision_id, mandate_id, decided_by, item_kind,
  decision, target, owls, reason, petition_id, action_id, created_at
- `plan_items`: each item of a mandate's plan, as its page shows it, with
  the standing the plan materializer last wrote on it. mandate_id,
  item_index, plan_cursor (it stands past the last item whose work has
  run or is running; an item before it can still be waiting), action,
  node_id, url, partition, variant, focus, rationale, ledger_status,
  ledger_reason, action_id (the ledger row it names), exclusion_group,
  ledger_checked_at, proposed_kind, proposed_text, proposal_ref, node_ref,
  contribution_id, added_by (who put the item in the plan:
  grantmaker_draft, grantmaker_planning, grantmaker_chat with the funder,
  or grantmaker_review, its own pass whatever woke it), added_at and
  added_run_id (null on items added before these were recorded). Join action_id to `ledger` to check a plan against
  what ran: a named row that is missing, or whose status disagrees with
  ledger_status, is a plan out of step with its ledger. A `propose` item
  is a node the plan asked the graph to take in: proposed_kind and
  proposed_text are what it proposed, contribution_id the contribution it
  filed (join `contributions`), and node_id the node it became or landed
  on once accepted. An item with node_ref and no node_id is waiting on the
  proposal whose proposal_ref that is.
  An `assess`, `reassess` or `deepen` item is a
  standing order its mandate commissions: once placed, its money is the
  row in `commissions` on that action_id with commissioned_by `plan`. A
  ledger_status of `waiting` on one is an order the mandate's pace, its
  Grantmaker's reserve, or its escrow has no room for yet, and `blocked` one
  that could never fit, or one stored with no variant, which commissions
  nothing until its Grantmaker names a tier; ledger_reason gives the tier
  and the figures. `cancelled` with a ledger_reason beginning "withdrawn" is
  an item its Grantmaker withdrew before its pass began. A deepen item
  orders passes only on the node's children that carry no assessment.
- `petitions`: petition_id, mandate_id, kind, asked_owls, granted_owls,
  requester_agent, requester_node_id, status, plan, reason, created_at,
  decided_at
- `contributions`: contribution_id, node_id, type, review_status,
  submitted_at
- `requests`: request_id, ask, why, state, keeper_kind, keeper_node_id,
  budget_owls, created_at, closed_at
- `changes`: the change stream as one table. kind, node_id, at, summary.
  kind `state_changed` is a node archived, restored, merged or deprecated;
  its summary reads `<from> -> <to> by <who>: <reason>`, with the
  successors that carry on what the node stated, if any

**What is fast.** Ids, node_id and target_node_id on every view, tags (use
`= ANY` or `&&`), importance, assessed_at and created_at. Filter on these
first, join on ids, and aggregate in the query rather than returning rows to
count. A query the planner prices too high is refused before it runs, with
its estimate.

**Queries for common questions.**

Important nodes under a tag that have gone stale:

```sql
SELECT n.id, n.text, n.importance, a.assessed_at
  FROM nodes n JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE $1 = ANY(n.tags) AND n.importance >= 0.5
   AND a.assessed_at < now() - interval '60 days'
 ORDER BY n.importance DESC LIMIT 50;
```

Messages waiting longest on important nodes:

```sql
SELECT m.node_id, n.text, m.trigger, now() - m.created_at AS waiting
  FROM messages m JOIN nodes n ON n.id = m.node_id
 WHERE m.read_at IS NULL AND n.importance >= 0.6
 ORDER BY m.created_at LIMIT 50;
```

What each kind of work cost over the last 30 days, and how much of its
budget it used:

```sql
SELECT l.kind, count(*) AS runs, sum(c.spent_owls) AS spent,
       round(avg(c.spent_owls / nullif(c.budget_owls, 0)), 2) AS budget_used,
       percentile_cont(0.8) WITHIN GROUP (ORDER BY c.spent_owls) AS p80
  FROM commissions c JOIN ledger l USING (action_id)
 WHERE c.settled_at > now() - interval '30 days'
 GROUP BY l.kind ORDER BY spent DESC;
```

Everything beneath a node, with the signals for deciding where work goes
(a scope survey): standing, age, expected gain from another pass, and
subclaims still waiting on a deepen. For a territory found by meaning,
start from search_claims' ids instead of the subtree.

```sql
WITH RECURSIVE sub(id) AS (
  SELECT $1::uuid
  UNION SELECT e.child_id FROM edges e JOIN sub ON e.parent_id = sub.id)
SELECT n.id, n.text, n.importance, n.contestation, n.steward_state,
       n.steward_park_reason,
       a.status, now()::date - a.assessed_at::date AS days_since_assessed,
       a.marginal_yield,
       (SELECT count(*) FROM edges e JOIN nodes c ON c.id = e.child_id
         WHERE e.parent_id = n.id AND c.steward_state = 'deferred') AS deferred_subclaims
  FROM sub JOIN nodes n USING (id)
  LEFT JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;
```

Statuses carried over from a retired label and not yet re-judged, most
important first, with the reassessment open on each and the budget already
committed to it. Price what is left with the cost query above (kind
`reassess`):

```sql
SELECT n.id, n.text, n.importance, a.status, a.relabeled_from, a.assessed_at,
       r.open_reassess, r.committed_owls
  FROM assessments a JOIN nodes n ON n.id = a.node_id
  LEFT JOIN LATERAL (
    SELECT count(DISTINCT l.action_id) AS open_reassess,
           coalesce(sum(c.budget_owls - c.spent_owls)
                      FILTER (WHERE c.settled_at IS NULL), 0) AS committed_owls
      FROM ledger l LEFT JOIN commissions c USING (action_id)
     WHERE l.target_node_id = n.id AND l.kind = 'reassess'
       AND l.status IN ('open', 'running')) r ON true
 WHERE a.is_current AND a.relabeled_from IS NOT NULL AND n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;
```

Funded work that is waiting on a platform fault, with what is held on it:

```sql
SELECT l.kind, l.waiting_on, count(DISTINCT l.action_id) AS rows,
       min(l.waiting_since) AS since, min(l.next_attempt_at) AS next_attempt,
       coalesce(sum(c.budget_owls - c.spent_owls), 0) AS held_owls
  FROM ledger l LEFT JOIN commissions c
    ON c.action_id = l.action_id AND c.settled_at IS NULL
 WHERE l.status = 'open' AND l.waiting_on IS NOT NULL
 GROUP BY l.kind, l.waiting_on ORDER BY since;
```

**What is not here.** Only public data: no emails, keys, balances or
unfunded drafts, and no funder or contributor identities.

If a question needs something the views lack, say so with raise_issue.
Dispute Arbitrator · 1 section · 11,187 characters
# Method skill: Sql (version 13)

This skill says how the constitution and your role apply to one kind of work. It never outranks either.

## For every administrator

query_sql runs one read-only SELECT against views of the graph's public
data. It is the way to ask questions the other reads can't: which important
nodes have disputes waiting, what reassessments cost and how often they
changed a verdict, what a mandate has funded and what it bought. To find
nodes by meaning, use search_claims first and pass its ids in
(`WHERE n.id = ANY($1::uuid[])`); SQL can't search by meaning.

**Conventions.** Ids are uuids. Times are UTC. Money is in owls.
importance, contestation, confidence and credence run from 0 to 1. A status
is one of verified, supported, inconclusive, doubtful, contradicted or
unknown.

**The views.**

- `nodes`: id, kind (claim, quantity, question), text, claim_type, state,
  merged_into, importance, contestation, steward_state, stewarded_at,
  proposed_by_person, tags (array of slugs), created_at, updated_at,
  steward_park_reason (null unless steward_state is 'error': the node is
  parked after failed Steward passes and will not be assessed until someone
  commissions a pass on it; one of credentials_fault, model_refusal,
  database_fault, tool_failure, provider_error, other)
- `assessments`: id, node_id, status, confidence, credence, marginal_yield,
  is_current, assessed_at, trigger, summary, reasoning_head (the first 500
  characters), relabeled_from (the retired label, contested or
  unsupported, a migration carried the status over from; set until the
  node is re-judged, so such a status is provisional, not a finding)
- `edges`: id, parent_id, child_id, relation, reasoning, created_at
- `arguments`: id, node_id, name, stance, shows, description, created_at,
  retired_at
- `tags`: slug, name, description, status, node_count
- `sources`: id, url, title, source_type, publisher, published_date, doi,
  retrieved_at
- `instances`: where a claim is asserted. id, node_id, source_id, stance,
  speaker, publication, source_date, verbatim_head, created_at, detached_at
- `ledger`: every piece of graph work. action_id, kind, variant,
  target_node_id, target_ref, label, status (open, running, finished,
  cancelled), spent_owls, opened_at, updated_at, waiting_on (null unless
  the row is open, a platform fault stopped its last attempt and the
  platform's next attempt is still ahead: one of
  credits_fault, the platform's account with a model provider is out of
  credits; credentials_fault, a provider rejected the platform's key;
  provider_unavailable, a provider or network failure that outlasted its
  retries), waiting_since, next_attempt_at (always in the future: once it
  has come all three are null and the row is due, a plain open row the
  platform picks when its turn comes). A row with waiting_on has not
  failed and is not cancelled: it stays funded, no attempt is charged, and
  the platform retries it on its own, so commissioning it again buys
  nothing. Its budget stays held meanwhile and counts against the
  mandate's pace from when it was placed, as any held budget does.
  extraction (null unless the row is a running ingest: queued, its source
  is waiting its turn to be read; extracting, a worker is reading it),
  extraction_started_at (when the current reading began; null while
  queued), queued_ahead (for a queued ingest, about how many extractions
  submitted before it are still waiting; the queue does not promise its
  order). A running ingest is not necessarily being read: say queued when
  it is
- `commissions`: the money on each piece of work. commission_id, action_id,
  exclusion_group, payer_kind (mandate, person), payer_mandate_id,
  budget_owls, spent_owls, returned_owls, commissioned_by, brief, reason,
  parent_action_id (the run that paid, when an agent spent from its own
  budget), created_at, settled_at
- `messages`: what was sent to a node's Steward. message_id, node_id,
  trigger, sender_kind, sender_node_id, paid, body, created_at, read_at,
  outcome (changed, no_change, disagree), outcome_note
- `mandates`: mandate_id, title, objective, status, is_platform, pace
  (jsonb: `{"kind":"as_needed"}`, or `{"kind":"steady","owls":…,
  "period_hours":…}` for at most that much committed in any rolling
  window), reserve_owls and reserve_reason (what only the Grantmaker may
  commit, and why), escrow_owls, operating_policy, created_at
- `mandate_decisions`: every commission, grant, refusal, decline and note
  a mandate's agents made. decision_id, mandate_id, decided_by, item_kind,
  decision, target, owls, reason, petition_id, action_id, created_at
- `plan_items`: each item of a mandate's plan, as its page shows it, with
  the standing the plan materializer last wrote on it. mandate_id,
  item_index, plan_cursor (it stands past the last item whose work has
  run or is running; an item before it can still be waiting), action,
  node_id, url, partition, variant, focus, rationale, ledger_status,
  ledger_reason, action_id (the ledger row it names), exclusion_group,
  ledger_checked_at, proposed_kind, proposed_text, proposal_ref, node_ref,
  contribution_id, added_by (who put the item in the plan:
  grantmaker_draft, grantmaker_planning, grantmaker_chat with the funder,
  or grantmaker_review, its own pass whatever woke it), added_at and
  added_run_id (null on items added before these were recorded). Join action_id to `ledger` to check a plan against
  what ran: a named row that is missing, or whose status disagrees with
  ledger_status, is a plan out of step with its ledger. A `propose` item
  is a node the plan asked the graph to take in: proposed_kind and
  proposed_text are what it proposed, contribution_id the contribution it
  filed (join `contributions`), and node_id the node it became or landed
  on once accepted. An item with node_ref and no node_id is waiting on the
  proposal whose proposal_ref that is.
  An `assess`, `reassess` or `deepen` item is a
  standing order its mandate commissions: once placed, its money is the
  row in `commissions` on that action_id with commissioned_by `plan`. A
  ledger_status of `waiting` on one is an order the mandate's pace, its
  Grantmaker's reserve, or its escrow has no room for yet, and `blocked` one
  that could never fit, or one stored with no variant, which commissions
  nothing until its Grantmaker names a tier; ledger_reason gives the tier
  and the figures. `cancelled` with a ledger_reason beginning "withdrawn" is
  an item its Grantmaker withdrew before its pass began. A deepen item
  orders passes only on the node's children that carry no assessment.
- `petitions`: petition_id, mandate_id, kind, asked_owls, granted_owls,
  requester_agent, requester_node_id, status, plan, reason, created_at,
  decided_at
- `contributions`: contribution_id, node_id, type, review_status,
  submitted_at
- `requests`: request_id, ask, why, state, keeper_kind, keeper_node_id,
  budget_owls, created_at, closed_at
- `changes`: the change stream as one table. kind, node_id, at, summary.
  kind `state_changed` is a node archived, restored, merged or deprecated;
  its summary reads `<from> -> <to> by <who>: <reason>`, with the
  successors that carry on what the node stated, if any

**What is fast.** Ids, node_id and target_node_id on every view, tags (use
`= ANY` or `&&`), importance, assessed_at and created_at. Filter on these
first, join on ids, and aggregate in the query rather than returning rows to
count. A query the planner prices too high is refused before it runs, with
its estimate.

**Queries for common questions.**

Important nodes under a tag that have gone stale:

```sql
SELECT n.id, n.text, n.importance, a.assessed_at
  FROM nodes n JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE $1 = ANY(n.tags) AND n.importance >= 0.5
   AND a.assessed_at < now() - interval '60 days'
 ORDER BY n.importance DESC LIMIT 50;
```

Messages waiting longest on important nodes:

```sql
SELECT m.node_id, n.text, m.trigger, now() - m.created_at AS waiting
  FROM messages m JOIN nodes n ON n.id = m.node_id
 WHERE m.read_at IS NULL AND n.importance >= 0.6
 ORDER BY m.created_at LIMIT 50;
```

What each kind of work cost over the last 30 days, and how much of its
budget it used:

```sql
SELECT l.kind, count(*) AS runs, sum(c.spent_owls) AS spent,
       round(avg(c.spent_owls / nullif(c.budget_owls, 0)), 2) AS budget_used,
       percentile_cont(0.8) WITHIN GROUP (ORDER BY c.spent_owls) AS p80
  FROM commissions c JOIN ledger l USING (action_id)
 WHERE c.settled_at > now() - interval '30 days'
 GROUP BY l.kind ORDER BY spent DESC;
```

Everything beneath a node, with the signals for deciding where work goes
(a scope survey): standing, age, expected gain from another pass, and
subclaims still waiting on a deepen. For a territory found by meaning,
start from search_claims' ids instead of the subtree.

```sql
WITH RECURSIVE sub(id) AS (
  SELECT $1::uuid
  UNION SELECT e.child_id FROM edges e JOIN sub ON e.parent_id = sub.id)
SELECT n.id, n.text, n.importance, n.contestation, n.steward_state,
       n.steward_park_reason,
       a.status, now()::date - a.assessed_at::date AS days_since_assessed,
       a.marginal_yield,
       (SELECT count(*) FROM edges e JOIN nodes c ON c.id = e.child_id
         WHERE e.parent_id = n.id AND c.steward_state = 'deferred') AS deferred_subclaims
  FROM sub JOIN nodes n USING (id)
  LEFT JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;
```

Statuses carried over from a retired label and not yet re-judged, most
important first, with the reassessment open on each and the budget already
committed to it. Price what is left with the cost query above (kind
`reassess`):

```sql
SELECT n.id, n.text, n.importance, a.status, a.relabeled_from, a.assessed_at,
       r.open_reassess, r.committed_owls
  FROM assessments a JOIN nodes n ON n.id = a.node_id
  LEFT JOIN LATERAL (
    SELECT count(DISTINCT l.action_id) AS open_reassess,
           coalesce(sum(c.budget_owls - c.spent_owls)
                      FILTER (WHERE c.settled_at IS NULL), 0) AS committed_owls
      FROM ledger l LEFT JOIN commissions c USING (action_id)
     WHERE l.target_node_id = n.id AND l.kind = 'reassess'
       AND l.status IN ('open', 'running')) r ON true
 WHERE a.is_current AND a.relabeled_from IS NOT NULL AND n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;
```

Funded work that is waiting on a platform fault, with what is held on it:

```sql
SELECT l.kind, l.waiting_on, count(DISTINCT l.action_id) AS rows,
       min(l.waiting_since) AS since, min(l.next_attempt_at) AS next_attempt,
       coalesce(sum(c.budget_owls - c.spent_owls), 0) AS held_owls
  FROM ledger l LEFT JOIN commissions c
    ON c.action_id = l.action_id AND c.settled_at IS NULL
 WHERE l.status = 'open' AND l.waiting_on IS NOT NULL
 GROUP BY l.kind, l.waiting_on ORDER BY since;
```

**What is not here.** Only public data: no emails, keys, balances or
unfunded drafts, and no funder or contributor identities.

If a question needs something the views lack, say so with raise_issue.
Curator · 1 section · 11,187 characters
# Method skill: Sql (version 13)

This skill says how the constitution and your role apply to one kind of work. It never outranks either.

## For every administrator

query_sql runs one read-only SELECT against views of the graph's public
data. It is the way to ask questions the other reads can't: which important
nodes have disputes waiting, what reassessments cost and how often they
changed a verdict, what a mandate has funded and what it bought. To find
nodes by meaning, use search_claims first and pass its ids in
(`WHERE n.id = ANY($1::uuid[])`); SQL can't search by meaning.

**Conventions.** Ids are uuids. Times are UTC. Money is in owls.
importance, contestation, confidence and credence run from 0 to 1. A status
is one of verified, supported, inconclusive, doubtful, contradicted or
unknown.

**The views.**

- `nodes`: id, kind (claim, quantity, question), text, claim_type, state,
  merged_into, importance, contestation, steward_state, stewarded_at,
  proposed_by_person, tags (array of slugs), created_at, updated_at,
  steward_park_reason (null unless steward_state is 'error': the node is
  parked after failed Steward passes and will not be assessed until someone
  commissions a pass on it; one of credentials_fault, model_refusal,
  database_fault, tool_failure, provider_error, other)
- `assessments`: id, node_id, status, confidence, credence, marginal_yield,
  is_current, assessed_at, trigger, summary, reasoning_head (the first 500
  characters), relabeled_from (the retired label, contested or
  unsupported, a migration carried the status over from; set until the
  node is re-judged, so such a status is provisional, not a finding)
- `edges`: id, parent_id, child_id, relation, reasoning, created_at
- `arguments`: id, node_id, name, stance, shows, description, created_at,
  retired_at
- `tags`: slug, name, description, status, node_count
- `sources`: id, url, title, source_type, publisher, published_date, doi,
  retrieved_at
- `instances`: where a claim is asserted. id, node_id, source_id, stance,
  speaker, publication, source_date, verbatim_head, created_at, detached_at
- `ledger`: every piece of graph work. action_id, kind, variant,
  target_node_id, target_ref, label, status (open, running, finished,
  cancelled), spent_owls, opened_at, updated_at, waiting_on (null unless
  the row is open, a platform fault stopped its last attempt and the
  platform's next attempt is still ahead: one of
  credits_fault, the platform's account with a model provider is out of
  credits; credentials_fault, a provider rejected the platform's key;
  provider_unavailable, a provider or network failure that outlasted its
  retries), waiting_since, next_attempt_at (always in the future: once it
  has come all three are null and the row is due, a plain open row the
  platform picks when its turn comes). A row with waiting_on has not
  failed and is not cancelled: it stays funded, no attempt is charged, and
  the platform retries it on its own, so commissioning it again buys
  nothing. Its budget stays held meanwhile and counts against the
  mandate's pace from when it was placed, as any held budget does.
  extraction (null unless the row is a running ingest: queued, its source
  is waiting its turn to be read; extracting, a worker is reading it),
  extraction_started_at (when the current reading began; null while
  queued), queued_ahead (for a queued ingest, about how many extractions
  submitted before it are still waiting; the queue does not promise its
  order). A running ingest is not necessarily being read: say queued when
  it is
- `commissions`: the money on each piece of work. commission_id, action_id,
  exclusion_group, payer_kind (mandate, person), payer_mandate_id,
  budget_owls, spent_owls, returned_owls, commissioned_by, brief, reason,
  parent_action_id (the run that paid, when an agent spent from its own
  budget), created_at, settled_at
- `messages`: what was sent to a node's Steward. message_id, node_id,
  trigger, sender_kind, sender_node_id, paid, body, created_at, read_at,
  outcome (changed, no_change, disagree), outcome_note
- `mandates`: mandate_id, title, objective, status, is_platform, pace
  (jsonb: `{"kind":"as_needed"}`, or `{"kind":"steady","owls":…,
  "period_hours":…}` for at most that much committed in any rolling
  window), reserve_owls and reserve_reason (what only the Grantmaker may
  commit, and why), escrow_owls, operating_policy, created_at
- `mandate_decisions`: every commission, grant, refusal, decline and note
  a mandate's agents made. decision_id, mandate_id, decided_by, item_kind,
  decision, target, owls, reason, petition_id, action_id, created_at
- `plan_items`: each item of a mandate's plan, as its page shows it, with
  the standing the plan materializer last wrote on it. mandate_id,
  item_index, plan_cursor (it stands past the last item whose work has
  run or is running; an item before it can still be waiting), action,
  node_id, url, partition, variant, focus, rationale, ledger_status,
  ledger_reason, action_id (the ledger row it names), exclusion_group,
  ledger_checked_at, proposed_kind, proposed_text, proposal_ref, node_ref,
  contribution_id, added_by (who put the item in the plan:
  grantmaker_draft, grantmaker_planning, grantmaker_chat with the funder,
  or grantmaker_review, its own pass whatever woke it), added_at and
  added_run_id (null on items added before these were recorded). Join action_id to `ledger` to check a plan against
  what ran: a named row that is missing, or whose status disagrees with
  ledger_status, is a plan out of step with its ledger. A `propose` item
  is a node the plan asked the graph to take in: proposed_kind and
  proposed_text are what it proposed, contribution_id the contribution it
  filed (join `contributions`), and node_id the node it became or landed
  on once accepted. An item with node_ref and no node_id is waiting on the
  proposal whose proposal_ref that is.
  An `assess`, `reassess` or `deepen` item is a
  standing order its mandate commissions: once placed, its money is the
  row in `commissions` on that action_id with commissioned_by `plan`. A
  ledger_status of `waiting` on one is an order the mandate's pace, its
  Grantmaker's reserve, or its escrow has no room for yet, and `blocked` one
  that could never fit, or one stored with no variant, which commissions
  nothing until its Grantmaker names a tier; ledger_reason gives the tier
  and the figures. `cancelled` with a ledger_reason beginning "withdrawn" is
  an item its Grantmaker withdrew before its pass began. A deepen item
  orders passes only on the node's children that carry no assessment.
- `petitions`: petition_id, mandate_id, kind, asked_owls, granted_owls,
  requester_agent, requester_node_id, status, plan, reason, created_at,
  decided_at
- `contributions`: contribution_id, node_id, type, review_status,
  submitted_at
- `requests`: request_id, ask, why, state, keeper_kind, keeper_node_id,
  budget_owls, created_at, closed_at
- `changes`: the change stream as one table. kind, node_id, at, summary.
  kind `state_changed` is a node archived, restored, merged or deprecated;
  its summary reads `<from> -> <to> by <who>: <reason>`, with the
  successors that carry on what the node stated, if any

**What is fast.** Ids, node_id and target_node_id on every view, tags (use
`= ANY` or `&&`), importance, assessed_at and created_at. Filter on these
first, join on ids, and aggregate in the query rather than returning rows to
count. A query the planner prices too high is refused before it runs, with
its estimate.

**Queries for common questions.**

Important nodes under a tag that have gone stale:

```sql
SELECT n.id, n.text, n.importance, a.assessed_at
  FROM nodes n JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE $1 = ANY(n.tags) AND n.importance >= 0.5
   AND a.assessed_at < now() - interval '60 days'
 ORDER BY n.importance DESC LIMIT 50;
```

Messages waiting longest on important nodes:

```sql
SELECT m.node_id, n.text, m.trigger, now() - m.created_at AS waiting
  FROM messages m JOIN nodes n ON n.id = m.node_id
 WHERE m.read_at IS NULL AND n.importance >= 0.6
 ORDER BY m.created_at LIMIT 50;
```

What each kind of work cost over the last 30 days, and how much of its
budget it used:

```sql
SELECT l.kind, count(*) AS runs, sum(c.spent_owls) AS spent,
       round(avg(c.spent_owls / nullif(c.budget_owls, 0)), 2) AS budget_used,
       percentile_cont(0.8) WITHIN GROUP (ORDER BY c.spent_owls) AS p80
  FROM commissions c JOIN ledger l USING (action_id)
 WHERE c.settled_at > now() - interval '30 days'
 GROUP BY l.kind ORDER BY spent DESC;
```

Everything beneath a node, with the signals for deciding where work goes
(a scope survey): standing, age, expected gain from another pass, and
subclaims still waiting on a deepen. For a territory found by meaning,
start from search_claims' ids instead of the subtree.

```sql
WITH RECURSIVE sub(id) AS (
  SELECT $1::uuid
  UNION SELECT e.child_id FROM edges e JOIN sub ON e.parent_id = sub.id)
SELECT n.id, n.text, n.importance, n.contestation, n.steward_state,
       n.steward_park_reason,
       a.status, now()::date - a.assessed_at::date AS days_since_assessed,
       a.marginal_yield,
       (SELECT count(*) FROM edges e JOIN nodes c ON c.id = e.child_id
         WHERE e.parent_id = n.id AND c.steward_state = 'deferred') AS deferred_subclaims
  FROM sub JOIN nodes n USING (id)
  LEFT JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;
```

Statuses carried over from a retired label and not yet re-judged, most
important first, with the reassessment open on each and the budget already
committed to it. Price what is left with the cost query above (kind
`reassess`):

```sql
SELECT n.id, n.text, n.importance, a.status, a.relabeled_from, a.assessed_at,
       r.open_reassess, r.committed_owls
  FROM assessments a JOIN nodes n ON n.id = a.node_id
  LEFT JOIN LATERAL (
    SELECT count(DISTINCT l.action_id) AS open_reassess,
           coalesce(sum(c.budget_owls - c.spent_owls)
                      FILTER (WHERE c.settled_at IS NULL), 0) AS committed_owls
      FROM ledger l LEFT JOIN commissions c USING (action_id)
     WHERE l.target_node_id = n.id AND l.kind = 'reassess'
       AND l.status IN ('open', 'running')) r ON true
 WHERE a.is_current AND a.relabeled_from IS NOT NULL AND n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;
```

Funded work that is waiting on a platform fault, with what is held on it:

```sql
SELECT l.kind, l.waiting_on, count(DISTINCT l.action_id) AS rows,
       min(l.waiting_since) AS since, min(l.next_attempt_at) AS next_attempt,
       coalesce(sum(c.budget_owls - c.spent_owls), 0) AS held_owls
  FROM ledger l LEFT JOIN commissions c
    ON c.action_id = l.action_id AND c.settled_at IS NULL
 WHERE l.status = 'open' AND l.waiting_on IS NOT NULL
 GROUP BY l.kind, l.waiting_on ORDER BY since;
```

**What is not here.** Only public data: no emails, keys, balances or
unfunded drafts, and no funder or contributor identities.

If a question needs something the views lack, say so with raise_issue.
Matcher · no sections · 139 characters
# Method skill: Sql (version 13)

This skill says how the constitution and your role apply to one kind of work. It never outranks either.

Extractor · no sections · 139 characters
# Method skill: Sql (version 13)

This skill says how the constitution and your role apply to one kind of work. It never outranks either.

Researcher · 1 section · 11,187 characters
# Method skill: Sql (version 13)

This skill says how the constitution and your role apply to one kind of work. It never outranks either.

## For every administrator

query_sql runs one read-only SELECT against views of the graph's public
data. It is the way to ask questions the other reads can't: which important
nodes have disputes waiting, what reassessments cost and how often they
changed a verdict, what a mandate has funded and what it bought. To find
nodes by meaning, use search_claims first and pass its ids in
(`WHERE n.id = ANY($1::uuid[])`); SQL can't search by meaning.

**Conventions.** Ids are uuids. Times are UTC. Money is in owls.
importance, contestation, confidence and credence run from 0 to 1. A status
is one of verified, supported, inconclusive, doubtful, contradicted or
unknown.

**The views.**

- `nodes`: id, kind (claim, quantity, question), text, claim_type, state,
  merged_into, importance, contestation, steward_state, stewarded_at,
  proposed_by_person, tags (array of slugs), created_at, updated_at,
  steward_park_reason (null unless steward_state is 'error': the node is
  parked after failed Steward passes and will not be assessed until someone
  commissions a pass on it; one of credentials_fault, model_refusal,
  database_fault, tool_failure, provider_error, other)
- `assessments`: id, node_id, status, confidence, credence, marginal_yield,
  is_current, assessed_at, trigger, summary, reasoning_head (the first 500
  characters), relabeled_from (the retired label, contested or
  unsupported, a migration carried the status over from; set until the
  node is re-judged, so such a status is provisional, not a finding)
- `edges`: id, parent_id, child_id, relation, reasoning, created_at
- `arguments`: id, node_id, name, stance, shows, description, created_at,
  retired_at
- `tags`: slug, name, description, status, node_count
- `sources`: id, url, title, source_type, publisher, published_date, doi,
  retrieved_at
- `instances`: where a claim is asserted. id, node_id, source_id, stance,
  speaker, publication, source_date, verbatim_head, created_at, detached_at
- `ledger`: every piece of graph work. action_id, kind, variant,
  target_node_id, target_ref, label, status (open, running, finished,
  cancelled), spent_owls, opened_at, updated_at, waiting_on (null unless
  the row is open, a platform fault stopped its last attempt and the
  platform's next attempt is still ahead: one of
  credits_fault, the platform's account with a model provider is out of
  credits; credentials_fault, a provider rejected the platform's key;
  provider_unavailable, a provider or network failure that outlasted its
  retries), waiting_since, next_attempt_at (always in the future: once it
  has come all three are null and the row is due, a plain open row the
  platform picks when its turn comes). A row with waiting_on has not
  failed and is not cancelled: it stays funded, no attempt is charged, and
  the platform retries it on its own, so commissioning it again buys
  nothing. Its budget stays held meanwhile and counts against the
  mandate's pace from when it was placed, as any held budget does.
  extraction (null unless the row is a running ingest: queued, its source
  is waiting its turn to be read; extracting, a worker is reading it),
  extraction_started_at (when the current reading began; null while
  queued), queued_ahead (for a queued ingest, about how many extractions
  submitted before it are still waiting; the queue does not promise its
  order). A running ingest is not necessarily being read: say queued when
  it is
- `commissions`: the money on each piece of work. commission_id, action_id,
  exclusion_group, payer_kind (mandate, person), payer_mandate_id,
  budget_owls, spent_owls, returned_owls, commissioned_by, brief, reason,
  parent_action_id (the run that paid, when an agent spent from its own
  budget), created_at, settled_at
- `messages`: what was sent to a node's Steward. message_id, node_id,
  trigger, sender_kind, sender_node_id, paid, body, created_at, read_at,
  outcome (changed, no_change, disagree), outcome_note
- `mandates`: mandate_id, title, objective, status, is_platform, pace
  (jsonb: `{"kind":"as_needed"}`, or `{"kind":"steady","owls":…,
  "period_hours":…}` for at most that much committed in any rolling
  window), reserve_owls and reserve_reason (what only the Grantmaker may
  commit, and why), escrow_owls, operating_policy, created_at
- `mandate_decisions`: every commission, grant, refusal, decline and note
  a mandate's agents made. decision_id, mandate_id, decided_by, item_kind,
  decision, target, owls, reason, petition_id, action_id, created_at
- `plan_items`: each item of a mandate's plan, as its page shows it, with
  the standing the plan materializer last wrote on it. mandate_id,
  item_index, plan_cursor (it stands past the last item whose work has
  run or is running; an item before it can still be waiting), action,
  node_id, url, partition, variant, focus, rationale, ledger_status,
  ledger_reason, action_id (the ledger row it names), exclusion_group,
  ledger_checked_at, proposed_kind, proposed_text, proposal_ref, node_ref,
  contribution_id, added_by (who put the item in the plan:
  grantmaker_draft, grantmaker_planning, grantmaker_chat with the funder,
  or grantmaker_review, its own pass whatever woke it), added_at and
  added_run_id (null on items added before these were recorded). Join action_id to `ledger` to check a plan against
  what ran: a named row that is missing, or whose status disagrees with
  ledger_status, is a plan out of step with its ledger. A `propose` item
  is a node the plan asked the graph to take in: proposed_kind and
  proposed_text are what it proposed, contribution_id the contribution it
  filed (join `contributions`), and node_id the node it became or landed
  on once accepted. An item with node_ref and no node_id is waiting on the
  proposal whose proposal_ref that is.
  An `assess`, `reassess` or `deepen` item is a
  standing order its mandate commissions: once placed, its money is the
  row in `commissions` on that action_id with commissioned_by `plan`. A
  ledger_status of `waiting` on one is an order the mandate's pace, its
  Grantmaker's reserve, or its escrow has no room for yet, and `blocked` one
  that could never fit, or one stored with no variant, which commissions
  nothing until its Grantmaker names a tier; ledger_reason gives the tier
  and the figures. `cancelled` with a ledger_reason beginning "withdrawn" is
  an item its Grantmaker withdrew before its pass began. A deepen item
  orders passes only on the node's children that carry no assessment.
- `petitions`: petition_id, mandate_id, kind, asked_owls, granted_owls,
  requester_agent, requester_node_id, status, plan, reason, created_at,
  decided_at
- `contributions`: contribution_id, node_id, type, review_status,
  submitted_at
- `requests`: request_id, ask, why, state, keeper_kind, keeper_node_id,
  budget_owls, created_at, closed_at
- `changes`: the change stream as one table. kind, node_id, at, summary.
  kind `state_changed` is a node archived, restored, merged or deprecated;
  its summary reads `<from> -> <to> by <who>: <reason>`, with the
  successors that carry on what the node stated, if any

**What is fast.** Ids, node_id and target_node_id on every view, tags (use
`= ANY` or `&&`), importance, assessed_at and created_at. Filter on these
first, join on ids, and aggregate in the query rather than returning rows to
count. A query the planner prices too high is refused before it runs, with
its estimate.

**Queries for common questions.**

Important nodes under a tag that have gone stale:

```sql
SELECT n.id, n.text, n.importance, a.assessed_at
  FROM nodes n JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE $1 = ANY(n.tags) AND n.importance >= 0.5
   AND a.assessed_at < now() - interval '60 days'
 ORDER BY n.importance DESC LIMIT 50;
```

Messages waiting longest on important nodes:

```sql
SELECT m.node_id, n.text, m.trigger, now() - m.created_at AS waiting
  FROM messages m JOIN nodes n ON n.id = m.node_id
 WHERE m.read_at IS NULL AND n.importance >= 0.6
 ORDER BY m.created_at LIMIT 50;
```

What each kind of work cost over the last 30 days, and how much of its
budget it used:

```sql
SELECT l.kind, count(*) AS runs, sum(c.spent_owls) AS spent,
       round(avg(c.spent_owls / nullif(c.budget_owls, 0)), 2) AS budget_used,
       percentile_cont(0.8) WITHIN GROUP (ORDER BY c.spent_owls) AS p80
  FROM commissions c JOIN ledger l USING (action_id)
 WHERE c.settled_at > now() - interval '30 days'
 GROUP BY l.kind ORDER BY spent DESC;
```

Everything beneath a node, with the signals for deciding where work goes
(a scope survey): standing, age, expected gain from another pass, and
subclaims still waiting on a deepen. For a territory found by meaning,
start from search_claims' ids instead of the subtree.

```sql
WITH RECURSIVE sub(id) AS (
  SELECT $1::uuid
  UNION SELECT e.child_id FROM edges e JOIN sub ON e.parent_id = sub.id)
SELECT n.id, n.text, n.importance, n.contestation, n.steward_state,
       n.steward_park_reason,
       a.status, now()::date - a.assessed_at::date AS days_since_assessed,
       a.marginal_yield,
       (SELECT count(*) FROM edges e JOIN nodes c ON c.id = e.child_id
         WHERE e.parent_id = n.id AND c.steward_state = 'deferred') AS deferred_subclaims
  FROM sub JOIN nodes n USING (id)
  LEFT JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;
```

Statuses carried over from a retired label and not yet re-judged, most
important first, with the reassessment open on each and the budget already
committed to it. Price what is left with the cost query above (kind
`reassess`):

```sql
SELECT n.id, n.text, n.importance, a.status, a.relabeled_from, a.assessed_at,
       r.open_reassess, r.committed_owls
  FROM assessments a JOIN nodes n ON n.id = a.node_id
  LEFT JOIN LATERAL (
    SELECT count(DISTINCT l.action_id) AS open_reassess,
           coalesce(sum(c.budget_owls - c.spent_owls)
                      FILTER (WHERE c.settled_at IS NULL), 0) AS committed_owls
      FROM ledger l LEFT JOIN commissions c USING (action_id)
     WHERE l.target_node_id = n.id AND l.kind = 'reassess'
       AND l.status IN ('open', 'running')) r ON true
 WHERE a.is_current AND a.relabeled_from IS NOT NULL AND n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;
```

Funded work that is waiting on a platform fault, with what is held on it:

```sql
SELECT l.kind, l.waiting_on, count(DISTINCT l.action_id) AS rows,
       min(l.waiting_since) AS since, min(l.next_attempt_at) AS next_attempt,
       coalesce(sum(c.budget_owls - c.spent_owls), 0) AS held_owls
  FROM ledger l LEFT JOIN commissions c
    ON c.action_id = l.action_id AND c.settled_at IS NULL
 WHERE l.status = 'open' AND l.waiting_on IS NOT NULL
 GROUP BY l.kind, l.waiting_on ORDER BY since;
```

**What is not here.** Only public data: no emails, keys, balances or
unfunded drafts, and no funder or contributor identities.

If a question needs something the views lack, say so with raise_issue.
Consistency Checker · 1 section · 11,187 characters
# Method skill: Sql (version 13)

This skill says how the constitution and your role apply to one kind of work. It never outranks either.

## For every administrator

query_sql runs one read-only SELECT against views of the graph's public
data. It is the way to ask questions the other reads can't: which important
nodes have disputes waiting, what reassessments cost and how often they
changed a verdict, what a mandate has funded and what it bought. To find
nodes by meaning, use search_claims first and pass its ids in
(`WHERE n.id = ANY($1::uuid[])`); SQL can't search by meaning.

**Conventions.** Ids are uuids. Times are UTC. Money is in owls.
importance, contestation, confidence and credence run from 0 to 1. A status
is one of verified, supported, inconclusive, doubtful, contradicted or
unknown.

**The views.**

- `nodes`: id, kind (claim, quantity, question), text, claim_type, state,
  merged_into, importance, contestation, steward_state, stewarded_at,
  proposed_by_person, tags (array of slugs), created_at, updated_at,
  steward_park_reason (null unless steward_state is 'error': the node is
  parked after failed Steward passes and will not be assessed until someone
  commissions a pass on it; one of credentials_fault, model_refusal,
  database_fault, tool_failure, provider_error, other)
- `assessments`: id, node_id, status, confidence, credence, marginal_yield,
  is_current, assessed_at, trigger, summary, reasoning_head (the first 500
  characters), relabeled_from (the retired label, contested or
  unsupported, a migration carried the status over from; set until the
  node is re-judged, so such a status is provisional, not a finding)
- `edges`: id, parent_id, child_id, relation, reasoning, created_at
- `arguments`: id, node_id, name, stance, shows, description, created_at,
  retired_at
- `tags`: slug, name, description, status, node_count
- `sources`: id, url, title, source_type, publisher, published_date, doi,
  retrieved_at
- `instances`: where a claim is asserted. id, node_id, source_id, stance,
  speaker, publication, source_date, verbatim_head, created_at, detached_at
- `ledger`: every piece of graph work. action_id, kind, variant,
  target_node_id, target_ref, label, status (open, running, finished,
  cancelled), spent_owls, opened_at, updated_at, waiting_on (null unless
  the row is open, a platform fault stopped its last attempt and the
  platform's next attempt is still ahead: one of
  credits_fault, the platform's account with a model provider is out of
  credits; credentials_fault, a provider rejected the platform's key;
  provider_unavailable, a provider or network failure that outlasted its
  retries), waiting_since, next_attempt_at (always in the future: once it
  has come all three are null and the row is due, a plain open row the
  platform picks when its turn comes). A row with waiting_on has not
  failed and is not cancelled: it stays funded, no attempt is charged, and
  the platform retries it on its own, so commissioning it again buys
  nothing. Its budget stays held meanwhile and counts against the
  mandate's pace from when it was placed, as any held budget does.
  extraction (null unless the row is a running ingest: queued, its source
  is waiting its turn to be read; extracting, a worker is reading it),
  extraction_started_at (when the current reading began; null while
  queued), queued_ahead (for a queued ingest, about how many extractions
  submitted before it are still waiting; the queue does not promise its
  order). A running ingest is not necessarily being read: say queued when
  it is
- `commissions`: the money on each piece of work. commission_id, action_id,
  exclusion_group, payer_kind (mandate, person), payer_mandate_id,
  budget_owls, spent_owls, returned_owls, commissioned_by, brief, reason,
  parent_action_id (the run that paid, when an agent spent from its own
  budget), created_at, settled_at
- `messages`: what was sent to a node's Steward. message_id, node_id,
  trigger, sender_kind, sender_node_id, paid, body, created_at, read_at,
  outcome (changed, no_change, disagree), outcome_note
- `mandates`: mandate_id, title, objective, status, is_platform, pace
  (jsonb: `{"kind":"as_needed"}`, or `{"kind":"steady","owls":…,
  "period_hours":…}` for at most that much committed in any rolling
  window), reserve_owls and reserve_reason (what only the Grantmaker may
  commit, and why), escrow_owls, operating_policy, created_at
- `mandate_decisions`: every commission, grant, refusal, decline and note
  a mandate's agents made. decision_id, mandate_id, decided_by, item_kind,
  decision, target, owls, reason, petition_id, action_id, created_at
- `plan_items`: each item of a mandate's plan, as its page shows it, with
  the standing the plan materializer last wrote on it. mandate_id,
  item_index, plan_cursor (it stands past the last item whose work has
  run or is running; an item before it can still be waiting), action,
  node_id, url, partition, variant, focus, rationale, ledger_status,
  ledger_reason, action_id (the ledger row it names), exclusion_group,
  ledger_checked_at, proposed_kind, proposed_text, proposal_ref, node_ref,
  contribution_id, added_by (who put the item in the plan:
  grantmaker_draft, grantmaker_planning, grantmaker_chat with the funder,
  or grantmaker_review, its own pass whatever woke it), added_at and
  added_run_id (null on items added before these were recorded). Join action_id to `ledger` to check a plan against
  what ran: a named row that is missing, or whose status disagrees with
  ledger_status, is a plan out of step with its ledger. A `propose` item
  is a node the plan asked the graph to take in: proposed_kind and
  proposed_text are what it proposed, contribution_id the contribution it
  filed (join `contributions`), and node_id the node it became or landed
  on once accepted. An item with node_ref and no node_id is waiting on the
  proposal whose proposal_ref that is.
  An `assess`, `reassess` or `deepen` item is a
  standing order its mandate commissions: once placed, its money is the
  row in `commissions` on that action_id with commissioned_by `plan`. A
  ledger_status of `waiting` on one is an order the mandate's pace, its
  Grantmaker's reserve, or its escrow has no room for yet, and `blocked` one
  that could never fit, or one stored with no variant, which commissions
  nothing until its Grantmaker names a tier; ledger_reason gives the tier
  and the figures. `cancelled` with a ledger_reason beginning "withdrawn" is
  an item its Grantmaker withdrew before its pass began. A deepen item
  orders passes only on the node's children that carry no assessment.
- `petitions`: petition_id, mandate_id, kind, asked_owls, granted_owls,
  requester_agent, requester_node_id, status, plan, reason, created_at,
  decided_at
- `contributions`: contribution_id, node_id, type, review_status,
  submitted_at
- `requests`: request_id, ask, why, state, keeper_kind, keeper_node_id,
  budget_owls, created_at, closed_at
- `changes`: the change stream as one table. kind, node_id, at, summary.
  kind `state_changed` is a node archived, restored, merged or deprecated;
  its summary reads `<from> -> <to> by <who>: <reason>`, with the
  successors that carry on what the node stated, if any

**What is fast.** Ids, node_id and target_node_id on every view, tags (use
`= ANY` or `&&`), importance, assessed_at and created_at. Filter on these
first, join on ids, and aggregate in the query rather than returning rows to
count. A query the planner prices too high is refused before it runs, with
its estimate.

**Queries for common questions.**

Important nodes under a tag that have gone stale:

```sql
SELECT n.id, n.text, n.importance, a.assessed_at
  FROM nodes n JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE $1 = ANY(n.tags) AND n.importance >= 0.5
   AND a.assessed_at < now() - interval '60 days'
 ORDER BY n.importance DESC LIMIT 50;
```

Messages waiting longest on important nodes:

```sql
SELECT m.node_id, n.text, m.trigger, now() - m.created_at AS waiting
  FROM messages m JOIN nodes n ON n.id = m.node_id
 WHERE m.read_at IS NULL AND n.importance >= 0.6
 ORDER BY m.created_at LIMIT 50;
```

What each kind of work cost over the last 30 days, and how much of its
budget it used:

```sql
SELECT l.kind, count(*) AS runs, sum(c.spent_owls) AS spent,
       round(avg(c.spent_owls / nullif(c.budget_owls, 0)), 2) AS budget_used,
       percentile_cont(0.8) WITHIN GROUP (ORDER BY c.spent_owls) AS p80
  FROM commissions c JOIN ledger l USING (action_id)
 WHERE c.settled_at > now() - interval '30 days'
 GROUP BY l.kind ORDER BY spent DESC;
```

Everything beneath a node, with the signals for deciding where work goes
(a scope survey): standing, age, expected gain from another pass, and
subclaims still waiting on a deepen. For a territory found by meaning,
start from search_claims' ids instead of the subtree.

```sql
WITH RECURSIVE sub(id) AS (
  SELECT $1::uuid
  UNION SELECT e.child_id FROM edges e JOIN sub ON e.parent_id = sub.id)
SELECT n.id, n.text, n.importance, n.contestation, n.steward_state,
       n.steward_park_reason,
       a.status, now()::date - a.assessed_at::date AS days_since_assessed,
       a.marginal_yield,
       (SELECT count(*) FROM edges e JOIN nodes c ON c.id = e.child_id
         WHERE e.parent_id = n.id AND c.steward_state = 'deferred') AS deferred_subclaims
  FROM sub JOIN nodes n USING (id)
  LEFT JOIN assessments a ON a.node_id = n.id AND a.is_current
 WHERE n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;
```

Statuses carried over from a retired label and not yet re-judged, most
important first, with the reassessment open on each and the budget already
committed to it. Price what is left with the cost query above (kind
`reassess`):

```sql
SELECT n.id, n.text, n.importance, a.status, a.relabeled_from, a.assessed_at,
       r.open_reassess, r.committed_owls
  FROM assessments a JOIN nodes n ON n.id = a.node_id
  LEFT JOIN LATERAL (
    SELECT count(DISTINCT l.action_id) AS open_reassess,
           coalesce(sum(c.budget_owls - c.spent_owls)
                      FILTER (WHERE c.settled_at IS NULL), 0) AS committed_owls
      FROM ledger l LEFT JOIN commissions c USING (action_id)
     WHERE l.target_node_id = n.id AND l.kind = 'reassess'
       AND l.status IN ('open', 'running')) r ON true
 WHERE a.is_current AND a.relabeled_from IS NOT NULL AND n.state = 'active'
 ORDER BY n.importance DESC LIMIT 100;
```

Funded work that is waiting on a platform fault, with what is held on it:

```sql
SELECT l.kind, l.waiting_on, count(DISTINCT l.action_id) AS rows,
       min(l.waiting_since) AS since, min(l.next_attempt_at) AS next_attempt,
       coalesce(sum(c.budget_owls - c.spent_owls), 0) AS held_owls
  FROM ledger l LEFT JOIN commissions c
    ON c.action_id = l.action_id AND c.settled_at IS NULL
 WHERE l.status = 'open' AND l.waiting_on IS NOT NULL
 GROUP BY l.kind, l.waiting_on ORDER BY since;
```

**What is not here.** Only public data: no emails, keys, balances or
unfunded drafts, and no funder or contributor identities.

If a question needs something the views lack, say so with raise_issue.

Tools

This skill brings no tools.