feat(cli): same-command completeness corrections, comma-list --unset, bounded test receipts

Merged
UN
2d ago
+2360-733

Agent-UX delivery for the read-refusal and linked-test receipt surfaces, plus the text-refusal overflow ladder. Four GitHub-reported items and three tracker-only items close in this PR; every one carries its before/after measurement and negative control in the tracker.

What changes

  • Contract-derived completeness corrections (GH-1626, pm-gh1626). Read refusals now offer a same-command replay for every equivalent completeness spelling, derived from runtime contracts instead of a hand-maintained pair list. CliFlagContract gains an optional values domain (declared on get/context/plan --depth), and resolveReadCompletenessControls joins it with each read-output surface's projection modes. get --brief replays as --depth brief, list --depth brief as --brief, --depth standard drops to the default, and aliased reads replay on their noun-first path. A command without an equivalent lists its own controls instead of pointing at other commands.
  • Comma-list --unset (GH-1633, pm-gh1633). create, update and update many accept comma-separated --unset field lists; each part is validated and refused by name. The split is unambiguous because schema add-field now refuses comma keys and flags (before this it registered foo,bar and advertised an unusable --foo,bar). update many --unset <unknown> refuses before planning instead of reporting no_effect.
  • Bounded selective test receipts (GH-1630, pm-gh1630). --match, --only-index and --only-last runs list only the selected tests; count and selection keep the full picture and tests_omitted names pm test <id> --list as the restore path. A 58-test --only-last receipt drops from 8,662 to 2,212 bytes in TOON and from 18,826 to 2,695 in JSON.
  • Compact lean receipts for quiet successes (pm-covpax). Under --lean, a passing linked-test run with no context mismatch and no failure category projects execution_context to its modes, trust reason and restore path and omits the all-zero failure_categories (2,178 → 865 bytes TOON; 2,645 → 1,166 JSON). Failures, skips, mismatches and default output keep full sandbox provenance.
  • Dash-leading values in unknown-option recovery (pm-stq61b). A quoted value that starts with -- (a close reason, a comment) is no longer dropped from the advertised replay; it is passed after a -- separator when only options follow, otherwise the refusal explains the parse instead of advertising a lossy retry.
  • Text refusal overflow ladder (pm-4oc353). Text refusals whose recovery bundle echoes a long argv no longer jump from full rendering to action-only and lose the What happened line. They drop the explanation, then extra collection entries, then the argv echo, then bound an oversized detail, each stage naming --json as the restore path. Short refusals are unchanged. The strict-create refusal for a cleared required option now states the actual rule.
  • Tracker closeout (pm-m6ig79). Records the hosted CI evidence for the runner-demand reduction that shipped in #1634 and classifies pm-covpax with the escape class and gate evidence the defect-evidence gate requires.
  • The native read-surface tables move into a dependency-free module so completeness recovery stays off the formatter import path and pm --version works without installed dependencies. The --unset help text is shortened to fit the zero-headroom help-token ratchet.

Merge hygiene

  • main (including #1629 and the 2026.10.30 release) is merged in. The one field-aware tracker merge (pm-7zs0 expected_result) is reconciled and its durable receipt committed.
  • CHANGELOG.md is regenerated from closed items; no hand edits.

Validation

  • node scripts/run-tests.mjs test: 885 files, 11,675 tests passed, 3 skipped.
  • pnpm typecheck: clean.
  • pnpm changelog:pm:check: clean after regeneration.
  • Per-item measurements, negative controls and linked tests are recorded on pm-gh1626, pm-gh1633, pm-gh1630, pm-covpax, pm-stq61b, pm-4oc353 and pm-m6ig79.

Closes #1626
Closes #1633
Closes #1630

Summary by Sourcery

Improve CLI refusal recovery, mutation ergonomics, and linked-test receipts while preserving actionable diagnostics and addressing dependency advisories.

New Features:

  • Support comma-separated field lists for --unset across create, update, and bulk update commands with per-field validation.
  • Provide bounded, selection-aware linked-test receipts with restore commands for omitted tests.
  • Derive same-command completeness corrections from runtime CLI contracts and read-surface capabilities.

Bug Fixes:

  • Preserve dash-leading values during unknown-option recovery instead of dropping them from replays.
  • Keep specific refusal details visible when oversized text diagnostics exceed their output budget.
  • Clear claim ownership completely when closing an item.
  • Retain meaningful execution context in lean receipts while omitting redundant success metadata.
  • Block comma-containing schema keys and flags to keep comma-separated field parsing unambiguous.

Enhancements:

  • Move native read-surface metadata into a dependency-free module for bootstrap-time recovery.

Build:

  • Raise dependency overrides for follow-redirects and minimatch to versions addressing registry security advisories.

Documentation:

  • Document same-command completeness recovery, comma-separated unset fields, selective test receipt restoration, and dependency advisories.

Tests:

  • Expand integration and unit coverage for completeness recovery, unset validation, selective receipts, lean output, dash-leading values, and bounded refusals.

Chores:

  • Regenerate the changelog and update tracker evidence and merge receipts.

Summary by cubic

Fixes agent-facing refusal and receipt friction: completeness misspellings replay on the same command, --unset accepts comma-separated lists, selective test receipts only list selected tests, and oversized text refusals keep the specific failure detail. Also raises pnpm overrides for follow-redirects and minimatch to clear two registry advisories that blocked the advisory gate.

Bug fixes

  • --unset on create, update, and update many accepts comma-separated lists; unique entries that resolve whole (like legacy comma-registered keys) stay intact, and schema add-field now refuses comma keys so the split is unambiguous.
  • update many --unset <unknown> refuses before planning instead of reporting no_effect, the planner resolves possibly aliased fields into the same keys validation accepted, and runtime fields declared only for update_many resolve under that scope instead of being refused.
  • close clears claim_principal with assignee, so a closed claimed item no longer keeps an active owner that only pm release could remove.
  • Quoted values starting with -- survive unknown-option recovery via a -- separator instead of being dropped from the advertised replay.
  • Text refusals whose recovery echoes a long argv no longer lose the What happened line; they drop explanation, collections, and argv echo progressively, each stage naming --json.
  • Selective --match/--only-index/--only-last runs list only selected tests, with tests_omitted naming pm test <id> --list plus --pm-path, --no-extensions, and shell escaping when the run used an explicit tracker root or suppressed extensions.
  • Under --lean, passing mismatch-free runs omit all-zero failure_categories and compact execution_context, while keeping the mismatch and trust booleans since a pass under an explicit override can be untrusted.
  • Overrides for follow-redirects and minimatch are raised to versions clearing the new advisories GHSA-mrwp-f3q8-3g9p and GHSA-g3hv-75wg-m249.

Refactors

  • Completeness spellings replay on the same command (get --brief → --depth brief), derived from CliFlagContract.values and read-output surface projection modes instead of a hand-maintained pair list.
  • Read-surface tables moved into a dependency-free module so pm --version works without installed dependencies.