feat(dashboard): nav restructure, full context-help coverage, 11 new ref docs

Navigation:
- New order: Overview · Todo · Domains · Repos · Workstreams (collapsible,
  open:false, with atomic sub-entries: Decisions, Tasks, Debt, Extends,
  Dependencies) · Contributions · SBOM · Progress · Reference (collapsible)
- Reference section gains path:/reference landing page; all 18 doc pages
  listed in nav (alphabetical) and in reference.md table

New pages:
- todo.md — Internal / Ecosystem / Third-party todo classification
- dependencies.md — dependency edge table derived from state/summary
- reference.md — Reference landing page with full doc index

New reference doc pages (11):
  contributions, debt, dependencies, domains, extensions, overview,
  repos, tasks, todo + reference (meta) already added previously

doc-overlay.js — lazy bubblehelp tooltip:
- _titleCache Map + _fetchDocTitle(docPath): on first hover of any ?
  button, fetches the target doc page, parses <h1>, sets btn.title
- Native browser tooltip appears exactly on the ? circle on subsequent hover

Context-help wired on all 14 dashboard pages:
- h1 withDocHelp added to: index, todo, domains, repos, tasks, techdept,
  extensions, dependencies (contributions/workstreams/decisions/sbom/
  progress/reference were already wired)
- domains.md + repos.md: added missing withDocHelp import and live-data link
- tasks/techdept/extensions: removed duplicate _h1 const that caused
  SyntaxError: Identifier '_h1' has already been declared

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-01 23:46:26 +01:00
parent 70c8e3cd51
commit 947c2e8824
22 changed files with 1468 additions and 25 deletions

View File

@@ -0,0 +1,120 @@
---
title: Contributions — Reference
---
# Contributions — Reference
Contributions track **outbound upstream work** — things the Custodian has
identified that belong in a repo it does not own or control. Each contribution
is a structured artifact filed locally in the repo's `contrib/` directory and
registered in the state hub so it is never lost.
---
## Contribution types
| Type | Full name | Use when |
|------|-----------|----------|
| `br` | Bug Report | You found a defect in an upstream tool or library |
| `fr` | Feature Request | You need functionality that upstream does not yet provide |
| `ep` | Extension Point | You identified a future enhancement opportunity in upstream code |
| `upr` | Upstream PR | You have written (or are writing) a patch for an upstream repo |
---
## Lifecycle
```
draft → submitted → acknowledged → accepted → merged
↘ ↘
rejected withdrawn
```
| Status | Meaning |
|--------|---------|
| **draft** | Artifact written locally; not yet sent upstream |
| **submitted** | Filed as a GitHub issue, PR, or email — awaiting upstream response |
| **acknowledged** | Upstream has seen it and responded (e.g. triaged, commented) |
| **accepted** | Upstream agreed to take action |
| **merged** | PR accepted and merged; issue resolved |
| **rejected** | Upstream declined; record kept for future reference |
| **withdrawn** | We decided not to pursue it |
Transitions are enforced by the API — you cannot skip stages arbitrarily.
`submitted_at` is stamped automatically when status moves to `submitted`;
`resolved_at` is stamped when status moves to `merged`, `rejected`, or `withdrawn`.
---
## Relation to the Todo classification
Contributions map directly to the **Third-party** class in the inter-repo
communication taxonomy:
| Todo class | Mechanism |
|------------|-----------|
| Internal | Workplan file + task in this repo's workstream |
| Ecosystem | State hub task with `[repo:<slug>]` prefix |
| **Third-party** | **Contribution artifact in `contrib/` + state hub registration** |
Contributions in `draft`, `submitted`, or `acknowledged` status appear as
open Third-party todos on the [Todo](/todo) page.
---
## File layout
Each artifact lives in the current repo under `contrib/`:
```
contrib/
bug-reports/ br-YYYY-MM-DD--<org>--<repo>--<slug>.md
feature-requests/ fr-YYYY-MM-DD--<org>--<repo>--<slug>.md
extension-points/ EP-<DOMAIN>-NNN--<org>--<repo>--<slug>.md
upstream-prs/ upr-YYYY-MM-DD--<org>--<repo>--<slug>.md
```
Templates live in `~/the-custodian/canon/standards/contrib-templates/`.
Convention details: `~/the-custodian/canon/standards/contribution-convention_v0.1.md`.
---
## Adding a contribution
**1. Write the artifact file** using the appropriate template.
**2. Register it in the state hub** via MCP:
```
register_contribution(
type = "fr",
title = "Add sidebar TOC injection API",
target_org = "observablehq",
target_repo = "framework",
body_path = "contrib/feature-requests/fr-2026-02-26--observablehq--framework--toc.md",
related_workstream_id = "<uuid>"
)
```
**3. Close the loop** when you file it upstream:
```
update_contribution_status(contribution_id="<uuid>", status="submitted")
```
**4. Keep updating** as upstream responds — `acknowledged`, `accepted`, `merged`.
---
## Kanban board
The Contributions page groups artifacts by status column. Only columns with at
least one entry are shown. The **⚠ follow-up banner** appears when any
contribution has been in `submitted` or `acknowledged` for an extended period
without further movement — a prompt to check in with upstream.
---
*Contributions are append-only. Rejected or withdrawn artifacts are retained as
institutional memory — they explain why certain approaches were tried and
dropped.*

