Skip to content
This repository was archived by the owner on Jul 29, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .agents/skills/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Installed skills:
- `meta-module-build/` — metadata-first module scaffolding
- `new-retain-old/` — safe replacement workflow that preserves the old implementation while creating a new active path
- `manifest/` — living-spec generator for `CLAUDE.md` (vendored from
`The-Interdependency/skill-lib@d0f6209`). Generates the mechanical facts
`The-Interdependency/skill-lib@6f36340`). Generates the mechanical facts
block in `CLAUDE.md` from `backend/pyproject.toml` + the tree; the
`manifest drift check` workflow runs `generate.py --check` in CI. Refresh with
`python .agents/skills/manifest/generate.py --pyproject backend/pyproject.toml --write`.
Expand Down
139 changes: 139 additions & 0 deletions .agents/skills/doctrine/msdmd-checks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# msdmd doctrine: CONTRACTS / CHECKS / audit

Status: ratified for skill-lib. Reference implementation:
`skill_lib/safety/repo_loto.py` + `tests/test_repo_loto.py`.

## The triad

```
CONTRACTS are obligations.
CHECKS are accountable witnesses.
audit reconciles the witness list against the obligation list.
```

Source modules own promises. Test modules own evidence. Neither owns
the other's declarations.

## Ownership

**CONTRACTS live in the source module.** A contract is a normative
claim: what must remain true of this module's behavior. It belongs to
the module doing the promising, never to the file checking it.

**CHECKS live in the test module.** A check is an evidentiary
procedure: an executable claim to prove a named contract. Test
topology is the test module's business; source modules do not carry
`call:` fields. There is no legacy bridge in skill-lib — new code
adopts this split directly.

## Grammar

Blocks are comment-fenced, one entry per `id:`, fields indented
beneath it:

```python
# === CONTRACTS ===
# id: loto_scope_enforced
# given: files touched outside the declared --files globs
# then: close refuses with the violating paths named
# class: safety
# === END CONTRACTS ===
```

```python
# === CHECKS ===
# id: check_scope_enforced
# proves: loto_scope_enforced
# call: self::test_scope_enforced
# requires: git, python3, posix_shell
# timeout: 20
# mutates: filesystem
# cleanup: tempdir_teardown
# === END CHECKS ===
```

CONTRACTS fields: `id`, `given`, `then`, `class`
(doctrine | evidence | safety | security).

CHECKS fields, all consumed: `id`, `proves`, `call`, `requires`
(runner refuses to execute on hosts missing them), `timeout` (runner
sets the active subprocess bound per check), `mutates` and `cleanup`
(danger documentation read by humans deciding when a check may run).
Comment on lines +58 to +61

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Separate human-only fields from consumed CHECKS fields

These lines say all CHECKS fields are consumed, but the same sentence defines mutates and cleanup as danger documentation read by humans, while the field-entry rule below treats declared-but-unread metadata as a defect. A runner author following this doctrine either has to invent machine behavior for those human-only fields or reject the required examples as decorative, so the schema should not list them under “all consumed” unless a runner actually consumes them.

Useful? React with 👍 / 👎.


## The field-entry rule

A field enters the schema in the same change that makes a runner
consume it, not before. Declared-but-unread metadata is F6 —
decorative preservation — and is treated as a defect, not diligence.
(`determinism` and `level` are currently out for exactly this reason;
they enter when a runner mode reads them. Note that `determinism` is
self-reported until a runner measures it by repeated execution.)

## call: resolution

The only sanctioned form is `self::fn` — a callable defined in the
file that declares the check. Dotted import paths are refused by the
audit: Python imports execute module top level, and **an audit that
executes is not an audit**. The `self::` form is also rename-immune;
copies and uploads reconcile identically.

## audit

The cheapest runner mode and the first one built: no execution, pure
reconciliation of the declared graph. It must report, at minimum:

```
GAP <contract> has no CHECKS entry claiming to prove it
GAP <check> claims unknown contract: <id>
GAP <check> call does not resolve: <reason>
GAP executable check <fn> has no resolving CHECKS declaration
```

Exit nonzero on any gap. A reconciler that has only ever said
"closed" is itself unverified: every audit implementation must be
negative-tested by planting an orphan contract, a phantom `proves`
target, and an unresolvable call, and observing the GAP.

## Semantics of "proves"

`proves:` means *claims to prove*. The audit verifies linkage and
resolution, not that the check exercises the contract. The rung above
— break the module, confirm the witness notices (mutation-level
verification) — is named here so its absence stays visible. A module
is `[test-backed]` when its suite passes and its graph closes; it is
not thereby mutation-verified.

