Skip to content

mino-verify

Verification Gatekeeper

Validate executed work against explicit acceptance criteria and repository-native checks, then produce a deterministic pass/fail verdict bound to a specific commit (Verify Anchor SHA).

This skill consumes run's output and feeds checkup. All structured artifacts (events, brief sections) are rendered from templates in templates/ so downstream skills can rely on schema stability.

Workflow

Step 1: Confirm Scope

  • Identify the task being verified (issue number or task key from the user)
  • Load .mino/briefs/issue-{N}.md and the latest valid event sequence from the issue
  • Verify Approved Revision == Spec Revision; if not, halt and direct user to /mino-task for re-approval

Optional note: the invocation may include free-form text after the issue/spec ref (e.g., /mino-verify #1842 在小红书场景下需要 ...). If present:

  • Capture it as local variable manual_verifier_note (single string).
  • Otherwise manual_verifier_note = null.

Step 2: Anchor The Verification

Record Verify Anchor SHA = git rev-parse HEAD before running any check.

This SHA is bound into every event and the verification summary. It guarantees the verdict refers to a specific committed state, not the current working tree.

If git status --porcelain shows uncommitted changes at this point, halt and direct user back to /mino-runverify evaluates committed code only. (run is responsible for committing before handoff.)

Step 3: Select Verification Commands

Resolve commands in this order; the first hit wins:

  1. .mino/config.yml override — read verify.commands (a list); if present, use exactly this list and skip auto-detection. The list may include any shell-runnable command.

  2. Brief override — if the brief's Verification section contains an explicit shell command list (lines starting with $ ), use that.

  3. Auto-detect repo-native tooling by file signature:

    SignatureDefault commands
    package.json (with pnpm-lock.yaml)pnpm install --frozen-lockfile, pnpm build, pnpm test, pnpm lint
    package.json (with yarn.lock)yarn install --frozen-lockfile, yarn build, yarn test, yarn lint
    package.json (otherwise)npm ci, npm run build, npm test, npm run lint
    pyproject.toml / setup.pypytest
    Cargo.tomlcargo build, cargo test, cargo clippy -- -D warnings
    Package.swiftswift build, swift test
    Mino.xcodeproj / *.xcodeprojxcodebuild -scheme <name> test
    Makefilemake test

    Skip commands whose script is not present (e.g., pnpm lint if package.json has no lint script). Do not invent a missing build/test target.

  4. Nothing detected → route to pending_acceptance (Step 6.D).

Step 4: Run Checks

Execute the selected commands sequentially. Capture stdout + stderr per command. Stop on the first failure.

When tooling integration with PRs is available and a PR is known, also surface gh pr checks output in the failure context if it is more authoritative than the local result.

Step 5: Compare To Acceptance Criteria

Walk each item in the brief's Acceptance Criteria section:

  • If the criterion is satisfied by an automated check, mark it as covered
  • If a criterion has no automated coverage, route the verdict to pending_acceptance (Step 6.D), even if all automated checks pass

Step 5.5: Author Verification Report

For outcomes 6.A (passed), 6.C (terminal failure), and 6.D (pending acceptance) — when there is substantive evidence to record — render templates/report.md.tmpl to .mino/reports/issue-{N}/report.md.

Skip for 6.B (retryable failure) and 6.E (publication failure): their context already lives in the brief's Failure Context section.

The report's content is your synthesis of:

  • The selected verification commands (Step 3) and their outputs (Step 4)
  • The acceptance-criteria walk (Step 5)
  • Environment versions discovered (language toolchain, framework, key deps)
  • Configuration steps that were necessary to make verification pass
  • Recurring gotchas worth documenting

Write .mino/reports/issue-{N}/report.md (overwrite if it already exists — the verify_anchor_sha in the header preserves which run authored it). Set local variable report_path = .mino/reports/issue-{N}/report.md for use in Step 6's event yml.

If there is genuinely no substantive content (e.g., a trivial change with only a one-line test pass), set report_path = null and skip writing.

If manual_verifier_note is non-null, append the following block to the report verbatim (no agent rephrasing — this is the human's input, preserved for audit):

## Manual Verifier Note

{{ manual_verifier_note }}

The agent will synthesise from this note in Step 7 (Reply Dispatch); the verbatim copy here is the source of truth.

Step 6: Render Verdict

Choose exactly one of A–E. Each writes the brief and writes a local event file under .mino/events/issue-{N}/{next_seq:04d}-{event-kebab}.yml. Whether a GitHub comment is posted depends on the event's category:

  • 6.A verify_passedsilent, no comment.
  • 6.B verify_failed_retryableaudible, post comment.
  • 6.C verify_failed_terminalaudible, post comment.
  • 6.D verify_pending_acceptanceaudible, post comment.
  • 6.E verify_publication_failedaudible, post comment.

Audible comment bodies are pure human notifications: short heading line, Reason:, and Action:. Do NOT include a Local events: pointer or any rendered YAML block — those exist in the local event file only. The local YAML at .mino/events/issue-{N}/{seq:04d}-{event-kebab}.yml is the authoritative log; the comment is a notification channel.

No path stages or commits .mino/briefs/.

Brief updates use surgical section replacement; preserve Open Questions / Warnings and any other human-authored content.

6.A All automated checks passed AND all acceptance criteria covered

  1. Publish code if relevant:
    • If code files changed during run:
      • The commit was already created by run.
      • Run all git commit operations for this outcome (run's commit is already in place; docs commit comes from 6.A.1.5). Run git push exactly once after 6.A.1.5 has had its chance to add a docs commit. If push fails, go to 6.E (publication failed) instead.
      • Capture Code Ref = git rev-parse HEAD after push.
      • Set Code Publication State: published.
    • If no code files changed:
      • Set Code Ref: not_applicable, Code Publication State: not_applicable.

1.5. Promote to Project Docs (optional):

Read .mino/config.yml field report.promotion (default auto). Read .mino/config.yml field report.docs_path (default docs/integrations/).

  • If promotion: never → skip; set promoted_doc = null.
  • If promotion: always → promote.
  • If promotion: auto → apply the heuristic from protocol § Verification Report ("Promotion Heuristic"). When in doubt, do NOT promote.

On promote:

  • Compute slug = kebab-case(issue_title, max 60 chars) (see protocol).
  • promoted_path = {docs_path}/{slug}.md.
  • If promoted_path exists: append a new section ## Update {YYYY-MM-DD} (verify_anchor: {sha7}) with the new content.
  • If not: write the report content as a fresh file.
  • git add {promoted_path}
  • git commit -m "docs(issue-{N}): {short title} integration notes" with the standard Co-authored-by trailer.
  • NEVER git commit --amend and NEVER git push --force.
  • Set local variable promoted_doc = {promoted_path}.

After step 1.5 (whether promotion occurred or not):

  • Run git push exactly once. If push fails, go to 6.E.

On promotion failure (commit error, file write error): log promotion_failed: <reason> to the report header and set promoted_doc = null. Do NOT abort verify_passed.

  1. Update brief sections (surgical replace):

    • Verification Report ← render templates/brief-section-verification-report.md.tmpl
    • Verification Summary ← render templates/brief-section-verification-summary.md.tmpl
    • Workflow State:
      • Current Stage: checkup
      • Next Stage: done
      • Workflow Entry State: ready_to_start
      • Code Publication State: published | not_applicable
    • Pass/Fail Outcomepass
    • Completion Handoff:
      • Completion Basis: verified
      • Code Ref: {sha or not_applicable}
  2. Do NOT post a GitHub commentverify_passed is silent in v1.10 and remains silent in v0.6.2. The local event yml at .mino/events/issue-{N}/{seq}-verify-passed.yml is the sole record at this stage. The eventual checkup_done comment will surface the commit + docs links.

After recording verify_passed, sync the GitHub stage label:

gh issue edit {N} --remove-label "stage:verify" --add-label "stage:done"

Label sync failure is a warning, not an error: log stage_label_sync_failed: <reason> in the verify report and proceed. The local yml remains authoritative.

  1. Detect orchestrator mode: if .mino/loops/active.lock exists AND its holder_agent: mino-task AND its heartbeat_at is within the last 6 hours: return silently. Otherwise proceed (the local event and brief updates are the hand-off signal).

6.B Checks failed AND attempt budget remains

A failure on attempt N is retryable when N <= Max Retry Count. With default Max Retry Count: 3, attempts 1/2/3 may yield fail_retryable; attempt 4 must be terminal.

  1. Update brief sections:

    • Failure Context ← render templates/brief-section-failure-context.md.tmpl with pass_fail_outcome: fail_retryable
    • Workflow State:
      • Current Stage: run
      • Next Stage: verify
      • Workflow Entry State: ready_to_start
    • Pass/Fail Outcomefail_retryable
  2. Do NOT change Attempt Count. Only run increments it.

  3. Post comment — render templates/comment-verify-failed-retryable.md.tmpl. The full error output lives in the brief Failure Context section, NOT in the GitHub comment.

  4. Detect orchestrator mode: if .mino/loops/active.lock exists AND its holder_agent: mino-task AND its heartbeat_at is within the last 6 hours: return silently. Otherwise proceed.

6.C Checks failed AND attempt budget exhausted (or unrecoverable)

  1. Update brief sections:

    • Failure Context ← render templates/brief-section-failure-context.md.tmpl with pass_fail_outcome: fail_terminal
    • Workflow State:
      • Current Stage: verify
      • Next Stage: none
      • Workflow Entry State: blocked
    • Pass/Fail Outcomefail_terminal
  2. Post comment — render templates/comment-verify-failed-terminal.md.tmpl. Truncated output stays in the brief Failure Context; the comment links to Report: if a report was authored in Step 5.5.

  3. Detect orchestrator mode: if .mino/loops/active.lock exists AND its holder_agent: mino-task AND its heartbeat_at is within the last 6 hours: return silently. Otherwise proceed.

6.D Manual acceptance required

Triggers:

  • All automated checks passed but at least one acceptance criterion has no automated coverage
  • No verification tooling could be detected
  • An acceptance criterion explicitly requires human review (UI screenshot, perceptual quality, etc.)
  1. Update brief sections:

    • Verification Report ← render templates/brief-section-verification-report.md.tmpl
    • Manual Acceptance ← render templates/brief-section-manual-acceptance.md.tmpl (write the actionable checklist here)
    • Workflow State:
      • Current Stage: verify
      • Next Stage: checkup
      • Workflow Entry State: pending_acceptance
    • Leave Pass/Fail Outcome unset; do not write Completion Handoff yet.
  2. Tag the issue with the pending-acceptance label. Skip gracefully if the label is missing on this repo.

  3. Post comment — render templates/comment-verify-pending-acceptance.md.tmpl. The acceptance checklist itself stays in the brief Manual Acceptance section, NOT in the GitHub comment.

  4. Detect orchestrator mode: if .mino/loops/active.lock exists AND its holder_agent: mino-task AND its heartbeat_at is within the last 6 hours: return silently. Otherwise proceed.

6.E Publication failed (push or commit refused after checks passed)

This is reachable only from 6.A when git push (or any equivalent publication step) fails after automated checks have already passed.

  1. Do NOT record success. Leave Pass/Fail Outcome and Completion Handoff unset.

  2. Update brief sections:

    • Failure Context ← render templates/brief-section-failure-context.md.tmpl with the publication error and pass_fail_outcome: null
    • Workflow State:
      • Current Stage: verify
      • Next Stage: verify
      • Workflow Entry State: ready_to_start
      • Code Publication State: local_only
  3. Do NOT change Attempt Count. Publication failure must not consume retry budget.

  4. Post comment — render templates/comment-verify-publication-failed.md.tmpl.

  5. Detect orchestrator mode: if .mino/loops/active.lock exists AND its holder_agent: mino-task AND its heartbeat_at is within the last 6 hours: return silently. Otherwise proceed.

Step 7: Reply Dispatch

Runs after the verify outcome is recorded, only for outcomes 6.A (verify_passed) and 6.D (verify_pending_acceptance). Skip for 6.B / 6.C / 6.E.

  1. Read .mino/config.yml > comment.reply (default auto).

    • If never: set reply_posted = null, skip to step 5.
    • If always: jump to step 3.
    • If auto: continue to step 2.
  2. Apply the auto decision rule (see protocol § Reply Dispatch):

    • If manual_verifier_note is non-null AND contains content the issue author would act on (steps, configuration, environment specifics), proceed to step 3.
    • Else if a doc was promoted in this flow (Step 6.A.1.5 set promoted_doc != null), proceed to step 3.
    • Else: set reply_posted = null, skip to step 5.
  3. Detect orchestrator context: if .mino/loops/active.lock shows holder_agent: mino-task AND its heartbeat is fresh (≤ 6 hours), and the loop has already replied for this issue earlier in this iteration (check .mino/events/issue-{N}/ for a prior reply_posted non-null in the current loop window): set reply_posted = null, skip to step 5. This avoids duplicate convergence comments per loop pass.

  4. Render templates/comment-reply.md.tmpl:

    • Synthesise variables from the report (Step 5.5 output) and manual_verifier_note.
    • Apply the variable rules in the template's HTML comment header.
    • Post via gh issue comment {N} --body-file <rendered>.
    • Capture the returned URL as reply_posted.
    • On post failure: log reply_post_failed: <reason> in the report, set reply_posted = null, do NOT retry. The local report remains authoritative.
  5. Patch the previously written event file (the one for the chosen verify outcome) to set the reply_posted field to the captured URL or null. The event file is local and append-only at the file level but field-level edits before the next event are permitted (this matches how report_path and promoted_doc are written today).

Templates

All artifact shapes are externalized; verify MUST NOT generate freehand variations.

  • templates/event-verify-passed.yml.tmpl
  • templates/event-verify-failed-retryable.yml.tmpl
  • templates/event-verify-failed-terminal.yml.tmpl
  • templates/event-verify-publication-failed.yml.tmpl
  • templates/event-verify-pending-acceptance.yml.tmpl
  • templates/comment-verify-failed-retryable.md.tmpl
  • templates/comment-verify-failed-terminal.md.tmpl
  • templates/comment-verify-pending-acceptance.md.tmpl
  • templates/comment-verify-publication-failed.md.tmpl
  • templates/comment-reply.md.tmpl
  • templates/report.md.tmpl
  • templates/brief-section-verification-report.md.tmpl
  • templates/brief-section-verification-summary.md.tmpl
  • templates/brief-section-failure-context.md.tmpl
  • templates/brief-section-manual-acceptance.md.tmpl

Variable syntax is . Replace literally; do not introduce conditional logic in templates.

Constraints

  • Do NOT skip recording Verify Anchor SHA — it is required by the protocol (v1.4 § Verify Anchor) and required in every event.
  • Do NOT modify Attempt Count. Only run increments it.
  • Do NOT auto-pass a task when no verification tooling is found — route to 6.D instead.
  • Do NOT record verify_passed before code publication has succeeded; on push failure go to 6.E.
  • Do NOT fix the failure here — hand Failure Context back to run for self-correction.
  • Do NOT stage or commit .mino/briefs/ or .mino/locks/ — these are local workflow cache.
  • Do NOT invent fields in the YAML events; the schema is fixed by workflow-state-contract.md.
  • Do NOT overwrite Open Questions / Warnings in the brief; replace target sections only.
  • Keep narrative summaries compact; the structured event is the machine source of truth.
  • Do NOT push --force, reset --hard past the remote tip, rebase or amend any pushed commit; use git revert to undo published work (see protocol § Multi-Agent Git Hygiene).
  • Do NOT treat gh issue edit label-sync failures as fatal; the local event yml is authoritative.
  • Do produce a verification report at .mino/reports/issue-{N}/report.md whenever evidence is substantive (outcomes 6.A, 6.C, 6.D).
  • Do NOT include local report paths (.mino/reports/...) in GitHub comments. Promoted docs/ paths are fine because they resolve as repo URLs.
  • Do NOT amend the run commit when promoting; create a separate docs commit before the verify push.
  • Do honor .mino/config.yml > report.promotion: never to disable promotion.
  • When in doubt about promotion: do NOT promote.
  • Audible comments are rendered exclusively from comment-*.md.tmpl files. NEVER inline event yml into a comment.
  • Commit auto-link: include the commit URL in audible comments when verify_anchor_sha (or code_ref) is known.
  • Do NOT post a GitHub comment for verify_passed — silent in v1.10.
  • Do post audible comments for all other verify outcomes.
  • Do NOT post verify_passed as a status comment. The reply channel (Step 7) is the only audible surface for convergence outcomes.
  • Do NOT echo manual_verifier_note verbatim to GitHub. Synthesise into the reply template.
  • Do NOT retry a failed reply post. Local report is the durable artifact.

References

Released under the MIT License.