Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
25ebaf3
feat: implement issue #1713 — [#1269 split 1/2] shadow_mode input + t…
Sep 8, 2026
1b46a54
chore: dev-lead update (review-changes) [skip ci-relay]
don-petry Sep 8, 2026
a810206
docs: improve shell function docstrings to match org standard format
don-petry Oct 6, 2026
c763258
fix(reviews): suppress hold-notice and dry-run dedup writes in shadow…
don-petry Oct 6, 2026
a6a88be
fix(bot): allow agent execution in shadow mode while still suppressin…
don-petry Oct 9, 2026
feb84ab
fix(bot): export SHADOW_OUTPUT_FILE for output capture in shadow mode
don-petry Oct 9, 2026
fcb1087
fix(bot): improve docstring format in shadow-suppress.sh to match org…
don-petry Oct 9, 2026
f04e708
fix(bot): register dev-lead unit tests in lint.yml bats job
don-petry Oct 9, 2026
a45948d
fix(bot): add docstrings to test setup/teardown functions
don-petry Oct 9, 2026
dd1be7d
fix(bot): add missing docstrings to dev-lead-fix-ci functions
don-petry Oct 10, 2026
2919be9
fix(bot): allow agent execution in shadow mode while still suppressin…
don-petry Oct 10, 2026
64153e7
Merge branch 'main' into dev-lead/issue-1713-20260908-0306
don-petry Oct 10, 2026
4f6af5b
Merge branch 'main' into dev-lead/issue-1713-20260908-0306
don-petry Oct 10, 2026
97abe44
Merge branch 'main' into dev-lead/issue-1713-20260908-0306
don-petry Oct 10, 2026
6ced358
Merge branch 'main' into dev-lead/issue-1713-20260908-0306
don-petry Oct 10, 2026
a2d4c41
Merge branch 'main' into dev-lead/issue-1713-20260908-0306
don-petry Oct 10, 2026
f64a605
Merge branch 'main' into dev-lead/issue-1713-20260908-0306
don-petry Oct 10, 2026
92b5981
Merge branch 'main' into dev-lead/issue-1713-20260908-0306
don-petry Oct 10, 2026
dde0b5a
Merge branch 'main' into dev-lead/issue-1713-20260908-0306
don-petry Oct 10, 2026
fce2ad1
Merge branch 'main' into dev-lead/issue-1713-20260908-0306
don-petry Oct 10, 2026
8840829
Merge branch 'main' into dev-lead/issue-1713-20260908-0306
don-petry Oct 10, 2026
5e3be1f
chore: rename petry-projects references to combsmith
don-petry Oct 14, 2026
5786dcd
chore: limit the org-rename rewrite to the files this PR changes
don-petry Oct 14, 2026
8336b94
chore: limit the org-rename rewrite to the files this PR changes
don-petry Oct 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions .github/workflows/dev-lead-reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,24 @@ on:
required: false
default: ""
agent_ref:
# Ref of petry-projects/.github-private to check out for the dev-lead
# Ref of combsmith/.github-private to check out for the dev-lead
# scripts. A trigger-stub caller passes its pinned channel (dev-lead/stable)
# so the agent runs at the pinned version, not main — the self-host pin
# (#535/#506). Defaults to "main" → unchanged behaviour.
description: "Ref of petry-projects/.github-private to check out for dev-lead scripts"
description: "Ref of combsmith/.github-private to check out for dev-lead scripts"
type: string
required: false
default: "main"
shadow_mode:
# #1713 (split 1/2): when true, this lane posts NOTHING to the PR/issue
# (no review, comment, thread reply, label, or auto-merge enable) — its
# output goes to the run log + a file instead. Default false ⇒ behaviour
# is byte-identical to today. INERT: only an explicit caller input can
# set it; nothing dispatches a shadow lane yet (that is split 2/2).
description: "Run silently: suppress all PR/issue output (shadow mode)"
type: boolean
required: false
default: false
secrets:
CLAUDE_CODE_OAUTH_TOKEN:
# required:false (#1525) — a hard required:true fails the CALLER at
Expand All @@ -36,8 +46,8 @@ on:
# callers that haven't set the new secret yet still authenticate. Remove once
# GH_PAT_DON_PETRY is confirmed everywhere.
# Required for cross-repo callers: the default github.token cannot read
# petry-projects/.github-private from another repo. Callers must pass a
# PAT that has read access to petry-projects/.github-private.
# combsmith/.github-private from another repo. Callers must pass a
# PAT that has read access to combsmith/.github-private.
required: false
GOOGLE_API_KEY:
required: false
Expand All @@ -58,7 +68,7 @@ permissions: {}
# and can no longer drift into — their own concurrency group. Separate per-issue
# and per-PR lanes ensure issue pickups are NEVER cancelled by unrelated PR
# follow-up traffic (reviews, comments, ci-relay) — the root cause of issue
# pickups being cancelled before they could open a PR. See petry-projects/.github#402.
# pickups being cancelled before they could open a PR. See combsmith/.github#402.
#
# Routing (first match wins):
# check_run -> dev-lead-ci-relay-<sha> (per-SHA relay lane)
Expand Down Expand Up @@ -168,6 +178,11 @@ jobs:
AI_MODELS_GEMINI: ${{ vars.AI_MODELS_GEMINI || '' }}
AI_MODELS_COPILOT: ${{ vars.AI_MODELS_COPILOT || '' }}
DEV_LEAD_DRY_RUN: ${{ vars.DEV_LEAD_DRY_RUN || 'false' }}
# #1713 (split 1/2): forwarded to the handlers, which fail-closed suppress
# ALL PR/issue output when active. Sourced from the caller's shadow_mode
# input (default false ⇒ today's behaviour). Nothing sets it yet.
DEV_LEAD_SHADOW_MODE: ${{ inputs.shadow_mode }}
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
Resolved
SHADOW_OUTPUT_FILE: /tmp/dev-lead-shadow-output-${{ github.run_id }}.txt

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

SHADOW_OUTPUT_FILE is set unconditionally in the job env: even when inputs.shadow_mode is false. Because the handlers (scripts/dev-lead-fix-ci.sh:285, scripts/dev-lead-fix-issue.sh:636, scripts/dev-lead-fix-reviews.sh:346) branch on if [ -n "$capture_file" ] rather than if shadow_mode_active, every normal non-shadow run writes /tmp/dev-lead-shadow-output-<run_id>.txt and pipes run_writer_with_fallback ... | tee -a "$capture_file".

Running run_writer_with_fallback on the left side of a pipeline executes it in a subshell, discarding any shell state mutated inside run_writer_with_fallback (such as _ENGINE_EXHAUSTED_REASON across fix-ci retry cycles).

DEEP_TIMEOUT_SEC: ${{ vars.DEEP_TIMEOUT_SEC || '' }}
ACTION_TIMEOUT_SEC: ${{ vars.ACTION_TIMEOUT_SEC || '' }}
GH_TOKEN: ${{ secrets.GH_PAT_DON_PETRY || secrets.GH_PAT_WORKFLOWS || github.token }}
Expand Down Expand Up @@ -227,7 +242,7 @@ jobs:
- name: Checkout dev-lead scripts
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: petry-projects/.github-private
repository: combsmith/.github-private
# Pinned channel (e.g. dev-lead/stable) when a trigger stub passes it;
# defaults to "main" → unchanged behaviour (#535/#506).
ref: ${{ inputs.agent_ref }}
Expand Down Expand Up @@ -800,7 +815,7 @@ jobs:
- name: Checkout dev-lead scripts
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: petry-projects/.github-private
repository: combsmith/.github-private
# Pinned channel (e.g. dev-lead/stable) when a trigger stub passes it;
# defaults to "main" → unchanged behaviour (#535/#506).
ref: ${{ inputs.agent_ref }}
Expand Down
8 changes: 5 additions & 3 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ jobs:
tests/dev-lead/integration/test_usage_telemetry_roundtrip.bats \
tests/dev-lead/unit/test_gemini_quota.bats \
tests/dev-lead/unit/test_budget_poller.bats \
tests/dev-lead/unit/test_fix_issue.bats \
tests/dev-lead/unit/test_shadow_suppress.bats \
tests/test_qa_lead_test_surface.bats \
tests/test_qa_lead_advisory_gate.bats \
tests/test_persona_pr_pregate.bats \
Expand Down Expand Up @@ -391,7 +393,7 @@ jobs:
run: bash scripts/validate-ingress-if.sh