## Evidence discipline

- **Latest run wins, per identical command.** A rerun supersedes its
predecessor as standing evidence; history persists in working
memory until distillation. Superseding is by exact command string —
a passing narrow rerun does not launder a failing broad one.
- **Skipped or flaky checks are non-proof** unless explicitly waived,
and waivers ride the record; they do not erase it.
- **Execution semantics are evidence.** Records carry `shell:`,
exit codes, and timestamps, not just command strings.
- **Harness errors are results.** The runner reports TimeoutExpired,
CalledProcessError, and resolver failures as `ERROR` per check and
continues; an aborted run is not evidence about the unrun checks.
- **Subprocesses are bounded and owned.** Every spawned process runs
in its own session with a metadata-driven timeout; on expiry the
whole process group is killed. A hung witness is dismissed, on the
record, not waited on.

## Status vocabulary

```
[implemented-prototype] runs; verified by session contact only
[test-backed] suite passes and audit closes the graph
[mutation-verified] checks demonstrated to notice planted breakage
```

Each term is earned, never assumed, and never claimed one rung above
its evidence.

hmmm: the block-type for harness/infrastructure tests that prove no
contract remains unnamed; mutation-level verification is defined but
unbuilt; the audit grammar is currently specified by its reference
parser rather than by this document, and if a second parser disagrees,
one of them yields here, in writing.
89 changes: 57 additions & 32 deletions .agents/skills/msdmd/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
---
name: msdmd
description: Module Self-Declared Metadata in Markdown — the foundational convention where each source module declares its own structured metadata in a fenced comment block. Other skills in this lib (doc-build, cap-build, deps-build, owner-build, test-build, meta-module-build, risk-boundary-build, ratios, etc.) are thin applications on top of this convention. Load this when authoring a new metadata-driven skill, when extending the block schema, or when building a parser/executor for a new application.
description: Module Self-Declared Metadata in Markdown — the foundational convention where each module declares its own structured metadata in a fenced comment block. Other skills in this lib (doc-build, cap-build, deps-build, owner-build, test-build, meta-module-build, risk-boundary-build, ratios, etc.) are thin applications on top of this convention. Load this when authoring a new metadata-driven skill, when extending the block schema, or when building a parser/executor for a new application.
---

# msdmd — Module Self-Declared Metadata in Markdown

## The doctrine

Every cross-cutting fact a module owns — its test contracts, its public
documentation, its declared capabilities, its dependency edges, its
owner — should live **in the same file as the code that implements it**,
in a structured comment block. A meta-runner walks the tree, parses
every block, and acts on it.
Every cross-cutting fact a module owns — its behavior obligations,
public documentation, declared capabilities, dependency edges, owner,
runtime boundaries, or executable evidence — should live **in the same
file as the module that owns that fact**, in a structured comment
block. A meta-runner walks the tree, parses every block, and acts on
it.

Modules without the relevant block surface as visible coverage gaps in
the runner output. Coverage is observable, not implicit.
Expand All @@ -20,8 +21,14 @@ This is the inverse of the conventional "keep your docs/tests/configs in
sync with code" approach, which fails because the contract and the
implementation live in different files. Anyone can delete the code and
forget the doc; the lie persists. msdmd makes the lie structurally
impossible: when you delete the code, you delete the block in the same
diff.
visible: when the implementation-owning file disappears, its owned
block disappears in the same diff.

For tests, ownership is split rather than flattened: source modules own
`CONTRACTS` obligations; test modules own `CHECKS` evidence that
claims to prove those obligations. See
[`test-build/SKILL.md`](../test-build/SKILL.md) and
[`doctrine/msdmd-checks.md`](../doctrine/msdmd-checks.md).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Vendor the referenced doctrine file

This new reference points to ../doctrine/msdmd-checks.md, but the vendored .agents/skills tree does not contain any doctrine/ directory or msdmd-checks.md file (checked with repo-wide search). As a result, both this link and the matching new link in test-build/SKILL.md are dead, so agents following the updated skill docs cannot reach the ratified CHECKS/CONTRACTS doctrine that the text now depends on.

Useful? React with 👍 / 👎.


## Block syntax

Expand All @@ -39,8 +46,8 @@ diff.
### Universal rules

