Skip to content

F3 审查超时提醒仍按固定 30 天触发;应读合同类型的审查时限,与看板「审查超时限」一致 #203

Closed

Description

@objectstack-fleet

Found while landing #31 (PR #201).

现状。 PR #201 之后,法务工作台的「审查超时限」按每份合同自己类型的 review_sla_days 判定(读 clm_contract.review_sla_days_offset,平台存储表达式)。但 F3 日任务 src/flows/legal-review-sla.flow.ts 仍在审查开始满 30 天时提醒,clm_contract_type.review_sla_days 的帮助文字也照此说明。九种类型的真实时限是 2/3/5/10 天,所以看板说某份合同已超时限,提醒却要再等几周才发。

要做的。 让 F3 的触发条件读 review_sla_days_offset(同一条记录上的列,日任务可直接比较),并同步改 review_sla_days 的帮助文字和 DESIGN.md 里 F3 的描述(受管部分走 PR #120)。

注意。 升级的旧库里该列可能为 NULL(平台不回填存储表达式,见 objectstack 卡);条件应对 NULL 不提醒,而不是按 0 天提醒。

验收。 用 demo 账号,把 cron 临时改成每分钟(不提交):一份 DPA(时限 5 天)审查第 6 天收到提醒,同日开始的 MSA 不提醒。


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 19
    Ruling-ref: none (triaged follow-up of #31 / PR #201)
    Session: session_017nzWFRUo2U7evMkPdVniAn
    Account: zhuangjianguo (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-203-f3-type-sla
    Worktree: hotclm-issue-203
    Domain: repo:hotclm (single-lane sister repo — no domain:*)
    Seat: repo:hotclm#1
    File surface: src/flows/legal-review-sla.flow.ts · src/flows/_daily-sweep.ts (only if F3's query needs it; the stale notifyRecipients obligation clause may be fixed in passing) · src/objects/contract-type.object.ts (the review_sla_days help text) · src/email-templates/** (the F3 template only) · src/translations/{en,zh-CN}/ (F3 and review_sla_days strings) — stop on breach; explain in the report
    Container & model: S, mode:subagent, model: opus (TIER_DEFAULT; hand-derived for a sister repo), effort: medium
    Clause-②: no
    Metadata-protocol: none
    Responsibility: this app's F3 legal-review reminder (fires on the contract type's own SLA, as the workbench tile counts) | PR #201 stored review_sla_days_offset | legal counsel
    Thread-read: none
    Premise: re-measured by the dev on origin/main 7257a23 (@objectstack 18.3.0) with the declared demo staff
    Serial constraints cleared: batch 12 lanes landed (PRs #202, #204, #205); nothing else in flight.


    Generated by Claude Code

  2. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim amendment: PM loop round 19 · #203
    Session: session_017nzWFRUo2U7evMkPdVniAn
    Branch: claude/issue-203-f3-type-sla
    Seat call: option A. F3 escalates to the head of legal at 2× the type SLA, as DESIGN.md §06 F3 already says (超一倍), so no new ruling is needed.
    File surface, added: src/data/plan-contracts.ts (only handBackInReview's band and its guard text, so the one unassigned in-review row stays inside (SLA, 2×SLA] and the 「Nobody to tell」 edge stays covered) · src/datasets/contract.dataset.ts (only review_over_sla_count, which gains the same review_sla_days_offset: { $ne: null } guard, so the workbench tile and the reminder count the same rows; at 18.3.0 a NULL offset reads as 0 days, objectstack#29961).


    Generated by Claude Code

  3. objectstack-fleet commented on Nov 4, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 203,
      "status": "done",
      "branch": "claude/issue-203-f3-type-sla",
      "pr": "https://github.com/objectstack-ai/hotclm/pull/206",
      "session": "session_017nzWFRUo2U7evMkPdVniAn",
      "premise_still_valid": true,
      "summary": "F3 now selects in-review contracts whose review_started_at is earlier than { $now: true, addDays: { $field: 'review_sla_days_offset' } }, with review_sla_days_offset: { $ne: null }. The anchor is a literal operand, which the flow executor passes to the query unchanged (crud-nodes resolveNodeFilter evaluates CEL envelopes only) and the ObjectQL read path pins. Measured: 18.3 expresses the rule, so no refusal. The DESIGN §06 F3 head-of-legal copy (超一倍) is a partitioned per-row CEL decision, datetime(review_started_at) earlier than addDays(now(), offset + offset): one notice per row per run, which is F3's existing de-dup. The NULL guard is required because at 18.3.0 driver-sql reads a NULL addDays column as ZERO days (#25808 conformance table, row 4; also measured on the REST door). Per the seat's amendment (option A): the review_over_sla_count tile gets the same guard, and handBackInReview moves the unassigned in-review row to SLA + ceil(SLA/2) days so the Nobody-to-tell edge stays covered. Templates and topics are renamed to over_sla / over_double_sla; the review_sla_days help text (en + zh-CN) is rewritten. No stamp, hook or mirror column; _daily-sweep.ts is untouched.",
      "tests": "Throwaway DBs, pnpm demo:zh on port 3170, the uncommitted every-minute cron override reverted afterwards (git diff HEAD = 0 lines). Fixture applied identically to both trees by direct SQLite edit after seed, because review_started_at and the offset are engine/system-written: DPA-2026-0005 started 6d ago, MSA-2026-0001 started 1d ago, NDA-2026-0003 offset NULL. Inbox read as persona via GET /api/v1/data/sys_inbox_message. BEFORE origin/main 7257a23: DPA 6d gets no reminder; NULL-offset NDA (38d) reminded once per tick; only the 30-60d rows reminded. AFTER 99c58b1: counsel2 '2x clm_legal_review_over_sla | warning | Legal review over SLA: 数据处理协议 — 渡鸦安保 [23:56:00, 23:57:00]', no head copy; MSA-2026-0001 (counsel1) none; NDA-2026-0003 (counsel1) none; 8 others over_double_sla critical once per tick each, legal.head 16 = 8 per tick; unassigned MSA-2026-0004 (8d, SLA 5) sends nothing (Nobody-to-tell edge). Fresh seed without fixture: 11 doubled per tick, legal.head 11 per tick. REST door as counsel1: unguarded anchor filter total 11 including NDA-2026-0003 (NULL read as 0 days); with $ne:null total 10. Tile 审查超时限 in Chromium zh-CN as counsel1 (POST /api/v1/analytics/dataset/query 200): main fresh 12 (MSA 6, NDA 2, SUP 1, DPA 1, LSE 1, ICA 1); branch fresh 12, same per type (the moved row is still over its SLA, so the numbers do not move); branch with fixture 10 (MSA 5, NDA 1, SUP 1, DPA 1, LSE 1, ICA 1), equal to F3's set for that tick. Console: one 404 resource error on both trees. Seed band probe (CONTRACT_PLAN): all 12 dealt in-review rows were past 2x SLA, hence the move. No ablation: metadata/config only, no tested behaviour pinned by a test file.",
      "gates": "On final HEAD 99c58b1, exit codes captured before any pipe: pnpm install 0; pnpm validate 0 (Validation passed, 7 pre-existing warnings, the same 7 on origin/main, none on legal_review_sla); pnpm lint 0 (0 warnings, 6 suggestions, the same as main); pnpm typecheck 0; pnpm lint:i18n-gate 0 (0 missing keys across 2 locales); CLM_DEMO_SEED=1 pnpm validate 0. CI on PR #206: Validate completed success, a second Validate run in_progress at report time. dispatch-gates.mjs not applicable (hotclm has no such script; gates are the repo's own verify set).",
      "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm; hotclm has no dogfood battery",
      "mcp_calls": "0",
      "api_writes": "2 — fleet-write relay: pr_create (POST /repos/objectstack-ai/hotclm/pulls + POST /issues/206/assignees, read back identical 7895 bytes, assignee zhuangjianguo); this os-dev-report comment (POST /repos/objectstack-ai/hotclm/issues/203/comments). git push is not a REST write.",
      "open_questions": [
        {
          "question": "Governed text for the seat to carry on PR #120: DESIGN.md §06 F3 row.",
          "options": [
            "A | F3 | `legal_review_sla` | 定时(日) | `in_review` 超过类型 `review_sla_days`(按合同上存储的 `review_sla_days_offset` 判定,与法务工作台「审查超时限」同一规则;该值为空的合同不提醒):提醒 `legal_owner`,超一倍抄送 `clm_legal_head`;每份合同每次运行只发一条 |",
            "B Leave the row as it is: its intent already matches the implementation."
          ],
          "recommendation": "A, because it names the stored column F3 and the tile share, and the NULL rule, which an upgraded database depends on."
        },
        {
          "question": "DESIGN.md §12 row \"CEL 日期算术 | #7 | 到期、逾期由日任务盖戳字段 | 公式字段\" is stale on 18.3: @objectstack/formula registers daysBetween, addDays, now() and datetime(), and F3 now uses them in a flow edge. Revise it?",
          "options": [
            "A Seat drafts a §12 revision on PR #120 (whether a formula field may now use daysBetween is a separate product question)",
            "B Leave it until a card needs date formulas"
          ],
          "recommendation": "B, because no card needs it now; the stale claim lived in F3's header, which this PR removed."
        }
      ],
      "out_of_scope_findings": [
        "class: a · reach: GET /api/v1/data/sys_inbox_message as counsel2@example.com on pnpm demo:zh returns English subjects ('Legal review over SLA: …'), and the same English (over_30_days) on origin/main 7257a23. The demo staff have sys_user.locale = null, so every email_template bundle falls to the en-US floor (_bundle.ts) in the zh-CN demo · dedupe words: demo:zh notifications English, demoStaff locale, sys_user.locale null, en-US floor, inbox language",
        "carrier: none · noted, not filed — the F3 notice's {{ review_started_at }} hole renders the raw ISO instant (2026-10-09T00:00:00.000Z), unchanged from main (polish)",
        "carrier: none · noted, not filed — src/data/contract.seed.ts comment says 'two contracts in review are handed back' while UNASSIGNED_IN_REVIEW = 1 (pre-existing drift; file outside the claim)"
      ]
    }
  4. objectstack-fleet commented on Nov 4, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling-ref: none (triaged follow-up of #31)

    Landed — PR #206 · 2026-11-04

    reading value
    PR #206 MERGED (squash on main), merged at its ACCEPT head 99c58b1; Fixes #203 closes this card
    authority maintainer, project thread, verbatim: 「你可以自己审核的就自己合并」

    Release: the F3 reminder fires when a review passes its contract type's own SLA and copies the head of legal at twice the SLA, the same rule the workbench tile counts; a contract whose SLA offset is still empty is neither reminded nor counted. The §06 F3 text is on PR #120. State: pm:dispatched removed, assignee cleared.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions