Skip to content

pr-merge cost hold: LOW-rated shapes S&C's probe still passes #9241

Open

Description

@kyle-sexton

Refs: #9221

Problem

The cost hold in #9224 (cost-review-required) closes S&C's HOLD findings. Its probe
still passes a set of shapes that S&C rated LOW. A change of one of these shapes merges
unattended with no owner decision when the HIGH path floor is off, as it is by default in the
pr-merge lane.

In this repository, .github/** and docs/conventions/** are already on the HIGH floor, so the
workflow cases below already wait for a person here.

Shapes still passing the probe

These are the passing rows from S&C's probe re-run against #9224's head.

Timeouts

  • A timeout raised on a workflow that calls a local reusable workflow, which itself runs a model.
  • A timeout-minutes removed entirely, so the default of 360 applies.
  • A timeout-minutes set to an expression.
  • One job raised while a higher value is removed and re-added elsewhere in the same patch.
  • A timeout set in flow-mapping style.

Model legs

  • A model leg behind a local reusable workflow or composite action
    (uses: ./.github/workflows/..., ./.github/actions/...).
  • A non-Claude model action that replaces claude-code-action.
  • ANTHROPIC_MODEL env values, and with: model: or with: max-turns: inputs on a model step.
  • --model or --max-turns in .github/actions/**/action.yml or .github/scripts/**, which
    are outside .github/workflows/.

Triggers and guards

  • New triggers on a model workflow: workflow_run, a push with no paths, on: [...] lists.
  • concurrency.cancel-in-progress or a job if: guard removed from a model job.
  • strategy.matrix growth and max-parallel.

Files and paths

  • A workflow in a subdirectory (.github/workflows/sub/x.yml).
  • Spend logic in code: .github/actions/resolve-config/*.mjs.
  • Pulumi.yml, ARM templates (azuredeploy.json) and *.tf.json.

Moves

  • A secret reference moved within one file. This is net zero by design, but a move can hide a
    new use.

Next step

Triage each shape: hold it, accept it with a reason, or leave it to the review lanes. Then add
probe rows for the held ones to the cost tests.

Activity

  1. added
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 22, 2026
  2. github-actions commented on Oct 22, 2026

    @github-actions
    Contributor

    Proposed work class: work-class: structural
    Basis: automated intake triage; the lanes App applied this class.

    Size: Medium
    Complexity: Medium
    Uncertainty: Knowable
    Flags: none
    Blocked by: none

    Decision recorded. This supersedes the "Model legs: hold" and "timeouts hold on every repository" lines in this issue's spec. My standing cost rule of 2026-10-27 (docs/conventions/loop-lane/README.md, "When work stops for the owner") governs:

    "Cost, which comes to me: anything that can bill me. That means Azure, GitHub (larger runners, Actions minutes or storage on private repositories, paid storage or artifact retention beyond the free quota, plan or seat changes) and any other billing account."

    "Not cost, so spend it freely: model usage under the Claude subscriptions, and each account's promotional $200 API credits."

    Acceptance:

    • A model-settings change (model, effort, turns) in the pr-pipeline config is a non-holding cost finding, not a cost hold.
    • A job-timeout change holds as cost only on a private repository; on a public repository it does not hold.
    • Every shape that can bill (larger runners, private-repo minutes or storage, paid retention, plan or seat changes, Azure) still holds.

    #9241 (comment)

    This decision settles the open scope questions. PR #10583 merged with Refs:, so the issue stays open. Changelog entries and probe tests for #9241 are already on main. What remains is a check that the probe matches the three acceptance items above: model settings don't hold, timeouts hold only on private repositories, and billable shapes still hold.

    Automated triage, applied by the lanes App.

  3. added
    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.
    and removed
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 22, 2026
  4. kyle-sexton commented on Oct 22, 2026

    @kyle-sexton
    MemberAuthor

    More LOW items from Security & Cost's re-probes of #9224 (heads f5d53282 and b37ffc18):

    • Timeout comparison. _raised_timeouts compares each added value against the highest removed
      value in the patch. So a raise from 30 to 200 passes when an unchanged 300 is removed and re-added
      elsewhere in the same patch. Fix: compare per job or by key path.
    • .lstrip() before DECISION_LINE. cost_decision strips leading whitespace before matching
      **Decision recorded.** Cost:. As a result, a marker after leading whitespace or blank lines, or
      on what renders as line 2, still counts. Fix: match the raw first line.
    • pr-pipeline.yaml value swaps. _unsafe_pipeline_lines compares multisets, so a check that
      added and removed lines are equal (gained == lost) passes when two keys swap their values.
      Fix: compare by key path.
    • Secret reference shapes _SECRET_REF misses: ${{ secrets }}, contains(secrets, ...), and
      a reference split across a folded scalar.
    • Runners behind an expression. runs-on: ${{ matrix.os }} or ${{ inputs.runner }} passes
      when the matrix values or the input's default gain a larger-runner label. The runner check
      reads only runs-on values.
  5. kyle-sexton commented on Oct 22, 2026

    @kyle-sexton
    MemberAuthor

    Two items from the earlier comment are fixed in #9224 at 2795674, after the review lanes raised them: a Cost: marker on line 2 no longer counts (DECISION_LINE takes spaces or tabs only), and pr-pipeline.yaml value swaps between keys now hold (each change run is compared in place). The rest stay open.

  6. removed
    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.
    on Oct 24, 2026
  7. kyle-sexton commented on Oct 24, 2026

    @kyle-sexton
    MemberAuthor

    Released for re-triage under the owner's 2026-10-24 rule: an issue stops for a person only for an intent or vision question, a security call, a host or attended run, or spend outside prepaid credit. The hold label came off and intake triage runs again now; it re-applies a hold, with a numbered question, when one of those applies.

    To hold this issue again, add needs-human (or status: needs-decision) and say why in a comment.

  8. added
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    priority: mediumReal value, no hard deadline; normal backlog flow.
    status: needs-decisionAwaiting a human or maintainer judgment call.
    on Oct 24, 2026
  9. melodic-automation-lanes commented on Oct 24, 2026

    @melodic-automation-lanes
    Contributor

    Refinement. A read-only run explored this repository, searched its issues and pull requests, and read the allowed docs to draft what follows. On an issue a listed human filed, it counts as the issue's spec once posted, while unedited; it is still model text, so check it.

    Intended outcome: Extend the cost hold in babysit_risk.py so the shape groups the owner chooses to hold rate HIGH as cost-review-required, with probe rows added to test_babysit_risk_cost.py.

    Dependencies

    • #​9224 (merged cost hold) is the base this extends; some follow-up items were already fixed there at 2795674

    Related work

    Open questions

    1. Which shape groups should the cost hold block (timeouts, model legs, triggers and guards, files and paths, moves), and which are accepted with a reason or left to the review lanes?
      RECOMMENDED: Hold timeouts (including per-job comparison) and model legs (reusable workflows, composite actions, non-Claude actions, ANTHROPIC_MODEL, model and max-turns inputs, script and action files); accept moves; leave triggers, guards and file paths for a later pass. Basis: judgment: timeouts and model legs are direct spend levers, while a moved secret reference is net zero.
    2. Should this be split into one issue per shape group, each with its own probe rows?
      RECOMMENDED: Yes, one issue per group, with the later-comment items riding with their group. Basis: judgment: the triage sized this Large and the shapes are independent changes to babysit_risk.py.
    3. Should the open items from the 2026-10-22 comment (per-job timeout comparison in _raised_timeouts, _SECRET_REF shapes, runners behind expressions) ride with their groups?
      RECOMMENDED: Yes: timeout comparison with timeouts, secret reference shapes with moves, runner expressions with model legs or files. Basis: plugins/source-control/skills/babysit-prs/scripts/babysit_risk.py:834
    4. Is a person needed to rule on the cost-versus-false-hold tradeoff for broad shapes such as new triggers or workflow subdirectories?
      RECOMMENDED: Yes, since this is a spend-policy call outside prepaid credit; the owner should accept or hold each broad shape. Basis: judgment: the owner's 2026-10-24 rule keeps spend decisions with a person.

    Sources read

    • plugins/source-control/skills/babysit-prs/scripts/babysit_risk.py:636: defines COST_CODE cost-review-required
    • plugins/source-control/skills/babysit-prs/scripts/babysit_risk.py:834: _raised_timeouts, which compares added timeouts to the highest removed value
    • plugins/source-control/skills/babysit-prs/scripts/tests/test_babysit_risk_cost.py:1: the cost hold probe tests where new rows go
    • docs/conventions/pr-pipeline/README.md:806: cost-review-required scores HIGH in both lanes regardless of high-path-floor

    Automated refinement by the lanes App. Answer with a comment whose first line is **Decision recorded.**.

  10. 14 remaining items

  11. removed
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.
    on Oct 28, 2026
  12. github-actions commented on Oct 28, 2026

    @github-actions
    Contributor

    The triage sweep dispatched intake triage for this issue (attempt 1 of 2).

  13. added
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.
    on Oct 28, 2026
  14. kyle-sexton commented on Oct 28, 2026

    @kyle-sexton
    MemberAuthor

    Decision recorded. This supersedes the "Model legs: hold" and "timeouts hold on every repository" lines in this issue's spec. My standing cost rule of 2026-10-27 (docs/conventions/loop-lane/README.md, "When work stops for the owner") governs:

    "Cost, which comes to me: anything that can bill me. That means Azure, GitHub (larger runners, Actions minutes or storage on private repositories, paid storage or artifact retention beyond the free quota, plan or seat changes) and any other billing account."

    "Not cost, so spend it freely: model usage under the Claude subscriptions, and each account's promotional $200 API credits."

    Acceptance:

    • A model-settings change (model, effort, turns) in the pr-pipeline config is a non-holding cost finding, not a cost hold.
    • A job-timeout change holds as cost only on a private repository; on a public repository it does not hold.
    • Every shape that can bill (larger runners, private-repo minutes or storage, paid retention, plan or seat changes, Azure) still holds.
  15. melodic-automation-lanes commented on Oct 29, 2026

    @melodic-automation-lanes
    Contributor

    The lanes App's pull request #10583 merged with Refs:, so this issue stays open and nothing starts the lane on it again. work-unblock removed status: ready and agent-ready, so the hourly triage sweep sends it back to intake triage. Admission then parks it at status: confirmed for a check of what that pull request left, until a **Decision recorded.** comment says what is left or someone closes it.

  16. added
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    status: confirmedA maintainer confirmed the item is real and in scope; ready to be worked.
    and removed
    status: readyTriaged, unblocked, and fully specified; eligible to pick up.
    agent-readyFully specified and briefed; eligible for autonomous pickup from the frontier.
    on Oct 29, 2026
  17. melodic-automation-lanes commented on Oct 29, 2026

    @melodic-automation-lanes
    Contributor

    Not admitted to the issue lane: merged pull request #10583 names it with Refs: after its newest decision or refinement comment, so its work may already be done: close the issue if it is, or post a comment whose first line is **Decision recorded.** saying what is left, which sends it back through intake. Admission takes the issue once each of those is met, when intake triages it again (.github/actions/resolve-config/admission-rules.json).

  18. melodic-automation-lanes commented on Oct 29, 2026

    @melodic-automation-lanes
    Contributor

    The latest triage verdict holds nothing: admission moved the issue to status: confirmed; its comment says why.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority: mediumReal value, no hard deadline; normal backlog flow.status: confirmedA maintainer confirmed the item is real and in scope; ready to be worked.work-class: structuralRefactors, migrations, contract changes; cross-cutting and hard to reverse.

    Type

    Fields

    No fields configured for Task.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions