fix(core): align Moirai F1 judgment contracts and Codex roadmap - #15
Merged
Merged
Conversation
Preserve legacy policy replay and mechanism revisions while holding incomplete judgments under policy revision two. Prepare bounded prose before immutable hashing and retain clipping provenance. Restore the Codex and OpenCodex backend decision in the canonical roadmap.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
This was referenced Sep 13, 2026
Automated review on 4ed1ff8 found two defects in the new contracts. An incomplete deferred receipt is terminal but still trusted its order, recommendations, exclusions and abstentions, so a caller could preserve arbitration claims that no stored evidence supports. Budget conversion was also ungated on policy revision, letting a revision-1 replayed hold become a terminal budget-exhausted receipt that revision 1 never declared. An incomplete deferred receipt now must restate the declared policy order, must match the recommendations its stored assessments prove, and must leave exclusions, abstentions, conflicts, ranking and concessions empty. Budget conversion requires revision 2 or higher. Held receipts keep their PR14 descriptive latitude so historical action bytes and digests stay readable. Four regressions failed first, then passed; a positive case keeps proven recommendations. Judgment suite 631 pass, typecheck, lint and build pass.
Follow-up review found the incomplete-evidence branch admitted a terminal deferred receipt under any policy revision. Revision 1 is kept only for historical replay and ended such rounds as held, so closing one as deferred permanently stopped work that revision 1 left retryable. Incomplete evidence now yields a terminal receipt only under revision 2, matching the budget-conversion gate, while held stays available for every revision. The incomplete-evidence cases moved onto revision-2 rounds, a new test covers the revision-1 rejection, and the candidate suite returns to its revision-1 contract with the closed-round and null-selection checks kept. Judgment suite 630 pass; typecheck, lint and build pass.
Follow-up review found two more defects. An incomplete revision-2 round accepted any deferred reason, so a caller could end a round that still had evaluation budget, and recording a resolution then blocks the missing assessment. The policy lookup also ran for held rows, and because the ledger audit runs inside every transaction, one historical hold recorded under a catalog or revision this binary does not declare would fail unrelated reads. A terminal receipt for incomplete evidence now requires the shared EVALUATION_BUDGET_EXHAUSTED reason, so any other interruption stays held and the round keeps its remaining work. The held path resolves no policy; the lookup runs only for that terminal receipt and for complete replay. Three regressions failed first, then passed, including a revision-3 hold that reopens and still serves unrelated reads. Judgment suite 632 pass; typecheck, lint and build pass.
A readout whose first 4,000 units are whitespace passed whole-value validation and then failed the same non-empty rule on its clipped prefix, so long prose failed the judgment instead of clipping. Storing the whitespace prefix instead would have produced a record the parser cannot read back, so such a bound is now reported for repair or hold. The contract also records two boundaries the code cannot verify: store writes keep the permissive historical parsers, so fresh output must go through the builders, and an incomplete held receipt carries unreplayed diagnostics that are not execution, learning or ranking evidence. Regression failed first, then passed. lina-core 2065 pass; typecheck, lint and build pass.
The emptiness test used trim(), which strips ECMAScript whitespace but leaves invisible format characters, so a bound holding 4,000 zero-width spaces passed and produced a record that renders empty while real text sat just past the bound. Content is now judged with a Unicode test that also excludes control and format characters. Regression covers space, newline, U+200B and U+FEFF, and a positive case keeps clipping when a zero-width character precedes real text inside the bound. lina-core 2065 pass; typecheck, lint and build pass.
The content test ran only after clipping, so the early return for prose within the bound still accepted a readout made only of control or format characters: a single zero-width space produced an assessment whose text renders empty, while the same content past the bound was rejected. The bounded text is now determined first and the rule applies to both return paths. Regressions cover short and long invisible prose for assessments and for both dialogue readouts. lina-core 2065 pass; typecheck, lint and build pass.
The incomplete-deferred path resolved a policy before its field checks, so a receipt written by a later build under an undeclared revision would fail the ledger audit that runs inside every transaction, leaving unrelated rounds and intentions unreadable after a downgrade. Validation now takes an explicit stored flag: auditing persisted bytes keeps such a receipt as history, while a fresh write still requires a policy it can check. The complete-evidence replay path keeps its existing behavior, tracked separately. The readable-text class also accepted standalone combining marks, which render as nothing without a base character, so it now excludes Mn and Me. Both regressions failed first, then passed. lina-core 2066 pass; typecheck, lint and build pass.
The provenance digest hashed the readout as UTF-8, which folds every unpaired surrogate onto the same replacement character, so two originals differing only in a trailing lone surrogate could share one sourceDigest and the metadata could no longer identify which prose was clipped. The digest now hashes UTF-16LE bytes, which is injective over code units. No stored digest changes meaning, since F1 has no product writer yet and this branch is unmerged. Regression failed first, then passed. lina-core 2067 pass; typecheck, lint and build pass.
Hangul fillers such as U+3164 and U+115F are category Lo, so the readable-text class still accepted a readout made only of them, which renders blank. The class now excludes Default_Ignorable_Code_Point, the Unicode property the earlier category-by-category fixes were approximating. Regression adds both fillers to the existing blank cases. lina-core 2067 pass; typecheck, lint and build pass.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7ded8af6c4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
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.
Change
#14의 F1 계약에서 긴 판단 설명문이 거부되고, 평가가 불완전한 행동 회차를 예산 소진으로 종료할 수 없던 문제를 수정합니다.
deferred저장과 예산 소진 기록의 재생·복원을 지원합니다. 기존 revision 1 기록은 당시 정책으로 재생합니다.mechanismRevision에 내용 해시를 허용하고 기존 숫자 버전과의 호환성을 유지합니다.Verification
동일 head의 로컬 검증과 독립 코드 재검토가 통과했습니다.
bun test packages/lina-core/test/judgment*.test.ts: 628 passed, 0 failed.bun test packages/lina-codex/test/tasks.test.ts packages/lina-runtime/test/task-connection.test.ts packages/lina-runtime/test/task-tools.test.ts packages/lina-runtime/test/codex-fleet.test.ts: 23 passed, 0 failed.bun run typecheck: passed.bun run lint: passed; 기존 경고 27개가 남아 있습니다.bun run ci:build: passed; 런타임 자산 빌드와 상태를 쓰지 않는 CLI smoke.git diff --check: passed.GitHub CI 결과는 이 PR의 checks에서 별도로 확인합니다. 전체 패키지 테스트와 라이브 모델 호출 결과를 위 로컬 검증에 포함하지 않습니다.
Risks and remaining work