Archived
feat(activity-registry): 配方静态审 —— 写错地址在装包那一刻就拒
与 refersTo 目标检查同款:代码错是必然的错,而必然的错只有在装的时候被拦下才算好查。 台账地址 / 列名 / 模型名 / 视图模版 / submit 的验收清单逐条核; analyze 的出参没人消费报 warning —— 那是白烧一次模型调用。 顺带(R8,Task 7 评审挖出):全 auto 的步没有 guide 是正常形态, guide.min(1) 放宽为 z.string() + superRefine —— 没 auto 又不写 guide 照旧拒装。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
This commit is contained in:
@@ -33,3 +33,32 @@ describe('auto 配方契约', () => {
|
||||
expect(parsed.success).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
import { planStepSchema } from '../manifest.ts';
|
||||
|
||||
describe('全 auto 的步可以没有 guide', () => {
|
||||
/* brief 原样缺了 intent(required,非空)—— 缺了它 safeParse 恒失败,前两条测试就都验不到「guide 允不允许空」这件事本身 */
|
||||
const base = { item: 'S1', intent: '这一步交出什么', guide: '', writes: [], reads: [], tools: [] };
|
||||
|
||||
it('声明了 auto 就允许 guide 为空 —— 那一步压根不问模型', () => {
|
||||
const parsed = planStepSchema.safeParse({
|
||||
...base,
|
||||
auto: { do: [{ kind: 'say', text: '办完了' }] },
|
||||
});
|
||||
expect(parsed.success).toBe(true);
|
||||
});
|
||||
|
||||
it('没有 auto 又不写 guide → 拒 —— 「作者忘了写做法」这个老错照旧要拦', () => {
|
||||
const parsed = planStepSchema.safeParse(base);
|
||||
expect(parsed.success).toBe(false);
|
||||
});
|
||||
|
||||
it('有 auto 但 guide 写了内容 → 照收(半 auto:确定的先做完,剩下的仍问模型)', () => {
|
||||
const parsed = planStepSchema.safeParse({
|
||||
...base,
|
||||
guide: '把结论写实',
|
||||
auto: { do: [{ kind: 'say', text: 'x' }] },
|
||||
});
|
||||
expect(parsed.success).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -119,7 +119,7 @@ export const planStepSchema = z.object({
|
||||
/** 一句话:这一步交出什么 */
|
||||
intent: z.string().min(1),
|
||||
/** 这一步的做法(从说明书里搬过来的那一段)—— 只在轮到它时进上下文 */
|
||||
guide: z.string().min(1),
|
||||
guide: z.string(),
|
||||
/** 这一步可写哪几个台账地址「域.对象」;空 = 这一步不写台账 */
|
||||
writes: z.array(z.string()).default([]),
|
||||
/**
|
||||
@@ -200,7 +200,22 @@ export const planStepSchema = z.object({
|
||||
* **老活动一个字不用改** —— 不写就是不写,不是缺件。
|
||||
*/
|
||||
auto: autoRecipeSchema.optional(),
|
||||
});
|
||||
})
|
||||
.superRefine((step, ctx) => {
|
||||
/*
|
||||
* **全 auto 的步没有 guide 是正常形态**(2026-08-29):引擎按 `guide.trim() === ''`
|
||||
* 分「半 auto(确定的先做完,剩下的仍问模型)」与「全 auto(这一步一次都不问模型)」。
|
||||
* 而 `.min(1)` 让后者压根写不出来 —— 四步全 auto 的活动会在装包那一刻被拒。
|
||||
* 非空这条要求仍留给没有 auto 的步:**「作者忘了写做法」是个老错,照旧要拦**。
|
||||
*/
|
||||
if (step.auto === undefined && step.guide.trim() === '') {
|
||||
ctx.addIssue({
|
||||
code: 'custom',
|
||||
path: ['guide'],
|
||||
message: '这一步的做法不能为空 —— 只有声明了 auto 配方的步才允许没有 guide',
|
||||
});
|
||||
}
|
||||
});
|
||||
export type PlanStep = z.infer<typeof planStepSchema>;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user