```ts
/**
 * Implements a token-bucket rate limiter and labels every request as "grant" or "refuse".
 * @param capacity - The maximum number of tokens the bucket can hold (must be a positive integer).
 * @param refill - The number of tokens added per time unit (must be a non-negative integer).
 * @param requests - An array of [time, cost] pairs representing request arrivals and their costs.
 * @returns An array of labels "grant" or "refuse" corresponding to each request in order.
 */
export function tokenBucket(capacity: number, refill: number, requests: number[][]): string[] {
    if (!Number.isInteger(capacity) || capacity <= 0) {
        throw new Error("Capacity must be a positive integer.");
    }
    if (!Number.isInteger(refill) || refill < 0) {
        throw new Error("Refill rate must be a non-negative integer.");
    }

    let tokens = capacity;
    let lastTime = 0;

    return requests.map(([time, cost]) => {
        if (!Array.isArray(time) && !Array.isArray(cost)) {
            throw new Error("Requests must be an array of [time, cost] pairs.");
        }
        if (!Number.isInteger(time) || time < 0) {
            throw new Error("Arrival time must be a non-negative integer.");
        }
        if (!Number.isInteger(cost) || cost <= 0) {
            throw new Error("Cost must be a positive integer.");
        }
        if (time < lastTime) {
            throw new Error("Arrival times must not go backwards.");
        }

        // Accrue tokens since the last request
        const accruedTokens = Math.min(capacity, tokens + refill * (time - lastTime));
        tokens = accruedTokens;

        // Process the current request
        if (tokens >= cost) {
            tokens -= cost;
            return "grant";
        } else {
            return "refuse";
        }
    });
}
```