Skip to content

refactor(executor): make the three protection-bearing context fields REQUIRED (#9541) - #9582

Merged
JSONbored merged 1 commit into
mainfrom
refactor/required-decision-context-9541
Jul 28, 2026
Merged

refactor(executor): make the three protection-bearing context fields REQUIRED (#9541)#9582
JSONbored merged 1 commit into
mainfrom
refactor/required-decision-context-9541

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Closes #9541deliverable 3 of 3, and the structural half of #9482.

Deliverable 1 shipped as #9580; deliverable 2 as #9557. This completes the issue.

The gap this closes

#9482's behavioural fixes already landed: the approval-accept path now threads authorLogin, expectedBaseRef and moderationSettings.

But it threads them by convention — three explanatory comments at one call site — while the type still marked all three optional. Nothing stopped the next caller omitting them again. That is exactly what #9482's own deliverable asked for:

Prefer a shared, typed "decision pass context" constructed by both paths over ad-hoc optional fields — that structurally prevents the next omission.

What changes

All three are now required on AgentActionExecutionContext, following #9539's required decisionNowMs precedent.

null remains a valid value. What is no longer expressible is omitting the field. That distinction is the whole point, because each absence disabled a protection rather than degrading it:

field what its absence did
authorLogin step 8c's cap-lock key degrades to contributor-cap-lock:<repo>: — zero exclusion, and every accept-path merge in the repo collapsing onto one shared empty-author key. Separately, maybeEscalateModeration early-returns, so enforcement closes recorded no violation and never counted toward the warning/ban threshold.
expectedBaseRef #9055's base-retarget guard never runs, so a PR retargeted after staging merges into a base the reviewed diff and CI never targeted. A wrong-merge class.
moderationSettings the repo's per-repo overrides silently fall back to global defaults.

IssueActionExecutionContext gets the same treatment. #9482 audited only the PR context, but its twin carries two of the same fields with the same hazard — fixing one type and not the other is precisely the drift this deliverable exists to end.

What the type change found

Four more call sites in processors.ts omitting expectedBaseRef (two also moderationSettings), none of them audited by #9482.

All four turn out to be close or update_branch paths where null is genuinely correct — a close has no base to protect against a retarget — so the fix is a stated null with the reason, not a behaviour change.

That they stayed invisible until the compiler demanded an answer is the entire argument for a type guarantee over a convention.

Behaviour-preserving

Full suite: 24,016 passed. Test fixtures were updated only to supply the fields real callers must now supply.

Two tests that deliberately exercised the absent-author degradation move from undefined to null — the same case, spelled the way the type now expresses it. They still assert the same behaviour (maybeEscalateModeration skipping, the cap-recheck path), so the degradation stays covered; it just can no longer be reached by accident.

Testing

Two type-level invariants pin the guarantee itself: that null stays expressible (so "no author / no base / inherit defaults" remains a stated choice rather than a forbidden one), and that a real value is carried through unchanged. Both would fail tsc if any field reverted to optional.

…REQUIRED (#9541)

Deliverable 3 of #9541, and the structural half of #9482.

#9482's behavioural fixes landed: the approval-accept path now threads authorLogin,
expectedBaseRef and moderationSettings. But it threads them by CONVENTION -- three
explanatory comments at the call site -- while the type still marked all three optional.
Nothing stopped the next caller omitting them again, which is precisely what #9482's own
deliverable asked for: "prefer a shared, typed decision-pass context constructed by both
paths over ad-hoc optional fields -- that structurally prevents the next omission."

All three are now required on AgentActionExecutionContext, following #9539's required
`decisionNowMs` precedent. `null` remains a valid value; what is no longer expressible is
OMITTING the field. The distinction matters because each absence disabled a protection
outright rather than degrading it:

  authorLogin        step 8c's cap-lock key degrades to `contributor-cap-lock:<repo>:`,
                     giving zero exclusion AND collapsing every accept-path merge in the
                     repo onto one shared empty-author key; and maybeEscalateModeration
                     early-returns, so enforcement closes recorded no violation and never
                     counted toward the warning/ban threshold.
  expectedBaseRef    #9055's base-retarget guard never runs, so a PR retargeted after
                     staging merges into a base the reviewed diff and CI never targeted.
                     A wrong-merge class.
  moderationSettings the repo's per-repo overrides silently fall back to global defaults.

IssueActionExecutionContext gets the same treatment. #9482 only audited the PR context,
but its twin carries two of the same fields with the same hazard -- fixing one type and
not the other is exactly the drift this deliverable exists to end.

WHAT THE TYPE CHANGE FOUND

Four more call sites in processors.ts omitting expectedBaseRef (and two also
moderationSettings), none of them audited by #9482. All four are close or update_branch
paths where null is genuinely correct -- a close has no base to protect against a
retarget -- so the fix is a stated `null` with the reason, not a behaviour change. That
they were invisible until the compiler demanded an answer is the argument for the type
guarantee over a convention.

Behaviour-preserving: the full suite passes 23,940 tests, with test fixtures updated only
to supply the fields real callers must now supply. Two tests that deliberately exercised
the absent-author degradation move from `undefined` to `null` -- the same case, spelled
the way the type now expresses it.
@loopover-orb

loopover-orb Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Caution

🛑 LoopOver review result - fixes required

Review updated: 2026-07-28 18:30:25 UTC

6 files · 1 AI reviewer · no blockers · CI failing · unstable

🛑 Suggested Action - Manual Review

Review summary
This is a well-scoped type-tightening refactor: it makes `expectedBaseRef`, `authorLogin`, and `moderationSettings` required (but nullable) on both `AgentActionExecutionContext` and `IssueActionExecutionContext`, forcing every call site to state an explicit choice instead of silently omitting the field. All call sites shown in the diff (`processors.ts`, `agent-approval-queue.ts`, executor/queue tests) are updated with `?? null` or explicit `null` values consistent with each path's semantics (e.g. update_branch/close paths correctly pass `expectedBaseRef: null` since there's no merge to protect). The change is coherent with the stated #9541/#9482 history and closes a real structural gap (optional fields silently degrading protections).

Nits — 5 non-blocking
  • The codecov/patch check failed at 60% vs 99% target — worth confirming the newly-required fields' null/non-null branches in `maybeEscalateModeration` and the moderation early-return path are exercised by tests, since this is exactly the kind of branch this refactor is meant to make visible.
  • test/unit/pr-command-prologue.test.ts's new describe block is a type-level invariant test with runtime assertions that don't really exercise any production code path — consider whether a compile-time-only check (e.g. a `// @​ts-expect-error` on omission) would state the intent more directly than runtime `expect().toBeNull()` on inline object literals.
  • Double check that `applyModerationEscalationForRule`'s and `maybeEscalateModeration`'s signatures (now `ModerationContextSettings | null | undefined`) are consistent with the new required context field — the diff shows the arg types loosened to include `null`, which is correct since `ctx.moderationSettings` can now legitimately be `null`.
  • Given codecov/patch failed, it'd help to see coverage specifically on the new `expectedBaseRef: null` skip-path in the review-nag/mention-throttle call sites in processors.ts, since these are newly-added lines this PR introduces.
  • PR author also opened the linked issue — Link an issue that was opened by a different contributor, or provide a rationale for why this self-authored issue represents genuine discovery work.

CI checks failing

  • codecov/patch — 60.00% of diff hit (target 99.00%)

Decision drivers

  • ✅ Code review — No blockers (1 reviewer)
  • ✅ Gate result — Passing (No configured blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #9541, #9482
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ❌ 8/20 High review scope from cached public metadata (2 linked issues).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 14 registered-repo PR(s), 13 merged, 300 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 14 PR(s), 300 issue(s).
Improvement ✅ Minor risk: clean · value: minor
Linked issue satisfaction

Addressed
The PR makes expectedBaseRef, authorLogin, and moderationSettings required (not optional) on both AgentActionExecutionContext and IssueActionExecutionContext, updates all call sites in processors.ts and agent-approval-queue.ts to explicitly pass null where absent, and adds tests confirming the type-level guarantee — precisely deliverable 3's ask for a required typed decision-pass context replacing

Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository is registered but has no active allocation in the current snapshot.
  • Public profile languages: not available
  • Official Gittensor activity: 14 PR(s), 300 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Start here: Treat this as maintainer-lane context rather than normal contributor-lane activity.
  • Then work through the remaining 3 steps in the Signals table above.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @loopover ask &lt;question&gt; answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat &lt;question&gt; answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

Full command reference: https://loopover.ai/docs/loopover-commands

🧪 Experimental — new and may change.

Decision record
  • action: hold · clause: success
  • config: 010bd9888657489e378bcf3a7393309e9211c443d0d069baa4a5973a1b2d1df7 · pack: oss-anti-slop · ci: failed
  • record: b686a505a2cc1499eb35589a122d8b16f5b8bac13ab86fbb41f130bb639b0067 (schema v5, head 364d745)

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.

  • Re-run LoopOver review

@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@JSONbored JSONbored self-assigned this Jul 28, 2026
@codecov

codecov Bot commented Jul 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 60.00000% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.03%. Comparing base (0e990a3) to head (364d745).

Files with missing lines Patch % Lines
src/queue/processors.ts 50.00% 0 Missing and 4 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #9582      +/-   ##
==========================================
- Coverage   89.84%   89.03%   -0.82%     
==========================================
  Files         875      875              
  Lines      110980   110990      +10     
  Branches    26402    26412      +10     
==========================================
- Hits        99706    98815     -891     
- Misses       9992    11155    +1163     
+ Partials     1282     1020     -262     
Flag Coverage Δ
backend 94.15% <60.00%> (-1.48%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/services/agent-action-executor.ts 96.78% <ø> (ø)
src/services/agent-approval-queue.ts 98.12% <100.00%> (+0.02%) ⬆️
src/queue/processors.ts 94.71% <50.00%> (-0.11%) ⬇️

... and 3 files with indirect coverage changes

@loopover-orb loopover-orb Bot added the manual-review Gittensor contributor context label Jul 28, 2026
@JSONbored
JSONbored merged commit 423f410 into main Jul 28, 2026
6 of 7 checks passed
@JSONbored
JSONbored deleted the refactor/required-decision-context-9541 branch July 28, 2026 18:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

manual-review Gittensor contributor context

Projects

None yet

Development

Successfully merging this pull request may close these issues.

maintainability: split processors.ts (16.2k lines, 437 touches) — the structural cause of this audit's drift and determinism gaps

1 participant