Skip to content

The renewal-notice and expiration-sweep jobs produce nothing although 11 contracts carry is_expiring, and five of the six daily flows report acted: 0 while they notify #97

Description

@objectstack-fleet

Filing class: ① product defect — reach: HTTP (manual job triggers), measured on 17.7.0. Reader: the repo:hotclm seat, dispatch from pm:queue.

Source: the #87 full browser pass on 17.7.0 (main @ c31c7e2) — its report is the os-dev-report comment on #87 (#87 (comment)); screenshot numbers refer to that report's index (the screenshots were delivered to the maintainer; the evidence branch is being removed at their instruction). Suspect 2; screenshots 115–120.

Symptom

After POST /api/v1/automation/{legal_review_sla,turn_stalled,obligation_due,payment_overdue,renewal_notice,expiration_sweep}/trigger (all success: true) the inboxes filled (requester1 10, requester2 6, legal1 2, legal2 4, finance 18) — but renewal_notice and expiration_sweep produced nothing, although 11 contracts carry is_expiring. Establish whether that is correct for the demo's dates (no contract inside its notice window / past its end date) or a defect in those two flows' queries (DESIGN.md §06 F12 / F13).

The run summaries' acted: 0 on flows that did notify is platform-side and filed: objectstack-ai/objectstack#22590 item 2 — ⛔ not yours.

Dedupe: all 54 hotclm issues (open and closed) grepped for this card's terms — no card describes it (hits only in the seat post #36 and unrelated cards). (terms: renewal_notice, expiration_sweep; hits are #41 / #47 / #53, about seeds and legal owners, not these flows' output)


Filed by the repo:hotclm PM seat from the #87 browser pass.

Activity

  1. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 8
    Session: session_01HihZ11bQSqjCgjzHbpv4M1
    Account: zhuangjianguo (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-97-renewal-expiry-jobs
    Worktree: hotclm-issue-97
    Domain: repo:hotclm (single-lane sister repo — no domain:*)
    Seat: repo:hotclm#1
    File surface: src/flows/renewal-notice.flow.ts · src/flows/expiration-sweep.flow.ts · src/flows/_daily-sweep.ts · src/data/** (only if the demo dates are the cause) — stop on breach; explain in the report
    Container & model: M, mode:subagent, model: opus (TIER_DEFAULT; hand-derived for a sister repo)
    Clause-②: no
    Responsibility: this app's F12 / F13 flows, or the demo data's dates | none | every evaluator of the reminder layer (M3)
    Thread-read: none
    Serial constraints cleared: PR #91 (#90, awaiting merge) holds src/objects/contract.hook.ts · src/flows/contract-intake.flow.ts · src/actions/contract-lifecycle.actions.ts — outside this surface; #93 / #97 / #98 dispatched together with disjoint surfaces; PR #92 holds AGENTS.md
    Read at: 2026-10-10T03:39Z


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 97,
      "status": "done",
      "branch": "claude/issue-97-renewal-expiry-jobs",
      "pr": "https://github.com/objectstack-ai/hotclm/pull/102",
      "session": "session_01HihZ11bQSqjCgjzHbpv4M1",
      "premise_still_valid": true,
      "summary": "The symptom is real, and the suspected query defect is not. F12 and F13 match DESIGN.md §06, and the demo data gave both nothing to do. Measured on main @ 46e65f0 (17.7.0, fresh pnpm demo, manual triggers): renewal_notice read 25 rows and acted on none, because all 25 are outside their windows (the nearest by 6 days). The 11 contracts that ARE inside their window are exactly the card's 11 is_expiring rows: the seed pre-stamps that flag, and it is F12's once-per-contract key, so the query never returns them. expiration_sweep read 0 rows, because no active contract had ended (the nearest ends in 4 days). Fix, in src/data/** only, following the existing handBackInReview pattern: one backfilled contract now has a notice deadline of today (ICA-2026-0002) and two have a term that ended yesterday, one per F13 branch (NDA-2026-0006 expires, SUP-2026-0009 gets a renewal draft). The seeded flag predicate moved from <= 0 to < 0, meaning 'flagged by a run on an earlier day'. Assertions under pnpm validate pin the placement and confirm that §10's spread, the 10-within-30-days count and the 90-day tile did not move. Measured after the fix: 6 inbox messages, each to the right owner and counsel, and a second run acts on 0. Accepted trade-off: the NDA row joins #41's set on boot day (re-seed after F13: 819 ok / 1 error).",
      "tests": "pnpm verify (validate + lint + typecheck + lint:i18n-gate = the four CI steps) under os-verify-lock, at final head 7d8a059: VERDICT command-exit 0. Validate printed 'Validation passed (1239ms)', lint 6 suggestion(s) (all contract_approval), typecheck exit 0, and 'i18n gate ... 0 missing keys across 2 locale(s)'. The same run at 029c9ef and aaad12b also gave VERDICT command-exit 0. CI on 7d8a059: Validate x2 completed success. Live demo at 029c9ef (7d8a059's seed output is byte-identical: sha256 of JSON(CONTRACT_PLAN) is c58f14d9001b19be and of contractSeed is 1eaf54465270b941 on both commits): fresh DB, then README operator setup (5 named accounts), then re-seed. Run 1: notice_select 23, notice_flag 1, notice_tell 2 recipients; expire_select 1, expire_flag 1, expire_tell 2; autorenew_select 1, auto_create 1 (SUP-2026-0019, 2026-10-10..2029-10-09, renews SUP-2026-0009), auto_tell 2. Contracts: active 60->59, expired 8->9, draft 10->11. sys_inbox_message 0->6. Run 2: notice_flag 0 runs, expire_select 0, auto_existing 1 so no second draft, inbox still 6. Browser (Playwright, pre-installed Chromium): Business Requester 2 sees inbox badge 1 with the renewal notice, and clicking it opens ICA-2026-0002 with Start Renewal. Legal Counsel 2 sees badge 2 (expired + renewal). The only console errors after sign-in were the pre-existing sys_approval_request 403. Re-seed after F13: '819 ok / 1 error', contract_state_machine refusing NDA-2026-0006. Ablation, run from the committed tree with objectstack's scripts/ablation-replace.mjs under the lock: renewalFlagged '< 0' -> '<= 0', the anchor hit 1 time, blob bf1965a692ef -> 059271db73c2, and pnpm validate exited 1 with 'demo fixture: 0 unflagged active contracts with a renewal deadline of today after placing the sweep-window rows, expected 1'. The restore was proven: blob == HEAD bf1965a692ef and git diff HEAD is empty. No dist/ build is involved: validate compiles from src.",
      "mcp_calls": "0",
      "api_writes": "3 relay writes, each one repository_dispatch to objectstack-ai/objectstack executed as objectstack-fleet[bot]: (1) pr_create, POST /repos/objectstack-ai/hotclm/pulls, opening #102 as a draft; (2) assign, POST /repos/objectstack-ai/hotclm/issues/102/assignees with zhuangjianguo; (3) comment, POST /repos/objectstack-ai/hotclm/issues/97/comments, which is this report. Plus 4 git pushes (the empty branch, then 029c9ef, aaad12b, 7d8a059), which are not REST. Local-only writes against my own demo DB (port 3497): 5 users via /api/v1/auth/admin/create-user, 3 sys_user_permission_set rows, 2 sys_user_position rows, and 4 change-password calls.",
      "gates": {
        "pnpm verify @7d8a059": "VERDICT command-exit 0",
        "validate": "Validation passed (1239ms); 7 warnings, all hierarchy-security or contract_approval",
        "lint": "6 suggestion(s), 0 errors",
        "typecheck": "tsc --noEmit exit 0",
        "lint:i18n-gate": "0 missing keys across en, zh-CN",
        "CI @7d8a059": "Validate x2 completed success",
        "derivation": "hand-derived: hotclm has no dispatch-gates.mjs; .github/workflows/ci.yml runs exactly validate, lint, typecheck, lint:i18n-gate"
      },
      "line_budget": "n/a",
      "files_changed": [
        "src/data/plan-contracts.ts",
        "src/data/contract.seed.ts"
      ],
      "deviations": [
        "Commit trailers: my 3 commits carry the harness reminder's model-named pair (Co-Authored-By: Claude Opus 5.5, noreply address, plus Claude-Session). I copied it into the commits myself, but the os-dev contract says trailer pairs are model-free and the harness form is not to be imitated. History is not rewritten.",
        "Footer conflict, noted rather than resolved silently: the harness reminder asks PR bodies to end with its robot-line form, the os-dev contract asks for the session-URL footer. The PR uses the os-dev form, because the os-dev contract takes precedence over the harness reminder.",
        "The live measurement ran at 029c9ef. Final head 7d8a059 changes only comments and error text, and the seed output is byte-identical on both commits (hashes in tests). The demo was not re-run on 7d8a059.",
        "Gate list was hand-derived from hotclm package.json and ci.yml. objectstack's dispatch-gates.mjs does not apply to this repository."
      ],
      "open_questions": [
        {
          "question": "Keep the non-renewing F13 row (NDA-2026-0006) now that it puts #41's contract half on boot day? Measured: re-running pnpm demo after expiration_sweep prints 819 ok / 1 error. Non-blocking, since the lane delegates business calls to the seat.",
          "options": [
            "A keep both F13 rows (current): both §06 F13 branches send their reminder on a fresh demo; #41's eventual A/B/C resolves this row along with every other row the jobs move",
            "B keep only the auto-renewing row until #41 is ruled: no status change, so re-seed stays clean, but the expiry reminder (the core of 到期提醒) is never seen on a fresh demo"
          ],
          "recommendation": "A. M3's acceptance asks for expiry reminders in the inbox. The refusal is loud rather than silent. #41 already owns the class, and the same refusal reaches this demo anyway once it is 5 days old."
        }
      ],
      "out_of_scope_findings": [
        "carrier: #41 (open, needs-user-decision) · noted, not filed. Two measured additions to its set. (1) NDA-2026-0006 after F13: re-seed prints 819 ok / 1 error. (2) A re-seed resets ICA-2026-0002 is_expiring to 0, so the next F12 run repeats that renewal notice. Silent, and the same class (the fixture re-asserting a column a job wrote). The seat may append both to #41.",
        "class: a · reach: browser, Business Requester 2 and Legal Counsel 2 opening a contract record page on main 46e65f0, where GET /api/v1/data/sys_approval_request answers 403 PERMISSION_DENIED (console error) · evidence: Playwright NET log in this run; already listed in the #87 report's finding 3 (sys_approval_request), and #88 granted only sys_comment / sys_activity / sys_attachment · dedupe words: sys_approval_request, 403, requester, record page, Approvals tab",
        "carrier: none · noted, not filed. The seed's 18 partial instalments are planned 15 to 205 days ago, and a daily F11 would already have made them overdue. They flip on the first run. Recorded in PR Acceptance notes.",
        "carrier: none · noted, not filed. The contract page's stage path shows Draft through Signing as completed on backfilled contracts (for example ICA-2026-0002), which skipped review and approval. Adjacent to #53. Recorded in PR Acceptance notes."
      ]
    }

    Generated by Claude Code

  3. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT — PR #102, head 7d8a059 · 2026-10-10T04:31Z

    Reviewed by the repo:hotclm seat against GitHub.

    check reading
    CI on the head both Validate check-runs success on 7d8a059 = PR head.sha
    scope 2 files, src/data/plan-contracts.ts (+163/−1) and src/data/contract.seed.ts (+6/−11) — demo data only; no flow, object or governed file touched
    closing keyword Fixes #97
    premise the symptom was real, the suspected query defect was not: F12 / F13 match DESIGN.md §06; the demo gave them nothing to do (the 11 is_expiring rows are pre-flagged, so F12 skips them by design; no active contract had ended for F13) — a corrected PM premise, accepted
    fix three placed rows (a renewal-notice deadline of today; one expiring and one auto-renewing ended term), the seeded flag predicate moved to "flagged on an earlier day", and pnpm validate assertions pinning the placement and §10's spread / 30-day / 90-day counts
    measured fresh demo + manual triggers: 6 inbox messages to the right owner and counsel; a second run acts on 0; browser: the requester's badge opens the contract with Start Renewal; the ablation (< 0 → <= 0) makes pnpm validate fail with the fixture message

    Non-blocking open question — the seat's answer: A, keep both F13 rows. M3's acceptance (「到期、逾期提醒在收件箱可见」) needs the expiry reminder visible on a fresh demo; the re-seed refusal it adds is loud and belongs to #41's class, which that decision resolves for every job-moved row.

    Landing: waits on the maintainer's merge approval.

    Out-of-scope findings


    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

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions