@boopkit/cap-workflows 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "workflows",
3
+ "description": "Reusable end-to-end development and writing workflows",
4
+ "type": "development",
5
+ "package": "@boopkit/cap-workflows",
6
+ "dependencies": [],
7
+ "devDependencies": [],
8
+ "files": [],
9
+ "skills": [
10
+ "boop-feature-dev-workflow",
11
+ "boop-light-dev-workflow",
12
+ "boop-refactor-dev-workflow",
13
+ "boop-test-audit-workflow",
14
+ "boop-architecture-audit-workflow",
15
+ "boop-issue-sweep-workflow",
16
+ "boop-website-dev-workflow",
17
+ "boop-design-handoff-workflow",
18
+ "boop-knowledge-backfill"
19
+ ]
20
+ }
package/package.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "@boopkit/cap-workflows",
3
+ "version": "0.1.0",
4
+ "description": "Reusable end-to-end development and writing workflows for AI agents",
5
+ "files": [
6
+ "skills/",
7
+ "capability.json"
8
+ ],
9
+ "boopkit": {
10
+ "capability": true,
11
+ "skillsDir": "skills",
12
+ "manifest": "capability.json"
13
+ },
14
+ "license": "ISC",
15
+ "publishConfig": {
16
+ "access": "public"
17
+ }
18
+ }
@@ -0,0 +1,199 @@
1
+ ---
2
+ name: boop-architecture-audit-workflow
3
+ description: "When you need to judge whether an area of shipped code is structurally healthy and decide what is worth fixing — undesired coupling, concerns bleeding across layers or domain boundaries, interfaces that are not composable because they are use-case specific or unparameterized — follow this process: scope one area and name the properties it should uphold → check the tests can catch you → measure before reading → grade every property and classify every finding against a named change → critique → operator gate → decompose → execute via refactor-dev-workflow. The sibling of test-audit-workflow for production code rather than tests. Not for finding bugs, and not for executing a structural change you have already decided on."
4
+ metadata:
5
+ category: workflow
6
+ ---
7
+
8
+ # Architecture audit workflow — judge an area's structural health, and find the debt a named change would actually hit.
9
+
10
+ When you need to audit an area of shipped, working code for structural problems — coupling that should not exist, concerns that have bled across a layer or a domain boundary, interfaces that cannot be composed because they are shaped around one caller — follow this process. It is the sibling of [`boop-test-audit-workflow`](../boop-test-audit-workflow/SKILL.md): that one audits a population of tests, this one audits a population of modules, and both remove things, so both need a safeguard that building does not.
11
+
12
+ ## Goal
13
+
14
+ Six beliefs shape every decision below.
15
+
16
+ **First: coupling is not debt until you can name the change it makes expensive.** This is the whole discipline, and without it the workflow degenerates into opinion generation. Every codebase violates some principle, so an agent told to "find bad architecture" will always succeed, and the findings will be indistinguishable from taste. The question below cannot be answered without evidence, which is what makes it useful. It is this workflow's equivalent of the question test-audit-workflow asks of a test, "where would a bug have to live for this test to go red?":
17
+
18
+ > **Name the change this structure makes expensive, and name what it costs.**
19
+
20
+ A real answer points at a specific piece of work — one on the near roadmap, or one that has already been painful more than once — and says which files it has to touch that have no business knowing about each other. "This violates separation of concerns" is not an answer. "Adding a second payment provider means editing the job queue, the receipt builder, and three controllers, because the provider type is a string literal matched in each" is. No named change, no finding.
21
+
22
+ **Second: findings alone do not answer the question the reader is asking.** A list of individually well-grounded problems does not tell anyone whether the area is fine, salvageable, or a disaster, because there is nothing to sum them into. So the audit has to grade the area against a small set of **named structural properties**, decided before the measuring starts, each ending with a verdict. Those verdicts are what make an audit legible in thirty seconds, and what let two areas be compared later. This is not the same as grading against a principle: a property is concrete and checkable ("every piece of state has one writer"), where a principle is a matter of taste.
23
+
24
+ **Third: a working system's structure is evidence, not error.** The code shipped, so somebody had a reason, and the reason is often invisible from the outside. Before filing anything, go find out why it is that way — the file's own header comments and `git log` usually say outright. A large fraction of obvious-looking findings dissolve on contact with the reason, and the ones that dissolve are the expensive ones, because they are the ones you would otherwise have spent a week undoing. This is not deference to the status quo. When the reason turns out to be stale or wrong, that is a strong finding with its evidence already assembled.
25
+
26
+ **Fourth: file layout and naming are the weakest evidence there is.** A suspicious directory tree, a file that looks like a duplicate, an inconsistent suffix — these generate more false positives than every other signal combined, because they are the only signals visible without reading anything. Weight measured coupling, real call sites, and change history above the shape of the tree. If your finding rests on how the files are arranged, you have not looked yet.
27
+
28
+ **Fifth: dependencies must point one way, and a name is a dependency.** A healthy area can be drawn as a DAG — storage at the bottom, the application at the top, every arrow pointing down. Draw it, in text, in the audit document, before concluding anything. The drawing *is* the measurement: a clean layering renders in a few lines and a reader can check it at a glance, while a layering you cannot draw without arrows going both ways — or without a module you cannot place on any level — has shown you where the refactor is before you have read a line of the code. Difficulty drawing it is the finding, not a failure of the exercise.
29
+
30
+ Two kinds of arrow count, and the second is the one that survives. A **code** dependency is an import, and tooling already polices it — a genuine cycle usually announces itself. A **vocabulary** dependency is a name from a higher layer surfacing in a lower layer's public interface: a method name, an exported constant, a type, a union member. Nothing detects those. No build ever breaks. So they accumulate in precisely the modules that look cleanest by import graph. A module that imports nothing above it while naming its callers' concepts throughout its API is still pointing up; it has only done it where the compiler cannot see.
31
+
32
+ **Sixth: you cannot safely restructure code whose tests cannot catch you.** A refactor preserves behaviour by definition, so the test suite is the only thing standing between the plan and a silent regression. If the tests around the area are mock theater — asserting data the test fed in, stubbing the collaborator that matters — then the area is not auditable yet, and the honest output is a test audit first.
33
+
34
+ ## Before you start: is this codebase auditable?
35
+
36
+ The method runs on evidence: issues with argued bodies, commit messages that name what they were for, reference docs, design notes. That is where a named change comes from and where a structure's reason is recorded.
37
+
38
+ If a candidate change cannot be grounded in an issue, a specification, or a commit, do not invent a plausible one. Say so. In a codebase with no such record, the honest output is that this method does not apply yet, and the useful first step is to start recording intent rather than to audit.
39
+
40
+ ## The flow
41
+
42
+ ### 1. Scope one area, name the properties, and draft the changes it faces
43
+
44
+ Three things, in one pass. They are grouped because the second and third both need evidence, and separating them into "think first, look later" produces either invention or a step nobody can follow.
45
+
46
+ **Name the area.** A directory, a service and its consumers, a layer boundary. One area per audit. A scope that spans the codebase produces a list nobody can act on, and the value here comes from going deep enough to be sure rather than wide enough to be comprehensive.
47
+
48
+ **Name the structural properties this area should uphold.** These are the grading criteria, and fixing them now is what stops the audit from being a list of whatever you happened to notice. Each must be concrete enough that a measurement or a call site can settle it. A reusable starting set, to extend per area:
49
+
50
+ - One public entry, with the internals unreachable from outside.
51
+ - Consumers depend on narrow contracts rather than whole surfaces.
52
+ - Every arrow points down: no module knows about a layer above it, in code or in name.
53
+ - Layers do not carry each other's types or vocabulary.
54
+ - Every piece of state has exactly one writer.
55
+ - Data crossing a process or trust boundary is validated where it arrives.
56
+ - The tests can detect a behaviour change.
57
+
58
+ **Draft the changes this area is expected to face.** This is the measuring stick for every finding. Derive it from real evidence: open issues, the roadmap, specifications, and what has already been rebuilt more than once. Do not invent entries to fill it out.
59
+
60
+ **You will not know the roadmap.** An agent running this cannot, so draft the list from evidence, put it at the top of the document, and mark it as needing the operator's confirmation. Every finding is graded against it, so a wrong list quietly invalidates the whole audit. On an unattended run, gate on it — see step 6.
61
+
62
+ ### 2. Check the tests can catch a behaviour change
63
+
64
+ Use [`boop-test-audit-workflow`](../boop-test-audit-workflow/SKILL.md)'s two questions on a sample rather than the full population. You are answering one question: if a refactor here broke something, would anything go red?
65
+
66
+ If the answer is no, stop and say so. The audit's output becomes "this area needs a test audit before it can be restructured," which is a real and useful result.
67
+
68
+ **This step earns its keep even when it passes**, and that is the more common case. Reading the tests tells you which ones are written against the current structure rather than against behaviour, and those are the tests a refactor will fight. A test that pins a call sequence, a label, or the shape of a collaborator is both refactor friction and, frequently, direct evidence for a finding — a guard written to enforce a rule is proof the rule exists and worth checking against the code it cannot see. Record what you learn here; do not reduce the step to a pass or fail.
69
+
70
+ ### 3. Measure before reading
71
+
72
+ Read the area only after the measurements tell you where to read. Going in with a reading list built from evidence is what separates this from a code review with a thesis. All of these are cheap:
73
+
74
+ - **Draw the knows-about DAG.** Put every module in the area on a level — storage at the bottom, application at the top — and draw the arrows in text. Then count both edge kinds separately, because they routinely disagree and the disagreement is the finding: how many modules above does each one **import**, and how many of its **exported members name a concept from a layer above it**? "Imports nothing above it, and 12 of its 21 exported members name its callers' concepts" is a two-number verdict that a reader can act on. Do this first — it tells you where to point every measurement below.
75
+ - **Change coupling from history.** Which files keep changing together in the same commit while living in different modules? `git log --name-only` over the last few months, counted by co-occurrence. This is the strongest available signal because it is a record of what the structure actually cost, not a prediction. Two files that always change together belong together, or the boundary between them is drawn in the wrong place.
76
+ - **Interface width against actual use.** For each exported interface, how many members does it declare, and how many does any single consumer call? A wide interface where every consumer uses two or three members is the non-composable shape, stated as a number.
77
+ - **Outward reach.** What does this module import from outside its own domain? A service reaching into four other domains marks where to look. Do not bother counting importers: a high importer count on a public entry point is the design working, and it has never produced a finding.
78
+ - **Type leakage across layers.** Does a persistence row type appear in a controller signature? Does an HTTP or rendering vocabulary appear in a service? Grep for the names of one layer's types in another layer's files.
79
+ - **Reach-arounds.** Does anything bypass a module's sanctioned entry point and import its internals directly? Note both the violations and whether a guard exists to prevent them.
80
+
81
+ **Count exhaustively, not from the first sample.** Enumerating "the five event kinds" from one file when eight exist elsewhere produces a finding whose cost estimate is wrong. Search the whole area for every instance before stating a number.
82
+
83
+ Record the numbers. They are evidence inside the findings, and the baseline if the work gets done.
84
+
85
+ ### 4. Grade the properties, then classify each finding
86
+
87
+ **Grade every property from step 1** — met, not met, or partly met — each with the measurement or call site that settles it. This is the part a reader looks at first, so it goes at the top of the document. Expect the verdicts to cluster, and say so when they do: "the structure is sound, the data contracts are not" tells someone more than six separate rows.
88
+
89
+ **Then classify each candidate the measurements surfaced.** Find out why it is that way, write it up with the named change and its cost, and give it one of three verdicts:
90
+
91
+ - **Sound.** The structure encodes a real constraint, or the named change is not actually expensive. **Record the reason.** This is a deliverable, not a null result: an audit that reports only problems throws away the knowledge that stops the next sweep from re-flagging the same thing.
92
+ - **Deferred debt.** The named change is genuinely expensive, but nobody is making it and nothing suggests they will. Record it with its cost and park it. It becomes active if the roadmap moves.
93
+ - **Active debt.** The named change is on the near list from step 1, or it has already been paid for more than once. This is the only verdict that becomes work.
94
+
95
+ Rank the active debt by how often the named change comes up multiplied by what it costs each time. State that in prose. Do not invent a severity score, which is a taste ranking wearing a number.
96
+
97
+ ### 5. Critique the findings before they become a plan
98
+
99
+ Read the list back as a skeptic. Do not skip this step. The most likely way this workflow fails is by producing a confident list of aesthetic preferences, and this is the only step that catches that before the list becomes work.
100
+
101
+ - **The named change test, applied honestly.** For every active-debt finding, is the named change real and specific, or did you write a plausible-sounding one to clear the bar? A change nobody has proposed and nobody is planning is a hypothesis, and a hypothesis belongs in deferred debt.
102
+ - **The reason check.** For every finding, did you go find out why the code is that way, or did you infer it? Point at the comment, the commit, or the issue. This is also where a finding resting on naming or directory structure gets caught, because that is nearly always a finding whose reason nobody looked up.
103
+ - **The size check.** For each proposed change, how much of the system has to move, and do the tests from step 2 cover all of it? A correct finding whose repair moves half the system is deferred debt. This check changes the output more than any other, because the most tempting findings are the largest ones — a long file or a wide interface invites a split that costs far more than the pain it removes.
104
+ - **The property check.** Does every property from step 1 have a verdict, and does the evidence actually settle it? An ungraded property is a question the reader will ask and the document will not answer.
105
+ - **The scope check.** Is the plan still about the area from step 1, or has it grown into a redesign of everything the area touches?
106
+ - **The tenets check.** Restructuring is not a customer-visible improvement. Weigh each item against the project's stated tenets — useful before easy before fast before pretty — and be willing to conclude that an area is honestly ugly and honestly fine.
107
+
108
+ Fix the list here. It is far cheaper than fixing it after an epic has been written against it.
109
+
110
+ ### 6. Stop for the operator
111
+
112
+ **Do not decompose until a human has read the findings.** Restructuring is destructive in the way test deletion is: a mistake does not announce itself, it just means something quietly stops working later. `test-audit-workflow` requires its trim list be reviewed before anything is deleted, and this workflow has the same property and needs the same control. An agent's own critique in step 5 is self-critique, not review.
113
+
114
+ Make the stop structural rather than an instruction someone might skip. Create the epic and its first child, then hold that child behind a gate:
115
+
116
+ ```bash
117
+ bd gate create --type=human --blocks <decompose-child-id> \
118
+ --reason="Operator confirms the active-debt findings before they become work"
119
+ ```
120
+
121
+ A human gate holds its waiter with no periodic check and releases it on `bd gate resolve`. Verify the waiter is actually held afterwards, because gate creation is not atomic — a rejected blocking edge still leaves the gate behind.
122
+
123
+ **On an unattended run, gate the step 1 change list too**, before any measuring. It is the measuring stick for every finding, and an agent cannot derive it reliably. A pause there costs a wait; discovering it was wrong at step 5 costs the whole audit.
124
+
125
+ ### 7. Decompose the active debt
126
+
127
+ Once the gate releases, write the child issues while the analysis is fresh. Use [`boop-project-mgmt-beads-planning`](../../../cap-project-mgmt/skills/boop-project-mgmt-beads-planning/SKILL.md) to shape the tree.
128
+
129
+ **First, check whether the findings are already filed.** An audit's most valuable output is often not new work but a new explanation: two or three bugs already in the queue turn out to be one structural cause. When that happens, do not file duplicates. Write one issue for the structural change, link the existing issues to it, and say in its body which symptoms it subsumes. An audit that adds only an explanation and closes nothing new has still earned its keep, and reporting that honestly is better than manufacturing issues to look productive.
130
+
131
+ For the work that is genuinely new:
132
+
133
+ - **One child per structural change, not one per call site.** Enumerate-and-patch is the failure that [`boop-refactor-dev-workflow`](../boop-refactor-dev-workflow/SKILL.md) exists to prevent, and it starts at decomposition time.
134
+ - **Carry the method on every child.** Each child must state the go-red discipline explicitly: delete the old shape first, commit the red build, follow the compiler. An agent picking up "split this interface" without that instruction will keep the build green by leaving a fallback, which is the exact failure this is meant to prevent.
135
+ - **Carry the named change too**, so the executor can tell a finished refactor from a rearranged one.
136
+ - **Name the skills on every child, and name only their names.** Step 8 says each child runs under [`boop-refactor-dev-workflow`](../boop-refactor-dev-workflow/SKILL.md) — but the executing session never reads this workflow, only the issue body, so that pointer reaches it exactly when the child says so and never otherwise. Put `boop-refactor-dev-workflow` on every child, plus the skill for the layer the structural change touches (services, controllers, data model, view) and [`boop-testing-testing`](../../../cap-testing/skills/boop-testing-testing/SKILL.md) for the real-path proof. Names, not extracts: the go-red method in the bullet above is copied deliberately, because a fallback that survives into the branch cannot be corrected afterwards, and that is the one exception. Everything else stays in its skill so there is a single copy to keep current.
137
+ - **Settle open decisions before the work starts, not during.** A choice like which validation library, or where a declaration lives, belongs in the issue body marked as decided, with the reasoning. An executor who has to pick one mid-implementation will pick silently.
138
+ - **Include a review child** that checks each change against its named change, not merely that the issue closed.
139
+ - **Put the test run scope on every child.** Focused tests for what that child touches, plus the project's whole-program static check; the full suite once, on the review child that completes the branch. Left unstated, a child that has just changed a widely called function runs the whole suite on its own reasoning — minutes to tens of minutes, paid again on every sibling, and it reads as diligence in the log rather than as waste. The rule and the wording to use are in [`boop-project-mgmt-beads-planning`](../../../cap-project-mgmt/skills/boop-project-mgmt-beads-planning/SKILL.md).
140
+ - **Do not create the feature branch.** The loop creates the worktree and its `work/<epic-id>` branch when it takes the first child.
141
+
142
+ - **Audit the issue bodies before the session ends, then revise them.** Writing an issue and auditing it are separate passes, and doing both at once produces bodies that read well to their author and cost their reader time. Once every child issue exists, re-read them all as the agent who will claim them cold, using the audit pass in [`boop-project-mgmt-beads-planning`](../../../cap-project-mgmt/skills/boop-project-mgmt-beads-planning/SKILL.md) and the anti-patterns in [`boop-writing-technical-prose`](../../../cap-product-design/skills/boop-writing-technical-prose/SKILL.md), then rewrite whatever the audit finds. Read the tree side by side rather than one issue at a time: a child that says "a sibling issue handles this" without naming it, or a term the container defines and a child then uses bare, is only visible that way.
143
+
144
+ ### 8. Execute, verify, close out
145
+
146
+ Hand the tree to a loop. Each child runs under [`boop-refactor-dev-workflow`](../boop-refactor-dev-workflow/SKILL.md), which owns the execution discipline this workflow does not re-derive.
147
+
148
+ - **Prove it against the named change.** The closing evidence is that the change from step 1 is now cheap: make it, or make enough of it to show the file list shrank. A green suite proves you did not break anything, which is necessary and is not the point.
149
+ - **Re-grade the properties.** The step 4 verdicts are the baseline, and the ones that moved are the result.
150
+ - Run the full suite before closeout.
151
+ - **Write the audit up, sound findings included**, into `reference/`, using [`boop-product-design-reference-integration`](../../../cap-product-design/skills/boop-product-design-reference-integration/SKILL.md). Annotate the resolved findings in place rather than deleting them: the record of why a change was made is what stops the next audit from re-deriving it.
152
+ - **Record what the work turned up that the audit did not predict.** A go-red refactor routinely exposes a type or a contract that was wrong all along and hidden by the loose shape. Those are findings the method missed, and writing them down is how the next audit gets better.
153
+ - Leave the branch for review. The human owns the merge.
154
+
155
+ ## The lenses, and the test that grounds each one
156
+
157
+ These are the shapes to look for. Each has a named-change test, because the shape alone is never the finding.
158
+
159
+ | Shape | What it looks like | The test that makes it a finding |
160
+ |---|---|---|
161
+ | **Coupling** | Two modules change together but neither owns the other | Name the change that touches both, and say why one has any business knowing about the other |
162
+ | **Layer bleed** | A persistence row type in a controller signature; HTTP or render vocabulary in a service | Name the change to one layer that forces an edit in the other |
163
+ | **Domain bleed** | One domain's service reaching another domain's internals rather than its entry point | Name what breaks in domain B when domain A changes something it declared private |
164
+ | **The god interface** | One type with many members; every consumer takes all of it to call two | Name the consumer that must satisfy or fake the whole surface. In a structurally-typed language a consumer can narrow unilaterally, so check for that first — if consumers already declare narrow views, the wide type is a namespace and there is no finding |
165
+ | **The use-case method** | A method named for one caller's scenario rather than a capability | Name the second caller that needs a near-duplicate because the first one's method does almost, but not quite, the right thing |
166
+ | **Missing parameterization** | Two near-identical paths differing by a constant | Name the third case, and count what it costs to add |
167
+ | **Upward vocabulary** | A low-level module whose public interface names its callers' concepts — methods, constants, or union members carrying a higher layer's entities, even though it imports nothing from that layer | Name a consumer that has none of those concepts, and say what it could actually do with the module as it stands. "It could read but could not write a single record without pretending to be a `<higher-layer entity>`" is the finding, stated as a capability rather than a preference |
168
+ | **The unenforced contract** | A shape everyone agrees on that nothing checks — an open envelope, an untyped payload, a convention in comments | Name the change to what the consumer requires, and count the call sites someone has to find by hand |
169
+
170
+ The last three are the same problem at different scales, and together they are the most common form of "not composable" in practice. Look for a method or a route whose name describes a scenario rather than an operation.
171
+
172
+ ## When to use this instead of a related workflow
173
+
174
+ | Situation | Workflow |
175
+ |---|---|
176
+ | Judge an area's structural health, decide what is worth fixing, and plan it | **this** |
177
+ | Execute a structural change you have already decided on | [`boop-refactor-dev-workflow`](../boop-refactor-dev-workflow/SKILL.md) |
178
+ | The tests around the area cannot catch a behaviour change | [`boop-test-audit-workflow`](../boop-test-audit-workflow/SKILL.md) first |
179
+ | Clear a noisy backlog of small lingering items in a themed sweep | [`boop-issue-sweep-workflow`](../boop-issue-sweep-workflow/SKILL.md) |
180
+ | Extend an existing system toward a goal, wiring new behaviour from parts that exist | [`boop-light-dev-workflow`](../boop-light-dev-workflow/SKILL.md) |
181
+ | Find bugs in a diff | [`boop-coding-review-changes`](../../../cap-coding/skills/boop-coding-review-changes/SKILL.md) |
182
+
183
+ If the area is small enough that the audit is one obvious finding with an obvious fix, skip the epic and file a plain issue. This workflow earns its overhead when the structure is large enough that measuring first genuinely changes what you would have concluded.
184
+
185
+ ## Anti-patterns
186
+
187
+ - **Filing a finding with no named change.** The single most important rule. Without it this workflow produces a well-written list of preferences, and acting on it costs real time and buys nothing.
188
+ - **Reporting findings with no verdict on the area.** A reader who cannot tell whether the area is fine or a disaster has been handed research, not an audit.
189
+ - **Auditing from the directory tree.** Layout is the weakest signal and the most available one, which is a bad combination. Measure first.
190
+ - **Clearing a module of upward dependencies on the strength of its import list.** The import graph is the half a compiler already checks, so it is the half least likely to be wrong. Read the exported names.
191
+ - **Skipping the reason.** Assuming a structure is a mistake because you cannot see its constraint. Read the header comment and the commit that introduced it.
192
+ - **Reporting only problems.** Sound findings and their reasons are half the deliverable. Without them the next audit re-flags the same things.
193
+ - **Restructuring on a suite that cannot catch you.** Step 2 exists so this is a decision rather than a discovery.
194
+ - **Letting the fix outgrow the pain.** The biggest, most obvious target is usually the one whose repair costs the most and buys the least.
195
+ - **Filing duplicates of issues that already exist.** Check the queue before writing the tree; an explanation that unifies filed bugs is a real result.
196
+ - **Decomposing before a human has read the findings.** The gate is the only safeguard this workflow has, and self-critique is not review.
197
+ - **Confusing this with bug hunting.** A bug is a defect in behaviour and belongs in review or debugging. This workflow is about the cost of future change, and mixing the two loses both.
198
+ - **Keeping the build green through a structural change.** That is how the fallback survives. The execution discipline lives in `boop-refactor-dev-workflow`; use it.
199
+ - **Grading against a principle rather than against this codebase.** The criteria that apply here live in [`boop-services-services`](../../../cap-services/skills/boop-services-services/SKILL.md), [`boop-services-controllers`](../../../cap-services/skills/boop-services-controllers/SKILL.md), [`boop-api-rest-api-design`](../../../cap-api/skills/boop-api-rest-api-design/SKILL.md), and [`boop-skills-agent-surface-design`](../../../cap-skills/skills/boop-skills-agent-surface-design/SKILL.md). Cite them, not a textbook.
@@ -0,0 +1,93 @@
1
+ ---
2
+ name: boop-design-handoff-workflow
3
+ description: "When the operator hands off a design package (a README plus a drop-in view template and CSS) for a redesigned surface, follow this process: read the README, VERIFY its claims against the real code, surface any buried decision to the operator, file an issue, run it as a sub-agent (branch for UAT or merge-on-clean-visual-check), then close out with knowledge integration and archival. The README is confident; confidence is not correctness — verify before you run."
4
+ metadata:
5
+ category: workflow
6
+ ---
7
+
8
+ # Design-handoff workflow — turn a design package into shipped, reviewed code.
9
+
10
+ A design handoff package is a high-leverage input: someone has already done the design work and grounded it against the real view-model, so the implementation is mostly mechanical. The leverage is real, but so is the risk, and the risk lives in one place — **the README's claims about the existing code.** A handoff that says "the service already computes X, just re-expose it" is trivial if true and a hidden architectural decision if false. The whole process turns on verifying those claims before any code is written.
11
+
12
+ ## What a handoff package looks like
13
+
14
+ Three files, typically grouped under a per-handoff directory in the project's design/eval reference area:
15
+
16
+ - **`README.md`** — the authoritative spec. Names what is being built, which files it replaces, a "Data to surface" list (the view-model fields the redesign needs that the controller does not pass yet), what was deliberately dropped, and any follow-ons that are explicitly out of scope.
17
+ - **A drop-in view template** — replaces an existing view. Every new field is guarded (rendered only when the field is present) with a live fallback, so the template renders *today* against the current view-model and "lights up" as each data field lands. Ship the template first, work the data list independently.
18
+ - **A CSS file** — appended into an existing style block; its header comment names the rules it supersedes.
19
+
20
+ ## The process
21
+
22
+ ### 1. Read the README in full
23
+
24
+ It is the spec — read it before touching anything. Note the "Data to surface" items (the view-model gaps), what it claims already exists, what it dropped and why, and the named follow-ons.
25
+
26
+ ### 2. Verify the README's claims against the real code (the load-bearing step)
27
+
28
+ The README makes assertions about the current code: "X already exists," "Y was retired," "field Z is right there on the type," "this renders today with zero controller changes." **Every one of those is a feasibility claim, and each must be checked against the actual code before you judge the package.** This is the step that separates a clean run from a buried decision.
29
+
30
+ - Confirm each "already exists" / "is right there" claim by reading the named symbol. (In a real run: a handoff claimed a field was "right there" — it was, on the underlying type, just dropped on the way to the view-model; trivial. Another claimed an upstream surface "already computed" a value — it deliberately did *not*, behind a documented boundary; that was a hidden architectural decision, not a re-expose.)
31
+ - Confirm the template's "renders today" claim: the fields it depends on now exist on the view-model (or are provided by the controller), and the genuinely-new fields are guarded with a fallback.
32
+ - Confirm any "retired" / "dropped" claim — a value the README says is gone may still be live and reusable.
33
+
34
+ When every claim checks out, it is a clean single sub-agent run. When a claim is wrong — especially when "re-expose this" turns out to mean "reverse a deliberate architectural boundary" — there is a design decision hiding inside the package.
35
+
36
+ ### 3. Judge feasibility for a single sub-agent run
37
+
38
+ Ask: is the work bounded with a clear path, or is there a judgment call hiding — an architectural decision, a premise error in the README, a spec ambiguity, a value that has to be derived rather than re-exposed? If the path is clear, it is one sub-agent run. If a decision is hiding, **do not let a sub-agent silently resolve it** (it will take the easy path — e.g. calling the function that reverses the boundary — because that is what "makes it work").
39
+
40
+ ### 4. Surface the verdict and any decision to the operator
41
+
42
+ Report: feasible or not, the scope, and the one question that is genuinely theirs — the buried architectural decision, framed at their altitude with a recommendation. Use [`boop-product-design-thought-partnership`](../../../cap-product-design/skills/boop-product-design-thought-partnership/SKILL.md) here. Get the call, then bake the decision into the issue so the sub-agent inherits it rather than re-deriving it. (Example: "derive the value from the shared source, not by duplicating — the README's 're-expose' framing assumed an upstream surface already had it, which it didn't.")
43
+
44
+ ### 5. File a bd issue (goal/approach/context shape)
45
+
46
+ Per [`boop-project-mgmt-beads-planning`](../../../cap-project-mgmt/skills/boop-project-mgmt-beads-planning/SKILL.md). Breadcrumb the handoff README as the authoritative spec, and **if the operator settled a decision in step 4, state it in the issue and say it supersedes the README where they differ** — otherwise the sub-agent will follow the README's wrong premise. Note the template's graceful-degradation (template + CSS can drop first; view-model edits light it up). Name the visual-check as the done-gate.
47
+
48
+ ### 6. Run it as a sub-agent
49
+
50
+ - **Isolated worktree on a non-default port.** The operator's dev server on the main checkout (e.g. `:3000`) is theirs — never touch it. Create a worktree branch off main (e.g. `work/<id>`), run the worktree's dev server on a different port (`:3001`/`:3002`/etc.), copy `.env` in if tests/capture need it (gitignored, don't commit).
51
+ - **Apply template + CSS**, removing the rules the CSS header names as superseded.
52
+ - **Make the view-model edits** per the (corrected) data list.
53
+ - **Trim brittle tests rather than lovingly rework them.** A redesigned surface is in flux; the operator's visual UAT is the safety net. Keep the full suite green; do not invest in expanding coverage on a surface that is still moving.
54
+ - **The visual-check is the gate.** Build the CSS bundle, capture the affected states at desktop (1280) and mobile (390), and *read* the captures — the render is the proof, not the diff. (Auth caveat: the default capture tool may log in as a demo account and not reach the populated data you need; use a capture path that authenticates as the fully-populated account so the render shows real content.)
55
+ - **Never `pkill` or pattern-kill a process** — an over-broad `pkill -f "<server command>"` can kill the operator's main-checkout server. Stop only your own server, by precise PID via `lsof -i:<port>`.
56
+ - **Disposition:**
57
+ - **Branch for UAT** when the change is a substantial visual redesign the operator will want to see — leave the branch, the worktree, and the captures; do not merge, do not close.
58
+ - **Merge on a clean visual-check** when the change is quick, clear, and additive — merge to main only if the capture clearly confirms the result and tests are green; if verification is blocked or ambiguous, fall back to branch-for-UAT rather than merging blind.
59
+
60
+ ### 7. Close out (after the operator's UAT, or on a clean merge)
61
+
62
+ Often itself a sub-agent. Per [`boop-knowledge-backfill`](../boop-knowledge-backfill/SKILL.md):
63
+
64
+ - **Merge** the branch to main; run the full suite green first.
65
+ - **Integrate the knowledge** — update the relevant reference page (e.g. the web-UI reference for a redesigned surface) to describe the new shape, and fix any reference line the redesign made stale. Commit docs direct to main.
66
+ - **Archive the handoff package** (unedited) to `specs/history/<name>-handoff/`.
67
+ - **Clean up** — close the issue, remove the worktree, delete the branch, stop the server by precise PID. Do not push to origin unless asked.
68
+
69
+ ## When to use this vs the other workflows
70
+
71
+ | Situation | Workflow |
72
+ |---|---|
73
+ | A design handoff package (README + drop-in template + CSS) for a surface | **this** |
74
+ | A goal-framed improvement to an existing surface, no package | [`boop-light-dev-workflow`](../boop-light-dev-workflow/SKILL.md) |
75
+ | A backlog cleanup sweep of lingering P1/P2 items | [`boop-issue-sweep-workflow`](../boop-issue-sweep-workflow/SKILL.md) |
76
+ | A feature with backend work driven by a spec | [`boop-feature-dev-workflow`](../boop-feature-dev-workflow/SKILL.md) |
77
+
78
+ ## Anti-patterns
79
+
80
+ - **Running the package without verifying its claims.** The README reads as authoritative; authority is not accuracy. The verify-against-code step (2) is the whole game — skip it and you ship a hidden decision or hit a wall mid-run.
81
+ - **Letting a sub-agent resolve a buried architectural decision.** When "re-expose X" actually means "reverse a documented boundary," a sub-agent will reverse it because that is the path of least resistance. Surface it to the operator instead.
82
+ - **Auto-merging a substantial visual redesign without the operator's eye.** Branch for UAT. Reserve merge-on-clean-visual-check for quick, clear, additive fixes.
83
+ - **Lovingly reworking brittle tests on a surface in flux.** Trim them; the visual UAT is the safety net. Reworking assertions that the redesign is about to invalidate again is wasted effort.
84
+ - **`pkill`.** It can kill the operator's main-checkout server. Precise PID only, and never the main checkout's server.
85
+ - **Following the README's premise after the operator corrected it.** If step 4 settled a decision, the issue must say it supersedes the README, or the sub-agent inherits the wrong framing.
86
+ - **Taking a package's scope at face value against the full mockup.** A handoff package may be a *subset* of the designer's full vision: a package redesigned only the primary list and scoped the header and empty-state out as "unchanged," but the full mockup redesigned them too — the gap only surfaced at the operator's UAT. In step 2/4, confirm the package's scope against the full design mockup; a package that says parts are "unchanged / out of scope" may still leave the surface divergent from what the operator expects. Surface that at UAT.
87
+
88
+ ## Related
89
+
90
+ - [`boop-knowledge-backfill`](../boop-knowledge-backfill/SKILL.md) — the archive + reference-integration discipline for the closeout.
91
+ - [`boop-web-web-ui-design`](../../../cap-web/skills/boop-web-web-ui-design/SKILL.md) — the visual-check-before-done rule the run leans on.
92
+ - [`boop-light-dev-workflow`](../boop-light-dev-workflow/SKILL.md) — the per-issue beats that run inside the sub-agent.
93
+ - [`boop-product-design-thought-partnership`](../../../cap-product-design/skills/boop-product-design-thought-partnership/SKILL.md) — surfacing the buried decision at the operator's altitude.