@gobing-ai/spur 0.3.80 → 0.3.81

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.
Files changed (158) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/config/config.example.yaml +29 -18
  3. package/config/config.global.yaml +10 -11
  4. package/config/pipeline-budgets.json +34 -2
  5. package/config/plugin-scripts.json +25 -0
  6. package/config/rules/boundary/config-loading-ownership.yaml +0 -3
  7. package/config/rules/boundary/dao-boundary.yaml +4 -17
  8. package/config/rules/boundary/planning-folder-hardcode.yaml +0 -1
  9. package/config/rules/boundary/sp-no-vendor-refs.yaml +3 -2
  10. package/config/rules/boundary/sp-runtime-path.yaml +3 -14
  11. package/config/rules/quality/coverage-gate.yaml +3 -14
  12. package/config/rules/quality/tsdoc-exports.yaml +4 -7
  13. package/config/rules/strict/http-boundaries.yaml +5 -8
  14. package/config/rules/strict/runtime-boundaries.yaml +1 -5
  15. package/config/rules/structure/protected-files.yaml +9 -3
  16. package/config/rules/structure/test-focus-skip.yaml +0 -2
  17. package/config/rules/structure/test-location.yaml +0 -5
  18. package/config/rules/surface/check-cli-surface.yaml +3 -2
  19. package/config/rules/typescript/bun-tooling.yaml +5 -7
  20. package/config/rules/typescript/guarded-happy-dom-register.yaml +0 -2
  21. package/config/rules/typescript/happy-dom-teardown.yaml +0 -2
  22. package/config/rules/typescript/no-biome-suppressions.yaml +0 -2
  23. package/config/rules/typescript/no-debugger.yaml +0 -2
  24. package/config/rules/typescript/no-eslint-suppressions.yaml +0 -4
  25. package/config/rules/typescript/no-leaky-module-mocks.yaml +6 -13
  26. package/config/rules/typescript/no-module-scope-import-calls.yaml +0 -2
  27. package/config/rules/typescript/no-syscall-emulation-in-boundary-mock.yaml +0 -3
  28. package/config/rules/typescript/no-unmocked-module-eval-side-effects.yaml +0 -3
  29. package/config/rules/typescript/output-boundaries.yaml +0 -3
  30. package/config/rules/typescript/prefer-accessible-role-for-button-queries.yaml +0 -3
  31. package/config/rules/ui/ui-import-boundary.yaml +1 -5
  32. package/config/transition-shims.json +7 -7
  33. package/config/workflows/basic.yaml +4 -0
  34. package/config/workflows/docs-pipeline.yaml +13 -14
  35. package/config/workflows/feature-dev.yaml +20 -65
  36. package/config/workflows/history-anatomy.yaml +22 -1
  37. package/config/workflows/idea-pipeline.yaml +53 -97
  38. package/config/workflows/pr-review.yaml +21 -33
  39. package/config/workflows/task-pipeline.yaml +87 -330
  40. package/config/workflows/wayfinder-resolution.yaml +12 -26
  41. package/config/workflows/wrapup-pipeline.yaml +48 -189
  42. package/package.json +9 -9
  43. package/plugins/sp/README.md +10 -1
  44. package/plugins/sp/agents/expert-spur.md +41 -19
  45. package/plugins/sp/lib/idea-handoff.generated.d.mts +17 -0
  46. package/plugins/sp/lib/idea-handoff.generated.mjs +1301 -0
  47. package/plugins/sp/plugin.json +1 -1
  48. package/plugins/sp/scripts/feature-dev-precheck.mjs +146 -0
  49. package/plugins/sp/scripts/feature-dev-precheck.ts +238 -0
  50. package/plugins/sp/scripts/idea-handoff.mjs +27 -0
  51. package/plugins/sp/scripts/idea-handoff.ts +44 -0
  52. package/plugins/sp/scripts/quality-gate.mjs +165 -0
  53. package/plugins/sp/scripts/quality-gate.ts +217 -0
  54. package/plugins/sp/scripts/workflow-step-profile.mjs +319 -0
  55. package/plugins/sp/scripts/workflow-step-profile.ts +456 -0
  56. package/plugins/sp/scripts/wrapup-steps.mjs +350 -0
  57. package/plugins/sp/scripts/wrapup-steps.ts +466 -0
  58. package/plugins/sp/skills/parallel-execution/references/dispatch-surface.md +1 -1
  59. package/plugins/sp/skills/spec-decomposition/references/decomposition.md +29 -0
  60. package/plugins/sp/skills/spur-cli/references/agent.md +56 -14
  61. package/plugins/sp/skills/spur-cli/references/message.md +30 -3
  62. package/plugins/sp/skills/spur-cli/references/projects.md +45 -1
  63. package/plugins/sp/skills/spur-cli/references/self.md +5 -4
  64. package/plugins/sp/skills/spur-cli/references/serve.md +5 -4
  65. package/plugins/sp/skills/spur-cli/references/tasks.md +1 -1
  66. package/plugins/sp/skills/spur-cli/references/team.md +21 -1
  67. package/plugins/sp/skills/spur-cli/references/workflows/operations.md +6 -3
  68. package/plugins/sp/skills/spur-cli/references/workflows/workflow-fit-and-tuning.md +57 -18
  69. package/plugins/sp/skills/spur-composer/SKILL.md +145 -0
  70. package/plugins/sp/skills/spur-dev/references/planning-workflow.md +24 -0
  71. package/plugins/sp/skills/spur-doctor/SKILL.md +138 -0
  72. package/plugins/sp/skills/taste-refactoring-api/README.md +43 -0
  73. package/plugins/sp/skills/taste-refactoring-api/SKILL.md +334 -0
  74. package/plugins/sp/skills/taste-refactoring-api/checklists/daily-api-review.md +71 -0
  75. package/plugins/sp/skills/taste-refactoring-api/examples/refactor-example.md +72 -0
  76. package/plugins/sp/skills/taste-refactoring-api/examples/review-template.md +93 -0
  77. package/plugins/sp/skills/taste-refactoring-api/references/api-refactoring-playbook.md +253 -0
  78. package/plugins/sp/skills/taste-refactoring-api/references/protocol-modes.md +79 -0
  79. package/plugins/sp/skills/taste-refactoring-api/references/research-basis.md +58 -0
  80. package/plugins/sp/skills/taste-refactoring-architect/README.md +26 -0
  81. package/plugins/sp/skills/taste-refactoring-architect/SKILL.md +471 -0
  82. package/plugins/sp/skills/taste-refactoring-architect/checklists/daily-architecture-review.md +48 -0
  83. package/plugins/sp/skills/taste-refactoring-architect/examples/refactor-example.md +55 -0
  84. package/plugins/sp/skills/taste-refactoring-architect/examples/review-template.md +51 -0
  85. package/plugins/sp/skills/taste-refactoring-architect/references/architecture-refactoring-playbook.md +173 -0
  86. package/plugins/sp/skills/taste-refactoring-architect/references/research-basis.md +28 -0
  87. package/plugins/sp/skills/taste-refactoring-tests/README.md +28 -0
  88. package/plugins/sp/skills/taste-refactoring-tests/SKILL.md +482 -0
  89. package/plugins/sp/skills/taste-refactoring-tests/checklists/daily-test-review.md +39 -0
  90. package/plugins/sp/skills/taste-refactoring-tests/examples/refactor-example.md +85 -0
  91. package/plugins/sp/skills/taste-refactoring-tests/examples/review-template.md +59 -0
  92. package/plugins/sp/skills/taste-refactoring-tests/references/research-basis.md +47 -0
  93. package/plugins/sp/skills/taste-refactoring-tests/references/test-refactoring-playbook.md +222 -0
  94. package/plugins/sp/skills/taste-refactoring-ui/README.md +12 -0
  95. package/plugins/sp/skills/taste-refactoring-ui/SKILL.md +290 -0
  96. package/plugins/sp/skills/taste-refactoring-ui/checklists/daily-ui-review.md +72 -0
  97. package/plugins/sp/skills/taste-refactoring-ui/examples/review-template.md +51 -0
  98. package/plugins/sp/skills/taste-refactoring-ui/references/refactoring-ui-playbook.md +170 -0
  99. package/plugins/sp/skills/wayfinder/SKILL.md +2 -2
  100. package/plugins/sp/skills/wayfinder/references/pipeline-resolution.md +30 -0
  101. package/schemas/spur-config.schema.json +49 -0
  102. package/spur.js +46754 -44121
  103. package/web/_astro/{BoardApp.CHQ1lycZ.js → BoardApp.B1U26g3I.js} +97 -95
  104. package/web/_astro/BoardApp.Csgyg-lS.js +1 -0
  105. package/web/_astro/{TaskDetail.GKfQJ60c.js → TaskDetail.DwPqpq7v.js} +1 -1
  106. package/web/_astro/{arc.DWEtA3Tx.js → arc.CweZEjN2.js} +1 -1
  107. package/web/_astro/{architectureDiagram-3BPJPVTR.DB42oWmP.js → architectureDiagram-3BPJPVTR.D89pbDuv.js} +1 -1
  108. package/web/_astro/{blockDiagram-GPEHLZMM.rhv-zNQV.js → blockDiagram-GPEHLZMM.BOuTeEpX.js} +1 -1
  109. package/web/_astro/{c4Diagram-AAUBKEIU.Ci4-4VvY.js → c4Diagram-AAUBKEIU.CASbkWZF.js} +1 -1
  110. package/web/_astro/channel.Cx6sXxhq.js +1 -0
  111. package/web/_astro/{chunk-2J33WTMH.Cc9veUgf.js → chunk-2J33WTMH.BKQYtOvY.js} +1 -1
  112. package/web/_astro/{chunk-4BX2VUAB.Bec9c4eI.js → chunk-4BX2VUAB.9sHLdMtG.js} +1 -1
  113. package/web/_astro/{chunk-55IACEB6.DoV8S1iB.js → chunk-55IACEB6.wOLXWlPs.js} +1 -1
  114. package/web/_astro/{chunk-727SXJPM.DwR-Qlyj.js → chunk-727SXJPM.DovFbwg3.js} +1 -1
  115. package/web/_astro/{chunk-AQP2D5EJ.ND_a81WY.js → chunk-AQP2D5EJ.B1Weod1X.js} +1 -1
  116. package/web/_astro/{chunk-FMBD7UC4.Wv_jwG48.js → chunk-FMBD7UC4.TEMS04st.js} +1 -1
  117. package/web/_astro/{chunk-ND2GUHAM.CXKXCMmp.js → chunk-ND2GUHAM.Cp8VT1wQ.js} +1 -1
  118. package/web/_astro/{chunk-QZHKN3VN.nkaoNYQq.js → chunk-QZHKN3VN.BzATdEcP.js} +1 -1
  119. package/web/_astro/{classDiagram-4FO5ZUOK.cMQcVlQu.js → classDiagram-4FO5ZUOK.C9BOCfAO.js} +1 -1
  120. package/web/_astro/{classDiagram-v2-Q7XG4LA2.cMQcVlQu.js → classDiagram-v2-Q7XG4LA2.C9BOCfAO.js} +1 -1
  121. package/web/_astro/{cose-bilkent-S5V4N54A.OaDJ7Mr2.js → cose-bilkent-S5V4N54A.DUnr4UAw.js} +1 -1
  122. package/web/_astro/{cynefin-OW5HDTMX.Chi8IphF.js → cynefin-OW5HDTMX.rYq5uM3D.js} +1 -1
  123. package/web/_astro/{cytoscape.esm.DzSz-X2X.js → cytoscape.esm.BB4DxJjf.js} +1 -1
  124. package/web/_astro/{dagre-BM42HDAG.CzK2t_Fp.js → dagre-BM42HDAG.CWeNKe3I.js} +1 -1
  125. package/web/_astro/{diagram-2AECGRRQ.DRvxlVS7.js → diagram-2AECGRRQ.DCkfls10.js} +1 -1
  126. package/web/_astro/{diagram-5GNKFQAL.CnYvNdwA.js → diagram-5GNKFQAL.D5U4JCka.js} +1 -1
  127. package/web/_astro/{diagram-KO2AKTUF.CpLpMw5R.js → diagram-KO2AKTUF.BZJgqaqG.js} +1 -1
  128. package/web/_astro/{diagram-LMA3HP47.JTb78qUA.js → diagram-LMA3HP47.DoMeHvPR.js} +1 -1
  129. package/web/_astro/{diagram-OG6HWLK6.Bk-1jDIb.js → diagram-OG6HWLK6.B50qwwWX.js} +1 -1
  130. package/web/_astro/{erDiagram-TEJ5UH35.D8hN9GZq.js → erDiagram-TEJ5UH35.DdGPG6LK.js} +1 -1
  131. package/web/_astro/{flowDiagram-I6XJVG4X.-6zQr6m5.js → flowDiagram-I6XJVG4X.QP2MJ12u.js} +1 -1
  132. package/web/_astro/{ganttDiagram-6RSMTGT7.DboLQ9ca.js → ganttDiagram-6RSMTGT7.BI6LgKSy.js} +1 -1
  133. package/web/_astro/{gitGraphDiagram-PVQCEYII.4tYvJKGR.js → gitGraphDiagram-PVQCEYII.npPZiC2G.js} +1 -1
  134. package/web/_astro/index.DayyIngm.css +1 -0
  135. package/web/_astro/{infoDiagram-5YYISTIA.Bd9rXpsB.js → infoDiagram-5YYISTIA.DCJCBVbp.js} +1 -1
  136. package/web/_astro/{ishikawaDiagram-YF4QCWOH.CvMoaf67.js → ishikawaDiagram-YF4QCWOH.BMLV-3I1.js} +1 -1
  137. package/web/_astro/{journeyDiagram-JHISSGLW.Ccy1CA7y.js → journeyDiagram-JHISSGLW.LE58crde.js} +1 -1
  138. package/web/_astro/{kanban-definition-UN3LZRKU.0MaMqHNS.js → kanban-definition-UN3LZRKU.BPbz8rH9.js} +1 -1
  139. package/web/_astro/{linear.CHXgcIbN.js → linear.DhZaBtYh.js} +1 -1
  140. package/web/_astro/{mermaid.core.Ca-kcelG.js → mermaid.core.BD5-jXum.js} +6 -6
  141. package/web/_astro/{mindmap-definition-RKZ34NQL.BUIDlHa0.js → mindmap-definition-RKZ34NQL.MTJyrQ65.js} +1 -1
  142. package/web/_astro/ordinal.BYWQX77i.js +1 -0
  143. package/web/_astro/{pieDiagram-4H26LBE5.2dX3CU1s.js → pieDiagram-4H26LBE5.BrDhDvIS.js} +1 -1
  144. package/web/_astro/{quadrantDiagram-W4KKPZXB.B3LBlRiv.js → quadrantDiagram-W4KKPZXB.71d73_5N.js} +1 -1
  145. package/web/_astro/{requirementDiagram-4Y6WPE33.X12I2uNx.js → requirementDiagram-4Y6WPE33.Bga6UF-z.js} +1 -1
  146. package/web/_astro/{sankeyDiagram-5OEKKPKP.BXohIHqx.js → sankeyDiagram-5OEKKPKP.BnHs4K82.js} +1 -1
  147. package/web/_astro/{sequenceDiagram-3UESZ5HK.C37ZIUzg.js → sequenceDiagram-3UESZ5HK.DsfY2gnj.js} +1 -1
  148. package/web/_astro/{stateDiagram-AJRCARHV.BRgz317z.js → stateDiagram-AJRCARHV.DvsTSc9a.js} +1 -1
  149. package/web/_astro/{stateDiagram-v2-BHNVJYJU.7VYSXN9-.js → stateDiagram-v2-BHNVJYJU.DxzzmHUR.js} +1 -1
  150. package/web/_astro/{timeline-definition-PNZ67QCA.BVNz_HiN.js → timeline-definition-PNZ67QCA.4ZuQmOTt.js} +1 -1
  151. package/web/_astro/{vennDiagram-CIIHVFJN.CHVDkPX4.js → vennDiagram-CIIHVFJN.Ck5Q86SG.js} +1 -1
  152. package/web/_astro/{wardleyDiagram-YWT4CUSO.EQQ_qT9v.js → wardleyDiagram-YWT4CUSO.BK7k2hXr.js} +1 -1
  153. package/web/_astro/{xychartDiagram-2RQKCTM6.DrAT9WoP.js → xychartDiagram-2RQKCTM6.DfCrgauK.js} +1 -1
  154. package/web/index.html +2 -2
  155. package/web/_astro/BoardApp.DV9kx0wo.js +0 -1
  156. package/web/_astro/channel.BAI6xLeV.js +0 -1
  157. package/web/_astro/index.Dcr_8fiK.css +0 -1
  158. package/web/_astro/ordinal.DBvzRdQf.js +0 -1
