chore: promote CHANGELOG for v1.12.0

This commit is contained in:
github-actions[bot]
2026-08-30 03:06:22 +00:00
parent 9fe51d4de9
commit ceed559fd4
151 changed files with 171 additions and 755 deletions

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3815
---
**Workflows no longer send AI runtimes hunting the filesystem for the GSD shim** — 50 places across 23 runtime-loaded workflow, agent, reference, and command files told the agent to run `gsd-tools.cjs` by filename, which is not on PATH under any name. The agent got "command not found", fell back to locating the file, and on Git Bash for Windows `find /` walked the entire drive until someone killed it. Every one now calls the canonical `gsd_run` launcher. (#3809)

View File

@@ -1,5 +0,0 @@
---
type: Changed
pr: 3922
---
**`--pick <field>` now exits non-zero when a field is absent, and `parseNamedArgs` strictly rejects unrecognized flags and stray positionals** — previously an absent `--pick` field printed an empty string at exit 0 (indistinguishable from a genuinely empty answer, #3365), and a stray or unrecognized argv token was silently dropped rather than rejected, in one case corrupting STATE.md by running a command against the wrong phase (#3358). Both now fail loudly instead of silently: `X=$(gsd_run query V --pick F) || X=default` observes the real failure it was written for, and an unrecognized flag or positional exits non-zero naming what was wrong. (#3884)

View File

@@ -1,5 +0,0 @@
---
type: Changed
pr: 3925
---
**Diagnostics stop reporting a clean result when they had to drop data to get one.** `intel query`'s recursive search now stops at 48 levels and marks the result `truncated: true` instead of quietly matching arbitrarily deep (a match past the ceiling now reports truncated rather than found, and no longer crashes with a stack overflow past ~12000 levels); `phase-plan-index` now names an unresolved `depends_on` token in its own warning instead of blaming the plan's declared `wave:` for a dependency edge the tool itself dropped, and that warning's own token is escaped so an attacker-authored token cannot forge a second warning line; and a code-review run where every lane failed no longer writes a `REVIEWS.md` synthesized from nothing, preserving each lane's raw output first. (#3885)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3670
---
**`/gsd-ingest-docs`, `/gsd-import`, `/gsd-audit-fix`, `/gsd-profile-user`, and `/gsd-docs-update` now honor model routing for their subagents** — the doc classifier/synthesizer/verifier, roadmapper, plan-checker, fix executor, and user-profiler subagents (plus the debugger spawned by the `diagnose-issues` workflow behind `/gsd-verify-work`) ran on the calling session's model, silently ignoring `dynamic_routing`/`model_profile` tier config. Each workflow now resolves the per-agent model and passes it on the spawn (omitting it when it resolves to inherit/empty per #2517). (#3602)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3690
---
**Upgrading the Codex runtime no longer aborts when a top-level config key sits below the GSD marker** — the regenerated `[agents]` table captured such keys into its scope, so post-write schema validation rejected the merged `config.toml` and the install failed mid-flight. Surviving top-level keys are now hoisted above the managed block, preserving their file scope. (#3610)

View File

@@ -1,5 +0,0 @@
---
type: Added
pr: 3678
---
**Verify-command path grounding for phase planning** — a plan's `<automated>` verify command whose target directory does not exist (or holds no `package.json`) is now caught deterministically before execution instead of being hand-reasoned by the plan checker, which previously prescribed wrong replacement paths. The planner also inherits the nearest prior phase's proven verify commands at every context window, not only above 500k. (#2401)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3826
---
**`phase complete` now reports `roadmap_updated` and `state_updated` honestly** — both flags read `fs.existsSync()`, so they were `true` for any project that had the file at all, and a rollup that silently wrote nothing was indistinguishable from one that landed. Each flag now reflects whether that file's content actually changed in the transaction, matching the contract `requirements_updated` already honored. (#3685)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3733
---
**`windows` ledger commands survive a formatter pass** — the WINDOWS.md ledger's JSON block is written with a four-backtick fence, which Prettier and other CommonMark formatters legally narrow to three; the reader then rejected the file and every `gsd-tools windows` subcommand (status/append/waive/fixed) failed with "Ledger missing JSON code block". The reader now accepts any CommonMark-legal fence width (the writer still emits four), resolves the real block past fences planted in entry descriptions, and preserves user prose below the ledger; the refactor-trigger proposal reader gets the same fence tolerance. (#3657)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3847
---
**Stage the emitted-drift-ack sweep around open PRs** — sweeping an all-spent fragment used to delete it unconditionally, handing any open PR that still touched the same file a modify/delete conflict it did not cause (#3330, #3774, #3648). The guard now holds a fragment back when an open PR still touches it, deferring the sweep until that PR merges or closes. (#3842)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3814
---
**Resuming `/gsd-execute-phase` on a phase whose verification passed but whose run died before marking complete now finishes the job** — the phase is marked complete, progress state advances, phase todos close, and the transition handoff runs, instead of every resume reporting "nothing to do" while the roadmap checkbox stays unticked forever. Already-completed phases keep exiting cleanly, and verification is never redone. (#3684)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3844
---
**`state validate` now sees the `last_activity` invariant, and `--strict` makes the verdict gateable** — a STATE.md whose `Last activity` value no reader could parse used to validate clean (`{valid:true, warnings:[], scope:'complete'}`), and a wrapped description was silently truncated; both are now reported as coded diagnostics (`S008`/`S009`). `state validate --strict` exits non-zero when the report is not valid, so a CI step or git hook can gate on state correctness without parsing JSON — the default exit status is unchanged. (#3696)

View File

@@ -1,5 +0,0 @@
---
type: Added
pr: 3716
---
**Live-DOM UAT: browser-backed UI acceptance checks during execution** — a phase whose acceptance criteria needed a live DOM could not be finished by the agent that executed it, so it silently degraded to "executed, then finished by hand in the orchestrator". Enable `workflow.live_dom_uat` (default off) and a purpose-built `gsd-dom-verifier` checks those criteria after each wave and reports whether it looked, or could not. The plan executor's tool surface is unchanged in every configuration. (#2856)

View File

@@ -1,5 +0,0 @@
---
type: Changed
pr: 3999
---
**A twelfth hand-rolled slug copy can no longer land, and two existing ones are fixed.** `generateSlugInternal` is the canonical slug owner, but nothing prevented a call site from re-deriving it — and two had: `qa-smell-ratchet` trimmed before truncating instead of after, so any non-ASCII input collapsed to just its ASCII tail, and a test helper claimed parity with a function that transliterates while itself not transliterating. A new drift guard now fails the build on an unsanctioned re-derivation, with three legitimately-different sites explicitly sanctioned. (#3987)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3728
---
**`/gsd:plan-phase` no longer writes gitignored install-mirror paths into plans** — `files_modified` and artifact paths are now verified against `git ls-files` and resolved to tracked source (e.g. a plugin's own tree) instead of a runtime mirror under `.gsd/capabilities/`, whose edits died on every capability sync; paths inherited from PATTERNS.md are re-verified so one mirror path can no longer self-propagate across phases. (#3645)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3774
---
**`milestone complete` now requires an explicit `--confirm` to mutate** — the command irreversibly archives ROADMAP.md/REQUIREMENTS.md, MOVES every phase directory in the milestone, and rewrites STATE.md, yet ran unconditionally on first invocation through every invocation path, including `query milestone.complete <version>`, whose `query` meta-prefix reads as a read-only namespace but performs no filtering. Without `--confirm` (and without `--dry-run`) the command now refuses before touching anything and names the flag that proceeds; `--dry-run` still previews the exact move list with no confirmation needed, and is now documented in the command's own usage block. `--force` keeps its narrow meaning (bypass the TRUNCATED-scope / unstarted-phase guards) and does not double as the mutation opt-in. The `/gsd-complete-milestone` workflow passes `--confirm` at its archive step. (#3726)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3725
---
**In-process installs can no longer write a kind's `home` override into your real home** — a runtime kind with a global `home` override (codex skills → `$HOME/.agents`) resolves from `os.homedir()`, not from the caller's config dir, so a test that sandboxed only its target directory pruned every `gsd-*` skill from the developer's real `~/.agents/skills` while the suite still passed and the manifest still reported a healthy install. All six writers that resolve a kind `home` now refuse when a `node --test` run would land inside the real home, compared by filesystem identity rather than pathname and decided on where the write resolves rather than how it is spelled. Scope is stated rather than implied: the six are the writers on the `installRuntimeArtifacts` call tree, and this covers destinations a runtime kind resolves through a `home` override, not every path the installer touches through `os.homedir()` (`writeNonClaudeDefaults`' `~/.gsd/defaults.json` is still reached by a spawned installer with an un-sandboxed HOME) and not writers off that tree (`cmdGenerateDevPreferences` resolves the same codex `home` override through `getGlobalSkillsBase` and writes `SKILL.md` beneath it unguarded; it has no in-process caller today, so it is latent rather than live). Canonicalization fails CLOSED rather than falling back to the lexical spelling — an unresolvable component (`EACCES`/`ELOOP`/`EIO`) is refused, since that fallback is the exact ALLOW an aliased `<sandbox>/.agents` needs; only `ENOENT`/`ENOTDIR` walk up, matching `identify`'s own errno split. Two limits are named in the source rather than papered over: a subordinate bind mount of the real directory into a sandbox is not detectable without mount-table introspection, and on a host with no readable passwd entry the guard falls back to a caller-set marker — which must itself identify, and must contain every destination, so a layout captured before the sandbox is still refused. Real installs are unaffected. (#3712)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 4049
---
writing any markdown file no longer converts tight multi-line lists to loose ones — a blank line was injected before every bullet following a wrapped item (61 blanks on a 1015-line ROADMAP via phase.complete; the defect sat in the write seam every .md write uses), and tight vs loose lists render differently so this was a rendering change plus large misleading diffs, not just whitespace (#3854)

View File

@@ -1,5 +0,0 @@
---
type: Changed
pr: 3789
---
**Section separators now render responsively instead of wrapping** — stage banners, checkpoints, completion and error panels used fixed-width runs of box-drawing characters (a 53-column `━` rule, a 62-column `╔═╗` box). In a narrower pane those runs wrap and the border comes apart from the heading it framed. GSD now emits Markdown headings and `---` thematic breaks, which adapt to the available width in every runtime. (#3028)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3790
---
**Managed hooks now resolve the node binary at hook-fire time** — a config root shared across environments (WSL/Docker bind-mounts, mounted or synced `~/.claude`) no longer fails every managed hook with `node: not found` outside the machine that ran the installer, and updates from any environment converge stale runners instead of creating a mixed state where no environment works. `--portable-hooks` installs route through a staged `hooks/gsd-node-runner.sh` resolver (install-time path first, then `command -v node`, then well-known layouts); other installs carry an equivalent inline fallback chain. (#3662)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3803
---
**/gsd-pr-branch now refuses to verify a PR branch that would delete planning files the target branch tracks** — the verification step counts planning-tree deletions via git diff --name-status and fails on any non-zero count, instead of reporting clean while pre-existing planning content was stripped. The underlying deletion class in the cherry-pick filter was already fixed by the strict-mode rewrite; this makes the workflow able to detect it. (#3679)

View File

@@ -1,5 +0,0 @@
---
type: Added
pr: 3824
---
**GSD now publishes a machine-readable state snapshot at every step boundary** — external tools that show project state no longer have to parse STATE.md and ROADMAP.md heuristically. `.planning/state.json` carries a versioned `contract`, the current `milestone`, every phase with its `complete`/`in_progress`/`pending` status, and the same recommended `next` action the `/gsd` front door routes. The write is best-effort and can never fail, slow, or alter the command that triggered it. (#3227)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3694
---
**Codex worktree-parallel executors now launch with the full executor contract** — the orchestrator-worktree process spawn handed its child a short objective-only prompt, so executors reconstructed their role by repository search and force-staged gitignored SUMMARY.md files (`git add -f`) to satisfy an unconditional commit criterion. The spawn prompt now carries the embedded executor workflow, required reading with the explicit plan path, the gsd-executor persona, and skip-aware success criteria, and halts before spawn when the contract embeds cannot be resolved. (#3637)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 4019
---
**`workflow.inline_plan_threshold` now has one default owner** — the key is registered in the defaults manifest (default `2`), so `config-get` resolves the absent key instead of erroring, `settings-advanced` no longer misdocuments the default as 3, and every shipped surface (workflow fallback, reference tables) agrees. (#3801)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 4022
---
**`audit-uat` sees workstream phases again** — the audit now enumerates all three phase-archive layouts (flat `milestones/vX.Y-phases/`, archived workstream `milestones/ws-*/phases/`, and active workstream `workstreams/<ws>/milestones/`), with workstream entries labeled `<ws>/<version>` so acknowledge-by-milestone stays unambiguous. A project using workstreams no longer gets an All Clear audit while items are open, and `--ws` no longer empties the report. Phase lookups keep their #2855 workstream scoping unchanged. (#3804)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3967
---
**`workflow.use_worktrees=false` at the root now applies inside workstreams too** — the dispatch-isolation resolver inherits the root opt-out under `GSD_WORKSTREAM` exactly as `config-get` does, so a root-level opt-out no longer leaves workstream runs recording `harness-worktree` over the mandated `none`. (#3963)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3852
---
**`phase complete` no longer advances to an inserted phase that merely has a directory** — the next-phase resolution scanned phase directories first and only consulted ROADMAP.md when the disk turned up nothing, so an inserted decimal phase (whose directory `phase insert` scaffolds immediately) outranked the phases preceding it in roadmap order. The wrong successor was reported and written to STATE.md as the resume pointer. Roadmap order now decides which phase is next; the disk still supplies the on-disk spelling when both agree, and remains the fallback when no roadmap is readable. (#3701)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 4050
---
the STATE.md Quick Tasks log accepts milestone-suffixed section headings (Quick Tasks Completed (v1.1+)) — the exact-anchored lookup never matched them, so every /gsd:fast append and milestone reset silently failed before the columns were even checked; among several matching sections the one with a recognized table schema wins (#3860)

View File

@@ -1,5 +0,0 @@
---
type: Changed
pr: 3941
---
**Non-Claude installs now resolve their own runtime by default, and `depends_on` accepts the bare plan number.** A Codex, Cursor, or other non-Claude install with no `GSD_RUNTIME` set and no `config.runtime` key previously still reported `claude` everywhere, because the per-install runtime marker the installer writes was read by four hand-rolled copies but never by `resolveRuntime` itself; it is now the third precedence rung. Separately, `depends_on: ["01"]` now resolves to the in-phase sibling plan instead of silently dropping the dependency and collapsing the plan into wave 1 — a phase that previously ran all its plans in a single wave now executes in its declared waves. Codex sandbox permissions are also now derived from each agent's own tool contract instead of a hand-maintained map, and `validate agents` reports any drift via a new `sandbox_posture` field; both are byte-identical to today's behavior. (#3897)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 4013
---
**`--config-dir` installs no longer plan removals of the default home's live legacy install** — the legacy get-shit-done-cc cleanup is scoped to the resolved config dir when `--config-dir` redirects the install (scan, shared cache, and per-package cache alike), the `--dry-run` preview shows the same scoped plan the real install would apply, and `--no-legacy-cleanup` skips the scan entirely. (#3799)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 4057
---
a spaced-hyphen thematic break (- - -) inside a UAT file ## Gaps section is no longer parsed as a gap entry — it fabricated a phantom open gap named "- -" with result unknown that audit-uat surfaced as outstanding work which could not be cleared by editing any entry (#3898)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3935
---
**No more console-window flash on Windows in non-GSD repositories** — the graphify auto-update hook ran a hidden `node` process to parse its payload before checking whether the project uses GSD at all; the cheap `.planning/config.json` and `CI` checks now run first, so non-GSD projects and CI pay for zero child processes per Bash tool call. (#3729)

View File

@@ -1,5 +0,0 @@
---
type: Added
pr: 3700
---
**Statusline can now warn that STATE.md has fallen behind the code** — enable `statusline.show_state_freshness` and the GSD-state segment renders `state ~N commits back` once HEAD is 20+ commits past the commit STATE.md was written against, the same advisory threshold `/gsd-health`'s W024 uses. Off by default; costs one bounded git call per render only while enabled, and stays silent rather than guessing when freshness cannot be established. (#2734)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3766
---
**docs/INVENTORY.md rows are now enforced** — a shipped agent, command, workflow, reference, CLI module, or hook could be added to the generated manifest with no row in the authoritative roster and still pass CI; the roster is now anchored the same way the manifest is, and 32 pre-existing gaps are backfilled. (#3762)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3950
---
**`total_plans` no longer counts REPLAN/PLANNING documents as plans** — a phase directory carrying a `REPLAN-INPUTS` or `PLANNING-NOTES` document no longer inflates the plan count that STATE.md derives on every state-mutating call. (#3741)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3979
---
**The isolation guard no longer denies sequential dispatches a workstream explicitly opted out of** — the sentinel-absent fallback now reads `workflow.use_worktrees` through the same project/workstream-aware ladder as the resolver and `config-get`, instead of the flat root config where a workstream-local opt-out was invisible. (#3972)

View File

@@ -1,5 +0,0 @@
---
type: Changed
pr: 3848
---
**The launcher now proves which `gsd-tools` it resolved before running any verb** — a project-local or config-directory install that cannot answer `runtime-identity` with an `@opengsd/gsd-core` payload now produces one actionable warning naming both causes (a foreign package, or a gsd-core older than the verb) and exports `GSD_IDENTITY_STATUS=unverified`, instead of silently handing a state-mutating verb to a tool written for a different contract. (#3841)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 4008
---
**`gsd-roadmapper` no longer contradicts itself on write-vs-approve ordering** — the agent's role, output format, and completion checklist now match its write-first execution flow (write for durability, return `## ROADMAP CREATED` with a preview; the orchestrator presents and owns the approval gate), and the orphaned `## ROADMAP DRAFT` template that matched no orchestrator branch is gone. (#3797)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3828
---
**`windows append`/`waive`/`fixed` no longer silently erase a hand-edited ledger table** — `.planning/WINDOWS.md` renders its table from the fenced JSON that is its source of truth, and every write regenerated that table without ever checking the two still agreed. A hand-edited cell was reverted and a table-only row vanished entirely, both at exit 0 with nothing on stdout. The write is now refused with a `windows_ledger_table_drift` error naming the offending row ids, and the file is left untouched. (#3689)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3863
---
**Agent frontmatter no longer reverts to catalog Anthropic models when `model_policy` is configured** — the install-time bake for the static-frontmatter runtimes (OpenCode, Kilo) read `model_profile` and `model_profile_overrides` but never `model_policy`, so every update rewrote agent `model:` fields to `anthropic/claude-*` IDs that a custom provider does not serve, while dispatch-time resolution honored the policy correctly. The bake now consults the same policy resolver dispatch uses, at the same precedence: an explicit per-agent `model_overrides` entry still wins, then `model_policy`, then the tier table. (#3705)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3815
---
**`gsd-core/references/` is now covered by the bare-command guard** — the #2751 guard only ever scanned `agents/` and `gsd-core/workflows/`, so 37 bare `gsd-tools <verb>` calls sat unguarded in a directory it never looked at. They now call the canonical `gsd_run` launcher, and the guard scans references too. (#2751)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 4069
---
**Release coverage gate no longer OOMs as the test suite grows** — `test:coverage:unit` (used by the release finalize/rc jobs) and `test:coverage:report` (the sharded coverage-gate merge step) now pass c8's `--merge-async` flag, so raw V8 coverage files are merged one at a time instead of all being loaded into memory at once. (#4068)

View File

@@ -1,9 +0,0 @@
---
type: Fixed
pr: 3903
---
**UAT rows separated only by a lone carriage return were silently dropped from the audit-uat scan.** A `VERIFICATION.md` or `deferred-items.md` written with lone-CR line endings rendered normally to a human reader, but reported zero outstanding items to the audit, hiding real human-verification and deferred-work entries. Both file types now surface their rows exactly as their LF/CRLF equivalents do.
**Planning-inspect now surfaces UAT rows separated only by a lone carriage return.** The same lone-CR line-ending gap also hid rows from planning-inspect's own UAT reporting; a row that previously vanished from `uat.unresolved` now appears there too, matching its LF/CRLF equivalents.
**A UAT row whose `result:` line had trailing text containing a Unicode line or paragraph separator (U+2028/U+2029) is no longer dropped.** A column-0 `result:` line whose text after the token happened to contain one of these separators previously failed to parse at all, silently discarding an outstanding row; it now parses the same as its plain-line equivalent. (#3707)

View File

@@ -1,5 +0,0 @@
---
type: Changed
pr: 3965
---
**Two lint rules that could not reach the code they govern now do, and `quick-tasks-append` stops overwriting curated progress values.** `local/no-adhoc-markdown-parsing` self-gated on its own filename, so it silently skipped every `.cts` file in a `src/` subdirectory and could not be widened by configuration alone; it now also covers `tests/` and `scripts/`, and the 80 hand-rolled markdown parses it surfaced are routed through the existing sectionizer and table seams — including one test that asserted against the wrong table column and so could never fail. `local/no-adhoc-regex-escape` examined only bare identifiers, missing the property-access shape runtime data actually arrives in, which is why it never caught a known ReDoS. Separately, `quick-tasks-append` gained optional `--quick-id`/`--slug`/`--directory` so a caller with a real quick task emits the canonical row, and a body-only append no longer forces a re-derive of disk-derived progress frontmatter that replaced curated values. (#3951)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3966
---
**~/.gsd/defaults.json is written under the install-migration lock and in a single atomic write** — concurrent installs for different runtimes can no longer lose each other's settings, and a crash mid-write can no longer truncate this machine-global file (which the read path treats as absent, silently degrading model resolution for every project on the machine). An install that changes nothing no longer rewrites the file.

View File

@@ -1,5 +0,0 @@
---
type: Added
pr: 3720
---
**`/gsd-pr-branch` gains a strict mode that keeps every planning artifact out of the PR branch** — set `planning.pr_strict: true` and the generated PR branch carries no `.planning/` path at all, structural files included, so a project can version its planning tree locally (keeping executor worktrees and `/gsd-undo` working) while publishing none of it. Defaults to `false`, which reproduces the previous classification and preservation exactly. (#2971)

View File

@@ -1,5 +0,0 @@
---
type: Changed
pr: 3831
---
**Shipped workflows can no longer reach a different package's `gsd-tools`** — a second package publishes a binary of the same name whose `phases.clear` deletes where GSD's archives, so a workflow could destroy planning directories and still print success. Workflows now resolve `gsd_run`, which only this package publishes, and stop with an install message rather than falling back to whatever `gsd-tools` is on `PATH`. Adds `gsd-tools runtime-identity` for confirming by hand which tool a project is running against. (#3146)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3720
---
**`/gsd-pr-branch` no longer deletes the base branch's planning files or silently drops commits** — the generated PR branch used to stage a deletion for any `.planning/` path the target branch already tracked, and a second commit touching the same planning file aborted the cherry-pick with "untracked working tree files would be overwritten", dropping that commit and every one after it. The filter now forces excluded paths back to what the target branch tracks in both the index and the working tree. Verification also asserts against the active filter mode instead of an unconditional zero, so a correct default-mode run that preserved `STATE.md` no longer reports itself as failed. (#2971)

View File

@@ -1,6 +0,0 @@
---
type: Changed
pr: 4029
---
**Removed a dead code path** — `listMilestoneArchiveDirs` (caller-less since the Phase-12 snapshot migration) and its test seam are gone; the #1883 unreadable-milestones regression suite now pins the live planning-snapshot path. (#3813)
<!-- docs-exempt: internal dead-code removal — the deleted helper had no production caller and no documented behavior; the replacement regression suite pins the live path's existing documented UNREADABLE scope contract -->

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 4034
---
audit-open summary counts now include the display-truncation remainder: a milestone with more than 5 open files reported counts capped at 5 because the _remainder_count display marker was counted as one item instead of the real files it records (#3817)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 4052
---
smart-entry classifies a STATE.md status of verified (or verification) as verify-pending instead of falling through to unknown — the classifier matched the exact word verify and missed the verif stem its own normalizeStateStatus uses (#3864)

View File

@@ -1,5 +0,0 @@
---
type: Added
pr: 3924
---
**A second terminator for code that cannot wait for the event loop, and a versioned exit-code projection** — hooks and other write-then-exit callers can now terminate through the same registry lookup that `runMain` uses, so both agree on what every outcome means. Exit integers are versioned: today's behavior is `v1`, and `--exit-contract=v2` (or `GSD_EXIT_CONTRACT=v2`) opts into the registry's codes ahead of the next major. (#3906)

View File

@@ -1,5 +0,0 @@
---
type: Changed
pr: 3980
---
**`milestone complete` blocks again when the roadmap still lists unstarted phases** — that guard had been silently swallowed, so milestones could be archived with work outstanding and nothing said so. Two more guards that inspected an error's message before deciding whether to re-raise were failing the same way and are fixed with it, and `extract-messages`/`profile-sample` no longer dump a raw Node stack trace on top of their error line. A new lint rule now rejects a raw `process.exit()` outside the sanctioned terminator, so a guard cannot quietly stop guarding this way again. (#3910)

View File

@@ -1,5 +0,0 @@
---
type: Added
pr: 3976
---
**New ESLint rule `local/no-exact-case-env-access`** — flags an exact-case read of a Windows case-varying environment variable (`PATH`, `PATHEXT`, `ComSpec`, `USERPROFILE`, `TEMP`, `TMP`, `APPDATA`) off any object other than `process.env` itself, closing the gap ADR-1703's portability catalog left on production Windows semantics. (#3624)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3732
---
**`/gsd:config --integrations` no longer prescribes writes that fail** — the review-models section states the real rule (only reviewer lanes whose capability declares a modelConfigKey are settable; the nine settable lanes are enumerated; cursor/qwen/coderabbit named as keyless) instead of a validation pattern that never existed, and agent-skill lists are now written as JSON arrays instead of a comma-joined string that resolves as one broken skill path. (#3651)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 4054
---
the phase-taking init.* queries (execute-phase, plan-phase, verify-work, code-review, phase-op, review, discuss-phase-assumptions, todos) accept --phase <N> as an alias for the positional form, matching phase list-plans; a valueless --phase is now a usage error instead of silently answering phase_found:false for a phase that has plans (#3865)

View File

@@ -1,5 +0,0 @@
---
type: Changed
pr: 3880
---
**The STATE.md field reference is generated from one schema, and the status lifecycle now appears in every language** — the key set, its types, enums and cardinality are declared once and projected into the field-classification tables, the shipped template and all five reference documents, so a field can no longer be described one way in code and another in the docs. The `Status lifecycle` section, which documents the status values, was missing from the Japanese, Chinese, Korean and Portuguese references and is now present in all of them. (#3873)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3952
---
**STATE.md frontmatter comments now survive every state write** — a column-0 comment no longer depends on an unrelated body line being present, and an indented comment above the `progress:` counters (the natural provenance spot) is preserved instead of silently stripped. (#3742)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3727
---
**`state` no longer lets a lone non-matching milestone section's phases become another milestone's `total_phases`** — with exactly one milestone section in ROADMAP.md and a STATE.md asserting a different milestone, the section's phases were silently written as the asserted milestone's total (clobbering the stored value). Both that shape and the multi-section one now keep the stored total and warn, naming the asserted milestone. Flat roadmaps (no milestone headings at all) are unchanged. (#3642)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 4041
---
the shipped hook tables documented gsd-validate-commit.sh as PostToolUse (it is registered PreToolUse — exit-2 blocking is its contract) and gsd-session-state.sh as PostToolUse (registered SessionStart); 18 wrong rows corrected across ARCHITECTURE.md and INVENTORY.md in en/ja-JP/zh-CN/ko-KR/pt-BR, with a new docs-vs-surface parity suite guarding all ten tables (#3839)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3998
---
**`audit-open acknowledge` works on heading-shaped deferred-items.md** — the CLI writer previously refused every entry in any file using the heading-delimited (#3457) convention (a real project saw 0 of 107 items acknowledgeable); leaf headings and interleaved headless bullets now acknowledge through the same span-anchored, span-verified write the bullet shape uses, with a human `Status: resolved` never downgraded. Only entries embedding a GFM table row still refuse. (#3781)

View File

@@ -1,5 +0,0 @@
---
type: Changed
pr: 3888
---
**`.planning/` frontmatter is now parsed by a real YAML parser.** Block scalars, quoted keys and non-ASCII keys are read correctly instead of being mangled or silently dropped, and a document whose frontmatter cannot be parsed keeps its frontmatter block instead of losing it on the next write. (#3881)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3921
---
**Antigravity global skills and agents now install to `~/.gemini/config/`** — the directory Antigravity actually scans for machine-local discovery, so installed skills are no longer silently ignored at startup. Upgrading an existing install automatically removes the old artifacts from the deprecated `~/.gemini/antigravity` location (modified files are backed up; user-authored files are preserved). (#3738)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3891
---
**Codex worktree executors now run on the model you pinned for them.** With `model_overrides.gsd-executor` set, `$gsd-execute-phase` spawned its worktree executor with no `--model` argument at all, so the child silently fell back to the global Codex session model — and because this path spawns a process rather than dispatching a named agent, the model baked into `gsd-executor.toml` could not apply either. An explicitly pinned model is now passed to the spawned process. An unpinned, blank, or `inherit` configuration still emits no model argument and keeps the session-model fallback, so Codex's session-only model posture is unchanged and no tier-derived model is ever sent. A pin that is Anthropic-flavored (`sonnet`, `opus`, `claude-*`), flag-shaped (e.g. `-c`), or otherwise outside the model-id character set is now dropped with a stderr warning instead of being sent to Codex — which would 400 — or aborting the whole run. (#3714)

View File

@@ -1,5 +0,0 @@
---
type: Added
pr: 3708
---
**New `planning inspect` query emits a schema-v1 snapshot of the whole planning state** — downstream harness UIs and dashboards can now read milestone identity, active position, per-phase verification/roadmap-acceptance/UAT evidence, requirement traceability, plan and task rows, and progress fractions from one read-only JSON document instead of parsing GSD's Markdown a second time. Unknown or conflicting evidence is reported as `unknown` with a coded diagnostic rather than inferred. (#2790)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3896
---
**`generate-slug` and phase/workstream slugs no longer diverge from the canonical formula.** — Some slug-producing commands and internal call sites re-implemented the ASCII slug formula by hand instead of delegating to the shared one: Cyrillic and other non-Latin titles could collapse to an empty slug where the canonical transliterates them, and slug truncation could leave a dangling trailing hyphen (regression of #2849). Every slug call site now delegates to the single canonical implementation. (#3883)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 4006
---
**Interrupted executors can be resumed again** — execute-plan deleted `current-agent-id.txt` before the check that read it, so the interrupted-agent detection and its Task `resume` prompt were unreachable after a kill; the id is now captured before the stale marker is cleared. (#3795)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3961
---
**Workflow config comparisons work again for string values** — every shipped `config-get` bash call site now passes `--raw`, so string-typed values (runtime, response_language, discuss_mode, …) reach shell comparisons unquoted instead of as JSON with literal quotes that never matched. (#3763)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 4048
---
gsd-mempalace-curator no longer hardcodes model: sonnet in its frontmatter — the only pin in the 34-agent fleet; it intercepted the deliberate inherit case (agents inherit the orchestrator model when resolution is inherit) and operators could not durably remove it. Default profiles keep sonnet via the model catalog; model_overrides and inherit now work (#3895)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3767
---
**A malformed config section no longer destroys the value it holds — or gets written back to disk.** If `.planning/config.json` had a `git` or `planning` key holding a string instead of an object, migrating a legacy top-level key into it expanded that string into numbered character keys (`"main"` became `{"0":"m","1":"a","2":"i","3":"n"}`), and the result was saved over the original file — so the value could not be recovered. Numbers and booleans were dropped outright. The migration is now declined instead: the section, the legacy key, and the file are left exactly as written, and a warning names the file so it can be fixed by hand. (#3760)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3971
---
**`GSD_PROJECT`-scoped projects keep their signals and probes in their own tree** — `init manager`'s waiting signal, `map-codebase`'s dir/maps probes, `skill-manifest --write`, and `init.new-project`'s codebase-map readiness now all resolve through the project-aware planning dir instead of the repo root. (#3964)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3933
---
**`/gsd-capture --backlog` no longer scatters backlog items across per-item branches** — `query commit`'s phase-branching arm now treats `999.x`/`0.x` backlog sentinels as non-phases, so a backlog capture commits on the current branch instead of silently creating and switching to a `gsd/phase-999.*` branch per item. (#3734)

View File

@@ -1,5 +0,0 @@
---
type: Changed
pr: 3825
---
**Plans must now say what output constitutes failure** — every runnable `<automated>` acceptance command needs a `<fails_when>` sibling naming an observable failure signal, and `/gsd-plan-phase` blocks a plan that omits one. A command with no expressible failure mode is not an acceptance test. Breaking for phases planned before this release: re-check reports one blocker per unstated command until statements are added or the phase is re-planned. (#3172)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 4042
---
phase add and phase add-batch now count phase numbers held by sibling git worktrees before allocating max+1, instead of colliding with them (the reported incident minted a second Phase 441 while a worktree already held one with six written plans); add-batch also now counts roadmap bullet rows (#1229 finally reaches the batch path) (#3849)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3893
---
**Sentinel phases no longer skew estimation calibration.** Backlog and icebox phase directories (milestones 0 and 999) were counted as completed phases when rebuilding the calibration factor, so a single one could switch calibration on from phantom evidence and two could corrupt the factor outright. (#3882)

View File

@@ -1,5 +0,0 @@
---
type: Added
pr: 3648
---
**`git.protected_branches` config field warns on additional shared branches, not just the resolved base branch** — a git-flow project whose GitHub-default branch differs from its actual integration branch (e.g. `main` vs. `develop`) can now list `develop`/`staging`/etc. so `execute-phase`'s `handle_branching` "none" strategy and `/gsd-ship`'s preflight warn on any of them, not only the one resolved base branch. Optional and additive — absent by default, existing projects see no behavior change. (#3552)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3994
---
**Two QA oracles no longer report findings against the wrong field.** `routing-validity` demanded a live-command token from `recommended`, which is an action id by design, and also validated `recommended_command`, a field nothing in the repo produces; it now checks the fields that actually carry tokens. `value-hygiene` reported command tokens such as `/gsd:progress` as leaked absolute paths, and now exempts them by value shape rather than by key name, so a `command` field holding a genuine absolute path is still reported. (#3913)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 4046
---
a timed-out git commit is now reported as commit_timeout with the stale .git/index.lock path surfaced in the error, instead of commit_failed with the killed hook's partial stderr; the commit call also moves to the 30s band the push call uses (pre-commit hooks alone can exceed the old 10s cap) (#3886)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 4001
---
**`/gsd-progress` no longer presents archived milestones\' verification debt as current-milestone debt** — the Verification Debt warning segments by the audit\'s `archived_milestone` stamp (current vs still-open-in-archived-mileses), keeps the archived segment visible with its own label, and no longer silently reads zero on large audits (`@file:` payload unwrap). (#3782)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 4025
---
**Acknowledged moot items stay closed in `audit-uat`** — the `audit_acknowledged` frontmatter marker (the documented, self-invalidating "this item is moot" seam) now suppresses items in `query audit-uat` exactly as it already does in `audit-open`, with the same snapshot keys and a visible `acknowledged_files` count — no more choosing between lying (`status: passed`), inventing tokens, or deleting the planning record. (#3805)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3903
---
**A phase with an unreadable UAT row no longer reports an affirmative milestone completion percentage.** Previously, one specific unreadable class — UAT rows hidden inside a closed code fence — was exempted from degrading a phase's fold, so a milestone could still publish a completion percentage over work nobody could actually see. Every class of unreadable UAT content now withholds the milestone's percentages the same way. The per-phase signal is unchanged: a phase's own `uat.scope` already reported "truncated" for this case and still does. (#3707)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3989
---
**`audit-open acknowledge` no longer silently strands or clobbers Title-case status lines** — a bare `Status:`/`STATUS:` marker is now acknowledged through a line the reader actually parses instead of being rewritten in place invisibly, and a human-written `Status: resolved` is left untouched rather than downgraded to `acknowledged`. (#3775)

View File

@@ -1,5 +0,0 @@
---
type: Security
pr: 3966
---
**Atomic config writes preserve hardened file permissions and create temp files exclusively** — a chmod 600 on settings.json, settings.local.json, or defaults.json now survives the temp+rename write instead of silently resetting to the umask default; temp files are opened with O_EXCL so a symlink pre-planted at the predictable temp path is never followed; and the install-migration lock writes its payload through the exclusively-created descriptor, closing a symlink-swap window between create and write.

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3966
---
**A malformed settings.local.json survives the #338 migration** — readSettings()'s null "could not parse, preserve existing" signal is now honored and the whole migration stands down, so the shared GSD entries are not stripped either. Also fixes two crashes on that path: an unparseable settings file previously aborted the install with a TypeError instead of skipping the file.

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 4007
---
**The milestone audit report is written where its readers look for it** — `/gsd-audit-milestone` created the report at a doubled `.planning/v{version}-v{version}-MILESTONE-AUDIT.md` path while every downstream reference (Report pointers, the `cat`, the completion checklist) reads the single-version `v{version}-MILESTONE-AUDIT.md`, so the report silently landed unread. (#3796)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3680
---
**`check-glossary-refs` no longer reports a false clean** — backtick-pairing parity let stale file references in CONTEXT.md hide behind RULESET predicate lines, so renamed files stayed invisible to the drift gate. Visibility is now structural (per-line pairing + predicate-value harvesting), the renamed test reference is corrected, and retired-file mentions are exempted by name. (#3604)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3846
---
**`state update` now explains why a field was not written, instead of reporting it as absent** — asking to update a frontmatter key such as `stopped_at` returned "not found in STATE.md", byte-identical to a genuinely missing field and pointing away from the body field that does work. The refusal now names the body source, or names what derives the key when it has no body source. A document whose frontmatter carries a key with no body source at all — previously unrepairable through this command — can now be fixed by writing the key directly, reported as `wrote: "frontmatter"`. (#3699)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 4018
---
**`local/require-registered-exit` now catches computed and optional-chained `process.exit()` calls.** The rule previously missed `process['exit']()` and `process?.[k]?.()` forms where the property name is a statically resolvable string, letting a raw terminator slip past the ADR-3889 registered-exit contract. It now resolves a computed property to a string literal (directly, or through a single never-reassigned string-literal-initialized binding) and flags those forms too. `n/no-process-exit` remains registered everywhere it already was — the two rules are complementary, not predecessor/successor, so neither is retired. (#3914)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3867
---
**OpenCode subagents now carry the reasoning effort GSD resolved for them** — `query resolve-execution` reported an effort level that never reached the generated OpenCode agent, so every subagent ran at whatever the runtime defaulted the model to, silently ignoring `effort` config. The bake now emits a `variant` key alongside `model`, and `effort sync` maintains it, so changing effort config no longer needs a reinstall. The key is written only when effort is actually configured; `inherit` and any level OpenCode does not accept omit it rather than naming a variant that cannot resolve. Config-supplied `model` and `variant` values are also quoted whenever YAML would not read them back verbatim — previously a value containing a newline could inject extra top-level keys into a generated agent file, and values like `no`, `12:30`, `@org/model` or a bare date were silently retyped or truncated. (#3706)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 4059
---
**Raised the emitted-drift acknowledgment cap from 64 to 128** — a wide-touching maintenance PR could legitimately accumulate more distinct commit-trailer acknowledgments than the old ceiling allowed, failing CI even though nothing was wrong. (#4058)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3888
---
**`gsd-tools --project-dir <path>` now works** — the flag was documented in docs/CONFIGURATION.md's multi-repo workspace resolution section but wired nowhere, so it was silently ignored and every command still resolved the project root from cwd. Passing `--project-dir` now sets the project root directly and skips the ancestor walk-up, as documented. (#3881)

View File

@@ -1,5 +0,0 @@
---
type: Added
pr: 3695
---
**Code review depth can now be scoped by repository path** — set `workflow.code_review_depth_overrides` to a list of `{paths, depth}` rules and a review touching a sensitive directory such as `src/auth` automatically runs at the stronger tier, while the rest of the repository keeps the standard depth. Paths are matched as directory prefixes on whole path segments (glob syntax is rejected with a clear configuration error), `--depth=` still wins, and the resolved depth and the rule that matched are printed in the review output. (#2554)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 4028
---
**`state advance-plan` refuses an ambiguous Current Position instead of silently advancing the first entry** — when the section carries more than one `Phase:` line (the wave-log style), the command now returns a typed `ambiguous_position_phase` error naming every candidate and leaves STATE.md byte-identical, instead of silently advancing the first entry's plan counter (in the reporting incident, a hard-gated final plan 7→8 of 8) with `advanced: true` and no ambiguity signal. (#3807)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3832
---
**Every reviewer lane can now be given a prompt-token cap, and the documented global `review.max_prompt_tokens` finally works** — the nine CLI reviewer lanes declared no budget key, so no cap could reach them by any configuration, and the central global was advertised in the config schema but declared nowhere, so setting it changed nothing. Each CLI lane now accepts `review.max_prompt_tokens_per_reviewer.<slug>` on the same terms as the local-server lanes, and the global resolves as the documented fallback. Defaults are unchanged: with nothing configured, no lane trims. (#3691)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3966
---
**The installer writes settings.json and settings.local.json atomically (temp+rename)** — a crash mid-write can no longer truncate the file. Hosts discard the entire settings file on a parse failure, so a truncated write previously cost users every hook, permission, env var, and statusline they had — not just GSD's.

View File

@@ -1,5 +0,0 @@
---
type: Changed
pr: 3944
---
**The API-coverage seal gate no longer clears a phase it never examined** — a phase with no plan body and no roadmap section previously ran the detector over zero bytes and sealed as "no external-API integration"; it is now held with `scope_unavailable`, and the assumption-delta checkpoint reports `skipped` instead of a fabricated `detected:false` when it cannot resolve a phase section. (#3909)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3687
---
**Capability hooks can no longer be silently registered-but-never-run** — the capability validator now checks that each host call site's dispatch text covers every hook KIND registered at that point (a gate-only consumer fails validation when a step or contribution hook is registered there), and the plan/execute/verify host consumers now dispatch steps and contributions generically per the loop hook contract instead of hand-rolling one kind. (#3606)

View File

@@ -1,5 +0,0 @@
---
type: Changed
pr: 3718
---
**The phase researcher no longer treats missing metadata as a compatibility constraint** — a claim like "this library does not support that runtime version", drawn from an absent `python_requires`, `engines` field, per-version classifier, changelog entry, or support-matrix row, no longer earns `[VERIFIED]` however authoritative the registry or docs consulted. An absence says nothing about the version being ruled out and nothing about the version being standardized on, so the same evidence would "prove" both; the only route from an absence to `[VERIFIED]` is a positive falsification attempt with its failing output pasted, and everything short of that stays `[ASSUMED]`, which already routes through a confirmation checkpoint before it can lock a decision. A present declared constraint and an affirmatively documented incompatibility are untouched. Previously an honestly-tagged absence could lock a CONTEXT.md decision and produce a real version downgrade that no downstream stage re-derived. (#2951)

View File

@@ -1,5 +0,0 @@
---
type: Added
pr: 4043
---
**CI shard/job timeouts now self-report near-cap and accumulate a trending history.** Every matrixed CI job (test, test-full, mutate, smoke) warns in its own run once it crosses 90% of its timeout-minutes budget, and a new scheduled workflow keeps a durable, accumulating record of elapsed-vs-cap across runs — so a lane drifting toward its cap is visible before it actually breaches, not just after. (#4036)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 3978
---
**Reduced the complexity of the refactor-trigger evaluate handler.** `handleEvaluate` scored above the complexity-triggered-refactor feature's own default threshold; the read/analyze loop and the artifact/baseline/ledger write path are now separate named helpers, with no change to CLI behavior, output shape, or reason codes. (#3267)

View File

@@ -1,5 +0,0 @@
---
type: Fixed
pr: 4015
---
**A killed test chunk now names the file that was hanging.** `scripts/run-tests.cjs` logged only chunk starts, so a chunk killed at the 600s cap printed ~55 basenames and left the operator to guess which one hung — and every timing figure had to be reconstructed from CI log timestamps. It now emits per-chunk elapsed time on every path, names the files still in flight on a kill with how stale the last event is (hang vs. merely slow), and ranks the chunk by known weight, flagging files missing from the timings table. (#4012)

Some files were not shown because too many files have changed in this diff Show More