@affectively/trace-lint
v5.0.0
Published
Extensible linting framework for Chrome/DevTools trace files with loop detection rules.
Maintainers
Readme
@affectively/trace-lint
Extensible linting framework for Chrome/DevTools trace files (.json and .json.gz).
It is designed for repeated runtime diagnostics and CI gating with a three-layer governance model:
constraint: non-negotiable failures (system truths).boundary: team-held discipline and runtime guardrails.expectation: directional pressure and optimization goals.
Installation
npm install @affectively/trace-lint
# or
bun add @affectively/trace-lintCLI Usage
trace-lint ./Trace-20260226T221208.json.gzLint the newest trace in ~/Downloads automatically:
trace-lint --latestLint the newest trace from a specific directory:
trace-lint --latest --trace-dir ~/DownloadsCapture a new trace from a URL for a fixed window, then lint it:
trace-lint --capture-url https://example.com --capture-seconds 10Capture to a specific folder as plain .json (no gzip):
trace-lint --capture-url https://example.com --capture-seconds 8 --capture-dir ~/Downloads --capture-jsonFilter to one rule and fail CI on warnings:
trace-lint ./trace.json.gz \
--rule repeated-async-task-loop \
--fail-on warnJSON output:
trace-lint ./trace.json.gz --json > trace-lint-report.jsonAgent-mitigation JSON output (includes objective/actions/verification per finding):
trace-lint ./trace.json.gz --json --detail-mode agent > trace-lint-agent-report.jsonForensics output for deeper automation/debugging:
trace-lint ./trace.json.gz --json --detail-mode forensics > trace-lint-forensics.jsonRun through the repo script:
bun run trace:lint ./trace.json.gz --fail-on warnLatest-trace script shortcut:
bun run trace:lint:latest --fail-on warnCapture-and-lint script shortcut:
bun run trace:lint:capture --capture-url https://example.com --capture-seconds 10 --fail-on warnNx target equivalents:
bun nx run trace-lint:run -- ./trace.json.gz --fail-on warn
bun nx run trace-lint:latest -- --fail-on warn
bun nx run trace-lint:capture -- --capture-url https://example.com --capture-seconds 10 --fail-on warnJank-focused run with strict dropped-frame policy:
trace-lint ./trace.json.gz \
--allowed-dropped-frames 0 \
--frame-budget-ms 16.7 \
--max-frame-overrun-ratio 0.03 \
--long-task-threshold-ms 50 \
--max-main-thread-long-tasks 0 \
--fail-on warnAPI Usage
import { loadTraceFile, runTraceLint, defaultTraceLintRules } from '@affectively/trace-lint';
import type { TraceLintRule } from '@affectively/trace-lint';
const customRule: TraceLintRule = {
id: 'my-custom-rule',
layer: 'expectation',
description: 'Example custom rule',
defaultSeverity: 'info',
check: ({ stats }) => {
const timerFires = stats.eventNameCounts.get('TimerFire') ?? 0;
if (timerFires < 200) return [];
return [
{
ruleId: 'my-custom-rule',
layer: 'expectation',
severity: 'info',
message: `High TimerFire activity: ${timerFires}`,
},
];
},
};
const trace = loadTraceFile('./trace.json.gz');
const composed = runTraceLint(trace, undefined, [
...defaultTraceLintRules,
customRule,
]);
console.log(composed.findings.length);Built-In Rules
no-dropped-frames(constraint) - fails when dropped frames exceed allowed threshold.frame-budget-jank(boundary) - checks BeginFrame cadence overrun ratio.main-thread-long-task-jank(boundary) - checks longRunTaskvolume on renderer main.renderer-main-boundary-bleed(boundary) - flags heavy parse/layout/script work on renderer main.parse-compile-budget(expectation) - tracks total parse+compile cost against budget.repeated-async-task-loop(boundary) - recurring async schedule loops.repeated-resource-request-loop(expectation) - stable request polling loops.timer-fire-loop(boundary) - regular timer cadence loops.
CI Integration
This repository includes a reusable workflow at:
It supports workflow_call, manual dispatch, and PR-triggered linting for trace-like files.
Development
cd open-source/trace-lint
bun run type-check
bun run build