Changed (SDK contract)
- GH-1707: URL credential redaction strips host and path from public URLs with @ in the path, and a stored credential-bearing identity is echoed verbatim in claim refusals: A public URL with an @ in its path lost its host and path and withheld the retry; a credential-bearing PM_AUTHOR, --author or --assignee was stored and echoed verbatim in claim refusals → Only an http(s), ws(s) or ftp URL that provably holds no userinfo is left alone, so scoped-package and blob URLs keep an executable retry; an asserted or configured identity, --assignee, a seed author or an identity runtime field carrying URL userinfo is refused with invalid_argument_value, and refusals, warnings and claim envelopes redact a stored one. Migrate: Use a plain name for PM_AUTHOR, --author, default_author, --assignee and seed author= values; rewrite a holder stored by an older version with pm update <id\> --assignee <name\> --force, or take it over with pm claim <id\> --force elemento pm-gh1707
- GH-1704: secret guard flags short credential values only under password keys; api_key, client_secret, token and \*\_TOKEN/\*\_SECRET keys pass: A short credential value under api_key, client_secret, token, secret_key, private_key, passwd, pwd or a compound key such as DB_PASSWORD or GITHUB_TOKEN produced no finding → Such a value produces a credential_key_assignment finding in advise mode and is refused in block mode; pm token budgets, counts, placeholders, masks, paths and prose stay clean. Migrate: Accept the credential_key_assignment rule id wherever finding rules are matched; replace the literal with a placeholder or reference, or review a force override in block mode elemento pm-gh1704
Security
- Identity refusal reads only top-level fields, so a runtime field mapped onto comments, notes, learnings or dependencies can store a nested author with URL userinfo elemento pm-ziv9yb
Changed (SDK contract)
- A time-bounded gate waiver expires straight into a release block: no notice window, and the gate's text output names neither the item nor the expiry: Reports said nothing about an approaching expiry; a waiver stayed silent until it expired and failed the gate → Reports carry waiver_notices for valid live waivers inside the declared waiver_notice_days window, and ok is unchanged. Migrate: Code that constructs BoundaryFixtureReport or DefectGateEvidenceReport adds waiver_notices: \[\]; declare waiver_notice_days in the policy or registry to receive notices elemento pm-xcndcu
- pm update --unset blocked_by (or --blocked-by none) deletes every blocked_by edge, not only the scalar's: clearing blocker A silently drops an independent prerequisite B: Clearing the scalar removed every blocked_by dependency edge → Clearing the scalar removes only the rows naming its own target; independent blocked_by edges keep blocking, and removed rows are named in a dependencies_removed warning. Migrate: Remove the remaining edges with --dep-remove kind=blocked_by, or one at a time with --dep-remove id=<id\>,kind=blocked_by elemento pm-4yxzvd
- A key repeated inside one structured entry silently replaces the earlier value, so note prose such as ', path: b.txt' relinks a different file: A key repeated inside one entry kept its last value → A repeated key is refused with structured_entry_key_repeated before anything is written. Migrate: Give each key once per entry, quote prose that contains a key-shaped word, or repeat the flag for another entry elemento pm-oglm0t
- files/docs --add refusal does not name the note segment it misread as a key, nor offer the standalone --note flag: Note prose misread as a key was refused with invalid_argument_value or a generic command failure → It is refused with linked_artifact_note_key_misread, naming the segment and key, with a retry that quotes the note. Migrate: Match the new code, or follow recovery.suggested_retry_args elemento pm-pwqiao
- GH-1700: pm test --add returns only the changed linked test, like pm comments --add: A write returned the whole stored collection, count was the stored total, and failure_categories was always present → A write returns only the entries it added or rewrote, with count (returned), total_count, mutation_receipt and omission_receipt; failure_categories appears only when tests ran. Migrate: Pass fullHistory (CLI --full-history, MCP full) to receive the whole collection after a write, read total_count for the stored total, and read failure_categories optionally elemento pm-gh1700
Fixed
- The release Sentry gate counts environment=test issues, so a downstream extension's CI test run blocks the daily pm-cli release elemento pm-usn5k2
Other
- Exclude the repository-only release runbook docs/RELEASING.md from the npm tarball to restore publication headroom elemento pm-pvun8c
- Exclude five repository-only docs from the npm tarball to restore publication headroom for the collection-mutation bundle elemento pm-tuxw1i
Security
- Telemetry and Sentry scrubbers keep URL credentials whose host has no dot: attempted_args ships https://token@localhost and user:password@registry:8080 verbatim elemento pm-5htunt
- Refusal recovery bundles echo URL credentials verbatim: attempted_command and normalized_args repeat a credentialed package source on stdout and in logs elemento pm-nhauur
- GH-1699: secret guard recognises quoted keys, nested JSON values and XML elements elemento pm-gh1699
Other
- Exclude the dated Codex plugin research plan from the npm tarball to restore publication headroom elemento pm-7ouxrr
Fixed
- Distinguish Vitest coverage-threshold exits from test assertion failures in combined runner verdicts elemento pm-qmb6h8
- GH-1694: recover pinned Bun and verified uploader downloads after GitHub asset gateway failures elemento pm-gh1694
- GH-1693: preserve complete flag tokens in bounded close-refusal headlines elemento pm-gh1693
- GH-1689: redact leading-slash regex sources with indexed safe refusals elemento pm-gh1689
- GH-1695: accept settings paths and provide bounded config-key recovery elemento pm-gh1695
Other
- Stabilize alias clear/prune race verification under monolithic release coverage elemento pm-01kwb2
- Restore publication headroom with lossless declaration delimiter compaction elemento pm-5aze0q
- Adopt the next mature tooling maintenance cohort after registry cooldown elemento pm-ogzvx6
Fixed
- MCP pm_comments lists only the newest 20 comments by default: the backward output cursor stops at that producer page and the last page reports has_more without a continuation elemento pm-sbqn4h
- Combining an annotation or linked-artifact mutation with a universal output control is refused untyped: code command_failed and pm --help examples instead of a stable code and a retry without the control elemento pm-rrwh2o
- TOON get --fields drops an empty child collection nested inside a selected object field, while JSON keeps it elemento pm-fkhdy8
- TOON annotation listings drop null rows while count reports them, so a malformed collection renders fewer rows than its count elemento pm-e3hfv8
- Release verification shares the build job's timeout and waits fifteen minutes while npm's publish-time scan can hold a version longer: 2026.11.8 was published but the job was cancelled before acceptance elemento pm-0jzl5t
- A malformed comments, notes or learnings entry in an item document crashes annotation reads with unknown_error (sortLogValues calls localeCompare on a missing text) elemento pm-30tjoh
Other
- Exclude the dated ecosystem planning review from the npm tarball to restore publication headroom elemento pm-1ke3mz
Fixed
- MCP annotation and linked-artifact tools silently read when add is passed at the top level: the strict schema declares add/text but dispatch only hoists ifAbsent elemento pm-wsqxwb
- pm comments --edit/--delete take an absolute index while a budget-truncated listing reports count as the page size and shows no row index, so 'edit the last comment' by count rewrites an older comment elemento pm-hka7ep
- Bare pm comments / pm notes reads keep the oldest page when output must be bounded, withholding the newest entries (GH-1605 fixed this for history only) elemento pm-8s53lj
- CLI argv keeps one value silently when two spellings of one extension flag differ (--status-filter a -s b), while direct callers are refused with extension_option_spelling_conflict elemento pm-wlxf8f
- pm comments/notes <id\> --add --file <path\> is refused as positional-and---add conflict instead of naming the swallowed --file flag, so the annotation flag-like check from pm-vcu7 loses precedence elemento pm-y26mvc
- GH-1667: sdk/graph does not export ProjectedGraphResult, the public return type of runGraph, and the merge conflict_resolution union has no public name, so extensions derive both elemento pm-gh1667
- GH-1666: per-command help and contracts for extension commands omit the inherited host flags (--json, --author, --pm-path) the command accepts and mark no flag as host- or extension-owned elemento pm-gh1666
- GH-1665: extension flag contracts omit the SDK option key, so PmClient.run and the extension test harness silently ignore a CLI-spelled option such as status-filter and fall back to the default elemento pm-gh1665
- TOON get --fields spends four lines on a complete omission receipt and drops requested empty collections, so a narrow read is two-thirds receipt and absent-vs-empty depends on that receipt elemento pm-sj66lm
- GH-1662: an infeasible --token-budget on context --for orient exits 0 with no context and contradictory receipts, its restore_with retry fails, and get/list intent receipts undercount the emitted envelope elemento pm-gh1662
- GH-1678: a scoped registerRenderer replacement bypasses --output-budget and its read_output receipt reports within_budget for the native payload, not the delivered bytes elemento pm-gh1678
Other
- Restore package headroom by excluding the generated refusal-closure census from the npm tarball elemento pm-dwy8kb
- Unknown-option refusals on extension commands with declared flags carry code unknown_option and list only the flags the command accepts elemento pm-1du7s3
Fixed
- GH-1677: the stale-revision refusal's next_steps and examples drop --pm-path, --no-extensions and the output mode, so the recovery reads return another tracker's item elemento pm-gh1677
- GH-1676: a pm close refused for missing close fields suggests a separate pm update and a retry, although pm close accepts --resolution, --expected-result and --actual-result itself elemento pm-gh1676
- GH-1674: pm list --fields/--compact and pm search print the verbose envelope that GH-1642 removed from the default projection, so --fields costs more than the default elemento pm-gh1674
- GH-1663: nested get --fields projections pad unrequested sibling collections with empty arrays (linked.files emits tests: \[\] and docs: \[\] for populated collections) and claim_state.claimed expands to the whole group elemento pm-gh1663
Other
- Packing ships only the declarations an exported types entry reaches, restoring the artifact headroom PR 1680 exhausted elemento pm-dg68kr
Fixed
- Release refuses an over-budget Sentry-injected package before tagging instead of stranding the tag elemento pm-ofllco
- GH-1670: pm health --full --summary silently drops --summary and emits the full projection (15.7 KB vs 636 B) with no receipt elemento pm-gh1670
Fixed
- GH-1660: the project telemetry block pm init writes is inert, so the wizard's telemetry decline and the project endpoint are ignored, and no supported way points opted-in tests at a local collector elemento pm-gh1660
- Start-blocker and revision-conflict follow-ups from the PR 1654 CodeRabbit full review elemento pm-mrvq8u
- Expected revisions advance from the pre-override document when an item_store_write override transforms contents elemento pm-thbdxu
- GH-1655: SDK placeholder and type refusals name CLI flags, and parent: null is refused, so typed callers have no documented way to clear a field elemento pm-gh1655
Fixed
- Starting work ignores open blockers: claim <id\> --start and update --status in_progress move a blocked item into progress without a refusal or warning elemento pm-urzubi