View File

@@ -0,0 +1,91 @@
---
title: Technical Debt — Reference
---
# Technical Debt — Reference
The Technical Debt page tracks known quality compromises across all six project
domains — intentional shortcuts, design weaknesses, missing tests, and similar
issues that reduce codebase health but have been consciously deferred.
---
## Debt types
| Type | Examples |
|------|---------|
| **design** | Architectural decisions that should be revisited |
| **implementation** | Hacky or fragile code that works but shouldn't stay |
| **test** | Missing or incomplete test coverage |
| **docs** | Missing or outdated documentation |
| **dependencies** | Pinned old versions, unused packages, missing lockfiles |
| **performance** | Known bottlenecks not yet worth addressing |
| **security** | Hardcoded values, missing input validation, weak auth |
| **other** | Anything that doesn't fit the above |
---
## Severity levels
| Severity | Meaning |
|----------|---------|
| **critical** | Blocks release or poses an active risk |
| **high** | Should be resolved before the next major milestone |
| **medium** | Normal triage priority |
| **low** | Nice-to-fix; acceptable to defer indefinitely |
---
## Statuses
| Status | Meaning |
|--------|---------|
| **open** | Known and unaddressed |
| **in_progress** | Being actively worked on |
| **deferred** | Acknowledged but intentionally postponed |
| **resolved** | Fixed |
| **wont_fix** | Accepted as permanent — documented for future reference |
Items are sorted by status (open → in_progress → deferred → resolved → wont_fix)
then by severity (critical → high → medium → low) within each group.
---
## Filters
| Filter | Effect |
|--------|--------|
| **Status** | Multi-select |
| **Severity** | Multi-select |
| **Domain** | Multi-select |
| **Type** | Multi-select |
---
## Registering debt
Via MCP:
```
register_technical_debt(
domain = "custodian",
title = "Hard-coded API URL in data loaders",
debt_type = "implementation",
severity = "high",
description = "All data loaders use http://127.0.0.1:8000 directly. Should read from an env var or config.",
location = "state-hub/dashboard/src/data/*.json.py",
workstream_id = "<uuid>" # optional
)
```
```
update_td_status(td_uuid="<uuid>", status="resolved")
```
---
## Human-readable IDs
Each debt item carries a human-readable ID in the form `TD-<DOMAIN>-NNN`
(e.g. `TD-CUST-001`). IDs are optional at creation and auto-assigned if omitted.
They appear in the table for easy reference in commit messages and comments.

View File

@@ -0,0 +1,90 @@
---
title: Dependencies — Reference
---
# Dependencies — Reference
The Dependencies page shows the directed dependency graph between active
workstreams — which workstreams are waiting on others to reach a satisfactory
state before they can fully proceed.
---
## What is a dependency edge?
A dependency edge **A → B** means workstream A cannot fully proceed until
workstream B is in a satisfactory state (typically `completed` or `archived`).
Edges are used to model real sequencing constraints: for example, a shared
library must reach a stable release before downstream domains can build on it.
The Custodian's dependency order is:
```
Railiance → Markitect → Coulomb.social → Personhood / Foerster → Custodian
```
---
## Edge table
Each row shows:
| Column | Meaning |
|--------|---------|
| **Depends-on domain** | Domain of the dependent workstream (the one waiting) |
| **Depends-on workstream** | Title of the workstream that has the dependency |
| **→** | Direction arrow |
| **Blocked-by domain** | Domain of the prerequisite workstream |
| **Blocked-by workstream** | Title of the workstream that must complete first |
| **Status** | Current status of the prerequisite (green = active, grey = completed) |
---
## KPI sidebar card
Shows the total number of edges and the number of distinct workstreams involved
in at least one dependency relationship.
---
## Registering a dependency
Via MCP:
```
create_dependency(
from_workstream_id = "<uuid of dependent>",
to_workstream_id = "<uuid of prerequisite>",
description = "Cannot build auth layer until shared-library API is stable"
)
```
Via REST:
```bash
curl -X POST http://127.0.0.1:8000/workstreams/<from_id>/dependencies/ \
-H "Content-Type: application/json" \
-d '{"to_workstream_id": "<to_id>", "description": "..."}'
```
To list dependencies for a workstream:
```
list_dependencies(workstream_id="<uuid>")
```
---
## Cycle detection
The Workstream Health Index (WHI) includes a **Cycle Penalty Index (CPI)**
metric that detects circular dependencies using depth-first search. If CPI = 1,
a cycle exists and the WHI is penalised by 50%. The WHI KPI card on the
[Workstreams](/workstreams) page will display a cycle alert.
---
## Data source
Dependency edges are derived from the `depends_on` arrays on `open_workstreams`
in `GET /state/summary`. Polls every **15 seconds**.

