universal-dev-standards 5.12.1 → 5.13.2

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.
@@ -65,6 +65,108 @@ Guide systematic code migration, framework upgrades, and technology modernizatio
65
65
  5. **驗證** - 執行完整測試套件、檢查回歸
66
66
  6. **清理** - 移除相容層、舊依賴
67
67
 
68
+ ## API Migration Contract Tests | API 遷移合約測試
69
+
70
+ When migrating an API endpoint from one tech stack to another (PHP → .NET, Express → Spring, Python → Go), unit tests on the **new** implementation verify against the **new DTO** — they cannot catch fields that the legacy returned but the new implementation forgot. Missing fields, renamed fields, type drift, and top-level vs nested placement drift will silently survive into production and break the existing frontend that still expects the legacy shape.
71
+
72
+ This is **NOT** caught by unit tests, integration tests, or code review alone. A real 2026-05-24 production incident shipped with 67/67 green tests and was discovered by the customer.
73
+
74
+ 當 API endpoint 從一個技術棧遷至另一個(PHP → .NET、Express → Spring 等),對**新**實作的單元測試只驗證**新 DTO**——無法捕捉「舊版有但新版漏掉」「欄位 rename」「型別漂移」「頂層 vs nested 層級漂移」等問題。這些缺陷會靜默流入生產,導致前端(仍預期舊版回應 shape)失靈。
75
+
76
+ **僅靠單元測試、整合測試或 code review 無法防止**。2026-05-24 真實 PROD 事故:67/67 測試全綠流入正式環境,由客戶發現缺漏。
77
+
78
+ ### Mandatory rule | 強制規則
79
+
80
+ Every migrated API endpoint **MUST** ship with at least one contract test that compares the new implementation's response against a fixture captured from the legacy implementation. Structural equivalence (keys, types, placement), not value equality, is verified.
81
+
82
+ 每個被遷移的 API endpoint **必須**至少有一份 contract test,比對新實作的 response 與從 legacy 捕獲的 fixture。驗證的是結構性等價(keys、type、層級位置),而非值等價。
83
+
84
+ ### Fixture capture protocol | Fixture 捕獲協議
85
+
86
+ **While legacy is still running (typical migration window) | Legacy 仍運行(典型遷移窗口):**
87
+
88
+ ```bash
89
+ # 1. Capture ≥3 representative inputs (happy path, edge case, empty result)
90
+ curl -X POST $LEGACY_BASE/endpoint -d @input1.json \
91
+ > tests/fixtures/migration/endpoint/scenario1.json
92
+ curl -X POST $LEGACY_BASE/endpoint -d @input2_empty.json \
93
+ > tests/fixtures/migration/endpoint/scenario2_empty.json
94
+ curl -X POST $LEGACY_BASE/endpoint -d @input3_edge.json \
95
+ > tests/fixtures/migration/endpoint/scenario3_edge.json
96
+
97
+ # 2. Scrub PII and volatile values (timestamps, generated IDs)
98
+ jq 'walk(if type == "string" and test("@") then "redacted@example.com" else . end)' \
99
+ tests/fixtures/migration/endpoint/scenario1.json > tmp && mv tmp ...
100
+
101
+ # 3. Commit fixtures
102
+ git add tests/fixtures/migration/endpoint/
103
+ ```
104
+
105
+ **When legacy is already retired but source-readable | Legacy 已退役但 source 可讀:**
106
+
107
+ - Trace through legacy source code, manually construct the expected response shape
108
+ - Document each field's origin (SQL column, computed expression, hardcoded) in a sibling `.notes.md` file
109
+ - 從 legacy source code 推導預期 response shape;每個欄位來源(SQL 欄位 / 計算式 / hardcoded)記錄於同位置 `.notes.md`
110
+
111
+ ### Contract test template
112
+
113
+ **C# / xUnit:**
114
+
115
+ ```csharp
116
+ [Theory]
117
+ [InlineData("scenario1")]
118
+ [InlineData("scenario2_empty")]
119
+ [InlineData("scenario3_edge")]
120
+ public async Task Endpoint_ResponseShape_MatchesLegacyFixture(string scenario)
121
+ {
122
+ var fixture = LoadFixture($"migration/endpoint/{scenario}");
123
+ var response = await CallNewImpl(fixture.Input);
124
+ // StructuralEquivalence checks keys + types + placement, ignores values
125
+ StructuralEquivalence.Assert(response, fixture.ExpectedShape);
126
+ }
127
+ ```
128
+
129
+ **TypeScript / Jest:**
130
+
131
+ ```typescript
132
+ import { structuralEquivalence } from "./test-utils/structural-equivalence";
133
+
134
+ describe.each([
135
+ ["scenario1"],
136
+ ["scenario2_empty"],
137
+ ["scenario3_edge"],
138
+ ])("Endpoint response shape vs legacy fixture (%s)", (scenario) => {
139
+ test("matches", async () => {
140
+ const fixture = loadFixture(`migration/endpoint/${scenario}.json`);
141
+ const response = await callNewImpl(fixture.input);
142
+ structuralEquivalence(response, fixture.expectedShape);
143
+ });
144
+ });
145
+ ```
146
+
147
+ `structuralEquivalence` / `StructuralEquivalence.Assert` rule: same set of keys at each level (no missing, no extra unless explicitly opted in), same primitive type per key, same placement (top-level vs nested). Values can differ (timestamps, IDs); types and structure cannot.
148
+
149
+ ### Field-by-field migration audit checklist
150
+
151
+ Before merging any migrated endpoint:
152
+
153
+ - [ ] All legacy response fields mapped to new DTO (no silent drops)
154
+ - [ ] Naming preserved where possible (avoid `TotalX` rename that drops the "per-member" semantic)
155
+ - [ ] Top-level vs nested placement preserved
156
+ - [ ] Type compatibility verified (string→int conversions explicit, not coincidental)
157
+ - [ ] Error path return codes match legacy (`509` not `506`; `404` not `400`)
158
+ - [ ] Contract test fixture committed under `tests/fixtures/migration/`
159
+ - [ ] Cross-link to [contract-test-assistant](../contract-test-assistant/SKILL.md) for ongoing consumer-side verification
160
+
161
+ 合併前必確認:
162
+ - [ ] 所有 legacy response 欄位 mapping 至新 DTO(無 silent drop)
163
+ - [ ] 命名儘量保留
164
+ - [ ] 頂層 vs nested 層級保留
165
+ - [ ] 型別相容性已明確驗證
166
+ - [ ] Error path return code 與 legacy 一致
167
+ - [ ] Contract test fixture 已 commit
168
+ - [ ] Cross-link 至 contract-test-assistant 做持續消費端驗證
169
+
68
170
  ## Rollback Strategy | 回滾策略
