金融与交易
在需要以 Allium 规格驱动功能从意图到代码收敛时…
当你需要编写/维护 `.allium` 规格,或从意图/代码出发让规格、测试与实现一致时,用本技能选择语法、路由技能并驱动收敛循环。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
在需要以 Allium 规格驱动功能从意特定
解决思路
- 遇到 `**/*.allium` 文件或关键词 `allium`、`allium spec`、`allium specification`、`.allium file` 时启用本技能。
- 编写或阅读 `.allium` 文件时,使用本技能获取 Allium 语言语法和结构,不要凭猜测写。
- 遵循 Allium 原则:只描述可观察行为,不描述实现;只捕获行为级有意义的域逻辑;生成集成和端到端测试而非单元测试;在实现前强制暴露歧义;保持实现无关。
- 通过对话从用户意图构建规格时,使用 `elicit` skill。
- 从现有实现代码提取规格时,使用 `distill` skill。
- 修改已有 `.allium` 规格时,使用 `tend` skill。
- 查找或修复规格与实现分歧时,使用 `weed` skill。
- 从规格生成测试、PBT 属性或状态机测试时,使用 `propagate` skill。
- 需要独立确认某次运行是否真收敛时,使用 `witness` skill:核对测试真的通过、没有生成测试被弱化、没有阻塞问题被静默搁置。
- 端到端构建或调和功能到收敛时,用 `/allium <goal>` 驱动整个循环,自主执行收集上下文→行动→验证→重复,直到规格、测试、代码一致。
- 响应 `/allium` 时偏向自主路径:清晰单一任务按路由表直接路由到对应 skill,不要让用户翻菜单。
- 当输入是一个目标或功能(如 `add gift cards`、`get password reset working`)时,自己驱动整个循环,而不是只跑一个阶段;遵循 `references/driving-the-loop.md`。
- 当输入空泛或模糊时,采用 loop-first 引导:默认提出驱动整个循环,再列出各单独 skill 作为控制路径并各给一行提示,同时根据项目状态建议具体起点(已有 `.allium` 规格?有代码但无规格?有 drift 待调和?)。
- 回复时先讲循环,把单独 skill 留在一步之外给需要手动控制的用户;单个 skill 完成后主动建议下一阶段,不要等用户问。
- 把各 skill 组合成循环:收集上下文 → 采取行动 → 验证 → 重复,使三种产物达成一致:规格(意图)、测试(契约)、代码(实现)。
- 用 `/elicit` 或 `/distill` 收集上下文(规格是持久上下文);用 `/propagate` 后接实现来采取行动;在 spec-first 工作中先确认新测试失败——实现前已绿的测试要么已覆盖要么无效。
- 通过运行测试、再 `/weed`、再做 CLI 结构检查来验证;重复直到收敛。
- 把验证视为最重要的阶段;规格 + 测试 + `/weed` 信号是让循环可信的关键。
- Spec-first 前向流程:`/elicit` → `/propagate` → 实现 → `/weed`;需求变化时用 `/tend` 后重新 `/propagate`。
- Code-first 后向流程:`/distill` → 审查有意行为 vs 意外行为 → `/propagate` → 对代码运行测试 → `/weed` 调和 → 按区域重复。
- 完成条件:测试通过、`/weed` 报告无分歧、没有未决问题;code-first 还要求新跑一次 `/distill` 找不到新内容;并由独立 `/witness` 对照基准事实证实该声明。
- 循环时遵守两条常设规则:绝不为了让测试通过而弱化生成测试(应修规格并重新 `/propagate`);遇到真实歧义升级给人而不是猜测;二者由 witness 在收敛门禁强制。
- 记住实现本身是普通编码;Allium 产出规格和测试,不产出应用代码;完整走查、图示、退出条件和实现提示见 `references/recommended-loops.md`。
- 用 `entity Name { ... }` 定义实体:字段、内联枚举(如 `status: pending | active | completed | cancelled`)、关系(`invitation: Invitation with candidacy = this` 一对一,`slots: InterviewSlot with candidacy = this` 一对多)、投影(`confirmed_slots: slots where status = confirmed`)、派生(`is_ready: confirmed_slots.count >= 3`,`has_expired: invitation.expires_at <= now`)。
- 用 `external entity Role { title: String, required_skills: Set<Skill>, location: Location }` 声明外部实体。
- 用 `value TimeRange { start: Timestamp, end: Timestamp, duration: end - start }` 声明值类型。
- Sum type:在基础实体中声明一个 discriminator 字段,其首字母大写的值命名变体;变体使用 `variant` 关键字(如 `kind: Branch | Leaf`,`variant Branch : Node { ... }`)。小写管道值是 enum literals(`status: pending | active`),大写值是 variant references(`kind: Branch | Leaf`)。类型守卫(`requires:` 或 `if` 分支)可窄化到变体并解锁其字段。
- 用 module `given` 声明模块规则操作的实体实例,所有规则继承这些绑定;不是每个模块都需要:由域实体触发器限定的规则从触发器获得实体;`given` 用于规则操作每模块作用域只存在一次的共享实例的规格。导入的模块实例用限定名访问(如 `scheduling/calendar`),不出现在本地 `given` 块。它不同于 surface `context`(为边界契约绑定参数化作用域)。
- 用 rule 语法编写规则:`rule InvitationExpires { when: ... requires: ... let ... ensures: ... ensures: ... @guidance ... }`。
- 选择正确触发器类型:外部刺激(`when: CandidateSelectsSlot(invitation, slot)`)、状态转换(`when: interview: Interview.status transitions_to scheduled`,仅转换不含创建)、状态成为(`when: interview: Interview.status becomes scheduled`,创建或转换达到该值)、时间(`when: invitation: Invitation.expires_at <= now`,总是加 `requires` 守卫防重复触发)、派生条件(`when: interview: Interview.all_feedback_in`,派生值变真)、实体创建(`when: batch: DigestBatch.created`,新实体创建时触发)、链式(`when: AllConfirmationsResolved(candidacy)`,订阅另一规则 ensures 子句的触发器发射)。
- 所有实体作用域触发器使用显式 `var: Type` 绑定;不需要名字处用 `_` 作为丢弃绑定,如 `when: _: Invitation.expires_at <= now`、`when: SomeEvent(_, slot)`。
- 用 rule-level iteration:`for` 子句对集合中每个元素应用一次规则体,如 `for user in Users where notification_setting.digest_enabled: let settings = user.notification_setting ensures: DigestBatch.created(user: user, ...)`。
- Ensures 子句使用四种结果形式:状态变更 `entity.field = value`;实体创建 `Entity.created(...)`(唯一规范创建动词);触发器发射 `TriggerName(params)`;实体删除 `not exists entity`。这些形式可与 `for` 迭代、`if`/`else` 条件和 `let` 绑定组合。
- 实体创建只用 `.created()`;领域含义放在实体名和规则名,不放创建动词。
- 在状态变更赋值中,右侧表达式引用规则前字段值;在 ensures 块内的条件(`if` 守卫、创建参数、触发器发射参数)引用结果状态。
- 用 `surface` 定义边界契约:`facing` 命名外部方,`context` 限定实体;其余子句使用统一词汇,不论边界是面向用户还是代码到代码:`exposes`(可见数据,支持对集合 `for` 迭代)、`provides`(可用操作,可带 when-guards)、`contracts:`(引用模块级 `contract` 声明,带 `demands`/`fulfils` 方向标记)、`@guarantee`(命名散文断言)、`@guidance`(非规范建议)、`related`(从本 surface 可达的关联 surface)、`timeout`(引用适用于该 surface 上下文的时间规则)。
- `facing` 子句接受 actor 类型(带对应 `actor` 声明和 `identified_by` 映射)或直接接受实体类型。边界有特定身份要求时用 actor 声明;任意实例可交互时用实体类型(如 `facing visitor: User`)。外部方是代码的集成 surface,声明 actor 类型并给最小 `identified_by` 表达式。actor 的 `identified_by` 引用 `within` 时必须声明期望上下文类型:`within: Workspace`。
- Surface-to-implementation contract:`exposes` 块是字段级契约;实现恰好返回这些字段,消费者恰好使用这些字段;不要添加未列字段,不要省略已列字段。
- 用 `contract Codec { serialize: (value: Any) -> ByteArray deserialize: (bytes: ByteArray) -> Any @invariant Roundtrip ... }` 声明契约;contracts 是模块级声明,在 surface `contracts:` 子句中按名称引用(`demands Codec`、`fulfils EventSubmitter`)。声明语法和引用规则见 `references/language-reference.md#contracts`。
- 表达式用法:导航 `interview.candidacy.candidate.email`、可选 `reply_to?.author`、null coalescing `timezone ?? "UTC"`;集合 `slots.count`、`slot in invitation.slots`、`interviewers.any(i => i.can_solo)`、`for item in collection: item.status = cancelled`、`permissions + inherited`(集合并)、`old - new`(集合差);比较 `status = pending`、`count >= 2`、`status in {confirmed, declined}`、`provider not in providers`;布尔 `a and b`、`a or b`、`not a`、`a implies b`。
- 模块化规格:用 `use "github.com/allium-specs/google-oauth/abc123def" as oauth` 引用;用限定名引用跨规格实体(`oauth/Session`);坐标不可变(git SHAs 或 content hashes);本地规格用相对路径:`use "./candidacy.allium" as candidacy`。
- 用 `config { invitation_expiry: Duration = 7.days max_login_attempts: Integer = 5 extended_expiry: Duration = invitation_expiry * 2 sync_timeout: Duration = core/config.default_timeout }` 定义配置;规则用 `config.invitation_expiry` 引用配置值;默认实体实例用 `default`。
- 用 `default Role viewer = { name: "viewer", permissions: { "documents.read" } }` 定义默认值。
- 用 `invariant NonNegativeBalance { for account in Accounts: account.balance >= 0 }` 编写表达式不变量;它们断言实体状态属性,是逻辑断言不是运行时检查。与 contract 中的散文注解 `@invariant Name` 区分:后者用 `@` 标记检查器不求值的内容。见 `references/language-reference.md#invariants`。
- 用 transition graph(v3):在实体中声明 `transitions status { pending -> confirmed ... terminal: delivered, cancelled }` 来约束状态转换。
- 用 state-dependent field presence(v3):字段可带条件存在,如 `tracking_number: String when status = shipped | delivered`、`shipped_at: Timestamp when status = shipped | delivered`。
- 用 `deferred InterviewerMatching.suggest -- see: detailed/interviewer-matching.allium` 标记延迟规格。
- 用 `open question "Admin ownership - should admins be assigned to specific roles?"` 记录未决问题。
- 当 `allium` CLI 已安装时,依赖 hook 在每次 write/edit 后自动验证 `.allium` 文件;在呈现结果前修复报告的问题。
- 如果 `allium` CLI 不可用,对照 `references/language-reference.md` 验证。
- 需要完整语法时查阅 `references/language-reference.md`:entities、rules、expressions、surfaces、contracts、invariants 和 validation。
- 需要从规格生成测试时查阅 `references/test-generation.md`。
- 需要收集上下文 → 采取行动 → 验证 → 重复的完整走查、spec-first 和 code-first walkthrough 时查阅 `references/recommended-loops.md`。
- 需要 `/allium` 驱动目标到收敛的程序时查阅 `references/driving-the-loop.md`:入口检测、tick、停止条件、ledger。
- 在扇出目标整合切片时执行 reduce 步骤:组装切片、用 `allium analyse` 交叉检查接缝、调和并 witness 整体;见 `references/integrating-slices.md`。
- 需要已工作的模式时查阅 `references/patterns.md`:9 个模式包括 auth、RBAC、invitations、soft delete、notifications、usage limits、comments、library spec integration、framework integration contract。
适用边界 · 注意事项
- 不要用 Allium 指定编程语言/框架选择、数据库 schema 或存储机制、API 设计或 UI 布局、内部算法(除非它们是域级关注)。
- 不要生成或依赖单元测试;Allium 生成集成和端到端测试。
- 不要在不需要规格/测试契约协同、只想直接写应用代码时套用 Allium 循环;Allium 只产出 spec 和 tests,实现是普通编码。