Skip to content

mino-checkup

Workflow Health Mechanic

Diagnose environment readiness, skill wiring, brief freshness, and source-task alignment. Record manual acceptance, aggregate composite parents, and finalize verified tasks. Repair safely, report what cannot be repaired, never silently mutate human content.

Modes

The user may specify a mode. Default is check.

  • pre-flight <issue> — validate environment for one task before /mino-run executes. Halts on broken environment, never advances state.
  • check — read-only inspection of .mino/, skill ecosystem, briefs. No mutation.
  • repair — fix missing wiring and auto-repairable issues (re-create missing dirs, refresh stale brief metadata).
  • reconcile [<issue>] — compare local briefs against source tasks; replay valid events to rebuild brief state; detect external close.
  • accept <issue> — record human acceptance for a task currently in pending_acceptance. Publishes any local-only code first.
  • aggregate <issue> — finalize a composite / container task once all required children are done.
  • finalize <issue> — bind verified-completion evidence and transition to done. Invoked by the Loop Mode Decision Function (see iron-tree-protocol.md) when verify produced pass + verified but the task is not yet done.

Pre-flight gate

pre-flight is a stable interface called by /mino-run before it acquires the lock. It is the only mode that must never mutate state beyond writing one structured event when blocking.

Steps:

  1. Confirm .mino/ and .mino/briefs/ exist; gh is authenticated; the brief for <issue> exists and is well-formed.
  2. Working tree cleanliness — the workflow commits via git add -A -- ':!.mino/briefs/' ':!.mino/locks/' ':!.mino/run.lock'. Any pre-existing uncommitted change outside that allow-list would be silently bundled into the run commit. Treat as blocking:
    • Run git status --porcelain -- ':!.mino/briefs/' ':!.mino/locks/' ':!.mino/run.lock'.
    • If non-empty, the environment is broken: list the offending paths and tell the user to commit, stash, or revert them before re-running /mino-run.
  3. Run task-specific dependency checks (e.g. node_modules present, toolchain available, secrets present).
  4. If everything is healthy, print pre-flight ok issue-{N} and exit 0. Do NOT post any comment or modify any file.
  5. If something is broken:
    • Set Workflow Entry State: blocked in the brief.
    • Render templates/event-checkup-preflight-blocked.yml.tmpl with the next sequence number and post it as an issue comment. Set the blocking_check placeholder to a short kebab-case identifier (e.g. dirty-working-tree, gh-not-authenticated, missing-dependency) so downstream consumers can distinguish causes.
    • Exit non-zero so /mino-run halts before acquiring the lock.

Check / Repair

Both modes do the inspection below. check is read-only; repair may auto-repair the items explicitly marked safe.

  1. Core checks:
    • .mino/ and .mino/briefs/ exist (repair may mkdir -p).
    • gh authenticated.
    • Project- or global-scope skills directory accessible.
  2. Skill ecosystem scan:
    • Discover installed skills across scopes: .claude/skills/, .agents/skills/, ~/.claude/skills/, ~/.agents/skills/.
    • Verify the four core skills are present: task, run, verify, checkup.
    • Report complementary skill coverage and gaps.
  3. Brief freshness (repair only):
    • For each brief, ensure required sections exist per brief-contract.md. Missing sections may be appended with empty placeholders. Existing human content is never overwritten.

Neither mode mutates any workflow event or transitions any task. Print a concise health report at the end.

Reconcile

reconcile (or reconcile <issue> for one task) refreshes brief state from canonical evidence and detects out-of-band activity.

  1. List local briefs: ls .mino/briefs/issue-*.md.
  2. List source tasks: gh issue list --state all --limit 200.
  3. For each brief in scope:
    • Sources of truth, tried in order:
      1. Local events — glob .mino/events/issue-{N}/*.yml. Parse yml blocks, keep those whose task_key and approved_revision match the brief. This is the primary source.
      2. Terminal summary comment (fallback for done issues when local log is missing, pre-v1.12 only) — pull all issue comments, pick the one whose body matches the pre-v1.12 signature (🏁 Issue ... done with inline YAML blocks). v1.12+ done comments are not parseable as a recovery source.
      3. Legacy per-event comments (fallback for pre-v1.10 issues) — pull issue comments, parse every yml event block directly.
    • If primary yields events, use only primary. Fallbacks are invoked only when primary is empty.
    • If multiple sources are present and their event chains diverge (same sequence, different event), halt with checkup_reconcile_sequence_gap_detected and require human intervention.
    • Sequence gap detection: list the sequence values of every parsed event. If they are not a contiguous run starting at 1, treat the gaps as missing canonical evidence:
      • Replay events up to the highest contiguous sequence (max(sequences) such that 1..max are all present); ignore events past the first gap because their state assumes evidence that no longer exists.
      • Render templates/event-checkup-reconcile-sequence-gap.yml.tmpl with found_sequences, missing_sequences, and highest_replayable_sequence, write to .mino/events/issue-{N}/{next_seq:04d}-checkup-reconcile-sequence-gap.yml, then post as a short audible comment (heading: ⚠️ checkup reconcile — sequence gap on #{N}, plus a one-line description). Do NOT inline the YAML; the local event file is the authoritative record.
      • Do NOT advance the workflow past Workflow Entry State: blocked until the operator reviews the gap (e.g. recovers the deleted comment, or runs /mino-task to re-publish a fresh approved_revision).
    • Replay events in ascending sequence order to rebuild the canonical workflow state. Surgically replace Workflow State, Pass/Fail Outcome, and Completion Handoff sections from the resulting state. Never overwrite Open Questions / Warnings.
    • External close detection: if the source issue is closed but no checkup_done event exists for the active approved revision:
      • Set Workflow Entry State: blocked in the brief.
      • Render templates/brief-section-external-event.md.tmpl (event=issue_closed, source=github, action=Investigate the close reason and either re-open the issue with /mino-task or accept the close as final) and surgically replace the External Event section.
      • Render templates/event-checkup-reconcile-external-close.yml.tmpl, write to .mino/events/issue-{N}/{next_seq:04d}-checkup-reconcile-external-close.yml, then post as a short audible comment (heading: ⚠️ external close detected — #{N}, body: one sentence stating the action the operator must take). Do NOT inline the YAML.
      • Do NOT mark the task done. Do NOT auto-sync brief to a completed state.
  4. Emit a Pending Acceptance subsection in the report listing every task still in pending_acceptance with the next manual action.

Accept

accept <issue> records human acceptance for a task currently in pending_acceptance.

Optional note: invocation may include free-form text after the issue ref (/mino-checkup accept #1842 在你的项目里 ...). If present, capture as manual_verifier_note and append it verbatim to the brief's Manual Acceptance section under a ### Accept Note subsection.

  1. Confirm Workflow Entry State: pending_acceptance. If not, halt and report.
  2. Publish any local-only code first:
    • Stage all changes except workflow-local cache:
      bash
      git add -A -- ':!.mino/briefs/' ':!.mino/locks/' ':!.mino/run.lock'
    • If nothing is staged, skip to step 3 with Code Ref: not_applicable, Code Publication State: not_applicable.
    • Otherwise commit with [run] #{N}: {concise change summary} and git push.
    • Capture the resulting HEAD SHA as Code Ref. Set Code Publication State: published.
    • On commit or push failure: do NOT record acceptance. Keep Current Stage: verify, Next Stage: checkup, Workflow Entry State: pending_acceptance, Code Publication State: local_only. Render templates/brief-section-publication-failure.md.tmpl into the Failure Context section. Render templates/event-checkup-accept-publication-failed.yml.tmpl and post as comment. Stop.
  3. Render templates/brief-section-acceptance-summary.md.tmpl with reviewer name, ISO timestamp, code ref, and notes; surgically replace the Verification Summary section.
  4. Surgically update brief metadata:
    • Current Stage: checkup
    • Next Stage: done
    • Workflow Entry State: ready_to_start
    • Pass/Fail Outcome: pass
    • Completion Basis: accepted
    • Code Ref: and Code Publication State: per step 2
  5. Render templates/event-checkup-accept-recorded.yml.tmpl and write to .mino/events/issue-{N}/{next_seq:04d}-checkup-accept-recorded.yml. Silent: do NOT post a GitHub comment.
  6. Remove the pending-acceptance label from the issue.
  7. Proceed to Finalize (below).

Aggregate

aggregate <issue> finalizes a composite or container parent.

  1. Confirm Classification is composite or container.
  2. Resolve required child task keys from the brief Work Breakdown and Dependencies sections. Confirm every child brief has Pass/Fail Outcome: pass and Current Stage: done.
  3. Render templates/brief-section-aggregate-summary.md.tmpl with the children evidence list (each line: - {child_task_key} (issue-{N}): {completion_basis} @ {code_ref_or_not_applicable}); surgically replace the Verification Summary section.
  4. Surgically update brief metadata:
    • Current Stage: checkup
    • Next Stage: done
    • Workflow Entry State: ready_to_start
    • Pass/Fail Outcome: pass
    • Completion Basis: aggregated
    • Code Publication State: not_applicable
    • Code Ref: not_applicable
  5. Render templates/event-checkup-aggregate-recorded.yml.tmpl and write to .mino/events/issue-{N}/{next_seq:04d}-checkup-aggregate-recorded.yml. Silent: do NOT post a GitHub comment.
  6. Proceed to Finalize (below).

Finalize

finalize <issue> (also entered automatically by accept and aggregate) binds completion evidence and transitions the task to done.

  1. Read the brief. Refuse to proceed unless ALL of:

    • Pass/Fail Outcome: pass
    • Completion Basis ∈ {verified, accepted, aggregated}
    • Code Publication State ∈ {published, not_applicable}
    • Code Ref is a SHA when Code Publication State: published, else not_applicable If any check fails, halt and report which precondition is missing. Do NOT mutate state.
  2. Surgically update brief metadata:

    • Current Stage: done
    • Next Stage: none
  3. Record checkup_done locally — render templates/event-checkup-done.yml.tmpl with the bound completion_basis, code_ref, code_publication_state, and write to .mino/events/issue-{N}/{next_seq:04d}-checkup-done.yml.

  4. Reply Dispatch (replaces the deprecated v0.6.2 summary comment):

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

    • If never: set reply_posted = null, skip to step 5.
    • If always: render templates/comment-reply.md.tmpl and post.
    • If auto:
      • Check whether a reply was already posted in this loop iteration (scan .mino/events/issue-{N}/ for any prior event with reply_posted non-null within the current loop window). If yes: set reply_posted = null, skip to step 5 (no duplicate convergence reply).
      • Else if the latest verify event has promoted_doc != null OR the brief's Manual Acceptance contains a ### Accept Note subsection with actionable prose: render and post.
      • Else: set reply_posted = null, skip to step 5.

    When rendering, synthesise variables from:

    • The latest verify_* event (for promoted_docdocs_link_line_or_empty)
    • The brief's report at .mino/reports/issue-{N}/report.md
    • The brief's Accept Note subsection (if present)

    Apply the template's HTML-comment variable rules. Post via gh issue comment {N} --body-file <rendered>. On failure: log reply_post_failed: <reason>, set reply_posted = null, do NOT retry.

    Then patch the event-checkup-done.yml file written in step 3 to set reply_posted to the captured URL or null.

  5. Issue closure:

    • If brief Close On Done: auto and the issue is still open: gh issue close {N} --reason completed.
    • If Close On Done: manual: leave the issue open. Convey the close instruction via ONE of:
      • If step 4 posted a reply (reply_posted != null): append a final line to the reply body BEFORE posting it (or, if already posted, this is a known minor lag — the brief still carries the instruction).
      • If step 4 was silent: write the close instruction to the brief's Workflow State section as Manual Close: gh issue close {N} --reason completed. Never post a standalone manual-verification prompt as a status comment.
    • If the issue was already closed externally before finalize ran, do NOT re-open and do NOT re-close. Note the pre-existing closure in the report.
  6. 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.

Sequence numbers

Events posted by checkup share the same sequence space as task / run / verify events. Before writing any event, fetch the current max sequence for the active approved_revision from the local event log (ls .mino/events/issue-{N}/ + parse filename prefixes) and use max + 1. GitHub comments are no longer the sequence source.

Templates

All event YAML and brief sections come from templates/. Render via literal substitution; no conditionals.

  • Events: event-checkup-preflight-blocked.yml.tmpl, event-checkup-accept-recorded.yml.tmpl, event-checkup-accept-publication-failed.yml.tmpl, event-checkup-aggregate-recorded.yml.tmpl, event-checkup-done.yml.tmpl, event-checkup-reconcile-external-close.yml.tmpl, event-checkup-reconcile-sequence-gap.yml.tmpl.
  • Reply: comment-reply.md.tmpl — sole rendering source for finalize convergence.
  • Deprecated (kept on disk for rollback, remove in v0.7.0): the old summary template (comment-checkup-*.md.tmpl).
  • Brief sections: brief-section-acceptance-summary.md.tmpl, brief-section-aggregate-summary.md.tmpl, brief-section-external-event.md.tmpl, brief-section-publication-failure.md.tmpl.

Brief edits are always surgical: replace only the named section header and its body up to the next ## header. Never touch Open Questions / Warnings, Source, or any other section not listed above.

Constraints

  • Do NOT create issues or re-open closed issues.
  • Do NOT mark a task done outside finalize (or via accept / aggregate which delegate to finalize).
  • Do NOT mark a task done during pre-flight, check, repair, or reconcile.
  • Do NOT record manual acceptance against an unpublished code state.
  • Do NOT bypass pre-flight failures — if the environment is broken, block execution.
  • Do NOT close issues when Close On Done: manual.
  • Do NOT stage or commit .mino/briefs/, .mino/locks/, or .mino/run.lock — these are local workflow cache and must not enter git history.
  • Do NOT overwrite human-authored sections (Open Questions / Warnings, free-form notes inside Acceptance Criteria, etc.).
  • Do NOT auto-sync a brief to done after detecting an external close — record External Event and stop.
  • 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 post individual comments for checkup_accept_recorded or checkup_aggregate_recorded — silent in v1.10.
  • Do NOT post a checkup_done status comment. Convergence reaches the user via Reply Dispatch (Finalize step 4) or remains silent. The local .mino/events/issue-{N}/ tree is the authoritative log.
  • Do NOT post a standalone manual-verification prompt as a comment. Manual close instructions live in the reply (when one is posted) or in the brief Workflow State section.
  • Do NOT echo manual_verifier_note / Accept Note verbatim to GitHub.
  • Do NOT retry a failed reply post.
  • Do NOT derive sequence from issue comments; read from .mino/events/issue-{N}/ filenames.

References

Released under the MIT License.