Skip to content

A greyed lifecycle button only says 「对此记录不可用」 — 18.3 ships an authored disabledReason, so 送审 / 发起签署 / 生效 can say what is missing #195

Closed

Description

@objectstack-fleet

repo:hotclm#1 · zhuangjianguo · session_01QsR2jUw8KJgAwuwk6sqYLD

Filing gate: ① user-visible defect, reproduced in the browser on @objectstack 18.3.0 (hotclm 18.3 upgrade pass).

Symptom. Since PR #173 the contract header's lifecycle buttons stay greyed until they can succeed. Hovering a greyed one tells the user nothing: on NDA-2026-0021 (in review, no passed review yet) 送审 shows only the platform default 「对此记录不可用」. The lawyer has to guess that a passed legal review and a current clean version are missing.

What changed upstream. objectstack#26619 (ruled A, closed) shipped in 18.3: an action may declare disabledReason, translated at objects.OBJECT._actions.ACTION.disabledReason or inline (@objectstack/spec ui/action.zod.ts ~L908; a blank string is refused). hotclm declares none today.

Scope. Each greyed-capable action in src/actions/contract-lifecycle.actions.ts (submit, accept, send_for_approval, start_signing, activate, terminate, start_renewal, withdraw) gets a reason that names the missing condition, in both bundles. Browser-verify the hover text as a real persona (counsel1 for 送审, records for 发起签署 / 生效).

Evidence: /mnt/project-files/hotclm-objectstack-18-3-upgrade/18-legal-new-version-disabled-reason.png.

Activity

  1. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    Triaged — 2026-11-03

    Filing gate ① user-visible (a greyed button gives no reason). main is on @objectstack/* 18.3.0 since PR #198 (fc68eb6, push CI green). The fix is app-side: an authored disabledReason on the lifecycle actions that already carry disabled. State: → pm:queue.


    Generated by Claude Code

  2. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 18
    Ruling-ref: none (triaged defect, 2026-11-03)
    Session: session_017nzWFRUo2U7evMkPdVniAn
    Account: zhuangjianguo (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-195-disabled-reason
    Worktree: hotclm-issue-195
    Domain: repo:hotclm (single-lane sister repo — no domain:*)
    Seat: repo:hotclm#1
    File surface: src/actions/contract-lifecycle.actions.ts (disabledReason beside each disabled) · src/translations/{en,zh-CN}/objects.contract.ts (the reason 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 lifecycle buttons (a greyed button says what is missing) | none | every requester, lawyer and desk that meets a greyed button
    Thread-read: none
    Premise: re-measured by the dev on origin/main fc68eb6 (@objectstack 18.3.0) with the declared demo staff
    Serial constraints cleared: 18.3.0 landed (PR #198). Dispatched together on disjoint files: #195 (lifecycle actions), #197 (demoStaff, README, demo script), #157 (child-name mirror), #31 (SLA field, datasets, dashboards); #195 and #31 both add translation keys to objects.contract.ts and rebase before their PRs.


    Generated by Claude Code

  3. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 195,
      "status": "done",
      "branch": "claude/issue-195-disabled-reason",
      "pr": "https://github.com/objectstack-ai/hotclm/pull/200",
      "session": "session_017nzWFRUo2U7evMkPdVniAn",
      "premise_still_valid": true,
      "summary": "send_for_approval, start_signing and activate_contract, the only three lifecycle actions that declare disabled, now declare an authored disabledReason. The reasons are in en and zh-CN at objects.clm_contract._actions.ACTION.disabledReason, and each mirrors the contract.hook.ts refusal for the same guard. Spec 18.3.0 (ui/action.zod.ts L907-936, L1710) defines disabledReason as an I18nLabel: a non-blank string or an inline locale map, translated through translateAction. It is display only and is not an expression, so it cannot tell which half of an OR predicate failed. Send for Approval's reason therefore names both conditions. The five other actions the card lists declare no disabled, so a reason on them would never show; none was added. The transition() comment that said ActionSchema had no key for a reason is rewritten. File surface: contract-lifecycle.actions.ts and translations en/zh-CN objects.contract.ts only. main has not moved since fc68eb6, so no rebase was needed.",
      "tests": "Browser: Chromium /opt/pw-browsers/chromium, pnpm demo:zh -- --port 3164 on a throwaway DB, @objectstack 18.3.0, each reading signed in as the persona. BEFORE (fc68eb6): counsel1 on NDA-2026-0003, 送审 disabled=true, tooltip and aria-describedby '对此记录不可用'. records on NDA-2026-0007, 生效 disabled=true, '对此记录不可用'. records on DPA-2026-0001 (approved, counsel2 filed a redline so current clean=0), 发起签署 disabled=true, '对此记录不可用'. AFTER (acddb37): counsel1 zh-CN, 送审 disabled=true, tooltip = describedby '须有一条结论为「通过」的法务审查,且没有未决偏离,才能送审。'. en-US shows 'An approved legal review is required, and no deviation may still be open, before the contract enters approval.' counsel1 approves the review (counts 1/1): still disabled with the same reason. counsel1 accepts the deviation (0/1): disabled=false, no tooltip. records zh-CN, 生效 disabled=true '须先上传一份「最终签署版」版本,才能生效。'; en 'A Final Signed version is required before activation.' records files a final_signed version: disabled=false. records zh-CN, 发起签署 disabled=true '当前版本须为「清稿」,才能发起签署。'; en 'A current Clean version is required before signing.' counsel2 files a clean version: disabled=false. Condition changes were made through REST /api/v1/data as the persona (200); button readings were taken in the browser. One 404 and one 401 resource error appear in the console on every load, before and after alike. No ablation: no tested behaviour changed (metadata copy only).",
      "gates": "head acddb37, exit codes captured before any pipe: pnpm install EXIT=0; pnpm validate EXIT=0 '✓ Validation passed'; pnpm lint EXIT=0 '18 warning(s), 6 suggestion(s)', the same as main (17 #196 + 1 #64), no new warning; pnpm typecheck EXIT=0; pnpm lint:i18n-gate EXIT=0 '✓ i18n gate', 0 missing keys across 2 locales; CLM_DEMO_SEED=1 pnpm validate EXIT=0 '✓ Validation passed'. PR #200 CI: in_progress at report time, not waited on.",
      "dogfood_battery": "n/a: hotclm, no ! in the title and no (narrowing) arm",
      "mcp_calls": "0",
      "api_writes": "2 relay writes (fleet-write dispatch): pr_create objectstack-ai/hotclm#200 with its assignees leg (POST pulls, POST issues/200/assignees), and the os-dev-report comment POST issues/195/comments. git push (1, not REST).",
      "open_questions": [],
      "out_of_scope_findings": [
        "class: a (user-visible truncation) · reach: console record page at a 390px viewport, as counsel2 on ICA-2026-0004: the greyed Send for Approval tooltip is 727px wide on one line, so it runs off the right edge and the reason is cut off after '…no deviation may'. At 1024px and 1400px it fits. Seam: spec:ActionSchema.disabledReason → renderer:objectui packages/app-shell/src/views/DeclaredActionsBar.tsx TooltipContent, which has no max-w class, while HomePage.tsx's disabled-reason tooltip uses max-w-xs. Repo for the issue: objectstack-ai/objectui. Dedupe words: disabledReason tooltip wrap, DeclaredActionsBar TooltipContent max-w, tooltip clipped mobile, greyed action reason truncated",
        "carrier: noted in PR #200 Acceptance notes · the activation hook's second guard (signature round formalities_done covering execution_formalities) is still not mirrored in disabled (a summary filter cannot express it), as documented before. The activate_contract reason never names it. Not filed."
      ]
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling-ref: none (triaged defect, 2026-11-03)

    Landed — PR #200 · 2026-11-03

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

    Release: a greyed 送审 / 发起签署 / 生效 button now says what is missing (for example 「当前版本须为「清稿」,才能发起签署。」) instead of 「对此记录不可用」. 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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions