Implemented grounded-extraction bundle via a generic coordinator capability-contribution seam¶
Angelo › zettelkasten › Phase: Grounded Extraction Pipeline + Reusable Schemas (coordinator capability)
Type: Decision · Status: active · Created: 2026-06-24 · Updated: 2026-06-25
Tags: coordinator,contrib,entry-points,schema,extractor,scribe,auditor,create_extraction_graph,conditional-shipping
What¶
A grounded-extraction run applies a fixed extractor -> scribe -> auditor (+ trailing memory) pipeline to N sources, parameterized by one named schema (a rubric). extractor emits grounded claim+verbatim-quote candidates per schema dimension; scribe commits them as claim+quote note pairs tagged with the dimension tags and linked to a per-source hub; auditor verifies grounding integrity + dimension coverage. Each schema dimension's tag becomes the note tag, so the schema is simultaneously the extraction rubric and the cross-source comparison index.
Key architectural decision: capability-contribution seam¶
The coordinator core stays generic. New module coordinator/contrib.py discovers capabilities via the angelo.coordinator.capabilities entry-point group (with a first-party fallback list so it works in editable/dev installs without reinstall). A capability is a zero-arg callable returning {name, enabled, agents, schemas}. The coordinator learned exactly two generic tricks:
1. Contributed agents folded into list_agents/get_persona/roles with precedence core < contributed < project-local (agents.yaml).
2. A schema task attribute resolved + flowed into task context exactly like model (Task.schema name + Task.schema_obj expanded rubric ride through get_ready_tasks/claim_task/get_task_context).
zettelkasten/coordinator_agents.py defines the three personas (extractor=planner, scribe=implementer, auditor=checker with a deliberately different model family) + the capability() entry point. zettelkasten/extraction_schemas.py + extraction-schemas.yaml are the schema registry (package defaults + project overlay, tag-uniqueness enforced).
Enablement / conditional shipping (locked)¶
The capability self-gates: capability() returns enabled=False unless ANGELO_ZETTELKASTEN=1 is set on the coordinator MCP process (written by mcp-zettelkasten.json). When disabled: trio absent from list_agents, create_extraction_graph not registered, and a task carrying a schema is a HARD validation error (spec 8.3). zettelkasten is now a coordinator capability, not just an MCP server.
create_extraction_graph (coordinator tool, conditional)¶
One tool does in-process tool-side prep (ingest -> create_source -> seed per-source hub, capturing its id) then emits the trio DAG stamping schema on every task. Prep is tool-side, NOT a graph task, because the extractor is a planner and a planner cannot depend on an implementer (graph validation forbids it), so ingest can't be a graph node. Returns {run_id, task_ids, graph, sources, graph_summary}. Driven with the normal wave loop; scribes serialize via the write-lease.
Locked decisions¶
- schema-tag enforcement (strict): a written note lacking a valid schema tag is rejected.
- grounding is a per-schema option (
grounded: true/false). schemaattribute with the capability disabled => validation error.
Shipped rule + tests¶
grounded-extraction.mdc/.md (with a schema-authoring mini-guide) wired into the CLI file maps + Claude imports + live .cursor/. 23 new tests in tests/test_grounded_extraction.py (gating, schema registry, schema flow/validation, DAG shape) all pass; coordinator/CLI regression suites green. The 8 full-suite failures are pre-existing and unrelated (artifacts reruns, claude-hook registry, federation API, one intra-file-ordering-flaky memory git-pin test).
Where things live¶
- contrib seam: coordinator/contrib.py
- schema attribute on tasks: coordinator/graph.py
- agent merge + schema flow + tool gating: coordinator/server.py, coordinator/agents.py
- prep + DAG builder: coordinator/extraction.py
- personas + entry point: zettelkasten/coordinator_agents.py
- schema registry: zettelkasten/extraction_schemas.py + extraction-schemas.yaml
- entry point + package-data: pyproject.toml ([project.entry-points."angelo.coordinator.capabilities"])
- enablement flag: mcp-zettelkasten.json (ANGELO_ZETTELKASTEN=1)
Referenced files¶
coordinator/contrib.py@c62563dcoordinator/extraction.py@c62563dcoordinator/graph.py@c62563dcoordinator/server.py@c62563dcoordinator/agents.py@c62563dzettelkasten/coordinator_agents.py@c62563dzettelkasten/extraction_schemas.py@c62563dzettelkasten/extraction-schemas.yaml@c62563dpyproject.toml@c62563dangelo_cli/__init__.py@c62563dangelo_cli/data/mcp-zettelkasten.json@c62563dangelo_cli/data/claude/mcp-zettelkasten.json@c62563dangelo_cli/data/rules/grounded-extraction.mdc@c62563dangelo_cli/data/claude/rules/grounded-extraction.md@c62563dtests/test_grounded_extraction.py@c62563d- .cursor/mcp.json@c62563d
- .cursor/rules/grounded-extraction.mdc@c62563d
Source: memory entry deci-1ebbd521.