Skip to content

Local repository observations

The workstation harvester records Git metadata for local repositories, including repositories that have no remote. Use the existing CLI to obtain a private report:

praetorctl harvest workstation --dir /path/to/dev --json

The existing standards_harvest_workstation MCP tool accepts the same directory as dev_dir and an optional json: true. Its directory remains confined to the server root unless the server explicitly permits outside paths. Both adapters use the same harvester; neither creates remotes, adopts repositories, executes project scripts, contacts a forge, or publishes the report.

git_common_dir is the local identity used to associate a primary checkout with its linked worktrees. Adding a remote preserves this identity. Moving the Git directory can change it; it is not a portable identity across machines. Remote metadata is an observation and does not prove ownership, visibility or permission to publish. Keep reports in private storage: they contain workstation paths and repository URLs even after URL credentials have been removed.

The report retains existing governance counts and adds repository_observations:

Field Meaning
path, git_common_dir Checkout location and local Git identity
classification Observed repository or worktree classification
remote_state, remote_urls Successfully read and sanitized remotes, or unknown state
dirty_state, dirty_scope, dirty_entries Status availability, coverage and count; bare repositories have no working tree
workingdir_tracked_state, workingdir_tracked_entries Whether the tracked-file probe succeeded and its count, without filenames
workingdir_probe_ignored Optional ignore result for one sentinel path; not proof that every file is private
probe_errors Bounded diagnostics for unavailable observations

Consumers must inspect repository_inventory_scope, repository_inventory_complete and repository_inventory_truncated before using the report. The declared scope covers flat checkouts, one organization level and the recognized worktree containers. It excludes hidden and ignored development directories and does not claim a recursive inventory of every disk path. Failed Git probes and unsupported remote forms remain unknown rather than proving that a repository is local-only. A remote is recorded only when it is a network remote: an https, http, ssh, git or git+ssh URL, or the scp-like [user@]host:path form, which is recorded as ssh://host/path. User info, query and fragment are removed. Local paths, file:// URLs, Windows drive paths and remote-helper addresses such as ext::... are rejected and mark the inventory incomplete. The inventory and sync --remote share this parser (util.ParseGitRemoteURL, TestInventoryRemoteForms_SharedParser). Incomplete reports retain their observations. The CLI returns nonzero and MCP sets isError; consumers should still read the report.

stale_worktrees lists worktrees under a recognized container in which nothing changed for 24 hours. Age is the newest modification anywhere in the worktree, measured by gc.NewestModification, the same bounded walk praetorctl gc applies retention with (garbage collection); an edit to a nested file keeps the worktree off the list. A worktree whose contents cannot be read, or that exceeds the walk bounds, is recorded in repository_inventory_errors and leaves the report incomplete instead of being classified (internal/harvester/harvester_test.go, TestScanWorktreeDir_*). The list is an observation only: it neither releases a worktree nor makes it collectable.

Git probes use an isolated environment and disable filesystem monitors and hooks. Dirty coverage is explicitly checkout-excluding-submodules: Git status cannot traverse submodule worktrees, whose local filters might execute commands. A known dirty state and complete inventory apply only to the declared scope; neither certifies submodule cleanliness. Inspect submodules separately as repository roots when their state is required. Bare repositories use not-applicable dirty scope. When repository configuration declares a clean or process filter and the filter attribute of a tracked path selects it, dirty state is unavailable: computing it could execute repository-supplied commands. A filter that no tracked path selects, such as the filter.lfs block Git for Windows and git lfs install define, never runs and leaves dirty state known (TestInventoryReadsDirtyStateBesideUnselectedFilter in internal/harvester/repository_inventory_safety_test.go). Identity, remote and privacy probes still run, with incomplete coverage explicitly reported.

Use these observations to select a later, explicit dogfood run. The configured suites accept pinned public repositories and explicit transcript inputs; an inventory does not enroll or upload a local repo. harvest fleet reads the operator-supplied .config/fleet-topology.yaml (see operational configuration) and prints the configured orgs and archetype membership as a reference, not a live probe. The engine ships no fleet of its own: an engine checkout without that file prints === Fleet Topology: not configured === rather than a built-in example. Live GitHub or Gitea coverage requires a configured remote inventory source and its own completion evidence.

Fleet drift survey

praetorctl harvest drift --dir /path/to/dev finds files that several local repositories carry under the same path and reports whether the copies still agree. It reads the repositories the inventory above finds, one checkout per git_common_dir, at their HEAD commits through the same isolated Git probes, and compares the files under .githooks/ and scripts/, or under the repository-relative prefixes given with repeated --path flags (a directory of agent hook scripts, for example).

The text report lists each drifted path with one line per variant (short digest, line count, lines removed and added relative to the most common variant, repositories) and each identical path with its repositories; --json carries full digests and every repository's state and revision. A path one repository carries alone is not listed. Drift never fails the command; an unreadable repository or copy, a reached bound or an incomplete inventory makes it exit nonzero with the report still printed (cmd/standardsctl/harvest_drift_test.go, internal/harvester/drift_test.go). Declared copies and an audit check are designed but not implemented: see fleet drift and schema conformance.

Skill-root audit

praetorctl harvest skills --gemini /path/to/.gemini --repo /path/to/repo audits the supported agent roots and the selected repository's .agents/skills. It prints completion and each root's status, examined entries, and skill count. An explicit repository selection requires that skill directory to exist; use --repo '' to omit it. With the default repository selection, an absent local skill directory is optional. Absent auto-detected agent roots are not applicable.

Directory reads are limited to 500 entries and a 30-second audit context. Invalid roots, symlink roots or manifests, non-regular manifests, read failures, and overflow leave an incomplete report and a nonzero exit. Partial evidence remains visible; optional dedupe or backup removal does not run after an incomplete audit. Duplicate names are reported deterministically; matching names alone do not establish identical content. The workstation MCP inventory does not currently expose this separate skill audit.