feat(contracts): auto 配方契约 —— 确定的活由引擎按声明做,五个动词四种地址

配方是数据不是代码(ADR-004:不执行包代码即知包为何物),装进来可静态审、可回放。
只声明真实现了的那几式;嵌套两层封顶,没实现的形状 zod 当场拒。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
This commit is contained in:
xcs
2026-08-29 03:04:56 +08:00
co-authored by Claude Opus 5
parent 04234d2fda
commit 16fe8ba71b
9 changed files with 385 additions and 0 deletions
@@ -0,0 +1,35 @@
import { describe, expect, it } from 'vitest';
import { autoRecipeSchema } from '../auto-recipe.ts';
describe('auto 配方契约', () => {
it('收下一份用全了五个动词的配方', () => {
const parsed = autoRecipeSchema.safeParse({
let: { evalRef: { cat: ['W05-', { fmt: { in: 'case:openedAt' }, as: 'digits' }] } },
do: [
{ kind: 'project', into: 'sub_eval.part', prune: true, from: { rows: [{ pn: { in: 'originalInternalPn' } }] }, fields: { internal_pn: { col: 'pn' } } },
{ kind: 'analyze', model: 'deepseek-v4-flash', into: 'items', instruction: '逐条判四态', input: { from: { each: 'parts.type_param' }, fields: { name: { col: 'param_name' } } }, output: { type: 'object' } },
{ kind: 'card', as: 'execution', variant: 'data', title: '补数据', basis: [{ k: '原 PN', v: { in: 'originalInternalPn' } }], gateLedgers: ['parts.profile'] },
{ kind: 'submit', rationale: '结论已备好' },
{ kind: 'say', text: '这一步办完了' },
],
});
expect(parsed.success).toBe(true);
});
it('不认识的动词当场拒 —— 没实现的形状不许装进来', () => {
const parsed = autoRecipeSchema.safeParse({ do: [{ kind: 'drop', into: 'a.b' }] });
expect(parsed.success).toBe(false);
});
it('嵌套只许两层:第三层当场拒', () => {
const parsed = autoRecipeSchema.safeParse({
do: [{ kind: 'project', into: 'a.b', from: { each: 'a.b', then: { each: 'c.d', then: { each: 'e.f' } } }, fields: {} }],
});
expect(parsed.success).toBe(false);
});
it('prune 只许挂在 project 上', () => {
const parsed = autoRecipeSchema.safeParse({ do: [{ kind: 'say', text: 'x', prune: true }] });
expect(parsed.success).toBe(false);
});
});