- **Fence**: `=== <BLOCK_NAME> ===` opens, `=== END <BLOCK_NAME> ===`
closes. Block name is uppercase snake_case (e.g. `CONTRACTS`, `DOCS`,
`CAPABILITIES`, `REQUIRES`, `OWNERS`).
closes. Block name is uppercase snake_case (e.g. `CONTRACTS`,
`CHECKS`, `DOCS`, `CAPABILITIES`, `OWNERS`).
- **Comment marker**: whatever is idiomatic for the file's language.
`#` for Python / Ruby / Elixir / shell. `//` for TS / JS / Rust / Go /
Java / C / C++ / Swift. `--` for SQL / Lua / Haskell. The marker
Expand All @@ -58,27 +65,39 @@ diff.
`CONTRACTS` and `DOCS` (and any others). Each is parsed
independently by its respective application.

### Example (Python)
### Example (Python source module)

```python
# === CONTRACTS ===
# id: chat_get_other_owner_404
# given: GET /api/v1/conversations/{id} with x-user-id != row.user_id
# then: 404 (existence non-disclosure)
# class: security
# call: tests.contracts.chat.test_get_other_owner_404
# === END CONTRACTS ===
```

### Example (TypeScript)
### Example (Python test module)

```python
# === CHECKS ===
# id: check_chat_get_other_owner_404_http
# proves: chat_get_other_owner_404
# call: self::test_chat_get_other_owner_404_http
# requires: python3, posix_shell
# timeout: 20
# mutates: db
# cleanup: transaction_rollback
# === END CHECKS ===
```

### Example (TypeScript source module)

```typescript
// === CONTRACTS ===
// id: chat_input_send_disabled_while_pending
// given: a message is in flight
// then: send button is disabled and shows pending state
// class: ux_correctness
// call: src/__contracts__/chat_input.ts#test_send_disabled_while_pending
// === END CONTRACTS ===
```

Expand Down Expand Up @@ -137,12 +156,14 @@ export default defineMsdmdCollection({
repo: "<reponame>",
declarations: [
{ file: "path/to/module.py", block: "CONTRACTS", id: "...", fields: { summary: "..." } },
{ file: "tests/test_module.py", block: "CHECKS", id: "...", fields: { proves: "..." } },
],
gaps: [
{ file: "path/to/module.py", missing: ["CONTRACTS", "DOCS"] },
],
edges: [
{ from: "module_a", to: "module_b", kind: "requires", source_block: "DEPENDENCIES", source_id: "..." },
{ from: "check_module_a", to: "module_a_contract", kind: "claims_proves", source_block: "CHECKS", source_id: "..." },
],
});

