Skip to content

Docs: Minor/Major Release Watchers - #461

Open
kiran1287 wants to merge 20 commits into
mainfrom
docs/release-watchers
Open

kiran1287 wants to merge 20 commits into
mainfrom
docs/release-watchers

Conversation

@kiran1287

Copy link
Copy Markdown
Contributor

Replaces #457, closed automatically when its source branch was renamed via the GitHub branch-rename API (which deletes the old ref rather than migrating the PR, contrary to what I expected). No commits were lost -- this PR is the exact same branch content under its new name, docs/release-watchers.

Summary

  • minor-release-watcher.yml — twice weekly (Mon/Thu), scans only the current minor/patch line (2.0.0 -> 2.0.1 -> ...). Never touches main.
  • major-release-watcher.yml — biweekly (every other Monday), scans only main for the next major (2.0 -> 2.1 -> ...). Classifies main-branch PRs as genuinely major-only vs. not-yet-backported minor work (backport search first, then deep scrutiny of "Type of change" if none found), and folds in a completeness check for already-tracked multi-PR features.

Both add a real dry_run mode (a genuine preview option, not just a testing artifact), a since override for the first catch-up run (see Testing below), and drop the redundant needs-docs label — every issue either workflow files already means that by existing.

Also includes .ai/release-watchers/PROCESS-OVERVIEW.md — full process documentation: overview, design principles, both workflows step by step with their actual prompt logic, the schedule, required secrets/variables, and known limitations. (This doc still describes the pre-fix lookback mechanism in a couple of places -- a correction pass is planned once everything below settles.)

Testing — what's actually been verified, and how

Everything below was checked on disposable branches, never a PR, per explicit request. Being specific here on purpose, since an earlier version of this description overstated what had been confirmed.

Confirmed working, via real live-API calls on disposable branches:

  • The plain gh CLI commands this workflow depends on (label create, issue create/comment/edit/close) work against the live API with the default GITHUB_TOKEN
  • The lookback mechanism itself: an earlier version used a repo Actions variable to remember the last run's timestamp -- confirmed by direct testing that the default GITHUB_TOKEN gets a 403 on that API regardless of declared permissions, so it never actually worked. Replaced with gh run list --event schedule, which only needs read access and was confirmed to filter correctly by trigger event
  • The major watcher's extra wrinkle -- an off-week scheduled run also reports status: success while skipping its real work -- confirmed via the Jobs API that per-step skipped vs. success is reported correctly, and the lookback walk uses that to find the last real on-week run, not just the last non-erroring one
  • The new since override input: confirmed it takes priority over the computed lookback when set, and falls through to the normal computation when blank
  • The FORCE_DRY_RUN safety switch added for the first live rollout: confirmed the if: gate keyed on it actually skips the label-creation step, DRY_RUN resolves to true from it, and Claude's allowed tools genuinely omit gh issue create/edit/comment while it's on -- not just told not to use them, physically unable to
  • De-duplication checks both marker prefixes (old daily-watcher:pr-X from before this workflow existed, and the new per-workflow prefix), confirmed live that searching by number alone finds either
  • De-duplication also checks the "Backport #X" title pattern real backport PRs use, not just "Fixes #X" -- confirmed against real upstream backport PRs
  • Major/minor classification logic verified by manually walking it against real PRs both ways: a since-backported PR (glossary pagination, #32223 -> #32473) correctly excluded, genuinely major-only PRs (dark mode switcher #32383, sourceConfig validation #29566) correctly included
  • No orphaned test artifacts left behind -- every temporary label/issue/branch used in testing was cleaned up and verified closed/deleted

NOT yet verified -- and can't be, before this merges:
schedule, workflow_dispatch, and issue_comment triggers only fire from a repo's default branch -- this is a GitHub platform constraint, not something we chose to skip. That means the actual claude-code-action step (the part that reads real PRs, applies the filter/verify logic, and would create/update issues) has never executed successfully in a real run yet -- only the surrounding bash/gh logic above has been proven live. An earlier attempt to test it via a push-triggered disposable branch failed outright (claude-code-action doesn't support push as a trigger event) -- that failure was found only while re-verifying this PR's own claims, and is why this section is now this explicit.

