Repository navigation
F3 审查超时提醒仍按固定 30 天触发;应读合同类型的审查时限,与看板「审查超时限」一致 - #206
Merged
Merged
Conversation
F3 fired at a fixed 30 days while the legal workbench counts a review as over SLA by its type's review_sla_days (2/3/5/10 days) since #201. F3 now selects with the same rule: in review, review_started_at earlier than the $now anchor shifted by the stored review_sla_days_offset. The head of legal is copied past twice the SLA (DESIGN.md §06 F3, 超一倍) via a per-row CEL decision over the two projected fields. At 18.3.0 the SQL driver reads a NULL offset column as zero days, and an upgraded database holds NULL until the contract is next written (objectstack#29961), so both F3 and the workbench's review_over_sla_count require review_sla_days_offset to have a value. The demo seed moves its one unassigned in-review contract into (SLA, 2 x SLA] so F3's "nobody to tell" edge stays exercised. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017nzWFRUo2U7evMkPdVniAn
Contributor
Author
席位核对 — ACCEPT · head
|
| check | reading |
|---|---|
| shape | draft → main, Fixes #203; base 7257a23, mergeable clean |
| CI on the head | both Validate check-runs success on 99c58b1 = PR head.sha |
| scope | 8 files, inside the claim as amended (seat call A: the head-of-legal copy at 2× the type SLA, as §06 F3 already says). F3 selects in-review contracts past $now + review_sla_days_offset with review_sla_days_offset: { $ne: null }; the 2× band is a per-row CEL decision; review_over_sla_count gains the same NULL guard; the seed's one unassigned in-review row moves to SLA + ⌈SLA/2⌉ days so the 「Nobody to tell」 edge stays covered. No stamp, hook or mirror column. Lint 0 warnings |
| measured (18.3.0, every-minute cron override, reverted) | a DPA review 6 days in (SLA 5) reminds its counsel, no head copy; an MSA 1 day in does not; a NULL-offset contract does not (main reminded it once per tick); 8 rows past 2× reach legal.head; the unassigned row sends nothing. Tile on a fresh seed: 12, the same per type as main; with the fixture the tile and F3's set agree at 10 |
| seat calls on the open questions | §06 F3 row: A, carried on PR #120. §12 「CEL 日期算术」 row: B, left until a card needs date formulas |
| residuals | demo notifications render in English because demo staff have no locale (existing cards #172 / #142); the F3 notice prints the raw ISO start time (polish, not filed) |
Landing: under the maintainer's merge authorization (project thread: 「你可以自己审核的就自己合并」).
Generated by Claude Code
zhuangjianguo
marked this pull request as ready for review
November 4, 2026 00:03
zhuangjianguo
pushed a commit
that referenced
this pull request
Nov 4, 2026
Code: PR #206. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017nzWFRUo2U7evMkPdVniAn
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.
Fixes #203
F3 (
legal_review_sla) now reminds on each contract type's own review SLA, using the same rule as the legal workbench's 「审查超时限」 tile (PR #201). It no longer uses a fixed 30/60 days.What changed
src/flows/legal-review-sla.flow.ts: one daily query in place of the two fixed bands. It selectsstatus: 'in_review'andreview_sla_days_offset: { $ne: null }, andreview_started_at: { $lt: { $now: true, addDays: { $field: 'review_sla_days_offset' } } }. The anchor is a literal operand, so the flow executor hands it to the query unchanged (crud-nodes.tsresolveNodeFilterevaluates CEL envelopes only), and the ObjectQL read path pins$now(resolveFilterTokens, corefilter-tokens.ts). DESIGN §06 F3's 「超一倍抄送clm_legal_head」 is a per-row CEL decision over the two projected fields:datetime(review_started_at)earlier thanaddDays(now(), offset + offset). Its two edges are exact complements, so each selected row gets exactly one notification per run: over SLA goes to the legal owner; over double the SLA goes to the legal owner with the head of legal copied. That is F3's existing de-duplication (a daily nudge, one notice per row per run), kept as it was.addDayscolumn as zero days (driver-sqlcross-field-conformance-cases.ts, #25808 table, row 4). An upgraded database holds NULL until the contract is next written (objectstack#29961). The$ne: nullconjunct is the filter grammar's has-a-value predicate.src/datasets/contract.dataset.ts(review_over_sla_countonly, claim amendment): the samereview_sla_days_offset: { $ne: null }guard, so the tile and the reminder count the same rows.src/email-templates/legal-review-sla.email-template.ts+index.ts:clm.legal_review_over_30_days/_over_60_daysbecomeclm.legal_review_over_sla/clm.legal_review_over_double_sla(en + zh-CN). Topics are renamed to match:clm_legal_review_over_sla/clm_legal_review_over_double_sla. The wording no longer says 30/60 days.clm_contract_type.review_sla_dayshelp text (object + en + zh-CN): it now says what F3 does, and that a contract keeps the value it was last saved with.src/data/plan-contracts.ts(handBackInReviewonly, claim amendment): the one unassigned in-review contract has to sit in F3's over-SLA band (legal owner as sole recipient) to keep the 「Nobody to tell」 edge exercised. Every dealt in-review row is past twice its type's SLA, so the chosen row (shortest review first) has its whole timeline shifted toSLA + ⌈SLA/2⌉days in review. The function then re-proves the band on the result. On this corpus it is MSA-2026-0004 at 8 days (SLA 5)._daily-sweep.tsis untouched.Evidence: browser + persona readings, 18.3.0,
pnpm demo:zh, port 3170, throwaway DBsFixture. The card's three cases need rows a persona cannot write:
review_started_atis a lifecycle stamp, and the offset is a stored expression. So after boot and seed, the same three seeded in-review rows were edited directly in each throwaway SQLite DB, identically on both trees (2026-11-03T23:48Zbefore,23:55Zafter):review_sla_days_offset = NULL, the upgraded-DB state; review is 38 days old.F3 cron was overridden to
* * * * *, uncommitted and reverted (git diff HEADempty afterwards). Inboxes were read as each persona fromGET /api/v1/data/sys_inbox_message, signed in with the demo password.7257a2399c58b1clm_legal_review_over_sla· warning, 1 per tick (23:56:00, 23:57:00); head not copiedover_30_days)over_double_sla· critical, 1 per tick each, legal.head copied (8 per tick)The fresh seed with no fixture, read the same way: 11 rows in the doubled band, each 1 notice per tick to its counsel plus 11 to legal.head; the unassigned MSA-2026-0004 sends nothing.
NULL offset reads as zero days, measured on the REST door. As counsel1,
GET /api/v1/data/clm_contractwith the unguarded anchor filter returns 11 rows including NDA-2026-0003. Withreview_sla_days_offset: { $ne: null }added it returns 10, without it.Workbench tile 审查超时限, read in Chromium (zh-CN) as counsel1 on
/_console/apps/app.objectstack.hotclm/dashboard/legal_workbench, fromPOST /api/v1/analytics/dataset/query(200):With the fixture, the tile's 10 equals F3's set for that tick: DPA over SLA, 8 doubled, and MSA-2026-0004 over SLA with nobody to tell. Browser console on both trees: one
404 (Not Found)resource error, the same before and after. Boot banner on both:Flows: 13, seeds1130 rows, nodegraded/no such table.Gates (final commit
99c58b1, each exit code captured before any pipe)pnpm validateprints 7 ⚠ lines (approval-approver and capability notices) on both origin/main and this branch; none namelegal_review_sla.Acceptance notes
auth, pin better-auth, require browser verification #7 ("nodaysBetweenin CEL"). That is stale on 18.3:@objectstack/formularegistersdaysBetween,addDays,now()anddatetime(), and this PR's decision edge uses them.sys_user.locale = null, so F3's notices (and every other bundle's) fall to theen-USmember even underdemo:zh, as_bundle.tsdocuments. The same holds on origin/main.{{ review_started_at }}hole renders the raw ISO instant (2026-10-09T00:00:00.000Z). This is unchanged from origin/main.review_sla_daysreaches a contract already in review only when that contract is next saved (stored expression, recomputed on the contract's own write). The new help text says so.src/data/contract.seed.tssays "two contracts in review are handed back";UNASSIGNED_IN_REVIEWis 1. This was stale before this PR, and the file is outside the claim, so it is left as is.grepoversrc/).🤖 Generated with Claude Code
https://claude.ai/code/session_017nzWFRUo2U7evMkPdVniAn