Skip to content

feat(manifestos): discover_manifestos loader + pydantic schema (#131)#143

Merged
hadamrd merged 1 commit into
trunkfrom
loop/131-discover-manifestos
May 28, 2026
Merged

feat(manifestos): discover_manifestos loader + pydantic schema (#131)#143
hadamrd merged 1 commit into
trunkfrom
loop/131-discover-manifestos

Conversation

@hadamrd
Copy link
Copy Markdown
Owner

@hadamrd hadamrd commented May 28, 2026

Closes #131.

Summary

Adds discover_manifestos() and the QualityManifesto / TestingManifesto / Manifestos / Rule pydantic models in forge_loop.manifestos, plus a MissingManifestoError modelled on MissingVisionError. Existing load_manifestos / ManifestoBundle surface (#132 worker-prompt injection) is preserved unchanged — the two APIs share the same files but serve different consumers.

Acceptance criteria → coverage

  • QualityManifesto / TestingManifesto (markdown: str, rules: list[Rule] | None) + Manifestos bundle with quality / testing / warnings.
  • discover_manifestos(repo_path, *, required=False).
  • ✅ Discovers .forge/quality-manifesto.md + optional .forge/quality-rules.yaml; same for testing.
  • ✅ Missing markdown → empty manifesto + warning entry containing the absolute path.
  • required=TrueMissingManifestoError with absolute path.
  • ✅ Malformed rules YAML always raises (parse error or schema invalidity), with absolute path + pydantic-formatted error.
  • ✅ Empty markdown ⇒ "present but empty", no warning.
  • ✅ Public API exported via __all__. (ProductVision is not re-exported from forge_loop/__init__.py, so neither are these — consistent.)
  • ✅ Dependency-light: only pathlib, pydantic, pyyaml.

Adversarial coverage

  • Dangling .forge symlink → clean MissingManifestoError, not OSError.
  • .forge is a regular file → clean error.
  • quality-manifesto.md is a directory → clean "not a regular file" error.
  • Rules YAML is a bare list (lenient) vs scalar (rejected).
  • Both required=True legs (missing quality, missing testing).

Test plan

  • PYTHONPATH=src pytest tests/test_manifestos_discover.py — 19 passed.
  • PYTHONPATH=src pytest tests/test_manifestos_discover.py tests/test_manifestos_discovery.py — 41 passed (existing seed-manifesto tests unaffected).

🤖 Generated with Claude Code

Adds the issue #131 discovery API alongside the existing #132
worker-prompt injection API in forge_loop.manifestos:

* QualityManifesto / TestingManifesto / Manifestos pydantic models
* Rule model (id, description, severity?) — minimal per the #131
  out-of-scope clause
* MissingManifestoError exception (mirrors MissingVisionError)
* discover_manifestos(repo_path, *, required=False) -> Manifestos

Soft-default semantics: missing markdown ⇒ empty manifesto + warning.
required=True ⇒ raises MissingManifestoError with absolute path.
Malformed *-rules.yaml always raises (silent corruption is worse than
absence). Empty markdown is treated as "present but empty" with no
warning. Adversarial cases (dangling .forge symlink, .forge as file,
markdown-is-a-directory) raise clean MissingManifestoError rather than
leaking OSError stacktraces.

Test matrix in tests/test_manifestos_discover.py covers every bullet
from the acceptance criteria plus the symlink / directory / bare-list
adversarials.
@hadamrd hadamrd merged commit de18428 into trunk May 28, 2026
2 checks passed
@hadamrd
Copy link
Copy Markdown
Owner Author

hadamrd commented May 28, 2026

Source issue #131 was closed mid-flight (state: closed). Loop refusing auto-merge. Reopen the issue OR merge manually.

@hadamrd hadamrd deleted the loop/131-discover-manifestos branch May 28, 2026 18:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(manifestos): quality + testing manifesto discovery + schema

1 participant