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.
 
 
 
 
 
 

4.0 KiB

G-173 punk::path machine-parsable returns (text/dict/json) with stable conflict verdict

Status: proposed Scope: src/modules/punk-999999.0a1.0.tm (punk::path proc - add -return modes + -context); src/tests/modules/punk/path/testsuites/tests/ (return-shape + round-trip + ansi-freeness tests) Goal: punk::path results are consumable by programs and LLMs as well as humans - a -return option adds text, dict and json choices producing ansi-free output with a documented structure (ordered PATH entries; per-entry executables with overshadowing; TCL-context conflicts), the default table output is unchanged for existing users, and the JSON form uses tcllib json::write as the preferred encoder (the runtests json_emit investigation confirmed json::write is robust where a hand-rolled emitter carried a defect class - misclassified numbers emitted bare, unescaped C0 controls). Acceptance: -return gains text, dict and json choices whose output contains no ansi escapes regardless of -highlight; the returned structure is documented in the command's punk::args definition; the default table output is byte-unchanged for existing users (existing path.test cases stay green); -return json round-trips the same data as -return dict (decode via tcllib json, recompare); the conflict verdict is stable independent of how the consumer invoked the proc via a -context option (default the caller's namespace); new tests pin dict/json shape, ansi-freeness, and dict/json round-trip parity; a duplicate-path entry and an overshadowed executable each appear in the dict/json with the fields a machine consumer needs (idx, is_duplicate, duplicate_of, overshadowed, overshadowed_by, tcl_conflicts with match=exact|nocase).

Context

punk::path currently renders only an ANSI textblock::table; its conflict detection keys off the caller's namespace (uplevel 1 {namespace current}), meaningful interactively but fragile for a machine consumer invoked through a wrapper. G-049 established -return dict on punk::ns::cmdhelp (the in-repo machine-parsable convention); G-064 applies it to lib.search and adds json for agent consumers. This goal applies the same pattern to punk::path. The runtests json_emit hardening (done 2026-08-07, separate work) closed a defect class in a hand-rolled JSON emitter (string is entier -strict misclassified 007/+5/0x10 as bare JSON numbers; the string escaper left most C0 controls raw); that investigation named tcllib json::write as the robust preferred encoder, which this goal adopts.

Approach

Split punk::path into a collect phase (the existing d_path_info/d_bin_info/d_index_executables dicts, unchanged) plus a per-mode render/serialise branch: table (current textblock::table output, unchanged), text (fixed-key plain-ASCII layout, one line per executable, no colour/layout), dict (return the structure), json (serialise via tcllib json::write). Add -context (default uplevel 1) so the conflict verdict is explicit and stable for machine consumers, and -conflicts 0|1 (default 1) to skip it for a perf win.

Alternatives considered

  • Strip ANSI from the existing table for the text mode: rejected - column wrapping and box glyphs are layout-dependent and ambiguous to an LLM; a fixed-key plain layout is cleaner.
  • Hand-roll the JSON encoder for punk::path: rejected - the runtests emitter showed the defect class; json::write is already in the build (argparsingtest uses it) and is correct.

Notes

Related: G-064 (sibling surface - same -return dict/json pattern applied to lib.search; this goal's json-writer decision resolves G-064's open "json serialization mechanism" question by adopting tcllib json::write). Related: G-049 (achieved 2026-07-10 - established the -return dict machine-parsable pattern on punk::ns::cmdhelp that this goal extends to punk::path and adds json). overlap survey: G-042/G-019/G-061/G-110 surfaced as keyword-only ("punk", a testsupport path) with no surface overlap - deliberate non-overlap (checked: src/modules/punk-999999.0a1.0.tm, src/tests/modules/punk/path, src/tests/testsupport/json_emit.tcl).