Skip to content

Contract descriptions and LinkML

Verified approval requests show the library title (and declared Mock/Mixed badge), a library-qualified call with named arguments, and a deterministic sentence. The fully resolved Python symbol is visible beneath the sentence. For example, an agent's rules.only_reads_files([clauz3.FilePath("test.md")]) displays filesystem.only_reads_files(files=[clauz3.FilePath('test.md')]), followed by:

Filesystem tools read only the exact files ["test.md"]; directory listings and copy or move sources are forbidden.

The visible symbol is tools.filesystem.trusted.contracts.only_reads_files. Source and documentation is an expandable section containing the original expression, source file and line, captured function source, source and selected layer fingerprints, recorded library origin/revision, and full docstring. Titles, origins, and mock badges are library declarations; the SHA-256 fingerprints identify the selected source. A mock badge does not enforce isolation.

For a directory boundary use rules.only_reads_files_under(clauz3.DirectoryPath("data")). The legacy only_read_under("test.md") still permits test.md.bak. Descriptions name the specific effects they constrain; the coverage panel continues to show which other effects have guarantees.

Define a trusted description

The existing @contract form still works. A trusted library can opt in with a description argument:

@contract(description="Every filesystem.read_file or filesystem.read_lines path must start with {root}.")
def only_read_under(root: str) -> ContractSpec:
    """Require every read_file path to start with root.

    This is a literal prefix check, not resolved directory containment.
    """
    return Read.all(lambda e: e.path.startswith(root))

Templates are reviewed library metadata. They are not inferred from function names, generated by a language model, or accepted from the submitting agent. Python still defines the executable contract semantics. Changing a template changes trusted source identity, so remembered approvals cannot silently match a modified library.

The first renderer supports parameters annotated as str, int, float, or bool, FilePath, DirectoryPath, or a list of one of these (list[FilePath]), including ordinary postponed annotations. Typed paths render as quoted path strings while their signature and exported LinkML ranges retain the file/directory distinction. A list renders as a JSON array. Every parameter must appear in the template. Variadic parameters and other composite types are unsupported. Existing contracts without a description can continue using any parameter types supported by the prover.

Only {parameter} substitutions are allowed. Attribute/index access, conversions, and format specifications are rejected. Positional and keyword arguments are bound to the selected function's signature and its defaults. The renderer requires the declared scalar type, quotes strings as JSON, and escapes control characters. It does not execute the function body. HTML escaping happens separately in the UI.

Invalid template definitions fail when the trusted library loads. If a sentence cannot be generated (for example, an unsupported literal value or missing template), the first paragraph of the verified docstring appears instead. The resolved identity does not depend on a description template. Full docstrings, including scope limitations, remain under Source and documentation. The renderer never guesses a stronger guarantee or interpolates docstring text.

Where descriptions come from

These descriptions have different sources and audiences:

Display Source
Library summary in the Libraries view and clauz3 libraries The installed library's summary in tools/<domain>/clauz3.yaml
Library setup in the Libraries view and generated skills Domain manifest requirements combined with the generated .clauz3-package.yaml snapshot, when present
Sentence beneath an approval's Python contract The trusted helper's @contract(description="...") template, filled with its literal arguments; otherwise the first docstring paragraph
Expanded contract scope in an approval The trusted contract function's Python docstring
Effect and contract documentation returned by the tools tool Function signatures and docstrings, read from the selected trusted source
API summaries in generated library skills The first line of each function's docstring, captured by clauz3 install --skills

Library descriptions and setup requirements live in the library's own manifest, alongside its code. The central library_registry.yaml lists only source locations. Bundled and installed manifests are read locally; external metadata is cached during explicit installation or review. No README or module docstring is used to guess a library summary.

The optional source-root package manifest owns shared requirements only; it does not override domain descriptions. Legacy sources without manifests install with a metadata warning; missing descriptions do not prevent effect/contract docstrings from being displayed. See the manifest reference for validation rules.

Write a concise first line and fuller scope documentation in each public effect and contract docstring. After changing a library, reinstall its source with --force --skills to refresh the project's copied code and generated skill. Existing approval history retains its original metadata snapshots.

Verification and history

The approval service obtains identity and descriptions during independent verification, using the same selected contract registrations as the prover. Two libraries with identical qualified Python names retain their own metadata. Agent-supplied contract_identities, contract_descriptions, and contract_documentation are ignored. Identity binds arguments to the registered signature, expands defaults and imported argument aliases, and records the defining Python symbol and source fingerprints. It does not execute a helper body to produce a display label.

Each generated description saves its exact text, canonical Python symbol, bound parameters, template digest, and renderer version. These snapshots are preserved in history and remembered rules. Documentation changes do not rewrite old decisions. Identity snapshots likewise retain the code and metadata that were reviewed, even after installation changes. Records without identity snapshots retain their original expression and explicitly say Resolved identity not recorded; the service does not reinterpret them against today's libraries. Failed verification and manual services without an operator-authorized layer cannot provide verified identity. With an authorized layer, manual requests can display verified identity even when their arguments (such as Row classes) are ineligible for remembered approval rules.

Descriptions explain the displayed formal contract. They do not broaden profile matching or replace the program/guarantee/coverage binding in execution receipts. Exact source spellings can still produce different profile signatures even when their generated sentences are equal.

Generate the LinkML catalog

Every stdlib:filesystem contract has a template. Their signatures, docstrings, and templates, plus the effect signatures, generate the LinkML catalog:

just contract-schema

The exporter reads Python AST without importing or executing library code. Every exported contract and effect, even one without a description, must use those parameter types; a list becomes a multivalued slot. Unsupported signatures stop catalog generation with the Python symbol in the error; other composite parameters in a cataloged library need an exporter extension. This build-time constraint does not restrict the types of undescribed contracts in other trusted libraries.

The catalog uses JSON serialization of a LinkML schema, so generation needs only clauz3's existing environment. just check verifies that the checked-in catalog matches the current source. It includes:

  • A class for each contract and effect, with typed parameter slots.
  • Qualified class URIs and Python symbol annotations.
  • Trusted source digests, documentation, and CNL templates.
  • Parameter kind/default annotations. Runtime defaults remain the Python signature's responsibility; python_default is descriptive metadata.

Source files and catalog JSON use UTF-8. Source digests hash the original file bytes, including line endings.

The qualified class URI identifies a vocabulary term. Trusted source digests distinguish different library implementations of that term. These schema URIs are versioned identifiers; they are not a claim that every URI is a published ontology landing page.

To exercise LinkML itself and export OWL, SHACL, and JSON Schema:

uv run --no-project --with linkml==1.12.0 python \
  docs/prototypes/contract-linkml/demo.py --output /tmp/clauz3-contract-linkml

LinkML and its transitive dependencies are isolated tooling, not runtime or development dependencies of clauz3. This command validates sample contract instances and exports their shapes. It does not prove programs or translate the Python contract bodies into OWL restrictions. See the design exploration for the proposed shared contract algebra and the limits of semantic exports.