Skip to main content

diagit

AI Cost Tracking

PyPI Version Python License AI Cost Human Time Model

  • 🤖 LLM usage: $0.4305 (15 commits)
  • 👤 Human dev: ~$727 (7.3h @ $100/h, 30min dedup)

Generated on 2026-08-10 using openrouter/qwen/qwen3-coder-next


diagit is a read-only-by-default auditor for a fleet of Git repositories laid out as ROOT/owner/repository, for example /home/tom/github/*/*.

It records immutable protobuf events, builds a disposable SQLite CQRS read model, and exposes a small allowlisted diagit:// process URI catalog. It never fetches, checks out, commits, pushes, or repairs a repository during an audit. Separate control plans require a digest-bound authority grant and independent read-back validation.

Install and run

python -m pip install -e '.[test]'
diagit audit --root ~/github
diagit audit --root ~/github --inventory subactor-repositories.v1.json
diagit audit --root ~/github --organization subactor \
  --repository 'subactor/*-agent' --exclude-repository 'subactor/*-worktree'
diagit audit --root ~/github/semcod --repository todo2code
diagit audit --root ~/github/semcod --layout organization
diagit query summary
diagit query findings --severity SEVERITY_CRITICAL
diagit priority readings --document /path/to/organization.v1.json
diagit query repo subactor/core
diagit diagnostics list
diagit diagnostics show DIRTY_WORKTREE
diagit uri 'diagit://fleet/query/summary'
diagit remote audit --organization subactor \
  --inventory subactor-repositories.v1.json

# Worktree set of a repository: overlap, leftovers, dead registrations
diagit query findings --severity SEVERITY_ERROR
diagit plan worktrees --output-dir ./plans --advisory
diagit apply ./plans/<plan>.json --authority-file ./grant.json --confirm-apply
diagit remote summary --organization subactor
diagit remote findings --organization subactor --severity SEVERITY_ERROR
diagit uri 'diagit://github/subactor/query/findings?code=PR_CHECKS_FAILED'
diagit plan governance --organization subactor --output governance.json
diagit plan repairs --organization subactor --output-dir repair-plans
diagit plan fleet-repairs --organization subactor \
  --repository 'subactor/*-agent' \
  --exclude-repository 'subactor/*-worktree' \
  --code OPENROUTER_APP_IDENTITY_MISSING --output-dir openrouter-repairs
diagit watch --source local --root ~/github --layout fleet \
  --organization subactor --organization wellmanifest \
  --interval-seconds 30 --max-cycles 0 --output-dir watch-plans
diagit watch --source github --organization subactor \
  --interval-seconds 60 --max-cycles 1 --output-dir remote-watch-plans
diagit plan governance --organization legacy-org \
  --rename-default-to-main --archive-unmerged --output governance.json
diagit onedev status \
  --onedev-password-file /path/to/onedev-admin-password
diagit onedev monitor \
  --onedev-password-file /path/to/onedev-admin-password
diagit forge audit --max-items 1000
diagit forge recommend --require actions --require projects \
  --visibility private --prefer-self-managed
diagit grammar
diagit dsl --expression '```diagitdsl
QUERY SUMMARY
```'
diagit shell
diagit serve --root ~/github --bind 127.0.0.1 --port 8765

The default state directory is $XDG_STATE_HOME/diagit, or ~/.local/state/diagit. Override it with --state-dir or DIAGIT_STATE_DIR.

An audit root may be the fleet directory (ROOT/owner/repository) or one organization directory (ROOT/repository). Repository selectors containing / match the canonical owner/repository ID; selectors without / match the bare repository name. Both forms accept shell-style globs.

--layout auto is the default. Use --layout fleet or --layout organization when a root contains both direct worktrees and organization directories. A selected candidate whose Git marker cannot be read remains visible as a typed PROBE_FAILED result instead of disappearing from audit coverage.

A fleet root also includes one extra grouping level under a recognized directory name (projekty, projects, repos, or repositories), for example ROOT/owner/projekty/repository, when that directory is not itself a Git worktree. The repository identity stays owner/repository, matching the GitHub remote, so control plans and OneDev handoff keep a two-segment ID. --layout organization still means only direct worktrees of that root.

Fleet audits normalize common HTTPS, SSH, and SCP-like origin URLs and add two cross-repository layout findings:

Code Meaning
REMOTE_PATH_MISMATCH The owner/repository from origin differs from the canonical local path.
DUPLICATE_REMOTE_CHECKOUT Multiple independent local checkouts reference the same normalized origin.

Registered linked worktrees are collapsed by their common Git directory and do not produce either finding merely because their checkout path differs.

diagit watch is the bounded near-real-time mode. It repeats a local or GitHub audit, writes one cycle directory, and prepares only repair plans backed by registered delegable diagnostics. --max-cycles 0 runs until interrupted; the default is one cycle so automation must opt in to a long-lived process. Stable findings whose plan was already submitted or validated are reported as deduplicated and are not delegated again. Watch never invents an authority grant or mutates a repository: an operator or authority service must still run diagit apply for the exact plan digest. That handoff invokes the existing OneDev Doctor → Repair → Validator lifecycle.

A desired repository inventory uses diagit.desired-repository-inventory/v1, has an explicit semantic version and content digest, and declares whether its coverage is selected or complete. Selected coverage can report required missing repositories without claiming that every other repository is unmanaged; only complete coverage emits UNMANAGED_REPOSITORY. Remote reconciliation also distinguishes archived-but-required and policy-divergent repositories.

Repair planning adopts the exact merged skills-agent catalog, routing policy, priority profile and executable-task bindings. Every delegable finding must map to one registered operation, governed skill and ready OneDev task. Bootstrap is a separate repository:bootstrap plan with absent base, explicitly declared private visibility, a single-use external grant, and ordered mirror registration, profile validation/application and clean re-audit follow-ups. Diagit never infers public visibility or a destructive action.

diagit onedev monitor keeps a submitted plan pending until OneDev exposes a terminal receipt bound to the exact plan digest, independent Validator identity and exact head, satisfied EQL read-back, and secret-free evidence. A merely closed ticket or stage=done is not accepted as success.

Git stash storage is shared by linked worktrees. A fleet audit groups worktrees by their common Git directory and emits one STASHED_CHANGES warning on the primary, or otherwise deterministic representative, worktree.

Worktree set

git_probe observes one checkout. worktree_probe observes the set of checkouts a repository owns, which is where a whole class of damage lives.

Code Meaning
WORKTREE_OVERLAP Two writer checkouts whose heads git cannot merge.
WORKTREE_SCOPE_OVERLAP Active tickets in sibling worktrees claim overlapping paths without conflictsWith.
WORKTREE_STALE_REGISTRATION A registration whose checkout directory is gone.
WORKTREE_LEFTOVER A linked worktree already merged and clean.
ORPHAN_LOCAL_BRANCH Local branches already contained in the default branch.

Overlap is decided by git merge-tree --write-tree, not by path intersection: two branches usually edit different regions of a file and merge cleanly, and a branch stacked on another shares every path with its own ancestor. A checkout already contained in the default branch with a clean tree is a leftover, not a writer, and is never paired.

Only WORKTREE_STALE_REGISTRATION is repairable, because it is the one class where the effect cannot destroy work — the checkout is already gone. The repair is a control plan like any other: the pruneable set is pinned into the plan, execution refuses if that set moved, and the read-back proves the planned entries went away and every valid registration stayed.

--advisory attaches a SubLLM second opinion to a plan. It is advisory in the strict sense: deterministic checks decide, and a missing package, credential or provider degrades the result to advisory_unavailable with a reason rather than blocking the repair. Install it with pip install -e '.[advisory]'.

Operator service

Running diagit without a subcommand starts the operator service. From ~/github it discovers every organization that contains Git worktrees. From ~/github/<organization> or any repository below it, it limits the initial scope to that organization. The initial local audit starts immediately and reports progress for every completed repository.

In a terminal, the service remains active and accepts single-key shortcuts without Enter:

a  repeat the local audit
r  audit selected GitHub organizations and compile repair planfiles
d  explicitly approve and delegate the prepared plans to OneDev
s  select one organization or the complete detected scope
q  exit cleanly

Delegation requires an additional y confirmation. Diagit then creates a mode-0600, ten-minute authority grant for each exact plan digest and submits only CONTROL_ACTION_SUBMIT_REPAIR; Doctor/Repair/Validator evidence remains mandatory. When stdin is not a TTY, the same bare invocation performs one bounded local audit, prints progress, and exits instead of waiting for input.

Diagnostic registry

Every finding keeps its concise compatibility code, such as DIRTY_WORKTREE, and is enriched from the packaged diagit.diagnostic-registry/v2 catalog with a stable identifier such as DIAGIT-GIT-003, category, severity, error class, retryability, and an optional repair URI. The registry is the source of truth: emitting an unknown code or a severity/message that differs from its definition fails closed.

The four severities have consistent operational meaning: INFO records useful state, WARNING requires planned attention, ERROR blocks the requested invariant, and CRITICAL means the audit or control boundary itself is not trustworthy or available.

Priority readings

Diagit adopts wellmanifest.priority/readings/v1 as a signal producer only. diagit priority readings reads a valid priority JSON document, resolves only allowlisted local diagit://fleet/query/findings producers against the latest completed projection, paginates every findings query, and emits a document- digest-bound readings envelope on stdout. Signals owned by Queue Agent or other producers remain absent, so their declared hold policy applies.

The command never evaluates priorities, selects work, executes producer text, or grants execution authority. Queue Agent remains the planned single ranking adapter and Core remains responsible for readiness and execution gates.

Remote pull requests are classified independently of the generic OPEN_PULL_REQUEST finding. The registry distinguishes green mergeable PRs, failed, pending or missing checks, merge conflicts, unknown mergeability, and drafts stale for at least 30 days. A green unmerged PR is always emitted as PR_GREEN_MERGEABLE. If archive cleanup is requested, the generated plan adds PR_GREEN_REQUIRES_MERGE as a blocker instead of archiving that branch.

Architecture

  • Commands change only the auditor's own state. AuditFleet observes Git repositories and appends AuditRunStarted, RepositoryAudited, and AuditRunCompleted protobuf events.
  • The length-delimited events.pb file is the canonical event store. New Protobuf events form a deterministic SHA-256 chain and retain read compatibility with legacy version 1 history.
  • Queries read a rebuildable SQLite projection (projection.sqlite3).
  • Forge account observations from GitHub, GitLab, Gitea/Forgejo, and Bitbucket are stored as ForgeAccountTwinObserved protobuf events. Their read model ranks providers from visible scopes, repositories, capabilities, visibility, completeness, and self-managed preference; it never reads repository content. The canonical contract and reviewed decision baseline are pinned to uri-twin/uri-twin-forge; Diagit returns that source revision with each audit and recommendation.
  • diagit rebuild recreates the projection solely from stored events.
  • URI processes are explicit adapters to the same command/query handlers; an arbitrary URI can never become a shell command.

The canonical GBNF request language maps to the same CQRS messages as CLI, shell, process URI, and loopback REST. Its Wellmanifest contract binds the grammar, parser, storage schema, examples, command documentation, errors, and critical security pages by SHA-256. See docs/DSL_ARCHITECTURE.md and dsl-manifest.json.

DSL and API

Every DSL request is exactly one fenced statement:

```diagitdsl
QUERY FINDINGS CODE "*" SEVERITY "SEVERITY_ERROR" LIMIT 1000 OFFSET 0
```

LIMIT is deliberately bounded to 1000. Fleet controllers must increment OFFSET until the returned page is shorter than the requested limit; values are never silently truncated.

The REST adapter binds only to loopback and exposes GET /health, GET /v1/grammar, CQRS query routes, bounded command routes, and POST /v1/dsl. It does not expose GitHub control-plan application. The interactive shell accepts the inner statement without Markdown fencing but sends it through the same GBNF parser.

Command help: AUDIT, REBUILD, SUMMARY, FINDINGS, and REPOSITORY.

Error help: DIAGIT-REQUEST-INVALID, DIAGIT-NOT-FOUND, DIAGIT-ROOT-ESCAPE, and DIAGIT-EVENT-INTEGRITY.

Supported URI processes:

diagit://fleet/audit?root=/home/tom/github
diagit://fleet/query/summary
diagit://fleet/query/findings?severity=SEVERITY_WARNING&limit=100
diagit://repository/<owner>/<repo>/query/report
diagit://projection/rebuild
diagit://github/<organization>/audit
diagit://github/<organization>/query/summary
diagit://forge/audit?providers=github,gitlab,gitea,bitbucket&max_items=1000
diagit://forge/query/recommend?requires=actions,projects&visibility=private&prefer_self_managed=true

Governed control plans

Remote audit observations can be compiled into the versioned diagit.control-plan/v1 JSON DSL. Every executable plan embeds a subactor.process-envelope.v2 with all four governed definitions: AQL authority, transport-independent OQL operations, exact URI processes, and EQL expectations. A governance plan closes an open pull request or deletes an extra branch only when the branch head is already contained in main. By default, unmerged branches remain blockers. The explicit --archive-unmerged policy first creates and independently validates a deterministic diagit/archive/<branch>-<sha> tag, then permits branch deletion and PR closure through dependent URI steps. --rename-default-to-main safely migrates a default branch only when main does not already exist and the observed head SHA still matches.

Applying a plan requires a separate mode-0600 diagit.authority-grant/v1 file. The grant must name the organization and allowed action kinds, bind the exact plan SHA-256 digest, identify its approver, and have a future expiry. Execution is explicit:

diagit apply governance.json \
  --authority-file authority.json \
  --confirm-apply

An archived branch can be restored through a separately authorized plan:

diagit plan restore --repository owner/repository --branch fix/recover \
  --tag diagit/archive/fix/recover-0123456789ab \
  --expected-head 0123456789abcdef0123456789abcdef01234567 \
  --output restore.json

For code repair, generate a single OneDev handoff action. The instruction is data, never a command:

diagit plan repair \
  --repository subactor/core \
  --task-id 0004_node-domain-tickets \
  --instruction-file repair-instruction.txt \
  --output repair.json

Before applying an action, Diagit fails closed unless its AQL actor explicitly allows the matching OQL operation and the action is bound to exactly one URI step. After an authorized apply, Diagit sends the complete envelope, canonical plan digest, grant ID, and approving principal to the existing OneDev Agent /tasks/execute boundary. OneDev independently repeats the AQL/OQL/URI/EQL checks before materializing a Planfile ticket. OneDev then owns Doctor → Repair → Validator, test gates, exact-SHA checks, and publication. A submission receipt remains submitted; only validator evidence can satisfy the terminal EQL. The referenced diagit-repair-delegation.pl.aql decision model is packaged with the wheel, so the envelope never relies on an unresolved model name.

diagit plan repairs compiles the latest remote audit into one independently authorizable plan per affected repository plus a diagit.repair-plan-set/v1 manifest. It selects only diagnostics whose registered repair URI delegates to OneDev, deduplicates them into a bounded instruction, and preserves the source audit run ID. --code can be repeated to restrict generation to specific delegable diagnostic codes. Generating the set never submits work; each plan still requires its own digest-bound authority grant before diagit apply can cross the OneDev boundary. Across later audits, a plan already in submitted or validated state is deduplicated by its stable action identity. A changed finding produces a new identity and therefore needs a new exact-digest grant.

diagit audit accepts repeatable exact or glob repository selectors. The fleet-repairs variant compiles local findings from the latest completed audit, so one diagnostic becomes an independently authorized OneDev ticket for each selected repository rather than one unbounded fleet mutation.

OpenRouter application attribution

DIAGIT-LLM-001 / OPENROUTER_APP_IDENTITY_MISSING identifies tracked runtime consumers of OpenRouter that do not provide verifiable cost attribution. A compliant repair declares OPENROUTER_APP_NAME and an application URL in the environment template and binds them to X-OpenRouter-Title and HTTP-Referer. The URL may use the canonical OPENROUTER_APP_URL name or the established OPENROUTER_SITE_URL compatibility alias. When the name is blank, runtime code must use the repository directory name. Environment templates and policy implementations are not consumers by themselves. Applications routed through subllm receive provider identity from its central application/function policy and do not duplicate this local binding. Diagit reads only variable names and bounded tracked source files; finding evidence never contains environment values or API keys.

The audit uses only local Git metadata. Ahead/behind values therefore describe the locally known upstream refs and do not imply a network refresh.

Release readiness

diagit audit --root ~/github --organization subactor --check-registries adds bounded release checks to the normal event-sourced fleet audit. Local checks validate goal.yaml, package file boundaries, and version tags. Registry checks compare public package.json and pyproject.toml manifests with npm and PyPI; Node packages with private: true are never treated as publication candidates.

The command is read-only: it reports unpublished packages and version drift but never publishes, tags, or pushes. Registry access is opt-in because it requires network I/O.

Development

python -m grpc_tools.protoc -Iproto --python_out=src --pyi_out=src proto/diagit/v1/audit.proto
scripts/verify
scripts/verify-dsl

The package distribution name is diagit, its Python import is diagit, and its executable is diagit (which also permits the Git external-command form git diagit).

License

Licensed under Apache-2.0.

Metadata

Release files for diagit 0.12.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for diagit 0.12.1
File Size Uploaded
diagit-0.12.1.tar.gz 152.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for diagit 0.12.1
File Interpreter ABI Platform
diagit-0.12.1-py3-none-any.whl Python 3 none any Details

Total release size: 280.5 kB

Release files / diagit-0.12.1.tar.gz

Download URL diagit-0.12.1.tar.gz
Size 152.7 kB
Tags Source
SHA-256 checksum
How to use checksums
bdd98d488d7f091890d266a6652813cee2f4eb875048dd038bd8231c5df17eb2
BLAKE2b-256 checksum
How to use checksums
b9041b5472445233b9593c72f207f10b6b0bd112f783a5faba392f7b68e8cdc1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.7

Release files / diagit-0.12.1-py3-none-any.whl

Download URL diagit-0.12.1-py3-none-any.whl
Size 127.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d47897c55107b43cefd5ef03957ce56edf7b2359574902013efbbd331277d136
BLAKE2b-256 checksum
How to use checksums
64e15790df9f33eeb816ec1b65028db256ec091ae73d53b96c5ad36c8d673a03
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.7

Release history Release notifications | RSS feed

This release

0.12.1 This release

2 release files

0.10.1

2 release files

0.10.0

2 release files

0.9.1

2 release files

0.9.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page