Canonset
← Samples

Verified coding tasks

Tasks that prove their own tests

Each task is what a coding agent would receive: a problem statement and starting code, plus hidden tests and a reference solution. Our sandbox ran every one: the tests fail on the starting code, pass twice on the reference, and have no network access.

  • 12 tasks
  • Python 3.12, TypeScript, JavaScript
  • 33 fail→pass tests
  • Bug fixes, features, two security fixes

Add leading calls and cancel to debounce

code-08 · what the agent sees is the problem statement and the starting code

mediumTypeScript · Node.js 24 · node:test
Problem statement

debounce.ts powers search-as-you-type. Product wants two changes, and neither works today: 1. With { leading: true } the first call in a burst runs immediately; later calls in the same burst still produce one trailing call with the latest arguments (unless { trailing: false }). 2. The returned function has cancel(), which drops any pending call. A burst ends when wait milliseconds pass without a call. Keep the default behavior: trailing only.

Starting code
debounce.ts
export function debounce<A extends unknown[]>(
  fn: (...args: A) => void,
  wait: number,
  _options: { leading?: boolean; trailing?: boolean } = {},
) {
  let timer: ReturnType<typeof setTimeout> | undefined;
  return (...args: A) => {
    clearTimeout(timer);
    timer = setTimeout(() => fn(...args), wait);
  };
}
Reference solution
debounce.ts
export function debounce<A extends unknown[]>(
  fn: (...args: A) => void,
  wait: number,
  { leading = false, trailing = true }: { leading?: boolean; trailing?: boolean } = {},
) {
  let timer: ReturnType<typeof setTimeout> | undefined;
  let pending: A | undefined;
  const debounced = (...args: A) => {
    if (timer === undefined && leading) {
      fn(...args);
      pending = undefined;
    } else {
      pending = args;
    }
    clearTimeout(timer);
    timer = setTimeout(() => {
      timer = undefined;
      if (trailing && pending) fn(...pending);
      pending = undefined;
    }, wait);
  };
  debounced.cancel = () => {
    clearTimeout(timer);
    timer = undefined;
    pending = undefined;
  };
  return debounced;
}
Tests (hidden from the agent)
debounce.test.ts
import assert from "node:assert/strict";
import { afterEach, beforeEach, mock, test } from "node:test";
import { debounce } from "./debounce.ts";

beforeEach(() => mock.timers.enable({ apis: ["setTimeout"] }));
afterEach(() => mock.timers.reset());

test("calls once with the latest arguments after the wait", () => {
  const calls: number[] = [];
  const d = debounce((n: number) => calls.push(n), 100);
  d(1);
  d(2);
  d(3);
  mock.timers.tick(99);
  assert.deepEqual(calls, []);
  mock.timers.tick(1);
  assert.deepEqual(calls, [3]);
});

test("leading runs the first call now and the latest call at the end", () => {
  const calls: number[] = [];
  const d = debounce((n: number) => calls.push(n), 100, { leading: true });
  d(1);
  assert.deepEqual(calls, [1]);
  d(2);
  d(3);
  mock.timers.tick(100);
  assert.deepEqual(calls, [1, 3]);
});

test("leading without trailing runs once per burst", () => {
  const calls: number[] = [];
  const d = debounce((n: number) => calls.push(n), 100, { leading: true, trailing: false });
  d(1);
  d(2);
  mock.timers.tick(100);
  d(3);
  assert.deepEqual(calls, [1, 3]);
});

test("cancel drops the pending call", () => {
  const calls: number[] = [];
  const d = debounce((n: number) => calls.push(n), 100);
  d(1);
  d.cancel();
  mock.timers.tick(200);
  assert.deepEqual(calls, []);
});
Notes

node:test mock timers make the tests instant and deterministic.

Sandbox run

Recorded by pnpm samples:verify. Our tests fail the build if this stops matching the task.

Checks passed4 tests pass on the reference solution; 3 of them fail on the starting code.
TestStarting codeReferenceSecond run
debounce.test.ts::calls once with the latest arguments after the wait
passpasspasspass → pass
debounce.test.ts::leading runs the first call now and the latest call at the end
Expected values to be strictly deep-equal: + actual - expected + [] - [ - 1 - ]
failpasspassfail → pass
debounce.test.ts::leading without trailing runs once per burst
Expected values to be strictly deep-equal: + actual - expected [ + 2 - 1, - 3 ]
failpasspassfail → pass
debounce.test.ts::cancel drops the pending call
d.cancel is not a function
failpasspassfail → pass

TypeScript · Node.js 24 · node:test · canonset-sandbox-node:1 · 0.9 s · checked 2026-09-29 23:30 UTC

Output: Starting code (exit 1, 0.2 s)
✔ calls once with the latest arguments after the wait (2.345199ms)
✖ leading runs the first call now and the latest call at the end (1.516396ms)
✖ leading without trailing runs once per burst (0.623787ms)
✖ cancel drops the pending call (0.543414ms)
ℹ tests 4
ℹ suites 0
ℹ pass 1
ℹ fail 3
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 125.533351

✖ failing tests:

test at debounce.test.ts:20:1
✖ leading runs the first call now and the latest call at the end (1.516396ms)
  AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
  + actual - expected
  
  + []
  - [
  -   1
  - ]
  
      at TestContext.<anonymous> (file:///work/0-starter/debounce.test.ts:24:10)
      at Test.runInAsyncScope (node:async_hooks:227:14)
      at Test.run (node:internal/test_runner/test:1402:25)
      at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
    generatedMessage: true,
    code: 'ERR_ASSERTION',
    actual: [],
    expected: [ 1 ],
    operator: 'deepStrictEqual',
    diff: 'simple'
  }

test at debounce.test.ts:31:1
✖ leading without trailing runs once per burst (0.623787ms)
  AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
  + actual - expected
  
    [
  +   2
  -   1,
  -   3
    ]
  
      at TestContext.<anonymous> (file:///work/0-starter/debounce.test.ts:38:10)
      at Test.runInAsyncScope (node:async_hooks:227:14)
      at Test.run (node:internal/test_runner/test:1402:25)
      at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
    generatedMessage: true,
    code: 'ERR_ASSERTION',
    actual: [ 2 ],
    expected: [ 1, 3 ],
    operator: 'deepStrictEqual',
    diff: 'simple'
  }

test at debounce.test.ts:41:1
✖ cancel drops the pending call (0.543414ms)
  TypeError: d.cancel is not a function
      at TestContext.<anonymous> (file:///work/0-starter/debounce.test.ts:45:5)
      at Test.runInAsyncScope (node:async_hooks:227:14)
      at Test.run (node:internal/test_runner/test:1402:25)
      at async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
Output: Reference solution (exit 0, 0.2 s)
✔ calls once with the latest arguments after the wait (2.401213ms)
✔ leading runs the first call now and the latest call at the end (0.505366ms)
✔ leading without trailing runs once per burst (0.55992ms)
✔ cancel drops the pending call (0.662648ms)
ℹ tests 4
ℹ suites 0
ℹ pass 4
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 162.379412
Output: Reference, second run (exit 0, 0.2 s)
✔ calls once with the latest arguments after the wait (2.36765ms)
✔ leading runs the first call now and the latest call at the end (0.569899ms)
✔ leading without trailing runs once per burst (0.660209ms)
✔ cancel drops the pending call (1.746941ms)
ℹ tests 4
ℹ suites 0
ℹ pass 4
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 159.101999