fix(shared): exam の time-box を advisory に戻し binding の valid から外す (#220) - #272
Merged
Conversation
ADR-0013 / system-spec §4.7 は deadline を「advisory な提出窓の上限。verifyExamBinding の time-box は失格条件にしない (開始/締切の管理は Moodle が唯一の正)」と定めているが、 verifyExamBinding が withinWindow !== false を総合 valid に合流させていた。 波及: - root アンカー gate (#131 / ADR-0017) の exam 免除は examBindingVerified = binding.valid なので、遅延提出というだけで免除が外れる - deriveAssurance (ADR-0020) にも同じフラグが流れ、保証等級まで落ちる - verify (web) は submissionTimeMs を渡さないため、同じ proof で web は PASS・CLI は FAILED という非対称が出る time-box を valid から外し (withinWindow の算出ロジックは不変・表示専用の advisory)、 verify-cli の time-box 行も総合 PASS の下で FAIL と読ませない表記に改めた。 docs/system-spec.md §6.4 に valid と合流しない旨を明記。 Assisted-by: Claude <noreply@anthropic.com>
shinyaoguri
enabled auto-merge (squash)
August 15, 2026 21:32
🚀 Preview Deployment
Deployed from commit bea2ebd |
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.
Closes #220
目的
ADR-0013 と system-spec §4.7 は
deadlineを「advisory な提出窓の上限。verifyExamBindingの time-box は失格条件にしない。開始/締切の管理は Moodle が唯一の正」と定めているが、verifyExamBindingがwithinWindow !== falseを総合validに合流させており、docs と正面から矛盾していた (同関数内のコメント自体が「time-box (advisory)」と書いていて、18 行下のコードと食い違っていた)。docs を正とし、実装を ADR-0013 に合わせる。 判断の経緯・却下案は #220 のコメント に記録した。
なぜ「exit 1 になるだけ」ではないか
binding.validの下流は 3 方向に伸びている。verify.tsのexamBindingVerified: binding?.valid === trueにより、遅延提出というだけで ADR-0017 の gate 免除 ([shared] 自己申告の proof.exam ブロックで --require-root-anchor gate をバイパスできる #131) が外れるderiveAssuranceのbindingValidに流れる。「実証拠のみから導出し自己申告は使わない」という ADR-0020 の原則に、スケジュールという運用情報が混入していたsubmissionTimeMsを渡さないためwithinWindowは常にnull。同じ proof + 同じ package でも Web は PASS、CLI に--submitted-atを渡すと FAILED になっていた ([verify/verify-cli] web↔CLI の結論一致を CI で固定するパリティテストを追加する #216 でパリティを固めた直後の非対称)変更点
packages/shared/src/exam/examPackage.ts—result.validからwithinWindow !== falseを削除。withinWindowの算出 (下限>= releaseTimeを含む) は一切変更せず、timeBoxは表示専用の advisory 情報になるpackages/verify-cli/src/output.ts— time-box 行からpassFailを外す。validから外すだけだとSubmitted within window: FAILと出したまま総合は PASS になり、採点者に「FAIL と書いてあるのに合格」と読まれるため。窓内はyes、窓外はno (advisory — the submission window is managed by Moodle, not by this proof)。ADR-0013 が Negative 節に残した「advisory である旨が伝わるかは UI 表示次第 (既存の繰り越し課題)」もここで閉じるdocs/system-spec.md— §6.4 手順 5 に「withinWindow=falseはvalidに合流しない」を明記 (§4.7 は既に正しいので変更なし)CHANGELOG.md— Unreleased / 修正 に 1 行ADR-0013 は変更していない。 実装を ADR に合わせる修正であり、
docs/adr/README.mdの append-only 規約の改廃手続き (新 ADR + Superseded) には該当しないため。テスト
packages/shared/src/__tests__/examBinding.test.ts— 「窓外で fail」を「窓外でも valid、withinWindow=falseが立つ」に反転 (= 本 Issue の再現テスト)。下限側 (releaseTime より前の提出) の境界ケースも 1 件追加packages/verify-cli/src/__tests__/output.test.ts— time-box 行の表示テストを新設。この行は既存テストを一度も通っていなかった (examBindingFailed()がtimeBox: nullだったため)実装前にテストだけ投入して shared 2 件 / verify-cli 2 件が赤くなることを確認し、修正後に緑にした。仕上げに
validの式へwithinWindow !== falseを戻し、CLI の行をpassFailに戻して、4 ケースすべてが再び赤くなることも確認済み。CLI 経路の統合テストは新設していない — 出題者鍵レジストリが本番定数
EXAM_AUTHORITY_KEYS固定のため「binding valid かつ窓外」を組み立てられない (#216 のパリティテストに binding が valid になるケースが 1 件も無いのも同じ理由)。波及 1・2 は shared 側でbinding.valid === trueを固定することで担保している。確認方法
E2E は CI の e2e job に委ねる。
変更していないもの
releaseTimeの意味づけ (発行時刻 = 鍵有効性アンカー) と下限判定 → 見直しは [docs/editor] releaseTime を「教員が設定する試験開始時刻」に戻すか決める (ADR-0013 の再検討) #271 に切り出し/authorの UI、manifest フォーマット、--submitted-atの引数仕様ResultPanel(withinWindowを表示しないため不要)🤖 Assisted by Claude Code