Metadata-Version: 2.4
Name: frontmattering
Version: 0.9.4
Summary: Governed frontmatter, freshness tethers, and validate-only runtime gates for agent-facing Markdown
Author: Lasse T.
License-Expression: LicenseRef-FRONTMATTERING-Individual-Use-1.2
Project-URL: Homepage, https://frontmattering.com
Project-URL: Repository, https://github.com/frontmattering/frontmattering
Project-URL: Issues, https://github.com/frontmattering/frontmattering/issues
Project-URL: Commercial, https://github.com/frontmattering/frontmattering/blob/main/COMMERCIAL_LICENSE_REQUIRED.md
Project-URL: License, https://github.com/frontmattering/frontmattering/blob/main/LICENSE.md
Keywords: markdown,frontmatter,documentation,governance,ai-agents,validation
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Documentation
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE.md
License-File: COMMERCIAL_LICENSE_REQUIRED.md
License-File: NOTICE
License-File: THIRD_PARTY_NOTICES.md
License-File: TRADEMARKS.md
Requires-Dist: PyYAML>=6.0
Requires-Dist: markdown-it-py>=4.0.0
Requires-Dist: mdit-py-plugins>=0.4.0
Provides-Extra: markdown-plugins
Requires-Dist: mdit-py-plugins>=0.4.0; extra == "markdown-plugins"
Dynamic: license-file

# Frontmattering

Frontmattering makes Markdown safer for agents.

It adds governed frontmatter, task routing, body/frontmatter freshness tethers, and a vendorable validate-only runtime gate so an agent can consume a compact brief without silently relying on stale documentation.

## Install

```bash
python -m pip install frontmattering
frontmattering --version
frontmattering doctor
```

## First-hour path

`frontmattering init .` scaffolds a starter router under `docs/`, and `frontmattering new` creates governed documents. This block runs verbatim in an empty directory (it is executed as a release gate in CI):

```bash
frontmattering init . --set-id MYDOCS --title "My docs"
frontmattering new docs/10_GUIDE.md --profile guide --title "My guide"
frontmattering tether update --add .
frontmattering validate .
frontmattering brief .
```

Already have Markdown under `docs/`? Add governance to a file you already have with `promote`, one file or many at once:

```bash
frontmattering promote docs/YOUR_GUIDE.md --profile guide --in-place
frontmattering promote docs/guides/*.md --profile guide --in-place   # batch: --in-place required
```

Have a file that already carries a leading frontmatter block — a legacy or hand-rolled one — you want replaced with a fresh canonical block? Use `reauthor`. It removes the existing block, writes a shipped starter-profile block over the preserved body, and keeps the document's canonical `document_id` so inbound references are not orphaned:

```bash
frontmattering reauthor docs/LEGACY_GUIDE.md --profile guide --in-place
frontmattering reauthor docs/guides/*.md --profile guide --in-place   # batch: --in-place required
```

`promote` refuses a file that already has a leading block (`FRONTMATTERING-PROMOTE-FRONTMATTER-PRESENT` — use `reauthor`); `reauthor` refuses a plain file with no block (`FRONTMATTERING-REAUTHOR-FRONTMATTER-ABSENT` — use `promote`). A multi-file batch is all-or-nothing: every input is built and preflighted before any byte is written, and any failure — including one that would leave the corpus without exactly one router — restores every file. Promoting or reauthoring a file outside the selected corpus fails before the file is touched (`FRONTMATTERING-AUTHORING-TARGET-OUTSIDE-CORPUS`).

Choose the starter profile that matches the document's role: `router`, `guide`, `spec`, `contract`, `evidence`, `release`, `registry`, or `template` (for reusable snippet/template surfaces). Files without a single top-level heading — generated snippets, for example — can be titled from their filename with `--title-strategy stem`, so a whole batch of headingless files authors in one call:

```bash
frontmattering promote docs/generated/snippets/*.md --profile template --in-place --title-strategy stem
```

For strict freshness enforcement, set `validation_profile: trust` in `.frontmattering/project.yaml`, then re-run `frontmattering validate .` and `frontmattering brief .`.

## Stamping generated or edited files

If a tool generates or edits governed Markdown, it must not hand-reimplement the body-tether digest — that silently drifts from the model. Use the supported single-file surface instead. `frontmattering stamp` refreshes one already-governed file's `body_tether` so it reads FRESH:

```bash
frontmattering stamp docs/generated/SNIPPET.md --in-place
```

In-process, call the documented public API — it reads the canonical trust-field list from the shipped spec and reuses the exact kernel path the validator trusts, so a stamped file is accepted as FRESH:

```python
from frontmattering.api import stamp_tether
receipt = stamp_tether("docs/generated/SNIPPET.md")   # {'operation': 'stamp', 'body_sha256': ..., ...}
```

