Mediva CI
Gate pull requests and issues on GitHub with a copy-in workflow — friendly, signal-not-verdict checks that never reject the author.
DOCKING CONTROL, Babylon 5: This is Command. Your manifest is missing the cargo declaration on bay four. You are not refused — hold position, amend the manifest, and you are cleared to dock.
Every PR and issue body is read against your contract; the check annotates the line to amend and never closes anything.
Wire it up
# .github/workflows/mdv.yml
name: mediva
on:
pull_request:
types: [opened, edited, synchronize, reopened]
permissions:
contents: read
jobs:
mediva:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: jamespacileo/mediva@v0.2.0<!-- mdv: section required content.words.min=20 content.none=@placeholders -->
## Description
Describe what changed, why, and the impact.
<!-- mdv: section required -->
## Pre-Merge Checklist
<!-- mdv: list required items.all=checked labels.eq=@template -->
- [ ] I reviewed the diff for unrelated changes.
- [ ] I updated docs, or this PR does not require docs.The template is the contract: you write it by hand, npx mdv check --pr body. tries it locally. Mark the job required to block merges.
| Input | Meaning |
|---|---|
fail-on | error (default), warning, never |
pr-contract | default . |
issue-contract | an issue template (add an issues: trigger) |
paths | limit the changed-Markdown check |
Your mediva. applies.
What the check does
| Check | Command | Reports |
|---|---|---|
| Title and body | mdv check - --schema <contract> --title <title> -f github | all |
| Changed Markdown | mdv check --changed BASE. | every problem in each changed document |
Every document runs the lint gate first (markdownlint's rules plus mediva's fence check, always errors), then shape, then state; a failed gate stops the ones after it. A document no contract governs gets the lint gate alone and a no-contract warning.
--changed picks which documents run and nothing else: a document the pull request changed (or whose contract it changed) is checked in full.
✓ mediva: 3 documents checked, no problemsExit codes and merge gating
| Code | Meaning |
|---|---|
0 | green: no blocking errors |
1 | blocking errors |
>1 | could not run: config or contract error |
Warnings and advisory findings never fail, even raised to error; fail-on: warning counts them, and a gate then fails on any finding, so a shape warning stops the state gate.
Colour in workflow logs
No TTY means no colour; see Colour.
- run: npx mediva check
env:
FORCE_COLOR: "1"Two details that make it tamper-proof
| Detail | Effect |
|---|---|
| Base-branch contract | a PR cannot weaken its own contract |
| Bootstrap skip | no template on base yet: notice, exit 0 |
Rendering a comment yourself
For a comment instead (needs pull-requests: write):
npx mediva check body.md --schema .github/pull_request_template.md --title "$TITLE" -f pr-comment > comment.md
gh pr comment "$PR" --body-file comment.mdAgent-grade guards
| Guard | Rule | Catches |
|---|---|---|
| LLM residue | content. | "I've implemented…" (advisory) |
| Truncation | content. | …, [truncated] (advisory) |
| Fence wrapper | always on: the lint gate | a document fenced whole |
| Placeholder | content. | TODO, FILL ME IN |
| Vague evidence | items. | "Tested thoroughly" (advisory) |
| Bare tick | items. | a tick with no evidence |
Document-scope severity overrides
<!-- soft: a short Summary prints a warning, never fails -->
<!-- mdv: section required content.words.min=20 warn=too-few-words -->
## Summary
<!-- mdv: endsection -->
<!-- hard: a vague Verification item blocks the merge -->
<!-- mdv: list required items.all=@evidence/specific error=vague-evidence -->
## Verification
<!-- mdv: endlist -->See Overrides.
Permissions and secrets
contents: read and the auto GITHUB_TOKEN only. It runs on pull_request, never pull_request_target: forks get a read-only token.