rag-wright 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rag_wright/__init__.py +13 -0
- rag_wright/api/__init__.py +33 -0
- rag_wright/api/config.py +59 -0
- rag_wright/api/discover.py +70 -0
- rag_wright/api/documents.py +39 -0
- rag_wright/api/ids.py +31 -0
- rag_wright/api/invoke.py +99 -0
- rag_wright/api/kg.py +61 -0
- rag_wright/api/mcp.py +94 -0
- rag_wright/api/usage.py +30 -0
- rag_wright/api/workspace.py +85 -0
- rag_wright/capabilities/__init__.py +8 -0
- rag_wright/capabilities/answer_generator.py +427 -0
- rag_wright/capabilities/ard.py +286 -0
- rag_wright/capabilities/assertion_extraction.py +79 -0
- rag_wright/capabilities/chunk_read.py +58 -0
- rag_wright/capabilities/chunk_write.py +163 -0
- rag_wright/capabilities/claim_extraction.py +153 -0
- rag_wright/capabilities/clause_exception_linking.py +117 -0
- rag_wright/capabilities/compliance_judgment.py +322 -0
- rag_wright/capabilities/compliance_store.py +87 -0
- rag_wright/capabilities/contract_kg_serve.py +156 -0
- rag_wright/capabilities/contract_kg_store.py +251 -0
- rag_wright/capabilities/dg_extraction.py +585 -0
- rag_wright/capabilities/disambiguation.py +163 -0
- rag_wright/capabilities/document_parse.py +87 -0
- rag_wright/capabilities/document_scope.py +49 -0
- rag_wright/capabilities/embedding.py +164 -0
- rag_wright/capabilities/embedding_profiles.py +43 -0
- rag_wright/capabilities/entity_resolution.py +154 -0
- rag_wright/capabilities/fusion.py +64 -0
- rag_wright/capabilities/graph_extraction.py +243 -0
- rag_wright/capabilities/graph_query.py +73 -0
- rag_wright/capabilities/graph_storage.py +111 -0
- rag_wright/capabilities/highlight_serve.py +142 -0
- rag_wright/capabilities/hybrid_search.py +65 -0
- rag_wright/capabilities/invoke.py +31 -0
- rag_wright/capabilities/jev_decision.py +38 -0
- rag_wright/capabilities/manifests.py +872 -0
- rag_wright/capabilities/okf_navigate.py +456 -0
- rag_wright/capabilities/parsing.py +286 -0
- rag_wright/capabilities/property_boosted_retrieval.py +125 -0
- rag_wright/capabilities/query_function_classifier.py +94 -0
- rag_wright/capabilities/query_understanding.py +109 -0
- rag_wright/capabilities/registry.py +262 -0
- rag_wright/capabilities/remote_encoders.py +94 -0
- rag_wright/capabilities/requirement_extraction.py +247 -0
- rag_wright/capabilities/reranking.py +123 -0
- rag_wright/capabilities/retrieval_core.py +126 -0
- rag_wright/capabilities/rlm_chunking.py +808 -0
- rag_wright/capabilities/rlm_synthesis.py +316 -0
- rag_wright/capabilities/scan_quality.py +136 -0
- rag_wright/capabilities/span_relevance_judgment.py +191 -0
- rag_wright/capabilities/vision_to_text.py +85 -0
- rag_wright/capabilities/vlm_ocr.py +85 -0
- rag_wright/contracts/__init__.py +6 -0
- rag_wright/contracts/chunk.py +79 -0
- rag_wright/contracts/compliance.py +303 -0
- rag_wright/contracts/contract_meta.py +27 -0
- rag_wright/contracts/extraction.py +130 -0
- rag_wright/contracts/function.py +167 -0
- rag_wright/contracts/function_routing.py +91 -0
- rag_wright/contracts/highlight.py +74 -0
- rag_wright/contracts/identifiers.py +153 -0
- rag_wright/contracts/jurisdiction.py +96 -0
- rag_wright/contracts/ontology.py +142 -0
- rag_wright/contracts/property.py +201 -0
- rag_wright/contracts/provenance.py +78 -0
- rag_wright/contracts/query_intent.py +53 -0
- rag_wright/contracts/span.py +76 -0
- rag_wright/contracts/value_match.py +84 -0
- rag_wright/corpus/__init__.py +0 -0
- rag_wright/corpus/canonicalize.py +116 -0
- rag_wright/corpus/cuad.py +153 -0
- rag_wright/corpus/cuad_ingestion.py +72 -0
- rag_wright/corpus/document_parser.py +299 -0
- rag_wright/corpus/edgar.py +231 -0
- rag_wright/corpus/gcs_ingestion.py +120 -0
- rag_wright/corpus/http.py +110 -0
- rag_wright/corpus/selection.py +152 -0
- rag_wright/mcp/__init__.py +11 -0
- rag_wright/mcp/compliance_server.py +299 -0
- rag_wright/mcp/intra_document_qa_server.py +170 -0
- rag_wright/mcp/relational_qa_server.py +171 -0
- rag_wright/mcp/session_store.py +64 -0
- rag_wright/mcp/typed_property_retrieval_server.py +191 -0
- rag_wright/models/__init__.py +8 -0
- rag_wright/models/profiles.py +331 -0
- rag_wright/models/seam.py +497 -0
- rag_wright/models/tag_structured.py +285 -0
- rag_wright/models/tracing.py +179 -0
- rag_wright/models/usage.py +102 -0
- rag_wright/okf/__init__.py +11 -0
- rag_wright/okf/compile.py +292 -0
- rag_wright/okf/document.py +47 -0
- rag_wright/okf/enrich.py +176 -0
- rag_wright/okf/links.py +190 -0
- rag_wright/okf/lint.py +105 -0
- rag_wright/ontology/__init__.py +6 -0
- rag_wright/ontology/_generated_template_meta.py +60 -0
- rag_wright/ontology/_generated_vocab.py +52 -0
- rag_wright/ontology/clause_template.py +964 -0
- rag_wright/ontology/codegen.py +84 -0
- rag_wright/ontology/compliance_bridge.ttl +186 -0
- rag_wright/ontology/contract_bridge.ttl +2685 -0
- rag_wright/ontology/contract_taxonomy.py +24 -0
- rag_wright/ontology/derive.py +58 -0
- rag_wright/ontology/loader.py +435 -0
- rag_wright/ontology/packs/ftc_16cfr255.ttl +29 -0
- rag_wright/ontology/registry.py +87 -0
- rag_wright/ontology/template_introspect.py +100 -0
- rag_wright/py.typed +0 -0
- rag_wright/reference/__init__.py +2 -0
- rag_wright/reference/compliance.py +41 -0
- rag_wright/reference/contract_seam.py +123 -0
- rag_wright/skills/__init__.py +7 -0
- rag_wright/skills/claim_extraction/SKILL.md +47 -0
- rag_wright/skills/claim_extraction/__init__.py +1 -0
- rag_wright/skills/claim_extraction/template.py +50 -0
- rag_wright/skills/compliance_judgment/SKILL.md +59 -0
- rag_wright/skills/corpus_ingest/SKILL.md +106 -0
- rag_wright/skills/extraction_semantic_judge/SKILL.md +51 -0
- rag_wright/skills/extraction_semantic_judge/__init__.py +1 -0
- rag_wright/skills/generation/SKILL.md +64 -0
- rag_wright/skills/generation/__init__.py +1 -0
- rag_wright/skills/generic_compliance_judgment/SKILL.md +58 -0
- rag_wright/skills/okf_navigate/SKILL.md +137 -0
- rag_wright/skills/requirement_extraction/SKILL.md +47 -0
- rag_wright/skills/requirement_extraction/__init__.py +1 -0
- rag_wright/skills/requirement_extraction/template.py +50 -0
- rag_wright/skills/rlm/SKILL.md +186 -0
- rag_wright/skills/rlm/__init__.py +31 -0
- rag_wright/skills/rlm/agent.py +292 -0
- rag_wright/skills/span_relevance_judgment/SKILL.md +67 -0
- rag_wright/skills/vision_to_text/SKILL.md +36 -0
- rag_wright/skills/vision_to_text/__init__.py +1 -0
- rag_wright/spans/__init__.py +1 -0
- rag_wright/spans/boundary.py +78 -0
- rag_wright/spans/clause_function_classifier.py +490 -0
- rag_wright/spans/clause_kg_extractor.py +337 -0
- rag_wright/spans/cuad_labels.py +81 -0
- rag_wright/spans/dim_classifier.py +158 -0
- rag_wright/spans/dim_fleet.json +411 -0
- rag_wright/spans/function_classifier.py +77 -0
- rag_wright/spans/function_families.py +62 -0
- rag_wright/spans/hybrid_classifier.py +103 -0
- rag_wright/spans/legalbert_classifier.py +83 -0
- rag_wright/spans/model_capabilities.py +107 -0
- rag_wright/spans/new_function_labels.py +111 -0
- rag_wright/spans/page_map.py +68 -0
- rag_wright/spans/property_extractor.py +365 -0
- rag_wright/spans/property_grounding.py +182 -0
- rag_wright/spans/reclassify.py +77 -0
- rag_wright/spans/scarce_function_labels.py +105 -0
- rag_wright/spans/segment.py +341 -0
- rag_wright/spans/semantic_judge.py +197 -0
- rag_wright/spans/symbolic_validation.py +131 -0
- rag_wright/spans/tag_clause_extractor.py +182 -0
- rag_wright/store/__init__.py +6 -0
- rag_wright/store/arcadedb.py +1135 -0
- rag_wright/store/chunk_text.py +66 -0
- rag_wright/store/seam.py +213 -0
- rag_wright/subgraphs/__init__.py +0 -0
- rag_wright/subgraphs/async_ingestion.py +204 -0
- rag_wright/subgraphs/compliance_check.py +1042 -0
- rag_wright/subgraphs/compliance_ingestion.py +306 -0
- rag_wright/subgraphs/contract_ingestion_pipeline.py +999 -0
- rag_wright/subgraphs/graph_extraction.py +102 -0
- rag_wright/subgraphs/intra_document_qa.py +328 -0
- rag_wright/subgraphs/observability.py +140 -0
- rag_wright/subgraphs/query_constraint_extraction.py +73 -0
- rag_wright/subgraphs/relational_qa.py +165 -0
- rag_wright/subgraphs/requirement_extraction.py +137 -0
- rag_wright/subgraphs/scaffold.py +65 -0
- rag_wright/subgraphs/semantic_chunking.py +183 -0
- rag_wright/subgraphs/typed_clause_extraction.py +172 -0
- rag_wright/subgraphs/typed_property_retrieval.py +278 -0
- rag_wright/util/__init__.py +1 -0
- rag_wright/util/concurrent.py +153 -0
- rag_wright/util/spacy_model.py +45 -0
- rag_wright-0.1.0.dist-info/METADATA +168 -0
- rag_wright-0.1.0.dist-info/RECORD +184 -0
- rag_wright-0.1.0.dist-info/WHEEL +4 -0
- rag_wright-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,872 @@
|
|
|
1
|
+
"""Per-capability ARD manifest authoring (the committed source; T15 onward).
|
|
2
|
+
|
|
3
|
+
Every discoverable capability (FR-C / FR-I / FR-Q) authors one ARD manifest, written to the shared
|
|
4
|
+
registry root as `<slug>.json` under `urn:air:dreamai.io:rag_wright:<slug>`. The authoring data that
|
|
5
|
+
cannot be derived at registration — above all the 2-5 representative queries discovery ranks on — is
|
|
6
|
+
committed here, one `CapabilityManifest` per capability, added at that capability's own task. The
|
|
7
|
+
registry root itself is regenerable (outside the repo, `~/.air/registry`); this module is the durable
|
|
8
|
+
source, and `scripts/publish_manifests.py` writes every spec into the root.
|
|
9
|
+
|
|
10
|
+
Authoring reuses the T6 seam: the canonical-slug set and URN emitter (`registry.py`), the media-type
|
|
11
|
+
map and callable-bounds rule (`ard.py`), and `ManifestSkeleton.author(...)` for the validated
|
|
12
|
+
`RegistryEntry`. A live `RegistryStore` load is a GraphWright-side step, not done here.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from dataclasses import dataclass
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import Optional
|
|
20
|
+
|
|
21
|
+
from rag_wright.capabilities.ard import (
|
|
22
|
+
CALLABLE_KINDS,
|
|
23
|
+
MEDIA_TYPE_BY_KIND,
|
|
24
|
+
CapabilityInterface,
|
|
25
|
+
EntryKind,
|
|
26
|
+
RegistryEntry,
|
|
27
|
+
ResponseBounds,
|
|
28
|
+
SkillRuntime,
|
|
29
|
+
write_manifest,
|
|
30
|
+
)
|
|
31
|
+
from rag_wright.capabilities.registry import (
|
|
32
|
+
CANONICAL_CAPABILITY_SLUGS,
|
|
33
|
+
ManifestSkeleton,
|
|
34
|
+
capability_urn,
|
|
35
|
+
)
|
|
36
|
+
from rag_wright.skills.rlm.agent import GRANTED_SUBAGENTS
|
|
37
|
+
|
|
38
|
+
# The RLM sub-agent roster the three RLM skills dispatch to, as the skill itself declares them
|
|
39
|
+
# (single source of truth in `skills/rlm/agent.py`). Since the recursive rebuild (T15/T17/T28) these are
|
|
40
|
+
# real Deep Agents sub-agents, so `grantedSubagents` is populated (ADR-0015; was `[]` pre-rebuild). Bound
|
|
41
|
+
# from `GRANTED_SUBAGENTS` so the manifest roster cannot drift from the names the skill actually declares
|
|
42
|
+
# and dispatches — a conformance test asserts the two are identical (drift passes here, fails GraphWright's
|
|
43
|
+
# bind).
|
|
44
|
+
_RLM_GRANTED = list(GRANTED_SUBAGENTS)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass(frozen=True)
|
|
48
|
+
class CapabilityManifest:
|
|
49
|
+
"""The committed ARD authoring data for one capability (what registration cannot derive)."""
|
|
50
|
+
|
|
51
|
+
slug: str
|
|
52
|
+
kind: EntryKind
|
|
53
|
+
display_name: str
|
|
54
|
+
description: str
|
|
55
|
+
representative_queries: tuple[str, ...] # 2-5; the field discovery ranks on
|
|
56
|
+
tags: tuple[str, ...] = ()
|
|
57
|
+
requires: tuple[str, ...] = () # closure; agent_skill only
|
|
58
|
+
skill_runtime: Optional[SkillRuntime] = None # intrinsic runtime; agent_skill only
|
|
59
|
+
golden_eval_ref: Optional[str] = None
|
|
60
|
+
response_bounds: Optional[ResponseBounds] = None # callable kinds only; defaults if omitted
|
|
61
|
+
# GraphWright vendor extension (ADR-0030): the governed typed I/O. Declared only for the query-graph
|
|
62
|
+
# capabilities GraphWright's checker verifies (the 5 + graph_query + generation); None elsewhere.
|
|
63
|
+
capability_interface: Optional[CapabilityInterface] = None
|
|
64
|
+
# EP-CORE-2 vendor extension (ADR-0118): the invoke factory for an INVOKABLE capability (subgraph/model), as a
|
|
65
|
+
# "module:attr" import pointer to a `(resources, inputs) -> result` callable (model factories ignore resources).
|
|
66
|
+
# ARD stays metadata-only (ADR-0003): this is a STRING pointer, not a callable. The invoker resolves + imports it
|
|
67
|
+
# lazily, so there is no central engine-owned adapter dict — a developer registering a cap with an impl_ref makes
|
|
68
|
+
# it invocable with zero engine edits. None for non-invokable kinds (function/agent_skill/mcp_tool) + reserved.
|
|
69
|
+
impl_ref: Optional[str] = None
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
# One entry per capability, added at that capability's task. T15 registers the shared RLM method
|
|
73
|
+
# skill; the two RLM capabilities (rlm_chunking T17, rlm_synthesis T28) will `require` it.
|
|
74
|
+
_SPECS: tuple[CapabilityManifest, ...] = (
|
|
75
|
+
CapabilityManifest(
|
|
76
|
+
slug="rlm_method",
|
|
77
|
+
kind="agent_skill",
|
|
78
|
+
display_name="RLM divide-and-conquer method",
|
|
79
|
+
description=(
|
|
80
|
+
"The general recursive-language-model method (FR-C.10): load a working set into an "
|
|
81
|
+
"interpreter, slice and dispatch the work in code, and synthesize the results, so the "
|
|
82
|
+
"model never attends over the full volume. A shared skill required by the RLM chunking "
|
|
83
|
+
"and RLM synthesis capabilities; it carries no determinism, boundary, or gating behavior "
|
|
84
|
+
"of its own (those belong to the applying capability)."
|
|
85
|
+
),
|
|
86
|
+
representative_queries=(
|
|
87
|
+
"divide and conquer over a working set too large for a single prompt",
|
|
88
|
+
"load a large working set into an interpreter and dispatch the work in code",
|
|
89
|
+
"recursively call sub-models on small focused slices instead of the whole volume",
|
|
90
|
+
"synthesize an answer from many partitioned sub-calls",
|
|
91
|
+
),
|
|
92
|
+
tags=("rlm", "method", "divide-and-conquer"),
|
|
93
|
+
# No capability_interface (T44): rlm_method is a shared METHOD skill `require`d by rlm_chunking and
|
|
94
|
+
# rlm_synthesis (loaded knowledge), never bound as a data-processing node in a graph — it has no
|
|
95
|
+
# pipeline data I/O of its own. The applying capability (chunking / synthesis) is what carries the
|
|
96
|
+
# governed interface; governing the method here would be a type with no producer or consumer.
|
|
97
|
+
# Intrinsic RLM runtime: the interpreter holds the working set and runs the code-side recursive
|
|
98
|
+
# decompose(), dispatching the two real sub-agents (ADR-0015). granted_subagents is bound from the
|
|
99
|
+
# skill's own roster so it cannot drift from what the skill declares/dispatches.
|
|
100
|
+
skill_runtime=SkillRuntime(
|
|
101
|
+
needs_interpreter=True, rlm=True, requires_dynamic_dispatch=True, granted_subagents=_RLM_GRANTED
|
|
102
|
+
),
|
|
103
|
+
),
|
|
104
|
+
CapabilityManifest(
|
|
105
|
+
slug="rlm_chunking",
|
|
106
|
+
kind="agent_skill", # applies the RLM method; loaded knowledge, requires rlm_method
|
|
107
|
+
display_name="RLM chunking",
|
|
108
|
+
description=(
|
|
109
|
+
"Read a whole parsed document through an interpreter using the RLM method, split it along "
|
|
110
|
+
"topic/section/chapter boundaries into semantically coherent chunks (capped ~20,000 "
|
|
111
|
+
"tokens), and write a summary per chunk with a per-document manifest and stable "
|
|
112
|
+
"chunk_ids. Deterministic and content-hash gated (FR-I.1)."
|
|
113
|
+
),
|
|
114
|
+
representative_queries=(
|
|
115
|
+
"chunk a long parsed document into semantically coherent sections",
|
|
116
|
+
"split a document along topic and section boundaries within a token cap",
|
|
117
|
+
"produce a summary per chunk and stable chunk ids",
|
|
118
|
+
"re-chunk a document only when its content changes",
|
|
119
|
+
),
|
|
120
|
+
requires=("rlm_method",),
|
|
121
|
+
tags=("chunking", "rlm", "ingestion"),
|
|
122
|
+
skill_runtime=SkillRuntime( # LLM boundary discovery via the recursive machinery; real sub-agents
|
|
123
|
+
needs_interpreter=True, rlm=True, requires_dynamic_dispatch=True, granted_subagents=_RLM_GRANTED
|
|
124
|
+
),
|
|
125
|
+
capability_interface=CapabilityInterface(
|
|
126
|
+
# Emits the ingestion `chunk` (id + text + summary + index) — NOT the query-side chunk_with_text;
|
|
127
|
+
# embedding and graph_extraction consume this same `chunk`.
|
|
128
|
+
inputs={"parsed": "parsed_doc"},
|
|
129
|
+
outputs={"chunks": "chunk"},
|
|
130
|
+
success_criterion="split a parsed document into semantically coherent, capped, summarized chunks with stable ids",
|
|
131
|
+
),
|
|
132
|
+
),
|
|
133
|
+
# EP-CORE-1b-iii (ADR-0118): graph_extraction / entity_disambiguation / entity_resolution are INTERNAL steps of
|
|
134
|
+
# `contract_ingestion_pipeline` (composed by direct import, no impl_ref, never invoked by ARD name), not
|
|
135
|
+
# agent/product-facing standalone caps -- so they are NOT published to the reference pack. They remain canonical
|
|
136
|
+
# FR-C slugs (CANONICAL_CAPABILITY_SLUGS) and reserved-without-manifest, like `ontology_registry_derivation`.
|
|
137
|
+
# DD-3/4/5 first removed their domain-vocab coupling (EntityId/EntityResolver seam; the entity/edge taxonomy).
|
|
138
|
+
CapabilityManifest(
|
|
139
|
+
slug="rlm_synthesis",
|
|
140
|
+
kind="agent_skill", # applies the RLM method; loaded knowledge, requires rlm_method
|
|
141
|
+
display_name="RLM synthesis",
|
|
142
|
+
description=(
|
|
143
|
+
"Apply the RLM divide-and-conquer method to the retrieved candidate chunks: load them into "
|
|
144
|
+
"an interpreter as data, slice in code (one focused unit per chunk), sub-call a model once "
|
|
145
|
+
"per unit, and combine the outputs in a recursive code-side reduce — so synthesis never "
|
|
146
|
+
"attends over the full chunk volume (FR-Q.5)."
|
|
147
|
+
),
|
|
148
|
+
representative_queries=(
|
|
149
|
+
"synthesize an answer from many retrieved chunks without attending over all at once",
|
|
150
|
+
"divide-and-conquer synthesis over a large candidate set",
|
|
151
|
+
"reduce retrieved passages into a focused synthesis for a query",
|
|
152
|
+
"recursively combine per-chunk extracts into one answer",
|
|
153
|
+
),
|
|
154
|
+
requires=("rlm_method",),
|
|
155
|
+
tags=("rlm", "synthesis", "query"),
|
|
156
|
+
skill_runtime=SkillRuntime( # recursive descent (real sub-agents) + kept _reduce ascent
|
|
157
|
+
needs_interpreter=True, rlm=True, requires_dynamic_dispatch=True, granted_subagents=_RLM_GRANTED
|
|
158
|
+
),
|
|
159
|
+
capability_interface=CapabilityInterface(
|
|
160
|
+
# Takes chunk_with_text (already rehydrated; does not fetch text). Emits the answer AND the
|
|
161
|
+
# citations: cited_chunk_ids (the cited set) + cited_extracts (per-slice extract, each cited).
|
|
162
|
+
inputs={"query": "text", "chunks": "chunk_with_text"},
|
|
163
|
+
outputs={"answer": "text", "cited_chunk_ids": "chunk_id", "cited_extracts": "cited_extract"},
|
|
164
|
+
success_criterion="recursively extract per-slice then reduce the chunks into a cited synthesis",
|
|
165
|
+
),
|
|
166
|
+
),
|
|
167
|
+
CapabilityManifest(
|
|
168
|
+
slug="generation",
|
|
169
|
+
kind="agent_skill", # a single grounded/cited LLM act; loaded, not called (CAP-REG-1)
|
|
170
|
+
display_name="Answer generation (grounded, cited, abstains)",
|
|
171
|
+
description=(
|
|
172
|
+
"Produce a grounded, cited answer from the retrieved evidence — no claim without a citation, "
|
|
173
|
+
"confidence-aware, abstaining when the context does not support an answer (FR-C.9, FR-Q.6). "
|
|
174
|
+
"Split from vision-to-text so discovery ranks it only on answer-generation intents (ADR-0014)."
|
|
175
|
+
),
|
|
176
|
+
representative_queries=(
|
|
177
|
+
"answer a question grounded in the retrieved evidence with citations",
|
|
178
|
+
"abstain when the retrieved context does not support an answer",
|
|
179
|
+
"generate a confidence-aware cited answer from contract evidence",
|
|
180
|
+
"produce a cited answer or an abstention from retrieved passages",
|
|
181
|
+
),
|
|
182
|
+
tags=("generation", "answer", "grounded", "cited", "abstention"),
|
|
183
|
+
capability_interface=CapabilityInterface(
|
|
184
|
+
# Alt answer step to rlm_synthesis; also consumes chunk_with_text (evidence, already rehydrated).
|
|
185
|
+
# Abstain is a boolean `abstained` flag on the answer record (empty citations), not a distinct
|
|
186
|
+
# typed channel and nothing downstream gates on it — so it stays in the payload, noted here.
|
|
187
|
+
inputs={"query": "text", "evidence": "chunk_with_text"},
|
|
188
|
+
outputs={"answer": "text", "cited_chunk_ids": "chunk_id"},
|
|
189
|
+
success_criterion="produce a grounded cited answer, or abstain (abstained flag, empty citations) when evidence does not support one",
|
|
190
|
+
),
|
|
191
|
+
),
|
|
192
|
+
CapabilityManifest(
|
|
193
|
+
slug="vision_to_text",
|
|
194
|
+
kind="agent_skill", # a single grounded vision-language act; SKILL.md, applied via the seam (SKILL-SPLIT)
|
|
195
|
+
display_name="Vision-to-text (scanned-image transcription; authored skill)",
|
|
196
|
+
description=(
|
|
197
|
+
"Transcribe a scanned filing's images to text at ingestion on the Gemma 4 class model (FR-C.9), "
|
|
198
|
+
"authored as skills/vision_to_text/SKILL.md: transcribe all visible text exactly, preserving "
|
|
199
|
+
"reading order, output only the text. A single grounded vision-language act -- the ingestion-side "
|
|
200
|
+
"twin of answer generation (also an agent_skill). Split from generation (ADR-0014): different "
|
|
201
|
+
"inputs (an image, not evidence), different failure modes, a different caller (ingestion). "
|
|
202
|
+
"Model-neutral through the seam (product = self-hosted Gemma-class, ADR-0039)."
|
|
203
|
+
),
|
|
204
|
+
representative_queries=(
|
|
205
|
+
"transcribe a scanned filing image to text",
|
|
206
|
+
"extract the text from a scanned or image-only document",
|
|
207
|
+
"convert a contract page image into machine-readable text at ingestion",
|
|
208
|
+
"read text off a rasterized document image",
|
|
209
|
+
),
|
|
210
|
+
tags=("vision-to-text", "ocr", "transcription", "ingestion"),
|
|
211
|
+
capability_interface=CapabilityInterface(
|
|
212
|
+
inputs={"image": "image"},
|
|
213
|
+
outputs={"text": "text"}, # standalone ingestion transcription for image-only sources
|
|
214
|
+
success_criterion="transcribe a scanned image to text at ingestion (image-only filings)",
|
|
215
|
+
),
|
|
216
|
+
),
|
|
217
|
+
CapabilityManifest(
|
|
218
|
+
slug="span_relevance_judgment",
|
|
219
|
+
kind="agent_skill", # a single grounded LLM relevance judgement; SKILL.md, applied via the seam (issue 0023)
|
|
220
|
+
display_name="Span relevance judgment (span x condition -> verdict; authored skill)",
|
|
221
|
+
description=(
|
|
222
|
+
"Decide whether ONE retrieved span (a clause's operative text) actually addresses ONE structured "
|
|
223
|
+
"condition being searched for (a clause type, optionally a value condition, with the question as "
|
|
224
|
+
"context) -- returning a VERDICT (relevant | not_relevant | uncertain), not a similarity score, so no "
|
|
225
|
+
"caller chooses a threshold (issue 0023, ADR-0088). The retrieval analog of the compliance judge and of "
|
|
226
|
+
"answer abstention. Applied by typed_property_retrieval (Leg B) over the returned spans; the applying "
|
|
227
|
+
"capability owns the verdict vocab + conservative default, this skill teaches only the reading."
|
|
228
|
+
),
|
|
229
|
+
representative_queries=(
|
|
230
|
+
"decide whether a retrieved clause actually addresses the searched condition",
|
|
231
|
+
"judge a span as relevant, not_relevant, or uncertain for a clause-type + value condition",
|
|
232
|
+
"return a relevance verdict for a retrieved span instead of a similarity score",
|
|
233
|
+
"filter retrieved spans by whether they truly address the query condition",
|
|
234
|
+
),
|
|
235
|
+
tags=("relevance", "judge", "retrieval", "verdict", "skill"),
|
|
236
|
+
),
|
|
237
|
+
CapabilityManifest(
|
|
238
|
+
slug="okf_navigate",
|
|
239
|
+
kind="agent_skill", # query-discovered traversal; SKILL.md, applied via the seam (FR-K.6, ADR-0022; T50)
|
|
240
|
+
display_name="OKF navigation (embedding-free progressive-disclosure traversal)",
|
|
241
|
+
description=(
|
|
242
|
+
"Find the concepts in an Open Knowledge Format (OKF) bundle that answer a question by progressive "
|
|
243
|
+
"disclosure rather than vector similarity (FR-K.6, experimental per ADR-0022): keep the bundle in "
|
|
244
|
+
"interpreter variables, read index signposts + frontmatter with tools, dispatch a selector sub-agent to "
|
|
245
|
+
"choose which signposts to explore, judge candidate bodies in parallel, and return the shortlist of "
|
|
246
|
+
"concept ids. The embedding-free complement to similarity retrieval."
|
|
247
|
+
),
|
|
248
|
+
representative_queries=(
|
|
249
|
+
"find the concepts in a knowledge bundle that answer a question without embeddings",
|
|
250
|
+
"navigate an OKF bundle by progressive disclosure to a shortlist of concept ids",
|
|
251
|
+
"traverse a markdown knowledge tree by reading signposts instead of vector similarity",
|
|
252
|
+
"return the concept ids relevant to a query from an OKF foundation bundle",
|
|
253
|
+
),
|
|
254
|
+
tags=("okf", "navigation", "embedding-free", "progressive-disclosure", "skill"),
|
|
255
|
+
),
|
|
256
|
+
# --- CAP-REG-3: the KG-primary retrieval core (packaged out of eval/kg_primary.py) ---
|
|
257
|
+
# (issue 0028 / ADR-0091: the KG-7 `party_clause_linking` manifest was retired with the PartyTo edge.)
|
|
258
|
+
CapabilityManifest(
|
|
259
|
+
slug="clause_exception_linking",
|
|
260
|
+
kind="function",
|
|
261
|
+
display_name="Clause exception linking (IsExceptionTo carve-out edges over the contract KG)",
|
|
262
|
+
description=(
|
|
263
|
+
"Add the missing cap<->carve-out relationship over the contract KG WITHOUT re-ingest (ADR-0044): a "
|
|
264
|
+
"pure pass over the already-populated clauses that writes IsExceptionTo edges (an Uncapped clause -> "
|
|
265
|
+
"the Cap clause it excepts). The signal is symbolic co-occurrence + POSITIONAL PROXIMITY (an Uncapped "
|
|
266
|
+
"clause whose operative span is within ~one section of a Cap clause is that cap's carve-out); distant "
|
|
267
|
+
"co-occurrence is NOT linked. The link is INFERRED (a reasoned inference, not extracted; surfaced at "
|
|
268
|
+
"query time and human-validatable, FR-S.4). Lets a query answer 'capped at X, except uncapped for "
|
|
269
|
+
"[carve-outs]' from structured evidence instead of two contradictory fragments."
|
|
270
|
+
),
|
|
271
|
+
representative_queries=(
|
|
272
|
+
"link an uncapped-liability carve-out to the cap clause it excepts",
|
|
273
|
+
"connect a contract's cap and its exceptions so a query sees the conditions",
|
|
274
|
+
"derive the cap-to-carve-out relationship over the clause KG",
|
|
275
|
+
),
|
|
276
|
+
tags=("graph", "linking", "carve-out", "neuro-symbolic", "inferred"),
|
|
277
|
+
),
|
|
278
|
+
# --- CAP-REG-2: the built contract-KG capabilities (capability_interface added when GraphWright-governed) ---
|
|
279
|
+
CapabilityManifest(
|
|
280
|
+
slug="typed_value_normalization",
|
|
281
|
+
kind="function",
|
|
282
|
+
display_name="Typed value normalization",
|
|
283
|
+
description=(
|
|
284
|
+
"Normalize a typed property value to its canonical form for matching (KG-5a): jurisdiction "
|
|
285
|
+
"canonicalization (England / England and Wales / English law -> england) and closed-value "
|
|
286
|
+
"subsumption rollup, so a query constraint matches equivalent or more-specific clause values."
|
|
287
|
+
),
|
|
288
|
+
representative_queries=(
|
|
289
|
+
"canonicalize a jurisdiction surface form to its canonical value",
|
|
290
|
+
"roll a more specific closed value up to the broader value it satisfies",
|
|
291
|
+
"normalize a typed property value for subsumption-aware matching",
|
|
292
|
+
),
|
|
293
|
+
tags=("normalization", "matching", "deterministic"),
|
|
294
|
+
),
|
|
295
|
+
CapabilityManifest(
|
|
296
|
+
slug="extraction_grounding_judge",
|
|
297
|
+
kind="function",
|
|
298
|
+
display_name="Extraction grounding judge",
|
|
299
|
+
description=(
|
|
300
|
+
"Deterministically gate an extracted typed record against its source text (ADR-0028): downgrade "
|
|
301
|
+
"an EXTRACTED value to AMBIGUOUS when its lexical cue is absent from the text. A quality gate on "
|
|
302
|
+
"the extraction subgraph and a permanent gate on the final graph; lexically-anchored dims only."
|
|
303
|
+
),
|
|
304
|
+
representative_queries=(
|
|
305
|
+
"flag an extracted property value whose cue is not in the source text",
|
|
306
|
+
"downgrade ungrounded EXTRACTED assertions to AMBIGUOUS",
|
|
307
|
+
"ground a typed clause record against its clause text",
|
|
308
|
+
),
|
|
309
|
+
tags=("grounding", "quality-gate", "deterministic"),
|
|
310
|
+
),
|
|
311
|
+
CapabilityManifest(
|
|
312
|
+
slug="extraction_semantic_judge",
|
|
313
|
+
kind="agent_skill", # a single grounded LLM verify-or-refute reading; SKILL.md, applied via the seam
|
|
314
|
+
display_name="Extraction semantic judge (clause property -> supported?; authored skill)",
|
|
315
|
+
description=(
|
|
316
|
+
"Layer 3 of the neuro-symbolic extraction-fidelity cascade (ADR-0040), authored as "
|
|
317
|
+
"skills/extraction_semantic_judge/SKILL.md: the verify-or-refute reading METHOD for the closed "
|
|
318
|
+
"SEMANTIC dimensions (mutuality, favorability, party_asymmetry, cap_basis, the consent regimes) that "
|
|
319
|
+
"carry no surface form -- what the lexical and symbolic gates cannot reach. Given one property "
|
|
320
|
+
"(dimension = value, with its meaning) and the clause text, returns whether a faithful reading of "
|
|
321
|
+
"THIS clause supports it (strict: mere plausibility is not support). Model-neutral through the seam "
|
|
322
|
+
"(product = self-hosted Granite, ADR-0039); ingestion-side only. The AMBIGUOUS downgrade and "
|
|
323
|
+
"dimension selection are the applying extraction_semantic_gate function's job, not the skill's."
|
|
324
|
+
),
|
|
325
|
+
representative_queries=(
|
|
326
|
+
"verify whether a clause supports an extracted mutuality reading",
|
|
327
|
+
"refute a semantic property that a faithful reading of the clause does not support",
|
|
328
|
+
"LLM-audit the closed semantic dimensions the deterministic gates cannot check",
|
|
329
|
+
),
|
|
330
|
+
tags=("grounding", "quality-gate", "semantic", "skill"),
|
|
331
|
+
),
|
|
332
|
+
CapabilityManifest(
|
|
333
|
+
slug="extraction_semantic_gate",
|
|
334
|
+
kind="function",
|
|
335
|
+
display_name="Extraction semantic gate (semantic-dimension AMBIGUOUS downgrade)",
|
|
336
|
+
description=(
|
|
337
|
+
"DETERMINISTIC gate (ADR-0040 Layer 3, SKILL-SPLIT): select the surviving (non-AMBIGUOUS) assertions "
|
|
338
|
+
"on a closed SEMANTIC dimension, apply the extraction_semantic_judge SKILL to each concurrently "
|
|
339
|
+
"(async + semaphore), and downgrade a refuted one to AMBIGUOUS (kept but flagged), exactly like "
|
|
340
|
+
"reground / symbolic_validate. A judge that fails or returns no ruling leaves the assertion "
|
|
341
|
+
"untouched (never downgrade on a judge error). No model of its own -- it composes the skill."
|
|
342
|
+
),
|
|
343
|
+
representative_queries=(
|
|
344
|
+
"downgrade refuted semantic-property readings on a clause to AMBIGUOUS",
|
|
345
|
+
"apply the semantic faithfulness judge across a clause's surviving assertions",
|
|
346
|
+
"run the ADR-0040 Layer-3 semantic quality gate over an extraction record",
|
|
347
|
+
),
|
|
348
|
+
tags=("grounding", "quality-gate", "semantic", "deterministic"),
|
|
349
|
+
),
|
|
350
|
+
CapabilityManifest(
|
|
351
|
+
slug="intra_document_scoped_query",
|
|
352
|
+
kind="function",
|
|
353
|
+
display_name="Intra-document scoped query",
|
|
354
|
+
description=(
|
|
355
|
+
"Answer scoped questions over ONE contract's typed KG (intra-contract): the clause index, the "
|
|
356
|
+
"clauses of a given function, and aggregation by property — each cited (clause_id + span_id + "
|
|
357
|
+
"confidence). The intra-contract serving capability over the typed KG."
|
|
358
|
+
),
|
|
359
|
+
representative_queries=(
|
|
360
|
+
"list every clause in this contract with its function and citation",
|
|
361
|
+
"return the clauses of a given function within one contract",
|
|
362
|
+
"aggregate a contract's clauses by a typed property",
|
|
363
|
+
),
|
|
364
|
+
tags=("serving", "intra-contract", "cited"),
|
|
365
|
+
),
|
|
366
|
+
CapabilityManifest(
|
|
367
|
+
slug="clause_disambiguation",
|
|
368
|
+
kind="function",
|
|
369
|
+
display_name="Clause disambiguation",
|
|
370
|
+
description=(
|
|
371
|
+
"Within one contract, select the specific clause matching a typed condition among several of the "
|
|
372
|
+
"same function (e.g. the mutual cap; the covenant-not-to-sue that is unbounded), by typed property "
|
|
373
|
+
"filter over the KG. Cited."
|
|
374
|
+
),
|
|
375
|
+
representative_queries=(
|
|
376
|
+
"find the mutual cap clause among several cap clauses in this contract",
|
|
377
|
+
"select the clause matching a typed condition among same-function clauses",
|
|
378
|
+
"disambiguate same-type clauses by a typed property",
|
|
379
|
+
),
|
|
380
|
+
tags=("serving", "disambiguation", "cited"),
|
|
381
|
+
),
|
|
382
|
+
CapabilityManifest(
|
|
383
|
+
slug="clause_function_classification",
|
|
384
|
+
impl_ref="rag_wright.spans.model_capabilities:clause_function_classification",
|
|
385
|
+
kind="model",
|
|
386
|
+
display_name="Clause function classification (LegalBERT)",
|
|
387
|
+
description=(
|
|
388
|
+
"Classify an operative span into its CUAD-type function label(s) with a fine-tuned LegalBERT "
|
|
389
|
+
"sequence classifier (T56); supports top-k for confusable-sibling routing. Model inference "
|
|
390
|
+
"(CPU/GPU)."
|
|
391
|
+
),
|
|
392
|
+
representative_queries=(
|
|
393
|
+
"classify a contract span into its CUAD function type",
|
|
394
|
+
"predict the top-k function labels for an operative span",
|
|
395
|
+
"route a span to its clause type with a fine-tuned classifier",
|
|
396
|
+
),
|
|
397
|
+
tags=("classification", "legalbert", "model"),
|
|
398
|
+
),
|
|
399
|
+
CapabilityManifest(
|
|
400
|
+
slug="jev_decision",
|
|
401
|
+
impl_ref="rag_wright.capabilities.jev_decision:jev_decision",
|
|
402
|
+
kind="model",
|
|
403
|
+
display_name="Jev typed-decision model (TypeSafe System-1, via OpenRouter)",
|
|
404
|
+
description=(
|
|
405
|
+
"A calibrated TYPED-DECISION model (ADR-0119): given a `state` and typed `questions` -- a yes/no "
|
|
406
|
+
"(`noul`), a `choice` from a set, or a `score` -- it returns calibrated typed answers with no text in "
|
|
407
|
+
"~70-500 ms. Used for the compliance closed-set decisions (operative-rule gate zero-shot ~0.92; "
|
|
408
|
+
"claim_types / actor few-shot ~0.85/0.90) and for any domain's routing / tagging / screening. "
|
|
409
|
+
"I/O-bound -> ASYNC: invoke via `ainvoke_model`. Laya is the open-weight / on-prem fallback."
|
|
410
|
+
),
|
|
411
|
+
representative_queries=(
|
|
412
|
+
"make a calibrated yes/no decision about a sentence",
|
|
413
|
+
"classify text into a closed set of options with probabilities",
|
|
414
|
+
"route or tag an input with a fast typed-decision model, no training",
|
|
415
|
+
),
|
|
416
|
+
tags=("decision", "jev", "typesafe", "model"),
|
|
417
|
+
),
|
|
418
|
+
CapabilityManifest(
|
|
419
|
+
slug="clause_property_classification",
|
|
420
|
+
impl_ref="rag_wright.spans.model_capabilities:clause_property_classification",
|
|
421
|
+
kind="model",
|
|
422
|
+
display_name="Clause property classification (29-dim fleet)",
|
|
423
|
+
description=(
|
|
424
|
+
"Classify a provision's closed-vocab property dimensions (cap basis, mutuality, IP ownership, dispute "
|
|
425
|
+
"method, royalty basis, ...) with the best-of-both Laya/SetFit fleet (ADR-0115/0116), soft-scoped to the "
|
|
426
|
+
"clause's likely functions; abstaining dims say 'not present'. Returns (dimension, value, confidence) "
|
|
427
|
+
"soft tags -- the classifier lane of Step-3a, no LLM. Model inference (CPU/GPU)."
|
|
428
|
+
),
|
|
429
|
+
representative_queries=(
|
|
430
|
+
"classify the closed-vocab property dimensions of a contract provision",
|
|
431
|
+
"tag a clause with its cap basis / mutuality / IP ownership values",
|
|
432
|
+
"get the soft property tags for a provision without an LLM call",
|
|
433
|
+
),
|
|
434
|
+
tags=("classification", "laya", "setfit", "model"),
|
|
435
|
+
),
|
|
436
|
+
CapabilityManifest(
|
|
437
|
+
slug="query_function_classification",
|
|
438
|
+
kind="agent_skill",
|
|
439
|
+
display_name="Query function classification",
|
|
440
|
+
description=(
|
|
441
|
+
"Classify a natural-language query into the closed FUNCTION taxonomy via a single "
|
|
442
|
+
"taxonomy-constrained structured LLM call, normalized to canonical labels at the boundary "
|
|
443
|
+
"(KG-5e). The in-distribution query-side counterpart to the clause classifier."
|
|
444
|
+
),
|
|
445
|
+
representative_queries=(
|
|
446
|
+
"map a query to the clause function(s) it is about, constrained to the taxonomy",
|
|
447
|
+
"classify an attorney's question into the closed function taxonomy",
|
|
448
|
+
"route a query to functions for candidate-pool selection",
|
|
449
|
+
),
|
|
450
|
+
tags=("classification", "query-side", "routing"),
|
|
451
|
+
),
|
|
452
|
+
# --- LG-1: hardened LangGraph subgraphs ---
|
|
453
|
+
CapabilityManifest(
|
|
454
|
+
slug="typed_clause_extraction",
|
|
455
|
+
kind="subgraph",
|
|
456
|
+
display_name="Typed clause extraction",
|
|
457
|
+
description=(
|
|
458
|
+
"Extract a clause's typed (dimension, value) property record from its text, hardened as a LangGraph "
|
|
459
|
+
"subgraph: docling-graph + granite extraction (retry on transient), adapt to the record, "
|
|
460
|
+
"grounding-judge gate (ADR-0028), a Flash->Pro escalation on low-confidence, an optional human gate, "
|
|
461
|
+
"and a dead-letter terminal so one bad clause never kills a batch."
|
|
462
|
+
),
|
|
463
|
+
representative_queries=(
|
|
464
|
+
"extract the typed property record for a contract clause",
|
|
465
|
+
"turn a clause's text into confidence-tagged (dimension, value) assertions",
|
|
466
|
+
"run schema-driven clause extraction with grounding and escalation",
|
|
467
|
+
),
|
|
468
|
+
tags=("extraction", "ingestion", "subgraph", "langgraph"),
|
|
469
|
+
),
|
|
470
|
+
CapabilityManifest(
|
|
471
|
+
slug="query_constraint_extraction",
|
|
472
|
+
kind="subgraph",
|
|
473
|
+
display_name="Query constraint extraction",
|
|
474
|
+
description=(
|
|
475
|
+
"Extract a query's typed (dimension, value) constraints with the SAME granite + clause_template "
|
|
476
|
+
"extractor used on clauses (KG-5b), hardened as a LangGraph subgraph with graceful degradation: a "
|
|
477
|
+
"failed extraction yields an empty constraint set (embedding-only fallback), so the query is never "
|
|
478
|
+
"dropped. No reground on queries (KG-5d: it false-flags real constraints)."
|
|
479
|
+
),
|
|
480
|
+
representative_queries=(
|
|
481
|
+
"extract the typed constraints a retrieval query is asking for",
|
|
482
|
+
"turn an attorney's query into (dimension, value) constraints for KG matching",
|
|
483
|
+
"parse a query into typed property constraints, same schema as the clauses",
|
|
484
|
+
),
|
|
485
|
+
tags=("extraction", "query-side", "subgraph", "langgraph"),
|
|
486
|
+
),
|
|
487
|
+
# --- LG-3: composite pipeline subgraphs ---
|
|
488
|
+
CapabilityManifest(
|
|
489
|
+
slug="relational_qa",
|
|
490
|
+
impl_ref="rag_wright.subgraphs.relational_qa:ainvoke",
|
|
491
|
+
kind="subgraph",
|
|
492
|
+
display_name="Relational QA (cited answer from graph traversal)",
|
|
493
|
+
description=(
|
|
494
|
+
"Answer a relational/multi-hop entity question with a grounded, cited answer, as a composite "
|
|
495
|
+
"LangGraph subgraph: traverse the knowledge graph (graph_query, FR-C.5) for cited evidence, "
|
|
496
|
+
"rehydrate the evidence chunk_ids to full text (chunk_read, T38), then generate a grounded, "
|
|
497
|
+
"abstaining, cited answer (generate_answer, FR-Q.6). Query-side hardening: a transient traversal "
|
|
498
|
+
"failure degrades to empty evidence (the generator abstains, the query survives); an orphaned "
|
|
499
|
+
"chunk_id dead-letters rather than fabricating. Confidence tags surface graph->evidence->answer."
|
|
500
|
+
),
|
|
501
|
+
representative_queries=(
|
|
502
|
+
"answer a relational question about an entity with a cited answer",
|
|
503
|
+
"who does this party contract with, and cite the clauses",
|
|
504
|
+
"traverse the graph from an entity and generate a grounded answer",
|
|
505
|
+
),
|
|
506
|
+
tags=("qa", "relational", "graph", "subgraph", "langgraph", "composite"),
|
|
507
|
+
),
|
|
508
|
+
CapabilityManifest(
|
|
509
|
+
slug="intra_document_qa",
|
|
510
|
+
impl_ref="rag_wright.subgraphs.intra_document_qa:ainvoke",
|
|
511
|
+
kind="subgraph",
|
|
512
|
+
display_name="Intra-document QA (cited answer scoped to one contract)",
|
|
513
|
+
description=(
|
|
514
|
+
"Answer a question scoped to ONE contract with a grounded, cited answer, as a composite LangGraph "
|
|
515
|
+
"subgraph: run the intra-contract scoped KG query (KG-4; classify the question to its clause "
|
|
516
|
+
"function(s) and serve those clauses with their typed properties, each cited), rehydrate each "
|
|
517
|
+
"clause's real operative-span text and append its typed facts as cited evidence (worst-case "
|
|
518
|
+
"confidence surfaced, FR-S.4), then generate a grounded, abstaining, cited answer (generate_answer, "
|
|
519
|
+
"FR-Q.6). Query-side hardening: a transient serve failure degrades to empty evidence (the generator "
|
|
520
|
+
"abstains, the query survives); an orphaned span_id dead-letters rather than fabricating."
|
|
521
|
+
),
|
|
522
|
+
representative_queries=(
|
|
523
|
+
"answer a question about a single contract with cited clauses",
|
|
524
|
+
"what does this contract say about the liability cap, with citations",
|
|
525
|
+
"disambiguate and answer over one contract's typed clause KG",
|
|
526
|
+
),
|
|
527
|
+
tags=("qa", "intra-document", "contract", "subgraph", "langgraph", "composite"),
|
|
528
|
+
),
|
|
529
|
+
# cross_corpus_retrieval RETIRED (standardized on typed_property_retrieval / Leg B, which uses the correct
|
|
530
|
+
# BGE+property pool via property_boosted_retrieval; cross_corpus's function-only pool was the inferior copy).
|
|
531
|
+
CapabilityManifest(
|
|
532
|
+
slug="typed_property_retrieval",
|
|
533
|
+
impl_ref="rag_wright.subgraphs.typed_property_retrieval:ainvoke",
|
|
534
|
+
kind="subgraph",
|
|
535
|
+
display_name="Typed property-boosted retrieval (Leg B)",
|
|
536
|
+
description=(
|
|
537
|
+
"The property-boosted Leg B as a composite LangGraph subgraph (LEGB-SUBGRAPH, ADR-0033): extract the "
|
|
538
|
+
"query's typed constraints and route its functions (granite + LegalBERT) in parallel, then run the "
|
|
539
|
+
"property_boosted_retrieval capability -- a bounded BGE base pool joined to each span's clause props "
|
|
540
|
+
"via the operative-span edge.span_id link, reranked by typed-constraint match (BGE tiebreak) -- and "
|
|
541
|
+
"emit top-k spans cited by span_id with the constraints each satisfied. Query-side hardening: a "
|
|
542
|
+
"transient failure degrades to empty, never a crash. Wraps the registered property_boosted_retrieval "
|
|
543
|
+
"function so the WORKFLOW is a registered subgraph, not an imperative script."
|
|
544
|
+
),
|
|
545
|
+
representative_queries=(
|
|
546
|
+
"retrieve clauses matching the query's typed constraints, ranked over a BGE pool, cited",
|
|
547
|
+
"property-boosted typed retrieval as a hardened LangGraph workflow",
|
|
548
|
+
"route + constrain + property-boost rerank the contract clause corpus",
|
|
549
|
+
),
|
|
550
|
+
tags=("retrieval", "typed", "ranking", "subgraph", "langgraph", "composite"),
|
|
551
|
+
),
|
|
552
|
+
CapabilityManifest(
|
|
553
|
+
slug="contract_ingestion_pipeline",
|
|
554
|
+
impl_ref="rag_wright.subgraphs.contract_ingestion_pipeline:ainvoke",
|
|
555
|
+
kind="subgraph",
|
|
556
|
+
display_name="Contract ingestion pipeline (corpus -> populated, connected KG)",
|
|
557
|
+
description=(
|
|
558
|
+
"Ingest a corpus of contracts into a populated, connected contract KG, as one GENERIC composite "
|
|
559
|
+
"LangGraph subgraph: per document, chunk (semantic_chunking) -> extract clauses "
|
|
560
|
+
"(typed_clause_extraction) and the party/relational graph (graph_extraction) in parallel -> resolve "
|
|
561
|
+
"entities (entity_resolution) -> write (typed clause KG + entity graph), with a per-document "
|
|
562
|
+
"dead-letter so one bad document never kills the ingest. Corpus-agnostic: a CorpusAdapter supplies the documents (parsing + "
|
|
563
|
+
"the one canonical source_doc_id + any corpus metadata), so adding a corpus is one adapter, never a "
|
|
564
|
+
"re-implemented ingest_xyz()."
|
|
565
|
+
),
|
|
566
|
+
representative_queries=(
|
|
567
|
+
"ingest a corpus of contracts into the knowledge graph",
|
|
568
|
+
"populate and connect the typed clause KG and party graph from source documents",
|
|
569
|
+
"run the generic contract ingestion pipeline over a new corpus adapter",
|
|
570
|
+
),
|
|
571
|
+
tags=("ingestion", "pipeline", "corpus", "subgraph", "langgraph", "composite"),
|
|
572
|
+
),
|
|
573
|
+
# --- Compliance module rung 1 (roadmap §13): the ad-compliance engine ---
|
|
574
|
+
CapabilityManifest(
|
|
575
|
+
slug="requirement_extraction",
|
|
576
|
+
kind="subgraph", # extract(docling-graph, multi-call auto/dense) -> adapt; a workflow, not a single act
|
|
577
|
+
display_name="Requirement extraction (regulatory section -> deontic rules; subgraph)",
|
|
578
|
+
description=(
|
|
579
|
+
"Extract the deontic rules a regulatory section states into typed Requirement nodes as a hardened "
|
|
580
|
+
"LangGraph subgraph (CC-2, compliance §13.1, SKILL-SPLIT): extract (the docling-graph extraction act "
|
|
581
|
+
"using the skills/requirement_extraction/ template, extraction_contract='auto' -> dense/multi-call "
|
|
582
|
+
"on long sections) -> adapt (requirement_adaptation). A subgraph because the extraction is "
|
|
583
|
+
"multi-LLM-call and the extract->adapt chaining is deterministic. A transient extraction failure "
|
|
584
|
+
"retries then dead-letters the section. The regulatory side of the compliance module's ingestion."
|
|
585
|
+
),
|
|
586
|
+
representative_queries=(
|
|
587
|
+
"extract the rules a regulation section states as typed requirements",
|
|
588
|
+
"turn FTC endorsement-guide text into cited deontic requirement nodes",
|
|
589
|
+
"parse a regulatory corpus into obligation/prohibition/permission rules",
|
|
590
|
+
),
|
|
591
|
+
tags=("compliance", "extraction", "deontic", "regulatory", "subgraph"),
|
|
592
|
+
),
|
|
593
|
+
CapabilityManifest(
|
|
594
|
+
slug="requirement_adaptation",
|
|
595
|
+
kind="function",
|
|
596
|
+
display_name="Requirement adaptation (extracted section -> validated Requirements)",
|
|
597
|
+
description=(
|
|
598
|
+
"DETERMINISTIC adaptation (CC-2, SKILL-SPLIT): map the requirement_extraction subgraph's raw "
|
|
599
|
+
"ExtractedRegulationSection to validated CC-1 Requirement nodes -- deontic force coerced to the "
|
|
600
|
+
"closed vocab (off-vocab -> AMBIGUOUS, kept not dropped), applicability_scope from the claim_types "
|
|
601
|
+
"(off-vocab dropped), citation = the section, content-hash requirement_id. No model."
|
|
602
|
+
),
|
|
603
|
+
representative_queries=(
|
|
604
|
+
"adapt an extracted regulation section into validated requirements",
|
|
605
|
+
"coerce extracted deontic force to the closed vocab with a conservative fallback",
|
|
606
|
+
"attach citations and ids to extracted regulatory rules",
|
|
607
|
+
),
|
|
608
|
+
tags=("compliance", "adaptation", "deontic", "deterministic"),
|
|
609
|
+
),
|
|
610
|
+
CapabilityManifest(
|
|
611
|
+
slug="claim_extraction",
|
|
612
|
+
kind="agent_skill", # a single docling-graph LLM extraction act, authored as skills/claim_extraction/
|
|
613
|
+
display_name="Claim extraction (subject ad -> checkable claims; authored skill)",
|
|
614
|
+
description=(
|
|
615
|
+
"The subject-document claim-extraction METHOD (CC-3, compliance §13.1), authored as an agent skill "
|
|
616
|
+
"(skills/claim_extraction/: SKILL.md + the template.py schema asset ExtractedAd/ExtractedClaim) and "
|
|
617
|
+
"applied through the docling-graph + model seam (Granite, ADR-0039): read an ad and pull out its "
|
|
618
|
+
"distinct CHECKABLE assertions, each with its kind, the disclosures present near it, and whether the "
|
|
619
|
+
"ad references evidence. One 'direct' call (ads are short). The deterministic mapping to the closed "
|
|
620
|
+
"Claim vocab is the claim_adaptation FUNCTION's job, not the skill's."
|
|
621
|
+
),
|
|
622
|
+
representative_queries=(
|
|
623
|
+
"extract the checkable claims an ad makes",
|
|
624
|
+
"turn a marketing campaign into claims with disclosures and evidence flags",
|
|
625
|
+
"identify the health/efficacy/endorsement claims in a subject document",
|
|
626
|
+
),
|
|
627
|
+
tags=("compliance", "extraction", "claims", "advertising", "skill"),
|
|
628
|
+
),
|
|
629
|
+
CapabilityManifest(
|
|
630
|
+
slug="claim_adaptation",
|
|
631
|
+
kind="function",
|
|
632
|
+
display_name="Claim adaptation (extracted ad -> validated Claims)",
|
|
633
|
+
description=(
|
|
634
|
+
"DETERMINISTIC adaptation (CC-3, SKILL-SPLIT): map the claim_extraction skill's raw ExtractedAd to "
|
|
635
|
+
"validated CC-1 Claim nodes -- claim_type coerced to the closed vocab (an off-vocab value kept but "
|
|
636
|
+
"flagged AMBIGUOUS, a checkable assertion is never dropped), disclosures/evidence/medium carried, "
|
|
637
|
+
"the content-hash claim_id + span provenance attached. No model."
|
|
638
|
+
),
|
|
639
|
+
representative_queries=(
|
|
640
|
+
"adapt an extracted ad into validated typed claims",
|
|
641
|
+
"coerce extracted claim types to the closed vocab with a conservative fallback",
|
|
642
|
+
"attach span provenance and ids to extracted ad claims",
|
|
643
|
+
),
|
|
644
|
+
tags=("compliance", "adaptation", "claims", "deterministic"),
|
|
645
|
+
),
|
|
646
|
+
CapabilityManifest(
|
|
647
|
+
slug="compliance_judgment",
|
|
648
|
+
kind="agent_skill", # a single grounded LLM judgment act, authored as skills/compliance_judgment/SKILL.md
|
|
649
|
+
display_name="Compliance judgment (claim x requirement -> verdict; authored skill)",
|
|
650
|
+
description=(
|
|
651
|
+
"The advertising-compliance judgment METHOD (CC-4, compliance §13.2), authored as an agent skill "
|
|
652
|
+
"(skills/compliance_judgment/SKILL.md) and applied through the model seam (Granite, ADR-0039): given "
|
|
653
|
+
"one claim + one requirement and ONLY the ad text, decide violation (clearly wrong from the text -- "
|
|
654
|
+
"overclaimed proof without a cited study, missing disclosure, fake review), needs_review (an "
|
|
655
|
+
"objective claim whose substantiation cannot be verified from the text -- escalate), or compliant "
|
|
656
|
+
"(puffery / disclosure present / evidence cited). Reserves violation for clear breaches and escalates "
|
|
657
|
+
"the unverifiable; never a silent pass. The deterministic vocab/citation is the "
|
|
658
|
+
"compliance_finding_assembly FUNCTION's job, not the skill's."
|
|
659
|
+
),
|
|
660
|
+
representative_queries=(
|
|
661
|
+
"judge whether an ad claim violates a regulatory requirement",
|
|
662
|
+
"decide compliant / violation / needs-review for a claim against a rule",
|
|
663
|
+
"audit a marketing claim against an FTC endorsement requirement",
|
|
664
|
+
),
|
|
665
|
+
tags=("compliance", "judgment", "verdict", "skill", "human-in-the-loop"),
|
|
666
|
+
),
|
|
667
|
+
CapabilityManifest(
|
|
668
|
+
slug="compliance_finding_assembly",
|
|
669
|
+
kind="function",
|
|
670
|
+
display_name="Compliance finding assembly (verdict + inputs -> cited finding)",
|
|
671
|
+
description=(
|
|
672
|
+
"DETERMINISTIC assembly (CC-4, SKILL-SPLIT): map the compliance_judgment skill's raw verdict string "
|
|
673
|
+
"to the closed Verdict vocab (an unreadable or missing verdict -> needs_review, the conservative "
|
|
674
|
+
"default), and attach the BOTH-SIDED citation (the exact claim span + the exact requirement clause) "
|
|
675
|
+
"FROM THE INPUTS -- the model never authors a citation -- returning a ComplianceFinding. No model: "
|
|
676
|
+
"the trust guarantees the LLM judgment must not own live here."
|
|
677
|
+
),
|
|
678
|
+
representative_queries=(
|
|
679
|
+
"assemble a cited compliance finding from a raw judgment verdict",
|
|
680
|
+
"map a verdict string to the closed vocab with a conservative default",
|
|
681
|
+
"attach both-sided citations to a compliance verdict from the inputs",
|
|
682
|
+
),
|
|
683
|
+
tags=("compliance", "assembly", "deterministic", "citation", "conservative-default"),
|
|
684
|
+
),
|
|
685
|
+
CapabilityManifest(
|
|
686
|
+
slug="compliance_ingestion",
|
|
687
|
+
kind="subgraph",
|
|
688
|
+
display_name="Compliance ingestion (regulatory corpus -> Requirement KG)",
|
|
689
|
+
description=(
|
|
690
|
+
"Ingest a regulatory corpus into a Requirement KG as a hardened LangGraph subgraph (CC-5, "
|
|
691
|
+
"compliance §13): per section, extract the deontic rules (requirement_extraction) and write them "
|
|
692
|
+
"as Requirement nodes, with a per-section retry -> dead-letter so one bad section never kills the "
|
|
693
|
+
"ingest. Reuses the generic corpus driver (SourceDocument + run_corpus_ingestion) via a thin "
|
|
694
|
+
"RegulationAdapter; the Requirement KG lives in its own database so the contract KG stays clean. "
|
|
695
|
+
"The regulatory-corpus side of the compliance module's ingestion."
|
|
696
|
+
),
|
|
697
|
+
representative_queries=(
|
|
698
|
+
"ingest a regulation into a requirement knowledge graph",
|
|
699
|
+
"load the FTC endorsement guides as typed deontic requirement nodes",
|
|
700
|
+
"build the requirements KG from a regulatory corpus",
|
|
701
|
+
),
|
|
702
|
+
tags=("compliance", "ingestion", "regulatory", "subgraph", "langgraph"),
|
|
703
|
+
impl_ref="rag_wright.subgraphs.compliance_ingestion:ainvoke", # EP-REF-1c: invocable via ainvoke_subgraph
|
|
704
|
+
),
|
|
705
|
+
CapabilityManifest(
|
|
706
|
+
slug="compliance_check",
|
|
707
|
+
kind="subgraph",
|
|
708
|
+
display_name="Compliance check (subject doc x requirements -> cited findings + gap matrix)",
|
|
709
|
+
description=(
|
|
710
|
+
"Check a subject advertisement against a regulatory Requirement KG as a hardened LangGraph subgraph "
|
|
711
|
+
"(CC-6, compliance §13.3, the headline composite): extract the ad's claims (claim_extraction) -> "
|
|
712
|
+
"retrieve the applicable requirements (claim scope <-> requirement applicability, with a "
|
|
713
|
+
"section->claim_type map backfilling empty scopes) -> judge each (claim, requirement) pair "
|
|
714
|
+
"(compliance_judgment, concurrent, with ad-level disclosure context) -> assemble cited findings + a "
|
|
715
|
+
"per-requirement gap matrix + a verdict summary. Query-side: degrades to empty on failure; every "
|
|
716
|
+
"violation/needs_review is human-gated. Both-sided cited -- the trust product."
|
|
717
|
+
),
|
|
718
|
+
representative_queries=(
|
|
719
|
+
"check whether an ad campaign complies with the FTC endorsement guides",
|
|
720
|
+
"produce a cited compliance gap matrix for a marketing document",
|
|
721
|
+
"audit a subject document against a regulatory requirements KG",
|
|
722
|
+
),
|
|
723
|
+
tags=("compliance", "check", "verdict", "gap-matrix", "subgraph", "langgraph"),
|
|
724
|
+
impl_ref="rag_wright.subgraphs.compliance_check:ainvoke", # EP-REF-1c: invocable via ainvoke_subgraph
|
|
725
|
+
),
|
|
726
|
+
CapabilityManifest(
|
|
727
|
+
slug="compliance_check_mcp",
|
|
728
|
+
kind="mcp_tool", # the discoverable MCP-tool surface of the compliance_check subgraph (MCP-PROTO)
|
|
729
|
+
display_name="Ad compliance check (MCP tool)",
|
|
730
|
+
description=(
|
|
731
|
+
"The compliance_check capability exposed as a single MCP tool (`check_ad_compliance`, served by "
|
|
732
|
+
"rag_wright.mcp.compliance_server via FastMCP): screen one advertisement against the FTC 16 CFR 255 "
|
|
733
|
+
"endorsement rules and return a cited ComplianceReport (ad-level verdict, per-claim findings with "
|
|
734
|
+
"both-sided citations, verdict summary, per-requirement gap matrix). An external agent discovers "
|
|
735
|
+
"this via ARD search and calls it as ONE tool -- saving context tokens and inter-agent coordination "
|
|
736
|
+
"vs. embedding the compliance_check subgraph. Same output contract as the subgraph; distinct ARD "
|
|
737
|
+
"identity because the callable surface is a deployed MCP server, not an in-process graph node."
|
|
738
|
+
),
|
|
739
|
+
representative_queries=(
|
|
740
|
+
"check whether an advertisement complies with the FTC endorsement rules",
|
|
741
|
+
"screen ad copy for unsubstantiated claims and missing disclosures",
|
|
742
|
+
"get a cited compliance report for a marketing claim as a tool call",
|
|
743
|
+
),
|
|
744
|
+
tags=("compliance", "mcp-tool", "ad-screening", "cited", "discoverable"),
|
|
745
|
+
),
|
|
746
|
+
CapabilityManifest(
|
|
747
|
+
slug="intra_document_qa_mcp",
|
|
748
|
+
kind="mcp_tool", # the discoverable MCP-tool surface of the intra_document_qa subgraph (MCP-PROTO B1)
|
|
749
|
+
display_name="Intra-document contract QA (MCP tool)",
|
|
750
|
+
description=(
|
|
751
|
+
"The intra_document_qa capability exposed as a single MCP tool (`answer_contract_question`, served "
|
|
752
|
+
"by rag_wright.mcp.intra_document_qa_server via FastMCP): answer a natural-language question about "
|
|
753
|
+
"ONE known contract from its clause knowledge graph and return a cited GeneratedAnswer (grounded "
|
|
754
|
+
"answer, chunk_id citations, abstained flag). An external agent discovers this via ARD search and "
|
|
755
|
+
"calls it as ONE tool -- saving context tokens and inter-agent coordination vs. embedding the "
|
|
756
|
+
"intra_document_qa subgraph. Same output contract as the subgraph; distinct ARD identity because the "
|
|
757
|
+
"callable surface is a deployed MCP server, not an in-process graph node."
|
|
758
|
+
),
|
|
759
|
+
representative_queries=(
|
|
760
|
+
"answer a question about a known contract with cited clauses as a tool call",
|
|
761
|
+
"what does this contract say about the liability cap, with citations",
|
|
762
|
+
"get a cited answer for one contract's terms over MCP",
|
|
763
|
+
),
|
|
764
|
+
tags=("qa", "intra-document", "contract", "mcp-tool", "cited", "discoverable"),
|
|
765
|
+
),
|
|
766
|
+
CapabilityManifest(
|
|
767
|
+
slug="relational_qa_mcp",
|
|
768
|
+
kind="mcp_tool", # the discoverable MCP-tool surface of the relational_qa subgraph (MCP-PROTO B2)
|
|
769
|
+
display_name="Relational contract QA (MCP tool)",
|
|
770
|
+
description=(
|
|
771
|
+
"The relational_qa capability exposed as a single MCP tool (`answer_relational_question`, served by "
|
|
772
|
+
"rag_wright.mcp.relational_qa_server via FastMCP): answer a relational question about a known entity "
|
|
773
|
+
"by traversing the contract entity graph and return a cited GeneratedAnswer whose facts are cited by "
|
|
774
|
+
"their SOURCE CONTRACT (graph-structural evidence, no chunk text). An external agent discovers this "
|
|
775
|
+
"via ARD search and calls it as ONE tool -- saving context tokens and inter-agent coordination vs. "
|
|
776
|
+
"embedding the relational_qa subgraph. Same output contract as the subgraph; distinct ARD identity "
|
|
777
|
+
"because the callable surface is a deployed MCP server, not an in-process graph node."
|
|
778
|
+
),
|
|
779
|
+
representative_queries=(
|
|
780
|
+
"which parties does this company contract with, as a tool call",
|
|
781
|
+
"traverse the entity graph for a company's contracting relationships with citations",
|
|
782
|
+
"get a cited relational answer over MCP from a start entity",
|
|
783
|
+
),
|
|
784
|
+
tags=("qa", "relational", "entity-graph", "mcp-tool", "cited", "discoverable"),
|
|
785
|
+
),
|
|
786
|
+
CapabilityManifest(
|
|
787
|
+
slug="typed_property_retrieval_mcp",
|
|
788
|
+
kind="mcp_tool", # the discoverable MCP-tool surface of the typed_property_retrieval subgraph (MCP-PROTO B3)
|
|
789
|
+
display_name="Typed property-boosted retrieval (MCP tool)",
|
|
790
|
+
description=(
|
|
791
|
+
"The typed_property_retrieval capability (Leg B) exposed as a single MCP tool "
|
|
792
|
+
"(`retrieve_typed_property_spans`, served by rag_wright.mcp.typed_property_retrieval_server via "
|
|
793
|
+
"FastMCP): retrieve the most relevant contract clauses for a query from across the corpus, "
|
|
794
|
+
"property-boosted and cited, returning a TypedPropertyRetrieval (the query + ranked spans each with "
|
|
795
|
+
"its span_id citation, text, function, match score, and satisfied constraints). Corpus-wide "
|
|
796
|
+
"RETRIEVAL (ranked evidence), NOT a written answer -- distinct from the intra_document_qa / "
|
|
797
|
+
"relational_qa answer tools. An external agent discovers this via ARD search and calls it as ONE "
|
|
798
|
+
"tool vs. embedding the subgraph. Same output contract as the subgraph; distinct ARD identity "
|
|
799
|
+
"because the callable surface is a deployed MCP server, not an in-process graph node."
|
|
800
|
+
),
|
|
801
|
+
representative_queries=(
|
|
802
|
+
"find clauses across the corpus that cap liability at a multiple of the fees paid",
|
|
803
|
+
"retrieve ranked cited clauses matching a typed condition as a tool call",
|
|
804
|
+
"corpus-wide property-boosted clause search over MCP",
|
|
805
|
+
),
|
|
806
|
+
tags=("retrieval", "typed-property", "leg-b", "mcp-tool", "cited", "ranked", "discoverable"),
|
|
807
|
+
),
|
|
808
|
+
)
|
|
809
|
+
|
|
810
|
+
# EP-CORE-3 (ADR-0118): the engine ships an EMPTY ARD catalog. `MANIFEST_SPECS` is the runtime registry the
|
|
811
|
+
# DEVELOPER populates with their product's capabilities (via `register_capability`); the invoker + `capability_impl`
|
|
812
|
+
# read it live. The committed `_SPECS` above is the ENGINE's REFERENCE PACK (the contract/compliance worked example,
|
|
813
|
+
# kept in the engine repo per ADR-0052) -- it is OPT-IN, registered only by an explicit `load_reference_pack()`.
|
|
814
|
+
MANIFEST_SPECS: dict[str, CapabilityManifest] = {}
|
|
815
|
+
|
|
816
|
+
|
|
817
|
+
def register_capability(manifest: CapabilityManifest) -> None:
|
|
818
|
+
"""Register (or replace) one capability in the runtime ARD catalog. A product calls this for each of its
|
|
819
|
+
domain capabilities (with an `impl_ref`); the invoker then resolves it by name with zero engine edits."""
|
|
820
|
+
MANIFEST_SPECS[manifest.slug] = manifest
|
|
821
|
+
|
|
822
|
+
|
|
823
|
+
def reference_pack() -> tuple[CapabilityManifest, ...]:
|
|
824
|
+
"""The engine's committed REFERENCE PACK manifests (the contract/compliance worked example). Opt-in."""
|
|
825
|
+
return _SPECS
|
|
826
|
+
|
|
827
|
+
|
|
828
|
+
def load_reference_pack() -> None:
|
|
829
|
+
"""Register the engine's reference pack into the runtime catalog -- the opt-in worked example (the engine's own
|
|
830
|
+
test suite loads it; a downstream product does NOT, registering its own capabilities instead)."""
|
|
831
|
+
for manifest in _SPECS:
|
|
832
|
+
register_capability(manifest)
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
def author(slug: str) -> RegistryEntry:
|
|
836
|
+
"""Author a capability's committed spec into a complete, validated `RegistryEntry`."""
|
|
837
|
+
if slug not in MANIFEST_SPECS:
|
|
838
|
+
raise KeyError(f"no ARD manifest spec for {slug!r}; add one in capabilities/manifests.py")
|
|
839
|
+
spec = MANIFEST_SPECS[slug]
|
|
840
|
+
if slug not in CANONICAL_CAPABILITY_SLUGS:
|
|
841
|
+
raise ValueError(f"{slug!r} is not a canonical capability slug (SPEC.md section 5)")
|
|
842
|
+
|
|
843
|
+
# callable kinds must declare response bounds; agent_skill is loaded, not called (carries none).
|
|
844
|
+
bounds = (spec.response_bounds or ResponseBounds()) if spec.kind in CALLABLE_KINDS else None
|
|
845
|
+
|
|
846
|
+
skeleton = ManifestSkeleton(
|
|
847
|
+
name=spec.slug,
|
|
848
|
+
kind=spec.kind,
|
|
849
|
+
identifier=capability_urn(spec.slug),
|
|
850
|
+
media_type=MEDIA_TYPE_BY_KIND[spec.kind],
|
|
851
|
+
display_name=spec.display_name,
|
|
852
|
+
response_bounds=bounds,
|
|
853
|
+
description=spec.description,
|
|
854
|
+
tags=list(spec.tags),
|
|
855
|
+
)
|
|
856
|
+
return skeleton.author(
|
|
857
|
+
list(spec.representative_queries),
|
|
858
|
+
requires=list(spec.requires) or None,
|
|
859
|
+
skill_runtime=spec.skill_runtime,
|
|
860
|
+
capability_interface=spec.capability_interface,
|
|
861
|
+
golden_eval_ref=spec.golden_eval_ref,
|
|
862
|
+
)
|
|
863
|
+
|
|
864
|
+
|
|
865
|
+
def publish(slug: str, *, root: Optional[Path] = None) -> Path:
|
|
866
|
+
"""Author `slug` and write its manifest to `<root>/<slug>.json` (default: the shared root)."""
|
|
867
|
+
return write_manifest(author(slug), root=root)
|
|
868
|
+
|
|
869
|
+
|
|
870
|
+
def publish_all(*, root: Optional[Path] = None) -> list[Path]:
|
|
871
|
+
"""Author and write every specified manifest into the root. Returns the written paths."""
|
|
872
|
+
return [publish(slug, root=root) for slug in MANIFEST_SPECS]
|