template-drift:
# Drift guard (#969): fail when a file committed in petry-projects/repo-template
# Drift guard (#969): fail when a file committed in combsmith/repo-template
# has diverged from its standards-derived baseline, so the template stays a thin
# distribution layer of standards/ and never becomes a competing fork. Reuses the
# byte-identity (blob-SHA) model from scripts/fleet_stub_drift.sh. PR-triggered via
Expand Down Expand Up @@ -607,7 +609,7 @@ jobs:
# suite (tests/persona_reach_check.bats, run by the `bats` job) unit-tests the pure
# predicates; this job runs the guard END-TO-END against the real personas/ tree,
# passing --registry with the cross-repo canary-rings.json snapshot fetched from the
# PUBLIC petry-projects/.github standards (the same registry validate-personas reads).
# PUBLIC combsmith/.github standards (the same registry validate-personas reads).
# Without this, a status advanced past `draft` with no matching cross-repo
# registration only surfaces post-merge (the #1052 hollow-green skew) — this catches
# it at PR time. The fetch soft-fails to a warning (registration UNVERIFIED) so a
Expand All @@ -622,7 +624,7 @@ jobs:
- name: Run persona reach check (solution-architect)
run: |
curl -fsSL --retry 3 \
https://raw.githubusercontent.com/petry-projects/.github/main/standards/canary-rings.json \
https://raw.githubusercontent.com/combsmith/.github/main/standards/canary-rings.json \
-o canary-rings.json \
|| echo "::warning::could not fetch cross-repo canary-rings.json; running reach check without --registry (registration UNVERIFIED)"
if [ -f canary-rings.json ]; then
Expand Down
40 changes: 38 additions & 2 deletions scripts/dev-lead-fix-ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ source "$(dirname "$0")/lib/pr-automation-budget.sh"
# missing 3+ required description sections, once, marker-keyed.
source "$(dirname "$0")/lib/dev-lead-pr-body.sh"

# shadow_mode_active / shadow_apply_suppression (#1713): total PR-output
# suppression when this lane runs in shadow mode.
source "$(dirname "$0")/lib/shadow-suppress.sh"

# In shadow mode, force the already-tested dry-run "post nothing" path so no
# PR output escapes. Must run before any posting site.
DEV_LEAD_DRY_RUN="${DEV_LEAD_DRY_RUN:-false}"
shadow_apply_suppression

PR_NUMBER="${PR_NUMBER:-}"
HEAD_SHA="${HEAD_SHA:-}"
CHECKS_JSON="${CHECKS_JSON:-[]}"
Expand Down Expand Up @@ -82,6 +91,12 @@ has_rate_limited_marker() {
[ "${count:-0}" -gt 0 ]
}

