Project Ledger reads configured repository directories, git remotes, inventory files, and static .project-ledger.json declarations across machines. It validates schemas, checks source health and git drift, reconciles duplicate checkouts without guessing, and writes JSON manifests, per-project capsules, review queues, and change feeds in state/ for CLI and server queries.
Project Ledger is a project-reality compiler and control substrate for a distributed project estate.
It ingests project-like observations from directories, git repos, Obsidian vaults, mirrors, backups, and inventory/policy-backed sources. It preserves provenance and uncertainty as the shared project-identity and current-state layer for agents and operator tooling.
The optimization target is simple: a cold agent should be able to understand what project the user means, where trustworthy manifestations exist, how fresh the evidence is, what is uncertain, and what capability is actually available without replaying repo/filesystem archaeology.
- CURRENT.md — canonical executable frontier and next bounded work
- SYSTEM.md — canonical system model and invariants
- AGENT_PROTOCOL.md — agent orientation, action, and handoff protocol
- SCHEMA.md — compatibility schema and typed target contracts
- docs/WAVE1-AGENT-SUBSTRATE.md — exact executable Wave 1 contract
- ARCHITECTURE.md — implementation and dataflow architecture
- ROADMAP.md / BACKLOG.md — gated evolution and executable work
- RUNBOOK.md — operations and recovery
- docs/decisions/README.md — durable architectural decisions
Waves 0–5 and the Reality Provider seam (machina, homelab, gbrain) are implemented on main while preserving the frozen v0 compatibility scanner contract.
python -m ledger refreshThat runs the compatibility scanner and then compiles the agent-facing state plane.
Compatibility outputs remain:
output/projects.csv
output/projects.json
output/projects.md
docs/ledgers/projects-ledger.md
Generated agent projections are:
state/system-manifest.json
state/source-checkpoints.json
state/github-sync.json
state/observations.json
state/canonical-projects.json
state/canonical-projects.md
state/identity-evidence.json
state/review-queue.json
state/changes.json
state/runs/<run_id>.json
state/projects/<canonical_project_id>.json
state/ is intentionally gitignored: it is rebuildable compiled state, not canon.
Install onto $PATH (~/.local/bin) with uv:
uv tool install --editable /central/repos/active/project-ledgerBoth ledger and ledger-mcp resolve Project Ledger's workspace root automatically from any current working directory (CWD) via PROJECT_LEDGER_HOME, an active Project Ledger workspace checkout, or the package checkout root:
ledger validate
ledger sync-github [--check | --dry-run] [--clone-root /central/repos/active] [--force-fetch] [--json]
ledger refresh [--full-scan] [--check-remote] [--remote-timeout 3.0]
ledger refresh --no-markdown-mirror [--full-scan] [--check-remote]
ledger compile [--check-remote] [--remote-timeout 3.0]
ledger orient
ledger sources
ledger resolve <referent>
ledger show <project>
ledger locate <project>
ledger explain <referent>
ledger review [--approve-candidates] [--decision-id ID]
ledger changes [--since RUN_ID] [--project REFERENT] [--entity-kind KIND] [--change-type CODE]
ledger lineage [--check | --sync] [--json]
ledger sync-gbrain [--brain-dir /home/prime/brain] [--project REFERENT] [--ingest] [--dry-run] [--json]
ledger mcp
ledger-mcpUse --json on the CLI commands when machine-readable output is preferred. Connect a Model Context Protocol (MCP) client over stdio to ledger-mcp (python -m ledger mcp) for zero-subprocess read-only Reality Provider tools (ledger_orient, ledger_sources, ledger_resolve, ledger_show, ledger_locate, ledger_explain, ledger_changes, ledger_review, ledger_lineage) and ledger:// resources.
orient is the cheapest current entrypoint after a compile. It reports run/as-of information, source and observation counts, estate health, and the capability boundary so agents do not mistake planned features for implemented ones.
The first typed substrate includes:
- compiler/schema versions;
- explicit stable
source_idvalues in the production config; - source classes (
live,mirror,backup,inventory); - current source health and artifact availability;
- deterministic current source probe fingerprints;
- compatibility
snapshot_idvalues scoped by source + compatibility scan time; - stable manifestation-oriented
observation_idvalues; - typed observation wrappers around the existing flat compatibility records;
- explicit capability states and reason codes for unavailable future layers;
- stable validation error codes;
- explicit
known/unknown/unavailable/stale/absent/conflicted/not_applicablevocabulary for the new contracts; - failure containment: a temporarily unavailable source degrades the compiled manifest instead of erasing the rest of the estate from orientation.
The legacy flat record is still a compatibility observation, not a canonical project entity.
Implemented now:
registered sources
-> current source probes + single-pass scandir source/candidate/compile checkpoints (P5.1 + U4) + compatibility source/run snapshots
-> compatibility observations
-> typed observations
-> exact-remote identity evidence + explicit identity decisions + durable immutable project-lineage registry (registry/project-lineage.json, U3) + frontier zero-shot triage
-> canonical projects + identity review + GBrain cross-links + idempotent GBrain reality-block projector (ledger sync-gbrain, U1)
-> bounded project capsules (with read-only structural ctx synthesis across 166/172 capsules, U2, and Machina continuity, U1) + preferred-location resolution + human canonical view
-> header-indexed semantic run history + semantic change feed (state/changes.json, U4)
-> system manifest / orient / sources / resolve / show / locate / explain / review / changes / lineage / sync-gbrain / stdlib MCP server (ledger-mcp, U5)
Automatic identity is intentionally conservative:
- exact normalized repository remote is the only automatic merge authority;
- compatibility
project_keyvalues and names are referents, not automatic merge authority; - explicit committed decisions can merge, split, reject a match, assign a canonical key, supersede, or add an alias;
- ambiguous exact referents remain explicit.
Owned externally in the fleet:
work-unit / attempt / session receipts (owned by machina)
worktree leases & scheduled provider execution (owned by homelab)
semantic / entity search & cross-session memory (owned by gbrain)
Canonical project count is now distinct from observation count and is reported in the manifest.
Every committed operator root now has an explicit source_id. This identity is independent of roots[] ordering and should survive normal path/config refactors.
For additional sources, prefer an intentional stable source_id rather than relying on the deterministic compatibility fallback.
Compatibility scanner v0 provides one overall generated_at, not a native per-source snapshot record. Wave 1 therefore uses:
source_id + compatibility generated_at -> compat_snapshot_id
Separately, the manifest records a current source probe with health/access metadata and a probe_fingerprint. The probe is not rewritten into historical snapshot identity. This lets an older observation remain tied to the run that produced it even when its source is unavailable now.
An observation is a manifestation inside a source and is keyed primarily by source + observed location, not by a conceptual project key.
The first canonical identity slice now compiles those observations into conceptual projects using only exact normalized repository remotes plus explicit durable decisions. This avoids treating names or compatibility keys as stronger evidence than they are.
See docs/WAVE1-AGENT-SUBSTRATE.md for exact semantics and limitations.
python -m ledger validate is strict: malformed config or missing required inventory/policy artifacts fail validation.
python -m ledger compile is orientation-preserving: structurally valid but temporarily unavailable sources are represented as unavailable/degraded in system-manifest.json so one broken source does not prevent an agent from understanding the rest of the estate.
A full ledger refresh still depends on the compatibility scanner's ability to read its required ingestion artifacts.
The existing build_ledger.py remains the compatibility scanner during migration. It supports:
childrengit_reposselfinventory_policy
and continues to provide filesystem/git/Obsidian/README extraction, project-local sidecar overlay, inventory/policy promotion, Markdown/CSV/JSON exports, and safe handling of missing ordinary filesystem roots.
The new ledger/ package compiles around this stable output rather than rewriting the monolith before the contracts are proven.
.project-ledger.json is a static repository identity declaration (project_key, display_name, description, status, tags, canonical_url, repo_name, gbrain_source_slug, shared, storage_scope). Mutable per-commit/session fields (commit, head_commit, next_step) are ignored during validation so static sidecars never go stale after git commit.
See templates/project-ledger.sidecar.example.json and prompts/session_end_prompt.md.
Project Ledger owns project topology and compiled project reality.
- machina owns the reusable execution/control grammar: Work Units, Assertions, Receipts, evidence, control packets, and disposable-agent continuity.
- homelab owns deployment/orchestration against the real machine/service estate and its existing WorkSpec execution plane.
- Project Ledger owns source/project topology, provenance, identity/current-state compilation, and the compact reality surfaces those systems can consume.
Do not duplicate Project Ledger's schema/identity engine into machina or homelab. Integrate through explicit stable outputs once the relevant contract is implemented.
ruff check .
python -m ledger validate
/usr/bin/python3 -m unittest tests/test_doc_hygiene.py -v
python -m unittest discover -s testsVerification runs locally on the host per fleet proportional-verification policy (ops/merge-policy.json requires GitGuardian Security Checks on PR heads; .github/workflows/ci.yml is workflow_dispatch: only and runs ruff check ., py_compile, and unittest).
Waves 0–5, live ai-server provider verification, frontier weak-overlap triage, GBrain reality-block projection, and executable Draft 2020-12 JSON Schemas (schemas/*.schema.json) are all landed on main.
See CURRENT.md first, then ROADMAP.md / BACKLOG.md (including the Cross-Repo / Out-of-Scope Work Queue).