test(plan-eng batching): count saved decisions whose label drops the (recommended) marker or whose report is titled 'Eng Review Report — <plan>'

This commit is contained in:
garrytan committed 2026-10-01 17:08:34 +00:00
1 parent a065b02372
commit b3a26090e6
3 files changed
+107 -3

No files matched your search

+33
View File
@@ -192,3 +192,36 @@ describe('batching replay of a 2.1.284 rerun (bullet target, unnamed plan)', ()
expect(count(plan)).toEqual([]);
});
});
describe('saved ledger from run 36798539821: report title and (recommended) marker', () => {
const reportTitleCapture: { calls: NativePlanQuestionCall[]; plans: string[] } = JSON.parse(
fs.readFileSync(path.join(import.meta.dir, 'fixtures/eng-batching-report-title-36798539821.json'), 'utf8'));
const [d1, d3] = reportTitleCapture.calls;
const [d1Plan, d3Plan] = reportTitleCapture.plans;
const countReportTitle = (call: NativePlanQuestionCall, plan: string, prior: NativePlanQuestionCall[] = []) =>
createEngBatchingIssueCounter(() => plan, engSetupAUQ).isReviewAUQ(nativePlanCallFingerprint(structuredClone(call), 0, true), prior);
test('a saved option label without the native (recommended) marker still owns the decision', () => {
expect(d1!.questions[0]!.options[0]!.label).toBe('Library hooks + custom backoff (recommended)');
expect(d1Plan).toContain('\nA) Library hooks + custom backoff\n');
expect(countReportTitle(d1!, d1Plan!)).toBe(true);
});
test('an unsourced brief inherits PLAN.md from an "Eng Review Report — <plan>" title', () => {
expect(d3Plan!.split('\n')[0]).toBe('# Eng Review Report — Add background job retry framework');
expect(d3!.questions[0]!.question.split('\n')[1]).not.toMatch(/\.md\b/);
expect(countReportTitle(d3!, d3Plan!, [d1!])).toBe(true);
});
test('rejects a saved label that changes the choice, not just the marker', () => {
expect(countReportTitle(d1!, d1Plan!.replace('\nA) Library hooks + custom backoff\n', '\nA) Library hooks without custom backoff\n'))).toBe(false);
});
test('rejects a report title that names a different plan', () => {
expect(countReportTitle(d3!, d3Plan!.replace('# Eng Review Report — Add background job retry framework', '# Eng Review Report — Rewrite the billing service'), [d1!])).toBe(false);
});
test('rejects a report title with an unrelated prefix', () => {
expect(countReportTitle(d3!, d3Plan!.replace('# Eng Review Report — ', '# Copied Review Notes — '), [d1!])).toBe(false);
});
});
@@ -0,0 +1,69 @@
{
"source": "Periodic Evals run 36798539821, eval-slices (1), /plan-eng-review multi-finding batching; native calls D1 and D3 with the saved report as it stood 3s after each answer",
"calls": [
{
"sessionId": "b3ebef1e-8b0f-4613-ab80-392f4e780930",
"toolUseId": "toolu_01SKGoBCLaoNJhSFiGFmqMYV",
"questions": [
{
"question": "D1 — Retry engine: library hooks or hand-rolled?\nProject/branch/task: main — plan \"Add background job retry framework\", reviewing PLAN.md Architecture section.\nELI10: Your job library already knows how to retry a failed job later; the plan wants to rebuild that part by hand inside every worker, just so the wait-time curve is ours. Almost every job library lets you plug in your own curve through its retry hook, so you get the curve you want without also owning scheduling, attempt counting, persistence across process restarts, and dead-lettering. The stakes are a second retry system nobody else on the team knows, living in five copies.\nStakes if we pick wrong: a hand-rolled scheduler loses in-flight retries on deploy or crash, drifts from the library's attempt bookkeeping, and every retry bug is ours to find at 3am. Users see jobs that silently never run again.\nRecommendation: A because the plan admits the library already has the shape (PLAN.md:8); supplying a backoff function keeps full control of the curve at a fraction of the surface area. [Layer 1: reuse the installed dependency.]\nCompleteness: A=9/10, B=6/10, C=n/a (investigation, differs in kind)\nPros / cons:\nA) Library hooks + custom backoff (recommended) (human: ~1 day / CC: ~20 min)\n ✅ Full control of the delay curve via one backoff function; the library still persists attempts and survives restarts\n ✅ Dead-letter, max-attempts and retry visibility come for free from the library's existing dashboard and tooling\n ❌ If the library's hook cannot express the curve (verify first), you are back to B for that one worker\nB) Custom inline scheduler (human: ~3-4 days / CC: ~1 hr, plus ongoing maintenance)\n ✅ Zero dependence on the library's retry semantics; curve and scheduling are entirely ours\n ✅ Works even if the library's hook turns out to be too rigid\n ❌ Re-implements persistence, attempt tracking and dead-lettering; in-flight retries die with the process unless you also build durability\nC) Investigate hook API first (CC: ≤ 30 min)\n ✅ Replaces an assumption with a verified fact before committing either way\n ✅ Cheap; the answer feeds directly into A or B\n ❌ Decides nothing today; the mechanism stays pending and blocks the Code Quality question that depends on it\nNet: you are trading a few lines of backoff function (A) against owning a second retry system (B); C buys certainty for half an hour.",
"header": "Retry engine",
"multiSelect": false,
"options": [
{
"label": "Library hooks + custom backoff (recommended)",
"description": "Use the existing job library's retry hook and supply one custom backoff function that returns the delay for attempt N. The library keeps scheduling, attempt persistence, max-attempts and dead-letter. Full control of the curve. Human: ~1 day / CC: ~20 min. Risk: low; verify the hook accepts a function before coding."
},
{
"label": "Custom inline scheduler",
"description": "Hand-roll the exponential-backoff scheduler inside each worker as PLAN.md:7-9 proposes. We own scheduling, attempt counting, persistence across restarts and dead-lettering. Human: ~3-4 days / CC: ~1 hr plus ongoing maintenance. Risk: medium-high; in-flight retries are lost on crash or deploy unless durability is also built."
},
{
"label": "Investigate hook API first",
"description": "Bounded investigation only: read the library's retry/backoff hook API and report whether a custom curve function is supported. CC: ≤ 30 min. Approves no implementation; the retry mechanism stays pending and R2-R5 stay pending."
}
]
}
],
"answered": true,
"failed": false,
"answers": {
"D1 — Retry engine: library hooks or hand-rolled?\nProject/branch/task: main — plan \"Add background job retry framework\", reviewing PLAN.md Architecture section.\nELI10: Your job library already knows how to retry a failed job later; the plan wants to rebuild that part by hand inside every worker, just so the wait-time curve is ours. Almost every job library lets you plug in your own curve through its retry hook, so you get the curve you want without also owning scheduling, attempt counting, persistence across process restarts, and dead-lettering. The stakes are a second retry system nobody else on the team knows, living in five copies.\nStakes if we pick wrong: a hand-rolled scheduler loses in-flight retries on deploy or crash, drifts from the library's attempt bookkeeping, and every retry bug is ours to find at 3am. Users see jobs that silently never run again.\nRecommendation: A because the plan admits the library already has the shape (PLAN.md:8); supplying a backoff function keeps full control of the curve at a fraction of the surface area. [Layer 1: reuse the installed dependency.]\nCompleteness: A=9/10, B=6/10, C=n/a (investigation, differs in kind)\nPros / cons:\nA) Library hooks + custom backoff (recommended) (human: ~1 day / CC: ~20 min)\n ✅ Full control of the delay curve via one backoff function; the library still persists attempts and survives restarts\n ✅ Dead-letter, max-attempts and retry visibility come for free from the library's existing dashboard and tooling\n ❌ If the library's hook cannot express the curve (verify first), you are back to B for that one worker\nB) Custom inline scheduler (human: ~3-4 days / CC: ~1 hr, plus ongoing maintenance)\n ✅ Zero dependence on the library's retry semantics; curve and scheduling are entirely ours\n ✅ Works even if the library's hook turns out to be too rigid\n ❌ Re-implements persistence, attempt tracking and dead-lettering; in-flight retries die with the process unless you also build durability\nC) Investigate hook API first (CC: ≤ 30 min)\n ✅ Replaces an assumption with a verified fact before committing either way\n ✅ Cheap; the answer feeds directly into A or B\n ❌ Decides nothing today; the mechanism stays pending and blocks the Code Quality question that depends on it\nNet: you are trading a few lines of backoff function (A) against owning a second retry system (B); C buys certainty for half an hour.": "Library hooks + custom backoff (recommended)"
},
"unansweredQuestionIndices": [],
"answeredAt": "2026-10-01T00:59:59.441Z"
},
{
"sessionId": "b3ebef1e-8b0f-4613-ab80-392f4e780930",
"toolUseId": "toolu_012FpcaAT9TcStMcPRVJno8y",
"questions": [
{
"question": "D3 — Backoff jitter: randomize retry delays?\nProject/branch/task: main — plan \"Add background job retry framework\", custom backoff function approved in D1.\nELI10: When a downstream service goes down, every job that hit it fails at the same moment. Without jitter they all come back at the same moment too, hammering the service exactly when it is trying to recover, and failing together again. Jitter spreads retries randomly across the window so the herd becomes a trickle. The plan says \"full control over the curve\" but never mentions it.\nStakes if we pick wrong: a recovering dependency gets knocked over by our own synchronized retry wave; the outage lasts longer and the fix looks like \"the retries made it worse\".\nRecommendation: A because full jitter is one line inside the backoff function and it is the standard remedy for synchronized retry storms.\nCompleteness: A=9/10, B=6/10\nPros / cons:\nA) Full jitter (recommended) (human: ~1 hr / CC: ~3 min)\n ✅ Five workers retrying the same dead dependency spread their load across the window instead of in lockstep\n ✅ One line in the backoff function; the library still owns scheduling so nothing else changes\n ❌ Retry timing becomes non-deterministic, so tests must seed or inject the random source\nB) No jitter (human: ~0 / CC: ~0)\n ✅ Deterministic delays are trivial to assert in tests and to reason about in logs\n ✅ Nothing to build\n ❌ All jobs that failed together retry together; thundering herd against a recovering dependency\nNet: one injectable random call versus a synchronized retry wave during every downstream outage.",
"header": "Jitter",
"multiSelect": false,
"options": [
{
"label": "Full jitter (recommended)",
"description": "Inside the custom backoff function, return random(0, exponentialDelay(attempt)). Inject the random source so tests can seed it. Human: ~1 hr / CC: ~3 min. Risk: low."
},
{
"label": "No jitter",
"description": "Return exponentialDelay(attempt) exactly. Deterministic. Nothing to build. Risk: synchronized retries against a recovering dependency."
}
]
}
],
"answered": true,
"failed": false,
"answers": {
"D3 — Backoff jitter: randomize retry delays?\nProject/branch/task: main — plan \"Add background job retry framework\", custom backoff function approved in D1.\nELI10: When a downstream service goes down, every job that hit it fails at the same moment. Without jitter they all come back at the same moment too, hammering the service exactly when it is trying to recover, and failing together again. Jitter spreads retries randomly across the window so the herd becomes a trickle. The plan says \"full control over the curve\" but never mentions it.\nStakes if we pick wrong: a recovering dependency gets knocked over by our own synchronized retry wave; the outage lasts longer and the fix looks like \"the retries made it worse\".\nRecommendation: A because full jitter is one line inside the backoff function and it is the standard remedy for synchronized retry storms.\nCompleteness: A=9/10, B=6/10\nPros / cons:\nA) Full jitter (recommended) (human: ~1 hr / CC: ~3 min)\n ✅ Five workers retrying the same dead dependency spread their load across the window instead of in lockstep\n ✅ One line in the backoff function; the library still owns scheduling so nothing else changes\n ❌ Retry timing becomes non-deterministic, so tests must seed or inject the random source\nB) No jitter (human: ~0 / CC: ~0)\n ✅ Deterministic delays are trivial to assert in tests and to reason about in logs\n ✅ Nothing to build\n ❌ All jobs that failed together retry together; thundering herd against a recovering dependency\nNet: one injectable random call versus a synchronized retry wave during every downstream outage.": "Full jitter (recommended)"
},
"unansweredQuestionIndices": [],
"answeredAt": "2026-10-01T01:02:45.480Z"
}
],
"plans": [
"# Eng Review Report — Add background job retry framework\n\nReview target (fixed): `PLAN.md` in `/home/runner/.cache/gstack-paid-shard-i9xSoz/tmp/gstack-plan-count-QVv99m` (branch `main`, commit 9c0d5e5)\nReviewer: /plan-eng-review (native Claude), session 636-1790816247-91f1d704\nReport file: this file (user-requested destination)\n\n## Original plan (unchanged copy)\n\n# Plan: Add background job retry framework\n\n## Architecture\nWe'll roll a custom exponential-backoff scheduler inline in each worker\nrather than use the existing job library's built-in retry hooks. Same\nshape as the library version, but we want full control over the curve.\n\n## Code quality\nThe retry envelope (compute delay, log attempt, dispatch) is duplicated\nacross 5 worker files with copy-pasted bodies. We will leave the\nduplication for now and refactor \"later.\"\n\n## Tests\nThe existing `processWebhookJob()` flow gets rewritten as part of this\nchange. No regression test for the prior at-most-once delivery guarantee\nis planned.\n\n## Performance\nOn every retry we re-fetch the full job payload from the database, then\niterate the payload to recompute the dependency graph. Could cache the\ngraph on the first attempt; not planned.\n\n## Decision ledger\n\n### R1: Retry engine — library retry hooks with a custom backoff function vs a hand-rolled inline scheduler\nFinding: SC1, P1, confidence 8/10, PLAN.md:7-9, reviewer: Claude (native /plan-eng-review)\nPlan baseline: original proposal — \"roll a custom exponential-backoff scheduler inline in each worker rather than use the existing job library's built-in retry hooks\" (PLAN.md:7-9). Nothing approved yet.\nRuntime evidence: unknown. The repo contains no worker code, no job library dependency and no tests (git ls-files: CLAUDE.md, PLAN.md only). Library identity and its hook API are unverified. The plan's own line \"Same shape as the library version\" (PLAN.md:8) is the only evidence that the library already provides the shape.\nComparison grid:\n\n| Choice | Current | A) Library hooks + custom backoff | B) Custom inline scheduler | C) Investigate hook API first |\n|---|---|---|---|---|\n| R1 retry mechanism | custom inline scheduler in each worker (proposed, unapproved) | library retry hook supplying one custom backoff function (curve fully ours); library owns scheduling, attempt persistence, dead-letter | hand-rolled scheduler inline per worker as planned; we own scheduling, persistence, attempt tracking, dead-letter | bounded: read the library's retry/backoff hook API (CC ≤ 30 min), report whether a custom curve is supported; mechanism stays pending |\n| R2 shared retry envelope helper | duplicated in 5 worker files (proposed) | pending | pending | pending |\n| R3 webhook delivery regression contract | none planned (PLAN.md:17-19) | pending | pending | pending |\n| R4 payload / dependency-graph caching on retry | not planned (PLAN.md:22-24) | pending | pending | pending |\n| R5 jitter, max attempts, dead-letter policy | unspecified | pending | pending | pending |\n\nQuestion D1:\nD1 — Retry engine: library hooks or hand-rolled?\nProject/branch/task: main — plan \"Add background job retry framework\", reviewing PLAN.md Architecture section.\nELI10: Your job library already knows how to retry a failed job later; the plan wants to rebuild that part by hand inside every worker, just so the wait-time curve is ours. Almost every job library lets you plug in your own curve through its retry hook, so you get the curve you want without also owning scheduling, attempt counting, persistence across process restarts, and dead-lettering. The stakes are a second retry system nobody else on the team knows, living in five copies.\nStakes if we pick wrong: a hand-rolled scheduler loses in-flight retries on deploy or crash, drifts from the library's attempt bookkeeping, and every retry bug is ours to find at 3am. Users see jobs that silently never run again.\nRecommendation: A because the plan admits the library already has the shape (PLAN.md:8); supplying a backoff function keeps full control of the curve at a fraction of the surface area. [Layer 1: reuse the installed dependency.]\nCompleteness: A=9/10, B=6/10, C=n/a (investigation, differs in kind)\nPros / cons:\nA) Library hooks + custom backoff (recommended) (human: ~1 day / CC: ~20 min)\n ✅ Full control of the delay curve via one backoff function; the library still persists attempts and survives restarts\n ✅ Dead-letter, max-attempts and retry visibility come for free from the library's existing dashboard and tooling\n ❌ If the library's hook cannot express the curve (verify first), you are back to B for that one worker\nB) Custom inline scheduler (human: ~3-4 days / CC: ~1 hr, plus ongoing maintenance)\n ✅ Zero dependence on the library's retry semantics; curve and scheduling are entirely ours\n ✅ Works even if the library's hook turns out to be too rigid\n ❌ Re-implements persistence, attempt tracking aLine truncated
"# Eng Review Report — Add background job retry framework\n\nReview target (fixed): `PLAN.md` in `/home/runner/.cache/gstack-paid-shard-i9xSoz/tmp/gstack-plan-count-QVv99m` (branch `main`, commit 9c0d5e5)\nReviewer: /plan-eng-review (native Claude), session 636-1790816247-91f1d704\nReport file: this file (user-requested destination)\n\n## Original plan (unchanged copy)\n\n# Plan: Add background job retry framework\n\n## Architecture\nWe'll roll a custom exponential-backoff scheduler inline in each worker\nrather than use the existing job library's built-in retry hooks. Same\nshape as the library version, but we want full control over the curve.\n\n## Code quality\nThe retry envelope (compute delay, log attempt, dispatch) is duplicated\nacross 5 worker files with copy-pasted bodies. We will leave the\nduplication for now and refactor \"later.\"\n\n## Tests\nThe existing `processWebhookJob()` flow gets rewritten as part of this\nchange. No regression test for the prior at-most-once delivery guarantee\nis planned.\n\n## Performance\nOn every retry we re-fetch the full job payload from the database, then\niterate the payload to recompute the dependency graph. Could cache the\ngraph on the first attempt; not planned.\n\n## Working plan (current, amended only by approved decisions)\n\n### Architecture (R1 approved, D1 → A)\nUse the existing job library's retry hook. Supply one custom backoff function\n`backoff(attempt) -> delayMs` that owns the curve. The library keeps scheduling,\nattempt persistence, max-attempts and dead-letter. Verify the hook accepts a\nfunction before coding. No hand-rolled inline scheduler.\n\n### Code quality (pending R2)\nAs originally proposed: envelope duplicated across 5 worker files.\n\n### Tests (pending R3)\nAs originally proposed: `processWebhookJob()` rewritten, no regression test planned.\n\n### Performance (pending R4)\nAs originally proposed: full payload re-fetch and graph recompute on every retry.\n\n## Scope Challenge record\nComplexity gate: 5-6 proposed files, 0 new classes → B skipped. Findings: SC1 (P1, 8/10, PLAN.md:7-9) resolved by D1 → A.\nScope Challenge result: scope accepted as-is (mechanism changed, feature set unchanged; not a scope reduction).\n\n## Decision ledger\n\n### R1: Retry engine — library retry hooks with a custom backoff function vs a hand-rolled inline scheduler\nFinding: SC1, P1, confidence 8/10, PLAN.md:7-9, reviewer: Claude (native /plan-eng-review)\nPlan baseline: original proposal — \"roll a custom exponential-backoff scheduler inline in each worker rather than use the existing job library's built-in retry hooks\" (PLAN.md:7-9). Nothing approved yet.\nRuntime evidence: unknown. The repo contains no worker code, no job library dependency and no tests (git ls-files: CLAUDE.md, PLAN.md only). Library identity and its hook API are unverified. The plan's own line \"Same shape as the library version\" (PLAN.md:8) is the only evidence that the library already provides the shape.\nComparison grid:\n\n| Choice | Current | A) Library hooks + custom backoff | B) Custom inline scheduler | C) Investigate hook API first |\n|---|---|---|---|---|\n| R1 retry mechanism | custom inline scheduler in each worker (proposed, unapproved) | library retry hook supplying one custom backoff function (curve fully ours); library owns scheduling, attempt persistence, dead-letter | hand-rolled scheduler inline per worker as planned; we own scheduling, persistence, attempt tracking, dead-letter | bounded: read the library's retry/backoff hook API (CC ≤ 30 min), report whether a custom curve is supported; mechanism stays pending |\n| R2 shared retry envelope helper | duplicated in 5 worker files (proposed) | pending | pending | pending |\n| R3 webhook delivery regression contract | none planned (PLAN.md:17-19) | pending | pending | pending |\n| R4 payload / dependency-graph caching on retry | not planned (PLAN.md:22-24) | pending | pending | pending |\n| R5 jitter, max attempts, dead-letter policy | unspecified | pending | pending | pending |\n\nQuestion D1:\nD1 — Retry engine: library hooks or hand-rolled?\nProject/branch/task: main — plan \"Add background job retry framework\", reviewing PLAN.md Architecture section.\nELI10: Your job library already knows how to retry a failed job later; the plan wants to rebuild that part by hand inside every worker, just so the wait-time curve is ours. Almost every job library lets you plug in your own curve through its retry hook, so you get the curve you want without also owning scheduling, attempt counting, persistence across process restarts, and dead-lettering. The stakes are a second retry system nobody else on the team knows, living in five copies.\nStakes if we pick wrong: a hand-rolled scheduler loses in-flight retries on deploy or crash, drifts from the library's attempt bookkeeping, and every retry bug is ours to find at 3am. Users see jobs that silently never run again.\nRecommendation: A because the plan aLine truncated
]
}
+5 -3
View File
@@ -163,7 +163,7 @@ function recordedBatchingIssue(call: NativePlanQuestionCall, savedPlan: string):
const rawSourceNames = [...(lines[1] ?? '').matchAll(/\b[\w./-]+\.md\b/g)];
const directSource = sourceNames.length > 0 && sourceNames.every(name => name === 'PLAN.md') &&
new Set([...metadata.matchAll(/\bPLAN\.md:([1-9]\d*(?:[-–][1-9]\d*)?)\b/g)].map(match => match[1])).size <= 1;
const targetName = (s: string) => clean(s).replace(/^Eng(?:ineering)? review\s*[:—–-]\s*/i, '')
const targetName = (s: string) => clean(s).replace(/^Eng(?:ineering)? review(?: report)?\s*[:—–-]\s*/i, '')
.replace(/^Plan\s*[:—–-]\s*/i, '').toLowerCase();
const named = [...(lines[1] ?? '').matchAll(/"(Plan:\s*[^"\n]+)"|“(Plan:\s*[^”\n]+)”|\b[Pp]lan\s+"([^"\n]+)"|\b[Pp]lan\s+“([^”\n]+)”/g)]
.map(match => targetName(match[1] ?? match[2] ?? match[3] ?? match[4]!));
@@ -186,7 +186,7 @@ function recordedBatchingIssue(call: NativePlanQuestionCall, savedPlan: string):
const namedSource = !rawSourceNames.length && named.length <= 1 && titles.length >= 1 &&
titles[0]!.type === 'heading' && currentHeading(tokens.indexOf(titles[0]!)) &&
targetFiles.length === 1 && targetFiles[0]!.split('/').at(-1) === 'PLAN.md' &&
(named.length === 0 || /^Eng(?:ineering)? review\s*[:—–-]\s*\S/i.test(clean(titles[0]!.text)) &&
(named.length === 0 || /^Eng(?:ineering)? review(?: report)?\s*[:—–-]\s*\S/i.test(clean(titles[0]!.text)) &&
titles.every(title => title.type === 'heading' && targetName(title.text) === named[0]));
if (!directSource && !namedSource) return;
const withdrawn = (value: string, owners: string) => new RegExp(
@@ -324,6 +324,8 @@ function recordedBatchingIssue(call: NativePlanQuestionCall, savedPlan: string):
const explicitSelectors = nativeOptions.flatMap(option => option.selector ? [option.selector] : []);
if (new Set(explicitSelectors).size !== explicitSelectors.length ||
nativeOptions.some(option => option.selector && !selectors.includes(option.selector) || !option.label || /^[A-D][).:]\s+/.test(option.label))) continue;
// The preamble's `(recommended)` suffix marks the recommendation; it is not part of the choice.
const unmarked = (label: string) => clean(label).replace(/\s*\(recommended\)$/i, '');
const readOptions = (lines: string[]) => {
const records: Array<{ selector: string; label: string; description: string[] }> = [];
for (const line of lines) {
@@ -335,7 +337,7 @@ function recordedBatchingIssue(call: NativePlanQuestionCall, savedPlan: string):
if (records.length !== nativeOptions.length || new Set(records.map(record => record.selector)).size !== records.length ||
records.some(record => !selectors.includes(record.selector))) return undefined;
const matches = records.map(record => nativeOptions.flatMap((native, at) =>
(!native.selector || native.selector === record.selector) && clean(record.label) === native.label &&
(!native.selector || native.selector === record.selector) && unmarked(record.label) === unmarked(native.label) &&
clean(record.description.join('\n')) === clean(native.description) ? [at] : []));
return matches.every(match => match.length === 1) && new Set(matches.flat()).size === records.length ? records : undefined;
};