bug(router): stats.filePath is parsed as a file path but always writes stats.jsonl
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 4k
- Forks
- 453
- Avg merge
- 12h 30m
- Merged PRs (30d)
- 46
Description
Summary
router.stats.filePath is declared as an override for the stats file path, but the parser drops it, and the collector would not honor the full filename even if it received the field.
Why it matters
A user or test can reasonably set router.stats.filePath: /tmp/custom-name.jsonl and expect stats to be written to that exact file. Today the field does not survive parsing. Separately, TokenStatsCollector treats filePath as a directory hint by taking dirname(filePath) and then always writing stats.jsonl. This can make stats data appear missing, cause tests to read the wrong file, or make multiple custom configs collide on the same default filename.
Evidence
src/router/config/schema.ts:58documentsfilePathas an override for the default~/.pilotdeck/router/stats.jsonpath.src/router/config/schema.ts:59declaresfilePath?: string.src/router/config/parseRouterConfig.ts:491entersparseStats.src/router/config/parseRouterConfig.ts:508parsesenabled.src/router/config/parseRouterConfig.ts:510parsesmodelPricing.src/router/config/parseRouterConfig.ts:532parsesbaselineModel.src/router/config/parseRouterConfig.ts:538returns{ enabled, modelPricing, baselineModel }, droppingfilePath.src/router/stats/TokenStatsCollector.ts:71checksconfig?.filePath.src/router/stats/TokenStatsCollector.ts:72usespath.dirname(config.filePath).src/router/stats/TokenStatsCollector.ts:76always setsjsonlPathtopath.join(routerDir, "stats.jsonl").
Validation
Validation level: dynamic parser reproduction plus source-control-flow confirmation.
Minimal reproduction:
- Parse router config containing:
router.stats.enabled: truerouter.stats.filePath: /tmp/custom-name.jsonl
- Inspect parsed router stats.
- Inspect collector path construction for the same field.
Key output:
- Parser output is
{ enabled: true }. filePathis absent from parsed stats.- Collector code would convert
/tmp/custom-name.jsonlto directory/tmp, then write/tmp/stats.jsonl.
Boundary: the parser loss was reproduced directly. The collector behavior is confirmed by source control flow. This does not validate concurrent stats writes or migration behavior.
Expected behavior
The behavior should match the field contract. Either:
router.stats.filePathmeans a full output file path, in which case the parser should preserve it and the collector should write exactly that path; or- the supported override is only a directory, in which case the schema/config field should be renamed or documented as a directory setting instead of
filePath.
Existing coverage checked
No matching fix was found.
Checked adjacent work:
- PR #208 touches router runtime internals, but does not preserve
router.stats.filePathin the parser or make the collector honor the full file path.
Search terms checked included router.stats.filePath, TokenStatsCollector filePath, and stats.jsonl custom.
Suggested fix
Pick one contract and make both parser and collector follow it.
Recommended contract:
- Treat
router.stats.filePathas a full file path. - Preserve
filePathinparseStats. - In
TokenStatsCollector, createpath.dirname(filePath)but setjsonlPathtofilePathitself. - Keep the current default path when
filePathis absent.
If the intended contract is directory-only, rename the setting or update schema/docs so users are not promised a file path override.
Suggested tests
- Parsing
router.stats.filePathpreserves the exact string inRouterStatsConfig. TokenStatsCollector({ enabled: true, filePath: "/tmp/custom-name.jsonl" })writes to/tmp/custom-name.jsonl, not/tmp/stats.jsonl.- Default behavior without
filePathstill writes the existing default stats file. - Migration logic still works when a custom full file path is configured.
Submitted with Codex.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with parseStats in src/router/config/parseRouterConfig.ts and the filePath handling in src/router/stats/TokenStatsCollector.ts. Reproduce parsing with /tmp/custom-name.jsonl, then inspect the suggested parser and collector cases, including the default path and migration behavior. Done means the chosen filePath contract is consistent and the custom and default outputs are covered.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100