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:
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.