6.0 KiB
G-016 projects.work discovers git-based projects alongside fossil
Status: proposed
Scope: src/modules/punk/mix/commandset/project-999999.0a1.0.tm, src/modules/punk/repo-999999.0a1.0.tm
Goal: dev projects.work <glob> lists git-based project checkouts as well as fossil-based ones, each result identifying its VCS - fossil discovery stays central-config-db based, and git discovery uses a defined enumeration source (git has no central registry; the chosen mechanism is recorded in the detail file); output gains a -return table|dict|json option (default table, unchanged): dict is the canonical machine form (per-checkout records incl the VCS field, documented in the argdoc), json a faithful rendering of it for out-of-process consumers.
Acceptance: with a git-only project on disk registered in the chosen enumeration source and matching the glob, projects.work lists its working directory and identifies it as git; existing fossil results are unchanged apart from any added VCS-identifying column; a project that is both git and fossil (e.g. this repo) appears with both indicated rather than duplicated; glob matching remains case-insensitive; -return dict yields the documented record structure containing everything the table shows (incl VCS identification), -return json round-trips the same data, and the default table output is unchanged for existing users.
Context
dev projects.work <glob> (punk::mix::commandset::project::collection::work)
answers "where are my projects checked out" by opening the central fossil
config-db, globbing repository database filenames, and listing the known
checkout directories per repo - with optional per-checkout file-state detail.
This makes it the natural mechanism for agents to locate sibling projects
(e.g. the tomlish project space referenced by G-014) instead of recursively
scanning the filesystem.
The gap: it is fossil-only. Git-based projects are invisible to it, and git has no equivalent of fossil's central config-db - there is no built-in registry of clones on a machine. So git discovery needs a defined enumeration source of its own before the listing can be extended.
Approach
Enumeration-source candidates (implementation decision, to be recorded here when made):
- Configured search roots: a punk::config setting (natural G-014 consumer)
listing parent directories to scan one or two levels deep for
.gitdirs. Bounded scan, no registry maintenance, but discovery limited to declared roots. - Punk-maintained registry: record project paths when punk tooling creates/opens them (and offer a scan-once command to seed it). Fast lookups, works for arbitrary locations, but can go stale.
- Hybrid: registry seeded/refreshed by an explicit scan of configured roots.
Result-shape considerations:
- Each row identifies its VCS. Fossil rows keep their current columns (repo db filename, project name/code, checkout dirs, dup-set annotations); what the git analogue of "project name" is (dir name, remote URL tail, configured name) is part of the design work.
- A dual git+fossil workdir (like the shellspy repo itself) is one project row with both VCSs indicated, not two rows.
- Fossil supports multiple checkouts per repo db; git worktrees are the analogous multi-workdir case and should at least not break the listing.
Alternatives considered
- Filesystem-wide scanning at query time - rejected: unbounded cost and exactly the behaviour this mechanism is meant to replace for agents.
- Relying on external tools' state (e.g. IDE/zoxide/gh caches) - rejected: non-portable, not present on all machines, opaque formats.
Machine-parsable returns (added to contract 2026-07-11)
-return table|dict|json(default table, existing display unchanged), following the house convention (cmdhelp-return dict, parse_status - G-049): the dict is the canonical machine form and the single source the other renderings derive from - build it FIRST, render the table from it (avoids maintaining parallel assembly).- Suggested dict shape: list of per-checkout records - workdir, projectname, projectcode, vcs (fossil|git|both - this goal's addition), repo db/enumeration source path, multi-checkout dup info, optional -detail file-state - plus overall keys (globs, counts). Document the structure in the PUNKARGS argdoc like ::punk::args::parse_status does.
- json = faithful rendering of the dict (tcllib json::write is available in kits via tcllibc) - the parse target G-017's agent guidance standardizes on: self-delimiting and language-neutral over a pipe.
- Markdown deliberately NOT offered as a machine form (2026-07-11 decision): agents parsing should use json; the human table remains for eyeballing - a markdown rendering would be a third sync burden, lossier than json.
Notes
- Staleness of the fossil config-db source itself (observed 2026-07-11): a
throwaway test repo fossil-init/opened in an agent session scratchpad (temp
path) persisted for days as row 1 of the listing -
repo:rows live until an explicitfossil all ignore, andckout:rows are pruned only byfossil allcommands run after the checkout dir is deleted. So the "registry can go stale" concern listed against the punk-maintained-registry option applies equally to fossil's own central config-db. Whatever enumeration design this goal ships needs a staleness story for BOTH VCS sources - e.g. flag or filter rows whose checkout dirs are missing or under known temp locations - especially for the-return dict|jsonmachine forms agents will consume unfiltered. The prevention side (scratchFOSSIL_HOMEfor throwaway repos) is recorded in root AGENTS.md User Preferences. - Depends on nothing, but its value to agents is realised through G-015 (reliable piped invocation - achieved 2026-07-07) and G-017 (agent guidance documenting the call).
- The
-cd/-detailoptions and case-insensitive glob behaviour of the existing command are contracts to preserve. - Archived-goal references in this file: G-049 achieved 2026-07-10 (goals/archive/G-049-punkargs-parse-status-model.md).