diagit
AI Cost Tracking
- 🤖 LLM usage: $0.4500 (3 commits)
- 👤 Human dev: ~$100 (1.0h @ $100/h, 30min dedup)
Generated on 2026-08-08 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 --organization subactor \
--repository 'subactor/*-agent' --exclude-repository 'subactor/*-worktree'
diagit query summary
diagit query findings --severity SEVERITY_CRITICAL
diagit query repo subactor/core
diagit diagnostics list
diagit diagnostics show DIRTY_WORKTREE
diagit uri 'diagit://fleet/query/summary'
diagit remote audit --organization subactor
diagit remote summary --organization subactor
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 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 forge audit --max-items 1000
diagit forge recommend --require actions --require projects \
--visibility private --prefer-self-managed
The default state directory is $XDG_STATE_HOME/diagit, or
~/.local/state/diagit. Override it with --state-dir or
DIAGIT_STATE_DIR.
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.
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_REQUIRES_MERGE and cannot be archived by the governance cleanup
policy.
Architecture
- Commands change only the auditor's own state.
AuditFleetobserves Git repositories and appendsAuditRunStarted,RepositoryAudited, andAuditRunCompletedprotobuf events. - The length-delimited
events.pbfile is the canonical event store. - Queries read a rebuildable SQLite projection (
projection.sqlite3). - Forge account observations from GitHub, GitLab, Gitea/Forgejo, and Bitbucket
are stored as
ForgeAccountTwinObservedprotobuf 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 touri-twin/uri-twin-forge; Diagit returns that source revision with each audit and recommendation. diagit rebuildrecreates 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.
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.
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 OPENROUTER_APP_URL in the
environment template and binds them to X-OpenRouter-Title and HTTP-Referer.
When the name is blank, runtime code must use the repository directory name.
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
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.
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 diagit-0.9.0.tar.gz.
File metadata
- Download URL: diagit-0.9.0.tar.gz
- Upload date:
- Size: 80.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
506fa50c04039dbf00a028fce4f16f205b9fe9ada59bc4527c0aebd71596d205
|
|
| MD5 |
7403103e11b56386cb7491e96d99d495
|
|
| BLAKE2b-256 |
c8b25471a92ad3a55ee2eaa32298d20c43babbcef8fc3541e2557b26f771da43
|
File details
Details for the file diagit-0.9.0-py3-none-any.whl.
File metadata
- Download URL: diagit-0.9.0-py3-none-any.whl
- Upload date:
- Size: 74.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
34d60f906f5ef4ebe7c47a34c32c93fea91b0e330bcfb6f5e73ea37d700a8912
|
|
| MD5 |
6c3cc174a3350a6fbd9f8b3dcd8c122f
|
|
| BLAKE2b-256 |
63716203b4cd6add434eb17caa1e7f669e87fb8e3a281c020ceea3fdc219d763
|