Skip to content

feat(g01): observe bounded idle drain ordering - #72

Open
jjangg96 wants to merge 31 commits into
mainfrom
orca/g01-idle-drain
Open

feat(g01): observe bounded idle drain ordering#72
jjangg96 wants to merge 31 commits into
mainfrom
orca/g01-idle-drain

Conversation

@jjangg96

@jjangg96 jjangg96 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements issue #71 as an experiment-only drain observation phase on pinned github.com/actions/scaleset v0.4.0.

  • Runs the released high-level listener at capacity 1 and withdraws with public SetMaxRunners(0).
  • Holds the first poll response body behind a real transport WroteRequest boundary; response-before-write/timing misses remain inconclusive.
  • Records bounded secret-free counters, fixed response categories, ACK-before-acquire ordering, and exact owned set/runner identities before and after.
  • Integrates drain through approval, verification authority, finite broker ledger, journal validation/replay, and fail-closed quarantine rules.
  • Does not add preprovision seams, RemoveRunner, recovery/replay, live execution, credentials, or workflow operations.

TDD / verification

The initial undefined-symbol compile failure was not meaningful behavioral red. Original pre-implementation behavioral-red evidence is unavailable; later retrospective reproductions do not repair that history. The maintainer explicitly approved this historical process exception only (decision: #71 (comment)). Current corrections retain actual red-before-fix evidence and unchanged review/CI/live gates.

Correction head 5d715c486c959ae67ca615c4eaea3e7e89ede556 has 241 files byte-identical to the snapshot independently reviewed by two Luna/max agents. Coordinator re-ran focused drain/replay/FileJournal/security/pinned-SDK race tests on that exact commit: PASS (1.896s). Exact commands and finding-by-finding evidence remain in docs/evidence/g01-idle-drain.md. Fresh exact-head Codex and hosted CI are pending; this is not merge readiness or live qualification.

Passed:

  • cd experiments/g01-scaleset && go test ./...
  • cd experiments/g02-auth && go test ./...
  • bash scripts/check-offline-experiments.sh
  • make fmt-check build vet test test-race
  • targeted drain race tests and verification-authority tests

The synthetic listener tests are offline protocol evidence only; G01 live qualification remains unresolved. See docs/evidence/g01-idle-drain.md.

Closes #71

@jjangg96

jjangg96 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 9, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-10T07:20:32.857290Z 6357865 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 951e1b8b10

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +341 to +342
if phase == "drain" {
return d.drain(ctx, s.setID)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Route drain before the generic work quarantine

When the intended prerequisite exists—one registered, idle runner—the preceding d.owned call classifies the scale-set statistics as workUnresolved because statisticsWork rejects any nonzero registered/idle count, so Run returns ErrQuarantine before reaching this branch. Consequently the newly exposed drain phase cannot execute for the exact state required by validDrainIdlePrerequisite; dispatch it through drain-specific ownership validation before the generic no-worker gate.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Drain is routed before generic work quarantine; TestDriverRoutesDrainBeforeNoWorkerStatisticsQuarantine and real pinned-SDK Driver integration verify the idle prerequisite is reachable.

Resolution evidence at correction commit 5d715c4: https://github.com/1XP-AI/gh-runnerd/blob/5d715c486c959ae67ca615c4eaea3e7e89ede556/docs/evidence/g01-idle-drain.md . All 241 committed files match the two independently reviewed archive contents. Exact-head focused race verification passed (1.896s). Fresh exact-head Codex review and CI remain separate gates; this reply does not treat staleness as resolution or authorize merge/live work.

Comment on lines +530 to +531
case <-ctx.Done():
return obs, ErrQuarantine

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Join the listener goroutine before returning on cancellation

When the phase deadline expires or the caller cancels while a poll is in flight, this return releases the held body but does not wait for the l.Run goroutine started above. That goroutine can then resume parsing and enter journaledDrainClient, which persists an intent before noticing the canceled context, while drain concurrently closes the session and the command may close the journal; this can corrupt the ordering evidence and leave late ACK/acquisition activity outside the phase lifecycle. Cancel and join runResult before returning from every ctx.Done() path.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Cancellation releases the held body and joins the listener. Cancellation-before-snapshot, after-intent, no-late-effects, and race tests pass; no claim of revoking bytes already sent remotely.

Resolution evidence at correction commit 5d715c4: https://github.com/1XP-AI/gh-runnerd/blob/5d715c486c959ae67ca615c4eaea3e7e89ede556/docs/evidence/g01-idle-drain.md . All 241 committed files match the two independently reviewed archive contents. Exact-head focused race verification passed (1.896s). Fresh exact-head Codex review and CI remain separate gates; this reply does not treat staleness as resolution or authorize merge/live work.

if response.Body == nil {
response.Body = http.NoBody
}
response.Body = &drainHeldBody{source: response.Body, release: h.release}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Hold status-only poll responses as well as body reads

When the first poll returns a bodyless 202 Accepted/no-message response, the client can classify it from the status and close the body without ever calling Read (the synthetic session in drain_test.go follows exactly this pattern). Because drainHeldBody.Close is not gated, this wrapper does not actually hold that response from the listener, yet responseHeld is set to true and an absent first poll is allowed to produce an observed journal record. Gate both reads and close/response delivery, or do not promote status-only responses to observed evidence.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Both Read and Close remain release-gated. TestDrainHeldBodyHoldsCloseUntilRelease passes and bodyless/unknown no-message samples remain inconclusive.

Resolution evidence at correction commit 5d715c4: https://github.com/1XP-AI/gh-runnerd/blob/5d715c486c959ae67ca615c4eaea3e7e89ede556/docs/evidence/g01-idle-drain.md . All 241 committed files match the two independently reviewed archive contents. Exact-head focused race verification passed (1.896s). Fresh exact-head Codex review and CI remain separate gates; this reply does not treat staleness as resolution or authorize merge/live work.

@jjangg96

jjangg96 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

Independent Luna/max protocol and security reviews of exact head 951e1b8 both return FAIL. Focused offline tests passed but did not cover all required behavior. Blocking review items: persist observed request/work and rejected idle-prerequisite uncertainty before crash boundaries so later stale-zero cleanup cannot clear them; reject missing/replaced after-runner identity and no-message/unknown-counter samples as conclusive evidence; join listener lifecycle and fence effects against phase cancellation (including upstream WithoutCancel behavior); validate duplicate/wrong ACK/acquisition identity before remote effects; demonstrate Driver.Run/OpenDrainSession composition with the actual pinned SDK, not only a synthetic session. These source/control-flow findings have been assigned to the sole writer for executable reproduction before fixes; they are not being represented as already-executed failing tests. Codex P1 threads r3965776815, r3965776826 and r3965776832 remain merge blockers until reproduced resolution and fresh review. The original undefined-symbol compile failure is not acceptable behavioral TDD evidence; chronology must be corrected honestly rather than relabeled. Reviewers excluded work after the shared checkout advanced to f44f5f9. No merge or live qualification is authorized by passing CI.

@jjangg96

jjangg96 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f44f5f9b36

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

func (c controllerApproval) needsVerification() bool {
return slices.ContainsFunc(c.Phases, func(phase string) bool {
return phase == "before-ack" || phase == "after-ack" || phase == "before-acquire" || phase == "acquire-loss"
return phase == "before-ack" || phase == "after-ack" || phase == "before-acquire" || phase == "acquire-loss" || phase == "drain"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Recognize drain in paired approval validation

When a least-privilege paired-terminal approval contains create, drain, inspect, and cleanup, this change makes the broker treat it as verification-capable and accept it, but the downstream ValidatePairedApprovals and pairedPreparationReady checks still recognize only the four older verification phases. The broker can therefore approve and issue the paired handoff only for the controller to reject the same approval; add drain to those paired-side verification checks as well.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Paired approval validation recognizes drain. Exact-head TestValidatePairedApprovalsAcceptsDrainVerification passes (0.471s).

Resolution evidence at correction commit 5d715c4: https://github.com/1XP-AI/gh-runnerd/blob/5d715c486c959ae67ca615c4eaea3e7e89ede556/docs/evidence/g01-idle-drain.md . All 241 committed files match the two independently reviewed archive contents. Exact-head focused race verification passed (1.896s). Fresh exact-head Codex review and CI remain separate gates; this reply does not treat staleness as resolution or authorize merge/live work.

@jjangg96

jjangg96 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 945371e1ec

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if o == nil || o.Version != drainObservationVersion || (o.Outcome != drainOutcomeObserved && o.Outcome != drainOutcomeInconclusive) || o.InitialCapacity != drainInitialCapacity || o.WithdrawnCapacity != drainWithdrawnCapacity || o.ServerReceipt != drainServerReceiptUnproven || o.Sequence <= 0 || o.ObservedAt.IsZero() || len(o.Ordering) > 8 {
return false
}
if o.Boundary != drainBoundaryRequestWritten && o.Boundary != drainBoundaryResponseBeforeWrite && o.Boundary != drainBoundaryUnresolved || !validDrainPoll(o.Poll, drainInitialCapacity) || !validDrainPoll(o.NextPoll, drainWithdrawnCapacity) || !validDrainSnapshot(o.Before, o.Before.Set) || !validDrainSnapshot(o.After, o.Before.Set) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Require the same runner in the after snapshot

When the canary runner disappears or re-registers with a new ID between the before and after reads, this validation still accepts the observation because each snapshot independently permits either a nil runner or any positive runner associated with the scale set. drain can therefore persist Outcome == "observed", and replay retains it without uncertainty, even though the owned idle-runner identity was lost during the experiment; compare Before.Runner and After.Runner for exact equality (and require both for an observed outcome), otherwise mark the result inconclusive.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Observed evidence requires the exact same nonnil owned runner before/after and the one-owned-idle prerequisite. Runner replacement/missing identity and real FileJournal invalid-proof regressions pass.

Resolution evidence at correction commit 5d715c4: https://github.com/1XP-AI/gh-runnerd/blob/5d715c486c959ae67ca615c4eaea3e7e89ede556/docs/evidence/g01-idle-drain.md . All 241 committed files match the two independently reviewed archive contents. Exact-head focused race verification passed (1.896s). Fresh exact-head Codex review and CI remain separate gates; this reply does not treat staleness as resolution or authorize merge/live work.

@jjangg96

jjangg96 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6e954cfe1a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +119 to +120
if e.Operation == "drain" {
s.workObserved = true

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Quarantine a drain before its final observation

If the process exits after the durable session-close result—or after the completed after-snapshot reads—but before the final drain observation is recorded, replay never enters this branch: the drain phase itself does not set workObserved or uncertain, and every effect intent may already be balanced. A later approved cleanup can therefore pass authorizePhase and call DeleteScaleSet even though the drain ran without a durable outcome; mark the phase uncertain before remote polling or make replay quarantine a drain phase lacking its observation.

AGENTS.md reference: AGENTS.md:L8-L8

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The durable drain phase remains pending until exactly one matching valid observation; missing/repeated/interrupted phase, wrong identity/sequence, and unrelated uncertainty cannot discharge it. Crash and FileJournal reopen tests pass.

Resolution evidence at correction commit 5d715c4: https://github.com/1XP-AI/gh-runnerd/blob/5d715c486c959ae67ca615c4eaea3e7e89ede556/docs/evidence/g01-idle-drain.md . All 241 committed files match the two independently reviewed archive contents. Exact-head focused race verification passed (1.896s). Fresh exact-head Codex review and CI remain separate gates; this reply does not treat staleness as resolution or authorize merge/live work.

Comment on lines +154 to +155
stats, err := newDrainStatistics(current.Statistics)
if err != nil || stats != before.Statistics {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Validate the session's embedded scale set before draining

When the session response contains a non-nil RunnerScaleSet whose identity, update setting, or statistics disagree with the idle before-snapshot, this check accepts the session as long as the top-level Statistics still match. The existing probe path explicitly incorporates RunnerScaleSet.Statistics as work evidence, so ignoring it here can let the drain poll, ACK, and acquire while the session itself reports existing or busy work, invalidating the observation; validate the embedded set and require its statistics to agree before starting the listener.

AGENTS.md reference: AGENTS.md:L12-L12

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Session open checks embedded scale-set identity, labels, update setting and statistics against the idle snapshot. TestDrainRejectsEmbeddedSessionStatisticsMismatch and pinned-SDK integration pass.

Resolution evidence at correction commit 5d715c4: https://github.com/1XP-AI/gh-runnerd/blob/5d715c486c959ae67ca615c4eaea3e7e89ede556/docs/evidence/g01-idle-drain.md . All 241 committed files match the two independently reviewed archive contents. Exact-head focused race verification passed (1.896s). Fresh exact-head Codex review and CI remain separate gates; this reply does not treat staleness as resolution or authorize merge/live work.

Comment on lines +165 to +166
obs, runErr := runDrainListener(ctx, journaled, setID, hook)
closeErr := d.effect(ctx, "session-close", nil, func(call context.Context) (Event, error) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Retain the session after ambiguous drain side effects

When the first ACK or acquisition returns an error—or acquisition returns a mismatched response—the journal wrapper records an unknown/reservation and runDrainListener returns ErrQuarantine, but this path still unconditionally calls session.Close. Closing the session after an ambiguous acquisition can alter or requeue the outstanding work and destroys the known session that the existing acquire-loss contract deliberately retains; only close after outcomes that are known safe, and retain the session on quarantine.

AGENTS.md reference: AGENTS.md:L12-L12

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ambiguous listener effects retain the session and durable uncertainty rather than unconditionally closing. The independent archive reviews verified retained-session/zero-close behavior.

Resolution evidence at correction commit 5d715c4: https://github.com/1XP-AI/gh-runnerd/blob/5d715c486c959ae67ca615c4eaea3e7e89ede556/docs/evidence/g01-idle-drain.md . All 241 committed files match the two independently reviewed archive contents. Exact-head focused race verification passed (1.896s). Fresh exact-head Codex review and CI remain separate gates; this reply does not treat staleness as resolution or authorize merge/live work.

@jjangg96

jjangg96 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: f482d249e6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@jjangg96

jjangg96 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@jjangg96

jjangg96 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

Exact f482d24 independent reviews: security F1-F8 pass the corrected archived offline reproductions, including durable pre-ACK reservation, stale-zero cleanup refusal, runner/session identity, callback ordering and actual pinned-SDK drain integration. Protocol review additionally reproduced remaining gaps: unknown next-poll statistics and an empty statistics object can still be classified as observed; cancellation during durable ACK-intent append can precede an inner call; early snapshot cancellation omits its fixed marker. These deeper tests mean overall independent approval remains FAIL despite the narrower passing controls. Required fixes are assigned to the sole writer with focused failing-before-fix evidence; no claim is made that local cancellation can revoke a remotely accepted operation. F9 evidence chronology also remains unresolved: retrospective reproductions must not be described as preceding the correction without trustworthy earlier evidence. Root CI run34332963834 failed make fmt-check on sdk.go; formatting correction requires fresh exact-head CI. No merge or live qualification.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 02ba76466d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +649 to +650
if obs.Boundary == drainBoundaryRequestWritten && obs.ResponseHeld && obs.Poll.Message == drainMessagePresent && obs.Poll.StatsKnown && obs.Poll.ACK == drainResponseSucceeded && obs.Poll.Acquisition == drainResponseSucceeded && obs.NextPoll.Message == drainMessageAbsent {
obs.Outcome = drainOutcomeObserved

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reject poll counters that contradict the owned runner

When the first message response has internally consistent but contradictory runner counters—for example, zero registered/idle runners—newDrainStatistics accepts it and this predicate can still promote the run to observed after ACK/acquisition. The before and session snapshots prove exactly one registered idle runner, and docs/evidence/g01-idle-drain.md explicitly classifies contradictory counters as inconclusive, so require the poll's runner partition to remain consistent with that prerequisite before recording successful G01 evidence.

AGENTS.md reference: AGENTS.md:L11-L11

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

First, withdrawn and after runner partitions must agree with the owned one-idle proof; legitimate job counter changes remain allowed. Contradictory first/next-poll and real FileJournal non-owned-proof tests pass.

Resolution evidence at correction commit 5d715c4: https://github.com/1XP-AI/gh-runnerd/blob/5d715c486c959ae67ca615c4eaea3e7e89ede556/docs/evidence/g01-idle-drain.md . All 241 committed files match the two independently reviewed archive contents. Exact-head focused race verification passed (1.896s). Fresh exact-head Codex review and CI remain separate gates; this reply does not treat staleness as resolution or authorize merge/live work.

return h.inner.RoundTrip(req)
}

trace := &httptrace.ClientTrace{WroteRequest: func(info httptrace.WroteRequestInfo) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Detect transparently retried poll writes

When the first capacity-1 GET uses the keep-alive connection established while opening the session and encounters a network error, http.Transport may transparently retry this idempotent bodyless request. Each physical attempt invokes WroteRequest, but wroteOnce hides every callback after the first and no duplicate successful write marks the hook invalid; the retried request also retains its already-built capacity-1 header despite SetMaxRunners(0). Two old-capacity polls can therefore reach the service while the final response is still promoted to observed, so count and quarantine duplicate write callbacks or prevent transport-level retries.

AGENTS.md reference: AGENTS.md:L11-L11

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Each physical write is accounted for on BOTH polls. Duplicate/error/transparent retry traces cannot promote observed evidence; first/second real HTTP retries and 4x4 matrix pass.

Resolution evidence at correction commit 5d715c4: https://github.com/1XP-AI/gh-runnerd/blob/5d715c486c959ae67ca615c4eaea3e7e89ede556/docs/evidence/g01-idle-drain.md . All 241 committed files match the two independently reviewed archive contents. Exact-head focused race verification passed (1.896s). Fresh exact-head Codex review and CI remain separate gates; this reply does not treat staleness as resolution or authorize merge/live work.

@jjangg96

jjangg96 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. You're on a roll.

Reviewed commit: 21fe1f846d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@jjangg96

jjangg96 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6e1b2144cb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if !second {
return nil, ErrQuarantine
}
response, err := h.inner.RoundTrip(req)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reject retries on the withdrawn-capacity poll

When the second, capacity-zero GET uses a reused connection and encounters a retryable transport failure, http.Transport may transparently replay this idempotent bodyless request. The current correction counts WroteRequest callbacks only in the first-poll branch; this branch delegates directly to the inner transport, so multiple zero-capacity polls can reach GitHub while the journal still records one poll-zero and promotes the result to observed. Instrument and quarantine duplicate physical writes for the second poll as well.

AGENTS.md reference: AGENTS.md:L11-L11

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The withdrawn poll now uses the traced request path too; exactly one successful physical write per poll is required. TestDrainListenerRejectsWithdrawnPollPhysicalRetry and the both-poll matrix pass.

Resolution evidence at correction commit 5d715c4: https://github.com/1XP-AI/gh-runnerd/blob/5d715c486c959ae67ca615c4eaea3e7e89ede556/docs/evidence/g01-idle-drain.md . All 241 committed files match the two independently reviewed archive contents. Exact-head focused race verification passed (1.896s). Fresh exact-head Codex review and CI remain separate gates; this reply does not treat staleness as resolution or authorize merge/live work.

Comment on lines +113 to +116
if e.Operation == "drain" {
// The phase record is durable intent to observe a live session.
// A crash before its final observation must not reopen cleanup.
s.uncertain = true

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Discharge the drain phase fence after valid observation

Every real drain journal includes this phase record, so even a fully successful final drain observation replays with uncertain == true: the phase sets the flag here, while the observed-outcome branch only avoids adding more uncertainty and never clears the phase-local fence. This contradicts the documented distinction that only inconclusive drain results retain uncertainty and causes a successful experiment to remain classified like an interrupted one; track and discharge this specific fence when a valid observed record closes the phase without clearing unrelated uncertainty.

AGENTS.md reference: AGENTS.md:L11-L11

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Replay tracks a phase-local fence with positive explicit SetID and journal phase sequence. Only its exact valid one-idle observation discharges it; unrelated uncertainty, pending intents, work/reservations remain. Real FileJournal close/reopen and negative histories pass.

Resolution evidence at correction commit 5d715c4: https://github.com/1XP-AI/gh-runnerd/blob/5d715c486c959ae67ca615c4eaea3e7e89ede556/docs/evidence/g01-idle-drain.md . All 241 committed files match the two independently reviewed archive contents. Exact-head focused race verification passed (1.896s). Fresh exact-head Codex review and CI remain separate gates; this reply does not treat staleness as resolution or authorize merge/live work.

Comment on lines +103 to +107
| Security F5 / Protocol F5 counters and integration | known counters require nonnegative internally consistent busy/idle partition; unknown values cannot masquerade as zero. `TestDrainRequiresKnownConsistentStatisticsAndControlledMessage` and `TestDriverDrainThroughPinnedSDKAndPollHook` pass (`82d0d7d`). |
| Protocol F3 cancellation/WithoutCancel | phase context is bound through the wrapper, checked before every ACK/acquisition/poll effect, and cancellation/deadline/quarantine writes a fixed marker even when close/after inspect fails. `TestDrainRejectsEffectsAfterCancellationAndRecordsMarker` passes (`82d0d7d`). |
| Protocol F4 duplicate/wrong callbacks | exact phase, identity, ACK-before-acquire and one-shot state are validated before inner effects; wrong/duplicate callbacks make zero additional inner calls. `TestDrainRejectsDuplicateOrWrongEffectsBeforeInnerCall` passes (`82d0d7d`). |
| Protocol F6 cancellation race and early snapshot | durable intent is followed by a cancellation fence immediately before the bounded SDK call; a canceled before-snapshot path records its fixed marker. The fence does not claim to revoke bytes already accepted by a remote service. `TestDrainCancellationAfterIntentRejectsEffect` and `TestDrainCancellationBeforeSnapshotRecordsMarker` pass on the correction head. |
| Protocol F9 TDD chronology | the compile-only red and retrospective base/repro executions are now labeled candidly; no later archive reproduction is represented as pre-implementation evidence. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Record the latest Codex finding resolutions

The correction matrix ends without recording the two latest Codex findings concerning contradictory poll counters and transparent poll retries as Codex resolutions with their finding URLs, reproduction results, and resolution evidence. Although related tests now exist, the repository explicitly requires those per-finding records after fixes, so this head does not yet satisfy the documented exact-head review gate and must not be treated as merge-ready until the matrix is completed.

AGENTS.md reference: AGENTS.md:L17-L17

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The durable correction matrix now includes full finding URLs, actual red/green commands/results and rollback scope, including both earlier retry/counter findings and subsequent phase/idle-proof corrections. Original missing TDD history remains candidly disclosed with a separately recorded maintainer exception.

Resolution evidence at correction commit 5d715c4: https://github.com/1XP-AI/gh-runnerd/blob/5d715c486c959ae67ca615c4eaea3e7e89ede556/docs/evidence/g01-idle-drain.md . All 241 committed files match the two independently reviewed archive contents. Exact-head focused race verification passed (1.896s). Fresh exact-head Codex review and CI remain separate gates; this reply does not treat staleness as resolution or authorize merge/live work.

@jjangg96

jjangg96 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

Coordinator checkpoint for 6e1b214: all four hosted CI checks passed (run 34340970782). Two independent Luna/max archive reviews passed the three targeted corrections and their focused prior-boundary tests, including actual first-poll transparent HTTP retry fixtures. Those passes do NOT cover newly reported second-poll retry and successful-phase fence findings. Latest exact-head Codex review reports actionable findings #72 (comment), #72 (comment), and missing durable evidence #72 (comment). A sole Luna/max writer is assigned behavioral reproduction before minimal corrections and evidence updates. Merge remains held. PR body now honestly distinguishes initial compile-only failure from meaningful TDD; unavailable original behavioral-red chronology remains a historical process gap, not retroactively repaired by regression tests. No live resources or credentials were changed.

@jjangg96

jjangg96 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

Exact-head checkpoint: 9904048 has all four CI checks successful (run 34408989415). Independent Luna/max protocol review passed the prior six corrections; security review remains in progress. The fresh Codex review at 2026-09-09T22:01:40Z raises four NEW P1 findings: non-EOF poll-body read errors (r3973406578), physical ACK binding (r3973406571), strict runner snapshot decoding (r3973406564), and strict drain-session decoding (r3973406553). Merge remains blocked. A sole Luna/max writer is assigned meaningful red-first reproductions and minimal adapter corrections, plus a bounded audit of the full drain evidence boundary to avoid piecemeal lossy-decoding gaps. No live operation is authorized or performed; parent G01 live evidence remains unresolved. Completed protocol-review terminal has been released.

@jjangg96

jjangg96 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 88d37abea8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +564 to +568
h.wroteRequest = true
}
h.mu.Unlock()
if notify && info.Err == nil && h.onRequestWritten != nil {
h.onRequestWritten()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Wait for withdrawal before marking the boundary proven

When the first response becomes available while the WroteRequest callback is still executing, wroteRequest is already true even though onRequestWritten has not yet completed SetMaxRunners(0). The response-first branch can therefore treat the boundary as proven and release the held body, allowing parsing, ACK, and acquisition before capacity withdrawal completes and falsely promoting the run to observed. Record a separate withdrawal-completed fact after the callback returns and require it before releasing or proving this boundary.

AGENTS.md reference: AGENTS.md:L11-L11

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Correction in 64c6fce, retained in current clean head d85213a with the additional exact HTTPS Actions queue-host fix b3d45cb.

The hook now waits for withdrawal callback completion before normal response release and boundary proof; deterministic blocked-callback and cancellation tests cover the ordering.

Timestamped implementer red/green evidence and rollback are in docs/evidence/g01-idle-drain.md. Coordinator independently ran:

cd experiments/g01-scaleset
GOTOOLCHAIN=go1.26.8 go test -race ./livecanary -run '^(TestPinnedSDKDrainRequiresApprovedHTTPSQueueHost|TestValidDrainQueueURLRequiresExactApprovedHostPort|TestPinnedSDKDrainAcceptsUnrelatedRunnerMetadata|TestDrainListenerDoesNotReleaseBeforeWithdrawalCompletes|TestDrainListenerCancellationWhileWithdrawalBlockedDoesNotDeadlock|TestDriverDrainThroughPinnedSDKAndPollHook)$' -count=1 -timeout=180s

PASS, package1.533s, no race report. All evidence is offline. Current-head independent protocol/security review, fresh Codex and CI remain pending; keeping this thread open until final evidence audit.

ScaleSetID *int `json:"runnerScaleSetId"`
} `json:"value"`
}
if DecodeStrict(data, &w) != nil || w.Count == nil || w.Value == nil || *w.Count < 0 || *w.Count > 1 || *w.Count != len(*w.Value) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Allow unrelated runner metadata in strict captures

When the distributed-task agent response includes normal non-identity metadata such as status or version fields, DecodeStrict rejects the entire payload because its decoder disallows fields absent from this three-field value struct. The pinned SDK normally ignores such extra fields, but the new wire reader now quarantines both before and after snapshots before the drain listener can run. Retain the recursive duplicate-key check while decoding only the bounded identity fields with an unknown-field-tolerant unmarshal, as the scale-set capture already does.

AGENTS.md reference: AGENTS.md:L11-L11

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Correction in 64c6fce, retained in current clean head d85213a with the additional exact HTTPS Actions queue-host fix b3d45cb.

Runner metadata decoding now tolerates unrelated fields while retaining recursive duplicate/case-fold rejection and required count/value identity constraints.

Timestamped implementer red/green evidence and rollback are in docs/evidence/g01-idle-drain.md. Coordinator independently ran:

cd experiments/g01-scaleset
GOTOOLCHAIN=go1.26.8 go test -race ./livecanary -run '^(TestPinnedSDKDrainRequiresApprovedHTTPSQueueHost|TestValidDrainQueueURLRequiresExactApprovedHostPort|TestPinnedSDKDrainAcceptsUnrelatedRunnerMetadata|TestDrainListenerDoesNotReleaseBeforeWithdrawalCompletes|TestDrainListenerCancellationWhileWithdrawalBlockedDoesNotDeadlock|TestDriverDrainThroughPinnedSDKAndPollHook)$' -count=1 -timeout=180s

PASS, package1.533s, no race report. All evidence is offline. Current-head independent protocol/security review, fresh Codex and CI remain pending; keeping this thread open until final evidence audit.

@jjangg96

jjangg96 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

Exact-head checkpoint 88d37ab: all four CI checks pass, and coordinator race tests for the prior four corrections pass (1.575s). Fresh Codex review at 2026-09-09T22:56:00Z raises two P1s: normal extra runner metadata rejection (r3973755454) and withdrawal completion racing the response boundary (r3973755448). A sole Luna/max writer is assigned red-first reproductions and minimal corrections; independent reviewers remain read-only on the immutable archive. Merge remains blocked, with no live operation performed. Parent G01 live evidence remains unresolved.

@jjangg96

jjangg96 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

Checkpoint cb2c1ba: source64c6fce0f9f86ece48a7b28ee51b1aef9774f2cb fixes runner metadata compatibility and withdrawal-completion race, with timestamped red/green evidence. An independent security P1 remains: session queue URL can use the general API origin instead of an exact approved Actions host. The same implementation session is assigned that focused red-first follow-up before final reviews, avoiding redundant intermediate review launches. Both completed independent-review terminals were released. Unknown session-open remains locally fenced; a durable known session ID/reservation must not be claimed when strict decoding failed. No live operations or merge performed; parent G01 still requires authorized live evidence.

@jjangg96

jjangg96 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d85213a212

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

return runErr
}
closeErr := d.effect(ctx, "session-close", nil, func(call context.Context) (Event, error) {
if err := session.Close(call); err != nil {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Bind session close to the physical DELETE

If the pinned SDK sends the close DELETE to the wrong set/session path and that endpoint returns success, this direct session.Close call records session-close as completed, replay clears the outstanding session ID, and the drain can return an observed result even though its actual session remains open. Use the existing terminal-session-close wire capture to require the exact session DELETE and 204 response before persisting success.

AGENTS.md reference: AGENTS.md:L11-L11

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Correction pushed in 05b5fff; current review head 116beda. Timestamped baseline red and green evidence is recorded in docs/evidence/g01-idle-drain.md. Coordinator independently ran GOTOOLCHAIN=go1.26.8 go test -race ./livecanary -run '^(TestPinnedSDKDrainBindsAcquireToPhysicalRequestBody|TestPinnedSDKDrainBindsSessionCloseToPhysicalDelete|TestDriverDrainThroughPinnedSDKAndPollHook)$' -count=1 -timeout=180s: PASS (1.829s), including TestPinnedSDKDrainBindsSessionCloseToPhysicalDelete. Two independent Luna max reviews and a fresh exact-head Codex review are pending; this reply does not assert a clean verdict or authorize merge/live operations.

Comment on lines +173 to +176
wire = &baselineWireCapture{stage: "acquire", setID: setID, queue: queue, allowedHosts: baselineWireAllowedHosts(c.d.Approval, apiHost)}
call = wire.context(call)
}
got, err = c.inner.AcquireJobs(call, slices.Clone(ids))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Bind acquisition evidence to the physical request body

If the pinned SDK serializes a different runner-request ID than ids in the acquisition POST while the endpoint returns the expected count/value, the capture validates only method, path, host, query, and response, so both accepted.matches(ids) and slices.Equal(got, ids) pass while the remote call may have acquired different work. Pass the expected IDs into this wire capture and strictly compare the bounded POST body before forwarding it.

AGENTS.md reference: AGENTS.md:L11-L11

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Correction pushed in 05b5fff; current review head 116beda. Timestamped baseline red and green evidence is recorded in docs/evidence/g01-idle-drain.md. Coordinator independently ran GOTOOLCHAIN=go1.26.8 go test -race ./livecanary -run '^(TestPinnedSDKDrainBindsAcquireToPhysicalRequestBody|TestPinnedSDKDrainBindsSessionCloseToPhysicalDelete|TestDriverDrainThroughPinnedSDKAndPollHook)$' -count=1 -timeout=180s: PASS (1.829s), including TestPinnedSDKDrainBindsAcquireToPhysicalRequestBody. Two independent Luna max reviews and a fresh exact-head Codex review are pending; this reply does not assert a clean verdict or authorize merge/live operations.

@jjangg96

jjangg96 commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

Checkpoint d85213a: all four CI checks pass, both independent Luna/max passes validate the metadata, withdrawal-completion and exact Actions queue-host corrections, and both reviewer terminals are released. Fresh exact-head Codex review at 2026-09-09T23:41:25Z identifies two remaining P1 request-side gaps: physical acquisition POST body binding (r3974007599) and exact session-close DELETE binding before clearing the session fence (r3974007586). A sole Luna/max writer is assigned meaningful red-first real-SDK reproductions and minimal existing-adapter fixes. Merge remains blocked, no live operation performed, full parent G01 live evidence remains unresolved.

@jjangg96

Copy link
Copy Markdown
Contributor Author

@codex review

@jjangg96

Copy link
Copy Markdown
Contributor Author

Checkpoint for exact head 116beda: all four Public CI checks succeeded (run 34419651240). Coordinator focused race regressions passed (1.829s), and correction evidence is linked in replies to r3974007599/r3974007586. Two fresh independent Luna max reviews are active; a fresh Codex review was requested for this head and its verdict remains pending. A possible asynchronous request-body Read/Close lifetime issue is assigned to the security reviewer for reproduction; it is not yet a confirmed finding. No merge or live operations authorized by these offline results; G01 remains open.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 116beda04d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +159 to +160
if c == nil || c.stage != "acquire" || len(c.requestIDs) == 0 || !c.target(req) {
return nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reject mismatched acquisition targets before forwarding

When an SDK regression or request wrapper changes the acquisition host, path, set ID, or query, the !c.target(req) case returns success here, so baselineRequestCaptureTransport still sends the request and only quarantines after the remote side effect. A wrong-set acquisition can therefore reserve unrelated work even though the adapter claims to be the final pre-network boundary. Fresh evidence beyond the earlier request-body finding is that invalid bodies are now stopped before forwarding, while invalid targets explicitly bypass that guard; return an error for a marked acquisition whose target does not match.

AGENTS.md reference: AGENTS.md:L11-L11

Useful? React with 👍 / 👎.

Comment on lines +375 to +376
wire := &baselineWireCapture{stage: "terminal-session-close", setID: setID, sessionID: sessionID}
call = wire.context(call)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Bind session close to the exact endpoint origin

When an approval contains multiple allowed Actions hosts and the SDK or a transport wrapper sends this close to the wrong allowed origin, the terminal-session-close capture checks only the path suffix and query, not the scheme/host. A 204 from that other origin therefore satisfies wire.observed(), clears the durable session ID, and permits an observed result while the real session remains open. Fresh evidence beyond the earlier set/session-path finding is that the corrected capture still receives no expected origin here; bind it to the exact session-open endpoint before accepting close success.

AGENTS.md reference: AGENTS.md:L11-L11

Useful? React with 👍 / 👎.

@jjangg96

Copy link
Copy Markdown
Contributor Author

Exact-head Codex review completed for 116beda at 2026-09-10T00:20:25Z with two new P1 findings: r3974234277 (marked acquisition target bypasses pre-network validation), r3974234284 (session close is not bound to the expected endpoint origin). All four CI checks passed, but this head is NOT merge-ready. A sole Luna max implementation worker is assigned to reproduce both before minimal fixes; the two independent baseline reviewers continue archive-only checks, including asynchronous request-body lifetime. The historical clean verdict for 21fe1f is stale and does not authorize this head. No live operation or merge has occurred.

@jjangg96

Copy link
Copy Markdown
Contributor Author

Safe handoff: source 1d25d31 and evidence f08e9f3 are pushed. The writer reports red/green fixes for acquisition target preflight, session-close origin binding, and standard request-body lifetime/concurrency; exact commands and chronology are in docs/evidence/g01-idle-drain.md. Coordinator has accepted the handoff and released the implementation/review terminals, not approved merge. Maintainer prioritizes workflow-efficiency issue73: no new broad review cycle or duplicate local full-suite run is being started now. This head still needs independent delta acceptance, fresh exact-head Codex verdict, and completed CI; G01 live evidence and parent goal remain open.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f08e9f3e0b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +195 to +198
if c.stage == "session-open" {
if !c.target(req) {
return nil
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reject mismatched session-open requests before forwarding

When the pinned SDK or a transport wrapper changes the session-creation host, path, set ID, method, or query, this branch returns success and baselineRequestCaptureTransport still forwards the POST. A successful wrong-target request can therefore create an orphaned session for another scale set; OpenDrainSession rejects it only after the remote side effect and discards the returned session identity, leaving no way to close it. Reject a marked session-open request that does not match c.target(req) before calling the inner transport.

AGENTS.md reference: AGENTS.md:L11-L11

Useful? React with 👍 / 👎.

@jjangg96

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c0e8a2ec70

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 87 to +89
} else if c.stage == "acquire" {
suffix += "acquirejobs"
if len(c.allowedHosts) == 0 || !slices.Contains(c.allowedHosts, r.URL.Host) {
return false

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Bind acquisition to the session-open origin

When an approval lists multiple Actions hosts, or when api.github.com is added by baselineWireAllowedHosts, an acquisition redirected to any one of those hosts still passes this membership check. If that origin has the same numeric scale-set ID and returns the expected count/value, the request can reserve unrelated work and be recorded as successful; the fresh evidence beyond the earlier target fix is that the current capture stores the exact session-open origin but acquisition validates only the broader allowlist. Require the acquisition origin to equal the captured session origin.

AGENTS.md reference: AGENTS.md:L11-L11

Useful? React with 👍 / 👎.

Comment on lines +200 to +204
if !c.target(req) {
if baselineSessionOpenRequestCandidate(req) {
return c.rejectRequest(req)
}
return nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reject every non-bootstrap session-open mismatch

When the marked session-creation request is mutated to a path that no longer contains /runnerscalesets/—for example /sessions on an allowed origin—this predicate classifies it like bootstrap traffic and forwards the state-changing POST before the response-side capture can quarantine it. The fresh evidence beyond the prior resolution is that the new candidate check covers only one route family, so the claimed pre-network target fence is still bypassable; explicitly allow the known bootstrap requests and reject every other marked non-target request.

AGENTS.md reference: AGENTS.md:L11-L11

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6357865735

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +253 to +257
if !c.target(req) {
if baselineAcquireRequestCandidate(req) {
return c.rejectRequest(req)
}
return nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reject every marked acquisition mismatch

When a wrapper rewrites the marked acquisition POST to a path that contains neither the case-sensitive /_apis/runtime/runnerscalesets/ fragment nor the /acquirejobs suffix, this branch still forwards it even though c.target(req) has already rejected it. For example, a case-folded wrong-set acquisition route can reach a case-insensitive service and reserve unrelated work before the response is quarantined. Fresh evidence beyond the prior acquisition-target finding is that the new candidate predicate still leaves this route-family escape; unlike session opening, acquisition has no bootstrap traffic to preserve, so every marked non-target request should fail before the inner transport.

AGENTS.md reference: AGENTS.md:L11-L11

Useful? React with 👍 / 👎.

Comment on lines +202 to +204
if reader, ok := d.API.(drainScaleSetWireReader); ok {
wire := &baselineWireCapture{stage: "set-observe", setID: setID}
set, err = reader.drainGetScaleSet(call, setID, wire)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Bind scale-set snapshot requests to one origin

When an approval contains multiple allowed Actions hosts, this evidence-bearing capture records no expected origin, while the set-observe target check accepts any HTTPS request whose path merely ends in the scale-set suffix. Because newSDKTransport permits every approved Actions host, a mutated before or after request can read the same numeric set ID from a different origin (or tenant path), and matching identity/counters from that response can still support an observed drain. Fresh evidence beyond the earlier strict snapshot-response finding is that the response is now decoded strictly but its physical request origin is never captured or corroborated; bind both snapshots to the same expected runtime origin before using them as proof.

AGENTS.md reference: AGENTS.md:L11-L11

Useful? React with 👍 / 👎.

Comment on lines +246 to +248
c.origin = origin
c.mu.Unlock()
return nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Validate the session-open body before forwarding

When the pinned SDK or an intervening wrapper serializes a different owner in the marked session-creation POST, the exact target and origin checks pass and this branch forwards the request without inspecting its body. The service can therefore create a live session for the wrong owner; the later strict response comparison quarantines it but OpenDrainSession discards the returned session object, leaving the controller without an identity it can safely close. Validate the bounded session-open request body before the inner transport, as the acquisition path already does for its request IDs.

AGENTS.md reference: AGENTS.md:L11-L11

Useful? React with 👍 / 👎.

Comment on lines +1220 to +1223
Date: 2026-09-10. This correction addresses the two independent private review
findings on exact head c0e8a2e: acquisition was bound to the approved-host set
rather than the session-open origin, and the marked session-open classifier
could forward route-family escapes or reject an organization named

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Record URLs for the latest Codex resolutions

This final correction describes the acquisition-origin and session-open route findings only as independent private-review findings and does not record either Codex discussion URL, even though both findings were fixed in this head. Fresh evidence beyond the earlier correction-matrix finding is that these corrections were appended after that matrix was completed, so its earlier resolution does not cover them. The repository requires a finding URL, reproduction result, and resolution evidence for every addressed Codex finding; add the two latest URLs so this head can satisfy the documented exact-head review gate.

AGENTS.md reference: AGENTS.md:L17-L17

Useful? React with 👍 / 👎.

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.

[G01h] Observe in-flight idle drain without deleting owned work

1 participant