feat(engine): MulmoClaude 側で育った engine を持ち帰る(テスト一式と、Excel と違っていた期待値2件の修正つき) - #31
Conversation
The engine here and the one in MulmoClaude's src/plugins/spreadsheet started as one copy. The copy kept going: its formula handling was split into small units with tests of their own, and several Excel behaviours were corrected along the way. This brings that engine back, with its tests. What arrives with it: - src/engine is replaced wholesale. The reference handling moved from parser.ts into formulaRefs.ts, the aggregates read through cellBuilder / condition / numericCoercion, and the financial, statistical, lookup and math helpers are separate units. - src/engine/guards.ts holds the three runtime helpers the engine needs (isRecord, isObj, errorMessage). They come from MulmoClaude's leaf package; copied rather than depended on, because a gui-chat plugin must not take a dependency on a host's packages. - tests/engine gains the engine's own node:test suite, run by a new `test:engine` script and folded into `test:all`. Two expected values in the financial fixture were wrong and now match Excel: the first interest payment had the sign of money coming in rather than going out, and the first principal payment was not PMT - IPMT. The reason is recorded in tests/engine/fixtures/README.md so a future change cannot quietly flip them back. Two test-side repairs, neither of which changes the engine: - parser.test.ts kept exercising parseCellRef / parseRangeRef / cellRefToA1, which this engine does not have; expandRangeOrCell covers that ground and has its own tests. Column conversion stays, since the Vue view still uses it. - run-evaluator-tests.ts built a context whose range readers answered nothing for a single cell, so MAX(B1, A1:A3, 5) silently dropped B1. The real context resolves every reference through expandRangeOrCell; the fake now does too. typecheck, lint, build, and every test script pass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Evidence for the two corrected fixture values, from outside this repository (asked for on review): Microsoft's own So for
Which is what this engine returns, and what the fixture now expects. The old expectation had the interest payment positive while the Source: https://support.microsoft.com/en-us/office/ipmt-function-5cce0ad6-8402-4a41-8d29-61a0b054cb6f |
|
CODEX VERDICT: LGTM
FINDINGS COMPLETE: I read every hunk of the diff and this is every finding I have. |
Codex cross-review — round 1 (tier C): cleanCodex: What it did rather than read:
My own sign-offNo MUST-FIX from either reviewer. One note I am deliberately leaving: Prompt sent (verbatim)Codex stdout (verbatim) |
refactor(view): ハイライトと矢印キーの純粋部分を持ち帰る(#31 の上に積んでいます)
Summary
src/engineをまるごと、MulmoClaude 側で育った engine に入れ替えます(#30)。もとは同じコピーで、向こうだけが進み続けていました。engine 自身のテストも一緒に持ち込みます。parser.tsからformulaRefs.tsへ移り、集計はcellBuilder/condition/numericCoercionを通り、金融・統計・検索・数学のヘルパーはそれぞれ独立したファイルになっています。src/engine/guards.ts: engine が必要とする実行時ヘルパー3つ(isRecord/isObj/errorMessage)。MulmoClaude の leaf パッケージから写したもので、依存はしていません。gui-chat の plugin がホストのパッケージに依存してはいけないためです。tests/engine: engine の node:test 一式。新しいtest:enginescript で走り、test:allにも組み込みました。PMT - IPMTになっていませんでした)。理由はtests/engine/fixtures/README.mdに書いたので、将来また戻されることはありません。Items to Confirm / Review
exportsは././core/./vue/./style.cssで、core/index.tsは engine を再公開していません。vue/View.vueが使うのはSpreadsheetEngine/columnToIndex/indexToColumnの3つだけで、どれも残っています。利用者向けの破壊的変更はありません。parseCellRef/parseRangeRef/cellRefToA1は復活させませんでした。 この engine には無く、参照解決はexpandRangeOrCellに移っていて、そちらにテストがあります。parser.test.tsの該当ブロックは消し、列変換のテストは残しました(View がまだ使うため)。消してよかったかは見てください。IPMT(5%/12,1,24,10000)は Excel では支払いなので負、PPMTはPMT - IPMTです。同じ fixture のPMTはもともと負を期待していたので、中でも食い違っていました。Excel で確かめ直せる方に見てほしい箇所です。run-evaluator-tests.tsの偽コンテキストを直しました。 range を読む関数が単一セルに何も返さないため、MAX(B1, A1:A3, 5)が B1 を黙って落としていました。本物のコンテキストは参照をすべてexpandRangeOrCellで解決するので、偽物もそれに合わせています。engine 側は変えていません(MulmoClaude の engine を実際のシートで叩くと Excel と同じ 75 を返します)。typeをinterfaceにした箇所が3つあります(calculator.ts×2、functions/statistical.ts×1)。このリポジトリの lint 規則がそう要求するためで、中身は同じです。calculator.tsのCellPosition.cellsがany[]のままです。 持ち込んだコードのままにしました。直す価値はありますが、この PR では型を触らない方針にしています。vue/View.vueは手を付けていません。 MulmoClaude 側の View は wiki リンクや markdown 向けの処理などホスト固有の依存を持つので、次段にします。挙動が変わるところ(レビューで両エンジンを走らせて測りました)
fixture の2値以外にも、旧エンジンが黙って空や 0 を返していた3つが値を返すようになります。
a1:a3)$A$1:$A$3)MAX(B1, A1:A3, 5)のB1)これらは旧エンジンの取りこぼしで、どれも正しい値を返す方向の変化です。それ以外の入力については、旧エンジンを取り出して並べて走らせ、算術・セル参照の算術・SUM / AVERAGE の範囲・IF・文字列結合・シート跨ぎ参照・
DAY(date)・2^3^2の結合順まで一致を確認しています。確認したこと
typecheck/lint(エラー0)/buildと、test/test:engine/test:fixtures/test:calculator/test:evaluator/test:functionsがすべて通ります。User Prompt
src/plugins/spreadsheet/はこの plugin をコピーして改良したもの。こちらのほうが進んでいるので、上流に戻したい。Closes #30
🤖 Generated with Claude Code