# Spec Driven Development — Chapter-16: 7 - Completing a Task: When the Obvious Hides Decisions - **Source**: /library/Spec Driven Development/source-file.pdf - **PDF pages**: 204–215 - **Pages without text**: none --- 7 - Completing a Task: When the Obvious Hides Decisions The state of git, again In Chapter 6 you walked the whole cycle for the first time: you took "create and list tasks", carried it from specify to merge , and the first feature of the To-Do came to exist as running code. The main branch went stable again, with one more capability than it had before. Now you are about to take the second lap, and the good news is that the map is the same. It is worth reopening it for just a moment, not to relearn it, but to get your bearings: It is the same diagram from Chapter 5; what changes is only where you stand on it. The main branch is clean, with the create- task feature already integrated, and the first step of the cycle opens, on its own, the branch for the feature of the moment: 002- concluir-tarefa . Notice that the branch belongs to the feature, numbered by the project, not by the chapter. What sets this chapter apart lies ahead, in a step that raced by in the first loop and now takes the focus. The feature of the moment, and specify at a light pace The To-Do backlog has the next slice waiting: completing a task, marking as done what you recorded in the previous loop. Along with it comes the action of going back, reopening. It is the second feature in the queue, and it only makes sense because the first one exists: with no task created, there is nothing to complete. You already learned how to specify in the previous loop; that is why specify runs light here. You describe the feature in a few lines, with what matters: the problem, the scope, and, with equal care, the non-goals. /speckit-specify Complete and reopen a task in a personal to-do list. A perso n can mark an existing task as done and go back by reopening it. Out of scope for this feature: a history of completions, saved completion date and time, m ulti-level undo, filtering and editing tasks. The non-goals here are the constitution's Simplicity and YAGNI acting before the first line of code even exists: you say, out loud, that you will not keep a history of completions, nor save date and time, nor build a multi-level undo. Filtering and editing are other features, from other chapters, and they stay where they are, in the backlog. It is cheap to write a non-goal and expensive to remove the code of a capability that never should have been born; the short sentence in the spec is what holds that account in check. And, as in the first loop, specify decides nothing about technology: the stack was already chosen and will be inherited when the time for plan arrives. In a few minutes the spec is standing: short, with two user stories (complete and reopen), the rules and the non-goals. It seems nothing is left to clarify. And that is exactly where this chapter's trap lives. "Completing" seems obvious. It is not. Read the intent again: "mark a task as done". It sounds transparent. Anyone understands what it means. The natural reaction, faced with a sentence like that, is to say there is nothing to ask, that it is just a matter of implementing. Hold on to that feeling, because it is exactly the ground where decisions hide. The more obvious an intent seems, the more dangerous the ambiguities it carries, because no one thinks to discuss them. This is where clarify comes in, and it is what the spotlight of this chapter falls on. Its job is simple to state and powerful in practice: it takes your spec, looks for the points that admit more than one reasonable interpretation (the ambiguities, the term you already met back in Chapter 2) and asks targeted questions, one at a time, before any plan is drawn. Run over the spec for "complete task", which seemed so clear, it raised questions no one in a hurry would have asked: 1. When a task is completed, does it disappear from the list or stay there, marked somehow? 2. Is completing reversible? Can you reopen what has been completed? 3. Does completion change the order of the list? Does the task go to the end, to a group of completed ones? 4. What happens when you try to complete a task that is already completed? Each of these questions was hidden inside the verb "complete", and none of them has a single answer: the word seemed to carry the answer on its own, but it carried four decisions disguised as one. Here is the point that holds up the entire chapter, and it is worth reading slowly: a question you do not answer in clarify does not disappear. It only changes place. If you ignore the question about the order of the list and send it off to be implemented, someone will decide for you: the agent. When it comes time to write the code, faced with the ambiguity no one resolved, it will pick some plausible path, maybe the wrong one, and move on without warning. We have a name for this, the agent's assumption: the decision the agent makes on its own, in implement , when an ambiguity was left open. What the agent has in front of it at the moment it decides, and how that material gets there, belongs to Context Engineering (2026, https://books.kodel.com.br/en/books/context-engineering/), the third volume in this trilogy, which answers what the agent sees right now, in the window of this one call, and at what cost. You do not need it here: this chapter's remedy comes earlier and costs less, which is keeping the ambiguity from ever reaching that point. clarify exists so that these decisions are yours, made early, with you in control, and not the agent's, late, in the dark. Deep dive: what idempotency is in a command. The fourth question ("completing what is already completed") points to a property with a name of its own: idempotency. An action is idempotent when applying it once or many times to the same state gives the same result. Pressing the button of an elevator that is already called does not call it "even more"; completing a task that is already completed should not complete it "twice" nor throw an error. Recognizing that an operation needs to be idempotent is the kind of decision that goes unnoticed until it turns into a bug, and it is exactly what a question at the right moment brings to the surface. The answers go back into the spec Raising the questions is half the work. The other half, the one that turns clarify from an interesting conversation into a step of the flow, is what happens to the answers. You decide each one, and clarify records them back into the spec. Deciding is up to you, and the criterion is the To-Do constitution, Simplicity and YAGNI up front. For our To-Do, the set of answers came out like this: the completed task stays on the list, shown struck through, and it stays in the same position as always, without reordering anything. Completing is reversible by an explicit reopen action. And completing what is already completed, or reopening what is already open, is an idempotent no-op. "No-op" is short for no operation: the action is accepted, it succeeds, and it simply does nothing because there is nothing to do. Completing a task that is already completed is exactly that, a success that changes nothing. No separate view of completed tasks, no history, no saved date. The minimum that answers the four questions well. A caveat this chapter makes a point of nailing down: these are the author's answers for the To-Do, not the only right ones. Another project could send the completed task to the end of the list, or hide it in a tab. What clarify teaches, before any answer, is that there is a decision to make, and that it is better to make it now, with eyes open. Now the detail that changes everything. The answers did not stay in the chat. clarify wrote them back into the spec itself, in a dated clarifications section, in the tool's real format: ## Clarifications ### Session 2026-06-27 - Q: When a task is completed, does it disappear from the list or stay visibl e? → A: It stays on the list, shown as completed (struck through/marked). The re is no separate view of completed tasks. - Q: Does completing a task change its position in the list? → A: No. The tas k stays in the same position (creation order is kept); completing does not re order the list. - Q: Is completing reversible? → A: Yes, by an explicit reopen action, which takes the task from completed back to open. - Q: What happens when you complete an already completed task (or reopen an a lready open one)? → A: It is an idempotent no-op: the operation succeeds and the state stays the same, with no additional effect. The artifact changed before your eyes. The spec that went into clarify ambiguous came out with the four decisions recorded, and each answer was also propagated to the right part of the document: the edge cases stopped being questions and became requirements, with idempotency and staying on the list written out in full. clarify did not talk about the spec. It changed the spec. And that is why the next gesture is safe. Right after clarify comes /clear , that habit of clearing the agent's context you settled on back there. Clearing now throws nothing away, because the decision does not live in the memory of the conversation: it lives in the versioned spec, on disk, in git. The next step will start by reading the file, not the chat. You can forget the entire discussion without losing a comma of what was decided. Deep dive: why clarify has a limit on questions. The tool does not ask everything it could: it works with a cap on questions per session, which forces it to prioritize the highest-impact ambiguities instead of sweeping every detail. Far from a limitation, the cap forces focus on what changes the plan and the code, and leaves the rest to your review. The exact number may change from one version of spec-kit to another, so check the official documentation when you need the precise value; what does not change is the idea of a limit that pushes prioritization.1 What changes down the line It may sound like too much effort for four little questions. The best way to measure that effort is to follow a single decision down the stream, from clarify to the code. Take the answer "completing is reversible". Without that answer, the agent would have built a one-way feature: mark as done and that's it. With it, the whole stream changes. When plan read the clarified spec, it did not design one operation, it designed two, inverse: one to complete, one to reopen. The tasks , faithful to the constitution's TDD, broke that into pairs of test and implementation for each of the two actions, plus the tests for the idempotent case. In the code, the pair shows up literal, two symmetric operations the domain exposes: complete-task.ts open ─▶ completed (completing an already completed one = no-op) reopen-task.ts completed ─▶ open (reopening an already open one = no-op) The other decision, "stays struck through in the same position", ran down the stream just the same. It shaped the task's state (one extra field, saying whether it is completed) and the way to display it (struck through, without moving), and it forced the repository to gain an operation to update the task without reordering the list. One sentence answered in clarify , and three artifacts down the line already knew what to do. Now imagine the counterfactual. If the reversibility question had been left open, the agent would have assumed. Maybe it would have assumed that completing is final, and you would only discover the problem when you tried to reopen a task and realized you could not. The fix, at that point, would no longer be changing one answer in a spec: it would be redoing the plan, the tasks, the tests and the code. What cost one question here would cost, down the line, a whole round of rework. The rest of the loop ran at a following pace, each step reading the artifact of the one before. Between plan and tasks , spec-kit runs the checklist , and it is worth a sentence so as not to confuse things: it is a quality gate for the requirements, a kind of "test for the spec", that checks whether the decisions from clarify came out clear and measurable before they turned into tasks: a test of what was specified, without touching code. The analyze checked the consistency between spec, plan and tasks, and the implement walked the list until the code existed, with the tests in the green. None of these steps stood under the spotlight here, because it is not their turn: each will have its own chapter further on, with the care it deserves. For now, they appear in passing, just enough for you to see the clarify decision propagating through all of them. Deep dive: how "error as value" shapes the invalid case. There is a case clarify did not need to raise because the constitution already answered it: what to do when you ask to complete a task that does not exist? By the error-as-value principle, this does not become an exception that blows up between the layers; it becomes an explicit failure result, which the caller is obliged to handle. Notice the fine distinction: the nonexistent task is a failure (an error result), but completing the already completed one is a success that changes nothing (the idempotent no-op). Two similar cases, different treatments, both decided on purpose and not in a scramble. How to distrust the obvious You saw clarify at work. The question that remains is more valuable than the command: how do you generate good questions like those on your own, even before running the tool? Because what protects a project, more than the step itself, is the habit of distrusting the obvious that the step trains. Looking at the four questions that mattered, you can distill a handful of angles that almost always hide decisions. Faced with any short intent, try running through them: Behavior: what exactly happens when the action succeeds? What does "complete" mean, on the screen and in the data? Reversibility: can it be undone? Is there an inverse action? Who can do it? State: which states can the thing take on, and which transitions between them are valid? Order and position: does the action change the order, the position, the grouping of something the person sees? Repetition: what happens if the action is repeated on the same target? Is it idempotent? Edge cases: what about when the target does not exist, is empty, or is already in the final state? Do not memorize this as a list to tick off. The value is in acquiring the reflex of looking at an apparently simple sentence and asking "what is this not telling me?". The more natural it becomes to ask those questions, the less you will depend on the tool to remember them for you, and the better the specs you write before clarify even runs. An intent like "archive a message" or "cancel an order" opens, under these angles, the same fan of hidden decisions that "complete a task" opened. And here it is worth undoing a confusion of words. This set of angles is not the checklist step of spec-kit. The checklist is that requirements quality gate that showed up in the previous section, a real step of the loop. What we just assembled is only a habit of reasoning, a way of thinking, that you use in your head before and during clarify . One is a step of the tool; the other is the mental reflex that makes you distrust the obvious. Do not confuse the memorized list with the step of the flow: they are different things with similar names. End of the loop and the bridge to Ch. 8 With the tests in the green, the loop closes the same way as in the previous lap. You commit the work, artifact by artifact, and merge the 002-concluir-tarefa branch back into main . The feature that began as a sentence is now running code: it marks tasks as completed, keeps them struck through in place, lets you reopen them and does not get confused when the action repeats. The main branch is stable again, with two capabilities where there was one. And the focus will move once more. The next feature in the backlog is filtering tasks: seeing only the open ones, only the completed ones, or all of them. That is a feature of a different nature, and the difference has a consequence: in Chapter 8, the spotlight shifts one more notch, to plan , the step where the how is decided. Footnotes Command names, the order of the steps, and the exact form of invocation may evolve between versions of spec-kit; the excerpts in this chapter were generated with version 0.11.8. For details that change per release (flags, subcommands, internal paths), check the official spec-kit documentation instead of fixing them from memory.