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:
- discover repositories from a local workspace or
gh repo list; - exclude configurable name patterns such as
*-agentand*-agents; - clone or create isolated working copies;
- prepare
.envfrom.env.example,.env.doctorand safe CI-prefixed variables; - execute only declared Makefile targets;
- classify failures and generate stable fingerprints;
- apply one controlled automatic repair: add a missing
doctor-healthtarget; - re-run validation;
- validate explicitly configured repository pairs;
- create dry-run draft PR or issue records with deduplication;
- write
reports/latest.mdandreports/latest.json.
The system never merges Pull Requests.
Responsibilities
ifuri-doctor is responsible for:
- discovering repositories in the
if-uriorganization; - 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:detectedandrepair:pending; - writing the agent YAML contract, acceptance criteria, logs and reproduction command;
- preserving a shared
correlation_idfor 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-agentorvalidator-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-doctorrepository. - GitHub Actions runs Doctor on a schedule or on demand and updates Issues and Project fields.
if-uri/ifuri-doctoris 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ifuri_doctor-0.3.0.tar.gz.
File metadata
- Download URL: ifuri_doctor-0.3.0.tar.gz
- Upload date:
- Size: 56.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e700b03bf1d997b2ac5351d36a6b6cd6680cd304c5056ced422ad645088c5f71
|
|
| MD5 |
cea39dc7c2f6a7ef1861e0597dd2291b
|
|
| BLAKE2b-256 |
d3ce1aacd4c3c9d6100bdd93c7e0cf4b371cae4e76afaa9bbaa793e0c8715628
|
File details
Details for the file ifuri_doctor-0.3.0-py3-none-any.whl.
File metadata
- Download URL: ifuri_doctor-0.3.0-py3-none-any.whl
- Upload date:
- Size: 53.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d80ed10a8f142dafccb126019d4a3363996602db27c2456535f03d1cfdd8cc87
|
|
| MD5 |
9515328772da240ccdd7996492cce205
|
|
| BLAKE2b-256 |
ad5b3e7fb720ae43ec38af0d1257ff515bbe38add539051316fe298d54fe3588
|