Harden SDK schema-driven input fidelity and package preflight

Merged
UN
4mo ago
+604-71

Summary

  • make extension list: true flags preserve values across mixed long and short aliases
  • make template-defined custom item types participate in schema-driven create validation
  • reject malformed dependency shorthand consistently across create and update
  • preserve every repeated --ac value through Commander and normalize it once at the SDK boundary
  • expose reserved item-field names and reject package schemas that collide with core item fields
  • document the public contracts and cover the complete behavior through unit, integration, contract, CLI, and installed-package dogfood tests

Project management

  • closes pm-kfq5
  • closes pm-l6rz
  • closes pm-zazb
  • closes pm-b84u
  • closes pm-ghf1
  • closes #496
  • closes #497

The five related items were claimed, implemented as one coherent SDK/CLI package-authoring bundle, fully evidenced through pm, closed, and released. No unrelated item remains in progress.

Verification

  • pnpm build
  • pnpm typecheck
  • pnpm lint (ESLint, zero-copy jscpd, docstring/import-boundary/token-efficiency gates)
  • node scripts/run-tests.mjs coverage: 5,514 tests, 100% statements, branches, functions, and lines
  • focused linked item tests through pm test --run --progress
  • pnpm docs:check
  • pnpm skills:check
  • pnpm contracts:check
  • pnpm audit --audit-level high
  • pnpm security:scan
  • pnpm changelog:pm && pnpm changelog:pm:check using pm-changelog 2026.7.10
  • packed and installed @unbrained/pm-cli into a fresh temporary project; verified repeated acceptance criteria, malformed-dependency rejection, and public SDK reserved-field linting
  • pm health --check-only --summary --json: healthy, zero warnings
  • pm validate --check-resolution --check-history-drift --json: zero history drift; existing repository resolution-metadata warnings remain unchanged

Observability

Telemetry coverage is healthy with no missing error codes. The Sentry release gate continues to identify PM-CLI-1Y and PM-CLI-1Z, handled spawn errors originating in the external pm-starter package's legacy pm --path ... calls; this change neither introduces nor masks those external-package events.


Summary by cubic

Hardens schema-driven input fidelity and SDK preflight to prevent silent data loss and dangling deps. Repeatable parsers and coercion now preserve argv order across aliases; templates apply custom scalar options safely; --dep shorthands validate early.

  • Bug Fixes
    • Extension flags with list: true accumulate repeated long/short alias values and comma lists using one shared accumulator across visible/hidden aliases; parse occurrence provenance is carried into coercion so interleaved aliases keep exact argv order through CSV flatten; accumulators reset per parse; nullish alias values are ignored; arrays are deduped; scalar aliases canonicalize without duplicate keys (pm-kfq5, GH-496).
    • Mixed --acceptance-criteria/--acceptance_criteria/--ac accumulate in argv order and are joined with ; once at the SDK boundary; Commander-null/undefined alias keys are ignored; the runtime contract lists distinct repeatable aliases, and templates keep it scalar to avoid double-joining (pm-b84u).
    • Templates apply custom type-option fields via the validated --type-option pipeline; explicit type-option inputs override primitive template defaults; template custom options no longer override canonical create fields; non-scalar custom values are rejected while scalar string/number/boolean are accepted (pm-l6rz, GH-497).
    • --dep shorthand is guarded; malformed inputs like related:pm-abcd fail fast with an id=<id>,kind=<kind> hint on both create and update (pm-zazb).
    • SDK exports RESERVED_ITEM_FIELD_NAMES as a non‑mutating ReadonlySet with standard iterator methods; lint/preflight/harness reject blueprint item-field names that collide with core metadata keys (pm-ghf1).