You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

12 KiB

G-033 proj: package-mode scope prefix: visitor binary resolves dev/src against the cwd's project

Status: proposed Scope: src/vfs/_config/punk_main.tcl (package-mode dispatch and boot-time root discovery), src/modules/punk/repo-999999.0a1.0.tm (find_project / is_project_root - reuse or lean boot mirror), bin/AGENTS.md (mode docs) Goal: a proj: prefix on the package-mode string (e.g. punkshell proj:internal-src shell) makes the dev/src path blocks resolve against the punk project containing the current working directory - walking up to the nearest VCS repo root, the marker punk::repo::is_project_root already uses - instead of the executable's own project, so an installed ("visitor") punkshell binary, including one downloaded standalone with no source tree around it, can interactively explore a project that builds no shell-capable binary or no binary at all; the prefix scopes WHICH project, staying outside the ordered dash-list whose block order remains the same-version tie-break dial, and the explicit prefix gates the behaviour so no cd silently rebinds a normal launch. Acceptance: <installed-punkexe> proj:internal-src shell (the documented canonical visitor invocation - kit copies win same-version ties, protecting the visiting shell's infrastructure; proj:src is the documented faithful-vintage variant where the project's copies win) launched from within a punk project's tree discovers the project root by walking up from cwd to the nearest VCS repo root and feeds it to the existing src-mode path machinery (src/modules, src/bootsupport/modules, src/vendormodules on the module path, src/lib on auto_path), so the session loads the project's dev-versioned modules while ordinary version resolution still lets the project supply anything the kit lacks or exceeds; the launch reports the detected project root and effective path precedence (never a silent rebind); with no project found walking up from cwd, or a proj: string containing no root-using block (dev/src), it warns and proceeds without false rebind; proven for a standalone binary outside any source tree (internal = kit contents regardless of binary location) against a project that builds no executable (tomlish is the natural first); exe-relative src/dev discovery is unchanged for a binary that IS in a project's bin/; the packagemode help text drafted in the detail file becomes the live punk::args documentation when implemented (rendered via G-032).

Context

The earlier intent (recalled 2026-07-07): an installed punkshell binary sitting in PATH - possibly a downloaded binary, not built from any local source tree - should be able to detect when the cwd is inside a punkshell project and set up the appropriate source/dev library resolution for it, so the user can explore that project interactively via the shell subcommand. The project being worked on might not build a shell-capable binary, or might build no executable at all (e.g. a modules-only project).

History check: this was never active in the full sense. src mode is new (checkin 3d2d098d) and discovers the project root exe-relative (backtrack from the executable's bin/); dev is likewise exe-relative; os is the only cwd-relative piece and only shallowly (adds [pwd] and cwd-relative modules/modules_tcl<N> ad-hoc .tm sources - no walk-up, no src/ structure). The comments in punk_main.tcl name "the info nameofexecutable or info script or pwd relative paths" as design axes, so the intent seeded os mode, but cwd project-structure detection was never built into the boot modes.

The cwd-relative detector already exists at the runtime layer: punk::repo::find_project walks up from cwd via is_project_root, and dev commands (module.templates, module.new, ...) already use it. The marker question is answered: is_project_root defines a project as a VCS repo root (git or fossil) that is not an excluded location - deliberately NOT relying on punkproject.toml (its own comment notes that file also appears in layout templates; tomlish has no punkproject.toml yet but IS a fossil root). This goal aligns the boot-time package modes with that existing runtime detection.

Syntax: scope prefix, not a fifth token (decided 2026-07-07)

The existing modes (internal/dev/src/os) are ordered path-source blocks: punk_main assembles new_tm_path token-by-token in dash-string order, and because the head of tcl::list wins same-version ties (rules verified 2026-07-06), earlier blocks win same-version collisions - deliberately so (punk_main comment: "the lib/module paths based on the project being run should take preference if 'dev' is earlier in the list, even if the version number is the same"). The dash-list is the user's tie-break dial.

proj answers a different question - WHICH project root dev/src resolve against - so it has no meaningful position in that ordering; a positional token (os-proj-src-internal) reads as noise because it is a category error. Decided syntax:

[proj:]<block>[-<block>...]        e.g.  proj:internal-src
  • The proj: prefix scopes root discovery to cwd-walk-up; everything after the colon is the unchanged ordered block string with unchanged semantics.
  • A proj: string containing no root-using block (dev/src) warns that proj has no effect (os/internal do not reference a project root).
  • Parser impact is small: recognise an optional proj: prefix on arg 0, strip it, then validate dash-tokens as today. Explicit prefix = opt-in; no cd silently rebinds a normal launch.
  • Rejected: automatic cwd-detection without a token (silent rebind surprise); an explicit -flag route (less convenient for everyday use - user decision); a token-attached qualifier like src@proj (binds the root choice to a precedence slot; the root choice is launch-wide).

Same-version shadowing: why kit-first is the canonical default (decided 2026-07-07)

Order only decides exact-version ties. The project's own code is unaffected by the choice: dev-versioned modules (999999.0a1.0, package prefer latest) and higher-versioned modules load from the project in either order, and anything absent from the kit has no tie so the project supplies it. The decision governs only same-version-different-content drift - rare within one lineage (punkshell version-bump discipline, G-026 provenance), but structurally expected in visitor mode, where the binary and the visited project's bootsupport/ vendormodules snapshots are different vintages by definition.

Failure modes are asymmetric:

  • Project-first (proj:src): faithful to the project's snapshot vintage (reproduces its bugs), but the visiting shell's own machinery loads the project's older copies - a stale project can degrade the visiting shell (the 2026-07-06 stale-textblock/shellfilter silent-stdout class, imported).
  • Kit-first (proj:internal-src): the binary's tested infrastructure survives ties; robust session; drifted same-version project copies are silently masked (less faithful, invisible when it matters).

Canonical documented invocation: proj:internal-src (kit-first). The project's genuinely-own code wins in either order; ties involve infrastructure snapshots nobody explores; and for a standalone downloaded binary the kit is its only trustworthy lineage. proj:src is documented as the faithful-vintage variant for reproducing a project's behaviour exactly. No special-casing: both fall out of the existing ordering semantics (explicit internal placement), preserving one uniform mental model.

Standalone-binary semantics (downloaded, installed on PATH, no source tree):

  • internal = the kit's own vfs contents - location-independent; kit-first needs nothing from any source tree.
  • plain src/dev (exe-relative) find no project and degrade to warned no-ops (existing behaviour) - proj: is precisely what gives such a binary a project context.
  • Trimmed kits (G-019) compose gracefully: kit-first only arbitrates ties, so modules missing from a trimmed kit still flow from the visited project.
  • Note for docs: installing a binary INTO some project's bin/ makes exe-relative modes adopt that project (by design - adoption by location).

Required boot notice

A proj: launch must report the detected project root and the effective path precedence (and warn-and-proceed when no project is found walking up from cwd)

  • the rebind must never be silent. Candidate (non-acceptance) hardening: a shadow-report diagnostic listing name+version collisions between kit-internal and project paths, pairing naturally with G-025's buildinfo.

packagemode help text (source draft for G-032)

This is the designated source text for the packagemode leader in the launcher's punk::args definition (G-032 renders it; making it live is part of THIS goal's implementation - live help must not describe unimplemented behaviour, so it ships with the prefix, not before):