View File

@@ -0,0 +1,82 @@
---
title: Domains — Reference
---
# Domains — Reference
The Domains page shows all registered project domains and the repositories
associated with each one. Domains are the top-level organisational unit of the
Custodian ecosystem.
---
## What is a domain?
A domain corresponds to one of the six tracked project areas:
| Slug | Project |
|------|---------|
| `custodian` | The Custodian agent system itself |
| `railiance` | DevOps & infrastructure reliability |
| `markitect` | Knowledge artifact management |
| `coulomb_social` | Co-creation marketplace |
| `personhood` | Rights & obligations framework |
| `foerster_capabilities` | Agency capability taxonomy |
Each domain has a slug (URL-friendly identifier), a human-readable name, an
optional description, and a status.
---
## Domain statuses
| Status | Meaning |
|--------|---------|
| **active** | Live domain — topics, workstreams, and tasks are being tracked |
| **archived** | Soft-deleted; no active work. Fails to archive if active topics exist |
---
## KPI row
Four counters at the top of the page:
| Counter | Meaning |
|---------|---------|
| Total domains | All registered domains regardless of status |
| Active | Domains with status `active` |
| Total repos | Sum of all registered repositories across all domains |
| Newest domain | Name of the most recently created domain |
---
## Domain cards
One card per domain showing:
- **Slug** — monospace identifier
- **Status badge** — green `active` or grey `archived`
- **Name** — display name
- **Description** — first 160 characters
- **Repos** — list of registered repositories for this domain, each showing name, local path, and remote URL
---
## Managing domains
Via MCP:
```
create_domain(slug="my_project", name="My Project", description="…")
rename_domain(slug="old_slug", new_slug="new_slug", new_name="New Name")
archive_domain(slug="my_project") # fails if active topics exist
```
Via Makefile:
```bash
make add-domain SLUG=my_project NAME="My Project"
make rename-domain OLD_SLUG=my_project NEW_SLUG=myproject NEW_NAME="My Project"
```
*Domains are never hard-deleted — only archived.*

View File

@@ -0,0 +1,102 @@
---
title: Extension Points — Reference
---
# Extension Points — Reference
The Extension Points page tracks known future enhancement opportunities across
all six domains — design forks the system *could* take, parked deliberately
for later consideration rather than acted on immediately.
---
## What is an extension point?
An extension point (EP) captures a place in the design where additional
capability could be added — an API surface that could be extended, a schema
that could grow, an integration that could be built. Recording an EP
acknowledges the opportunity without committing to it.
Extension points are distinct from technical debt: debt is a known compromise
that should be fixed; EPs are optional future directions that may or may not
be pursued.
---
## EP types
| Type | Examples |
|------|---------|
| **api** | New endpoints, query parameters, response fields |
| **schema** | New tables, columns, relationships |
| **mcp** | New MCP tools or resources |
| **dashboard** | New pages, charts, or components |
| **architecture** | Structural changes to the system design |
| **integration** | Connections to external systems |
| **other** | Anything that doesn't fit the above |
---
## Statuses
| Status | Meaning |
|--------|---------|
| **open** | Identified, not yet acted on |
| **in_progress** | Being implemented as part of an active workstream |
| **addressed** | The capability has been built |
| **deferred** | Intentionally postponed |
| **wont_fix** | Decided not to pursue — kept for documentation |
Items are sorted by status (open → in_progress → deferred → addressed → wont_fix)
then by priority (critical → high → medium → low).
---
## Priorities
| Priority | Meaning |
|----------|---------|
| **critical** | Needed to unblock other work |
| **high** | High-value enhancement for the near term |
| **medium** | Would be useful but not urgent |
| **low** | Speculative or long-horizon idea |
---
## Filters
| Filter | Effect |
|--------|--------|
| **Status** | Multi-select |
| **Priority** | Multi-select |
| **Domain** | Multi-select |
| **Type** | Multi-select |
---
## Registering an extension point
Via MCP:
```
register_extension_point(
domain = "custodian",
title = "Configurable poll interval per dashboard page",
ep_type = "dashboard",
priority = "low",
description = "Each page hard-codes POLL = 15_000. An env var or per-page config would allow slowing down low-priority pages to reduce API load.",
location = "state-hub/dashboard/src/*.md",
workstream_id = "<uuid>" # optional
)
```
```
update_ep_status(ep_uuid="<uuid>", status="addressed")
```
---
## Human-readable IDs
Each EP carries an ID in the form `EP-<DOMAIN>-NNN` (e.g. `EP-CUST-001`).
IDs are optional at creation and auto-assigned if omitted.