## Relationships and mesh lint

The model carries a typed relationship graph (`relationships`, `evidence_references`), but an empty graph is easy to leave in place. Author edges with `link` — relationships are not a freshness trust field, so the file stays FRESH and the corpus stays GO:

```bash
frontmattering link add docs/RELEASE_NOTES_v2_4.md --to PRFT-RELEASE-NOTES-V2-3 \
  --type supersedes --scope release-notes --rationale "v2.4 supersedes v2.3"
```

`link add` preflights that the target resolves in the corpus and that a `supersedes` edge names a `--scope`. Lint the graph for gaps the per-document validator does not catch — dangling same-set targets, and release records that supersede no predecessor:

```bash
frontmattering mesh --lint
```

## Runtime gate

```bash
frontmattering runtime pack --out frontmattering-runtime.pyz
python frontmattering-runtime.pyz validate docs --format json
```

The runtime artifact is validate-only. It does not expose init, promote, reauthor, new, index, tether update, or authoring surfaces.

**`GO` means every *selected* document passed — not that every Markdown file under the supplied path was selected.** The report always names the boundary: `selection.outside_selection_markdown_count` (with `selection.outside_selection_paths` and `…_sha256`) counts Markdown discovered under the supplied path but *outside* the configured corpus. Note that discovery is relative to what you validate:

```bash
# corpus-only: validates docs/**/*.md; does not discover Markdown elsewhere
python frontmattering-runtime.pyz validate docs --format json

# whole-tree boundary audit: discovers all Markdown under . and reports what the corpus left out
python frontmattering-runtime.pyz validate . --format json | jq '.selection.outside_selection_markdown_count, .selection.outside_selection_paths'
```

Both the runtime and the main CLI emit the identical `selection`/`project` evidence, so either surface can gate on the boundary.

## Prompt pack

The validator proves your frontmatter is valid, current, scoped, and tethered. It does not prove the frontmatter is *good* — a GO document can still carry a copied summary or a generic deepest intention. The governed prompt pack closes that gap: it makes authoring excellent, body-grounded frontmatter repeatable.

```bash
frontmattering prompt list
frontmattering prompt inspect author-category-frontmatter
frontmattering prompt render \
  --task author-category-frontmatter \
  --category self_protection_layer \
  --support-profile frontmattering_only \
  --corpus-root docs \
  --output rendered_prompt.md --receipt-out render_receipt.yaml
```

`prompt render` is deterministic: it composes the prompt from a packaged task template, a structured category profile, a support profile, and shared fragments, and binds the rendered bytes to every input's digest — including the authorizing manifest, renderer source, distribution, and serializer identity. **The core CLI never executes an LLM** — a rendered prompt proves only that the bytes were deterministically composed, not that a model ran or that an authoring result is semantically correct.

Run `frontmattering prompt verify` (also a `doctor` step) to confirm the packaged pack renders cleanly, reproduces its worked example, and conforms to its own shipped JSON schemas. Run `frontmattering prompt verify-rendered --prompt rendered_prompt.md --receipt render_receipt.yaml --request render_request.yaml` to verify a rendered prompt: it re-renders the canonical prompt from the request against the installed pack and compares byte-for-byte, rejecting a non-canonical or re-sealed prompt (`FRONTMATTERING-PROMPT-NOT-CANONICAL`) and any unauthorized task/category/profile.

This establishes **reproducibility** — the prompt is the canonical render of that request on this installed pack. It is not, on its own, **provenance** that the request was authorized: a producer who controls the request and re-renders honestly produces a valid prompt. Hostile-producer provenance requires signing the request/receipt under an independent authority (tracked as deferred in `docs/DEFERRED_ITEMS_LEDGER.md`).

## License

Frontmattering is source-available. It is free for individual personal use within the scope of `LICENSE.md`. Professional, organizational, employer, client, CI/CD, hosted, managed-service, platform, consulting, or revenue-connected use is permitted for a 30-day evaluation period under `LICENSE.md`; continued use after the evaluation requires a paid commercial license.

Frontmattering is not open-source software under the Open Source Definition because professional and organizational use is restricted without a commercial license.

Runtime dependency status is recorded in `THIRD_PARTY_NOTICES.md`; project notices are recorded in `NOTICE`.

## Claim boundary

A `FRESH` brief means the current body bytes and canonical trust-bearing frontmatter fields match their mechanical tether. It does not prove semantic summary correctness, human approval, external adoption, or production suitability.

A `STALE` or `UNTETHERED` summary must not be relied on without reading the body.


## Publication status

This v0.9.2 minor release closes the architectural findings an external audit tracked against 0.9.1 (the code-addressable deferred-items), plus a fail-closed hardening pass. Every mutating command (`tether update`, `parse --batch`, `new`, single-file promote/reauthor, batch authoring, `init`) is now **operation-wide all-or-nothing** through one shared transaction primitive, and `tether update` writes each document once with final digests. The Markdown parser is **deterministic across hosts**: `mdit-py-plugins` is now a required dependency, the declared `extended_v1` profile is recorded in the IR, and the loader fails closed if the plugins are absent. The packed runtime declares its dependency contract (not self-contained) and reports a typed `BLOCKED` — never a raw traceback — on a missing dependency. Dangerous or malformed input is a typed input rejection, never `FRONTMATTERING-KERNEL-INTERNAL-BUG`. New surfaces: `prompt verify-execution` (rejects a fabricated `COMPLETE` execution record), `prompt sign` + `verify-rendered --signature` (hostile-producer provenance under an operator key), and `validate --require-all-markdown-selected` (opt-in corpus-completeness). CI expands to Linux/Windows/macOS × Python 3.10–3.14. LICENSE §3 adds an explicit generated-output grant. `prompt verify` stays GO and the validator trust-semantics, frontmatter schema, and canonical model (`v0.1.5`) are unchanged. It carries forward the 0.9.1 corrective fixes below.

The prior v0.9.1 patch release fixes four defects an external audit confirmed against 0.9.0: `reauthor` deleted authored leading body bytes while its receipt claimed byte preservation (now preserved exactly, and the writer refuses any body-byte change); a symlink under an include glob could import an out-of-corpus file into the governed set (now rejected); a batch could exit 0 leaving the corpus with duplicate document ids (now refused before any write); and untrusted filenames could inject control/bidi characters into derived titles (now rejected). See the changelog for the full list; the audit's remaining findings are the architectural items already tracked in `docs/DEFERRED_ITEMS_LEDGER.md`.

The prior v0.9.0 minor release closed DIL-21 — the empty relationship/evidence graph the tutorial dogfood surfaced. It adds `frontmattering link add`/`link rm` to author typed, schema-complete relationships on a governed document (target resolution is preflighted; a `supersedes` edge requires an explicit scope), and `frontmattering mesh --lint` to surface graph gaps the per-document validator does not catch — dangling same-set targets and release records that supersede no predecessor. Because `relationships` is not a body-tether trust field, authoring an edge keeps the file FRESH and the corpus GO. `prompt verify` stays GO and the validator trust-semantics, frontmatter schema, prompt-pack canonical model, and canonical model (`v0.1.5`) are unchanged. It carries forward the 0.8.0 stamping surface below.

The prior v0.8.0 minor release closed DIL-20 — the body-tether correctness hazard the tutorial dogfood surfaced. It adds a **supported single-file stamping surface** so tools that generate or edit governed Markdown stop re-implementing the closed model's canonicalization by hand (which silently drifts from the validator): a new `frontmattering stamp <file>` command and a documented, importable `frontmattering.api.stamp_tether()` that reads the canonical trust-field list from the shipped spec and reuses the exact kernel path the validator trusts. Both refuse a non-governed file (`FRONTMATTERING-STAMP-NOT-GOVERNED`). `prompt verify` stays GO and the validator trust-semantics, frontmatter schema, prompt-pack canonical model, and canonical model (`v0.1.5`) are unchanged. It carries forward the 0.7.0 authoring-completeness work below.

The prior v0.7.0 minor release completed the authoring surface that 0.6.0 began, closing the two gaps the 0.6.0 tutorial dogfood surfaced (tracked as DIL-18 and DIL-19). **A `template` starter profile** now emits the canonical `template_surface` role (kind `template`, authority `advisory`) with its own template id, so reusable snippet/template documents no longer have to borrow the authoring-guide template or be hand-authored. **`--title-strategy {h1,stem}`** on `promote`/`reauthor` lets a file with no single top-level heading be titled from its filename, so a batch of headingless generated files (the tutorial's snippets) authors in one call instead of failing `FRONTMATTERING-PROMOTE-TITLE-AMBIGUOUS`; the default (`h1`) is unchanged, and an explicit `--title` always wins. `prompt verify` stays GO and the validator trust-semantics, frontmatter schema, prompt-pack canonical model, and canonical model (`v0.1.5`) are unchanged. It carries forward the 0.6.0 batch authoring + `reauthor`, the 0.5.7 prompt-pack reasoning/deterministic classification, the 0.5.6 out-of-corpus path identities, the 0.5.5 runtime report-parity fix, the 0.5.4 generated runtime CLI, the 0.5.3 complete CLI help, and the 0.5.2 prompt-evidence layer. Deferred items remain tracked in `docs/DEFERRED_ITEMS_LEDGER.md` (DIL-20 stamping API and DIL-21 relationship authoring are the next authoring items). Custom license text should still receive legal review before paid commercial sales.
