You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
A greyed lifecycle button only says 「对此记录不可用」 — 18.3 ships an authored disabledReason, so 送审 / 发起签署 / 生效 can say what is missing #195
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/specui/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 发起签署 / 生效).
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.
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/mainfc68eb6 (@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.
{
"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."
]
}
Release: a greyed 送审 / 发起签署 / 生效 button now says what is missing (for example 「当前版本须为「清稿」,才能发起签署。」) instead of 「对此记录不可用」. State: pm:dispatched removed, assignee cleared.
Activity
objectstack-fleet commentedon Nov 3, 2026
Triaged — 2026-11-03
Filing gate ① user-visible (a greyed button gives no reason).
mainis on@objectstack/*18.3.0 since PR #198 (fc68eb6, push CI green). The fix is app-side: an authoreddisabledReasonon the lifecycle actions that already carrydisabled. State: →pm:queue.Generated by Claude Code
objectstack-fleet commentedon Nov 3, 2026
Claim: PM loop round 18
Ruling-ref: none (triaged defect, 2026-11-03)
Session:
session_017nzWFRUo2U7evMkPdVniAnAccount:
zhuangjianguo(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-195-disabled-reasonWorktree:
hotclm-issue-195Domain:
repo:hotclm(single-lane sister repo — nodomain:*)Seat:
repo:hotclm#1File surface:
src/actions/contract-lifecycle.actions.ts(disabledReasonbeside eachdisabled) ·src/translations/{en,zh-CN}/objects.contract.ts(the reason strings) — stop on breach; explain in the reportContainer & model:
S,mode:subagent,model: opus(TIER_DEFAULT; hand-derived for a sister repo),effort: mediumClause-②: 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 buttonThread-read: none
Premise: re-measured by the dev on
origin/mainfc68eb6(@objectstack 18.3.0) with the declared demo staffSerial 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
objectstack-fleet commentedon Nov 3, 2026
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
objectstack-fleet commentedon Nov 3, 2026
Ruling-ref: none (triaged defect, 2026-11-03)
Landed — PR #200 · 2026-11-03
MERGED(squash onmain), merged at its ACCEPT headacddb37;Fixes #195closes this cardRelease: a greyed 送审 / 发起签署 / 生效 button now says what is missing (for example 「当前版本须为「清稿」,才能发起签署。」) instead of 「对此记录不可用」. State:
pm:dispatchedremoved, assignee cleared.Generated by Claude Code