Spec compiler (resolve) accepts and stores the new relation keys:
- per-argument -conflicts <list>: parsekeys or flag names that must not be
RECEIVED together with this argument; checked against received args only at
parse time (defaults never conflict) - parse-time optionconflict enforcement
lands in a later G-083 increment.
- @opts-level -parsekeymode override|error: per named OPT_GROUPS group; error
= distinct-member co-occurrence within a shared-parsekey group raises
optionconflict at parse; override = legacy last-wins, the default.
Both keys are cross-validated at resolve: -conflicts targets must name a defined
argname or declared -parsekey; -parsekeymode requires -group and a value of
override|error. Define-time integrity hole closed: a -parsekey colliding with a
distinct defined argument's name (one not sharing that -parsekey) is now a
resolve error instead of silently forming an implicit shared-key group
(parsekey_collides_with_defined_optname_GAP flipped in parsekey.test to a
define-time error pin, plus redundant-self-name and deliberate-shared-group
guards).
Design settled (recorded in the goal detail): -parsekeymode is per named group
(OPT_GROUPS entry, keyed by the @opts line's -group), not form-wide. Rationale:
lsearch uses per-arg -conflicts only (partial conflicts, groups stay default
override); clock clicks uses -parsekeymode error on its single named group
(full pairwise exclusivity). Unnamed shared-parsekey groups default override.
Legacy untouched by default: -parsekeymode override is the default and absent
-conflicts means no check runs; the pinned parsekey_repeat_ordering last-wins /
prepend-defaults idiom and the full existing suite pass unchanged.
New testsuite relations.test pins the define-time vocabulary (7 tests, matching
the longopts.test/mashopts.test error-pin style). buildversion 0.18.0 -> 0.19.0.
Verification: full punk/args suite via canonical tclsh90s - 356 total / 353
passed / 3 skipped (punkargsKnownBug) / 0 failed. goals_lint clean. No
punkproject.toml bump (define-time only; no shell-level user-visible behaviour
yet - the module change, not the shell product).
Assisted-by: harness=pi; primary-model=huggingface/zai-org/GLM-5.2; api-location=huggingface.co
Activation-freshness overlap survey (goals_xref score G-083) confirmed the
existing Notes already record the real relationships (G-053, G-072, G-084 -
all linked). G-167's back-pointer explicitly declares a deliberate non-overlap
with no sequencing constraint; remaining unlinked pairs are low-score
term-only siblings with no path overlap. No new Related: lines warranted.
This work is a prerequisite for G-084 (parsekey completeness), whose
cross-member -multiple combination decision should be made with this goal's
relations vocabulary in hand. G-053 (occurrence arity) is slotted before
G-084 in the same sequence at the user's direction.
Assisted-by: harness=pi; primary-model=huggingface/zai-org/GLM-5.2; api-location=unknown
- GOALS.md: "Goals-system: v2" front matter; canonical "Goals system versions"
section; Scope structure rule (elements separated by '; ' at top level,
commas only inside parens/braces); Child DOX Index note in root AGENTS.md
- goals_lint.tcl: new finding for top-level commas in Scope lines
(paren/brace depth-aware)
- goals_xref.tcl: repo-local configuration via goals/xref.conf (path roots,
stop words, file extensions, reference containers, module dirs,
bare_path_roots, prefix_anchors); defaults byte-identical to previous
behaviour (verified on this tree)
- goals/AGENTS.md: cross-repo goal references drop the G- prefix; xref.conf
documented in Verification
- Scope delimiter normalisation across GOALS.md, GOALS-archive.md and all
detail files, live and archived: 224 lines, top-level commas only;
conservation verified (goals_xref report byte-identical pre/post, diff
hunks are Scope lines only). Archived tier converted under explicit user
approval; sanctioned exception recorded in GOALS-archive.md.
Assisted-by: harness=opencode; primary-model=openrouter/moonshotai/kimi-k3; api-location=openrouter.ai