Metadata-Version: 2.4
Name: plan-doc
Version: 0.1.0
Summary: Typed parser for plan-file YAML frontmatter (schema v1) — strict validation, first-block-only extraction, foreign-document discrimination
License: MIT
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Development Status :: 4 - Beta
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pyyaml>=6.0
Provides-Extra: dev
Requires-Dist: pytest>=9.0.3; extra == "dev"
Dynamic: license-file

# plan-doc

Typed parser for plan-file YAML frontmatter (schema v1). Extracts the
machine-readable fields a plan-driven-PR workflow needs — `template`,
`disposal`, `branch`, a planner-handoff `dossier` block — from markdown
plan documents, with strict validation and loud failures.

```python
from pathlib import Path
from plan_doc import PlanDoc, PlanDocError, NonDraftPrFrontmatterError

doc = PlanDoc.from_path(Path("docs/plans/my-plan.md"))
if doc.disposal == "delete-on-merge":
    ...
if doc.dossier is not None:
    files = doc.dossier.get("files", [])
```

## What it enforces

- **Schema v1.** `plan_schema: 1` is required; `template`, `disposal`,
  `phase`, `cleanup_trigger`, `ticket`, `branch`, `tdd_mode`, `dossier`
  are the only other top-level keys. Unknown keys raise `PlanDocError` —
  this is the typo guard (`dispozal` fails loud).
- **First-block-only parsing.** Only a `---`...`---` block at the very
  top of the file is frontmatter. Body-level `---` horizontal rules are
  never split on.
- **Foreign-document discrimination.** Valid frontmatter with no
  `plan_schema` and no plan indicator fields raises the typed subclass
  `NonDraftPrFrontmatterError`, so callers can treat non-plan documents
  leniently without swallowing real validation errors.
- **No frontmatter at all** raises `PlanDocError` with an actionable
  message (add `plan_schema: 1`).

## Dependency note

`pyyaml` is a hard dependency, and the module *also* keeps a minimal
no-yaml fallback parser (`_parse_yaml_minimal`) for simple `key: value`
frontmatter. Both halves are deliberate: the upstream source of this
module runs in a zero-pip environment and relies on the fallback, while
the package declares full functionality. The fallback is covered by
tests here — don't remove either half.

## Provenance

Extracted verbatim (code byte-identical, module docstring reframed) from
the draft-pr skill of the m0j0d portfolio plugin, where the vendored copy
remains the operational source of truth. This package mirrors it at
release points.

Pool purity rule: transport-free, LLM-agnostic, no secrets. Pure parsing;
the only I/O is `Path.read_text` in `PlanDoc.from_path`.

## License

MIT