69
171
 
70
172
  | Approach | When to Use | 使用時機 |
@@ -100,11 +202,13 @@ After `/migrate` completes, the AI assistant should suggest:
100
202
  ## Reference | 參考
101
203
 
102
204
  - Core standard: [refactoring-standards.md](../../core/refactoring-standards.md)
205
+ - Related: [contract-test-assistant](../contract-test-assistant/SKILL.md) — Strategy for ongoing contract verification post-migration
103
206
 
104
207
  ## Version History | 版本歷史
105
208
 
106
209
  | Version | Date | Changes | 變更 |
107
210
  |---------|------|---------|------|
211
+ | 1.1.0 | 2026-05-26 | Added: API Migration Contract Tests section — mandatory fixture capture protocol, C#/TS templates, field-by-field audit checklist (XSPEC-233 / closes #112) | 新增 API 遷移合約測試章節 |
108
212
  | 1.0.0 | 2026-03-24 | Initial release | 初始版本 |
109
213
 
110
214
 
@@ -43,8 +43,16 @@ Guide runbook writing, maintenance, drill exercises, and coverage reporting.
43
43
  > - 執行 `/incident --postmortem` 從事故更新 Runbook
44
44
  > - 執行 `/checkin` 提交變更
45
45
 
46
+ ## Deploy Runbook — Mandatory Rule
47
+
48
+ Any deploy runbook that includes a destructive-update pattern (stop → swap → start) **MUST** follow the [Defensive Deployment Ordering](../../core/deployment-standards.md#defensive-deployment-ordering) sequence: extract to staging → verify → only then touch the live install. Skipping the verify step has caused real production outages.
49
+
50
+ 任何包含 destructive-update(stop → swap → start)的部署 runbook **必須**遵循 [Defensive Deployment Ordering](../../core/deployment-standards.md#defensive-deployment-ordering) 順序:解壓到 staging → verify → 通過後才動 live install。跳過 verify 步驟已造成真實生產事故。
51
+
46
52
  ## Reference | 參考
47
53
 
48
54
  - Core standard: [runbook-standards.md](../../core/runbook-standards.md)
49
55
  - Related: [alerting-standards.md](../../core/alerting-standards.md)
50
56
  - Related: [postmortem-standards.md](../../core/postmortem-standards.md)
57
+ - Related: [deployment-standards.md § Defensive Deployment Ordering](../../core/deployment-standards.md#defensive-deployment-ordering) — mandatory ordering for destructive deploys
58
+ - Related: [packaging-standards.md § Archive Format Integrity](../../core/packaging-standards.md#archive-format-integrity) — upstream pair to defensive ordering
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "universal-dev-standards",
3
- "version": "5.12.1",
3
+ "version": "5.13.2",
4
4
  "description": "CLI tool for adopting Universal Development Standards",
5
5
  "keywords": [
6
6
  "documentation",
@@ -70,7 +70,7 @@
70
70
  "@vitest/coverage-v8": "^4.1.5",
71
71
  "ajv": "^8.20.0",
72
72
  "ajv-formats": "^3.0.1",
73
- "eslint": "10.3.0",
73
+ "eslint": "10.4.0",
74
74
  "glob": "^13.0.1",
75
75
  "globals": "17.6.0",
76
76
  "husky": "^9.1.7",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "version": "5.12.1",
3
+ "version": "5.13.2",
4
4
  "lastUpdated": "2026-05-13",
5
5
  "description": "Standards registry for universal-dev-standards with integrated skills and AI-optimized formats",
6
6
  "formats": {
@@ -58,14 +58,14 @@
58
58
  "standards": {
59
59
  "name": "universal-dev-standards",
60
60
  "url": "https://github.com/AsiaOstrich/universal-dev-standards",
61
- "version": "5.12.1"
61
+ "version": "5.13.2"
62
62
  },
63
63
  "skills": {
64
64
  "name": "universal-dev-standards",
65
65
  "url": "https://github.com/AsiaOstrich/universal-dev-standards",
66
66
  "localPath": "skills",
67
67
  "rawUrl": "https://raw.githubusercontent.com/AsiaOstrich/universal-dev-standards/main/skills",
68
- "version": "5.12.1",
68
+ "version": "5.13.2",
69
69
  "note": "Skills are now included in the main repository under skills/"
70
70
  }
71
71
  },
@@ -1147,6 +1147,18 @@
1147
1147
  "skillName": null,
1148
1148
  "description": "Content requirements and writing guidelines for different project types"
1149
1149
  },
1150
+ {
1151
+ "id": "self-review-protocol",
1152
+ "name": "Self-Review Protocol",
1153
+ "nameZh": "自我審查協議",
1154
+ "source": {
1155
+ "human": "core/self-review-protocol.md",
1156
+ "ai": "ai/standards/self-review-protocol.ai.yaml"
1157
+ },
1158
+ "category": "reference",
1159
+ "skillName": null,
1160
+ "description": "Mandatory self-review pass on large markdown edits (>50 lines) before commit; catches 6 categories of internal cross-reference inconsistencies (diagram/step mismatch, changelog reference errors, count drift, stale templates, wrong tool references, placeholder vs rule misalignment)"
1161
+ },
1150
1162
  {
1151
1163
  "id": "ai-instruction-standards",
1152
1164
  "name": "AI Instruction File Standards",
@@ -2326,7 +2338,7 @@
2326
2338
  "id": "license-compliance",
2327
2339
  "name": "License Compliance Standards",
2328
2340
  "nameZh": "授權合規標準",
2329
- "version": "5.12.1",
2341
+ "version": "5.13.2",
2330
2342
  "source": {
2331
2343
  "human": "core/license-compliance.md",
2332
2344
  "ai": "ai/standards/license-compliance.ai.yaml"