Skip to content

Reconciliation

How GitWire verifies that its actions are still in effect on GitHub.

Overview

GitWire's prove pillar requires ongoing verification. When GitWire adds a label, approves a PR, or creates a patch, it needs to confirm later that the action's effect persists. This is reconciliation.

The reconciliation system has two components:

  1. Periodic scan — the reconciliation worker checks all succeeded actions older than 6 hours
  2. Drift log — every check is recorded, whether drift is found or not

When reconciliation runs

TriggerFrequencyWhat it does
AutomaticEvery 6 hoursScans all eligible actions
On startup5 minutes after bootInitial scan
ManualPOST /api/actions/:id/reconcileSingle action

Reconciliation flow

mermaid
graph TD
    A[Succeeded action<br/>older than 6h] --> B[Fetch current state from GitHub]
    B --> C{Effect still present?}
    C -->|Yes| D[Mark reconciled<br/>status: confirmed]
    C -->|No| E[Mark reconciled<br/>status: drifted]
    C -->|Error| F[Skip<br/>assume ok]
    E --> G[Log to reconciliation_log]
    D --> G

What gets checked

Labels (add-label / remove-label)

js
// Fetch current labels from GitHub
const labels = await octokit.request("GET /repos/{owner}/{repo}/issues/{number}/labels");

// For add-label: expect the label to be present
// For remove-label: expect the label to be absent
const expected = action.action_type === "add-label" ? "present" : "absent";
const actual = labels.some(l => l.name === labelName) ? "present" : "absent";
const drifted = expected !== actual;

PR state (create-patch-pr)

js
const pr = await octokit.request("GET /repos/{owner}/{repo}/pulls/{number}");

// Patch PRs: merged is success, closed-without-merge is drift
if (pr.merged) return { drifted: false };
if (pr.state === "closed" && !pr.merged) return { drifted: true };
// Still open — not drifted yet

Reviews (approve)

js
const reviews = await octokit.request("GET /repos/{owner}/{repo}/pulls/{number}/reviews");

// Check if GitWire's approval is still present
const gitwireApproved = reviews.some(
  r => r.user?.login?.includes("gitwire") && r.state === "APPROVED"
);
const drifted = !gitwireApproved;

Comments (add-comment)

Comments are always confirmed — they're low-stakes and can't be meaningfully "drifted."

Drift log

Every reconciliation check is recorded in action_reconciliation_log:

FieldExampleDescription
check_typelabelWhat was checked
expectedpresentWhat we expected to find
actualabsentWhat we actually found
driftedtrueWhether they differ
checked_at2026-05-25T12:00:00ZWhen the check ran

Drift examples

ActionCheckExpectedActualDrifted?
add-label:ci-healedLabel on issue #42presentabsent
create-patch-prPR #100 statemergedclosed_without_merge
approveReview on PR #55APPROVEDAPPROVED
add-label:triagedLabel on issue #10presentpresent

No auto-remediation

GitWire does not automatically re-apply drifted actions. Drift is surfaced for human review through:

  • The Actions dashboard page — drifted actions show reconciliation_status: "drifted"
  • The reconciliation log — full history of every check
  • Future: Telegram notifications for drifted actions

This is intentional. Drift might be caused by:

  • A maintainer intentionally removing a label
  • A PR being closed in favor of a different approach
  • A review being dismissed during a re-review

Auto-remediation would fight against human decisions. GitWire reports, humans decide.

Configuration

Reconciliation runs on a fixed schedule (every 6 hours). There is no per-repo configuration.

SettingDefaultNotes
Scan interval6 hoursConfigured in index.js
Max actions per scan100Prevents API rate limit exhaustion
Max age for eligibility6 hoursOnly succeeded actions older than this are checked

See also

Released under the MIT License.