Archived
三面拆分⑰:编辑即其身 —— 保存写回本版,新版本只出自「新建」
用户问:为什么编辑一个版本、保存就自动多一个副本?那不是我要的。
旧机制「保存恒新增版本号」改为:
- savePackage:pkg.version 已存在 → **就地写回该版**(号不变、状态不变);
`asNew: true`(新建按钮)或新流程首版才铸新版本号(服务端算,不生效)
- 底线三道,一道不少:
① **在途钉版不可变** —— 该版有未完结工作流(按 (包,版本) 钉定义)→ 409,
一字不落库;「就地覆盖会改掉在途正在读的编排」由这道闸守,不再靠只插不改一刀切
② **生效版必须始终可运行** —— 写回生效版跑闭合闸,不闭合 412 带整份报告;
未生效版画图不检查、随手存
③ **陈旧编辑不复活** —— 流程存在而版本号已被清理 → 409(实测:停在已删旧版上的
标签页发来保存,把老内容静默复活成了新版本;StaleVersionError 拦死)
- store:新增 updatePackageDefinition(只许命中现存版本)+ countPinnedInFlight
- 前端:保存按钮「保存 v{n}」;新建走 asNew;文案全线「新建才长版本」
- 测试:save-package.test 六例(写回/钉版/热改闭合/asNew/防复活/首版);
过程中揪出双 API 进程并存(旧进程霸端口跑旧代码)——已重启归一
实测:改名保存 → 版本列表仍唯一 v4 生效中,名字已写回;八例端到端全绿;
五闸退出码全过(api:check 提交后转绿)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
This commit is contained in:
@@ -36,7 +36,7 @@ import {
|
||||
} from '@contracts';
|
||||
import { InstallRejectedError } from '@modules/activity-registry';
|
||||
import type { InstallVerdict } from '@modules/activity-registry';
|
||||
import { NotClosedError } from '@modules/process';
|
||||
import { NotClosedError, PinnedVersionError, StaleVersionError } from '@modules/process';
|
||||
import type { Container } from '../container.ts';
|
||||
import type { AppEnv } from '../http-env.ts';
|
||||
|
||||
@@ -265,7 +265,7 @@ export function registerGovernanceOpsRoutes(app: Hono<AppEnv>, container: Contai
|
||||
|
||||
/**
|
||||
* 保存编排 —— 保存 ≠ 发布:草稿可反复存;**已发布版本不可回改**。
|
||||
* 想改已发布的,另起新版本(恒新增、版本并存,在途按启动时版本跑完)。
|
||||
* 编辑即其身:保存写回当前版本;在途钉版不可变,新版本只出自显式新建。
|
||||
*/
|
||||
app.put(saveProcessRoute.path, async (c) => {
|
||||
const denied = await governProcess(c.get('account'));
|
||||
@@ -276,11 +276,24 @@ export function registerGovernanceOpsRoutes(app: Hono<AppEnv>, container: Contai
|
||||
return c.json(body, 400);
|
||||
}
|
||||
/*
|
||||
* 保存**不检查、不生效**:画图的中间态天然不完整,存下来是未生效的新版本。
|
||||
* 返回连同闭合报告 —— 异常看板据它列清单;完整性闸在激活路由。
|
||||
* 编辑即其身:已存在的版本就地写回(号不变);asNew / 新流程首版才长新版本。
|
||||
* 画图不检查(未生效版随手存);返回连同闭合报告 —— 异常看板据它列清单。
|
||||
* 两道闸:在途钉版 409;写回生效版不闭合 412(生效的必须始终可运行)。
|
||||
*/
|
||||
const pkg = await container.process.savePackage(parsed.data.pkg);
|
||||
return c.json({ pkg, report: await container.process.validate(pkg) });
|
||||
try {
|
||||
const pkg = await container.process.savePackage(parsed.data.pkg, { asNew: parsed.data.asNew === true });
|
||||
return c.json({ pkg, report: await container.process.validate(pkg) });
|
||||
} catch (error) {
|
||||
if (error instanceof PinnedVersionError || error instanceof StaleVersionError) {
|
||||
const body: ApiError = { code: 'conflict', message: error.message };
|
||||
return c.json(body, 409);
|
||||
}
|
||||
if (error instanceof NotClosedError) {
|
||||
const body: ApiError = { code: 'precondition-failed', message: error.message, detail: error.report };
|
||||
return c.json(body, 412);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
/** 版本启停:激活即独占,停用即下线 —— 在途按启动版本跑完,零影响 */
|
||||
|
||||
@@ -374,7 +374,7 @@ export async function seedMvpFlow(container: Container): Promise<void> {
|
||||
/*
|
||||
* 保存即生效,且**内容没变就不再存新版**。
|
||||
*
|
||||
* 保存恒新增版本(这是「旧任务走完旧版本」的前提),所以种子不能无条件存 ——
|
||||
* 内容变更走新版本(在途钉旧版跑完),所以种子不能无条件存 ——
|
||||
* 那样每跑一次播种就多一个版本,库里堆一串一模一样的定义。
|
||||
* 比对的是语义与呈现,不含 version/state(它们由保存本身决定)。
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user