View File

@@ -0,0 +1,84 @@
---
title: Overview — Reference
---
# Overview — Reference
The Overview page is the operational home screen of the Custodian State Hub.
It shows the live health of the entire ecosystem at a glance — active work,
blocking decisions, and system-derived next-step suggestions.
---
## Sections
### Open Workstreams by Domain
A horizontal stacked bar chart showing every active workstream across all six
domains. Each bar is broken into four task-status segments:
| Colour | Segment |
|--------|---------|
| green | done |
| blue | in progress |
| orange-red | blocked |
| light grey | todo |
The left axis shows domain labels (one per group of workstreams). The `done/total`
count is printed to the right of each bar. Workstreams with no tasks yet show
a grey "— no tasks yet" label.
### Contribution & SBOM Health
Three summary cards linked to the Contributions and SBOM pages:
| Card | Shows |
|------|-------|
| **Contributions** | Total artifact count; orange warning if any are awaiting upstream response |
| **Licence Risk** | Count of SBOM packages with copyleft licences in direct dependencies |
| **SBOM** | Breakdown by contribution type (BR / FR / EP / UPR) |
### Status
Four metric cards:
| Card | Meaning |
|------|---------|
| **Active Workstreams** | Count of non-completed, non-archived workstreams |
| **Blocking Decisions** | Pending decisions with status `open` or `escalated` — orange border if > 0 |
| **Blocked Tasks** | Click to expand the list with blocking reasons |
| **Events Today** | Progress events created on today's date |
### What's next?
System-derived action suggestions from `GET /state/next_steps`. Suggestions are
generated when a decision is resolved or a workstream dependency is cleared, and
they point to the first open task in the relevant workstream. These are derived
on request and never persisted.
### Blocking Decisions
Inline resolution form for each pending decision. Expand a card, enter a
rationale and "decided by" name, and click **Record & close**. The decision is
resolved via `POST /decisions/{id}/resolve` and disappears from the list
without a page reload.
### Registered Projects
Table of projects registered with `make register-project`, sourced from
`milestone` progress events whose summary starts with
`"Project registered with State Hub:"`.
### Recent Activity
Last 20 progress events across all domains, showing time, event type, author,
and summary.
---
## Data source
Polls `GET /state/summary` every **15 seconds**. Blocking decisions are fetched
separately via `GET /decisions/?decision_type=pending` and only re-fetched
after a successful resolve action — this prevents the inline form from being
wiped on every poll.

View File

