Originally created by: snowyukitty
Doberman’s extensibility story is that third parties can ship rules without core importing them — via the doberman.rules entry-point group. Until now there was no worked example to copy.
This PR adds a small, opt-in tutorial package at examples/plugin-guardrail/ that shows the full round trip:
Guardrail (ExampleRule)pyproject.tomlpip install -e → the rule appears in discover_rules() / ObjectiveGuardrailDemo behavior: a file_write whose canonical basename is SECRETS_TODO.md steps up to AUTH (sensitive_path_access). Everything else abstains (PASS). Harmless on purpose — easy to read in five minutes.
Closes [#91].
doberman.rules), not a hypothetical APIProtectedPathRule (prefer raw_arguments, canonicalize, normalize \ → /)registry.discover_rules() as todayObjectiveGuardrail(load_plugins=False, extra_rules=[…])tests/unit/test_examples_plugin_guardrail.py — layout, entry-point declaration, AUTH/PASS behavior, redacted-target + raw path, backslash normalize, near-miss basenames, explanation redaction, raise-only vs built-in .env BLOCK, Guardrail shapeexamples/plugin-guardrail/tests/test_example_rule.py — install-time discovery + objective-guardrail fire (run after pip install -e examples/plugin-guardrail; not in default testpaths by design)Local validation (Python 3.12, rebased on current main):
ruff check . / ruff format --check . — cleanlint-imports — both contracts keptpytest tests/unit/test_examples_plugin_guardrail.py tests/unit/test_core_is_standalone.py -q — greenpip install -e examples/plugin-guardrail && pytest examples/plugin-guardrail/tests -q — green (11)Covered: case-insensitive basename; Windows-style separators on any OS; redacted action.target with raw path; target-only fallback; near-miss basenames; read/empty abstain; explanation omits path; raise-only vs .env.
Deviations: none material vs [#91]. CI unit tests were added so default pytest covers evaluate/raise-only without registering the entry point (avoids polluting discover_rules() == []).
Risks / notes:
examples/ is git-checkout oriented (not added to the locked core sdist include list).AI assistance was used during implementation and review. The contributor independently verified the design, complete diff, and reported test results.
Originally posted by: fu351
Welcome @snowyukitty, and thanks for contributing! A custom Guardrail plugin tutorial is exactly the kind of example we want alongside the plugin interfaces. Taking a review pass now - feedback shortly.
Ticket changed by: fu351
Originally posted by: fu351
🎉 Merged — thank you, @snowyukitty!
This is exactly the kind of contribution that makes Doberman's plugin system real for people: a complete, tested, copy-pasteable example of a custom Guardrail plugin, wired through the entry-point registry the right way. A full tutorial plus tests with green CI, as a first-time contributor — genuinely appreciated. 🙏
If you're up for more, I'd love to have you around as we build this out:
help wantedissues shortly (real, hard parts of the system, not busywork). Would be great to have you take a crack at one.Thanks again for helping make Doberman something more than a solo project. 🐕
Originally posted by: fu351
Congrats on [#184] landing today too — busy week for you. The custom-guardrail plugin tutorial in this PR is thorough (a full working example plugin, its own tests, and the walkthrough docs), and since you're the one who wrote it, [#200] (plugins+docs: complete the
doberman.detectorsextension seam, level-9) is squarely your lane — it needs the same example-plugin-plus-docs treatment applied to a different seam. Levels run 1-10 on every open issue now, and commenting on one claims it.Related
Tickets:
#184Tickets: #200