Repository navigation
feat(compliance): migrate dev-lead trigger label claude→dev-lead + re-trigger persistent findings #400
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
feat(compliance): migrate dev-lead trigger label claude→dev-lead + re-trigger persistent findings #400
Changes from 3 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
bb2602a
feat(compliance): re-trigger dev-lead on findings that persist across…
don-petry 02b95e0
fix(reviews): address review comments [skip ci-relay]
donpetry-bot a714f5f
chore: apply manual instructions [skip ci-relay]
donpetry-bot 24887b8
feat(compliance): migrate dev-lead trigger label from `claude` to `de…
don-petry 0b62668
chore: apply manual instructions [skip ci-relay]
donpetry-bot 592a793
chore: apply manual instructions [skip ci-relay]
donpetry-bot 9797104
chore: apply manual instructions [skip ci-relay]
donpetry-bot f7f5fd1
chore: apply manual instructions [skip ci-relay]
donpetry-bot 84c8d31
fix(reviews): address review comments [skip ci-relay]
donpetry-bot 179749e
chore: apply manual instructions [skip ci-relay]
donpetry-bot c376e84
chore: apply manual instructions [skip ci-relay]
donpetry-bot a268283
chore: apply manual instructions [skip ci-relay]
donpetry-bot 14d80d2
chore: apply manual instructions [skip ci-relay]
donpetry-bot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| #!/usr/bin/env bash | ||
| # dev-lead-retrigger.sh — shared helpers for re-engaging the dev-lead agent on a | ||
| # compliance issue by cycling its trigger label. | ||
| # | ||
| # Sourced by: | ||
| # scripts/compliance-audit.sh — weekly audit; re-triggers findings that | ||
| # persist across runs (issue still open). | ||
| # scripts/compliance-retrigger.sh — daily sweep; re-triggers stale issues. | ||
| # | ||
| # Why a shared lib? | ||
| # Both entry points need the same two primitives, and both depend on how | ||
| # dev-lead names its branches (dev-lead/issue-<number>-<timestamp>, see | ||
| # scripts/dev-lead-fix-issue.sh in the agent repo). Keeping that convention in | ||
| # one place stops the two callers from drifting apart. | ||
| # | ||
| # These functions are pure helpers: they take all inputs as arguments and call | ||
| # `gh api` directly, so they do not depend on the sourcing script's own wrappers | ||
| # or globals. | ||
|
|
||
| # dl_dev_lead_active <org> <repo> <issue> | ||
| # Returns 0 (true) if dev-lead is ALREADY working this issue — either an open PR | ||
| # exists on a dev-lead/issue-<number>-* branch, or the issue carries the | ||
| # `in-progress` label. In that case the caller must NOT cycle the trigger label, | ||
| # to avoid interrupting or duplicating active work. | ||
| dl_dev_lead_active() { | ||
| local org="$1" repo="$2" issue="$3" | ||
|
|
||
| # Match the dev-lead branch exactly: "dev-lead/issue-<n>-<timestamp>". | ||
| # Require the trailing "-" so issue 1 does not match branch "issue-12-...". | ||
| # Use --paginate so repos with >100 open PRs are fully scanned. | ||
| local pr_count | ||
| pr_count=$(gh api "repos/$org/$repo/pulls?state=open&per_page=100" \ | ||
| --paginate \ | ||
| --jq "[.[] | select(.head.ref | type == \"string\" and startswith(\"dev-lead/issue-${issue}-\"))] | length" \ | ||
| 2>/dev/null | awk '{s+=$1} END {print s+0}') | ||
|
don-petry marked this conversation as resolved.
Outdated
|
||
| [ "${pr_count:-0}" -gt 0 ] && return 0 | ||
|
|
||
| # An agent currently mid-run marks the issue `in-progress` before it pushes a | ||
| # PR — respect that window, but cap it at IN_PROGRESS_MAX_HOURS so a crashed or | ||
| # cancelled run cannot block retrigger indefinitely. | ||
| local in_progress | ||
| in_progress=$(gh api "repos/$org/$repo/issues/$issue" \ | ||
| --jq '.labels[].name | select(. == "in-progress")' \ | ||
| 2>/dev/null || echo "") | ||
|
don-petry marked this conversation as resolved.
Outdated
|
||
|
|
||
| if [ -n "$in_progress" ]; then | ||
| local in_progress_max_hours="${IN_PROGRESS_MAX_HOURS:-4}" | ||
| local labeled_at | ||
| labeled_at=$(gh api "repos/$org/$repo/issues/$issue/events?per_page=100" \ | ||
| --paginate \ | ||
| --jq '.[] | select(.event == "labeled" and .label.name == "in-progress") | .created_at' \ | ||
| 2>/dev/null | tail -1 || echo "") | ||
|
|
||
| if [ -z "$labeled_at" ] || [ "$labeled_at" = "null" ]; then | ||
| # Cannot determine when the label was applied; trust it conservatively. | ||
| return 0 | ||
| fi | ||
|
|
||
| local now_epoch labeled_epoch elapsed_hours | ||
| now_epoch=$(date -u +%s) | ||
| labeled_epoch=$(date -u -d "$labeled_at" +%s 2>/dev/null \ | ||
| || python3 -c "import sys, calendar, datetime; \ | ||
| ts = sys.stdin.read().strip(); \ | ||
| print(calendar.timegm(datetime.datetime.strptime(ts, '%Y-%m-%dT%H:%M:%SZ').timetuple()))" \ | ||
| <<< "$labeled_at") | ||
| elapsed_hours=$(( (now_epoch - labeled_epoch) / 3600 )) | ||
|
|
||
| [ "$elapsed_hours" -le "$in_progress_max_hours" ] && return 0 | ||
| # in-progress label is stale (agent likely crashed); fall through to return 1. | ||
|
don-petry marked this conversation as resolved.
Outdated
|
||
| fi | ||
|
|
||
| return 1 | ||
| } | ||
|
|
||
| # dl_cycle_trigger_label <org> <repo> <issue> <label> [dry_run] | ||
| # Remove then re-add <label> so GitHub emits a fresh issues:labeled event, | ||
| # re-engaging dev-lead. dev-lead fires once per label application, so a | ||
| # persistent finding whose label is already present needs the label cycled to be | ||
| # picked up again. Returns non-zero if the re-add fails (the caller can fall | ||
| # back to ensuring the label is at least present). | ||
| dl_cycle_trigger_label() { | ||
| local org="$1" repo="$2" issue="$3" label="$4" dry_run="${5:-false}" | ||
|
|
||
| if [ "$dry_run" = "true" ]; then | ||
| echo "[dry-run] would cycle '$label' on $org/$repo#$issue" >&2 | ||
| return 0 | ||
| fi | ||
|
|
||
| # URL-encode the label for the REST path segment to handle names that contain | ||
| # spaces or other reserved characters. | ||
| local encoded_label | ||
| encoded_label=$(printf '%s' "$label" \ | ||
| | python3 -c "import sys, urllib.parse; print(urllib.parse.quote(sys.stdin.read().strip(), safe=''))" 2>/dev/null \ | ||
| || printf '%s' "$label" | sed 's/ /%20/g') | ||
| gh api -X DELETE "repos/$org/$repo/issues/$issue/labels/$encoded_label" >/dev/null 2>&1 || true | ||
|
don-petry marked this conversation as resolved.
Outdated
|
||
| # Let GitHub register the removal before re-adding so the add is not coalesced | ||
| # with the delete (which would emit no labeled event). | ||
| sleep 1 | ||
| gh api -X POST "repos/$org/$repo/issues/$issue/labels" \ | ||
| --field "labels[]=$label" >/dev/null 2>&1 || return 1 | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.