Skip to main content

Central diagnostic, validation and repair runner for if-uri repositories.

Project description

ifuri-doctor

ifuri-doctor is the central MVP diagnostic, validation and repair runner for GitHub repositories in the if-uri organization.

The first version intentionally focuses on a safe, testable workflow:

  1. discover repositories from a local workspace or gh repo list;
  2. exclude configurable name patterns such as *-agent and *-agents;
  3. clone or create isolated working copies;
  4. prepare .env from .env.example, .env.doctor and safe CI-prefixed variables;
  5. execute only declared Makefile targets;
  6. classify failures and generate stable fingerprints;
  7. apply one controlled automatic repair: add a missing doctor-health target;
  8. re-run validation;
  9. validate explicitly configured repository pairs;
  10. create dry-run draft PR or issue records with deduplication;
  11. write reports/latest.md and reports/latest.json.

The system never merges Pull Requests.

Responsibilities

ifuri-doctor is responsible for:

  • discovering repositories in the if-uri organization;
  • detecting build, test, runtime, dependency, configuration, documentation and CI problems;
  • confirming that a problem is still reproducible before opening work for repair;
  • creating or updating deduplicated GitHub Issues with doctor:detected and repair:pending;
  • writing the agent YAML contract, acceptance criteria, logs and reproduction command;
  • preserving a shared correlation_id for downstream agents;
  • reporting scan results and dry-run operations.

ifuri-doctor is not responsible for:

  • applying broad code changes across target repositories;
  • approving or merging Pull Requests;
  • replacing repair-agent or validator-agent.

Repository Layout

src/ifuri_doctor/
  cli.py          command line entrypoint
  config.py       profiles, timeouts and integration config
  discovery.py    local and GitHub repository discovery
  sync.py         isolated checkout/worktree preparation
  envfile.py      .env preparation and secret masking
  makefile.py     declared Makefile target validation and execution
  classifier.py   failure categories
  fingerprint.py  error normalization and fingerprints
  repair.py       controlled safe repairs
  integration.py  explicit pair validation
  github.py       dry-run PR/issue creation with dedupe store
  report.py       Markdown and JSON reports
tests/
  test_doctor_mvp.py

Local Example

python -m pip install -e ".[test]"
python -m pytest -q
python -m ifuri_doctor --config doctor.example.json --workspace ../fixtures --profile development

Reports are written to:

reports/latest.md
reports/latest.json

Development Profile

{
  "profile": "development",
  "profiles": {
    "development": {
      "schedule": { "light_scan_minutes": 12, "full_scan_minutes": 36 },
      "timing_multiplier": 0.2
    }
  },
  "timeouts": {
    "test": { "production_seconds": 600, "development_seconds": 120, "minimum_seconds": 60 }
  }
}

Production Profile

{
  "profile": "production",
  "profiles": {
    "production": {
      "schedule": { "light_scan_minutes": 60, "full_scan_minutes": 180 },
      "timing_multiplier": 1.0
    }
  }
}

Pair Validation Example

{
  "integrations": [
    {
      "id": "examples-with-urirun",
      "provider": {
        "repository": "if-uri/urirun",
        "start": "make doctor-start",
        "health": "make doctor-health"
      },
      "consumer": {
        "repository": "if-uri/examples",
        "test": "make doctor-integration-test"
      },
      "environment": { "URIRUN_URL": "http://urirun:8080" },
      "timeout_seconds": 600
    }
  ]
}

Example Failure, Repair and Deduplication

If a repository has a Makefile but lacks doctor-health, Doctor records a SKIPPED_UNDECLARED step with a fingerprint such as doctor:0123abcd....

The MVP repair appends:

.PHONY: doctor-health
doctor-health:
	@echo "doctor-health: default MVP healthcheck OK"

Doctor then re-runs all declared MVP targets. If they pass, it creates one dry-run draft PR record in .doctor-state/items.json. A second run finds the same fingerprint, updates last_seen, and reuses the existing item instead of creating a duplicate.

If a failure is not safely repairable, Doctor creates one issue record using the same dedupe path.

GitHub Mode

Set "source": "github" to discover repositories through GitHub CLI:

gh repo list if-uri --limit 1000 --json nameWithOwner,sshUrl,url,isArchived,defaultBranchRef

The MVP keeps PR and issue creation in dry-run state records by default. This makes local validation safe and avoids writing secrets or noisy duplicate issues while the repair policy is still being expanded.

Issue, Project, Actions

  • GitHub Issue is one ticket describing one detected Doctor problem.
  • GitHub Project is the organization board that organizes tickets. It is not the if-uri/ifuri-doctor repository.
  • GitHub Actions runs Doctor on a schedule or on demand and updates Issues and Project fields.
  • if-uri/ifuri-doctor is only the application repository.

The target organization Project is:

Owner: if-uri
Title: Tickets

GitHub Auth

GitHub Projects require a token with project access. Refresh local gh auth with:

gh auth refresh -s project
gh auth refresh -s project -s read:project -s repo -s read:org
gh auth status

Doctor detects missing project scope and prints the refresh command. It keeps local diagnostics running when Project writes are unavailable.

Project Commands

gh project list --owner if-uri
gh project create --owner if-uri --title "Tickets"
gh project link PROJECT_NUMBER --owner if-uri --repo if-uri/ifuri-doctor

ifuri-doctor project init
ifuri-doctor project inspect
ifuri-doctor project sync
ifuri-doctor project link

project init finds or creates the Tickets Project, checks or plans required fields, links it to if-uri/ifuri-doctor, and stores a local cache. In dry-run it prints planned operations such as:

DRY RUN: would create project if-uri/Tickets
DRY RUN: would link project to if-uri/ifuri-doctor
DRY RUN: would create project field Agent Status

