Skip to content

Launch wizard asks everything before writing, picks the parent contract, makes the submit choice explicit; Start Renewal lands on its draft - #180

Merged
zhuangjianguo merged 4 commits into
mainfrom
claude/issue-99-launch-wizard
Oct 27, 2026
Merged

zhuangjianguo merged 4 commits into
mainfrom
claude/issue-99-launch-wizard

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #161
Fixes #162
Part of #99 (items 3 and 4)

Clause-②: no
Metadata-protocol: none

Four changes to the F1 launch wizard and the renewal hand-off, on @objectstack 18.2.0. Each one is measured in the browser below, before and after.

What changed

Files: src/flows/contract-intake.flow.ts, src/actions/contract-lifecycle.actions.ts (start_renewal only), src/flows/renewal-notice.flow.ts (one seat-approved line), and src/translations/{en,zh-CN}/flows.ts.

Browser evidence

Setup: pnpm demo:zh -- --port 3154 on a fresh .objectstack/data for each boot, and Chromium /opt/pw-browsers/chromium in zh-CN at 1440x1000. Personas are the declared demo staff with password admin123. The only manual step was set-user-manager for requester1-3, which answered 200 x3. Every boot read Plugins: 44 loaded, with no degraded and no no such table.

Before (origin/main 475106f), as requester1@example.com unless noted:

After. The full set ran on 9c4779d. After merging main again (#176, #177, #178: backfill, email-template and data files only), the head bdabe1e re-ran the abandon count, draft, renewal and action-door probes with the same results.

  • Item 4: NDA wizard as requester1, filled through every screen including the upload, then closed at the last screen (提交方式). contracts=120 drafts=10 parties=40 before and after. The run stays paused. The uploaded file is left as an unowned sys_file (ref_object null).
  • Item 4, new counterparty: a wizard with a new counterparty typed in, closed at the last screen, left parties=41 before and after. Completing the same path created the party and the contract together.
  • Item 4, headless: a launch with no file answered paused at screen_document fields=templateAvailable:boolean,draft_from_template:boolean,first_version_file:file*, and counts were unchanged. Resuming with a URL answered 400 INVALID_SCREEN_INPUT and wrote nothing. Resuming with the uploaded id completed the run, wrote one draft with v1, and the file was claimed (ref_object clm_contract_version, ref_field file).
  • Two launch-wizard steps ask nothing useful: 「首个版本」 is an empty page for a type with no template, and 「提交合同」 is a lone checkbox whose button says 提交 either way #162 (1): 首个版本 on NDA shows 文件 * with the upload widget. On 订单, with a template set on the local DB only: 从模板起草 is shown, and ticking it hides the upload. The run wrote v1 as Drafted from the contract type template. with order-form-template.pdf. A headless draft_from_template on 订单 also completed with no screen.
  • Two launch-wizard steps ask nothing useful: 「首个版本」 is an empty page for a type with no template, and 「提交合同」 is a lone checkbox whose button says 提交 either way #162 (2): pressing 提交 with nothing chosen toasted 「请填写以下必填字段:提交方式」 and sent no resume. 「先保存为草稿」 leaves a draft with v1. 「现在提交给法务 / 审批」 lands in_review. In en the same screen reads "Submission" with "Submit to legal / approval now" and "Save as a draft for now".
  • The launch wizard asks a requester to type the parent contract's record id (SOW, amendment) — a flat screen field can be a lookup since 18.x #161, as counsel1@example.com on SOW: 主合同 * is a picker (BUTTON), and the popover lists contracts by title, number and counterparty. The pick (SUP-2026-0007) landed in parent_contract on SOW-2026-0026. As requester1 on 补充协议, picking SOW-2026-0016 landed in parent_contract on AMD-2026-0005.
  • Item 3, as requester1: 发起续签 on an active SOW opened /record/zVlHPstXPKc_eJUo, which is SOW-2026-0025, a draft with renewed_from set to the source. The response carried output.renewal.id. A second press was refused with 「这份合同已有续签草稿(SOW-2026-0025)…」 and stayed on the source record.
  • Refused ends over the action door (blocked party, missing party, unknown type) still answer refused and write nothing (counts unchanged). The department and entity pickers are unchanged: a run with 发起部门 picked stored both our_entity and department.
  • Browser console on every page: the same 404 and 401 before sign-in as before, plus the pre-existing first-render No such key: status predicate warnings on header actions. Nothing new.

Gates (bdabe1e)

Each exit code was captured before any pipe:

  • pnpm install: 0
  • pnpm validate: 0 (✓ Validation passed)
  • pnpm lint: 0 (6 suggestion(s), 0 warnings, same as main)
  • pnpm typecheck: 0
  • pnpm lint:i18n-gate: 0 (COVERAGE : 0 missing keys across 2 locale(s))
  • CLM_DEMO_SEED=1 pnpm validate: 0

Acceptance notes

  • Closing the dialog leaves a paused run and, if a file was uploaded, an unowned sys_file. This is the platform's behaviour per objectstack#25801's acceptance notes (cancel on close is an open product decision upstream). No record is left behind.
  • A renewal draft's title starts with the English word "Renewal —" under zh-CN (clm_renewal_draft). This is pre-existing and not touched here.
  • The header comment of src/actions/contract.actions.ts still says the flat screens have no record picker. The file was left alone because the wizard's inputs did not change. The four dialog pickers still belong there, for the reasons the flow header now gives.
  • objectstack#26578 is the platform's per-step 「已保存 — 下一步」 toast and 提交 wording, unchanged here.

🤖 Generated with Claude Code

https://claude.ai/code/session_017nzWFRUo2U7evMkPdVniAn

… draft

F1 now collects the counterparty, the first version's file (a `file`
screen field, objectstack#25801) and an explicit submission choice before
its first write, so a wizard closed part-way leaves no draft; the
object-form `screen_upload` step is gone. The parent contract is a record
picker (`type: 'lookup'`). Start Renewal navigates to the draft it made via
a flow action's `onSuccess` (objectstack#25800), reading the renewal flow's
new `renewal` output variable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nzWFRUo2U7evMkPdVniAn
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nzWFRUo2U7evMkPdVniAn
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nzWFRUo2U7evMkPdVniAn
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 — ACCEPT · head bdabe1e · 2026-10-27T11:44Z

check reading
shape draft → main, Fixes #161 + Fixes #162 + Part of #99 (items 3 and 4); mergeable clean, with main (#176, #177, #178) merged in
CI on the head both Validate check-runs success on bdabe1e = PR head.sha
scope 5 files (+142/−106): the F1 wizard in contract-intake.flow.ts and its translations; start_renewal's onSuccess navigate; and the one seat-approved line in renewal-notice.flow.ts (renewal declared isOutput). contract.actions.ts is untouched. Nothing governed; lint 0 warnings
item 4 (ask everything, then write) measured. Closing the wizard at its last screen, with every screen filled, left contracts 120 / drafts 10 / parties 40 (and 41 on the new-counterparty path) before and after. On main an NDA closed at 上传首个版本 had left an orphan draft with version_count 0. The first-version file is a screen file field (objectstack#25801). A headless launch with no file now pauses instead of writing
item 3 (go to the renewal) measured as requester1: 发起续签 opens the new draft (SOW-2026-0025, renewed_from set). A second press shows the existing refusal and stays put
#161 parent_contract is a record picker. Measured as counsel1 (SOW → SUP-2026-0007) and requester1 (AMD → SOW-2026-0016)
#162 the first-version step is never empty (the file is required unless the type's template is chosen). 「提交方式」 is a required choice with no default: pressing 提交 without a choice is refused client-side, and each choice lands as draft or in review. Its values are booleans, so the headless param is unchanged
residuals when the dialog closes, the run stays paused, and a file uploaded before closing stays unowned. objectstack#25801's second half carries this, and no record is written. The renewal draft's English 「Renewal —」 title prefix under zh-CN predates this PR; the seat files a card for it

Landing: under the maintainer's merge authorization (project thread: 「你可以自己审核的就自己合并」). With this PR, every item of #99 has landed (1, 2, 5, 6 earlier; 7 in PR #177; 3 and 4 here), so the seat closes #99.


Generated by Claude Code

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