Post-merge steps (do these before considering this fully live)

  1. Run minor-release-watcher.yml and major-release-watcher.yml via workflow_dispatch from main. FORCE_DRY_RUN is hardcoded to "true" in both files, so this is safe regardless of what's passed in -- neither workflow can create, edit, or comment on anything yet.
  2. Read the digest issue each produces ("Minor/Major Release Watcher — Scan Digest") and sanity-check it against what's actually open upstream right now. This is the first time the real prompt logic runs against live data end-to-end.
  3. If that looks right, flip FORCE_DRY_RUN to "false" in its own small, separate, reviewable commit -- that's the actual go-live moment.
  4. Separately, execution-test create-draft.yml's real git-push/PR-open path via an actual /create-draft comment -- also blocked pre-merge for the same platform reason above.
  5. docs-collate is explicitly out of scope for this PR. It currently has its own, separate copy of the same broken lookback mechanism found and fixed here; that gets ported over in a dedicated follow-up pass after this merges.

kiran1287 and others added 13 commits September 1, 2026 14:05
Scans merged open-metadata/OpenMetadata PRs daily, filters for doc
relevance using the existing upstream-watch-config.md rules, groups
related PRs, and opens de-duplicated tracking issues. Draft-PR
creation is deliberately out of scope for this first pass.
Commenting /create-draft on a Daily Watcher issue reads the real source PR(s), drafts the doc content with every claim checked against the actual diff, flags anything unverifiable under a Needs-verification heading, and opens a draft PR linked back to the issue. Opt-in per issue, never automatic - mirrors the trust model already used by /content-review.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Retires daily-watcher.yml and major-release-completeness-check.yml in
favor of two independent, symmetric workflows:

- minor-release-watcher.yml: twice-weekly (Mon/Thu), scans only current
  minor/patch release branches (2.0.0 -> 2.0.1 -> ...), self-healing
  lookback via real run history instead of a fixed day-count.
- major-release-watcher.yml: biweekly (every other Monday), scans only
  main for the next major (2.0 -> 2.1 -> ...), classifies main PRs as
  genuinely major-only vs not-yet-backported minor work (backport
  search first, deep scrutiny of Type of change if none found), and
  folds in the completeness check for already-tracked multi-PR features.

Both add a real dry_run mode (not just a testing hack) and drop the
now-redundant needs-docs label per earlier feedback.

Verified before commit, via disposable branches (no PR opened):
- GITHUB_TOKEN permission chain (label/issue create/comment/edit/close)
  confirmed working end-to-end against the real API.
- Found and fixed: the lookback step's gh run list call had no failure
  handling -- bash -e would abort the whole step on any API hiccup
  before ever reaching the documented fallback. Now neutralized.
- Found and fixed: dedup only checked each workflow own marker
  prefix, so neither new workflow would have recognized issues created
  before the split (e.g. issue 428's daily-watcher marker) -- confirmed
  live that searching by number alone finds it regardless of prefix.
- Found and fixed: dedup never checked for the Backport-title pattern
  real backport PRs actually use, only Fixes-X -- confirmed against
  real upstream backport PRs.
- Major watcher backport-vs-major classification verified against
  real PRs both ways: a since-backported PR (glossary pagination,
  PR 32223 -> PR 32473) and genuinely major-only PRs (dark mode 32383,
  sourceConfig validation 29566) both classify correctly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Explains the full flow: the problem being solved, design principles,
both workflows step by step with their actual prompt logic, the
schedule, required secrets/variables, known limitations, and a summary
of what was verified before this went anywhere near main.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
main had re-ignored release.config.json and .ai/release-checklist/ via
an accidental sweep-in from PR #426 (a homepage-carousel commit with
no mention of this tooling) -- confirmed nothing else on main
references or uses these paths. Kept our version: both stay tracked,
since both new watcher workflows read release.config.json directly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…sted-content, dry-run, trigger match, stale baseline, unpinned actions

- Paginate the upstream gh pr list scans in both watchers (default limit
  30 silently dropped most of a busy release window; verified live --
  193 PRs merged to OpenMetadata's 2.0 branch alone since the lookback
  cutoff). Added --limit 500 to both main scan queries.
- Stop advancing the lookback watermark from `gh run list --status
  success`: a manual dry-run and (for the major watcher) a scheduled
  off-week both complete successfully without scanning anything or
  writing a tracker record, so using them as the cutoff permanently
  skips that interval. Read the persistent digest issue's own latest
  comment timestamp instead -- it only gets a new comment after a real,
  non-dry scan actually finishes, so it's an exact, self-maintaining
  watermark with no separate bookkeeping. Also fixed a real
  DRY_RUN-vs-"always runs" contradiction in the major watcher's own
  Part C wording that this fix's correctness depends on.
- Committed scripts/check-release-consistency.sh for real and dropped
  `scripts/` from .gitignore -- both checklists require it, but it was
  gitignored and never actually in the repo, so a release pass halted
  immediately. Ran it locally against this repo to confirm it works
  before committing.
- create-draft.yml: stopped handing a write-capable agent an issue's
  raw, unvalidated body. Anyone can open a public issue; a real
  MEMBER's /create-draft comment on an attacker-opened one would
  otherwise feed adversarial content to a session already holding
  contents:write, pull-requests:write, and push/PR-create tools. Added
  a deterministic pre-step (no model involved) that requires an exact
  standalone `/create-draft` command (the job-level check is only a
  cheap substring pre-filter, and matches on incidental prose like
  "don't run /create-draft yet"), confirms the issue was actually filed
  by this repo's own bot identity, and extracts the source PR numbers
  from the watcher's own marker comments via regex -- gating checkout
  and the agent step on that validation, and having the prompt act on
  the pre-extracted PR list rather than free text. Caught and fixed a
  real bug in this same step during local testing: an empty grep match
  under `pipefail` was aborting the script before reaching its own
  graceful error message.
- Made dry-run enforcement structural instead of prompt-only in both
  watchers: `Bash(gh issue create/edit/comment:*)` are now absent from
  --allowedTools entirely when dry_run is true, so a prompt-injected
  model can't call them regardless of what it's told -- not just
  discouraged from doing so.
- Added `Bash(gh pr diff:*)` to both watchers' --allowedTools and
  updated their prompts to actually call it -- they promised real-diff
  verification but only had `gh pr view` (no patch mode) available.
- Updated release.config.json's stale 1.13.4/2.0.0/2026-08-24 baseline
  to the versions actually shipped since (1.13.5, 2.0.1, 2026-09-02).
- Pinned actions/checkout and anthropics/claude-code-action to the same
  reviewed commit SHAs already used in doc-review.yml/doc-review-auto.yml
  in this repo, instead of the mutable v6/v1 tags, across all three new
  workflows.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Replaced two different, both-broken lookback designs with one that's
actually been execution-tested:

- minor-release-watcher.yml: was using the digest issue's last-comment
  timestamp (real bug: no author filter, any human reply corrupts the
  baseline). Now uses gh run list --event schedule --status success --
  filtering to schedule events specifically means a manual dry-run
  workflow_dispatch can never contaminate it, without needing any
  elevated permissions.

- major-release-watcher.yml: same fix, plus one more wrinkle specific
  to its biweekly gate -- an off-week scheduled run also completes
  with status success while doing nothing, so --event schedule alone
  isn't sufficient here. Now walks back through recent schedule runs
  and checks whether "Ensure tracking labels exist" (already gated to
  on-week, non-dry runs only) actually ran vs. was skipped, via the
  Jobs API's step-level conclusion.

Both permissions reverted from actions: write back to actions: read --
the repo-variable approach both files had adopted (from whoever fixed
these after I last touched them) needs Variables-write access that the
default GITHUB_TOKEN does not have regardless of what's declared in
permissions, confirmed by direct testing: a live repo variable
read/write attempt failed with a 403 "Resource not accessible by
integration" on its very first call. That mechanism has never actually
worked in either repo.

Every piece of this fix was verified with a disposable branch before
being written into the real files, not assumed correct from the YAML
alone:
- Confirmed the repo-variable approach 403s in this environment before
  ruling it out (not just reasoning about it)
- Confirmed gh run list --event <type> actually discriminates by
  triggering event, with a real push vs. schedule comparison
- Confirmed the Jobs API reports step-level success vs skipped
  correctly, with a real run containing both cases

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Both watchers now accept an optional `since` (YYYY-MM-DD) input on
workflow_dispatch. When set, it overrides the computed lookback outright
and skips the normal run-history walk.

Why this is needed: the lookback fix in Fix #1 works by finding the
previous successful scheduled run and using its timestamp. The very
first real run after merging has no such run to find, so it would fall
back to the fixed 4-day (minor) / 15-day (major) window -- silently
missing any backlog older than that on day one. `since` lets that first
run be pointed at an explicit date instead of guessing.

Verified with a disposable push-triggered test branch
(test/since-override-check, deleted after use) exercising both branches
of the bash logic directly: override set -> its value wins and the step
exits before the fallback computation runs; override blank -> fallback
computation runs normally. Both passed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Both watchers now carry a workflow-level env FORCE_DRY_RUN, set to
"true". While it's true:
- The "Ensure tracking labels exist" step is skipped outright.
- DRY_RUN is forced to "true" for the claude-code-action step,
  regardless of trigger -- including the real schedule cadence, not
  just a manual workflow_dispatch.
- The write commands (`gh issue create`/`edit`/`comment`) are removed
  from Claude's allowedTools list entirely, not just described as
  off-limits in the prompt. Even if the model ignored DRY_RUN, it has
  no tool available to act on that.

This makes the first pass after merging safe by construction rather
than by trusting a manual toggle: the schedule can fire for real before
anyone gets around to testing it, and this guarantees that run can only
ever read and report, never write.

The plan once merged: run each workflow for real via workflow_dispatch
from main (only possible post-merge), read the digest output it prints,
and only then flip FORCE_DRY_RUN to "false" in its own separate,
reviewable commit.

Verified on a disposable push-triggered branch
(test/force-dry-run-check, deleted after use) that:
- the if: gate keyed on env.FORCE_DRY_RUN actually skips the step
- DRY_RUN resolves to "true" from the env context, not just the input
- the allowedTools string genuinely omits the write commands
All three passed against the exact expression forms used in the real
files. (The first attempt at this test had its own bug -- an unquoted
colon-space inside a string broke YAML parsing -- caught by the same
verification pass meant to catch it.)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Replaces reading release.config.json for version numbers with a
deterministic bash step that parses the current version straight out
of this repo's own already-published snippets/releases/latest.mdx (the
first, and only, <Update label="X.Y.Z Release"> in that file -- it's
replaced wholesale on every release, never accumulates).

Why: what's "current" is a publishing decision this team already makes
and ships -- it shouldn't live in a second, separately-maintained file
that can silently drift out of sync with what's actually published.
Deriving it from the same page a human already reviews and publishes
removes that whole class of drift, and keeps with this system's
existing principle of computing anything version/cadence-related in
plain bash rather than leaving it to model judgment.

Both watchers now compute NEXT_MINOR_VERSION / MINOR_RELEASE_BRANCH /
CURRENT_VERSION_DIR (minor) and MINOR_RELEASE_BRANCH / CURRENT_VERSION_DIR
/ NEXT_MAJOR_VERSION / NEXT_MAJOR_DIR (major) once, in bash, and pass
them to the claude-code-action step as env vars -- same pattern as
LOOKBACK. The prompts no longer instruct the model to read
release.config.json or iterate over its version directories.

This also simplifies scope going forward: docs-om previously tracked
multiple minor lines at once (e.g. 1.13.x alongside 2.0.x) via
release.config.json's versions[] array. The minor watcher now scans
only the single current line (MINOR_RELEASE_BRANCH) -- a deliberate
scope reduction, not an oversight; older lines are no longer watched
for new doc-relevant PRs.

release.config.json itself is untouched and still used elsewhere
(scripts/check-release-consistency.sh) -- only removed from the
watchers' own dependency chain.

Verified on two disposable branches:
- Confirmed on real docs-collate infrastructure that the same parsing
  logic correctly fetches this exact file cross-repo (docs-om is
  public, no token needed) and computes all four values against live
  data (2.0.1 -> next minor 2.0.2, next major 2.1, branch 2.0)
- Confirmed here, locally, that the two directory names this repo
  specifically needs (current_version_dir, next_major_dir) are not
  just correctly-formed strings but match real directories that exist
  on disk (v2.0.x, v2.1.x-SNAPSHOT)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ist out

This branch should carry only what the Minor/Major Release Watchers
themselves need to run. The pre/post-release checklist is a separate,
manually-triggered process with no automation ties to the watchers
(nothing in any workflow calls check-release-consistency.sh), so it
doesn't belong here -- it'll be added on its own branch instead.

Removed from this branch:
- .ai/release-checklist/instructions.md
- .ai/release-checklist/references/{pre,post}-release-checklist.md
- release.config.json (the watchers no longer read it after the
  version-derivation fix; its only remaining consumer,
  check-release-consistency.sh, is checklist-only)
- scripts/check-release-consistency.sh

Moved (genuinely needed by both watchers, just relocated out of the
checklist-only directory):
- .ai/release-checklist/references/upstream-watch-config.md ->
  .ai/release-watchers/upstream-watch-config.md, trimmed to just the
  Repo and Doc-relevance-filter sections the watchers actually read --
  the Query section was the checklist's own logic (tied to the
  release.config.json releaseDate this branch no longer carries), not
  something either watcher uses.

.gitignore reverted to main's version -- the promotion of
release.config.json/scripts//.ai/release-checklist/ from personal to
shared tooling belongs with the checklist branch, not this one.

Also brought .ai/release-watchers/PROCESS-OVERVIEW.md fully up to date:
it still described the pre-fix lookback mechanism and the
release.config.json-based version reads. Rewrote the design-principles,
both workflow tables, and the "verified before merge" section to match
current reality, including an explicit, honest split between what's
been proven on disposable branches and what genuinely can't be tested
before this merges (schedule/workflow_dispatch/issue_comment only fire
from the default branch).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@mintlify

mintlify Bot commented Sep 10, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
openmetadata 🟢 Ready View Preview Sep 17, 2026, 11:15 AM

💡 Tip: Enable Automations to automatically generate PRs for you.

…8, not pending)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread .github/workflows/create-draft.yml
Comment thread .github/workflows/create-draft.yml
Comment thread .github/workflows/minor-release-watcher.yml Outdated
Comment thread .github/workflows/minor-release-watcher.yml
…orced-dry lookback, dry-run Write leak

Addresses the latest review round:

1. Every claude-code-action step passed GH_TOKEN only as an env var, never
   as the action's own `github_token` input. Confirmed against the pinned
   action's actual source (src/github/token.ts): setupGitHubToken() only
   reads process.env.OVERRIDE_GITHUB_TOKEN, which action.yml wires
   exclusively from the `github_token` input -- an env var alone never
   reaches it. Without that input, the action requests an OIDC token
   instead, which none of these jobs are permitted to do (no
   `id-token: write`), so every Claude step across all three workflows
   would have failed outright, every time. Added
   `github_token: ${{ github.token }}` to all three invocations.

2. create-draft.yml's single session both read the untrusted upstream
   PR's title/body/diff and held push/PR-create/comment credentials.
   Prompt instructions telling it to treat that content as data, not
   commands, are not an isolation boundary. Split into two sessions: a
   read-only one that reads the issue and source PR(s) and writes the doc
   content plus a title/body handoff to /tmp/create-draft-handoff/ (no
   git/PR/comment tools at all), and a second one that only reads those
   handoff files and does the git/push/PR-create/comment work -- it has
   no tool that can read the original source PR, so untrusted upstream
   content has no path into the write-capable session regardless of what
   it says.

3. minor-release-watcher.yml's lookback took the most recent successful
   *scheduled* run at face value, but a FORCE_DRY_RUN'd scheduled run also
   completes with status success while writing nothing (the write tools
   and label step are gated off, not the run itself). Once FORCE_DRY_RUN
   is switched off, that would have made the first real run's baseline
   the most recent preview, silently discarding everything found-but-
   never-tracked during the whole dry-run rollout period. Ported the same
   fix the major watcher already had for its own off-week no-op runs:
   walk backward through recent scheduled runs and use the first one
   where "Ensure tracking labels exist" (gated off during both
   FORCE_DRY_RUN and a manual dry-run) actually ran, not just completed.
   The major watcher's own lookback already avoided this incidentally
   (its existing off-week check happens to also exclude FORCE_DRY_RUN'd
   runs), so it needed no change.

4. FORCE_DRY_RUN removed the `gh issue create/edit/comment` tools from
   the model's allowedTools, but left `Write` unconditionally available,
   and the Slack-send step had no dry-run gate at all in either watcher.
   The prompt says not to write slack-digest.txt in dry-run mode, but
   that was only ever a prompt instruction -- the tool to do it anyway
   was never actually removed, so an AI session that wrote the file
   regardless (confusion, or injected instructions from a hostile PR
   title/body) would have resulted in a real external Slack post despite
   the "safe by construction" design this branch's whole first-live-
   rollout plan depends on. Moved `Write` inside the same dry-run-gated
   branch as the issue-write commands, and added the missing dry-run gate
   to the Slack-send step in both watchers.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@kiran1287

Copy link
Copy Markdown
Contributor Author

Addressed all 4 P1 findings in b8d03b7:

  • Action auth: confirmed against the pinned action's actual source (src/github/token.ts) that setupGitHubToken() only reads OVERRIDE_GITHUB_TOKEN, wired exclusively from the github_token input -- an env var alone never reaches it, so every Claude step would have failed outright without id-token: write. Added github_token: ${{ github.token }} to all three invocations.
  • Untrusted content isolation: split create-draft.yml into a read-only session (reads the issue + source PR, writes doc content and a title/body handoff to /tmp/, no git/PR/comment tools at all) and a write-capable session that only reads the handoff files -- it has no tool that can read the original source PR, so untrusted upstream content has no path into the session that can push and open a PR.
  • Forced-dry lookback: the minor watcher's lookback took the most recent successful scheduled run at face value, but a FORCE_DRY_RUN'd run also completes with success while writing nothing. Ported the major watcher's own fix (walk back and check whether "Ensure tracking labels exist" actually ran, not just completed) -- the major watcher's existing off-week check already incidentally covered this, so it needed no change.
  • Dry-run Write leak: Write was left unconditionally available in allowedTools even during FORCE_DRY_RUN, and the Slack-send step had no dry-run gate at all -- so an AI session that wrote slack-digest.txt anyway (confusion, or injected instructions) would have resulted in a real external Slack post despite the "safe by construction" design. Moved Write inside the same dry-run-gated branch as the issue-write commands, and gated the Slack-send step in both watchers.

Comment thread .github/workflows/minor-release-watcher.yml Outdated
…both release watchers (#461)

A single Claude session in both minor-release-watcher.yml and
major-release-watcher.yml read untrusted upstream open-metadata/OpenMetadata
PR titles, bodies, and diffs while also holding gh issue create/edit/comment
tools for this repo. A crafted upstream PR could steer those issue
mutations regardless of any prompt instructions to treat that content as
data, not commands.

Splits each workflow into a read-only analysis session (scans, filters,
verifies, groups PRs; for the major watcher, also re-checks completeness
of already-tracked multi-PR features) that has no issue-mutation tools at
all and can only write a structured summary.json handoff to /tmp, and a
separate write-capable session that never reads any upstream PR content
and only acts on that handoff -- de-duplicating, creating/updating
issues, posting the digest, and preparing the Slack summary. Dry-run mode
now removes the create/edit/comment tools from the write session's
allowedTools entirely rather than just instructing it not to use them,
matching the same pattern already applied to create-draft.yml.

Mirrors the equivalent split already implemented in docs-collate's
parallel release-watcher PR (open-metadata/docs-collate#619).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@ayush-shah ayush-shah left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested for the new rollout-backlog P1 below and the residual shared-workspace boundary documented in the existing watcher thread. The older forced-dry watermark finding was not duplicated.

else
# First run ever (or every past attempt failed) -- a safe
# generous default rather than guessing.
echo "lookback=$(date -u -d '4 days ago' +%Y-%m-%d)" >> "$GITHUB_OUTPUT"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Fail closed when there is no successful live baseline

Initial rollout performs only forced-dry previews, and an explicit since value used for a preview is not persisted. After FORCE_DRY_RUN is disabled, this 20-run lookup can find no live marker and silently falls back to four days (15 in the major watcher), permanently omitting older untracked changes. Require an explicit since value for the first live dispatch and whenever no real baseline is found, or scan from a deterministic exhaustive baseline and persist the successful live watermark. Do not let the 20-run cap age a valid baseline out.

…ted jobs (#461)

- Cadence lookup now fails a live run outright when no successful
  non-dry baseline exists and no explicit `since` was given, instead of
  silently defaulting to a short fixed window that could permanently
  miss backlog. Also raised the run-list cap from 20 to 100 so a valid
  baseline can't age out of reach.
- Split each watcher's single job into prepare/scan/notify/slack jobs,
  each on its own runner and checkout. The scan job's token no longer
  holds `issues: write` (minor) / holds `issues: read` only (major),
  enforced by GitHub's job-level permissions rather than relying on
  allowedTools alone. The handoff between scan and notify now moves via
  upload-artifact/download-artifact and is deterministically schema-
  validated -- including that every target_version matches this run's
  own computed version, and (major) that every completeness_checks
  issue number is a real, open, major-watcher-marked issue -- before
  the write-capable session ever reads it.
@kiran1287

kiran1287 commented Sep 17, 2026

Copy link
Copy Markdown
Contributor Author

Addressed both findings from the latest review round in bc37420:

  • Fail closed when there is no successful live baseline: the cadence lookup in both watchers now fails the job outright on a live run when no successful non-dry baseline is found and no explicit since was given, instead of silently falling back to the 4-day (minor) / 15-day (major) default. Also raised the gh run list cap from 20 to 100 so a valid baseline further back can't get aged out and mistaken for "none found."
  • Residual shared-workspace boundary: split both minor-release-watcher.yml and major-release-watcher.yml from a single job into preparescannotifyslack, each on its own runner with its own checkout. The scan job's token now has no issues: write at all (minor) / issues: read only (major) -- an actual GitHub permissions boundary, not just allowedTools. The scan→notify handoff moves via upload-artifact/download-artifact and is schema-validated deterministically before the write-capable session reads it, including that every target_version matches this run's own computed value (not something the scan session could set) and, for major, that every completeness_checks.issue_number is a real, open, major-watcher-marked issue (checked live via gh issue view).

…reason loss

Forced-dry-run previews now write to dry-run-preview.md, published to the
job summary, since no digest issue exists to read in that mode (also
fixes major-release-watcher's Digest step, which previously wasn't
included in the dry-run print-instead list even though its issue-comment
tool is unavailable in that mode). The scan job's handoff file now
carries tracking_issue/original_pr references and per-item
held/ruled_out/needs_a_look reasons, which notify consumes directly
instead of re-deriving them from evidence prose or omitting them from
the digest entirely.

Refs #643
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.

Docs: Minor/Major Release Watchers

2 participants