Skip to content

feat(buds): edit impacted_repos from BUD detail - #195

Merged
mickyarun merged 8 commits into
mainfrom
feat/bud-edit-impacted-repos
Jun 3, 2026
Merged

feat(buds): edit impacted_repos from BUD detail#195
mickyarun merged 8 commits into
mainfrom
feat/bud-edit-impacted-repos

Conversation

@mickyarun

Copy link
Copy Markdown
Owner

Summary

Lets a PM correct the impacted-repos list from the BUD detail UI instead of hand-editing JSON or re-running the tech-arch agent. Adds an inline Edit affordance on BUDDevelopmentPanel.vue and a multi-select dialog.

Stacked on #194 (per-BUD branch overrides). That PR added impacted_repos to the BUDUpdate PATCH schema and the bud_impacted_repos_edited_post_planning audit log — this PR is purely the UI on top.

What changed

  • New BUDImpactedReposDialog.vue multi-select bound to the org's active tracked repos. Filter field, in-flight loader, per-row checkbox, aria-live count chip.
  • Repos already on the BUD but no longer active render as separate retired rows, pre-checked. The user consciously keeps or drops them — never silently erased.
  • Dialog always refreshes settingsStore.fetchRepos() on open (one cheap GET) so a repo added in another tab shows up before driving a destructive PATCH. In-flight fetch is memoised so reopen-during-load is safe.
  • Save → PATCH /v1/buds/{id} with the full new list. Clearing every row when the BUD previously had repos prompts a confirm — release-stage tabs and code-review status both go quiet on empty.
  • Empty-state copy on the chip row is reworded to read sensibly in any phase.
  • Dialog is non-persistent so Esc and backdrop-click work; persistent flag only activates during the in-flight save.

Test plan

  • vue-tsc --noEmit clean.
  • Open a BUD in any phase past tech_arch → click Edit next to impacted repos → uncheck one → save. Chip row updates, release-stage open-PR filter narrows to the new set.
  • Open with a BUD that references a retired repo. Confirm the retired row appears with the warning chip, pre-checked. Save with it kept → BUD still references it. Save with it unchecked → row drops on next reload.
  • Try to save the dialog with zero selections on a BUD that had repos → confirm prompt appears.
  • Open the dialog, add a new tracked repo in Settings, reopen — new repo appears in the picker without a full page reload.
  • Press Esc / click backdrop while idle — dialog closes. Click Save → during the spinner, Esc / backdrop are blocked.

Notes

  • The empty-state copy used to read tech_arch-only ("None set — pick the repos this BUD touches…"). It now reads naturally in development phase too.
  • The confirmation for clear-all is a plain window.confirm — that matches the existing destructive-action pattern in the codebase. A custom Vuetify dialog could replace it later if the team standardises on one shell.

mickyarun added 4 commits June 3, 2026 07:09
Lets a BUD opt out of the repo-wide tracking branch and watch its own
pattern instead. Release-train BUDs whose PRs target ``release/*`` can
be tracked without retraining the global repo setting; one-off ad-hoc
release branches can be pointed at directly.

Backend
- New ``branch_overrides`` JSONB column on ``bud_documents``, keyed by
  stage (``uat`` / ``prod``) with fnmatch-style values.
- ``BUDUpdate`` accepts ``branch_overrides`` and ``impacted_repos`` on
  PATCH. The validator rejects unknown stage keys, empty / whitespace
  patterns, and the wrong case (``"UAT"`` / ``"production"``) — typos
  surface as 422 at the API edge instead of silently missing in the
  filter.
- PATCH handler MERGES branch_overrides per-key so saving a UAT
  override doesn't clobber an existing prod override; ``{"uat": null}``
  is the clear-this-stage signal and drops the key from the merged
  column. Sending ``branch_overrides: null`` wipes both stages.
- ``bud_prs.py::release_stage`` honors ``bud.branch_overrides[stage]``
  before falling back to ``repo.uat_branch`` / ``repo.main_branch``.
  Reuses the existing ``branch_matches()`` fnmatch utility so wildcard
  semantics stay consistent with release detection.
- Editing ``impacted_repos`` after the planning phase logs
  ``bud_impacted_repos_edited_post_planning`` so an operator can audit
  scope changes that may leave PR rows linked to repos that no longer
  appear on the stage tab.

Frontend
- New ``BUDStageBranchOverride.vue`` widget rendered inside the shared
  ``BUDReleaseStagePanel.vue``. Shows the currently-effective pattern
  (override or repo default), an Edit affordance opening an inline
  dialog, and — for multi-repo BUDs — a one-line "applies to N repos"
  disclosure so the per-stage scope is explicit before saving.
- Save → PATCH ``/v1/buds/{id}`` with ``branch_overrides``; on success
  the panel re-fetches its stage data and emits ``refresh-bud`` so
  ``BUDDetail`` pulls the new override into the props feed.
- Empty input on Save and the dedicated Clear button both send
  ``{[stage]: null}`` — the merge-aware handler drops just that key.

Schema validator covered by 16 new parametrized tests.

Signed-off-by: Arun Rajkumar <mickyarunr@gmail.com>
The override widget previously described only the fnmatch half of the
filter ("Open PRs are matched against this pattern on each impacted
repo. Supports fnmatch wildcards"). After the over-match fix added the
content guard that requires PRs to also reference the BUD by number,
that copy understated what surfaces a PR on a release-stage tab.

Rewrites the in-card hint and the dialog body so both rules are
visible. The example is now per-BUD: BUD-4 sees
``release/bud-001-bud-004``, BUD-12 sees ``release/bud-001-bud-012``.
Threads ``bud_number`` from BUDDetail → BUDReleaseStagePanel → the
override widget so the copy renders the actual reference, not a
placeholder.

Signed-off-by: Arun Rajkumar <mickyarunr@gmail.com>
The validator hardcoded ``{"uat", "prod"}`` next to a comment that
already pointed at the existing ``Literal["uat", "prod"]`` in
``app.schemas.bud_release``. Drop the duplicate and source the
allowed-keys set from ``get_args(ReleaseStage)`` so adding a new
release-stage tab in one place automatically widens the override
contract — no second edit needed, no drift possible.

Behaviour and tests unchanged (16 cases pass).

Signed-off-by: Arun Rajkumar <mickyarunr@gmail.com>
Base automatically changed from feat/bud-branch-overrides to main June 3, 2026 06:39
mickyarun added 3 commits June 3, 2026 12:10
The tech-arch agent's initial guess at which repos a BUD touches is
often close but not perfect — and scope sometimes drifts mid-build.
This adds an Edit affordance next to the impacted-repos chip row on
``BUDDevelopmentPanel.vue`` so a PM can correct the list without
re-running the agent or hand-editing JSON.

UI
- ``BUDImpactedReposDialog.vue`` multi-select bound to the org's
  ``active`` tracked repos. Filter-by-name field, in-flight loader,
  per-row checkbox, count chip with ``aria-live`` so screen readers
  announce selection changes.
- Repos already on the BUD but no longer ``active`` in the tracked
  list render as separate "retired" rows, pre-checked. The user
  consciously preserves or drops them — never silently erased.
- Always refreshes the tracked-repo list on open (one cheap GET) so
  a repo added in another tab shows up in the picker before driving
  a destructive PATCH. In-flight ``fetchRepos`` is memoised so
  reopen-during-load is safe.
- Save → ``PATCH /v1/buds/{id}`` with the full new list. Clearing
  every row when the BUD previously had repos requires a confirm
  prompt — release-stage tabs and code-review status both go quiet
  on empty, so the consequence is surfaced before the write lands.
- Empty-state copy on the chip row is reworded to read in any phase
  (the previous imperative read as tech_arch-only).

Plumbing
- ``BUDDevelopmentPanel`` emits ``refresh-bud`` after a successful
  save; ``BUDDetail`` calls ``budStore.fetchBUD`` so the chip row
  updates everywhere and any downstream panel relying on
  ``bud.impacted_repos`` picks up the new list.
- Dialog is non-persistent so Esc and backdrop-click work; the
  ``persistent`` flag only activates during the in-flight save.

Backend already accepts ``impacted_repos`` on the ``BUDUpdate`` PATCH
schema and logs ``bud_impacted_repos_edited_post_planning`` for
mid-development edits — both landed in the per-BUD branch override PR
this stacks on.

Signed-off-by: Arun Rajkumar <mickyarunr@gmail.com>
Vite's Vue compiler rejected the no-matches placeholder because the
literal '.' between the inline v-if span and the v-else span counted
as a text node, breaking the v-if/v-else adjacency rule. Move the
two variants into <template v-if> / <template v-else> wrappers so
the directive pair sits on directly adjacent siblings with no
intervening text. Vue 3 template-compile rule — both branches still
render the same wording, only the wrapping element changes.

Found at runtime while testing the integration branch — would have
blocked the picker from rendering whenever the filter input matched
zero repos or no repos were tracked yet.

Signed-off-by: Arun Rajkumar <mickyarunr@gmail.com>
The Edit affordance only lived inside the empty-state branch of
``BUDDevelopmentPanel``. Once a BUD had any dev activity (commits,
PRs, todos), the panel switched to the has-activity template and the
button vanished — leaving no way to correct ``impacted_repos`` from
the UI on a BUD that had moved past tech_arch.

Reproduced on BUD-004 after promotion to development.

Adds a compact impacted-repos row at the top of the activity view
with the same Edit button. Mirrors the empty-state semantics —
chip list when the array has entries, "none yet" otherwise — but
slimmer so it sits cleanly above the stats grid.

Signed-off-by: Arun Rajkumar <mickyarunr@gmail.com>
@mickyarun
mickyarun force-pushed the feat/bud-edit-impacted-repos branch from 3e5a7fe to 3a75aac Compare June 3, 2026 06:41
@mickyarun
mickyarun merged commit 83f0e38 into main Jun 3, 2026
14 checks passed
@mickyarun
mickyarun deleted the feat/bud-edit-impacted-repos branch June 3, 2026 06:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant