--- type: Changed pr: 3318 --- **A percentage is now withheld everywhere its scope is not `COMPLETE`, not just at the sites Phase 3 reached** — closing ADR-3180 §7.6 rule 4 at the two remaining gaps an isolated review caught: `state json`'s `buildStateFrontmatter` no longer hardcodes `SCOPE.COMPLETE` when deriving `progress.percent` (it now threads the real `listMilestonePhaseDirs` scope through `_diskScanCache`, including its prose-fallback path, so a genuinely unreadable `.planning/phases` directory can no longer surface a stale or falsely-earned number there while every other surface withholds), and `roadmap analyze --json` now exposes the scope that actually gates `progress_percent` as its own `progress_scope` field — distinct from the top-level `scope` (heading-windowing identity) — so a consumer can tell *why* `progress_percent` is `null` from the JSON alone instead of seeing `scope: "complete"` next to an unexplained `null`. `state update-progress` also now writes a `[gsd-tools] WARNING:` line to stderr when it silently no-ops on a non-`COMPLETE` scope, so the skip is not visible only to a JSON `reason` field most callers never read. **`state sync` now also withholds**: it no longer hardcodes `SCOPE.COMPLETE` when deriving the percentage it writes into `STATE.md`'s body — a non-`COMPLETE` scope (confirmed reproducible on `TRUNCATED` and `UNSCOPED` fixtures, not just the previously-checked `UNREADABLE` case) skips the `Progress:` write entirely and records a `Progress: skipped — …(#3217)` entry in `changes`, instead of persisting a fabricated percentage that could disagree with the same write's own (already-scoped) frontmatter `progress:` block. `0` under a genuinely `COMPLETE` scope is unaffected and still renders. Tier-2: `progress_percent`, `percent`, and `plan_percent` are `number | null`; `computeProgressPercent` requires a `scope` argument; `roadmap analyze --json` gains a new `progress_scope` field; `state sync --raw`'s `changes` array can now contain a scope-skip entry and correspondingly withhold a `Progress:` body write it would previously have made. (#3217)