Expand All @@ -151,11 +172,12 @@ export const gaps = [];
```

A repo-level msdmd visualizer SHOULD read `<reponame>_msdmd.ts` and render
relationships between modules using the `MsdmdEdge` shape: `DEPENDENCIES.requires`,
`CAPABILITIES.exposes`, `OWNERS.owner`, `BOUNDARIES` risk fields, `DOCS.covers`,
`CONTRACTS.call`, and any `requires` edges shared across application skills.
The visualizer is a consumer of the collection point, not a second metadata
source.
relationships between modules using the `MsdmdEdge` shape:
`DEPENDENCIES.requires`, `CAPABILITIES.exposes`, `OWNERS.owner`,
`BOUNDARIES` risk fields, `DOCS.covers`, `CHECKS.call`,
`CHECKS.proves` as `claims_proves`, and any `requires` edges shared
across application skills. The visualizer is a consumer of the
collection point, not a second metadata source.

If a repo has no collection point or visualizer yet, record that as `hmmm` in
repo-local planning rather than pretending the graph exists.
Expand Down Expand Up @@ -220,16 +242,17 @@ consistency):
|---|---|
| `id` | Unique stable identifier within the block. Required on every entry. |
| `class` | Free-text tag for grouping (`security`, `correctness`, `idempotency`, etc.). The runner counts entries per class in summaries. |
| `call` | Fully-qualified path to an executable target (Python module path, JS module + export, etc.) the executor will invoke. |
| `call` | Executable target owned by an evidence/check declaration. Source `CONTRACTS` do not use this field for test topology. |
| `proves` | Comma-separated ids this evidence/check entry claims to prove. The collection edge kind is `claims_proves`; mutation sensitivity is a higher verification rung. |
| `summary` | One-sentence human description. |
| `requires` | Comma-separated list of other entry ids this one depends on. |
| `requires` | Comma-separated dependency ids or host capabilities. Exact semantics are application-specific and must be documented by the skill that consumes it. |
| `owner` | Who is responsible (person, agent role, team). |
| `since` | Version or date this declaration was added. |
| `deprecated` | If present, marks the entry as scheduled for removal. |

Application-specific fields (`given`, `then`, `expects`, `inputs`,
`outputs`, etc.) are introduced by individual SKILLs and documented in
their own SKILL.md.
`outputs`, `mutates`, `cleanup`, `timeout`, etc.) are introduced by
individual SKILLs and documented in their own SKILL.md.

## Authoring a new msdmd application

Expand All @@ -247,18 +270,20 @@ their own SKILL.md.
5. **Author a SKILL.md** in this lib with the convention spec, the
executor's behavior, and at least one worked example.

`test-build/` is the canonical reference application. Read its
SKILL.md alongside this one to see the pattern fully realized; read
`doc-build/`, `cap-build/`, `deps-build/`, `owner-build/`,
`risk-boundary-build/`, and `ratios/` for additional applications over
the same parser contract.
`test-build/` is the canonical reference application for paired source
`CONTRACTS` and test `CHECKS`. Read its SKILL.md alongside this one to
see the pattern fully realized; read `doc-build/`, `cap-build/`,
`deps-build/`, `owner-build/`, `risk-boundary-build/`, and `ratios/`
for additional applications over the same parser contract.

## Anti-patterns

- **Don't define the contract in a separate file.** The whole point is
that the declaration lives next to the implementation. If you find
yourself writing `tests.yaml` or `docs.json`, you're outside the
doctrine.
- **Don't define an owned declaration in a detached side file.** The
whole point is that the declaration lives next to the module that
owns that fact. Source obligations belong in source; test evidence
belongs in the test module that owns the evidence.
- **Don't put `call:` in source `CONTRACTS`.** Source modules own
obligations, not test topology. Put executable targets in `CHECKS`.
- **Don't make ids reflect implementation details.** `chat_returns_200`
tells future-you nothing; `chat_get_other_owner_404` tells you what's
protected. Ids are part of the documentation.
Expand Down
6 changes: 4 additions & 2 deletions .agents/skills/msdmd/collect.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# ratios: loc_comments=141:7 imports_exports=6:3 calls_definitions=35:6
# ratios: loc_comments=143:7 imports_exports=6:3 calls_definitions=35:6
"""Generate repo-level msdmd collection-point TypeScript.

This is a small stdlib helper for consuming repos that want to generate a
Expand All @@ -20,6 +20,7 @@
"DEPENDENCIES",
"OWNERS",
"CONTRACTS",
"CHECKS",
"MODULE_BUILD",
"BOUNDARIES",
"RATIOS",
Expand All @@ -33,6 +34,7 @@
"owner": "owns",
"covers": "covers",
"call": "calls",
"proves": "claims_proves",
"boundaries": "risk",
}

Expand Down Expand Up @@ -172,4 +174,4 @@ def main() -> int:

if __name__ == "__main__":
raise SystemExit(main())
# ratios: loc_comments=141:7 imports_exports=6:3 calls_definitions=35:6
# ratios: loc_comments=143:7 imports_exports=6:3 calls_definitions=35:6
9 changes: 5 additions & 4 deletions .agents/skills/msdmd/collection.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// ratios: loc_comments=66:0 imports_exports=0:0 calls_definitions=1:0
// ratios: loc_comments=67:0 imports_exports=0:0 calls_definitions=1:0
/**
* Shared TypeScript shapes for repo-level msdmd collection points.
*
Expand All @@ -13,6 +13,7 @@ export type MsdmdBlockName =
| "DEPENDENCIES"
| "OWNERS"
| "CONTRACTS"
| "CHECKS"
| "MODULE_BUILD"
| "BOUNDARIES"
| "RATIOS"
Expand All @@ -24,7 +25,7 @@ export type MsdmdFieldMap = Record<string, string>;
export interface MsdmdDeclaration {
/** Repository-relative source file that owns the declaration. */
file: string;
/** msdmd application block name, such as CONTRACTS or DOCS. */
/** msdmd application block name, such as CONTRACTS, CHECKS, or DOCS. */
block: MsdmdBlockName;
/** Stable entry id declared inside the block. */
id: string;
Expand All @@ -46,7 +47,7 @@ export interface MsdmdEdge {
from: string;
/** Target declaration id, capability id, owner, route, file, or external system. */
to: string;
/** Relationship kind: requires, exposes, owns, covers, calls, risk, etc. */
/** Relationship kind: requires, exposes, owns, covers, calls, claims_proves, risk, etc. */
kind: string;
/** Block that produced this edge. */
source_block: MsdmdBlockName;
Expand All @@ -71,4 +72,4 @@ export interface MsdmdCollection {
export function defineMsdmdCollection(collection: MsdmdCollection): MsdmdCollection {
return collection;
}
// ratios: loc_comments=66:0 imports_exports=0:0 calls_definitions=1:0
// ratios: loc_comments=67:0 imports_exports=0:0 calls_definitions=1:0
Loading
Loading