Browse Source
G-084 increment 2 + achieved flip - parsekey completeness closed: Cross-member -multiple on a shared-parsekey option group is now a DEFINE-TIME error unless ALL members belong to one @opts group marked -parsekeymode error (G-083 mutual exclusivity makes per-member collection well-defined; a single -multiple member with its own parsekey is unrestricted). This settles the G-084 cross-member accumulation decision as rejection rather than accumulate-in-received-order: collection on one storage key is ambiguous (collect-vs-replace undefined), and rejection eliminates the silent loss without new collection semantics. The check runs AFTER the G-053 canonicalisation so range forms verdict correctly ({0 1} replace-shape allowed; a pre-canonicalisation placement would raise a raw non-boolean error for any range form). Value -parsekey integrity settled at define time: duplicate value parsekeys rejected (trailing values consume positionally - the shared slot silently overwrote), dash-led value parsekeys rejected (they landed in the options namespace of result/received and aborted parse with an internal error in the option-shaped validation paths; every option storage key is dash-led, so this one rule also removes all cross-class collisions). parse_status/parse_report storage-key attribution: parse_status_build now resolves a storage key claimed by exactly ONE argument (value -parsekey, declared option -parsekey, '='-suffixed optset tail) back to that argument, so argstatus/Source report received with the value-in-effect instead of default/0. Shared-parsekey groups stay unresolved - the remaining recorded display gap (engine-level per-member tracking; archived as the goal's open Follow-on). undefine/undefine_deflist now return "" (previously the whole internal cache dict to any caller capturing the value). define -help documents -parsekey for the first time (rename semantics for options and values, leader rejection, shared groups and -parsekeymode, last-defined-member defaults precedence, the -multiple rule, value-key uniqueness/non-dash). Moduledoc tclcore comment corrected (leader -parsekey settled as rejection, not pending). Internal sweep: dead values-loop identifiers removed (val_ident/val_ident_is_parsekey/values-side seen_pks), leader reverse map removed (VAL_NAMES-driven build), dead parsekey-from--default derivation removed, stale pre-G-084 comments corrected. Tests: parsekey_shared_key_multiple_rejected strengthened (message pins, {0 1}/{0 4} range coverage, the -parsekeymode error escape hatch incl collection and optionconflict); new parsekey_value_parsekey_integrity, parsereport_storagekey_attribution, parsestatus_storagekey_attribution; inc-1 comment damage repaired (duplicated block, eaten G-083 provenance lines, stale GAP-era comment); 2026-08-08 future-dating normalized to 2026-08-07 in touched files (CHANGELOG 0.59.0/0.60.0 headers corrected likewise; the underlying commits landed 2026-08-07 AEST). Goal flip (user-approved): the Goal line's accumulate wording amended to the settled define-time-rejection design; G-084 flipped achieved 2026-08-07 and archived (detail -> goals/archive/, index -> GOALS-archive.md, reference sweep applied - G-167 survey note gains achieved markers for G-053/G-083/G-084; Follow-on recorded: shared-group per-member received attribution => open). Detail file gains ## Progress (inc 1 + inc 2 + flip evidence). src/tests/modules/AGENTS.md punk/args index updated to the settled-pin state. Project 0.60.0 -> 0.61.0 + CHANGELOG (value -parsekey support and the define-time integrity rules are user-visible shell behaviour; G-053 precedent). punk::args 0.23.0 -> 0.24.0. Suites: punk/args 401/0; modules tree 1313 pass / 11 constraint-skipped / 0 fail (zig-built tclsh90s 9.0.5); testbody_lint clean; goals_lint clean; punkboot version-parsing 81/81; make.tcl projectversion consistency OK. Claude-Session: https://claude.ai/code/session_01QgaxV27VZkmEec7oNbEVFc Assisted-by: harness=claude; primary-model=claude-fable-5; api-location=anthropic.commaster
15 changed files with 538 additions and 215 deletions
@ -1,70 +0,0 @@
|
||||
# G-084 punk::args -parsekey completeness: cross-member -multiple collection, leaders/values support, defined default precedence |
||||
|
||||
Status: active |
||||
Scope: src/modules/punk/args-999999.0a1.0.tm (parse paths, resolve directive handling for @leaders/@values); src/modules/punk/args/moduledoc/tclcore-999999.0a1.0.tm (sites carrying '#todo - fix -parsekey for leaders and values'); src/tests/modules/punk/args/testsuites/args/parsekey.test + testsuites/dev/parsekey-knownbugs.test (GAP/known-bug flips) |
||||
Goal: -parsekey behaves as a complete, position-independent result-keying mechanism: distinct -multiple members sharing a parsekey accumulate under the shared key in received order (no silent value loss), -parsekey on leaders and values renames their result/received keys the same way it does for options (or is rejected at define time everywhere it is unsupported - no silent ignore, no parse-time abort), and the precedence rule for multiple defaulted members of one group is documented behaviour rather than an in-code '? review'. |
||||
Acceptance: the three punkargsKnownBug tests in testsuites/dev/parsekey-knownbugs.test are enabled and pass (or are amended to the settled design and pass); the corresponding _GAP pins in parsekey.test are flipped or retired; the '#todo - fix -parsekey for leaders and values' moduledoc comment is resolved; the full existing punk::args suite passes untouched. |
||||
|
||||
## Context |
||||
|
||||
Probe findings from the 2026-07-14 parsekey coverage review, each pinned by a |
||||
_GAP test in src/tests/modules/punk/args/testsuites/args/parsekey.test: |
||||
|
||||
- Cross-member -multiple value loss: with `-add` and `-sub` both `-multiple 1` |
||||
sharing parsekey `-op`, parsing `-add a -sub b -add c` returns `-op b` - the |
||||
collected `-add` occurrences `{a c}` vanish. Occurrences are collected per |
||||
member flag and the shared-key resolution then returns only one member's |
||||
list (parsekey_shared_key_multiple_collection_GAP). |
||||
- `-parsekey` on a value is accepted at define time but ABORTS parsing with an |
||||
internal error; on a leader it is silently ignored; the `@values` directive |
||||
line rejects it as an unrecognised key (parsekey_values_leaders_GAP). The |
||||
tclcore moduledoc carries `#todo - fix -parsekey for leaders and values` |
||||
next to a definition using it, and choices.test notes a leaders/values |
||||
parsekey mechanism would help multi-element clause choice grouping. |
||||
- When more than one member of a shared-parsekey group declares `-default`, |
||||
the last-defined member's default wins - the ordered_opts default handling |
||||
in the source carries a literal `? review` |
||||
(parsekey_shared_key_member_defaults_GAP). |
||||
|
||||
## Approach |
||||
|
||||
- Accumulate-in-received-order is the lean for cross-member -multiple |
||||
collection, pinned (disabled) in dev/parsekey-knownbugs.test as |
||||
parsekey_shared_key_multiple_accumulation. Open design decision: with |
||||
G-083's relations vocabulary now landed (achieved - see |
||||
goals/archive/G-083-punkargs-argument-relations.md), "error on cross-member |
||||
combination unless permitted" is a defensible alternative - decide before |
||||
activating. |
||||
- Leaders/values support should reuse the option path's keying rules |
||||
(result + received dicts, required-list satisfaction) rather than a parallel |
||||
mechanism; where support is deliberately not implemented, define time must |
||||
reject the key with a clear message instead of deferring failure to parse. |
||||
- The defaulted-members precedence rule (whatever is settled) gets stated in |
||||
the -parsekey documentation and the `? review` comment removed. |
||||
|
||||
## Notes |
||||
|
||||
- Desired-behaviour pins (disabled behind punkargsKnownBug): |
||||
src/tests/modules/punk/args/testsuites/dev/parsekey-knownbugs.test - enable |
||||
and flip the parsekey.test _GAP pins as fixes land. |
||||
- Related: G-083 (argument relations - shared design context for the |
||||
cross-member collection decision; achieved - see |
||||
goals/archive/G-083-punkargs-argument-relations.md), G-053 (occurrence arity |
||||
of a single argument; achieved - see |
||||
goals/archive/G-053-punkargs-multiple-ranges.md). |
||||
- Related: G-151 (achieved 2026-08-05 - goals/archive/G-151-punkargs-annotated-success-render.md) - |
||||
its parse_report landing report bridges the parse-result storage-key folds |
||||
AT DISPLAY LEVEL only (an argument's -parsekey, else an aliased optionset's |
||||
last |-member, tried when the direct ARG_INFO-name value-in-effect lookup |
||||
misses; pinned by parsereport.test parsereport_aliased_optionset_row_bridged). |
||||
A G-151 follow-on assigns the engine-level rationalization of storage keys |
||||
vs definition argument names to this goal - when that lands, the display |
||||
bridge in parse_report (and the matching miss noted in |
||||
private::parse_status_build's comment) can retire. |
||||
- Concrete display gap for the above: parse_report's Source column and |
||||
parse_status's per-arg `received` count both report `default`/0 for an |
||||
explicitly-supplied shared-parsekey member (e.g `parse_report {-exact ...} |
||||
withid ::lsearch` shows every MATCHSTYLE member as `(default)` though the |
||||
value is correctly bridged) - `parse_status_build` keys the positions dict by |
||||
the storage key, so no per-member received attribution survives the fold; |
||||
flip when the engine-level storage-key model lands (the same follow-on). |
||||
@ -0,0 +1,120 @@
|
||||
# G-084 punk::args -parsekey completeness: cross-member -multiple collection, leaders/values support, defined default precedence |
||||
|
||||
Status: achieved 2026-08-07 |
||||
Scope: src/modules/punk/args-999999.0a1.0.tm (parse paths, resolve directive handling for @leaders/@values); src/modules/punk/args/moduledoc/tclcore-999999.0a1.0.tm (sites carrying '#todo - fix -parsekey for leaders and values'); src/tests/modules/punk/args/testsuites/args/parsekey.test + testsuites/dev/parsekey-knownbugs.test (GAP/known-bug flips) |
||||
Goal: -parsekey behaves as a complete, position-independent result-keying mechanism: distinct -multiple members sharing a parsekey are rejected at define time unless the whole group is mutually exclusive (-parsekeymode error), under which -multiple per member is well-defined (no silent value loss), -parsekey on leaders and values renames their result/received keys the same way it does for options (or is rejected at define time everywhere it is unsupported - no silent ignore, no parse-time abort), and the precedence rule for multiple defaulted members of one group is documented behaviour rather than an in-code '? review'. |
||||
Acceptance: the three punkargsKnownBug tests in testsuites/dev/parsekey-knownbugs.test are enabled and pass (or are amended to the settled design and pass); the corresponding _GAP pins in parsekey.test are flipped or retired; the '#todo - fix -parsekey for leaders and values' moduledoc comment is resolved; the full existing punk::args suite passes untouched. |
||||
|
||||
## Context |
||||
|
||||
Probe findings from the 2026-07-14 parsekey coverage review, each pinned by a |
||||
_GAP test in src/tests/modules/punk/args/testsuites/args/parsekey.test: |
||||
|
||||
- Cross-member -multiple value loss: with `-add` and `-sub` both `-multiple 1` |
||||
sharing parsekey `-op`, parsing `-add a -sub b -add c` returns `-op b` - the |
||||
collected `-add` occurrences `{a c}` vanish. Occurrences are collected per |
||||
member flag and the shared-key resolution then returns only one member's |
||||
list (parsekey_shared_key_multiple_collection_GAP). |
||||
- `-parsekey` on a value is accepted at define time but ABORTS parsing with an |
||||
internal error; on a leader it is silently ignored; the `@values` directive |
||||
line rejects it as an unrecognised key (parsekey_values_leaders_GAP). The |
||||
tclcore moduledoc carries `#todo - fix -parsekey for leaders and values` |
||||
next to a definition using it, and choices.test notes a leaders/values |
||||
parsekey mechanism would help multi-element clause choice grouping. |
||||
- When more than one member of a shared-parsekey group declares `-default`, |
||||
the last-defined member's default wins - the ordered_opts default handling |
||||
in the source carries a literal `? review` |
||||
(parsekey_shared_key_member_defaults_GAP). |
||||
|
||||
## Approach |
||||
|
||||
- Cross-member -multiple collection SETTLED 2026-08-07 as define-time |
||||
rejection (the G-083-informed alternative): accumulate-in-received-order |
||||
was the original lean, but cross-member collection on one storage key is |
||||
ambiguous (collect-vs-replace undefined; one member's collected list would |
||||
silently displace another's) and rejection eliminates the silent loss |
||||
without inventing new collection semantics. -multiple per member remains |
||||
available when ALL members share one @opts group marked -parsekeymode |
||||
error (G-083 mutual exclusivity makes it well-defined); a single -multiple |
||||
member with its own parsekey is unrestricted. The check runs after the |
||||
G-053 canonicalisation so range forms verdict correctly ({0 1} is |
||||
replace-shape and allowed). |
||||
- Leaders/values support should reuse the option path's keying rules |
||||
(result + received dicts, required-list satisfaction) rather than a parallel |
||||
mechanism; where support is deliberately not implemented, define time must |
||||
reject the key with a clear message instead of deferring failure to parse. |
||||
- The defaulted-members precedence rule (whatever is settled) gets stated in |
||||
the -parsekey documentation and the `? review` comment removed. |
||||
|
||||
## Notes |
||||
|
||||
- Desired-behaviour pins: settled 2026-08-07 - testsuites/dev/parsekey-knownbugs.test |
||||
holds no disabled pins (retained as the home for future punkargsKnownBug |
||||
pins); the settled assertions live in testsuites/args/parsekey.test |
||||
(parsekey_value_result_key_settled, parsekey_values_line_rejects_parsekey, |
||||
parsekey_leader_parsekey_rejected, parsekey_shared_key_multiple_rejected, |
||||
parsekey_value_parsekey_integrity). |
||||
- Related: G-083 (argument relations - shared design context for the |
||||
cross-member collection decision; achieved - see |
||||
goals/archive/G-083-punkargs-argument-relations.md), G-053 (occurrence arity |
||||
of a single argument; achieved - see |
||||
goals/archive/G-053-punkargs-multiple-ranges.md). |
||||
- Related: G-151 (achieved 2026-08-05 - goals/archive/G-151-punkargs-annotated-success-render.md) - |
||||
its parse_report landing report bridges the parse-result storage-key folds |
||||
AT DISPLAY LEVEL (pinned by parsereport.test |
||||
parsereport_aliased_optionset_row_bridged). NARROWED 2026-08-07 (inc 2, |
||||
punk::args 0.24.0): private::parse_status_build now resolves UNIQUE storage |
||||
keys itself (a value's -parsekey, an option's declared -parsekey, an |
||||
optset's '='-suffixed trimmed tail) for received attribution AND |
||||
value-in-effect, so the parse_report bridge and the build's miss now apply |
||||
only to SHARED-parsekey groups. |
||||
- Remaining display gap (shared groups only, as of inc 2): parse_report's |
||||
Source column and parse_status's per-arg `received` count still report |
||||
`default`/0 for an explicitly-supplied SHARED-parsekey member (e.g |
||||
`parse_report {-exact ...} withid ::lsearch` shows every MATCHSTYLE member |
||||
as `(default)` though the group value is bridged onto each member row) - |
||||
per-member received attribution does not survive the storage fold, and |
||||
which member was received is genuinely unrecoverable from the parse result |
||||
dict alone. Retirement needs engine-level per-member tracking in the parse |
||||
result (get_dict's optsets_received exists internally but is not exposed). |
||||
Pinned as the remaining gap by parsereport.test |
||||
parsereport_storagekey_attribution (the shared-group default/default row). |
||||
|
||||
## Progress |
||||
|
||||
- 2026-08-07 (inc 1, commit abd8616f, punk::args 0.23.0): value -parsekey |
||||
supported (result values slot and received keyed by parsekey, -multiple |
||||
collection, VAL_DEFAULTS/values_dict parsekey keying, api_valnames_received |
||||
tracking, val_pk2name reverse map); leader -parsekey rejected at define |
||||
time; defaulted-members precedence documented as last-defined-member-wins |
||||
and the in-code `? review` removed; tclcore moduledoc todo resolved; |
||||
parsekey.test value/leader/@values-line/defaults GAPs flipped to settled |
||||
pins; knownbugs value/leader disabled pins retired. |
||||
- 2026-08-07 (inc 2, punk::args 0.24.0): cross-member -multiple decision |
||||
SETTLED as define-time rejection (allowed only when ALL members share one |
||||
@opts group marked -parsekeymode error; check placed after the G-053 |
||||
canonicalisation so {0 1} range replace-shapes stay allowed - an earlier |
||||
pre-canonicalisation placement raised a raw non-boolean error for range |
||||
forms); value-parsekey integrity settled (duplicate value parsekeys and |
||||
dash-led value parsekeys rejected at define time - previously silent |
||||
positional overwrite / internal parse abort); parse_status/parse_report |
||||
unique-storage-key received+value attribution (shared groups remain the |
||||
recorded display gap); undefine/undefine_deflist return ""; define -help |
||||
-parsekey documentation added (first user-facing -parsekey doc, includes |
||||
the defaults-precedence rule per this goal's Approach); dead-code and |
||||
stale-comment sweep (val_ident/values-side seen_pks, leader reverse map, |
||||
pre-G-084 comment claims). Suites: punk/args 401/0, testbody_lint clean. |
||||
- 2026-08-07 (flip): acceptance verified met - knownbug pins settled and |
||||
passing, _GAP pins flipped/retired, moduledoc comment resolved, full suite |
||||
green (punk/args 401/0; modules tree 1313 pass / 11 constraint-skipped / |
||||
0 fail on the zig-built tclsh90s 9.0.5 runner; testbody_lint and |
||||
goals_lint clean). The Goal line's accumulate-in-received-order wording |
||||
was amended to the settled define-time-rejection design with the |
||||
-parsekeymode error escape at the user's explicit approval, and the goal |
||||
flipped achieved and archived. The shared-parsekey-group |
||||
received-attribution display gap is recorded below as a Follow-on |
||||
(=> open). |
||||
|
||||
## Follow-ons |
||||
|
||||
Follow-on: engine-level per-member received attribution for shared-parsekey groups - expose per-member tracking (e.g get_dict's internal optsets_received) in the parse result so parse_status/parse_report Source columns can attribute WHICH member of a shared-parsekey group was received; retires the parse_report display bridge and parse_status_build's shared-key miss (pinned today by parsereport.test parsereport_storagekey_attribution's shared-group default/default row) => open |
||||
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue