Repository navigation
pnpm demo stops being re-runnable once the daily jobs have run: the seed re-asserts statuses the state machines refuse to go back to #41
Description
Ruled: 6395830052 · letter A · 2026-10-25T09:14Z (A via a platform card: seed-dataset applyOn: 'create'; interim README truth)
Blocked-by: objectstack-ai/objectstack#25761
Found while browser-verifying card 09 (#39). Not a defect in the jobs — a consequence of them existing that the seed does not account for. Filed unassigned, out of scope for #39.
The documented workflow that now breaks
README.md tells the evaluator to re-run the demo:
Every dataset is an upsert, so create the accounts and run
pnpm demoagain and their contracts are handed over.
That works on a freshly seeded database. It stops working once card 09's daily jobs have run once, because those jobs are the declared writer of two statuses the fixture also declares, and the state machines refuse the way back.
Reproduction, measured on claude/issue-39-post-signature-jobs @ 83eda0a, 17.4.0, better-sqlite3
pnpm demoon an empty database —820 ok / 0 errors.- Run the sweeps once each:
POST /api/v1/automation/expiration_sweep/trigger,POST /api/v1/automation/payment_overdue/trigger. pnpm demoagain.
Boot banner on step 3:
⚠ Seeds: app.objectstack.hotclm 818 ok / 2 errors ⚠
✗ Failed to write clm_contract record #99 (title=Data Processing Agreement — Fernway Cleaning):
hook 'contract_state_machine' threw: A expired contract is closed; its status cannot
change to active. Start a renewal or an amendment instead.
✗ Failed to write clm_payment_plan record #2 (contract+seq=["…","3"]):
hook 'payment_plan_state_machine' threw: Payment instalment status cannot go from
overdue to planned. Allowed from overdue: partial, paid.
Two rows are dropped and every other row still loads, so the run looks almost clean — the same "the summary reads like a clean load" shape #39's acceptance criteria warn about.
Why it happens
The fixture writes status as a literal on every upsert. Once a job has moved a row on:
expiration_sweep(F13) moves anactivecontract past its end date toexpired. §03 makesexpiredterminal, so re-asserting the fixture'sactiveis refused.payment_overdue(F11) moves adueorpartialinstalment past its planned date tooverdue. §03 givesoverdueonly→ partial/→ paid, so re-assertingplannedis refused.
Both refusals are correct: the state machines are doing exactly what DESIGN.md §03 asks. It is the fixture's unconditional status that has no answer for "this row has since moved on".
The two rows are the ones whose dates the jobs act on, so the count grows as the demo database ages: any contract that expires and any instalment that falls into arrears joins the set.
What a fix has to decide (hence: not a rider on #39)
Whichever way it goes it is a change to card 08's seed, and it needs a product answer first:
- A — leave
statusout of the upsert on re-seed. The fixture stops fighting the jobs, and a demo database shows the lifecycle actually moving. Costs the guarantee thatpnpm demorestores a known corpus. - B — re-seed onto a clean database only, and say so in the README instead of promising re-runnability. Cheapest, and honest, but it takes away the account-handover workflow the README currently recommends.
- C — keep the promise and make the seed reset the row first (
overdue → paid → …is not reachable either, so this means a system-context reset, not a transition). Most machinery, and it puts a second writer on the columns Card 09 — F9 activation · F3/F4/F10–F14 scheduled jobs · F16 executed upload (M3) #39 gave exactly one.
I have no view worth acting on between them; A looks smallest but it changes what "the demo dataset" means, which is a §10 question.
Activity
zhuangjianguo commentedon Sep 9, 2026
维护者速读
事情:README 现在告诉试用者「建好账号后再跑一次
pnpm demo,合同就交接过来了」。卡 09 的定时任务上线后,这条路只在全新数据库上还成立。任务跑过一次之后再跑 demo,会有行被拒绝。为什么:种子把
status当字面值无条件写入。而定时任务是这两个状态的唯一声明写手,状态机不许回头:active合同推到expired,而expired是终态 —— 种子再写active被拒。due/partial期次推到overdue,而overdue只准去partial/paid—— 种子再写planned被拒。两条拒绝都是对的,状态机在照 §03 干活。是种子那个无条件的
status没有「这行已经往前走了」的答案。818 ok / 2 errors,其余全部照常加载。这正是卡 09 验收标准反复警告的「摘要读起来像成功」那个形状。而且随着演示库变老,掉的行会变多 —— 任何到期的合同、任何进入逾期的期次都会加入这个集合。你要做的:回一个字母,A、B 或 C。
选项 × 真实代价
status(只在首次种入时写)pnpm demo能把库恢复到已知状态」这个保证overdue → planned走不通,所以这意味着系统上下文强改,等于给卡 09 刚刚确立单一写手的那两列再加一个写手业务含义直译
A = 演示库像一个真实运行了半年的系统,你重跑只补数据不倒转时钟;B = 演示库是一次性快照,要重来就重装;C = 演示库有一个「时光倒流」按钮,代价是有两个人能改同一块表。
四棱分析
os-decision-facets
① 项目长远合理性 — 偏 A,明确反对 C。卡 09 刚刚把「谁写
overdue/expired」收敛成唯一写手(overdueis written by these jobs only,写在卡里也写在代码里)。C 立刻再开一个写手,把刚建立的不变量拆掉,方向反了。A 是让种子退出这两列的争夺。② 实际业务拉动 — 偏 B,判据实测。今天谁撞上?试用者,在 #28 描述的那条动线上 —— 建三个账号、重跑 demo 拿合同归属。那条动线是真的(README 写着,卡 09 的浏览器验证也照做了),但它只在首次种入后立刻执行,那时任务还没跑过,所以今天没有人真的被这个 bug 挡住。拉动是潜在的,不是现行的。
③ 防 AI 犯错 — 这一棱最要紧,且三个选项都要配一件事。出错时谁看到什么:今天是⚠️ 无论选哪个,都应要求「种子写入被状态机拒绝时,启动横幅必须响亮」—— 否则演示库会静悄悄地烂掉。C 在这一棱最差:系统上下文强改会让「状态机拒绝」这个信号本身消失。
818 ok / 2 errors混在启动日志里,没有任何人会注意到,而缺的恰恰是演示库里最有意思的两行。④ 创业阶段不扩散 — 偏 B,其次 A。B 零新增(改一段 README)。A 是种子逻辑的一处收窄,也不算扩张。C 要新增一套重置机制,是 declare-and-maintain,最重。
推荐:A,回退 B。 ①③④ 都反对 C,②在 A/B 之间偏 B 但拉动是潜在的。选 A 的理由是它同时满足①和④,且保住了 #28 那条动线;选 B 的理由是最省且诚实。⛔ 不建议 C。
本分析看不见什么:你是否把「
pnpm demo幂等地恢复一个已知语料」当成一条产品承诺。如果是,A 就动了那条承诺,B 是把承诺改小,而这两者的差别只有你能定。关联
#39 / PR #42(发现处,已合并
a7b7db5)· #28(README 那条开箱动线,决策箱中)· 卡 08 的种子 ·DESIGN.md§10Generated by Claude Code
zhuangjianguo commentedon Sep 10, 2026
⛔ 不是裁决,不动标签。这条是把只存在于会话里的结论落到卡上 —— 结论只在 chat 就是半状态。
本卡的正文说:任务跑过之后重跑
pnpm demo会报错并掉两行(818 ok / 2 errors,两条状态机拒绝)。dogfood 走查(#45,main@a7b7db5,17.4.0)测到的不是这个。pnpm demo818 ok / 2 errors,两行被拒overdue → planned被状态机拒绝payment_overdue跑完后那一轮把 18 期已逾期的款静默改回去了(overdue 30 → 12)expired → active被拒expiration_sweep选中 0 行,这条路径从未被走到这为什么比原来的缺陷更严重
原缺陷是响亮的:种子撞上状态机、被拒、启动横幅上有两行错。难看,但可见,而且数据是对的。
新观察是静默的:重跑把一个每日任务刚做完的工作撤销了,
0 errors,横幅干净。演示库里「这 18 笔款逾期了」这个事实消失了,没有任何人会知道。一个安静的错误结果和一个正确结果无法区分 —— 这正是这个仓反复在防的形状。卡 09(#39 / PR #42,已合并
a7b7db5)的验收明确测到payment_plan_state_machine拒绝overdue → planned:而 #45 在同一棵树上测到同一转换被静默接受。两份读数不可能都对。 三种可能,⛔ 都还没被排除:
main: drive the whole contract lifecycle in a browser and report what a real user hits #45 那轮里那些行当时并非overdue)。第 1 种成立的话,这不只是 #41 的问题 —— 它意味着我以复核人身份验收 PR #42 时,接受了一个在种子路径上不成立的不变量。
本卡状态与下一步
⛔ 不关、不改选项、不撤卡。 但正文的复现步骤现在是未经证实的,读者不要照抄。
需要按序做两件事,然后本卡的 A/B/C 才可判:
expiration_sweep真的选中行。Dogfood pass on M3-completemain: drive the whole contract lifecycle in a browser and report what a real user hits #45 没走到这条路径,所以本卡关于expired → active的那一半既未证实也未推翻。overdue期次写成planned,从数据库读回它的状态,并同时读 hook 是否被调用。答案决定这是pnpm demostops being re-runnable once the daily jobs have run: the seed re-asserts statuses the state machines refuse to go back to #41 的选项问题,还是一张关于状态机强制面的新缺陷卡。⇒ 若第 2 项证实是路径绕过,那是一张独立的缺陷卡,且优先于本卡:本卡在问「种子该怎么和任务共处」,而那张在问「状态机到底有没有生效」。
出处:#45 的走查报告与其席位复核;读数时刻 2026-09-10T01:5xZ,树
a7b7db5。Generated by Claude Code
zhuangjianguo commentedon Sep 10, 2026
上一条我说 dogfood 观察到的「静默改回 18 期」比原报的响亮拒绝更糟,并列了三种可能。#50 的调查把它settle了:候选 (b)。⛔ 没有绕过,状态机是好的,而我那个「更糟」的定性不成立 —— 我把一条正常工作的合法边说成了缺陷。
真正在发生的事
未改动的种子语料里,
payment_overdue只能动那 18 行partial:arrears 级选due/partial且过了planned_date,而 150 行 fixtureplanned的日期全在 +35 天以后,planned→due 那一级选中 0。那 18 行的 fixture 目标值就是partial,所以重跑把它们从overdue写回partial—— 而overdue → partial是你裁的 #10 → 2A 明确声明的合法边。⇒ 「18 行被改回、0 报错」是一台正常状态机的正确输出。
而卡 09 那次拒绝来自它自己造的探针行(fixture 值为
planned、被回拨日期推到overdue),overdue → planned确实被拒。#50 重造了那个探针,拿到卡 09 的报错原文与818 ok / 2 errors。两次都对,测的是不同的行。逐行证据(全部 300 行按 id 快照、逐行 diff 而非看总数):A→B 恰好 18 行变,全是
partial → overdue;B→C 同一批 18 个 id,全是overdue → partial,断言了集合相等。且 upsert 会跳过已与 fixture 相等的行(inserted 0, updated 18, skipped 802),所以 820 行里只有那 18 行被真正写过。这对本卡的三个后果
① 正文的复现步骤仍然未经证实,但原因变了。 它描述的
818 ok / 2 errors需要一行语料里不存在的行 —— 卡 09 造的那种。在未改动的演示库上,重跑 demo 是干净的,且只会沿合法边把那 18 行写回。⇒ 正文该改写成这个形状。② 新增一条抬高代价的事实,属 A/B/C 权衡的输入:被拒的种子记录是被整行丢弃的。 #50 的探针 A 里,被回拨的⚠️ 也就是说:fixture 行里一个非法状态,会静默连带损失那一行的其它列。选项 C(让种子先重置行)本来看着最保守,这条事实让它更贵;而选项 A(重跑不写
planned_date连同状态一起没写进去。status)因此更有吸引力 —— 它把整类整行丢弃的风险一起移走。③ 「无声」这个论点要从 A 的理由里撤掉。 我上一条把静默无报错当成 A 的论据。那是错的:静默是合法边的正常表现,不是隐患。A 的理由现在只剩两条 —— 卡 09 刚把
overdue/expired收敛成单一写手(C 会再开一个写手,方向相反),以及整行丢弃的代价。仍然缺的那一半,⛔ 不要当成已测
expiration 那半边(
expired → active)依然未被走到。 #50 只做了付款侧;dogfood 那次expiration_sweep选中 0 行。⛔ 本卡关于到期合同的那一半既未证实也未推翻,别照抄。⇒ 本卡出决策箱之前该先把那半边测掉,否则 A/B/C 是在半份事实上选。
一条与本卡相邻、影响读者判断的事实
#50 顺带测出:面向人的种子横幅本身是不可靠的那一面,不是 loader 的计数器。 第一次启动时内联 seed 超了 8000ms 预算转入后台,
Seeds: … 820 rows那一行从未打印,而 seed 在Server is ready之后还写了 3.5 分钟。权威的是后来那条WARN [Seeder] Seed loading completedJSON。任何基于「重跑后横幅说了什么」的论证都要改用 loader 的 JSON。(也因此顺带解释了 #49 的 dev 为何只看到 0 条
ERROR [SeedLoader]而 dogfood 看到 120 条 —— 同一个脚本、不同的预算结局。)出处:#50(已关闭,调查完成)· 读数时刻 2026-09-10T07:1xZ · 树
a7b7db5Generated by Claude Code
objectstack-fleet commentedon Oct 10, 2026
Evidence from the 17.7.0 browser pass · 2026-10-10T02:47Z — #87, suspect 6. The failure has changed shape on 17.7.0:
pnpm demoafter the daily jobs ran: seed summary{"inserted":0,"updated":18,"skipped":801,"errored":1}.Failed to write clm_contract record #104 (Lease Agreement — Granite Facilities): A terminated contract is closed; its status cannot change to active— a contract legal terminated during the run.payment_overdue's work — 18 part-paid instalments go fromoverdueback topartial, becauseoverdue → partialis an allowed transition. Overdue drops from 30 to 12 and nothing says so.overdue → plannederror this card quoted does not appear on 17.7.0.So the re-run no longer fails loudly on the jobs' instalments; it quietly undoes them. Relevant to the options here, and to #82 (whether
pnpm demoarms the daily jobs at all).Generated by Claude Code
docs(data): record the measured #41 interaction and scope the boot-da…
objectstack-fleet commentedon Oct 10, 2026
Two more measured additions to this card's set · 2026-10-10T04:32Z — from #97 (PR #102, 17.7.0):
is_expiring, and five of the six daily flows reportacted: 0while they notify #102's placed rows, re-runningpnpm demoafterexpiration_sweephas run prints819 ok / 1 error—contract_state_machinerefuses to move NDA-2026-0006 fromexpiredback toactive. Loud, same class.is_expiringto0, so the next F12 run sends that renewal notice again. Silent — the fixture re-asserting a column a job wrote, like the 18overdue → partialreversals measured in Full browser test on 17.7.0main: drive the whole contract lifecycle as every audience, in en and zh-CN, and report what a real user hits #87.Generated by Claude Code
The renewal-notice and expiration-sweep jobs produce nothing although…
zhuangjianguo commentedon Oct 25, 2026
Ruling: batch #2 item 5 · letter A · maintainer 「同意」 2026-10-25T09:14:04Z
裁定:A —— 任务写过的列重种时不再覆盖;走平台,期间 README 说真话
维护者在第 2 批决策箱回了「同意」(= 推荐项 A,回退 B)。裁决文档:https://claude.ai/artifact/X4sZxhLrEYshLjkgYp4svr 。
鲜度门:正文 2026-09-09T17:00Z;评论五条,最后一条 2026-10-10T04:32Z(#97 的两条新增读数)。录裁前重读,无变化。⚠️ 正文的复现步骤已被评论 5614657372 推翻,读者不要照抄;今天的事实形状是:未改动语料上重跑干净但把 18 期
overdue → partial静默改回(合法边);terminated → active、expired → active各响亮拒绝 1 行;is_expiring复位导致 F12 续签提醒重发(静默);被拒的种子行整行丢弃(#50)。为什么走平台:同样的需求 hotsrm 先撞上,维护者在 objectstack#25577 裁了 B(每列
applyOn: 'create' | 'always'),PR #25664 于 2026-10-24 合并。但它落在 import 门(packages/core/src/utils/import-runner.ts、packages/rest/src/import-prepare.ts),seed loader(packages/runtime/src/seed-loader.ts)没有这个列策略。去重:#25577 / #25475(import,已关)、#8740(driver 内部,开);seed 数据集的为 0。裁后执行
applyOn: 'create'延伸到 seed 数据集的列),回链见下一条评论;本卡Blocked-by它。pnpm demo只在干净库上有「恢复已知语料」的保证;任务跑过之后重跑会沿合法边把任务写过的列改回,且被状态机拒绝的行整行不写。搭车Refs #41,纯文档。status、is_expiring、各阶段时间戳等 —— 以卡 09 的「单一写手」清单为准)打applyOn: 'create',README 改回「建账号 → 重跑 → 交接」的承诺。⛔ 本席不动标签;lane 席位派发时转标签并带
Ruling-ref:。Generated by Claude Code
zhuangjianguo commentedon Oct 25, 2026
Platform card filed per the A ruling above: objectstack-ai/objectstack#25761 — seed-dataset columns take the import door's
applyOn: 'create'(#25577 / PR #25664), so a re-seed leaves job-written columns alone. Class ③, unlabelled, awaiting triage there.Blocked-by: objectstack-ai/objectstack#25761 (the README truth edit is not blocked and can go now,
Refs #41)Generated by Claude Code
objectstack-fleet commentedon Oct 25, 2026
Out of the decision box — Ruling-ref: comment 6395830052 (batch #2 · maintainer 「同意」).
needs-user-decision→pm:blocked,Blocked-by: objectstack-ai/objectstack#25761(seed-datasetapplyOn: 'create').pnpm demo) is not blocked: the seat dispatches it now as aRefs #41docs PR; the card stayspm:blockedfor the column policy.Generated by Claude Code
5 remaining items
objectstack-fleet commentedon Oct 27, 2026
Unblocked — 2026-10-27
closed493a6c4is an ancestor of tag@objectstack/spec@18.2.0mainnow pins@objectstack/*18.2.0 (PR #155, merge21f2319, push CIValidatesuccess), so the fix is installable in this repo. The ruling recorded in the body stands; this card returns to the queue for dispatch. The dev re-measures the premise onmainbefore writing code.State:
pm:blocked→pm:queue.Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
Claim: PM loop round 17
Ruling-ref: 6395830052
Session:
session_017nzWFRUo2U7evMkPdVniAnAccount:
zhuangjianguo(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-41-seed-apply-on-createWorktree:
hotclm-issue-41Domain:
repo:hotclm(single-lane sister repo — nodomain:*)Seat:
repo:hotclm#1File surface:
src/data/**(applyOn: 'create'on the job-written columns per card 09's single-writer list) ·README.md(restore the re-run promise) — stop on breach; 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 demo (pnpm demostays re-runnable after the daily jobs ran) | objectstack-ai/objectstack#25761 shipped in 18.2.0 | everyone who re-runs the demoThread-read: 6437391562
Premise: re-measured by the dev on
origin/main0159171(@objectstack 18.2.0) with the declared demo staff (PR #171)Serial constraints cleared: #156 landed (PR #170, flows) and #28 landed (PR #171, config / README); round 17 dispatches #43, #160 and #41 together on disjoint files; in flight #169 (lifecycle actions). #19 (seeds) follows #41; #99, #161, #162 (launch wizard) follow.
Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
os-dev-report
{ "issue": 41, "status": "done", "branch": "claude/issue-41-seed-apply-on-create", "pr": "https://github.com/objectstack-ai/hotclm/pull/176", "session": "session_017nzWFRUo2U7evMkPdVniAn", "premise_still_valid": true, "summary": "Ruling 6395830052 letter A, step 3. On the 18.2.0 key `columns.FIELD.applyOn: 'create'`, the demo datasets now declare 24 lifecycle columns create-only. clm_contract has 18: status, is_expiring, is_backfilled, route_* x4, approval_status, the seven stage stamps submitted_at..closed_at, termination_reason, archive_no, archived_at. clm_obligation has status and completed_at. clm_payment_plan has status, actual_date, actual_amount and invoice_no. The set starts from the single-writer family contract.object.ts documents (state machine plus F2/F5/F9-F14, which includes card 09's jobs) and adds the columns written in the same write as a status transition, so a re-run cannot split a status from its stamps. owner_id and legal_owner stay always. README restores the re-run promise with three stated limits: other edited columns revert; decided deviations and signature rounds are not covered; lifecycle stamps keep their dates while fixture dates slide. The stale 'operator creates the accounts and runs pnpm demo again' comments in keys.ts, contract.seed.ts, negotiation.seed.ts and plan-contracts.ts are rewritten for PR #171's platform-created demo staff. Measured on main 0159171 and on the branch with one identical sequence: fresh demo, all six daily jobs fired, four persona desk actions plus two deletes, re-run. main: {inserted 2, updated 20, skipped 805, errored 3}, refusing terminated->active, expired->active and paid->due, with 18 overdue->partial reversals, is_expiring reset and the archive undone. Branch: {inserted 2, updated 0, skipped 828, errored 0}, every job and desk value kept, the deleted rows restored. On the next tick F12 re-sent on main (renewal notices 1 -> 2, payment_overdue 18 -> 36) and sent nothing on the branch (1 and 18). The daily jobs could not be started on demand on 18.2.0 (403, see findings). As the seat directed, they were fired by an uncommitted measurement-only cron override ('* * * * *' at src/flows/_daily-sweep.ts:108), reverted before each re-run and before the commit; git diff HEAD -- src/flows is 0 bytes.", "tests": "No unit-test surface in this metadata-only app; no ablation (seed fixture and docs). Evidence is the end-to-end measurement above. Logs: scratchpad issue-41/{main-r1,main-r2,main-r3,br-r1,br-r2,br-r3,br-r4}.log; row snapshots {main,br}-{B,C,D}.json; per-row diffs from diff.mjs (main B->C: archive_no/archived_at x1, is_expiring true->false x1, payment status overdue->partial x18, new x2; branch B->C: new x2 only). Persona reads in Chromium zh-CN through the Console sign-in on the branch after the re-run: finance@ overdue 30, partial 0; counsel2@ Cobalt MSA terminated with reason and closed_at, Basalt NDA expired; records@ Beacon expired ARC-41-TEST with archived_at. Console errors were only the pre-login 401 session probe (plus one 404 resource for finance). NOT MEASURED: a requester marking an obligation done (PATCH as requester2@ answered 403 'update on clm_obligation requires edit access to its master record'); no alternate route was taken.", "gates": "local, worktree hotclm-issue-41; the bytes were then committed unchanged as ab8a2af; each exit was captured to a file before any pipe: pnpm install exit 0; pnpm validate exit 0 ('✓ Validation passed (1104ms)'); pnpm lint exit 0 ('6 suggestion(s)', 0 warnings, none in src/data); pnpm typecheck exit 0; pnpm lint:i18n-gate exit 0 ('COVERAGE : 0 missing keys across 2 locale(s)'); CLM_DEMO_SEED=1 pnpm validate exit 0 ('✓ Validation passed (1341ms)', parses the 24 columns keys through defineSeed/SeedSchema). CI on PR #176: not read at report time.", "dogfood_battery": "n/a — sister repo; no ! in the PR title and no (narrowing) arm", "mcp_calls": "0", "api_writes": "2 — fleet-write relay pr_create (dispatch fw-20261027T111439Z-34a1b8, run 40494672991 success, hotclm PR #176, body read back identical 9078 bytes, assignee zhuangjianguo); this os-dev-report comment via post-stamped (POST /repos/objectstack-ai/hotclm/issues/41/comments). Plus git push of the branch (not REST). The demo-local REST writes against localhost:3153 (persona actions, deletes) are not GitHub writes.", "open_questions": [], "out_of_scope_findings": [ "class: b · reach: public door, measured: POST /api/v1/automation/payment_overdue/trigger (and the other five daily sweeps) as the platform dev admin on @objectstack 18.2.0 answers 403 PERMISSION_DENIED 'This caller may not start this flow. A flow that runs on its own trigger starts there, or as a sub-flow from a parent flow's `subflow` node.' · evidence: runtime flow-start-admission.ts isElevatedSelfTriggered (objectstack#25643, f1ddace887) refuses any non-system caller for runAs:'system' schedule flows, and no capability opens it; IJobService.trigger()/replay() have no HTTP or CLI door, and a missed run is never replayed. Consequence: an operator or evaluator cannot run a system-run scheduled flow on demand (cards #39/#87/#97 measured with /trigger on 17.x; on 18.2 the only way is the cron itself) · Seam: spec:Flow.runAs+type schedule → runtime:flowStartRefusal at POST /automation/:name/trigger · dedupe words: scheduled flow run now, trigger 403 runAs system schedule, flow-start-admission elevated self-triggered, job service trigger HTTP, replay missed schedule · the seat decides whether to file it", "class: (none — not measured) · residual of #41's class not covered by the ruling's job-written columns: a re-run re-asserts clm_deviation.status and clm_signature.status, so a deviation decided or a signature round advanced by a user on a seeded row would be re-asserted to its fixture status and possibly refused (deviation_state_machine: decided once). Not measured; stated as a limit in the README · carrier: noted in PR #176 Acceptance notes, not filed", "carrier: noted, not filed — clm_review.reviewer still names the Dev Admin although Legal Counsel 1/2 exist at seed time since PR #171. Not changed: the right reviewer depends on the review stage (legal/compliance → counsel, finance → Finance Controller, business → requester), and scripts/demo.mjs (outside src/data) mirrors DEMO_USER as its pre-seed check. Comments in keys.ts and negotiation.seed.ts now say it is open.", "carrier: #64-family (controlled_by_parent edit) · noted, not filed — requester2@example.com cannot mark its own obligation done: PATCH /api/v1/data/clm_obligation/:id {status:'done'} answers 403 'requires edit access to its master record (master clm_contract not editable by this user (row-level security))' (the obligation's owner, dealt the contract's requester); may be the known controlled_by_parent shape (#64)" ], "governed_text_proposal": "none" }objectstack-fleet commentedon Oct 27, 2026
Ruling-ref: comment 6395830052 (letter A), step 3
Landed — PR #176 · 2026-10-27
MERGED(squash onmain), merged at its ACCEPT headab8a2af;Fixes #41closes this cardRelease: running
pnpm demoagain no longer walks back what the jobs and desks did. Statuses, stage stamps, approval routing and payment actuals stay as they are, and the fixture's own dates still slide forward. State:pm:dispatchedremoved, assignee cleared.Generated by Claude Code