@@ -0,0 +1,119 @@
---
title: Reference & Context Help — Reference
---
# Reference & Context Help
The **Reference** section is a collection of in-depth documentation pages
explaining the data model, design conventions, and mechanics of each dashboard
view. Reference pages are readable as standalone articles and also surfaced
inline via the **? context-help button** on dashboard pages.
---
## The ? context-help button
Every dashboard page exposes one or more **?** buttons — small circular
controls that open the relevant reference page in an overlay without leaving
the current view.
### Where ? buttons appear
| Location | Opens |
|----------|-------|
| Page **h1** heading | Reference page for that dashboard view |
| **KPI sidebar cards** | Reference page for the specific metric shown |
| **Live indicator** | [Live Data](/docs/live-data) — poll interval, offline recovery |
### How to use it
1. Hover over the element — the **?** button fades in at the top-right corner.
2. Click **?** — the reference page opens in a modal overlay.
3. Read the docs, then dismiss with **✕ close**, **Esc**, or by clicking the
backdrop.
The overlay does not interrupt the live data polling loop — the dashboard
continues refreshing in the background while the overlay is open.
---
## Overlay behaviour
| Detail | Value |
|--------|-------|
| Size | `min(780px, 92vw)` wide · `82vh` tall |
| Content | Observable Framework page rendered in an `<iframe>` |
| Dismiss | ✕ button · Esc key · click outside the box |
| Animation | Fade-in backdrop + slide-up box (150 ms) |
| Stacking | `z-index: 9000` — always above dashboard content |
Only one overlay can be open at a time. Opening a second **?** replaces the
first automatically.
---
## Adding ? help to a new page
The helper is exported from `src/components/doc-overlay.js`:
```js
import {withDocHelp} from "./components/doc-overlay.js";
```
**On a page h1:**
```js
const _h1 = document.querySelector("#observablehq-main h1");
if (_h1) { _h1.style.position = "relative"; withDocHelp(_h1, "/docs/my-page"); }
```
**On a sidebar card or other element** (must have `position: relative`):
```js
const _card = html`<div class="kpi-infobox" style="position:relative">…</div>`;
withDocHelp(_card, "/docs/my-page");
```
`withDocHelp(element, docPath)` mutates the element in place and returns it,
so it can be chained directly before `display()` or `injectTocTop()`.
---
## Writing a reference page
Reference pages live in `state-hub/dashboard/src/docs/` and follow a consistent
structure:
```
---
title: Topic — Reference
---
# Topic — Reference
One-sentence purpose statement.
---
## Section 1
## Section 2
---
*Footer note (optional — e.g. governance constraint, append-only policy).*
```
**Conventions:**
- Title frontmatter: `"Topic — Reference"` (em dash, not hyphen)
- Sections separated by `---` horizontal rules
- Tables preferred over prose lists for structured data
- Code blocks for MCP tool calls and REST examples
- No live data fetching — reference pages are static
After writing the page, register it in two places:
1. **`observablehq.config.js`** — add to the Reference `pages` array (alphabetical)
2. **`src/reference.md`** — add a row to the dashboard-pages table

View File

@@ -0,0 +1,83 @@
---
title: Repos — Reference
---
# Repos — Reference
The Repos page shows every repository registered in the Custodian ecosystem,
their SBOM ingestion status, and a domain-grouped coverage map.
---
## What is a managed repo?
A managed repo is a git repository that has been registered with the state hub
via `make add-repo` or `register_repo()`. Registration records the repo's slug,
domain, local path, and optional remote URL. Once registered, the repo can
receive SBOM ingestion and is eligible for the ADR-001 workplan validator.
---
## KPI row
| Card | Meaning |
|------|---------|
| **Registered Repos** | Active repos only (status = active) |
| **Domains** | Count of distinct domain slugs across registered repos |
| **SBOM Ingested** | Repos with at least one SBOM snapshot |
| **SBOM Gaps** | Repos with no ingested SBOM — red border when > 0 |
---
## Coverage Map
Groups repos by domain. Each domain block shows:
- **Domain name** with SBOM, EP, and TD chip indicators
- **SBOM chip** — green ✓ if all repos in the domain are ingested, amber ⚠ if any gap exists
- **EPs chip** — count of open/in-progress extension points for this domain
- **TDs chip** — count of open/in-progress technical debt items for this domain
- **Repo table** — one row per repo with SBOM status, package count, and local path
Rows with no SBOM are highlighted in amber.
---
## Filters
| Filter | Effect |
|--------|--------|
| **Domain** | Show repos for a single domain only |
| **Gaps only** | Toggle to show only repos without an ingested SBOM |
---
## Ingesting a repo's SBOM
```bash
# Register a new repo
cd ~/the-custodian/state-hub
make add-repo DOMAIN=<slug> SLUG=<repo-slug> NAME="Display Name" PATH=/absolute/path
# Ingest SBOM (auto-detects lockfile at repo root)
make ingest-sbom REPO=<slug> REPO_PATH=/absolute/path
# Multi-ecosystem repo — scan all lockfiles recursively
make ingest-sbom REPO=<slug> SCAN=1 REPO_PATH=/absolute/path
```
Supported lockfile formats: `uv.lock`, `requirements.txt`, `package-lock.json`,
`yarn.lock`, `Cargo.lock`, `.terraform.lock.hcl`.
---
## Infra-only repos
Repos with no lockfile (Ansible, shell scripts) can be registered for inventory
purposes. The SBOM gap is expected and can be left as-is. Terraform providers
are auto-detected via `.terraform.lock.hcl` when using `--scan`.
---
*SBOM snapshots are replaced on each ingest — not appended. The last ingestion
timestamp is recorded on the managed_repo row.*

View File

@@ -0,0 +1,95 @@
---
title: Tasks — Reference
---
# Tasks — Reference
The Tasks page shows all tasks across every workstream and domain, with live
filtering, a status distribution chart, and a blocked-tasks highlight section.
---
## Task statuses
| Status | Meaning |
|--------|---------|
| **todo** | Not yet started |
| **in_progress** | Actively being worked on |
| **blocked** | Cannot proceed — has a blocking reason |
| **done** | Completed |
| **cancelled** | Dropped; not counted toward totals |
---
## Task priorities
| Priority | Use for |
|----------|---------|
| **critical** | Must be resolved immediately; blocks a release or governance gate |
| **high** | Should be resolved this session or next |
| **medium** | Normal backlog priority |
| **low** | Nice-to-have; deferred is acceptable |
---
## Filter bar
| Filter | Effect |
|--------|--------|
| **Status** | Multi-select — show only chosen statuses |
| **Priority** | Multi-select — show only chosen priorities |
| **Domain** | Multi-select — filter by domain slug |
| **Assignee** | Case-insensitive substring match on the assignee field |
All filters are applied client-side after each poll.
---
## Status Distribution chart
A horizontal bar chart (Observable Plot) showing the count of filtered tasks
per status, colour-coded:
| Colour | Status |
|--------|--------|
| grey-blue | todo |
| blue | in_progress |
| red | blocked |
| green | done |
| light grey | cancelled |
---
## Blocked Tasks section
Shows cards for every task currently in `blocked` status within the active
filter. Each card displays:
- Priority badge and status
- Domain and workstream context
- Task title
- Blocking reason (amber background)
---
## KPI sidebar card
Shows four counts for the unfiltered dataset: open (todo + in_progress +
blocked), blocked, in progress, done, and a done-% of total.
---
## Sorting
Tasks are sorted by status (blocked first, then in_progress, todo, done,
cancelled) then by priority (critical → high → medium → low) within each
status group.
---
## Data sources
Polls every **15 seconds**:
- `GET /tasks/?limit=500`
- `GET /workstreams/`
- `GET /topics/`

View File

@@ -0,0 +1,71 @@
---
title: Todo — Reference
---
# Todo — Reference
The Todo page shows the Custodian's own open work items classified by where the
work belongs — inside this repo, routed from another ecosystem repo, or aimed
at an upstream third-party project.
This page is the session-start orientation surface for the `the-custodian` repo.
See [Inter-Repo Communication](/docs/inter-repo-communication) for the full
boundary rule and routing workflows.
---
## The three classes
### Internal
Open tasks (`todo`, `in_progress`, `blocked`) in **custodian domain workstreams**
whose title does not contain a `[repo:]` routing prefix.
These are tasks this agent is directly responsible for and can address within
the current repo.
### Ecosystem (inbound)
Tasks from **any workstream** whose title contains `[repo:the-custodian]`.
These tasks were created by agents in other repos to route work to the custodian.
When a task with this prefix appears, the session protocol picks it up, the
custodian creates a workplan file (ADR-001), and addresses the work here.
### Third-party (outbound)
Contribution artifacts in **open status** (`draft`, `submitted`, `acknowledged`).
These represent work the custodian has identified for upstream repos it does not
own. They remain on the todo list until the upstream loop is closed (`merged`,
`rejected`, or `withdrawn`).
---
## Classification decision table
| Situation | Class | Action |
|-----------|-------|--------|
| Bug found in this repo | Internal | Fix it directly |
| Work needed in another registered repo | Ecosystem | `create_task(..., title="[repo:<slug>] ...")` |
| Bug found in an upstream library | Third-party | Create BR artifact + `register_contribution` |
| Feature needed from upstream | Third-party | Create FR artifact + `register_contribution` |
---
## KPI sidebar card
Shows the count of open items in each class at a glance. The `?` button links
to this reference page.
---
## Data sources
Polls every **15 seconds**:
- `GET /tasks/?limit=500` — all tasks
- `GET /workstreams/` — for domain + title context
- `GET /topics/` — for domain slug resolution
- `GET /contributions/` — for third-party todos
*Classification is done client-side — no server-side filter endpoint required.*