packagemode -optional 1 -default internal -help
  "Package-source mode: an ordered dash-separated list of path blocks,
    optionally scoped with the 'proj:' prefix.
    Blocks (each adds a group of module/library paths):
      internal - paths inside the executable's kit (always included;
                 appended last unless listed explicitly)
      dev      - the project's built output (<projectroot>/modules ...)
      src      - the project's unbuilt source (src/modules,
                 src/bootsupport/modules, src/vendormodules, src/lib)
      os       - ad-hoc .tm paths from the current directory/environment
    Without 'proj:', dev/src resolve against the executable's own project
    (executable in <projectroot>/bin). With 'proj:', they resolve against
    the nearest project root at or above the current directory (a git or
    fossil repository root) - for an installed punkshell binary visiting
    a project that builds no shell of its own.
    ORDER MATTERS: earlier blocks win when the same version of a module
    exists in more than one location.
    Examples:
      src               work on the executable's own project source
      proj:internal-src explore the cwd project; the executable's own
                        copies win version ties (robust visitor default)
      proj:src          explore the cwd project; ITS copies win version
                        ties (faithful to the project's snapshot vintage)
    The launch reports the detected project root and effective precedence."

Approach

  • On proj:: walk up from [pwd] to the nearest VCS repo root (the is_project_root marker) and feed that root into the existing src-mode path machinery (already parameterised on a root variable - adds src/modules, src/modules_tcl, src/bootsupport/modules, src/vendormodules to the tm path, src/lib to auto_path, registers #modpod modules, sets package prefer latest). Only the discovery is new; the setup is reused.
  • Boot chicken-and-egg: find_project/is_project_root live in punk::repo, not loadable at the early package-mode phase. Options, decision to record: (a) lean inline VCS-root walk-up in punk_main using only Tcl builtins (fossil: FOSSIL/.fslckout/.fos; git: .git) - matches how the src-mode #modpod scan already inlines logic at boot; (b) defer proj setup to a post-boot phase where punk::repo is available.

Notes

  • The related dev machinery (module.templates -> punk::mix::commandset::module -> punk::cap punk.templates plugin handlers) uses find_project and has unpolished plugin issues, plus an 8.6 shell-context zip-modpod-mount failure (G-034). This goal deliberately does NOT gate on synchronising with that machinery - it only aligns with the find_project detection concept.
  • Related: G-018 (the installable generic/plain binary this serves), G-019 (trimmed kits borrow from the visited project gracefully under kit-first), G-031 (boot core is where proj discovery belongs; the template project_main.tcl lacks even src mode - fork drift), G-032 (renders the packagemode help text above), G-015 (proj:... script also benefits), G-027 (if a universal project marker is ever seeded, proj could prefer it over the structural VCS heuristic).
  • Archived-goal references in this file: G-015 achieved 2026-07-07 (goals/archive/G-015-script-subcommand-piped-stdin.md).