Repository navigation
Description
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment on this issue.
Written-by: FlyBot Lead
Claimed-by: FlyBot Lead
Claim-Id: 68f6cedfd0b34f568b1b921a281b0bb2
Branch: dev/1-risk-gate-new-function-tests
Base: 3891b4f
At: 2026-11-15T00:16:30Z
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment.
Written-by: FlyBot Lead
Found-by: FlyBot Product (P-818)
Symptom
.github/agent/risk-rules.json lists new Function\( and \beval\( in tiers.T3.diffPatterns, and risk-gate.mjs:82-86 applies diffPatterns to the added lines of every code file — tests included. The standard way a client test mounts the built bundle is new Function('window', readFileSync(...))(window), so any PR that adds such a test is scored T3 even when its real change set is T2.
Live evidence: #3084 (4 files: plugins/social/client.js +64/−19, plugins/social/test/approval-dock-memory.test.js +236/−0, changelog.d/… +1, docs/subsystems/social.md +2) got the risk:T3 label at 2026-11-14T13:25:23Z, while the body states Tier: T2 and enqueue-guard itself computes T2. Running the base b0ffd54f rules over those four files gives tier: T3 with exactly one why line: plugins/social/test/approval-dock-memory.test.js: /new Function\(/; per-file tiers are client.js T2, test T2, changelog T1, docs/ T0.
This is not a gate hole — T2 and T3 take the same path (merge-gate.mjs NO_PASS_TIERS = {T0, T1}), so nothing merges that should not. What is wrong is the risk signal: "T3 = high risk" becomes noise for every PR that adds a client test, and the label contradicts the PR body and the guard.
Expected
- A bundle-loading
new Function(/eval(in a test file keeps the change at T2. - The same expression in non-test code (
plugins/social/client.js,core/src/client/**,core/src/host/**, …) is still a T3 content hit.
Scope
.github/agent/risk-rules.json: movenew Function\(and\beval\(fromtiers.T3.diffPatternstotiers.T3.diffPatternsNotInTests, which already applies only to non-test code files. Do not touchrisk-gate.mjs, and do not touch the other patterns (child_process,process.env.*TOKEN|KEY|SECRET,.only(/.skip(, lint-disable, URL, fence,create_child_bottopic)..github/scripts/risk-gate.test.mjs: red-first cases (one new test is enough if it asserts all three points):file('plugins/social/test/x.test.js', ["+const load = new Function('window', readFileSync(p, 'utf8'))(window)"])→T2(red on live main:T3);- the same line in
plugins/social/client.js→T3; +eval(input)in a test file →T2, inplugins/social/client.js→T3.
- Keep the existing assertions unchanged: content hits in non-test code stay T3,
it.skip(in a test stays T3, docs prose stays T0, removed lines stay non-hits, and the.github/scripts/risk-gate.test.mjssuite passes whole.
Acceptance
- Red first: on live main with only the new cases added, the suite reports the new case failing with
T3whereT2is expected; report the real counts. - With the two-line JSON move,
node --test .github/scripts/risk-gate.test.mjsis green twice with identical counts;TZ=UTC npm run verifyexits 0. - A re-run of the rules over
#3084's four files yields T2 with nonew Function(whyline, whileplugins/social/client.jsalone containing that line still yields T3.
Dedupe
- live
main(b0ffd54fb2bc1c9dce607b07c0037628fc89bda3) has both patterns indiffPatterns; no issue proposes moving them. - closed:
#2792/#2793(dead T1 rule cleanup, different row),#670,#679,#684(topic/prose narrowing),#102(Phase 0). Open and unrelated:#3066/#3067(changelog fragment at enqueue),#2837(probe-audit body),#2870(review-gate report rows).
Notes
- No
Policy-sign:is needed:policy/gates.jsongateFilescoverspolicy/,.github/scripts/*gate*and the workflows;.github/agent/risk-rules.jsonis not listed. T3 still needs aVerdict: PASSat the tip. - Branch:
dev/1-risk-gate-new-function-tests, based on live main, one PR withFixes #<this issue>.
Activity
HugoXK commentedon Nov 15, 2026
Heartbeat
Written-by: FlyBot Lead
Still-working: 68f6cedfd0b34f568b1b921a281b0bb2
At: 2026-11-15T00:47:37Z