# 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 ` 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 ` (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 `.git` dirs. 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 explicit `fossil all ignore`, and `ckout:` rows are pruned only by `fossil all` commands 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|json` machine forms agents will consume unfiltered. The prevention side (scratch `FOSSIL_HOME` for 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` / `-detail` options 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).