Metadata-Version: 2.5
Name: matrx-mandate-scan
Version: 0.1.3
Summary: The one Mandate reference scanner: finds every mandate carrier, every bypass, and reports contract-v1 JSON to the platform
Project-URL: Homepage, https://github.com/AI-Matrix-Engine/aidream
Project-URL: Repository, https://github.com/AI-Matrix-Engine/aidream
Project-URL: Issues, https://github.com/AI-Matrix-Engine/aidream/issues
Author-email: Matrx <admin@aimatrx.com>
Maintainer-email: Matrx <admin@aimatrx.com>
License: MIT
Keywords: governance,mandates,matrx,static-analysis
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.13
Requires-Dist: pyyaml>=6.0.3
Provides-Extra: submit
Requires-Dist: asyncpg>=0.31.0; extra == 'submit'
Description-Content-Type: text/markdown

# matrx-mandate-scan

The ONE Mandate reference scanner. It finds every place code reaches for
platform intelligence — through a Mandate carrier or around it — reports the
result to the database in one frozen contract, and screams (never blocks) when
something is unresolved, unmeasured, or bypassing the mandate system.

Built for the **Mandate Declaration & Usage Reporting** program
(`common-docs/projects/mandate-declaration-reporting/`), lane L2.

## Install / run

```bash
# from any repo, no checkout needed
uvx --from matrx-mandate-scan==0.1.0 matrx-mandate-scan check

# inside the aidream workspace (vendored via [tool.uv.sources])
uv run matrx-mandate-scan scan --root aidream --root packages/matrx-ai
```

## Commands

| Command | What it does |
|---|---|
| `scan` | Contract-v1 JSON on **stdout**, the red human report on **stderr**. |
| `report` | `scan`, then submit through `mandate.submit_scan_report(jsonb)` and file every red finding into `ops.system_error` (`source_app='mandate-scan'`). |
| `check` | The release-path command: scan + report + reconcile. |
| `explain <file:line>` | What the scanner sees at one location, and why. |
| `--self-test` | The built-in RED→GREEN fixture suite. Runs from a `uvx` install. |

**Every command exits 0** unless `--strict` is passed. That is ruling **D23**:
a mandate check is loud and non-blocking; `--strict` exists for humans and for
the scheduled remediation task, never for a release script.

## What counts as a reference

Classification is **by carrier, never by the word or the path**. A dotted
string is a mandate key only where a carrier puts it — so `consumerId =
"extend.chat"` is not a reference and never becomes one.

Python carriers:

- `declare_mandate` / `declare_generated_mandate` / `declare_mandated_agent` → `declaration`
- `declare_mandate_family(prefix, members=...)` → `family_declaration`, one `constant` per resolvable member, `dynamic_family` when the iterable is computed
- `resolve_mandate` → `resolution`; `run_mandate` → `execution`
- `run_mandated(Cls)` / `Cls.run()` → `execution`
- a `NamedAgent` subclass `mandate_key` (including `type(name, (NamedAgent,), {...})`) → `declaration`
- `seed_agent_id=<uuid>` inside a `declare_*` → `seed_holder`
- `@mandate_passthrough` / `MandateKeyParam` → `passthrough`, with the caller attributed when it lives in the same module

Config carriers (JSON / YAML / TOML) — the **property name** is the carrier:
`mandate_key`, `mandateKey`, `defaultMandateKey`, `fallback_mandate_key`.
Anything else that merely looks key-shaped is `unclassified` and advisory.

Keys resolve through literals, module and function constants (UPPER or not),
attribute constants, f-strings, `+` concatenations, ternaries (both branches
become real references), tuple/list loop members, aliases, literal-container
subscripts, and one level of analyzable module-local wrapper function.

An argument that resolves to none of those → finding **`UNRESOLVED_KEY`**, plus
an `unresolved`-flagged reference: D21 says unreachable is a flag, never a
filter, so nothing is ever dropped from the inventory.

## Bypass detection and the ratchet

Importing a provider SDK (`anthropic`, `openai`, `groq`, `google.genai`,
`google.generativeai`, `litellm`, `xai`, `ollama`, `cohere`, `mistralai`) or
naming a provider host, anywhere outside
`packages/matrx-ai/matrx_ai/providers/**` and the one D10-approved module
(`conversation_labeler.py`), is a `bypass` reference. The exact standalone
RAG default embedding adapter (`packages/matrx-rag/matrx_rag/embeddings.py`) is
also an approved provider adapter: it is injected through `EmbeddingProvider`,
does not select a Mandate holder, and is independently ratcheted by
`scripts/check_raw_llm_clients.py`. No broader `matrx-rag` exemption exists.

- in the `--baseline` file → **`CONVERSION_PENDING`** (flag `conversion_pending`)
- not in it → **`NEW_BYPASS`** (D20: no new ones)
- a dynamic import that hides its target → **`UNRESOLVED_IMPORT`**

`--write-baseline` regenerates the file and **refuses to write a larger one**.
No entry in the baseline is an approved class; every one is a defect awaiting
conversion.

## Coverage is mandatory output

Every file is scanned or listed with a reason (`generated`, `test_fixture`,
`parse_error`, `unsupported_language`). Any `parse_error` makes the package
`verification_status = incomplete` and files an `UNMEASURED` finding.

## Reference identity

`sha256(repo_slug · package_path · file_path · symbol · occurrence_n ·
reference_type · mandate_key_or_prefix)`.

`repo_slug` is always the repo the scan ran in, resolved from
`git remote get-url origin` through the `platform.repo` mirror in
`matrx_mandate_scan/repo.py`. **An unknown remote is `UNMEASURED`, never a
guessed slug** — a folder name is not a repo identity.

## Boundaries

Per `docs/packages/PACKAGE_DOCTRINE.md`, this package imports **neither
`aidream` nor `matrx-orm`**. It carries the AST walkers that used to live in
`scripts/audit_mandate_wiring.py` and
`aidream/services/mandates/code_truth.py`; those two modules now import them
from here, so there is exactly one definition of "what a carrier looks like".
