fix(capabilities): kline/intraday/news 的 provenance.marketTime 从秒改为毫秒 - #163
Merged
Merged
Conversation
三个 capability manifest 直接把 epoch **秒**的时间戳写进 `provenance.marketTime`, 而该字段在所有其它产出方都是 epoch **毫秒**: - `market-quote.ts:51` 写 `quote.timestamp * 1000` - longbridge adapter 的 `marketTimeMsFrom()`(`marketTimeMsFrom` 命名 + `* 1000`) - 同一对象里的 `fetchedAt` 也是 `Date.now()`(毫秒) 涉事三处(同一个根因:manifest 漏做秒→毫秒换算): ```ts // market-kline.ts:51 marketTime: klines[klines.length - 1]?.timestamp // market-intraday.ts:32 marketTime: data[data.length - 1]?.timestamp // research-news.ts:37 marketTime: news[0]?.timestamp ``` 这些时间戳确实是秒——**同文件**的格式化函数就是证据: - `market-kline.ts:66` `new Date(kline.timestamp * 1000)` - `market-intraday.ts:47` `new Date(item.timestamp * 1000)` - `research-news.ts:54` `new Date(item.timestamp * 1000)` ## 影响 `buildFinancialEvidence()`(`packages/shared/src/evidence/financial-evidence.ts:54`) 直接把 `provenance.marketTime` 当作证据信封的 `asOf`。于是 kline/intraday/news 三类证据的 `asOf` 比正确值小 1000 倍(如 1.71e9 而非 1.71e12),任何按日期渲染 或做新鲜度比较的地方都会落到 1970 年。research runner 也会把这个值原样带上 (`research/runner.ts:355`)。 ## 修复 三处统一改为 `latest.timestamp * 1000`,并在序列为空时保持 `undefined`。 范围:仅这三个 manifest 的 `marketTime` 赋值,不改 `data`、不改 summary 格式化, 也不动 phase-two 里未经证实的同类写法。无可见 UI 变化(数据正确后展示才正确)。 ## 测试 `packages/shared/src/capabilities/manifests.test.ts` 新增 4 个用例: kline / intraday / news 各自校验 `marketTime === 1710000000 * 1000`, 以及空序列时 `marketTime` 为 `undefined`。 回归证明(修复前): ``` bun test packages/shared/src/capabilities --isolate -> 37 pass / 3 fail ``` 修复后: ``` bun test packages/shared/src/capabilities --isolate -> 40 pass / 0 fail (Ran 40 tests across 8 files) bun run typecheck -> @finagent/core / i18n / shared / ui / electron 全部 exit 0 ``` 基线说明:干净 `origin/main`(`7c9b550`)上 `bun test packages/shared --isolate` 为 1069 pass / 5 fail(`ExperimentService.runExperiment` ×1、`ResearchService` ×3、 `langfuse backend` ×1)。这些失败在 main 上可复现,与本改动无关;本改动未引入 任何新的失败。
helsome
approved these changes
Sep 22, 2026
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题
三个 capability manifest 直接把 epoch 秒的时间戳写进
provenance.marketTime,而该字段在所有其它产出方都是 epoch 毫秒(同一个根因:manifest 漏做秒→毫秒换算)。
判为 bug 的依据(单位证据)
marketTime是毫秒:market-quote.ts:51写marketTime: quote.timestamp * 1000;marketTimeMsFrom()名字带Ms,实现是return seconds * 1000;fetchedAt是Date.now(),即毫秒。这些 timestamp 是秒(同文件格式化函数即为证据):
market-kline.ts:66—new Date(kline.timestamp * 1000).toLocaleDateString()market-intraday.ts:47—new Date(item.timestamp * 1000).toLocaleTimeString()research-news.ts:54—new Date(item.timestamp * 1000).toLocaleString()实际 / 预期
17100000001710000000000影响
buildFinancialEvidence()(packages/shared/src/evidence/financial-evidence.ts:54):直接把
marketTime当作证据信封的asOf。kline / intraday / news 三类证据的asOf因此比正确值小 1000 倍(1.71e9 而非 1.71e12)——按日期渲染或做新鲜度比较时会落到
1970 年。
research/runner.ts:355也把这个值原样带上。修复
三处统一改为
latest.timestamp * 1000,序列为空时保持undefined:范围
仅这三个 manifest 的
marketTime赋值 + 一条注释。不改data、不改 summary 格式化。未一并改动的同类写法:
phase-two.ts里market.trades/market.capitalFlow也是latest?.timestamp/flow.timestamp,但这些类型的时间戳单位没有同文件证据可确认,留给单独确认,不混入本 PR。
无可见 UI 变化(数据是错的,改成正确值之后展示才正确)。
测试
packages/shared/src/capabilities/manifests.test.ts新增provenance.marketTime is epoch milliseconds一组 4 个用例:1710000000 * 10001710000000 * 10001710000000 * 1000undefined回归证明(修复前):
修复后:
基线说明(Full unit tests advisory):干净
origin/main(7c9b550)上5 项失败在 main 上可稳定复现,与本改动无关:
ExperimentService.runExperiment > creates + updates the experiment and persists runs and resultsResearchService > runs a report end-to-end and persists itResearchService > lists runs newest-firstResearchService > plans from the strategy and persists strategyId onto the reportlangfuse backend > does not throw when Langfuse is down — agent path keeps a diagnostic本改动未引入任何新的失败。
环境
Closes #162