Skip to content

feat(core): bind @-workflow confirms to a real WorkflowRun of the chosen snapshot - #114

Merged
EricWvi merged 38 commits into
ora-space:mainfrom
Zpc001:feat/374-workflow-snapshot-confirm
Oct 21, 2026
Merged

EricWvi merged 38 commits into
ora-space:mainfrom
Zpc001:feat/374-workflow-snapshot-confirm

Conversation

@Zpc001

@Zpc001 Zpc001 commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Refs ora-space/circus#374

承接 cloud#71(creegon2/cloud:feat/158-workflow-snapshot-confirm,最后 head 6699540)。cloud#71 来自 creegon2 的 fork,本人没有该 fork 的写权限,因此从同一历史在本人 fork 续作并开本替代 PR;cloud#71 的提交、审查与测试历史(运行 circus#158)继续有效,本 PR 确立后 cloud#71 由 owner 或作者关闭,避免两个 PR 同时推进。

Issue 里 @ Workflow 点 Confirm 时,按所选发布版本创建唯一的 WorkflowRun,并与 IssueRun 稳定关联;直接启动、manual workflow IssueRun 和 @ 确认走同一个创建函数 insertWorkflowRun;调度器推进 WorkflowRun 时,状态同步投影回关联的 IssueRun。已适配 main 上的运行身份与真实会话执行。fixtures=false 的真实 Node 联合验收仍未交付,补做时与 circus#77 的验收范围协调。

相对 6699540 的增量

  • Confirm 只按所选版本校验(owner 2026-10-20 在 circus#158 的结论):删除活稿与所选版本的字段比较和 409 workflow_version_fields_changed 门禁,liveFormDescriptor、workflowFieldDivergence 失去唯一调用点后一并删除;前端删除对应提示路径,协作文档与组件 README 改为「所选版本自身的 schema 是唯一依据」。集成测试改为:选字段与活稿不同的旧版本可按该版本通过;缺该版本必填字段返回 required_field_missing;提交该版本未声明的字段返回 invalid_field_value。
  • @ 表单的默认视图与 Confirm 同源(owner 2026-10-21 选定选项 A):前端先读活稿只为定位平台版本选择器及其默认版本(最新已发布版本),确定后初次打开就按该版本读取 GET …/snapshots/:snapshotId/form 渲染,切换版本按新版本重新读取。显示的字段与 Confirm 校验的 schema 因此始终来自同一版本,活稿里未发布的字段不再出现在默认视图。新增 TestWorkflowInteractionComposer 用例:默认视图显示最新发布版本的字段,Confirm 提交带该 snapshotId 并通过。同步做的非阻塞项:assist 按同一版本描述判断提交值;workflow_collaboration.go 的过期注释更新;faultParam 让 Confirm 的字段拒绝提示具体字段名(请填写必填项:<label>、字段「<label>」的取值不合法…)。
  • 迁移编号改为 0056:追平 main df9799c5 后,cloud#119 先合并并占用了 0055_workflow_run_workspace_release.sql,按「先合先得」本 PR 的迁移顺延为 0056_workflow_invocation_reference.sql,两份迁移 README 的序号表与文件数(58)同步更新。与 0052 的顺序仍有意义:0052 只结算 queued/dispatched,0056 结算其余未链接的非终态行(running、deferred、以及软删除的 queued),因为 0056 的 CHECK 无条件 VALIDATE 要求所有非终态 workflow 行带引用。TestMigration0052LegacyWorkflowIssueRunSettlementAppliesFreshAndUpgrades 因此拆成两段断言:仅应用 0052 时它自己的效果不变;应用完整序列后固定 0056 的追加结算。
  • 0056 不再重复建唯一索引:复合外键直接引用 0044 已建的 workflow_run_tenant_identity,两份迁移 README 同步。
  • linked IssueRun 投影用例:这些用例走真实的调度结算与数据库路径,但 Node 由 fake 会话驱动,不是 fixtures=false 的联合验收。Confirm 建立关联后、下一轮调度前取消 → IssueRun cancelled、started_at 为 NULL、没有 run.started;Node 不可达 → IssueRun failed、带上运行的时间戳与原因。
  • 已把 main df9799c5 合并进分支,冲突只在两份迁移 README:main 的 0055_workflow_run_workspace_release.sql 保留,本 PR 的迁移顺延为 0056,文件数更新为 58。

改动

  • Confirm / manual 建 WorkflowRun 并关联(issue_interactions.go、issue_runs.go、workflow_invocation.go):同一事务里依次做准入(admitWorkflowRun)→ insertWorkflowRun 建运行(snapshot_id 取准入解析出的版本,input 只放 Start 变量和全局变量)→ 冻结调用者的执行器槽位绑定 → 入队 IssueRun 并写 workflow_invocation_ref → 原有的 run_id IS NULL 比较交换。三个入口的共用创建函数统一冻结 created_by、project_id、plugin_version。Confirm/manual 的创建人取已验证的调用者,Project 取 Issue 的 project_ref;直接启动取请求体 projectId。三种入口均要求合法可访问的 Project,缺失返回 409 workflow_run_project_required。Confirm/manual 不通过开发模拟器伪造执行或跳过槽位绑定。
  • Confirm 的表单校验:只按所选快照投影的表单描述符校验(snapshotFormDescriptor),不再读取活稿比较字段;选旧版本就是按那份快照的表单执行。workflowLatestSnapshot 统一「最新已发布版本」的定义,运行解析与 assist 共用。
  • Assist 与所选版本同源(issue_interactions.go):提交里带发布版本(或工作流已有发布版本)时,按该版本的描述校验提交值的形状;没有发布版本时仍用活稿描述——这是这类工作流唯一能显示的表单,也是 Confirm 会拒绝运行的草稿。
  • 前端默认视图按发布版本渲染(workflow-interaction-composer.tsx):活稿只用于定位版本选择器与默认版本;useChosenVersionForm 把三个读取(活稿、已发布快照列表、所选版本表单)归约为 loading / failed / ready 三态,默认版本与切换后的版本走同一条读取路径。faultParam 读取后端 Fault.params.field,把 required_field_missing / invalid_field_value 映射成带字段名的提示。
  • 已关联的 workflow IssueRun 不再交给 legacy Dispatcher(issue_run_lifecycle.go),避免同一次调用出现两份互不相关的执行结果。
  • 迁移 0056_workflow_invocation_reference.sql:先把没有引用、仍未终结的历史 workflow IssueRun 结算为 failed(workflow_execution_unavailable_before_invocation_linkage),再加 (workflow_invocation_ref, tenant_id) → workflow_runs(id, tenant_id) 复合外键(引用 0044 的 workflow_run_tenant_identity)、引用唯一、执行器类型与引用一致的 CHECK(历史终态行放行),无条件 VALIDATE。编号接在 main 已有的 0055_workflow_run_workspace_release.sql 之后(与 0052 的先后仍有意义,见上);该列此前没有写入者,迁移注释里写明。
  • 状态投影 projectWorkflowRunToIssueRun(workflow_issue_projection.go):在调用方事务里把 WorkflowRun 状态映射到 IssueRun(pending→queued、running→running、succeeded→completed、failed→failed、cancelled→cancelled),写 run.started / run.message / 终态 system activity,不冒充 workflow 评论;awaiting_input 不改 IssueRun。
  • 投影接入调度器(workflow_scheduler.go、workflow_run_session.go、workflow_run.go):认领 pending→running 的比较交换成功后(同一 UPDATE 已写 started_at)调用投影;settleWorkflowRunStates 只在更新到行时投影,终态结算同一 UPDATE 先写 finished_at。会话完成、失败、启动超时、Node 不可达、取消都经过这个结算。摘要由调用方 workflowIssueOutputSummary 从输出节点结果或运行错误生成,按 UTF-8 字符边界截到 ≤20000 字节。
  • 前端其余:一次编辑只建一个 interaction,Confirm 失败重试复用它;已确认的行显示 WorkflowRun 状态并链接到运行详情,没有关联的历史行回退显示 IssueRun 状态;只有选项全是本 workflow 已发布快照时才把 snapshotId 字段当平台版本选择器。
  • 文档:docs/collaboration/interactions(中英)、internal/core 与迁移目录中英 README、组件与 lib 中英 README。两份文档与组件 README 都写明版本选择器的前提:活稿自行声明保留键 snapshotId(或用启动字段移除它)时平台没有选择器,@ 表单按活稿渲染、Confirm 仍按活稿的版本规则执行最新已发布版本,此时显示的字段可能属于另一个版本;这是作者占用保留键的边界,不是可依赖的配置,作者不得把 snapshotId 用作自己的变量名。选择器存在、但切到的版本自己的图声明了该键时,该版本文档同样写明:该版本表单没有平台字段,Confirm 仍按活稿判定版本,作者值会被当成版本游标。是否在切换时禁止或提示这类版本,已开 circus#405 等 owner 决定,本 PR 不改变这一行为(已知不精确:活稿把它声明为选项全属于已发布 id 的 select 时前端仍会当选择器;owner 已在 circus#405 选定方案 D,由发布门禁消除这个边界,四份文档在承接运行 circus#411 中对齐)。

测试

  • integration/workflow_interaction_test.go:TestWorkflowConfirmValidatesAgainstTheChosenVersion(选字段与活稿不同的旧版本按旧 schema 通过;缺旧版本必填字段 required_field_missing;提交旧版本未声明的字段 invalid_field_value;assist 对同一版本做同样的判断)。两条拒绝路径现在都断言 issue_runs 计数不变,并且同一 interaction 随后按该版本重新确认成功,与 specs 用例里的证据说明一一对应。
  • integration/workflow_invocation_test.go:未发布、跨 workflow / 跨租户 snapshot、非法输入都不留下任何行;选旧版本后编辑并重新发布,运行的 snapshot / input / definition 不变;同 Idempotency-Key 重放、换 key 409、并发两个 Confirm 只建一个 WorkflowRun 和一个 IssueRun;manual 路径同样关联;TestWorkflowConfirmSchedulerProjectsCancelBeforeStart 断言开始前取消投影为 cancelled、无 run.started。
  • internal/core/workflow_run_session_db_test.go:TestWorkflowSessionNodeUnreachableProjectsLinkedIssueRun(Node 不可达结算为 failed 后,关联 IssueRun 投影 failed,带 start/finish 与同一原因)。
  • integration/workflow_invocation_migration_test.go:空库与带历史数据升级(含 0052 之后的前一 schema)两种情况下约束都已 VALIDATE;四种非终态结算、三种终态保留、迁移重放、历史行之后仍可 UPDATE、新的无引用 workflow IssueRun 被拒。
  • integration/migration_upgrade_path_test.go:0052 的升级测试拆成「仅 0052」与「整条序列」两段,后者固定 0056 对 running 与软删除行的追加结算。
  • integration/workflow_invocation_identity_test.go:Confirm/manual 冻结实际调用者、Issue Project、插件版本与逐槽位模型绑定;后续配置变化不改写冻结值;开发模拟器不能使这两个入口跳过绑定。
  • 前端 workflow-interaction.test.tsx:默认视图显示最新发布版本的字段并用该 snapshotId 确认;invalid_field_value 显示带字段名的提示;重试提示改为 请填写必填项:<label>;版本切换重取表单、单 interaction、失败重试复用、状态与详情链接、历史行回退(共 19 个用例)。
  • 本 head 29f0532e 的验证:task check(REQUIRE_POSTGRES=1,含 PostgreSQL 集成测试)通过;task frontend:check 通过(生成客户端无漂移、140 个测试文件 / 1204 个用例);此前 head 上 go test -race ./integration/ -run Workflow 与 go test -race ./internal/core/ -run 'Workflow|Interaction|Form' 通过,本次增量只改迁移编号、测试措辞与文档,未再重跑 race;CI 的 check 与 frontend 两个任务在 29f0532e 上均通过。

ADR 状态

  • 修改的 ADR:ora-space/specs 的 decisions/cloud/issue-collaboration/0-typed-targets-and-explicit-execution-intent.md(implemented)D9。owner 2026-10-20 的结论删除了「活稿与所选版本不一致时返回 409 workflow_version_fields_changed」;specs 侧由新增日期 ADR 20261020-confirm-validates-against-the-chosen-version.md(当前 approved)在「继承与修改」中修改 D9 的校验依据,根 ADR 保持 implemented 并在标题下加历史决策提示。对应 specs PR ora-space/specs#164(运行 circus#395)。
  • 合并顺序(owner 确认):specs#164 已先合入(新 ADR 为 approved,证据当时按 Missing/Partial 记录),本 PR 再合入,最后由另一个运行把新 ADR 改为 implemented 并把证据升为 Covered。
  • 实现的 ADR:ora-space/specs 的 decisions/cloud/workflow/0-cloud-side-scheduler-owns-workflow-execution.md(approved)D3 中的创建与引用部分:三种入口共用启动函数;创建事务里冻结 created_by / project_id / plugin_version / 逐槽位绑定;workflow_invocation_ref 的租户一致复合外键、唯一引用与 CHECK;存量非终态 workflow IssueRun 的一次性结算。
  • 合并后未全部实现:fixtures=false 的真实 Node 联合验收仍未交付。根 ADR 保持 approved,剩余部分由 parent circus#71(及其运行 circus#374)承接(circus#70 已关闭),本次不开把 ADR 改为 implemented 的 specs PR。
  • 不涉及:decisions/cloud/workflow/20261015-executor-slots-replace-agent-model-ids.md(approved)的槽位语义本次未改,只在创建时按既有语义冻结绑定;decisions/cloud/workflow/20261016-asset-import-and-published-snapshots.md 已是 implemented,本次只补导入快照经 @ Confirm 与直接运行的调用证据。

未包含 / 待对齐

  • Project 是用户可见的创建要求:没有 Project 的 Issue 不能跑 workflow;编辑器的项目选择器由 cloud#70 负责。三种入口共用 Project 校验,缺失时不留下无法执行的运行。
  • fixtures=false 部署上的真实 Agent 节点验收:circus#70 已关闭,仍未补做;补做时与 circus#77 的验收范围协调,不重复建设。
  • 迁移编号:cloud#119 合并后 main 已占用 0052–0055,本 PR 顺延为 0056;合并前若再被占用,按同一规则顺延后再走一次复审。

🤖 Generated with Claude Code

creegon2 and others added 30 commits October 16, 2026 00:23
Pending WorkflowRun details must retain JSON null for startedAt and finishedAt instead of invalid empty date-time strings. TestPendingWorkflowRunDetailPreservesNullTimestamps directly checks both fields over HTTP. Build and full core/integration validation are logged per commit; the known Windows Git integration failure remains unchanged.
Create and link WorkflowRun/IssueRun atomically for Confirm and manual starts, bypass legacy dispatch, and enforce tenant-scoped one-to-one references in migration 0036. Settle all unlinked non-terminal history, retain editable terminal rows, and validate constraints on every database. Preserve the admission base live-form divergence gate verbatim. HTTP, concurrency, snapshot freeze and fresh/seeded migration regressions accompany this change; full core/integration and build checks are logged at this commit.
Project authoritative state in the caller transaction, write system activities and summaries, and preserve rollback/idempotency. Supplement run.started before direct terminal outcomes only with actual start evidence; awaiting_input leaves the IssueRun unchanged without rejecting the source transaction. PostgreSQL regressions cover these paths. Scheduler wiring remains deferred; full core/integration and build checks are logged at this commit.
Keep one interaction through confirm retries, show authoritative WorkflowRun status and link to its detail page. Historical rows without an invocation reference retain IssueRun status and have no run link.

When the user selects a published version, load its snapshot form with issue context, render that version's fields, discard obsolete answers and retain the selected snapshot instead of the descriptor's newest-version default. Component/API regressions and bilingual module docs accompany the feature. The existing backend field-divergence gate stays unchanged; no polling or backend endpoint is added.

The final rebased tree is validated with Go build, full core/integration packages and focused frontend gates. Race, per-commit rebuilds and HTTP/browser rechecks are explicitly excluded from this rebase follow-up.
Move invocation linkage to migration 0037, reserving 0035 and 0036 for the earlier identity and execution work. Explain why the composite foreign key fails closed on unexpected dangling references.

Identify the platform snapshot selector using all published snapshot ids from the existing paginated endpoint, preserving an author's same-named select as ordinary input when its options are custom. Explain how to resolve workflow_version_fields_changed in the composer without changing admission policy.

Validation: Go build, the core package, all migration and invocation integration cases with a 30-minute timeout, and touched-file frontend format, lint, types, component/API and module gates. No scheduler or identity changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The two field-divergence tests repeated the same 409 handler, render and
confirm steps, which the jscpd duplication gate rejects.

Docs-Unchanged: test-only refactor; no behavior or module contract changed

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keep both README sections: main's session dashboard / model request
statistics and this branch's workflow invocation linkage; list the 0035
model-attempt migration before 0037 in the migrations README.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reuse the real .orax, HTTPS marketplace and PostgreSQL harness to prove imported workflows enter the Issue target directory and their selected snapshot forms remain stable across administrators and import-trigger deactivation. Compare pending run bindings across those identities.

Verify Confirm links its IssueRun to a WorkflowRun bound to the imported snapshot, direct starts select the same snapshot, and editing the draft cannot replace the frozen graph. After provider uninstall, preserve the old snapshot, publish a new version and create a run from it.

Evidence stops at WorkflowRun creation and binding; real node execution remains with ora-space#70. No import implementation or specs changes.

Validation: go build ./..., the core package, three new import invocation cases and 23 existing invocation/confirm/assets regressions with 30-minute timeouts. The merge has no overlap with this branch's frontend edits, so the conditional frontend gate does not apply.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… linkage

Keep this branch's WorkflowRun linkage behaviour while adopting main's
"Issue collaboration D9" citations in place of the removed migration
notes, and list main's 0036 asset-import migration before 0037.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…inkage

main rebuilt docs/ and removed the accreted docs tree, so the invocation
linkage notes move into docs/collaboration/interactions and
docs/workflows/workflows. main also gained 0037_repository_bindings, and
the persistence guide now requires a new migration to follow the latest
number on main, so the invocation reference migration becomes 0038.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main gained 0038_agent_workspace_blocked_deadline, so the invocation
reference migration moves to 0039 to keep following the latest number
on main; the migration READMEs list main's 0038 before it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Issue 协作文档仍把确认前的表单描述为始终取自当前文档,与前端选择已发布版本后重取快照表单的行为不符。
同步修正中英文说明,区分初次打开与选择快照后的表单来源,明确现有活稿字段差异 409 检查仍然生效,并在流程图显示关联创建的两类运行。

验证:对照 WorkflowInteractionComposer、useWorkflowSnapshotForm 和 confirmInteraction 的现有实现;两份文档的相对文件链接均有效;git diff --check 通过。
仅修改文档,不改变 API、字段差异门禁、迁移或调度行为。
合并 c6cccaf,适配已合入的运行身份、执行器槽位与真实会话执行。
direct、Confirm 与 manual 共用创建函数;后两者冻结实际调用者、Issue Project、插件版本和执行器绑定,缺 Project 时事务完整回滚,不使用开发模拟器伪造执行。
将尚未合入的调用引用迁移顺延到 0043,保留 main 的 0039–0042,并同步中英迁移与运行说明。

验证:真实 PostgreSQL 聚焦 core/integration 测试通过,无跳过;身份冻结、缺 Project 回滚和并发 Confirm 定向 race 通过;checkformat、task lint、diff --check 通过。
本次不包含调度器向 IssueRun 的状态投影调用和真实 Node 联合验收,PR 仍按 preflight 范围交付。
保留既有提交历史,合并 upstream/main 的 ceb39bc 外部 Git 线路,解决中英文迁移 README 冲突。
保留已合入的 0043_external_git_line,将尚未合入的 WorkflowRun 调用引用迁移顺延为 0044,并同步升级测试常量与中英说明。
新主线没有改变 direct、Confirm、manual 的共用创建函数及 created_by/project_id/plugin_version 冻结语义;本次不改运行创建实现。
定向测试发现新主线路由漏传 SlotName,使具体槽位 PUT 被当成列表请求返回 405;恢复该字段,由已有身份冻结测试直接覆盖。

验证:真实 PostgreSQL 定向测试中9个顶层用例初次通过;恢复SlotName后仅重跑剩余身份冻结用例,confirm/manual均通过,0跳过。合并代码checkformat/lint通过,字段修复后路由文件格式及router包lint通过。已通过的其余用例未重复运行。
调度器向 IssueRun 投影调用、fixtures=false 真实 Node 联合验收仍未交付,本 PR 保持 preflight。
…nto invocation linkage

main gained 0044_model_attempt_workflow_run, so the invocation reference
migration moves to 0045; the migration READMEs list main's 0044 before it.
cloud#94 fixed the missing SlotName on main, so router.go now matches main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Project only successful workflow status writes in the same transaction. Propagate settle CAS outcomes before session dispatch or cleanup, and truncate existing output/error summaries at UTF-8 boundaries within 20000 bytes.

Add PostgreSQL coverage for Confirm lifecycle, repeat invocation after completion, deterministic failure, concurrent passes, lost CAS, summary limits, and atomic rollback. Validate with task format, go run ./cmd/checkformat, task lint, targeted DB tests, and the requested core/integration suite.
Keep Chinese and English workflow, collaboration, and core documentation aligned with same-transaction projection, affected-row guards, bounded summaries, and direct-run/awaiting-input no-ops.
main gained 0045_agent_configuration_catalog, so the invocation reference
migration moves to 0046; the migration READMEs list main's 0045 before it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main gained migrations 0046-0048, so the invocation reference migration
moves to 0049. enqueueRun keeps main's task-conversation admission checks
and enqueueAdmittedRun, and both now insert through
enqueueRunWithInvocation so the workflow invocation reference is written
with the IssueRun. The IssueRun type keeps both workflowInvocationRef and
main's triggerEvidenceRefId.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main replaced the core and migration READMEs with package and migration
maps, so the invocation linkage moves into that format: the workflow*.go
row names the shared WorkflowRun creation, the invocation reference and
the IssueRun status projection, and the migration map gains 0049 with
its settlement and constraint notes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…on linkage

main gained 0049_thread_commands_workflow_run, so the invocation reference
migration moves to 0050 in the migration map. main's new session end
deadline settles through finishWorkflowRun, so it projects onto the linked
IssueRun like every other status write.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in cloud#91 (Node-unreachable settlement of in-flight workflow sessions), cloud#100,
cloud#104 (workflow globals and sys.*) and cloud#105. The only textual conflict was the import
block of workflow_scheduler_db_test.go; advanceWorkflowRun now takes the deployment's
unreachability window, so the projection rollback test passes store.DeliveryUnreachableAfter
like AdvanceWorkflowRunsOnce does. The new Node-unreachable settlement goes through
finishWorkflowRun -> settleWorkflowRunStates, so it projects onto the linked IssueRun as well.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in cloud#83, cloud#101, cloud#102 and cloud#107. cloud#101 adds
0050_personal_agent_configurations.sql, so the invocation-reference migration moves on to
0051_workflow_invocation_reference.sql: the file is renamed unchanged, the integration test's
migration constant follows it, and both migration READMEs list 0050 and 0051 in order. main's new
`delete(input, "agentConfiguration")` lands in enqueueRunWithInvocation, the single writer that both
enqueueAdmittedRun and the workflow confirm path go through.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in cloud#108 (workflow session turn deadline) and cloud#109 (workflow run cancellation).
cloud#109 adds 0051_workflow_run_cancel.sql, so the invocation-reference migration moves on to
0052_workflow_invocation_reference.sql: the file is renamed unchanged, the integration test's
migration constant follows it, and both migration READMEs list 0050, 0051 and 0052 in order.
Every new settlement path (turn deadline, cancel-before-start, cancel of a running run) goes
through finishWorkflowRun -> settleWorkflowRunStates, so each projects onto the linked IssueRun;
a cancel before the claim projects queued -> cancelled without inventing a start.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The migration directory now holds 54 SQL files (main's 53 plus 0052), so both READMEs say so.
The 0052 entry also names `workflow_runs_id_tenant_uniq`, the unique (id, tenant_id) constraint
that the composite invocation foreign key requires.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
0052 added its own UNIQUE (id, tenant_id) on workflow_runs, which duplicates
workflow_run_tenant_identity from 0044. The composite invocation foreign key
resolves against that existing constraint, so 0052 only adds the reference
constraints now; the migration README says where the target comes from instead
of describing a second unique key.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Confirm used to compare the selected snapshot's fields with the live draft and
refuse with 409 workflow_version_fields_changed. That made selecting an older
version useless exactly when the draft had moved on, which is the ordinary
state between an edit and its publish, and the rule had no specs basis.

Confirm now validates the submission against the chosen snapshot's own
descriptor, the same rule the manual run entry follows. The divergence helpers
lose their only caller and are removed; the frontend drops the 409 hint, and
the collaboration docs and the composer READMEs describe the version's own
schema as the authority.

Co-Authored-By: Claude Code <noreply@anthropic.com>
…ked IssueRun

The scheduler-level projection tests covered the workflow row only. Two end to
end cases now assert what the issue shows: a Confirm-created IssueRun cancelled
before its first claim projects cancelled with no start and no run.started
activity, and one whose Node goes unreachable projects failed with both
timestamps and the same reason the run carries.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Zpc001 and others added 2 commits October 20, 2026 22:10
The component READMEs still listed the field-divergence test that the
chosen-version validation replaced, and the snapshot-form comment still said
the @ form relies on the confirm's divergence refusal.

Co-Authored-By: Claude Code <noreply@anthropic.com>

@wanglongan587 wanglongan587 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes:PR 描述的 ADR 状态漏了本 PR 实际修改的 implemented ADR,specs 记录需要同步;另有一处默认表单与校验依据不一致

审的 commit:676f758b4d1d2fa30c90f96c72b1e05fea2274a1(base upstream/main = ff72afa0;CI 按此 head check、frontend 均 SUCCESS)。增量范围 6699540..676f758b:7e1feb9(0052 去重)、bc47149(按所选版本校验)、2464f75(两条投影用例)、cedfbfe(文档/注释)与合并 main 676f758b。本地 go build ./...、go run ./cmd/checkformat、go vet ./internal/core ./integration 通过;本地没有 PostgreSQL,集成测试以 CI 为准。

已核过、没有问题的部分

  • owner 的放宽结论已实现且删得干净:confirmInteraction 只按 snapshotFormDescriptor 校验(internal/core/issue_interactions.go:144-148);全仓已无 workflow_version_fields_changed、liveFormDescriptor、workflowFieldDivergence、judgedField(s)、refusedFields;前端 409 提示路径删除;中英协作文档与组件 README 已改为「所选版本自身的 schema 是唯一依据」。
  • 0052 去重正确:(workflow_invocation_ref, tenant_id) 外键引用 0044 已建的 workflow_run_tenant_identity(0052:11-15;0044_model_attempt_workflow_run.sql:18 已是 UNIQUE(id, tenant_id),integration/migration_upgrade_path_test.go:1283 已有断言),迁移测试移除了重复索引的断言;两份迁移 README 都写 54 个 SQL 文件、0052 小节说明引用 0044 的约束,目录实际 54 个(main 53 + 1)。
  • 两条 linked IssueRun 用例存在,断言与 PR 描述一致:开始前取消 → IssueRun cancelled、started_at 为 NULL、activity 恰为 run.enqueued / run.cancelled;Node 不可达 → failed、带开始/完成时间与同一原因。
  • 合并干净:git merge-base cedfbfea ff72afa0 = 27e7f488,main 侧 20 个改动文件与本 PR 的 43 个文件无交集,676f758b 没有改写 PR 自有代码(逐提交比对增量一致)。
  • 交付物:43 个改动文件全是代码、测试、正式文档与模块 README,没有计划/进度记录;git diff --check 干净;提交按单一目的拆分,行为提交带测试。
  • workflow 根 ADR 的 approved 声明成立:specs 6aad4f9 上 decisions/cloud/workflow/0-cloud-side-scheduler-owns-workflow-execution.md 仍为 approved,fixtures=false 的真实 Node 联合验收未交付,本次不开把 ADR 改为 implemented 的 specs PR——这部分与描述一致。

需要修改(阻塞):PR 描述漏了 issue-collaboration 的 implemented ADR,specs 记录要跟着改

本 PR 删除的行为并不是「specs 里没有依据」。这条门禁写在 specs decisions/cloud/issue-collaboration/0-typed-targets-and-explicit-execution-intent.md(status: implemented,自 2026-10-17 ad5ed88 起,之后没有再改):

  • D9(specs upstream/main @ 6aad4f9 的 :204-205)明确要求:@ Confirm 在活稿表单与所选版本对提交有影响的属性不一致时返回 409 workflow_version_fields_changed 并列出字段。本 PR 删的正是这条。
  • 两个核心用例把本 PR 删除的测试当作证据:
    • test-cases/cloud/issue-collaboration/collaboration-interactions.md:173(必须成立:活稿与所选版本分歧时 409 并列出字段)与 :185(义务「版本分歧拒绝」→ TestWorkflowConfirmRefusesAVersionTheLiveFormHasLeft + TestWorkflowFieldDivergence,状态 Covered);
    • test-cases/cloud/workflow/publish-and-start-admission.md:73、:75、:81、:86(触发、禁止结果、义务「输入按运行将执行的那一份文档校验」与直接证据都引用 TestWorkflowConfirmRefusesAVersionTheLiveFormHasLeft)。
  • 因此 PR 描述的「ADR 状态」只列 workflow ADR 是不完整的:没有写「按 owner 2026-10-20 结论修改 issue-collaboration 根 ADR 的 D9」,也没有承接 specs 更新;「未包含 / 待对齐」只承诺合并后为导入快照核心用例提 specs PR,覆盖不到这两个核心用例和 ADR 正文。owner 结论第 3 条也要求把「Confirm 按所选版本校验」写进对应核心用例。

请处理:

  1. PR 描述「ADR 状态」补上这条 ADR(implemented,按 owner 结论修改 D9;ADR 保持 implemented,正文与两个核心用例由 specs PR 更新),并写明承接:在 circus#374 下开 specs 运行(node scripts/cli.ts run 71,parent #71)或明确一个 specs issue。
  2. 合并前把 specs PR 开出,或在描述里写明它的范围和合入时机;内容至少包括:
    • 在 decisions/cloud/issue-collaboration/ 新增日期 ADR(按 specs 的「部分决策被后续 ADR 修改时保持原状态、由后续 ADR 的『继承与修改』记录修改项」写法),把 D9 改为「Confirm 只按所选版本自身的 schema 校验,选择版本是可执行路径,不再比较活稿」;
    • collaboration-interactions.md 的「必须成立」与「版本分歧拒绝」证据行按新规则改写(证据换成 TestWorkflowConfirmValidatesAgainstTheChosenVersion,或删除该义务);
    • publish-and-start-admission.md 的触发/义务/证据里去掉已删除的测试,补上新用例。
  3. 请把 owner 结论里「这条规则来自 #65、specs 里没有依据」也纠正给 owner:依据就在这条 implemented ADR 的 D9。放宽结论本身有效,但合并后不能留下与实现相反的 implemented 规格承诺;这属于决策落地的记录,不改变 owner 的决定。

需要 owner 决定(建议合并前处理):默认版本的 @ 表单不是被校验的那份 schema

  • workflow-interaction-composer.tsx:403-406 初次打开读活稿描述符(useFormDescriptor),只有用户实际切换版本(setSnapshotId)才读 GET …/snapshots/:snapshotId/form;而版本选择器的默认值是最新已发布版本(internal/core/workflow_collaboration.go:441-446),seedValues 会把它写进 values(workflow-interaction.test.tsx:406-433 断言的就是这条路径)。用户不动选择器直接 Confirm 时,服务端按最新已发布版本校验(issue_interactions.go:144-148),前端显示的却是活稿字段。
  • 活稿在发布后又编辑过(owner 所述的普通状态)时,用户会被 required_field_missing / invalid_field_value 拒绝,而前端现在只剩「确认失败,请重试。」(workflow-interaction-composer.tsx:380),重试解决不了;这正是被删除的门禁原先解释的路径。也可能按用户从未看过的字段报错,而 collaboration-interactions.md 的禁止结果本来就写着「按用户没见过的字段报错」。
  • owner 结论的理由「前端也按所选版本渲染表单」目前只在显式切换版本后成立。建议二选一,并与 owner 确认:初次渲染就按默认选中的版本取表单(让渲染与校验同源),或取消默认预选、要求用户显式选择;若接受现状留作后续,请在描述里写明承接 issue,并把 issue_interactions.go:146-147、form_descriptor.go:373-377 里「the form offers the selected version's fields」这类断言改成实际行为。

非阻塞 / 建议

  • assistWorkflow 仍用活稿描述符(issue_interactions.go:169-179),而 confirm 已改为所选版本;选中旧版本后,旧版本声明而活稿已删的字段会让 assist 返回 400,而同样值 confirm 通过,issue_interactions.go:163-164 的「same descriptor」注释也不再成立。生产 assist 未接入(503 assist_unavailable),但这是同一规则的第三条路径,建议一并按所选版本解析,或把注释改成实际行为。
  • internal/core/workflow_collaboration.go:213-216 的注释还写「Both descriptors a confirm compares are built from here」;门禁删除后 confirm 已不再比较两个描述符,建议同步改掉。
  • 2464f75 的 Node 不可达用例用原始 SQL 造 linked IssueRun(workflow_run_session_db_test.go:901-933),覆盖的是 settle → projection,不是「创建/关联」链路;描述里称「端到端投影用例」时建议注明范围,或改用 enqueueWorkflowInvocation / confirm 造数据。
  • 删除的 TestWorkflowConfirmRefusesAVersionTheLiveFormHasLeft 原本覆盖「未选版本 + 活稿与最新发布版本字段不同」的端到端路径;替换后的 confirm 用例都显式带 snapshotId。如果保留活稿默认渲染(见上一节),建议补一条该路径的拒绝用例,避免新规则在这条路径上没有证据。

合并前提醒

  • 迁移编号:main 当前最高 0051,本 PR 的 0052 无同号;但开放的 cloud#113(0052_legacy_workflow_issue_run_settlement)与 cloud#112(0052_agent_run_residual_reclamation)也带 0052,先合者占号,合并前按 memory/rules/migration-numbering.md 再核一次(顺延需同步测试常量与中英 README)。旧 PR cloud#71 也仍开着,本 PR 确立后请 owner/作者关闭。
  • 描述里「剩余部分由 circus#374 承接」:运行 issue 收尾会关闭,建议改成 parent circus#71(或写明与 #77 的验收协调),避免承接点随运行关闭而消失。

审过的 commit:676f758b4d1d2fa30c90f96c72b1e05fea2274a1

Zpc001 and others added 2 commits October 21, 2026 10:25
…napshot-confirm

# Conflicts:
#	internal/core/migrations/README.en.md
#	internal/core/migrations/README.md
- 前端先读活稿只为定位平台版本选择器及其默认版本,确定默认发布版本后即按该版本读取
  `GET /workflows/{wfid}/snapshots/{sid}/form` 渲染,切换版本同样重新读取,使显示字段与
  Confirm 校验的 schema 始终来自同一版本;确认失败按 `params.field` 给出字段级提示。
- Assist 按同一版本描述判断提交值形状,与 Confirm、表单读取三方一致。
- 抽出 `workflowLatestSnapshot`,让「最新已发布版本」只有一个定义。
- 迁移改为 `0053_workflow_invocation_reference.sql`,避让上游已合入的 0052;0052 的升级测试
  拆成「仅 0052」与「整条序列」两段断言,后者覆盖 0053 结算剩余未链接的非终态行。

Co-Authored-By: Claude Code <noreply@anthropic.com>

@wanglongan587 wanglongan587 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复审 cloud#114 @ c9a6a48c:行为实现没问题,但这个 head 早于 main 解冻,迁移编号已与 main 同号且 PR 冲突

审过的 commit:c9a6a48c3e82517d5faa04df05ed550f593a3a58(base 9814cacd)。CI 按此 head:check 11m9s、frontend 3m44s,均 SUCCESS。增量 676f758b..c9a6a48c 是合入 main(09b9fe47,combined diff 只有迁移改名与两份迁移 README 三处解冲突)加 c9a6a48c 一个提交。

已核,没有问题的部分

  • 选项 A 的默认视图:useChosenVersionForm 只用活稿定位平台版本选择器及其默认版本,之后默认与切换都走同一条 GET …/snapshots/:id/form;seedValues 用选中的 snapshot id 覆盖选择器值,key 变化时表单按新版本重建,不会退回「默认值 = 最新版本」。默认视图里不再出现活稿未发布的字段,显示字段与 Confirm 校验的 schema 同源。
  • assist 与 Confirm 同源:assistWorkflow 先 workflowVersionCursor 取版本,再 snapshotFormDescriptor;没有发布版本时才回落到活稿。先算游标、再 foldLegacyVersionAnswer 的顺序是对的(旧 version 键要先被游标读到),我特意核了这一点。
  • 字段级拒绝提示:required_field_missing / invalid_field_value 在后端都带 Fault.params.field(form_descriptor.go:191/199/204、workflow_admission.go:83/100/105),前端按渲染版本的 descriptor 取 label,取不到时退回键名,其他 code 仍是通用提示。
  • 迁移语义与 0052 的先后:0052 只结算 queued / dispatched,本 PR 的迁移结算 running、deferred 与软删除的 queued,以及无条件 VALIDATE 的 CHECK;升级测试拆成「仅 0052」与「整条序列」两段,覆盖合理。
  • 文档与用例:中英协作文档、workflow_collaboration.go 注释、组件 README 都改成「默认视图也按所选发布版本渲染」,与实现一致;用例覆盖默认视图看到 v3 独有字段、Confirm 带 v3 的 snapshotId 通过、invalid_field_value 显示字段名、assist 在 v1 下拒绝活稿的 scope。

阻塞

  1. PR 与当前 main 冲突。 mergeable=CONFLICTING;git merge-tree upstream/main c9a6a48c 的冲突只在 internal/core/migrations/README.md 与 README.en.md——main 的 #183(merge a9c5f20)在 02:27Z 合入,新增了 0053 / 0054 两行。请合入当前 main 后重推。
  2. 迁移编号已与 main 同号。 main 现有 0053_retire_tenant_level_clones.sql、0054_git_delivery_refs.sql(共 56 个 SQL 文件),本 PR 的 0053_workflow_invocation_reference.sql 既同号又小于最新编号,违反 memory/rules/migration-numbering.md。请改名为 0055_workflow_invocation_reference.sql,并同步:
    • integration/workflow_invocation_migration_test.go:10 的 workflowInvocationMigration;
    • integration/migration_upgrade_path_test.go:1436 / 1452 / 1480 的注释与失败信息里的 0053;
    • 两份迁移 README 的表行与说明段(README.md:67 / :83、README.en.md:67 / :83);
    • PR 描述里的编号(「迁移编号改为 0053」「迁移 0053_…」以及「未包含 / 待对齐」里的顺延说明)。
  3. 两份迁移 README 的文件计数已经是错的。 head 的迁移目录实际有 55 个 SQL 文件(main 的 0052 + 本 PR 的一个),两份 README 仍写 54——09b9fe4 解冲突时保留了 54。合入当前 main 后应为 57(56 + 1),表行也应有 57 条。顺带说明:main 自己现在也是 56 个文件却写 54(#183 没改这句),本 PR 既然要改这两份文件,请写真实数字。
  4. 在新 head 上重跑 CI。 现在的 check / frontend 是 9814cacd 基线上的结果;#183 删掉了租户级 clone、Revision 改走 Git 交付 ref,虽然没直接改 issue_runs / workflow_runs,合并后的树仍要重新验证(CI,以及 task check 的 PostgreSQL 集成测试)。

非阻塞(请确认接受,还是另开承接)

  • 旧版本自己声明 snapshotId 时,显示与执行仍可能不同源。 场景:活稿没有声明 snapshotId(平台选择器在),但某个旧版本的图把它声明成自己的文本变量,或选项不全属于已发布 id 的 select。用户在默认视图切到该版本后,渲染的是该快照的表单,里面没有平台选择器,platformVersionField 认不出,versionField 为空、也不再 seed snapshotId;Confirm 时 workflowVersionCursor 按活稿判定这个键归平台,于是提交里作者字段的值被当成版本游标——空值落到最新版本,非 id 值 404。结果是「看到旧版本的字段、跑的是最新版本(或被拒)」。这是 #71 既有规则(游标按活稿判定)与选项 A(默认与切换都按快照渲染)的交界;要么切到没有平台选择器的版本时不允许切(或给出提示),要么在组件 README 与用例里写明这一情况的预期行为。不在本 PR 阻塞,但请给个结论,避免合并后才发现。
  • formBlocker 让任一读取失败都挡掉整个表单、切换版本期间整块换成 Skeleton,都是既有行为,本次不阻塞。

合并顺序

不变:specs#164(46a43ff,开放)先合,本 PR 再合,最后由另一个运行把新 ADR 改成 implemented。specs#164 我在 circus#395 单列 review,不在本 PR 的结论里。

Zpc001 and others added 3 commits October 21, 2026 10:54
main 已合入 0052_legacy_workflow_issue_run_settlement、0053_retire_tenant_level_clones
与 0054_git_delivery_refs,按先合先得把本分支的迁移改名为
0055_workflow_invocation_reference.sql,并同步迁移测试常量、升级测试说明与两份迁移
README 的序号表和文件数(57)。冲突只在这两份 README。

Co-Authored-By: Claude Code <noreply@anthropic.com>
缺必填字段与提交未声明字段的拒绝原本只断言错误码;补上 issue_runs 计数不变,
以及同一 interaction 随后按所选版本重新确认成功,与 specs 用例的证据说明对齐。

Co-Authored-By: Claude Code <noreply@anthropic.com>
活稿自行声明 snapshotId(或用启动字段移除它)时没有选择器,表单按活稿渲染而
Confirm 执行最新已发布版本;切到的版本自己声明该键时该版本表单同样没有平台字段,
作者值会被当成版本游标。两份协作文档与组件 README 按实际行为写明这是作者占用
保留键的边界,是否禁止或提示这类切换留给 circus#405。

Co-Authored-By: Claude Code <noreply@anthropic.com>

@wanglongan587 wanglongan587 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复审 @ 994fcbae:Approve

  • 审过的 commit:994fcbae0e88b95c7a223057d8f6abb6836b2222(base a9c5f20;当前 upstream/main = 4128d86)。CI 按此 head:check 12m49s、frontend 2m14s,均 SUCCESS。
  • 增量 c9a6a48..994fcbae 三个提交:2cedb05(合 main、迁移顺延 0055)、3f09884(两条拒绝路径补断言)、994fcbae(保留键边界文档)。本次不改变行为:版本游标、Confirm、投影、前端表单与 assist 的实现代码与 c9a6a48 一致,0055 与上一轮审过的 0053 内容逐字相同,只改了文件名。

上一轮阻塞项

  1. 合 main:已合 a9c5f20,冲突只在两份迁移 README;main 的 0052–0054 表行与说明段都保留。与 main 同时改过的另外 10 个文件逐个核对过,diff 只含本 PR 的改动,没有回退 main 的内容。
  2. 迁移顺延 0055:main 当前仍是 56 个 SQL、最高 0054;本 PR 57 个、编号 0055,无同号。workflowInvocationMigration 常量、migration_upgrade_path_test.go 的 0055 措辞与失败信息、中英 README 的表行和说明段都已同步。
  3. README 文件数:head 的表行 57 行,与目录 57 个 SQL 文件逐一对上,无重复、无缺行;正文写 57。main 原来的 54 确实是过期数字(实际 56),这里顺带纠正,符合复审判定。
  4. CI:新 head 上 check / frontend 均 SUCCESS。

本轮新增内容

  • TestWorkflowConfirmValidatesAgainstTheChosenVersion:缺必填字段与提交未声明字段两条拒绝路径都断言 issue_runs 计数不变,并各用同一个 interaction 按所选版本重新确认成功;assist 对同一版本的判断也在同一用例里。与 specs 复审要求的「两条路径都断言」一致。
  • TestMigration0052LegacyWorkflowIssueRunSettlementAppliesFreshAndUpgrades 拆成「仅 0052」与「整条序列」两段:前者保留 0052 自己的效果,后者固定 0055 对 running、deferred、软删除 queued 的追加结算,以及终态行与 agent 行不动;migratedTwice 覆盖重复应用。
  • 保留键边界的文档与实际行为一致:活稿声明 snapshotId 时 workflowVersionCursor 返回空、执行最新已发布版本;切到的版本自己声明该键时该版本快照表单不含平台字段,而 Confirm 仍按活稿判定游标,空值落最新、非 id 走 404。前端「文本变量」与「含未发布选项的 select」两条用例固定同名变量仍是普通输入。这类切换是否禁止/提示由 circus#405(type:decision)承接,本 PR 不改变行为,合理。

本地核对(含当前 main 的合并树)

head 比当前 main 少一个合并(#118 的 Node unknown window,4128d86)。我本地把 upstream/main 合进 994fcbae:无冲突(workflow_run_session_db_test.go 自动合并),go build ./...、go vet ./internal/core ./integration、版本游标与 launch key 的单元测试均通过。#118 去掉了 runWorkspaceNodeUnknown 的 connected 条件、并让 disconnect 不刷新 last_seen_at;本 PR 的 TestWorkflowSessionNodeUnreachableProjectsLinkedIssueRun 直接把 last_seen_at 老化 2 小时,语义不受影响。CI 只覆盖 a9c5f20 基线;GitHub 现在报 CLEAN,如需严格按合并树再跑一遍 CI,可再合一次 main,但我不认为这是阻塞。

合并前提醒(非阻塞)

  • 迁移号 0055 目前还有 cloud#112、#117、#119 也在排,先合者占号;若它们中有先合并的,请按 memory/rules/migration-numbering.md 顺延并同步常量与两份 README。
  • 合并顺序按 owner 结论:specs#164(新 ADR approved)先、cloud#114 后、再由另一个运行把新 ADR 改 implemented;specs#164 的 review 在 circus#395,不在本 PR。
  • PR 只含交付物(49 个文件:代码、测试、迁移、正式文档与模块 README),没有过程记录;git diff --check 干净。
  • 合并后 fixtures=false 的真实 Node 联合验收与 specs 证据 PR 仍未完成(描述已写明由 circus#71 承接),所以本 PR 合并不等于运行 circus#374 收尾。

ADR 状态

描述里的三条都成立:修改的 implemented ADR D9 由 specs#164 承接;实现的 approved ADR 写明剩余部分由 circus#71 承接;不涉及的 ADR 有说明。可以按 owner 定的顺序合并。

cloud#119 先合并并占用了 0055,把调用引用迁移顺延到 0056,并同步
workflowInvocationMigration 常量、迁移测试的措辞与失败信息,以及两份
迁移 README 的表行、说明段和文件计数(58)。

Co-Authored-By: Claude Code <noreply@anthropic.com>

@wanglongan587 wanglongan587 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes:迁移 0055 与 main df9799c 撞号,顺延后再审增量

审过的 commit:994fcbae0e88b95c7a223057d8f6abb6836b2222。这个 head 的内容与我 2026-10-21 03:28Z 的 Approve 相比没有变化,下面只有合并前的环境与编号阻塞,没有新的行为问题。

阻塞:编号与 main 同号

  • upstream/main 已是 df9799c5178db669337e39b6a5bb014628c93c34(cloud#119 / #377 合入),新增 0055_workflow_run_workspace_release.sql,共 57 个 SQL 文件,最高编号 0055。
  • 本 PR 也是 0055_workflow_invocation_reference.sql(57 个文件)。按 memory/rules/migration-numbering.md,合并前必须接在 main 最新编号之后,不能与 main 同号或更小。
  • PR 现在是 CONFLICTING。我本地用 git merge-tree 把 upstream/main 合进 994fcbae 核对:冲突只有 internal/core/migrations/README.md 与 README.en.md(两边都在序号表里加了 0055 行),其余文件(含 migration_upgrade_path_test.go、workflow_scheduler.go、中英文工作流文档)都能自动合并。撞号是唯一阻塞,和上一轮同性质。

请在新 head 一起做

  1. 追平 upstream/main,迁移改名为 0056_workflow_invocation_reference.sql(当前 main 最高 0055)。
  2. 同步引用:integration/workflow_invocation_migration_test.go:10 的 workflowInvocationMigration 常量;integration/migration_upgrade_path_test.go:1477、:1493、:1521 的 0055 措辞与失败信息;internal/core/migrations/README.md / README.en.md 的序号表行、说明段(第 69、87 行附近)和文件计数(合入 main 后应为 58)。
  3. 合并后保留 main 的 0055 表行与说明段,顺序为 0055(workspace release)→ 0056(本 PR)。
  4. PR 描述同步:迁移编号 0056、文件数 58;「ADR 状态」里 specs#164 已合并(merge commit c9e99a9f3670f831860f91a843d07658669cf4c7,新 ADR 以 approved 落到 specs main),把「specs#164 先合入」改成既成事实,并保留「合并后由另一个运行把新 ADR 改为 implemented、证据升 Covered」这一条。
  5. 新 head 上重跑 CI(check / frontend 与 PostgreSQL 集成测试),然后打 status:in-review 请我复审这段增量。

提醒:0056 也可能被先占

当前开放的 cloud#116 已带 0056_agent_run_controlled_reclamation.sql,cloud#117 / #112 也还带 0055;先合者占号。合并前按当时 main 的最新编号再核一次,若被别人先占,顺延到再下一个号并同步上面四处引用。

维持上一轮结论的部分(不需要返工)

默认视图与切换版本同源读取、assist 与 Confirm 同源、字段级拒绝提示、两条拒绝路径的断言、TestMigration0052… 拆段与 0055 的追加结算断言、保留键边界文档,我都已核过。0056 的 SQL 内容应与 0055 逐字相同,我只核对改名、计数与描述。

@wanglongan587 wanglongan587 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approve:增量只有迁移顺延与计数,29f0532e 可以合并

  • 审过的 commit:29f0532e788502ef9e81c7b5421633fcdab8412a(base df9799c5178db669337e39b6a5bb014628c93c34,即当前 upstream/main)。CI 按此 head:check 12m19s、frontend 3m47s,均 pass。
  • 增量 994fcbae..29f0532e 只有一个合并提交 29f0532e(两个父:旧 head 994fcbae + main df9799c);PR 自身相对新 main 仍是 49 个文件,文件集合与上一轮逐一对上,只多了迁移改名。

核对结果

  1. 迁移编号:main df9799c 57 个 SQL、最高 0055_workflow_run_workspace_release.sql;head 58 个、最高 0056_workflow_invocation_reference.sql,无同号,接在最新编号之后。
  2. 改名是纯改名:0056_workflow_invocation_reference.sql 与上一轮 0055 的 blob 都是 9130fae6,内容逐字未变。
  3. README 冲突解决正确:中英两份都保留 main 的 0055 表行与说明段,在其后追加 0056 表行与说明段,文件计数改为 58(main 57 + 1);表格行与 ls-tree 的 58 个 SQL 文件对得上。
  4. 引用同步:workflowInvocationMigration 常量、migration_upgrade_path_test.go 的三处 0055 措辞与失败信息都改为 0056;head 上已无「0055 + invocation」的残留。
  5. 合并没有丢 main 的改动:我用 git merge-tree 重算了自动合并树,实际 head 与它只差两份冲突的 README(人工解决)和两个测试文件的 0055→0056 字样;其余 main 与 PR 同时改过的文件(workflow_scheduler.go、workflow_run_session.go、docs/workflows 等)都是标准三方合并结果,#118 / #119 的改动与 PR 的改动都在。
  6. 仓库卫生:无冲突标记;git diff --check df9799c..29f0532e 干净;49 个改动文件仍是代码、测试、正式文档与模块 README,没有过程记录。
  7. ADR 状态:根 ADR 0-typed-targets-and-explicit-execution-intent.md 仍 implemented 并带历史决策提示;新 ADR 20261020-confirm-validates-against-the-chosen-version.md 在 specs main c9e99a9f(specs#164 已合并)为 approved,由后续运行改 implemented 并把证据升 Covered;0-cloud-side-scheduler-owns-workflow-execution.md 仍 approved,剩余 fixtures=false 联合验收由 parent circus#71 承接。三条与 owner 的合并顺序一致。

非阻塞

  • PR 描述「合并顺序」一句仍写「specs#164 先合入」,实际已在 c9e99a9f 合并。建议顺手改成既成事实;只改描述,不影响 head,也不影响这次 lgtm。
  • 合并提醒不变:0056 先合先得,cloud#116 / #117 / #112 还在排队,被占就顺延后重走一次复审。合并后 cloud#71 由 @creegon2 关闭;本运行继续做 fixtures=false 真实联合验收与 specs 证据升级。

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants