elicit

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Elicitation

需求获取

This skill guides you through building Allium specifications by conversation. The goal is to surface ambiguities and produce a specification that captures what the software does without prescribing implementation.
The same principles apply to distillation. Whether you are hearing a stakeholder describe a feature or reading code that implements it, the challenge is identical: finding the right level of abstraction.
此技能引导你通过对话构建Allium规范。目标是找出模糊点,生成一份仅描述软件功能、不规定实现方式的规范。
同样的原则也适用于提炼工作。无论是听取利益相关者描述功能,还是阅读实现功能的代码,面临的挑战都是相同的:找到合适的抽象层级。

Scoping the specification

规范范围界定

Before diving into details, establish what you are specifying. Not everything needs to be in one spec.
在深入细节之前,先明确要规范的内容。并非所有内容都需要放在一份规范里。

Questions to ask first

首先要问的问题

"What's the boundary of this specification?" A complete system? A single feature area? One service in a larger system? Be explicit about what is in and out of scope.
"Are there areas we should deliberately exclude?" Third-party integrations might be library specs. Legacy features might not be worth specifying. Some features might belong in separate specs.
"Is this a new system or does code already exist?" If code exists, you are doing distillation with elicitation. Existing code constrains what is realistic to specify.
“这份规范的边界是什么?” 是完整的系统?单一功能模块?大型系统中的某个服务?明确说明哪些内容在范围内,哪些不在。
“有没有我们需要刻意排除的内容?” 第三方集成可能属于库规范范畴。遗留功能可能不值得进行规范。有些功能可能适合放在单独的规范中。
“这是全新系统还是已有代码?” 如果已有代码,你需要在获取需求的同时进行提炼工作。现有代码会限制规范的可行性。

Documenting scope decisions

记录范围决策

Capture scope at the start of every spec:
-- allium: 3
-- interview-scheduling.allium

-- Scope: Interview scheduling for the hiring pipeline
-- Includes: Candidacy, Interview, Slot management, Invitations, Feedback
-- Excludes:
--   - Authentication (use oauth library spec)
--   - Payments (not applicable)
--   - Reporting dashboards (separate spec)
-- Dependencies: User entity defined in core.allium
The version marker (
-- allium: N
) must be the first line of every
.allium
file. Use the current language version number.
在每份规范的开头记录范围信息:
-- allium: 3
-- interview-scheduling.allium

-- Scope: Interview scheduling for the hiring pipeline
-- Includes: Candidacy, Interview, Slot management, Invitations, Feedback
-- Excludes:
--   - Authentication (use oauth library spec)
--   - Payments (not applicable)
--   - Reporting dashboards (separate spec)
-- Dependencies: User entity defined in core.allium
版本标记(
-- allium: N
)必须是每个
.allium
文件的第一行。使用当前的语言版本号。

Finding the right level of abstraction

找到合适的抽象层级

The hardest part of specification is choosing what to include and what to leave out. Too concrete and you are specifying implementation. Too abstract and you are not saying anything useful.
规范编写最困难的部分是选择要包含和排除的内容。过于具体就变成了规定实现方式,过于抽象则没有实际意义。

The "Why" test

“为什么”测试

For every detail, ask: "Why does the stakeholder care about this?"
DetailWhy?Include?
"Users log in with Google OAuth"They need to authenticateMaybe not, "Users authenticate" might be sufficient
"We support Google and Microsoft OAuth"Users choose their providerYes, the choice is domain-level
"Sessions expire after 24 hours"Security/UX decisionYes, affects user experience
"Sessions are stored in Redis"PerformanceNo, implementation detail
"Passwords must be 12+ characters"Security policyYes, affects users
"Passwords are hashed with bcrypt"Security implementationNo, how not what
对于每个细节,都要问:“利益相关者为什么关心这个?”
细节原因?是否包含?
“用户通过Google OAuth登录”需要身份验证可能不需要,“用户进行身份验证”就足够
“我们支持Google和Microsoft OAuth”用户可以选择提供商是,选择权属于领域层面
“会话24小时后过期”安全/用户体验决策是,会影响用户体验
“会话存储在Redis中”性能需求否,属于实现细节
“密码必须至少12个字符”安全策略是,会对用户产生影响
“密码使用bcrypt哈希”安全实现方式否,关注“做什么”而非“怎么做”

The "Could it be different?" test

“是否可以不同?”测试

Ask: "Could this be implemented differently while still being the same system?"
  • If yes, it is probably an implementation detail. Abstract it away.
  • If no, it is probably domain-level. Include it.
Examples:
  • "Notifications sent via Slack". Could be email, SMS, etc. Abstract to
    Notification.created(channel: ...)
    .
  • "Interviewers must confirm within 3 hours". This specific deadline matters at the domain level. Include the duration.
  • "We use PostgreSQL". Could be any database. Do not include.
  • "Data is retained for 7 years for compliance". Regulatory requirement. Include.
问:“这部分是否可以用不同方式实现,但系统本质不变?”
  • 如果是,它可能是实现细节,应该进行抽象。
  • 如果否,它可能属于领域层面,应该包含进来。
示例:
  • “通过Slack发送通知”。可以换成邮件、短信等,抽象为
    Notification.created(channel: ...)
  • “面试官必须在3小时内确认”。这个具体期限属于领域层面的关键要求,需要包含时长。
  • “我们使用PostgreSQL”。可以换成任何数据库,不需要包含。
  • “数据需保留7年以符合合规要求”。监管要求,需要包含。

The "Template vs Instance" test

“模板 vs 实例”测试

Is this a category of thing, or a specific instance?
Instance (implementation)Template (domain-level)
Google OAuthAuthentication provider
SlackNotification channel
15 minutesLink expiry duration (configurable)
Greenhouse ATSExternal candidate source
Sometimes the instance IS the domain concern. "We specifically integrate with Salesforce" might be a competitive feature. "We support exactly these three OAuth providers" might be design scope.
When in doubt, ask the stakeholder: "If we changed this, would it be a different system or just a different implementation?"
这是一类事物,还是具体实例?
实例(实现层面)模板(领域层面)
Google OAuth身份验证提供商
Slack通知渠道
15分钟链接过期时长(可配置)
Greenhouse ATS外部候选人来源
有时实例本身就是领域关注点。“我们专门与Salesforce集成”可能是一项竞争优势功能。“我们仅支持这三个OAuth提供商”可能属于设计范围。
不确定时,询问利益相关者:“如果我们更改这部分,系统会变成不同的系统,还是只是实现方式不同?”

Levels of abstraction

抽象层级示例

Too abstract:          "Users can do things"
                              |
Product level:         "Candidates can accept or decline interview invitations"
                              |
Too concrete:          "Candidates click a button that POST to /api/invitations/:id/accept"
Signs you are too abstract. The spec could describe almost any system. No testable assertions. Product owner says "but that doesn't capture..."
Signs you are too concrete. You are mentioning technologies, frameworks or APIs. You are describing UI elements (buttons, pages, forms). The implementation team says "why are you dictating how we build this?"
过于抽象:          "用户可以执行操作"
                              |
产品层面:         "候选人可以接受或拒绝面试邀请"
                              |
过于具体:          "候选人点击按钮,向/api/invitations/:id/accept发送POST请求"
过于抽象的迹象:规范几乎可以描述任何系统,没有可测试的断言,产品负责人会说“但这没有涵盖……”
过于具体的迹象:提到技术、框架或API,描述UI元素(按钮、页面、表单),实现团队会说“为什么要规定我们如何构建?”

Configuration vs hardcoding

配置 vs 硬编码

When you encounter a specific value (3 hours, 7 days, etc.), ask:
  1. Is this value a design decision? Include it.
  2. Might it vary per deployment or customer? Make it configurable.
  3. Is it arbitrary? Consider whether to include it at all.
-- Hardcoded design decision
rule InvitationExpires {
    when: invitation: Invitation.created_at + 7.days <= now
    ...
}

-- Configurable
config {
    invitation_expiry: Duration = 7.days
}

rule InvitationExpires {
    when: invitation: Invitation.created_at + config.invitation_expiry <= now
    ...
}
遇到具体数值(3小时、7天等)时,问自己:
  1. 这个数值是设计决策吗? 如果是,包含进来。
  2. 它可能因部署环境或客户不同而变化吗? 如果是,设为可配置项。
  3. 它是任意设定的吗? 考虑是否需要包含。
-- 硬编码的设计决策
rule InvitationExpires {
    when: invitation: Invitation.created_at + 7.days <= now
    ...
}

-- 可配置项
config {
    invitation_expiry: Duration = 7.days
}

rule InvitationExpires {
    when: invitation: Invitation.created_at + config.invitation_expiry <= now
    ...
}

Black boxes

黑盒处理

Some logic is important but belongs at a different level:
-- Black box: we know it exists and what it considers, but not how
ensures: Suggestion.created(
    interviewers: InterviewerMatching.suggest(
        considering: {
            role.required_skills,
            Interviewer.skills,
            Interviewer.availability,
            Interviewer.recent_load
        }
    )
)
The spec says there is a matching algorithm, that it considers these inputs and that it produces interviewer suggestions. The spec does not say how matching works, what weights are used or the specific algorithm.
This is the right level when the algorithm is complex and evolving, when product owners care about inputs and outputs rather than internals, and when a separate detailed spec could cover it if needed.
有些逻辑很重要,但属于不同层级:
-- 黑盒:我们知道它存在,知道它考虑的因素,但不知道具体实现方式
ensures: Suggestion.created(
    interviewers: InterviewerMatching.suggest(
        considering: {
            role.required_skills,
            Interviewer.skills,
            Interviewer.availability,
            Interviewer.recent_load
        }
    )
)
规范说明存在匹配算法,它考虑这些输入并生成面试官建议,但没有说明匹配的工作方式、权重或具体算法。
当算法复杂且不断演进、产品负责人只关心输入输出而非内部逻辑,以及需要时可以单独编写详细规范时,这是合适的抽象层级。

Elicitation methodology

需求获取方法

Phase 1: Scope definition

阶段1:范围定义

Goal: Understand what we are specifying and where the boundaries are.
Questions to ask:
  1. "What is this system fundamentally about? In one sentence?"
  2. "Where does this system start and end? What's in scope vs out?"
  3. "Who are the users? Are there different roles?"
  4. "What are the main things being managed, the nouns?"
  5. "Are there existing systems this integrates with? What do they handle?"
Outputs: List of actors and roles. List of core entities. Boundary decisions (what is external). One-sentence description.
Watch for: Scope creep ("and it also does X, Y, Z", gently refocus). Assumed knowledge ("obviously it handles auth", make explicit).
目标:明确要规范的内容及其边界。
要问的问题:
  1. “这个系统的核心是什么?用一句话概括?”
  2. “这个系统的起止范围是什么?哪些内容在范围内,哪些不在?”
  3. “用户是谁?有没有不同的角色?”
  4. “主要管理的对象是什么,也就是核心名词?”
  5. “是否有需要集成的现有系统?它们负责处理什么?”
输出:参与者和角色列表、核心实体列表、边界决策(外部内容)、一句话描述。
注意事项:范围蔓延(“它还能做X、Y、Z”,温和地将话题拉回)、默认假设(“显然它处理身份验证”,要明确记录)。

Phase 2: Happy path flow

阶段2:主流程梳理

Goal: Trace the main journey from start to finish.
Questions to ask:
  1. "Walk me through a typical [X] from start to finish"
  2. "What happens first? Then what?"
  3. "What triggers this? A user action? Time passing? Something else?"
  4. "What changes when that happens? What state is different?"
  5. "Who needs to know when this happens? How?"
Technique: Follow one entity through its lifecycle.
Candidacy:
  pending_scheduling -> scheduling_in_progress -> scheduled ->
  interview_complete -> feedback_collected -> decided
Outputs: State machines for key entities. Main triggers and their outcomes. Communication touchpoints.
Watch for: Jumping to edge cases too early ("but what if...", note it and stay on happy path). Implementation details creeping in ("the API endpoint...", redirect to outcomes).
目标:从头到尾梳理主要流程。
要问的问题:
  1. “带我走一遍典型的[X]流程,从开始到结束”
  2. “第一步是什么?接下来呢?”
  3. “触发这个动作的是什么?用户操作?时间推移?还是其他?”
  4. “发生这个动作后有什么变化?状态有何不同?”
  5. “谁需要知道这个动作的发生?如何通知他们?”
技巧:跟踪一个实体的完整生命周期。
Candidacy:
  pending_scheduling -> scheduling_in_progress -> scheduled ->
  interview_complete -> feedback_collected -> decided
输出:关键实体的状态机、主要触发器及其结果、沟通触点。
注意事项:过早跳到边缘情况(“但如果……”,记录下来并继续关注主流程)、混入实现细节(“API端点……”,转而去关注结果)。

Phase 3: Edge cases and errors

阶段3:边缘情况与错误处理

Goal: Discover what can go wrong and how the system handles it.
Questions to ask:
  1. "What if [actor] doesn't respond?"
  2. "What if [condition] isn't met when they try?"
  3. "What if this happens twice? Or in the wrong order?"
  4. "How long should we wait before [action]?"
  5. "When should a human be alerted to intervene?"
  6. "What if [external system] is unavailable?"
Technique: For each rule, ask "what are all the ways requires could fail?"
Outputs: Timeout and deadline rules. Retry and escalation logic. Error states. Recovery paths.
Watch for: Infinite loops ("then it retries, then retries again...", need terminal states). Missing escalation, because eventually a human needs to know.
When stakeholders state system-wide properties ("balance never goes negative", "no two interviews overlap for the same candidate"), these are candidates for top-level invariants. Capture them as
invariant Name { expression }
declarations.
目标:发现可能出现的问题以及系统的处理方式。
要问的问题:
  1. “如果[参与者]没有回应怎么办?”
  2. “如果他们尝试时[条件]不满足怎么办?”
  3. “如果这个动作发生两次?或者顺序错误怎么办?”
  4. “我们应该等待多久再执行[动作]?”
  5. “什么时候需要通知人工介入?”
  6. “如果[外部系统]不可用怎么办?”
技巧:针对每条规则,问“要求可能以哪些方式不满足?”
输出:超时和截止规则、重试和升级逻辑、错误状态、恢复路径。
注意事项:无限循环(“然后重试,再重试……”,需要终止状态)、缺失升级机制,因为最终需要人工介入。
当利益相关者提出系统级属性(“余额永远不会为负”、“同一候选人不会有重叠的面试”)时,这些可以作为顶级不变量的候选,记录为
invariant Name { expression }
声明。

Phase 4: Refinement

阶段4:规范细化

Goal: Clean up the specification and identify gaps.
Questions to ask:
  1. "Looking at [entity], are these states complete? Can it be in any other state?"
  2. "Is there anything we haven't covered?"
  3. "This rule references [X], do we need to define that, or is it external?"
  4. "Is this detail essential here, or should it live in a detailed spec?"
Technique: Read back the spec and ask "does this match your mental model?"
Outputs: Complete entity definitions. Open questions documented. Deferred specifications identified. External boundaries confirmed.
When the same obligation pattern (e.g. a serialisation contract, a deterministic evaluation requirement) appears across multiple surfaces, suggest extracting it as a
contract
declaration for reuse.
目标:整理规范并找出漏洞。
要问的问题:
  1. “看这个[实体],这些状态完整吗?它还能处于其他状态吗?”
  2. “有没有我们没覆盖到的内容?”
  3. “这条规则引用了[X],我们需要定义它,还是它属于外部内容?”
  4. “这个细节在这里是必要的,还是应该放在详细规范中?”
技巧:通读规范并问“这符合你的预期吗?”
输出:完整的实体定义、记录的待解决问题、确定的延迟规范、确认的外部边界。
当相同的约束模式(例如序列化契约、确定性评估要求)出现在多个场景中时,建议将其提取为
contract
声明以便复用。

Elicitation principles

需求获取原则

Ask one question at a time

一次只问一个问题

Bad: "What entities do you have, and what states can they be in, and who can modify them?"
Good: "What are the main things this system manages?" Then: "Let's take [Candidacy]. What states can it be in?" Then: "Who can change a candidacy's state?"
错误示例:“你们有哪些实体,它们可以处于哪些状态,谁可以修改它们?”
正确示例:“这个系统主要管理哪些对象?” 然后:“我们来看[候选人资格]。它可以处于哪些状态?” 然后:“谁可以更改候选人资格的状态?”

Work through implications

探讨决策的影响

When a choice arises, do not just accept the first answer. Explore consequences.
"You said invitations expire after 48 hours. What happens then?" "And if the candidate still hasn't responded after we retry?" "What if they never respond, is this candidacy stuck forever?"
This surfaces decisions they have not made yet.
当做出选择时,不要只接受第一个答案,要探索后果。
“你说邀请48小时后过期。过期后会发生什么?” “如果我们重试后候选人仍未回应怎么办?” “如果他们永远不回应,这个候选人资格会一直处于停滞状态吗?”
这会暴露他们尚未做出的决策。

Distinguish product from implementation

区分产品需求与实现细节

When you hear implementation language, redirect:
They sayYou redirect
"The API returns a 404""So the user is informed it's not found?"
"We store it in Postgres""What information is captured?"
"The frontend shows a modal""The user is prompted to confirm?"
"We use a cron job""This happens on a schedule, how often?"
听到实现相关的表述时,引导话题转向产品层面:
他们的表述你的引导
“API返回404”“也就是说用户会被告知资源不存在?”
“我们把它存储在Postgres中”“需要捕获哪些信息?”
“前端显示一个弹窗”“用户会被提示确认吗?”
“我们使用定时任务”“这是按计划执行的,频率是多少?”

Surface ambiguity explicitly

明确指出模糊点

Better to record an open question than assume.
"I'm not sure whether declining should return the candidate to the pool or remove them entirely. Let me note that as an open question."
open question "When candidate declines, do they return to pool or exit?"
记录待解决问题比假设更好。
“我不确定拒绝邀请后,候选人应该回到候选池还是被移除。我把这个记录为待解决问题。”
open question "When candidate declines, do they return to pool or exit?"

Use concrete examples

使用具体示例

Abstract discussions get stuck. Ground them.
"Let's say Alice is a candidate for the Senior Engineer role. She's been sent an invitation with three slots. Walk me through what happens when she clicks on Tuesday 2pm."
抽象讨论容易陷入僵局,要用具体案例支撑。
“假设Alice是高级工程师岗位的候选人,她收到了带有三个时间段的邀请。带我走一遍她点击周二下午2点后的流程。”

Iterate willingly

愿意迭代修改

It is normal to revise earlier decisions.
"Earlier we said all admins see all notifications. But now you're describing role-specific dashboards. Should we revisit that?"
修改之前的决策是正常的。
“之前我们说所有管理员都能看到所有通知,但现在你描述的是基于角色的仪表盘。我们要不要重新考虑这个问题?”

Know when to stop

知道何时停止

Not everything needs to be specified now.
"This is getting into how the matching algorithm works. Should we defer that to a detailed spec?"
"We've covered the main flow. The reporting dashboard sounds like a separate specification."
并非所有内容都需要现在就规范。
“这已经涉及到匹配算法的工作方式了。我们要不要把这个推迟到详细规范中?”
“我们已经覆盖了主流程。报告仪表盘听起来属于单独的规范。”

Common elicitation traps

常见的需求获取陷阱

The "Obviously" trap

“显然”陷阱

When someone says "obviously" or "of course", probe. "You said obviously the admin approves. Is there ever a case where they don't need to? Could this be automated later?"
当有人说“显然”或“当然”时,要进一步追问。“你说显然需要管理员批准。有没有不需要管理员批准的情况?以后可以自动化吗?”

The "Edge Case Spiral" trap

“边缘情况螺旋”陷阱

Some people want to cover every edge case immediately. "Let's capture that as an open question and stay on the main flow for now. We'll come back to edge cases."
有些人想立即覆盖所有边缘情况。“我们把这个记录为待解决问题,先专注于主流程。之后再回来处理边缘情况。”

The "Technical Solution" trap

“技术解决方案”陷阱

Engineers especially jump to solutions. "I hear you saying we need real-time updates. At the domain level, what does the user need to see and when?"
工程师尤其容易直接跳到解决方案。“我听到你说我们需要实时更新。从领域层面来看,用户需要看到什么,什么时候看到?”

The "Vague Agreement" trap

“模糊共识”陷阱

Do not accept "yes" without specifics. "You said yes, candidates can reschedule. How many times? Is there a limit? What happens after that?"
不要接受没有具体细节的“是”。“你说候选人可以重新安排面试。可以重新安排多少次?有没有限制?超过限制后会怎样?”

The "Missing Actor" trap

“缺失参与者”陷阱

Watch for actions without clear actors. "You said 'the slots are released'. Who or what releases them? Is it automatic, or does someone trigger it?"
注意没有明确参与者的动作。“你说‘时间段被释放’。谁或什么触发释放?是自动的,还是有人触发?”

The "Equivalent Terms" trap

“术语等价”陷阱

When you hear two terms for the same concept, from different stakeholders, existing code or related specs, stop and resolve it before continuing.
"You said 'Purchase' but earlier we called this an 'Order'. Which term should we use?"
A comment noting that two terms are equivalent is not a resolution. It guarantees both will appear in the implementation. Pick one term, cross-reference related specs and update all references. Do not leave the old term anywhere, not even in "see also" notes.
当从不同利益相关者、现有代码或相关规范中听到同一概念的两个术语时,先解决术语统一问题再继续。
“你说‘Purchase’,但之前我们称之为‘Order’。我们应该用哪个术语?”
仅注释说明两个术语等价不算解决问题,这会导致实现中同时出现两个术语。选择一个术语,交叉引用相关规范并更新所有引用,不要保留旧术语,即使是在“另请参阅”注释中。

Elicitation session structure

需求获取会议结构

Opening (5 min). Explain Allium briefly: "We're capturing what the software does, not how it's built." Set expectations: "I'll ask lots of questions, some obvious-seeming." Agree on scope for this session.
Scope definition (10-15 min). Identify actors, entities, boundaries. Get the one-sentence description.
Happy path (20-30 min). Trace main flow start to finish. Capture states, triggers, outcomes. Note communications.
Edge cases (15-20 min). Timeouts and deadlines. Failure modes. Escalation paths.
Wrap-up (5-10 min). Read back key decisions. List open questions. Identify next session scope if needed.
After session. Write up specification draft. Send for review. Note questions for next session.
开场(5分钟):简要介绍Allium:“我们正在记录软件的功能,而非构建方式。” 设定预期:“我会问很多问题,有些看起来很明显。” 确定本次会议的范围。
范围定义(10-15分钟):确定参与者、实体、边界。获取一句话描述。
主流程梳理(20-30分钟):从头到尾梳理主流程。记录状态、触发器、结果。标记沟通环节。
边缘情况处理(15-20分钟):超时和截止时间、故障模式、升级路径。
收尾(5-10分钟):回顾关键决策。列出待解决问题。确定下次会议的范围(如有需要)。
会后工作:编写规范草稿。发送审核。记录下次会议的待讨论问题。

After elicitation

需求获取之后

For targeted changes where you already know what you want, use the
tend
skill. For substantial additions that need structured discovery (new feature areas, complex entity relationships, unclear requirements), elicit is still the right tool even if a spec already exists. Checking alignment between specs and implementation belongs to the
weed
skill.
对于目标明确的变更,使用
tend
技能。对于需要结构化探索的重大新增内容(新功能模块、复杂实体关系、不明确的需求),即使已有规范,仍需使用elicitation技能。检查规范与实现是否一致属于
weed
技能的范畴。

References

参考资料

  • Language reference, full Allium syntax
  • Recognising library spec opportunities, signals, questions and decision framework for identifying library specs during elicitation
  • 语言参考,完整的Allium语法
  • 识别库规范机会,需求获取过程中识别库规范的信号、问题和决策框架