Required Project fields include Agent Status, Repository, Failure Type, Severity, Fingerprint, Last Seen, Doctor Result, Pull Request, and Merge Readiness.

Issues and Deduplication

Doctor stores fingerprints in Issue bodies as hidden comments:

<!-- ifuri-doctor:fingerprint=doctor:... -->

Before creating an Issue it checks GitHub and the local cache. Existing Issues are reused, closed recurring Issues are reopened, and Project fields such as Last Seen and Doctor Result are updated idempotently.

Agent Handoff Contract

ifuri-doctor is the only diagnostic repository. It hands work to if-uri/repair-agent by creating Issues in if-uri/ifuri-doctor with the initial labels:

doctor:detected
repair:pending

Every Issue contains a machine-readable YAML block:

source_agent: ifuri-doctor
target_repository: owner/repository
problem_type: ci | tests | build | dependency | configuration | documentation | runtime | other
severity: critical | high | medium | low
detected_at: ISO-8601
deduplication_key: stable-problem-key
correlation_id: ifuri-doctor-YYYYMMDD-repository-key
failing_command: command
workflow_run_url: link
commit_sha: SHA

The deduplication_key is also stored in hidden comments so repeated scans update or reuse the existing Issue instead of opening duplicates. The same correlation_id must appear in repair-agent logs, repair branches, Pull Requests, validator-agent reports and merge comments.

Required shared configuration names:

GITHUB_ORG=if-uri
DOCTOR_REPOSITORY=ifuri-doctor
REPAIR_REPOSITORY=repair-agent
VALIDATOR_REPOSITORY=validator-agent
ACTIVE_TIMEZONE=Europe/Warsaw

Optional secrets and variables used by the agent system are OPENROUTER_API_KEY, OPENROUTER_MODEL, GH_APP_ID, GH_APP_PRIVATE_KEY, GH_APP_INSTALLATION_ID, NOTIFICATION_EMAIL, ACTIVE_HOURS_START and ACTIVE_HOURS_END.

Codex

Codex execution is configurable:

{
  "codex": {
    "enabled": true,
    "command": "codex",
    "timeout_seconds": 1800,
    "dry_run": true
  }
}

Doctor passes repository, ticket, fingerprint, failure type, logs, reproduce command, test results, integration pairs, constraints, and expected output. Codex must work in an isolated branch/worktree. Diff validation rejects unsafe changes such as removed tests, skip/xfail, disabled linting, removed healthchecks, secrets, branch protection changes, unrelated files, and ignored failures.

Pull Requests

Successful repairs create draft PRs only after revalidation:

gh pr create --repo OWNER/REPO --draft --title "..." --body-file PR_BODY.md

Doctor never merges PRs. It deduplicates by fingerprint, branch, PR body, and local cache.

Inspect merge readiness with:

ifuri-doctor inspect-pr --repo if-uri/example --pr 123

Possible results are READY_TO_MERGE, BLOCKED_BY_CHECKS, BLOCKED_BY_CONFLICTS, BLOCKED_BY_REVIEW, DRAFT, and UNKNOWN.

Scan and Schedule

ifuri-doctor scan --mode light --profile development
ifuri-doctor scan --mode full --profile development
ifuri-doctor schedule --profile development
ifuri-doctor schedule --profile production

Production uses a light scan every 60 minutes and a full scan every 180 minutes. Development uses exactly one fifth of those times: 12 and 36 minutes, with timing multiplier 0.2 and safe minimum timeouts.

Light scan covers repository list, PRs, workflows, Issues, Project and ticket statuses. Full scan performs clone/fetch, .env, Makefile validation, build, lint, test, start, healthcheck, pair integrations, Codex planning, revalidation, and PR or ticket creation.

GitHub Actions

The default ${{ secrets.GITHUB_TOKEN }} is not enough for organization Projects. Create a PAT or GitHub App token and store it as:

gh secret set PROJECT_TOKEN --repo if-uri/ifuri-doctor

The workflow maps it to:

env:
  GH_TOKEN: ${{ secrets.PROJECT_TOKEN }}

Minimal workflow permissions are:

permissions:
  contents: write
  issues: write
  pull-requests: write
  checks: read
  actions: read

Project access still comes from the separate PAT or GitHub App token.

Dry Run

Dry-run never creates Projects, Issues, Project items, Codex runs, pushes, PRs, or status updates. It reports exact planned operations:

DRY RUN: would create issue
DRY RUN: would add issue to project
DRY RUN: would set Agent Status=Ready for repair
DRY RUN: would run Codex
DRY RUN: would create draft PR

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ifuri_doctor-0.2.0.tar.gz (52.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ifuri_doctor-0.2.0-py3-none-any.whl (51.3 kB view details)

Uploaded Python 3

File details

Details for the file ifuri_doctor-0.2.0.tar.gz.

File metadata

  • Download URL: ifuri_doctor-0.2.0.tar.gz
  • Upload date:
  • Size: 52.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for ifuri_doctor-0.2.0.tar.gz
Algorithm Hash digest
SHA256 2258662922a8e68196d796955aba7489c7aa337ab545ea220c2c86c358eee436
MD5 3d60a9bcb8e5abc1bc7662d907b133fa
BLAKE2b-256 221629516eb030d2308cae6e511cac0b2b2aec37918ba71e388665bd6f883c5e

See more details on using hashes here.

File details

Details for the file ifuri_doctor-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: ifuri_doctor-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 51.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for ifuri_doctor-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 14e182691511a530e1361c7763603be9a583090c70ea1598ef3bf1fe57b60e15
MD5 1c8a3d5b893aabad7deb6a4a933d0c61
BLAKE2b-256 715becdc3b99c45415266b681f5341c0502adba2c0dd7f6ff70c77e74b351c56

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page