Hardening a spec you didn't write
You're handed a build spec someone else wrote and asked to harden it. The temptation is to fix everything you see — which is exactly how you quietly make decisions that were never yours to make.
You're handed a build spec someone else wrote and asked to harden it before it goes to the client. The temptation is to fix everything you see — to treat every ambiguity as a defect and resolve it on the spot. That's how you quietly make decisions that were never yours to make, and how a hardening pass turns into an overreach nobody asked for.
The document in this case was a build specification for a master-data-management hub — the system that decides which of a client's records are the same real-world entity and mints the golden identifiers everything else keys on. Version 1.1, a bronze/silver/gold medallion data model, 69 addressable requirement IDs, and a functional requirements document about to be derived from it. "Harden" meant a pre-FRD pass: find the gaps, ambiguities, contradictions, and missing edge cases, and make recommendations on the open decision items. The pass surfaced 23 findings — five contradictions, six ambiguities, nine unhandled edge cases, three testability problems; four rated high severity.
Twenty-three findings, and one fork in the road before touching any of them: what are you actually allowed to do about each one?
Two bins, not one
The move that kept it clean was sorting every finding into one of two bins before editing a single line.
FOLD — clarifications you're certain about, the kind that carry no business-policy weight. These get merged into a new version of the document, every edit recorded in a §0 change log so the trail is auditable. Real examples from this pass:
- A state-model diagram labeled one state as the silver-to-gold boundary while the prose said records in that state were still silver. Only one reading was safe — no golden key exists yet — so the contradiction was resolved to it.
- A bronze-layer entity carried a
cleansed_namefield, but cleansing is the step that produces the silver record. The field couldn't exist where the spec put it. - A worked example showed three distinct silver-layer rows all bearing the same company name, accidentally implying they were duplicates of one another. A footnote fixed what a careless reader would have taken away.
- A merge event carried an effective date whose meaning was never pinned down — audit metadata, or does it gate when the redirect takes effect? Folding in a definition removed a whole class of future argument.
DECIDE — open questions that belong to the client: anything where a reasonable owner might choose differently, or where the choice has consequences you don't have the authority to accept. These you do not resolve. You surface them. From the same pass:
- Should merges and newly minted golden keys require maker/checker approval? Segregation of duties is a policy, not a clarification.
- How do changes propagate to consuming systems — lookup API, change events, or both, and at what contract level?
- When a source system offers no stable key, may a name ever serve as identity?
- What happens to records that cannot be matched at all?
The line between the bins is one question: would the client be surprised that I chose this? If yes, it's a DECIDE. The operative version in the memo was drier — "non-policy clarification" versus "needs a policy decision" — but it's the same test. Bain's RAPID framework gives it an org-chart name: the Recommend role gathers input and develops the recommendation; a distinct Decide role makes the call and commits the organization. A hardening pass is volunteering for R while making very sure you never sit down in D.
When you harden a document you don't own, your job is to remove the ambiguity you're certain about and surface the ambiguity you're not — never to quietly absorb decisions that belong to someone else.
This division of labor is also what the review literature says reviews are actually good at. Microsoft's study of modern code review — Bacchelli and Bird, ICSE 2013 — found that although defect-finding is the stated motivation, reviews turn out to be "less about defects than expected," with the real value in understanding and knowledge transfer. A hardening memo is that finding put to work: the FOLD bin is understanding written back into the document, and the DECIDE bin is an honest map of exactly where your understanding ends and the owner's judgment has to begin.
Some findings straddle the line — split them
The two bins sound cleaner than reality, and the exceptions taught me the most. Four or five of the 23 findings refused to sit in either bin, and every one of them, on inspection, was a mechanism question welded to a policy question. Take idempotent submissions: how to construct the idempotency key — source system plus source key — is pure mechanism, safely foldable. What a re-submission of a previously merged record means is policy that can change business outcomes. The wrong move is forcing the whole finding into one bin. The right move is to split it: fold the mechanism half, surface the policy half with its own recommendation. If you catch yourself agonizing over which bin a finding belongs in, that's usually the tell that it's two findings.
The final tally: fifteen findings folded outright into v1.2, seven open decisions surfaced to the client, and the stragglers contributing one half to each bin.
Recommend, don't mandate
A DECIDE item isn't a question lobbed back over the wall. Each one ships with a recommended default — your professional read of the right answer — that the client can accept in a single pass or override deliberately. So the segregation-of-duties item went out as "configurable maker/checker, default ON for merges and new golden keys." The source-key item went out as "require a stable source identifier where one exists; a name may serve only as a last resort, and never as identity."
The reason to bother is one of the most robust results in decision science: defaults mostly win. Johnson and Goldstein's organ-donation study found effective-consent rates around 4–27% in opt-in countries against near-total consent in opt-out ones — the same choice, decided overwhelmingly by which answer was pre-filled. Your client will, most of the time, take your default. That isn't a trick; it's the service being purchased. It also means the default had better be the answer you're prepared to defend in production, because attaching a recommendation is doing the thinking while leaving them the decision — the difference between advice and a quiz.
Prove coverage when coverage is claimed
This particular spec declared that every requirement ID was in scope for the functional requirements — all 69 of them, spanning lifecycle states, processes, outcomes, business rules, entities, non-functional requirements, and change-control rules. The right response wasn't to assert back that we'd covered them. It was to build the reverse-coverage matrix that demonstrates it, shipped as an appendix: every ID mapped to at least one functional requirement, mechanically, no empty cells. Bidirectional traceability is standard requirements-engineering discipline — it's baked into ISO/IEC/IEEE 29148, and the FHWA systems-engineering guide has a readable version — but the consulting point is sharper than the standards point: when a source document states an obligation, build the artifact that proves you met it. Assertions are cheap; matrices are checkable.
Guard the cross-references
The spec carried a scar from a previous revision: a heading that read, in effect, "§9 — reserved; content merged into §8; numbering preserved for stability of downstream references." Someone had already learned that renumbering breaks every document that points at yours. The hardening pass adopted the rule wholesale: v1.2 renumbers nothing, deprecates rather than deletes, and the verification checklist ends with one mechanical step — diff the section headings between versions to confirm only the intended structural changes moved. Cross-references and requirement IDs drift silently when section numbers shift underneath them; a two-minute diff keeps every reference valid across the bump. The derived FRD used sparse requirement numbering for the same reason — room to insert without ever renumbering.
When you should just fix everything
The two-bin discipline is not a universal law, and it's worth being honest about its boundary. In a docs-as-code or wiki culture — your own team's runbook, an internal README, anywhere the norm is be bold, edit first — filing a question about a typo you could have fixed is process cosplay. The heavyweight end of review has its own cautionary tale, too: Fagan's formal inspections, whose original 1976 IBM data located 82% of the errors in the product studied, still lost out to lightweight review in industry — a 25-year retrospective found that despite broad agreement inspections worked, the rigid ceremony never survived commercial practice. Ceremony has to earn its keep.
So calibrate on two axes: ownership and consequence. You own the document, or the fix is trivially reversible? Just fix it. You don't own it, and the resolution encodes a business decision? Two bins, a change log, and recommendations. The failure modes live at the corners: comment-first on your own docs is bureaucracy, and edit-first on someone else's spec is how a contractor quietly makes policy for a client who never noticed they'd delegated it.
The short version
FOLD what's safe to decide, with a change log. DECIDE what isn't yours, each item carrying a recommended default the client can accept in one pass — because defaults mostly win, yours had better be defensible. Split the findings that straddle the line. Prove coverage when coverage is claimed instead of asserting it. Diff headings across versions so the cross-references survive. The discipline is exactly what separates a trusted advisor from a contractor who either overstepped or rubber-stamped.