# collect_logs: fetch logs from a failing GitHub Actions run, or the PR diff if an
# external quality gate (SonarCloud, etc). Exports details for the fix-ci prompt.
#
# Arguments:
# $1 check_name - name of the failing check (for reference in output)
# $2 details_url - URL to the check details/run
collect_logs() {
local check_name="$1" details_url="$2"
local run_id
Expand All @@ -98,6 +113,11 @@ collect_logs() {
fi
}

# build_prompt: render the fix-ci prompt template with check context, failure logs,
# and PR annotations. Writes the rendered prompt to a temp file and echoes its path.
#
# Returns:
# Path to the rendered prompt file
build_prompt() {
local prompt_template="${PROMPTS_DIR}/fix-ci.md"
local check_name app_slug details_url
Expand All @@ -119,6 +139,12 @@ build_prompt() {
echo "$rendered"
}

# post_summary: post a dev-lead fix-ci status comment to the PR. Embeds a marker
# with the commit SHA and status for dedup and tracking. Logs instead when DEV_LEAD_DRY_RUN=true.
#
# Arguments:
# $1 status - status label (e.g. "applied", "failed", "rate-limited", "dry-run")
# $2 details - optional details/reason to append to the comment body
post_summary() {
local status="$1" details="${2:-}"
local marker="${MARKER_PREFIX}${HEAD_SHA} status=${status} -->"
Expand Down Expand Up @@ -175,6 +201,11 @@ ${details}"
fi
}

# post_exhaustion: post a dev-lead exhaustion marker when the fix-ci handler has failed
# MAX_FAIL_ATTEMPTS times. Includes the reason for the last failure and instructions for recovery.
#
# Arguments:
# $1 reason - the reason for the final engine failure (timeout, error, rate-limit)
post_exhaustion() {
local reason="$1"
local body="${EXHAUSTION_MARKER}
Expand Down Expand Up @@ -230,7 +261,7 @@ main() {
local prompt_file
prompt_file=$(build_prompt)

if [ "${DEV_LEAD_DRY_RUN:-false}" = "true" ]; then
if [ "${DEV_LEAD_DRY_RUN:-false}" = "true" ] && ! shadow_mode_active; then

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Bypassing the dry-run early exit when shadow_mode_active is true causes a shadow run to enter the while [ "$cycle" -le "$MAX_CI_CYCLES" ] loop (line 280), where git commit and git push run unconditionally without checking DEV_LEAD_DRY_RUN or shadow_mode_active, pushing shadow commits directly to the live PR branch. In addition, hold_auto_merge (called just before build_prompt in main) disables auto-merge on the live PR because it is not gated on DEV_LEAD_DRY_RUN or shadow_mode_active.

echo "[dry-run] fix-ci: would run engine with prompt: $prompt_file"
post_summary "dry-run" "Would apply fix for: $(echo "$CHECKS_JSON" | jq -r '[.[].name] | join(", ")')"
exit 0
Expand All @@ -250,7 +281,12 @@ main() {
echo " [fix-ci] cycle $cycle/$MAX_CI_CYCLES"

local engine_rc=0
run_writer_with_fallback "$prompt_file" "fix-ci" || engine_rc=$?
local capture_file="${SHADOW_OUTPUT_FILE:-}"
if [ -n "$capture_file" ]; then
run_writer_with_fallback "$prompt_file" "fix-ci" 2>&1 | tee -a "$capture_file" || engine_rc=$?
else
run_writer_with_fallback "$prompt_file" "fix-ci" || engine_rc=$?
fi

if [ "$engine_rc" -ne 0 ]; then
if [ "$engine_rc" -eq 2 ]; then
Expand Down
35 changes: 26 additions & 9 deletions scripts/dev-lead-fix-issue.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,16 @@ source "$(dirname "$0")/lib/issue-comments.sh"
# net_diff_is_empty / net_diff_summary (#1786): refuse to open/claim a PR whose
# three-dot net diff against base is empty.
source "$(dirname "$0")/lib/net-diff-guard.sh"
# shadow_mode_active / shadow_apply_suppression (#1713): total PR-output
# suppression when this lane runs in shadow mode.
source "$(dirname "$0")/lib/shadow-suppress.sh"

ISSUE_NUMBER="${ISSUE_NUMBER:-}"
REPO="${REPO:-${GITHUB_REPOSITORY:-}}"
DEV_LEAD_DRY_RUN="${DEV_LEAD_DRY_RUN:-false}"
# In shadow mode, force the already-tested dry-run "post nothing" path so no
# PR/issue output escapes. Must run before any posting site.
shadow_apply_suppression
export PROMPTS_DIR="${PROMPTS_DIR:-prompts/dev-lead}"

# Machine-readable marker the retry cron (dev-lead-retry.sh) scans for to requeue
Expand All @@ -45,11 +51,11 @@ NEEDS_HUMAN_LABEL="${NEEDS_HUMAN_LABEL:-dev-lead:needs-human}"
# from a completed pass at a glance. It is deliberately never a completion claim.
CHECKPOINT_COMMIT_PREFIX="${CHECKPOINT_COMMIT_PREFIX:-checkpoint(dev-lead): INCOMPLETE —}"

# PR-limit admission gate (epic petry-projects/.github#505 Phase 3) config.
# PR-limit admission gate (epic combsmith/.github#505 Phase 3) config.
# The shared guard + limits config live in the PUBLIC standards repo so every
# automation caller enforces the same org-wide cap. PLG_STANDARDS_DIR lets tests
# and offline runs source a local checkout instead of hitting the API.
PLG_SOURCE_REPO="${PLG_SOURCE_REPO:-petry-projects/.github}"
PLG_SOURCE_REPO="${PLG_SOURCE_REPO:-combsmith/.github}"
PLG_SOURCE_REF="${PLG_SOURCE_REF:-main}"
PLG_DEFER_MARKER="<!-- dev-lead-issue-deferred -->"

Expand Down Expand Up @@ -555,8 +561,14 @@ main() {

if check_existing_pr; then
echo "::notice::Existing open PR found for issue #${ISSUE_NUMBER} — skipping (dedup)"
gh issue comment "$ISSUE_NUMBER" --repo "$REPO" \
--body "<!-- dev-lead-issue-dedup -->Already working on this: an open PR exists for issue #${ISSUE_NUMBER}." 2>/dev/null || true
# Dedup comment fires before the dry-run early-exit below, so it is the one
# posting site not covered by forced dry-run — gate it on shadow or dry-run.
if shadow_mode_active || [ "${DEV_LEAD_DRY_RUN:-false}" = "true" ]; then
echo "[shadow/dry-run] would post dedup comment for issue #${ISSUE_NUMBER} (suppressed)"
else
gh issue comment "$ISSUE_NUMBER" --repo "$REPO" \
--body "<!-- dev-lead-issue-dedup -->Already working on this: an open PR exists for issue #${ISSUE_NUMBER}." 2>/dev/null || true
fi
exit 0
fi

Expand Down Expand Up @@ -590,15 +602,15 @@ main() {
envsubst < "$template_path" > "$prompt_file"
fi

if [ "$DEV_LEAD_DRY_RUN" = "true" ]; then
if [ "$DEV_LEAD_DRY_RUN" = "true" ] && ! shadow_mode_active; then

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Adding && ! shadow_mode_active here bypasses the only DEV_LEAD_DRY_RUN guard in scripts/dev-lead-fix-issue.sh.

Nothing after run_writer_with_fallback checks DEV_LEAD_DRY_RUN or shadow_mode_active: when DEV_LEAD_SHADOW_MODE=true, execution proceeds through admission_gate_allows, run_writer_with_fallback (which calls handle_engine_failure and posts comments/labels on the live issue if the engine fails), git push --set-upstream origin "$branch", gh pr create, label edits, and post_completion_claim on the live repository. This also breaks the new test @test "fix-issue: shadow on (normal run) → no PR create, no comment, exits 0" in tests/dev-lead/unit/test_fix_issue.bats:1461.

echo "[dry-run] fix-issue: would implement issue #${ISSUE_NUMBER} using prompt: $prompt_file"
rm -f "${prompt_file:-}"
exit 0
fi

# PR-limit admission gate — epic petry-projects/.github#505 Phase 3.
# PR-limit admission gate — epic combsmith/.github#505 Phase 3.
# Before opening a new automation PR, defer if the org-wide open-automation-PR
# queue is at the signed-off cap (standards/pr-limits.json in petry-projects/.github).
# queue is at the signed-off cap (standards/pr-limits.json in combsmith/.github).
# Placed AFTER the dry-run early-exit so a dry-run never defers; FAIL-OPEN so a
# guard problem never blocks PR creation.
if ! admission_gate_allows; then
Expand All @@ -620,7 +632,12 @@ main() {
pre_engine_sha=$(git rev-parse HEAD)

local engine_rc=0
run_writer_with_fallback "$prompt_file" "fix-issue" || engine_rc=$?
local capture_file="${SHADOW_OUTPUT_FILE:-}"
if [ -n "$capture_file" ]; then
run_writer_with_fallback "$prompt_file" "fix-issue" 2>&1 | tee -a "$capture_file" || engine_rc=$?
else
run_writer_with_fallback "$prompt_file" "fix-issue" || engine_rc=$?
fi
if [ "$engine_rc" -ne 0 ]; then
# Unified failure handler: classifies the cause, surfaces it on the issue
# (marker + comment + run link + redacted snippet), and decides retry vs.
Expand Down Expand Up @@ -709,7 +726,7 @@ ${lint_output}
rm -f "$pr_body_file"
echo "$pr_url"

# Mark the PR auto-rebase-eligible from creation (petry-projects/.github#711).
# Mark the PR auto-rebase-eligible from creation (combsmith/.github#711).
# The auto-rebase 'review-ready' gate (#465) only rebases PRs that are approved
# OR carry the ready label; without this, a dev-lead PR that falls behind before
# it is approved is skipped, drifts into a merge conflict, and cannot be approved
Expand Down
24 changes: 18 additions & 6 deletions scripts/dev-lead-fix-reviews.sh
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,18 @@ source "$(dirname "$0")/lib/ci-status.sh"
# labels API, logs the API's message on failure, and a failed hold fails the run.
source "$(dirname "$0")/lib/hold-label.sh"

# shadow_mode_active / shadow_apply_suppression (#1713): total PR-output
# suppression when this lane runs in shadow mode.
source "$(dirname "$0")/lib/shadow-suppress.sh"

INTENT_TYPE="${INTENT_TYPE:-fix-reviews}"
PR_NUMBER="${PR_NUMBER:-}"
REPO="${REPO:-${GITHUB_REPOSITORY:-}}"
HEAD_SHA="${HEAD_SHA:-}"
DEV_LEAD_DRY_RUN="${DEV_LEAD_DRY_RUN:-false}"
# In shadow mode, force the already-tested dry-run "post nothing" path so no PR
# output escapes. Must run before the budget/hold/dispatch posting sites below.
shadow_apply_suppression

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Calling shadow_apply_suppression at line 77 sets DEV_LEAD_DRY_RUN="true" before the worktree checkout block (if [ "${DEV_LEAD_DRY_RUN:-false}" = "false" ] && [ -n "${PR_NUMBER:-}" ]; then ... checkout_pr_in_worktree ...), so a shadow run skips checking out the PR branch into a worktree. Then at line 329 (if [ "$DEV_LEAD_DRY_RUN" = "true" ] && ! shadow_mode_active), build_and_run bypasses the dry-run return and invokes run_writer_with_fallback inside the agent checkout (combsmith/.github-private) instead of the target PR worktree (and for INTENT_TYPE=rebase, the prompt instructs the engine itself to git push --force, which is not blocked by DEV_LEAD_DRY_RUN).

export PROMPTS_DIR="${PROMPTS_DIR:-prompts/dev-lead}"
# Pin PROMPTS_DIR to an absolute path now, while CWD still points at the agent
# checkout — checkout_pr_in_worktree cds into the PR worktree, after which a
Expand Down Expand Up @@ -319,7 +326,7 @@ build_and_run() {
printf '%s\n' "${out}${rest}" > "$prompt_file"
fi

if [ "$DEV_LEAD_DRY_RUN" = "true" ]; then
if [ "$DEV_LEAD_DRY_RUN" = "true" ] && ! shadow_mode_active; then
echo "[dry-run] would run engine with prompt: $prompt_file ($(wc -l < "$prompt_file") lines)"
rm -f "${prompt_file:-}"
return 0
Expand All @@ -335,7 +342,12 @@ build_and_run() {
echo "::warning::could not install the reply recorder — no-change dispositions are disabled this pass (#2079)"
[ -n "${PASS_REPLY_RECORD:-}" ] && printf 'UNATTRIBUTED\n' > "$PASS_REPLY_RECORD"
fi
PATH="$engine_path" run_writer_with_fallback "$prompt_file" "${INTENT_TYPE:-}" || rc=$?
local capture_file="${SHADOW_OUTPUT_FILE:-}"
if [ -n "$capture_file" ]; then
PATH="$engine_path" run_writer_with_fallback "$prompt_file" "${INTENT_TYPE:-}" 2>&1 | tee -a "$capture_file" || rc=$?
else
PATH="$engine_path" run_writer_with_fallback "$prompt_file" "${INTENT_TYPE:-}" || rc=$?
fi
[ -n "$shim_dir" ] && rm -rf "$shim_dir"
rm -f "${prompt_file:-}"
return "$rc"
Expand Down Expand Up @@ -1139,7 +1151,7 @@ resolve_addressed_bot_threads() {
fi
# #2013: the claimed commit must be one THIS pass produced — not the PR's first
# commit or any other pre-pass ancestor, which passes the on-head + intersection
# checks trivially (the petry-projects/.github#1220 `571a3b8` case). Parity with
# checks trivially (the combsmith/.github#1220 `571a3b8` case). Parity with
# the issue-comment `fixed` check in resolve_dispositioned_comments (#1813).
in_base=$(printf '%s' "$facts" | jq -r 'if .in_base == false then "false" else "true" end' 2>/dev/null || echo "true")
if ! in_pass=$(acv_claim_in_pass "${RESOLUTION_BASE_SHA:-}" "$on_head" "$in_base"); then
Expand Down Expand Up @@ -3036,7 +3048,7 @@ commit_and_push() {
;;
esac
# Sync-stub guard (#2185): on a `standards-sync` PR, a bot-driven pass must not
# change a stub copied verbatim from petry-projects/.github/standards/ (the
# change a stub copied verbatim from combsmith/.github/standards/ (the
# incubator#164 shape). Restoring a stub to what the sync commit wrote is
# allowed. Maintainer-driven intents (review-changes/human-pr, on-mention,
# human) are the explicit override and are not guarded. The PR is read only
Expand All @@ -3063,7 +3075,7 @@ commit_and_push() {
;;
esac
# Test-tamper guard (#2013): a bot-driven fix pass must not silently rewrite an
# existing test to make its own change pass (the petry-projects/.github#1220
# existing test to make its own change pass (the combsmith/.github#1220
# `13927fc` shape). Refuse the push and escalate, like the no-op guard (rc 3).
# "Existing" means present at the merge base with the PR's base branch (#2141):
# tests the PR itself added are free to revise. The merge base is resolved only
Expand Down Expand Up @@ -3416,7 +3428,7 @@ If the test really is wrong, a human should make that call, or the fix should ca
# flag_sync_stub_drift <intent> <rows> — the sync-stub guard refused the push
# (#2185). <rows> are `path\ttemplate` lines (empty when the scan was unknown).
# Same escalation as flag_test_tamper; the comment answers the bot suggestion as
# declined and points at each template in petry-projects/.github.
# declined and points at each template in combsmith/.github.
flag_sync_stub_drift() {
local intent="$1" rows="$2"
_AM_NEEDS_RESTORE=0
Expand Down
4 changes: 4 additions & 0 deletions scripts/dev-lead-hold-notice.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,17 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib/hold-notice.sh
source "$SCRIPT_DIR/lib/hold-notice.sh"
# shellcheck source=lib/shadow-suppress.sh
source "$SCRIPT_DIR/lib/shadow-suppress.sh"

REPO="${REPO:-${GITHUB_REPOSITORY:-}}"
SUBJECT_NUMBER="${SUBJECT_NUMBER:-}"
HOLD_LABEL="${HOLD_LABEL:-}"
MODE="${MODE:-notice}"
NOTICE_AUTHOR="${NOTICE_AUTHOR:-${BOT_USER:-}}"
DRY_RUN="${DEV_LEAD_DRY_RUN:-${DRY_RUN:-false}}"
# Shadow mode (#1713) posts nothing: treat it as dry-run so no write call fires.
if shadow_mode_active; then DRY_RUN="true"; fi

if [ -z "$REPO" ]; then
echo "::warning::dev-lead-hold-notice: REPO/GITHUB_REPOSITORY not set — skipping"
Expand Down
Loading