@@ -0,0 +1,138 @@
1
+ ---
2
+ name: spur-doctor
3
+ description: "Evaluate spur artifacts from read-only CLI evidence — tasks, features, rules, workflows, agent specs — reflect over sp:history-anatomy findings, and return a proposal table. Diagnoses spur artifacts, not runtime environments (that is spur agent doctor). Triggers: check artifact health, propose evolution, reflect over history findings."
4
+ license: Apache-2.0
5
+ version: 1.0.0
6
+ metadata:
7
+ author: spur
8
+ platforms: "claude-code,codex,openclaw,opencode,antigravity,pi"
9
+ category: artifact-composition
10
+ interactions:
11
+ - reviewer
12
+ - inversion
13
+ operations:
14
+ - evaluate
15
+ - reflect
16
+ - propose
17
+ openclaw:
18
+ emoji: "🔬"
19
+ see_also:
20
+ - sp:spur-cli
21
+ - sp:spur-composer
22
+ - sp:history-anatomy
23
+ - sp:super-planner
24
+ ---
25
+
26
+ # sp:spur-doctor — evaluate spur artifacts and propose changes
27
+
28
+ One cross-noun method (ADR-114, [spur artifact evolution](../../../../docs/design/spur-artifact-evolution.md)
29
+ §2): gather **read-only CLI evidence** about tasks, features, rules, workflows and agent specs,
30
+ **reflect** over `sp:history-anatomy` findings, and return a **proposal table**. It diagnoses spur
31
+ **artifacts** — definitions, rules, corpus records — not runtime environments: whether an agent
32
+ binary, host session or tool install is healthy is `spur agent doctor`'s job, not this skill's.
33
+
34
+ ## Read-only invariant
35
+
36
+ The doctor **writes nothing and names no mutating verb**. It performs no task, feature, rule or
37
+ workflow write — the operator accepts rows and `sp:spur-composer`
38
+ ([../spur-composer/SKILL.md](../spur-composer/SKILL.md)) applies them. A caller that wants a
39
+ record saves the returned table under `docs/reports/`; the doctor creates no artifact store.
40
+
41
+ - **History enters only through `sp:history-anatomy` findings.** Raw history records stay out
42
+ of scope and are never re-interpreted here; history-anatomy is the only history interpreter.
43
+ - **Recurring reflection loops and coordination go to `sp:super-planner`** or a workflow — one
44
+ bounded evaluation pass per invocation.
45
+ - **Forbidden surfaces: `spur team` and `spur agent loop`.** Agent specs are read only through
46
+ `spur agent list --specs --json`.
47
+
48
+ ## Evidence per noun
49
+
50
+ | Noun | Evidence (read-only) |
51
+ | --- | --- |
52
+ | task | `spur task check <wbs> --json` |
53
+ | feature | `spur feature check <id> --json` |
54
+ | rule | `spur rule trace --json`, `spur rule validate` |
55
+ | workflow | `spur workflow validate --json` (findings by `level`), `node "$(superskill script path sp workflow-step-profile.mjs)" <workflow> --json` |
56
+ | agent spec | `spur agent list --specs --json`, read and written through `spur agent` with `--specs`, never `spur team` |
57
+ | history | A `sp:history-anatomy` report ([../history-anatomy/SKILL.md](../history-anatomy/SKILL.md)), never raw history records |
58
+
59
+ Every row of a proposal cites the evidence it rests on. No anchor, no proposal.
60
+
61
+ ## Workflow step profile and cache-window flags
62
+
63
+ The step profile (`plugins/sp/scripts/workflow-step-profile`, ADR-065 plugin entrypoint) reads
64
+ `spur workflow trace` for a workflow's last N completed, non-dry runs. Per node and action kind it
65
+ reports run count, executions, p50 and max `durationMs`, p50 idle gap before the step, session mode
66
+ (`fresh`, `resumed` or `mixed`) and `cacheHit` p50 with its coverage — satellite §10 step evidence.
67
+
68
+ ```bash
69
+ node "$(superskill script path sp workflow-step-profile.mjs)" <workflow> --json
70
+ ```
71
+
72
+ `W` is the cache window, **300** seconds by default (satellite §10). The script computes every flag
73
+ arithmetically; doctor maps the flag ids to proposals and never re-derives numbers from prose. Each
74
+ flag and each composition finding becomes one proposal row with action class **workflow
75
+ optimization**, and the change comes from the §10 table:
76
+
77
+ | Evidence | Flag | Proposed change |
78
+ | --- | --- | --- |
79
+ | Validate finding, `level: error` | always | Extract to an owner from the closed fix vocabulary |
80
+ | Validate finding, `level: warn` | always | Extract, or record a stays-shell reason inside the warn band |
81
+ | Deterministic step | `step-over-window` — p50 > W | Split it, or move the slow work out of the step |
82
+ | Resumed `agent.run` | `resume-after-idle` — p50 idle gap before it > W | `freshSession: true` with the prior artifact as handoff |
83
+ | Resumed `agent.run` | `resume-cold-cache` — `cacheHit` p50 < 0.5, with evidence | The same, or move a long in-step tool call to a deterministic step |
84
+ | `agent.run` | `agent-run-over-2w` — p50 > 2W | Split at an artifact seam, or no-op when none exists |
85
+
86
+ - The two validate finding rows classify by `level` alone and carry no flag id.
87
+ - A row with `cacheHit.known: 0` raises no cache flag. Its cache evidence is **unknown, never a zero
88
+ hit rate**, and doctor reports it as unknown rather than as a 0% hit.
89
+ - A proposal that changes a shared workflow goes through §7 of the composition ladder
90
+ ([spur-composer](../spur-composer/SKILL.md)), including its recorded operator consent.
91
+
92
+ ## Reflection map over history findings
93
+
94
+ For each history-anatomy finding (`key`, `category`, `trend`, `ownerSurface`), assign **exactly
95
+ one** action class. The first matching row wins:
96
+
97
+ | # | Finding | Action class |
98
+ | --- | --- | --- |
99
+ | 1 | `trend` is `resolved` or `improved` | no-op |
100
+ | 2 | `category` is `positive` | doc or learning |
101
+ | 3 | Automatable, per step 1 of the [placement rule](../../references/environment-lens.md#placement-rule) | rule candidate |
102
+ | 4 | `ownerSurface` is a workflow definition | workflow optimization |
103
+ | 5 | `ownerSurface` is a doc, skill, reference or steering file | doc or learning |
104
+ | 6 | Anything else | task |
105
+
106
+ The five action classes are closed: **task**, **rule candidate**, **workflow optimization**,
107
+ **doc or learning**, **no-op**. The doctor classifies the report's findings and never derives new
108
+ ones from raw records — that would make it a second history interpreter.
109
+
110
+ ## Proposal table
111
+
112
+ Return one row per actionable finding, with exactly these columns:
113
+
114
+ | Column | Content |
115
+ | --- | --- |
116
+ | `key` | The finding key, or `<noun>:<id>:<check>` for an artifact finding |
117
+ | `evidence` | The CLI output or report section the row rests on |
118
+ | `action` | One action class from the reflection map (or the per-noun evaluation) |
119
+ | `change` | The proposed change, in one line |
120
+ | `apply` | The `spur` verb or composer procedure that lands it |
121
+ | `verify` | The evidence to re-run after applying |
122
+
123
+ Rules:
124
+
125
+ - The `apply` route is always a `spur` verb or a gated composer step — never a raw file edit this
126
+ skill performs. Shared-workflow rows route through the composition ladder's shared step.
127
+ - A `task` row carries the finding `key` in the task body (the history-anatomy handoff route).
128
+ - Rows are proposals only. No applied change, diff, or command output claimed as run.
129
+
130
+ ## What this skill is not
131
+
132
+ - **Not the applier.** `sp:spur-composer` applies accepted rows; this skill performs no
133
+ task/feature/rule/workflow write.
134
+ - **Not a runtime doctor.** Environment, binary and session readiness belong to
135
+ `spur agent doctor`; this skill diagnoses spur artifacts from CLI evidence.
136
+ - **Not a history interpreter.** Findings come from `sp:history-anatomy` reports, never from raw
137
+ history records.
138
+ - **Not a loop.** Recurring evolution passes belong to `sp:super-planner` or a workflow.
@@ -0,0 +1,43 @@
1
+ # taste-refactoring-api
2
+
3
+ A reusable agent skill for designing, reviewing, and safely refactoring production APIs.
4
+
5
+ ## What it covers
6
+
7
+ - REST/HTTP
8
+ - RPC/gRPC
9
+ - GraphQL
10
+ - events/webhooks
11
+ - domain/resource modeling
12
+ - naming and schemas
13
+ - errors
14
+ - pagination/filtering/sorting
15
+ - idempotency and retries
16
+ - concurrency
17
+ - versioning/deprecation/migration
18
+ - API security
19
+ - observability
20
+ - reliability/performance
21
+ - contract testing and documentation
22
+
23
+ ## Suggested installation
24
+
25
+ Install/copy this directory as an agent skill named `taste-refactoring-api` and load `SKILL.md` as the skill instructions. Keep the `references`, `checklists`, and `examples` directories available for deeper reviews.
26
+
27
+ ## Daily usage examples
28
+
29
+ - “Use taste-refactoring-api to review this OpenAPI spec.”
30
+ - “Refactor these Express routes without breaking current clients.”
31
+ - “Review this GraphQL schema for compatibility and developer experience.”
32
+ - “Design a safe pagination and filtering contract for this endpoint.”
33
+ - “Create a migration plan from v1 to v2 with no abrupt client breakage.”
34
+ - “Run the daily API quality checklist on this PR.”
35
+
36
+ ## Files
37
+
38
+ - `SKILL.md` — main agent operating instructions
39
+ - `references/api-refactoring-playbook.md` — deeper operational guidance
40
+ - `references/research-basis.md` — standards and sources used to build the skill
41
+ - `checklists/daily-api-review.md` — fast daily checklist
42
+ - `examples/review-template.md` — reusable review format
43
+ - `examples/refactor-example.md` — worked refactoring example
@@ -0,0 +1,334 @@
1
+ ---
2
+ name: taste-refactoring-api
3
+ description: Design, review, and refactor REST/HTTP, RPC/gRPC, GraphQL, and event API contracts safely.
4
+ ---
5
+
6
+ # taste-refactoring-api
7
+
8
+ ## Purpose
9
+
10
+ Act as a senior API designer, reviewer, and refactoring partner. Improve API surfaces without confusing “cleaner implementation” with “better contract.” The public contract is the product.
11
+
12
+ Use this skill when the user asks to:
13
+ - design a new API or endpoint;
14
+ - refactor an existing REST/HTTP, RPC/gRPC, GraphQL, webhook, or event API;
15
+ - review an OpenAPI, protobuf, GraphQL SDL, AsyncAPI-like contract, routes, controllers, handlers, SDK shape, or API docs;
16
+ - fix naming, resource modeling, request/response schemas, status codes, errors, pagination, filtering, sorting, idempotency, concurrency, versioning, or deprecation;
17
+ - reduce breaking changes and create a migration plan;
18
+ - make an API easier to understand, safer to retry, more secure, more observable, or cheaper to operate;
19
+ - run a pre-ship API quality pass.
20
+
21
+ This skill is practical. Prefer concrete contract changes, compatibility analysis, examples, and migration steps over abstract API philosophy.
22
+
23
+ ## Core operating principles
24
+
25
+ 1. **Start from consumer jobs, not routes.** Understand what clients need to accomplish before choosing paths, methods, messages, or transport details.
26
+ 2. **Model the domain, not the database.** API resources/types should represent stable business concepts, not tables, ORM models, queues, or internal service boundaries.
27
+ 3. **Prefer boring semantics.** Standard protocol behavior is a feature. Use conventional HTTP methods/status codes, well-known RPC patterns, GraphQL type-system semantics, and standard event envelopes before inventing custom rules.
28
+ 4. **Make illegal states hard to express.** Use strong schemas, enums, validation, explicit requiredness, bounded values, and mutually exclusive shapes where the protocol supports them.
29
+ 5. **Design for retries and partial failure.** Distributed systems fail. Make idempotency, timeouts, cancellation, deduplication, and recovery behavior explicit.
30
+ 6. **Compatibility is part of correctness.** A locally cleaner contract can still be a bad refactor if it breaks consumers. Prefer additive evolution and staged migrations.
31
+ 7. **Errors are part of the API.** Errors need stable machine-readable identity, useful human context, appropriate protocol status, and enough detail to act without exposing secrets.
32
+ 8. **Collections are first-class.** Pagination, filtering, sorting, consistency, and ordering must be designed deliberately from the beginning.
33
+ 9. **Security is object- and field-level.** Authentication alone is not authorization. Check access on every resource, action, and sensitive property.
34
+ 10. **Operational behavior is part of the contract.** Rate limits, quotas, latency expectations, long-running operations, traceability, and request identity affect client correctness.
35
+ 11. **Documentation should be executable where possible.** Keep contract definitions close to reality and validate examples, schemas, and compatibility in CI.
36
+ 12. **Refactor in safe slices.** Improve the highest-leverage inconsistency first, preserve client behavior, instrument migration, then remove legacy only after evidence says it is safe.
37
+
38
+ ## First classify the API
39
+
40
+ Before proposing changes, identify the dominant interface style:
41
+
42
+ - **REST/HTTP** — resources, URIs, methods, headers, status codes, representations.
43
+ - **RPC/gRPC** — services, methods, request/response messages, deadlines, streaming, status codes.
44
+ - **GraphQL** — schema, fields, arguments, nullability, mutations, connections, deprecation.
45
+ - **Event/webhook** — event type, envelope, delivery semantics, ordering, retries, deduplication, signatures.
46
+ - **Hybrid** — apply shared principles but avoid forcing one protocol’s idioms onto another.
47
+
48
+ If the user has an established style guide or public compatibility promise, treat that as a constraint unless explicitly asked to redesign it.
49
+
50
+ ## Default workflow
51
+
52
+ ### 1. Frame the consumer contract
53
+
54
+ Identify:
55
+ - primary consumers and their jobs;
56
+ - whether this is public, partner, internal, or service-to-service;
57
+ - read/write patterns and expected scale;
58
+ - consistency and latency requirements;
59
+ - failure/retry expectations;
60
+ - existing clients that must remain compatible;
61
+ - security and data-sensitivity boundaries;
62
+ - protocol and tooling constraints.
63
+
64
+ Do not begin with route cleanup or naming cosmetics when the domain model is unclear.
65
+
66
+ ### 2. Audit in passes
67
+
68
+ Use this order unless the user requests a narrower review.
69
+
70
+ **Pass A — Domain and resource model**
71
+ - Does the API expose stable domain concepts rather than implementation details?
72
+ - Are ownership and parent/child relationships clear?
73
+ - Are resource identities stable and canonical?
74
+ - Are custom action endpoints actually resources or state transitions in disguise?
75
+ - Is there one obvious way to perform each common job?
76
+
77
+ **Pass B — Semantics and operations**
78
+ - Do methods/operations express intent consistently?
79
+ - For HTTP, are safe/idempotent method semantics respected?
80
+ - Are creates, replacements, partial updates, deletes, and actions distinguished clearly?
81
+ - Can clients retry mutations safely, or is an explicit idempotency mechanism needed?
82
+ - Are long-running operations modeled instead of holding connections indefinitely?
83
+
84
+ **Pass C — Naming and shape**
85
+ - Are path segments, operation names, fields, enums, and error codes predictable?
86
+ - Is casing consistent within the ecosystem?
87
+ - Are booleans affirmative and unambiguous?
88
+ - Are timestamps, durations, money, quantities, IDs, URLs, and enums represented consistently?
89
+ - Are server-generated and client-writable fields clearly separated?
90
+
91
+ **Pass D — Requests and responses**
92
+ - Is requiredness intentional?
93
+ - Are defaults observable and documented?
94
+ - Are request and response shapes minimal but sufficient?
95
+ - Is over-posting / mass assignment prevented?
96
+ - Can schemas evolve additively?
97
+ - Are partial-update semantics explicit rather than accidental?
98
+
99
+ **Pass E — Collections**
100
+ - Is pagination present from the start for potentially unbounded collections?
101
+ - Is ordering deterministic?
102
+ - Are page/cursor tokens opaque and bound to the relevant query context?
103
+ - Are filtering and sorting fields explicit and bounded?
104
+ - Is total count omitted, estimated, or exact by deliberate choice?
105
+ - Is collection consistency acceptable when data changes between pages?
106
+
107
+ **Pass F — Errors and edge cases**
108
+ - Does each failure map to an appropriate protocol-level status?
109
+ - Is there a stable machine-readable error type/code?
110
+ - Can a caller tell whether to fix input, authenticate, request permission, retry, wait, or contact support?
111
+ - Are validation errors field-addressable?
112
+ - Are conflict, precondition, quota, throttling, and dependency failures distinguished?
113
+ - Do errors avoid leaking internals, secrets, or existence of unauthorized resources?
114
+
115
+ **Pass G — Compatibility and evolution**
116
+ - Classify every proposed change as additive, behaviorally risky, or breaking.
117
+ - Prefer adding fields/operations over renaming/removing existing ones.
118
+ - Avoid changing meaning while preserving the same name.
119
+ - Define deprecation metadata and a migration path.
120
+ - Keep old and new behavior simultaneously only as long as needed, with observability.
121
+
122
+ **Pass H — Security and abuse resistance**
123
+ - Verify object-level authorization for every identifier received from the client.
124
+ - Verify property-level authorization for readable/writable sensitive fields.
125
+ - Prevent unrestricted resource consumption with bounded page sizes, payload sizes, batch sizes, and concurrency.
126
+ - Treat SSRF-capable URLs, webhook destinations, file fetches, and proxy-like parameters as high risk.
127
+ - Protect sensitive business flows from automation/abuse, not just authentication failures.
128
+ - Maintain an inventory of exposed versions, hosts, operations, and shadow/deprecated APIs.
129
+
130
+ **Pass I — Reliability and performance**
131
+ - Define timeouts/deadlines and retry guidance.
132
+ - Use idempotency or deduplication for retryable non-idempotent operations where necessary.
133
+ - Avoid chatty N+1 client workflows when a bounded aggregate/batch operation is clearer.
134
+ - Avoid huge payloads and unbounded lists.
135
+ - Design caching/conditional requests where freshness semantics support them.
136
+ - Model asynchronous work explicitly when latency is unpredictable or long.
137
+
138
+ **Pass J — Observability and operations**
139
+ - Propagate or generate request/trace identifiers.
140
+ - Make logs/metrics distinguish operation, client, status class, latency, and error type without logging secrets.
141
+ - Expose rate-limit/quota behavior consistently if clients need to react.
142
+ - Define SLO-relevant behavior for latency, availability, and freshness where appropriate.
143
+ - Make migration adoption measurable before removing legacy behavior.
144
+
145
+ **Pass K — Documentation and developer experience**
146
+ - Can a new consumer succeed from the contract and examples alone?
147
+ - Are common flows shown end-to-end?
148
+ - Do examples cover success plus important failures?
149
+ - Does the machine-readable spec match the implementation?
150
+ - Are deprecations, defaults, pagination, retries, rate limits, and compatibility expectations discoverable?
151
+
152
+ ### 3. Systematize the contract
153
+
154
+ Whenever a decision repeats, turn it into an API rule, reusable schema, lint rule, middleware behavior, or CI check.
155
+
156
+ At minimum, look for shared standards covering:
157
+ - resource and operation naming;
158
+ - identifiers;
159
+ - timestamps and durations;
160
+ - money and decimal values;
161
+ - pagination;
162
+ - filtering and sorting;
163
+ - errors;
164
+ - idempotency;
165
+ - optimistic concurrency;
166
+ - authentication and authorization metadata;
167
+ - request/trace IDs;
168
+ - long-running operations;
169
+ - webhooks/events;
170
+ - versioning and deprecation;
171
+ - rate limits and quotas.
172
+
173
+ The goal is to eliminate repeated low-level API decisions, not to create bureaucracy.
174
+
175
+ ## Protocol-specific review
176
+
177
+ After classifying the API, read the matching REST/HTTP, RPC/gRPC, GraphQL, or event/webhook section in [references/protocol-modes.md](references/protocol-modes.md). Apply that checklist before continuing with the refactoring strategy.
178
+
179
+ ## Refactoring strategy
180
+
181
+ ### Preserve behavior before improving shape
182
+
183
+ When refactoring an existing API:
184
+ 1. Inventory current operations, schemas, consumers, traffic, and known quirks.
185
+ 2. Identify the consumer pain, not just aesthetic inconsistency.
186
+ 3. Mark hard compatibility constraints.
187
+ 4. Design the target contract.
188
+ 5. Produce an explicit old → new mapping.
189
+ 6. Add adapters/aliases/new fields/new endpoints before removing old behavior where feasible.
190
+ 7. Add telemetry for legacy usage.
191
+ 8. Migrate first-party consumers first.
192
+ 9. Publish deprecation and migration guidance.
193
+ 10. Remove legacy only after the agreed support window and evidence of low/zero use.
194
+
195
+ ### Compatibility classification
196
+
197
+ Treat these as **usually breaking or behaviorally dangerous**:
198
+ - removing or renaming a field/operation/path;
199
+ - changing a field’s type, units, interpretation, or enum meaning;
200
+ - making an optional request field required;
201
+ - making a nullable GraphQL field non-null without proving all clients/data satisfy it;
202
+ - changing default sort order;
203
+ - adding pagination to an endpoint that previously returned the full collection;
204
+ - reducing accepted input ranges or max sizes without transition;
205
+ - changing authentication/authorization behavior;
206
+ - changing retry/idempotency behavior;
207
+ - changing error codes/statuses that clients branch on;
208
+ - reusing deleted protobuf field numbers;
209
+ - changing event delivery/order guarantees.
210
+
211
+ Treat these as **often additive but still review behaviorally**:
212
+ - adding response fields;
213
+ - adding optional request fields with backward-safe defaults;
214
+ - adding new operations;
215
+ - adding enum values when consumers are required/known to handle unknown values;
216
+ - adding optional event payload fields;
217
+ - adding GraphQL fields/types while preserving existing semantics.
218
+
219
+ ## Security review baseline
220
+
221
+ Use OWASP API Security Top 10 thinking as a minimum threat-model prompt, especially:
222
+ - broken object-level authorization;
223
+ - broken authentication;
224
+ - broken object-property-level authorization / mass assignment / excess exposure;
225
+ - unrestricted resource consumption;
226
+ - broken function-level authorization;
227
+ - unrestricted access to sensitive business flows;
228
+ - server-side request forgery;
229
+ - security misconfiguration;
230
+ - improper inventory management;
231
+ - unsafe consumption of third-party APIs.
232
+
233
+ For every API refactor, ask: **what new authority, data exposure, amplification, or request-forgery capability does this surface create?**
234
+
235
+ ## Anti-patterns to call out
236
+
237
+ - endpoint names that encode implementation verbs (`/runSql`, `/callService`, `/getCustomerById`);
238
+ - APIs that mirror database tables one-to-one;
239
+ - `200 OK` for every outcome with custom error flags;
240
+ - state-changing `GET` requests;
241
+ - inconsistent IDs (`id`, `userId`, `user_id`, UUID sometimes, integer elsewhere) without a deliberate boundary;
242
+ - nullable/optional fields whose absence, null, empty string, and zero all mean different undocumented things;
243
+ - giant “update everything” payloads that enable mass assignment;
244
+ - page-number pagination over fast-changing large datasets where cursor traversal is required;
245
+ - non-deterministic list ordering;
246
+ - retries on non-idempotent writes without deduplication;
247
+ - synchronous requests for jobs that routinely exceed normal request latency;
248
+ - leaking stack traces or backend exception names;
249
+ - client-visible internal microservice names;
250
+ - version bumps for implementation-only changes;
251
+ - permanent support for every historical version;
252
+ - undocumented breaking behavior hidden behind a nonbreaking schema diff;
253
+ - GraphQL schemas full of generic JSON blobs;
254
+ - gRPC methods with one-off naming and status conventions;
255
+ - webhook delivery without signatures, replay protection, or deduplication guidance.
256
+
257
+ ## Code / specification refactor mode
258
+
259
+ When OpenAPI, protobuf, GraphQL SDL, route code, or handlers are provided:
260
+ - read the contract before the implementation;
261
+ - infer existing conventions and preserve good ones;
262
+ - identify contract vs implementation-only changes;
263
+ - generate working edits where possible;
264
+ - keep schema validation and runtime validation aligned;
265
+ - add examples for changed operations;
266
+ - add compatibility tests or contract tests for risky changes;
267
+ - update generated-client-sensitive names deliberately;
268
+ - avoid broad renames that create SDK churn without consumer benefit.
269
+
270
+ When code is provided, explain only the design decisions that materially affect consumers or operations. Deliver usable patches/spec updates, not a lecture.
271
+
272
+ ## API review mode
273
+
274
+ Inspect in this sequence:
275
+ 1. What job is the consumer trying to complete?
276
+ 2. Is the domain/resource model obvious?
277
+ 3. Is there one conventional operation for that job?
278
+ 4. Are names and shapes predictable?
279
+ 5. Can the request be validated unambiguously?
280
+ 6. Can the caller understand and recover from failures?
281
+ 7. Can collection reads scale safely?
282
+ 8. Can writes be retried safely?
283
+ 9. Are authorization checks at object/action/property level?
284
+ 10. Can the contract evolve without breaking existing consumers?
285
+ 11. Can operators trace and debug a request?
286
+ 12. Is the documentation/spec sufficient to use the API correctly?
287
+
288
+ Return the smallest set of high-leverage contract improvements first.
289
+
290
+ ## New API design mode
291
+
292
+ 1. State the consumer job in one sentence.
293
+ 2. List stable domain resources/types and ownership.
294
+ 3. Choose the interaction style (HTTP resources, RPC, GraphQL, event) based on the job.
295
+ 4. Define the smallest coherent operations.
296
+ 5. Define request/response schemas and requiredness.
297
+ 6. Define errors and validation.
298
+ 7. Define pagination/filtering/sorting for collections.
299
+ 8. Define idempotency/concurrency/retry behavior.
300
+ 9. Define authn/authz and abuse limits.
301
+ 10. Define observability and operational limits.
302
+ 11. Define compatibility/deprecation rules.
303
+ 12. Produce contract examples and tests.
304
+
305
+ ## Output contract
306
+
307
+ Unless the user requests another format, answer with:
308
+
309
+ ### Diagnosis
310
+ One concise statement of the main API design problem, consumer impact, and target direction.
311
+
312
+ ### Highest-impact refactors
313
+ A prioritized set of concrete contract changes, usually 3–8 items.
314
+
315
+ ### Proposed contract
316
+ Show the recommended paths/methods/messages/schema snippets/examples needed to make the design concrete.
317
+
318
+ ### Compatibility impact
319
+ For every externally visible change, label it:
320
+ - additive;
321
+ - behaviorally risky;
322
+ - breaking.
323
+
324
+ Include a migration strategy for risky/breaking changes.
325
+
326
+ ### System rules
327
+ List reusable conventions/tokens/lint rules that should become organization-wide defaults.
328
+
329
+ ### Verification
330
+ Specify the tests/checks needed: contract tests, schema validation, compatibility diff, authorization tests, retry/idempotency tests, pagination tests, performance limits, and observability checks as relevant.
331
+
332
+ ## Decision rule
333
+
334
+ A “better” API is not the one with the prettiest route names. It is the one that makes common client code obvious, predictable, safe under failure, compatible over time, secure by default, and operable in production.
@@ -0,0 +1,71 @@
1
+ # Daily API Review Checklist
2
+
3
+ Use this for a fast pre-merge, pre-release, or refactoring pass.
4
+
5
+ ## Consumer and domain
6
+ - [ ] The consumer job is clear in one sentence.
7
+ - [ ] The API models domain concepts, not database/service internals.
8
+ - [ ] Resource/type ownership and identity are clear.
9
+ - [ ] There is one obvious path for the common use case.
10
+
11
+ ## Semantics
12
+ - [ ] Operations use protocol-native semantics.
13
+ - [ ] No state-changing behavior is hidden behind a safe/read operation.
14
+ - [ ] Retry/idempotency behavior is explicit for mutations.
15
+ - [ ] Long-running work is modeled asynchronously when needed.
16
+
17
+ ## Schema
18
+ - [ ] Names and casing are consistent.
19
+ - [ ] Required/optional/nullable/default behavior is explicit.
20
+ - [ ] IDs, timestamps, durations, money, enums, and booleans are consistent.
21
+ - [ ] Writable fields are explicitly whitelisted.
22
+ - [ ] Partial-update semantics are unambiguous.
23
+
24
+ ## Collections
25
+ - [ ] Potentially unbounded collections are paginated.
26
+ - [ ] Ordering is deterministic.
27
+ - [ ] Page size/batch size is bounded.
28
+ - [ ] Cursor/page token semantics are opaque and documented.
29
+ - [ ] Filtering/sorting is constrained and predictable.
30
+
31
+ ## Errors
32
+ - [ ] Protocol status/code matches failure semantics.
33
+ - [ ] Machine-readable error identity is stable.
34
+ - [ ] Validation errors point to actionable fields/arguments.
35
+ - [ ] Retryable vs non-retryable failures are distinguishable.
36
+ - [ ] Errors leak no stack traces, secrets, or sensitive internals.
37
+
38
+ ## Compatibility
39
+ - [ ] Every public change is classified as additive / risky / breaking.
40
+ - [ ] No existing field/operation changed meaning silently.
41
+ - [ ] Defaults and ordering did not change accidentally.
42
+ - [ ] Deprecation has replacement + migration guidance.
43
+ - [ ] Usage telemetry exists before legacy removal.
44
+
45
+ ## Security
46
+ - [ ] Object-level authorization is checked for client-controlled IDs.
47
+ - [ ] Function/action-level authorization is checked.
48
+ - [ ] Property-level read/write authorization is checked.
49
+ - [ ] Expensive operations and payloads are bounded.
50
+ - [ ] SSRF-capable URL/destination inputs are restricted.
51
+ - [ ] Sensitive business flows have abuse controls.
52
+
53
+ ## Reliability and operations
54
+ - [ ] Timeouts/deadlines are defined.
55
+ - [ ] Retries cannot duplicate side effects unexpectedly.
56
+ - [ ] Concurrency/lost-update behavior is intentional.
57
+ - [ ] Request/trace IDs are propagated.
58
+ - [ ] Rate limit/quota behavior is consistent if applicable.
59
+ - [ ] Logs/metrics can identify operation, status, latency, and error type.
60
+
61
+ ## Documentation and tests
62
+ - [ ] Contract/spec matches implementation.
63
+ - [ ] At least one success example is correct.
64
+ - [ ] Important failures are documented.
65
+ - [ ] Compatibility/schema diff is checked in CI where possible.
66
+ - [ ] Authorization, pagination, retry/idempotency, and error cases are tested.
67
+
68
+ ## Ship decision
69
+ - [ ] A new client can use the API without learning backend internals.
70
+ - [ ] A transient network failure will not create surprising corruption.
71
+ - [ ] Existing consumers have a safe path through the change.
@@ -0,0 +1,72 @@
1
+ # Worked Example — Refactor a brittle HTTP API
2
+
3
+ ## Before
4
+
5
+ ```http
6
+ GET /api/getOrder?id=42
7
+ POST /api/updateOrder
8
+ POST /api/deleteOrder
9
+ ```
10
+
11
+ ```json
12
+ HTTP/1.1 200 OK
13
+ {
14
+ "success": false,
15
+ "errorCode": "NOT_FOUND",
16
+ "message": "Order missing"
17
+ }
18
+ ```
19
+
20
+ Problems:
21
+ - action verbs and generic endpoint family instead of a resource model;
22
+ - all outcomes tunneled through `200`;
23
+ - update semantics are unknown;
24
+ - deletion uses a non-idempotency-signaling shape;
25
+ - no concurrency protection;
26
+ - client must learn application-specific protocol conventions before HTTP semantics help.
27
+
28
+ ## Target
29
+
30
+ ```http
31
+ GET /orders/42
32
+ PATCH /orders/42
33
+ DELETE /orders/42
34
+ ```
35
+
36
+ ```http
37
+ HTTP/1.1 404 Not Found
38
+ Content-Type: application/problem+json
39
+
40
+ {
41
+ "type": "https://api.example.com/problems/order-not-found",
42
+ "title": "Order not found",
43
+ "status": 404,
44
+ "detail": "No visible order exists with the supplied identifier."
45
+ }
46
+ ```
47
+
48
+ For a race-sensitive update:
49
+
50
+ ```http
51
+ PATCH /orders/42
52
+ If-Match: "rev-7"
53
+ Content-Type: application/merge-patch+json
54
+
55
+ {
56
+ "shippingAddress": {
57
+ "city": "San Jose"
58
+ }
59
+ }
60
+ ```
61
+
62
+ A stale revision can fail with a precondition response rather than silently overwriting another user’s change.
63
+
64
+ ## Safe migration
65
+
66
+ 1. Add `/orders/{id}` alongside legacy endpoints.
67
+ 2. Make legacy handlers adapt into the new domain service so behavior stays aligned.
68
+ 3. Emit telemetry when legacy endpoints are called.
69
+ 4. Migrate first-party clients.
70
+ 5. Mark legacy operations deprecated in docs/spec.
71
+ 6. Set removal criteria based on client adoption and support policy.
72
+ 7. Remove only after the agreed deprecation window.