其他
从零散或模糊需求出发,用分阶段结构化对话挖掘需求并写成…
当用户要从头创建规格、收集需求、描述领域行为或功能、把口述功能整理成规格时,用分阶段问答的引导式对话逐步产出 Allium 规格。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 35/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 39/100 ×0.15
适用场景
从零散或模糊需求出发,用分阶段结构化对话特定
解决思路
- 先界定规格边界:问「这个规格的边界是什么?」——整套系统、单个功能域还是大系统中的一个服务,并明确写出什么在范围内、什么在范围外。
- 问「有没有要刻意排除的部分?」第三方集成可能属于库规格,遗留功能可能不值得写规格,有些功能应拆成独立规格。
- 问「这是新系统还是已有代码?」若有代码,就是在做 distillation 加 elicitation,已有代码会约束哪些内容现实可写。
- 在每个 spec 开头记录范围决策,用 `-- Scope:` / `-- Includes:` / `-- Excludes:` / `-- Dependencies:` 注释块;每个 `.allium` 文件第一行必须是版本标记 `-- allium: N`,N 用当前语言版本号。
- 对每个细节做「Why」测试:问「干系人为什么在意这个细节?」在乎的写进去(如支持 Google 和 Microsoft OAuth 让用户自选、会话 24 小时过期、密码至少 12 位、数据保留 7 年合规),纯实现细节不写(如会话存在 Redis、用 bcrypt 哈希)。
- 做「Could it be different?」测试:若换一种实现仍是同一系统,就抽象掉;若不能,就是领域层。例:通知渠道抽象成 `Notification.created(channel: ...)`;「面试官必须 3 小时内确认」保留具体时长;「用 PostgreSQL」不写。
- 做「Template vs Instance」测试:判断这是某类事物还是具体实例。Google OAuth、Slack、15 分钟、Greenhouse ATS 是实现实例;认证提供方、通知渠道、可配置的链接过期时长、外部候选人来源是领域模板。当实例本身就是竞争性领域关注点(如「我们专门集成 Salesforce」)时例外;拿不准就问干系人「如果换掉它,是变成另一个系统,还是只是另一种实现?」
- 校准抽象层级,避免过抽象(「用户可以做一些事」、写不出可测试断言、产品负责人说「但这没抓住……」)与过具体(提到技术、框架、API,或描述按钮、页面、表单等 UI 元素,实现团队反问「你为什么要规定我们怎么建」)。目标停在产品层,如「候选人可以接受或拒绝面试邀请」。
- 遇到具体数值时依次判断:这是不是设计决策(是则写入);是否可能因部署或客户而异(是则做成 config,如 `invitation_expiry: Duration = 7.days` 并在规则中引用 `config.invitation_expiry`);是否纯属任意(考虑要不要写)。
- 对复杂且持续演进的逻辑用黑盒:在 `ensures:` 中声明类似 `Suggestion.created(interviewers: InterviewerMatching.suggest(considering: {role.required_skills, Interviewer.skills, Interviewer.availability, Interviewer.recent_load}))`,说明存在该匹配算法、它考虑哪些输入、产出什么,但不写算法、权重和内部实现。
- 读用户初始输入决定起点:用户描述流程 → 从流程发现开始(见 `process-discovery.md`);用户直接点出实体 → 跳过流程发现,先定范围再补细节(见 `detail-elicitation.md`);用户只有模糊想法 → 用开放问题做流程发现(如「客户来求助时会发生什么?」);已有代码 → 指向 `distill` 技能或两者结合;已有 spec → 先读 spec,用 `../allium/references/assessing-specs.md` 判断成熟度,跳过已覆盖阶段,从每个实体真正需要的层级开始(有生命周期无规则就补细节,有规则无失败路径就补障碍)。
- Phase 0 流程发现:在套用 Allium 结构之前,先让用户用自己的话描述系统,捕获流程、角色和结果,再组织成构造;输出流程名与结果、大致步骤序列、已识别角色,足以写出粗粒度 spec(含转移图和开放问题);警惕过早跳到实体定义,在流程清晰前停在流程层。
- Phase 1 范围定义:问「这个系统根本上讲一句话是什么?」「系统从哪里开始、到哪里结束?什么在范围内、什么在范围外?」「用户是谁?有不同角色吗?」「有哪些已有系统集成?它们各自负责什么?」;若跳过了 Phase 0,补问「这个系统支持哪些关键流程?每个流程的成功是什么样?」,把实体识别锚定到流程而不是孤立地罗列名词;输出角色清单、核心实体清单、边界决策和一句话描述;警惕范围蔓延、被默认知识(如「显然它会处理认证」)跳过、以及像库规格的描述(OAuth、支付处理、邮件投递)。
- Phase 2 happy path:以 Phase 0 产出的 walking skeleton 为起点,否则问「如果只能构建一条路径,会是什么?」,把骨架写成粗粒度 spec 并用领域术语向用户复述;然后补齐「每一步由什么触发?谁参与?什么会改变?」,跟踪一个实体走完生命周期,捕获状态转移、角色和触发;输出关键实体的转移图、主触发及其结果、每一步的角色分配;警惕过早讨论边缘情况(记下来,先留在主流程)和实现细节渗入;写完构造后若 CLI 可用就运行 `allium check`,先修结构问题再继续。
- 确定骨架后,参照 `detail-elicitation.md` 补全规则、surfaces、字段和数据依赖。
- Phase 3 边缘与失败路径:用 pre-mortem「假设这个系统已经建成并且正在失败,出了什么问题?」;每一步问「如果这里没人做任何事呢?一天后?一周后?」;每个交接问「谁接手?他们怎么知道轮到自己?他们需要看到什么?」;每个转移问「前置条件不满足会怎样?这能回滚吗?」;对外部依赖问「这些信息怎么进入系统?外部服务不可用时怎么办?」;输出异常转移、带 `requires` 守卫的时序触发、升级路径、终态错误状态和不变量;警惕无限重试循环、缺少最终人工升级;把干系人陈述的系统级属性(如「余额永不为负」「同一候选人的面试不重叠」)写成顶层 `invariant Name { expression }`;写完规则和异常转移后运行 `allium check`。
- Phase 4 精炼:用领域术语复述 spec 说了什么,并与用户的心智模型对照,追踪具体场景、检验顺序假设、核对角色分配;若 CLI 可用就运行 `allium check`,用诊断定位结构性缺口,若有 `allium analyse` 且 spec 已有规则和 surfaces 就运行它,并用 `../allium/references/actioning-findings.md` 把发现翻译成领域问题;必问:「看 [实体],这些状态完整吗?还能处于别的状态吗?」「还有什么没覆盖?」「这条规则引用了 [X],需要定义它还是它是外部的?」「这个细节必须放在这里,还是应该放到一个详细 spec?」;用具体场景演练,如「假设 Alice 申请 Senior Engineer 岗位,带我走一遍她的候选流程」;输出完整实体定义、记录的开放问题、已识别的延后规格和确认的外部边界;当同一义务模式(如序列化契约、确定性求值要求)在多个 surface 重复出现时,建议抽成可复用的 `contract` 声明。
- 一次只问一个问题,不要问「你们有哪些实体、它们能处于什么状态、谁能修改它们」。
- 顺着推论往下追:不要接受第一个答案,例「你说邀请 48 小时后过期,然后呢?」「如果重试后候选人还是没回应呢?」「如果一直不回应,这个候选流程会永远卡住吗?」
- 区分产品与实现:听到实现语言就重定向——「API 返回 404」→「所以用户被告知它不存在?」;「存在 Postgres 里」→「捕获了哪些信息?」;「前端弹出一个模态框」→「用户被提示确认?」;「用 cron job」→「这是按计划发生的,多久一次?」
- 显式暴露歧义:宁可记录开放问题也不要假设,例「我不确定拒绝后是让候选人回到池子还是彻底移除,先记为开放问题」,并写 `open question "当候选人拒绝时,是回到池子还是退出?"`。
- 愿意迭代:修改早先的决定是正常的,例「先前我们说所有 admin 看到所有通知,但你现在描述按角色的仪表盘,要不要重新审视这一点?」
- 深度优先于广度:先把最重要的实体完整展开,其他保持粗粒度并留开放问题,用户可以下次会话再补;不要试图在一次对话里把所有实体做到同一深度,否则会在什么都没完成前耗尽上下文。
- 知道何时停止:把匹配算法怎么工作一类细节延后到详细 spec,把报告仪表盘一类内容拆成独立规格。
- 避开「Obviously」陷阱:听到「显然」「当然」就追问,例「你说显然由 admin 审批,有没有不需要审批的情况?以后能自动化吗?」
- 避开「Edge Case Spiral」陷阱:对方想立刻覆盖所有边缘情况时,说「先把它记为开放问题,我们留在主流程,稍后回来处理边缘情况」。
- 避开「Vague Agreement」陷阱:不要接受没有细节的「是」,例「你说候选人可以改期,可以几次?有上限吗?超过之后怎样?」
- 避开「Missing Actor」陷阱:警惕没有明确执行者的动作,例「你说『时段被释放了』,是谁或什么释放的?是自动的,还是有人触发?」
- 避开「Equivalent Terms」陷阱:听到同一概念有两个术语(来自不同干系人、已有代码或相关 spec)就停下来先解决——「你说 Purchase,但前面我们叫它 Order,用哪个术语?」选一个术语,交叉引用相关 spec 并更新所有引用,不要留下旧术语,连 see also 也别留。
- 按会话结构推进:开场简要说明「我们在记录软件做什么,而不是怎么构建」并约定本次范围;接着范围定义(角色、实体、边界、一句话描述);接着 happy path(状态、触发、结果);接着边缘情况(超时与截止时间、失败模式、升级路径);最后收尾——复述关键决策、列出开放问题、点明哪些实体仍然粗糙及下一步需要什么、必要时确定下次会话范围。在 LLM 对话中按阶段产出决定何时推进,而不是看时钟。
- 会话结束后分派后续动作:已知要什么的局部改动用 `tend`;需要结构化发现的大幅新增(新功能域、复杂实体关系、需求不清)仍用 elicit,即使 spec 已存在;核对 spec 与实现是否一致用 `weed`。
适用边界 · 注意事项
- 只做目标明确的局部修改时,用 `tend` 而不是 elicit。
- 需要核对规格与实现是否一致时,用 `weed` 而不是 elicit。
- 依赖 Allium 语言与 CLI(`.allium` 文件格式、`allium check`、`allium analyse`)以及配套参考文档,没有这套工具链时无法直接套用。