universal-dev-standards 5.7.3 → 5.10.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.
- package/bundled/ai/language-packs/README.md +55 -0
- package/bundled/ai/language-packs/language-pack-php-to-csharp.ai.yaml +83 -0
- package/bundled/ai/standards/acceptance-criteria-traceability.ai.yaml +49 -3
- package/bundled/ai/standards/behavior-snapshot.ai.yaml +272 -0
- package/bundled/ai/standards/deployment-standards.ai.yaml +108 -3
- package/bundled/ai/standards/feature-discovery-standards.ai.yaml +459 -0
- package/bundled/ai/standards/feature-manifest-standard.ai.yaml +149 -0
- package/bundled/ai/standards/mock-boundary.ai.yaml +93 -2
- package/bundled/ai/standards/multi-environment-e2e-testing.ai.yaml +250 -0
- package/bundled/ai/standards/test-completeness-dimensions.ai.yaml +39 -7
- package/bundled/ai/standards/verification-evidence.ai.yaml +30 -4
- package/bundled/core/acceptance-criteria-traceability.md +41 -6
- package/bundled/core/behavior-snapshot.md +239 -0
- package/bundled/core/feature-manifest-standard.md +213 -0
- package/bundled/locales/zh-CN/CHANGELOG.md +37 -3
- package/bundled/locales/zh-CN/README.md +1 -1
- package/bundled/locales/zh-TW/CHANGELOG.md +37 -3
- package/bundled/locales/zh-TW/README.md +1 -1
- package/bundled/skills/brainstorm-assistant/SKILL.md +183 -30
- package/bundled/skills/brainstorm-assistant/guide.md +607 -117
- package/package.json +4 -4
- package/src/commands/update.js +4 -1
- package/standards-registry.json +53 -5
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# UDS Language Packs
|
|
2
|
+
|
|
3
|
+
Language packs provide migration risk labels for specific source→target language pairs.
|
|
4
|
+
They extend the core `feature-manifest-standard` without polluting the core standard.
|
|
5
|
+
|
|
6
|
+
## Naming Convention
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
language-pack-<source>-to-<target>.ai.yaml
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Examples:
|
|
13
|
+
- `language-pack-php-to-csharp.ai.yaml`
|
|
14
|
+
- `language-pack-java-to-go.ai.yaml`
|
|
15
|
+
- `language-pack-python-to-rust.ai.yaml`
|
|
16
|
+
|
|
17
|
+
## Available Language Packs
|
|
18
|
+
|
|
19
|
+
| Pack | Source | Target | Labels |
|
|
20
|
+
|------|--------|--------|--------|
|
|
21
|
+
| [language-pack-php-to-csharp.ai.yaml](language-pack-php-to-csharp.ai.yaml) | PHP | C# (ASP.NET Core) | SESSION_HANDLING, ORM_DIFFERENCES, TIMEZONE_HANDLING, FILE_UPLOAD_PATH, REGEX_DIFFERENCES, ARRAY_FUNCTIONS, EXCEPTION_HIERARCHY |
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
Reference language pack risk labels in `feature-manifest.yaml` alongside generic labels:
|
|
26
|
+
|
|
27
|
+
```yaml
|
|
28
|
+
features:
|
|
29
|
+
- id: FM-001
|
|
30
|
+
name: UserLogin
|
|
31
|
+
migration_risks:
|
|
32
|
+
- SESSION_HANDLING # from language-pack-php-to-csharp
|
|
33
|
+
- NULL_SEMANTICS # from generic risks (feature-manifest-standard)
|
|
34
|
+
- ASYNC_MODEL # from generic risks
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Generic vs Language Pack Labels
|
|
38
|
+
|
|
39
|
+
| Type | Source | When to use |
|
|
40
|
+
|------|--------|-------------|
|
|
41
|
+
| Generic | `feature-manifest-standard.migration_risks.generic` | All migration projects |
|
|
42
|
+
| Language Pack | `ai/language-packs/<pack>.ai.yaml` | Specific source→target pairs |
|
|
43
|
+
|
|
44
|
+
## Creating a New Language Pack
|
|
45
|
+
|
|
46
|
+
1. Copy the structure from an existing pack
|
|
47
|
+
2. Replace `source`, `target`, and `migration_risks` with the new pair's specifics
|
|
48
|
+
3. Each risk label should have: `label`, `description`, `details` (optional but recommended)
|
|
49
|
+
4. Submit via pull request to UDS with evidence from real migration projects
|
|
50
|
+
|
|
51
|
+
## Architecture Decision
|
|
52
|
+
|
|
53
|
+
Language packs were separated from the core `feature-manifest-standard` in UDS v1.1.0
|
|
54
|
+
(XSPEC-203) to keep the core standard language-agnostic. See `ai/standards/feature-manifest-standard.ai.yaml`
|
|
55
|
+
`migration_risks.language_packs` for the extension point declaration.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Language Pack: PHP → C# (ASP.NET Core) Migration Risks
|
|
2
|
+
# Migrated from: feature-manifest-standard v1.0.0 core standard
|
|
3
|
+
# Use with: feature-manifest.yaml features[].migration_risks
|
|
4
|
+
|
|
5
|
+
language_pack:
|
|
6
|
+
id: php-to-csharp
|
|
7
|
+
source: php
|
|
8
|
+
target: csharp
|
|
9
|
+
meta:
|
|
10
|
+
version: "1.0.0"
|
|
11
|
+
updated: "2026-05-13"
|
|
12
|
+
description: PHP to C# (ASP.NET Core) migration risk labels
|
|
13
|
+
migrated_from: "feature-manifest-standard v1.0.0 migration_risks.php_to_csharp"
|
|
14
|
+
references:
|
|
15
|
+
- "XSPEC-203: Language Pack Architecture"
|
|
16
|
+
|
|
17
|
+
migration_risks:
|
|
18
|
+
- label: SESSION_HANDLING
|
|
19
|
+
description: PHP session → ASP.NET Core Session/Cookie middleware differences
|
|
20
|
+
details: |
|
|
21
|
+
PHP sessions are file-backed by default and rely on PHPSESSID cookie.
|
|
22
|
+
ASP.NET Core uses IDistributedCache (Redis/SQL) backed sessions.
|
|
23
|
+
Check: session_start(), $_SESSION usage → ISession / IDistributedCache
|
|
24
|
+
|
|
25
|
+
- label: ORM_DIFFERENCES
|
|
26
|
+
description: Eloquent ORM → Entity Framework behavioral differences (lazy loading, conventions)
|
|
27
|
+
details: |
|
|
28
|
+
Eloquent uses ActiveRecord pattern; EF Core uses DataMapper/Unit of Work.
|
|
29
|
+
Lazy loading is opt-in in EF Core (vs default in Eloquent).
|
|
30
|
+
Check: Model relationships, ->with() eager loading, timestamps conventions
|
|
31
|
+
|
|
32
|
+
- label: TIMEZONE_HANDLING
|
|
33
|
+
description: PHP timezone functions → .NET DateTimeOffset handling
|
|
34
|
+
details: |
|
|
35
|
+
PHP date() and strtotime() are timezone-sensitive via date_default_timezone_set().
|
|
36
|
+
.NET uses DateTimeOffset for timezone-aware datetimes; DateTime is ambiguous.
|
|
37
|
+
Check: date(), strtotime(), Carbon usage → DateTimeOffset, TimeZoneInfo
|
|
38
|
+
|
|
39
|
+
- label: FILE_UPLOAD_PATH
|
|
40
|
+
description: PHP $_FILES superglobal → ASP.NET Core IFormFile interface
|
|
41
|
+
details: |
|
|
42
|
+
PHP uses $_FILES superglobal with move_uploaded_file().
|
|
43
|
+
ASP.NET Core uses IFormFile with CopyToAsync() and streaming.
|
|
44
|
+
Check: $_FILES, move_uploaded_file(), file validation logic
|
|
45
|
+
|
|
46
|
+
- label: REGEX_DIFFERENCES
|
|
47
|
+
description: PHP PCRE syntax vs .NET Regex syntax differences
|
|
48
|
+
details: |
|
|
49
|
+
PHP uses PCRE with delimiters (e.g., '/pattern/i'); .NET has no delimiters.
|
|
50
|
+
Named groups: PHP (?P<name>) vs .NET (?<name>).
|
|
51
|
+
Unicode properties and some PCRE extensions differ.
|
|
52
|
+
Check: preg_match(), preg_replace(), preg_split() usage
|
|
53
|
+
|
|
54
|
+
- label: ARRAY_FUNCTIONS
|
|
55
|
+
description: PHP array_* functions → LINQ equivalents
|
|
56
|
+
details: |
|
|
57
|
+
PHP array functions are procedural; .NET uses LINQ extension methods.
|
|
58
|
+
array_map() → .Select(); array_filter() → .Where(); array_reduce() → .Aggregate()
|
|
59
|
+
array_unique() → .Distinct(); usort() → .OrderBy()
|
|
60
|
+
Check: array_map, array_filter, array_reduce, usort, array_column usage
|
|
61
|
+
|
|
62
|
+
- label: EXCEPTION_HIERARCHY
|
|
63
|
+
description: PHP exception hierarchy vs .NET exception hierarchy differences
|
|
64
|
+
details: |
|
|
65
|
+
PHP: Exception → RuntimeException → InvalidArgumentException etc.
|
|
66
|
+
.NET: Exception → SystemException / ApplicationException → specific types
|
|
67
|
+
PHP allows catching multiple types with | (PHP 8+); .NET uses catch blocks.
|
|
68
|
+
Check: try/catch blocks, custom exception classes, exception type mapping
|
|
69
|
+
|
|
70
|
+
usage_example: |
|
|
71
|
+
# In feature-manifest.yaml:
|
|
72
|
+
features:
|
|
73
|
+
- id: FM-001
|
|
74
|
+
name: UserLogin
|
|
75
|
+
migration_risks:
|
|
76
|
+
- SESSION_HANDLING # from this language pack
|
|
77
|
+
- NULL_SEMANTICS # from generic risks (feature-manifest-standard)
|
|
78
|
+
|
|
79
|
+
- id: FM-007
|
|
80
|
+
name: OrderCancellation
|
|
81
|
+
migration_risks:
|
|
82
|
+
- ORM_DIFFERENCES # from this language pack
|
|
83
|
+
- ASYNC_MODEL # from generic risks
|
|
@@ -59,9 +59,48 @@ standard:
|
|
|
59
59
|
definition: AC has no tests
|
|
60
60
|
criteria: No test case references this AC
|
|
61
61
|
|
|
62
|
+
- status: not_implemented
|
|
63
|
+
symbol: "🚫"
|
|
64
|
+
definition: AC has no corresponding implementation (feature code does not exist)
|
|
65
|
+
criteria: |
|
|
66
|
+
No business logic in src/ corresponds to this AC.
|
|
67
|
+
Distinct from uncovered: uncovered = code exists but no test; not_implemented = code does not exist.
|
|
68
|
+
Typical signals: throw NotImplementedException(), empty stub body, FEATURE_STUB: marker.
|
|
69
|
+
decision_tree: |
|
|
70
|
+
Q1: Does the corresponding code exist in src/?
|
|
71
|
+
No → not_implemented
|
|
72
|
+
Yes → Q2: Does any test reference this AC?
|
|
73
|
+
No → uncovered
|
|
74
|
+
Yes → Q3: Are all conditions in the AC tested?
|
|
75
|
+
Yes → covered
|
|
76
|
+
No → partial
|
|
77
|
+
|
|
62
78
|
calculation:
|
|
63
|
-
formula: "AC Coverage % = (covered_count + partial_count × 0.5) / total_ac_count × 100"
|
|
64
|
-
note:
|
|
79
|
+
formula: "AC Coverage % = (covered_count + partial_count × 0.5) / (total_ac_count - not_implemented_count) × 100"
|
|
80
|
+
note: |
|
|
81
|
+
not_implemented ACs are excluded from the coverage denominator (separate dimension).
|
|
82
|
+
Partial counts as 0.5 for coverage calculation.
|
|
83
|
+
Example: 20 ACs total, 3 not_implemented, 15 covered, 2 uncovered →
|
|
84
|
+
coverage = (15 + 0) / (20 - 3) × 100 = 88.2%
|
|
85
|
+
|
|
86
|
+
ci_gate:
|
|
87
|
+
not_implemented_blocking: true
|
|
88
|
+
rule: "not_implemented_count > 0 → CI fails with [AC-NOT-IMPL] before UAT gate"
|
|
89
|
+
report_format: |
|
|
90
|
+
AC Traceability Report
|
|
91
|
+
──────────────────────
|
|
92
|
+
🚫 NOT IMPLEMENTED (<count>) — BLOCKING
|
|
93
|
+
AC-007 OrderCancellation src/orders/ 無對應實作
|
|
94
|
+
AC-012 RefundCalculation src/payments/ 無對應實作
|
|
95
|
+
|
|
96
|
+
❌ UNCOVERED (<count>) — WARNING
|
|
97
|
+
AC-003 BulkImport test/import/ 缺測試
|
|
98
|
+
|
|
99
|
+
✅ COVERED (<count>)
|
|
100
|
+
⚠️ PARTIAL (<count>)
|
|
101
|
+
|
|
102
|
+
AC Coverage: <pct>% (<covered>/<implemented_total> implemented ACs)
|
|
103
|
+
Status: BLOCKED by <not_impl_count> not_implemented AC(s)
|
|
65
104
|
|
|
66
105
|
quality_thresholds:
|
|
67
106
|
defaults:
|
|
@@ -147,7 +186,14 @@ standard:
|
|
|
147
186
|
|
|
148
187
|
- id: honest-status
|
|
149
188
|
trigger: reporting AC coverage
|
|
150
|
-
instruction: Use honest status classification (covered/partial/uncovered); never inflate coverage
|
|
189
|
+
instruction: "Use honest status classification (covered/partial/uncovered/not_implemented); never inflate coverage"
|
|
190
|
+
priority: required
|
|
191
|
+
|
|
192
|
+
- id: not-implemented-gate
|
|
193
|
+
trigger: AC traceability matrix contains not_implemented status
|
|
194
|
+
instruction: |
|
|
195
|
+
Flag CI as BLOCKED with [AC-NOT-IMPL] message. List all not_implemented ACs.
|
|
196
|
+
not_implemented must be resolved before UAT. Exclude not_implemented from coverage denominator.
|
|
151
197
|
priority: required
|
|
152
198
|
|
|
153
199
|
- id: track-all-ac
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
# Behavior Snapshot Standard - AI Optimized
|
|
2
|
+
# Source: core/behavior-snapshot.md
|
|
3
|
+
|
|
4
|
+
standard:
|
|
5
|
+
id: behavior-snapshot
|
|
6
|
+
name: Behavior Snapshot Standard
|
|
7
|
+
description: Multi-modal golden file format for migration parity verification and refactoring characterization; supports HTTP, CLI, File, and Event adapters; defines snapshot schema, parity gate, and Gate 0 protocol
|
|
8
|
+
|
|
9
|
+
meta:
|
|
10
|
+
version: "1.1.0"
|
|
11
|
+
updated: "2026-05-13"
|
|
12
|
+
source: core/behavior-snapshot.md
|
|
13
|
+
references:
|
|
14
|
+
- "XSPEC-201: Refactor/Migration Completeness Protocol"
|
|
15
|
+
- "XSPEC-203: Language Pack Architecture (multi-modal adapter extension)"
|
|
16
|
+
- "Michael Feathers: Working Effectively with Legacy Code (characterization tests)"
|
|
17
|
+
- "Golden Master Testing pattern"
|
|
18
|
+
|
|
19
|
+
snapshot_schema:
|
|
20
|
+
description: Format of a single snapshot JSON file in .snapshots/<feature-id>/<scenario>.json
|
|
21
|
+
required_fields:
|
|
22
|
+
- name: adapter
|
|
23
|
+
type: string
|
|
24
|
+
description: "Snapshot adapter type: http (default) | cli | file | event"
|
|
25
|
+
default: "http"
|
|
26
|
+
backward_compat: "Omitting adapter field is equivalent to adapter: http — existing snapshots remain valid"
|
|
27
|
+
- name: feature_id
|
|
28
|
+
type: string
|
|
29
|
+
description: FM-NNN from feature-manifest.yaml
|
|
30
|
+
- name: scenario
|
|
31
|
+
type: string
|
|
32
|
+
description: "Scenario name (snake_case): happy_path, not_found, invalid_credentials, etc."
|
|
33
|
+
- name: ignore_fields
|
|
34
|
+
type: list
|
|
35
|
+
description: |
|
|
36
|
+
Fields to skip during parity comparison.
|
|
37
|
+
Use for legitimately non-deterministic values: timestamps, tokens, IDs.
|
|
38
|
+
Do NOT use to hide business logic differences.
|
|
39
|
+
|
|
40
|
+
http_example: |
|
|
41
|
+
{
|
|
42
|
+
"adapter": "http",
|
|
43
|
+
"feature_id": "FM-007",
|
|
44
|
+
"scenario": "happy_path",
|
|
45
|
+
"request": {
|
|
46
|
+
"method": "POST",
|
|
47
|
+
"path": "/api/orders/123/cancel",
|
|
48
|
+
"headers": { "Content-Type": "application/json" },
|
|
49
|
+
"body": { "reason": "customer_request" }
|
|
50
|
+
},
|
|
51
|
+
"response": {
|
|
52
|
+
"status": 200,
|
|
53
|
+
"body": {
|
|
54
|
+
"success": true,
|
|
55
|
+
"order_status": "cancelled",
|
|
56
|
+
"refund_initiated": true
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"ignore_fields": ["refund_id", "cancelled_at"]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
adapters:
|
|
63
|
+
description: Adapter schemas for different software interaction types. Choose based on how the feature interacts with the outside world.
|
|
64
|
+
|
|
65
|
+
http:
|
|
66
|
+
description: HTTP request/response adapter — for web services and REST APIs (default)
|
|
67
|
+
fields:
|
|
68
|
+
request:
|
|
69
|
+
method: "HTTP method (GET|POST|PUT|PATCH|DELETE)"
|
|
70
|
+
path: "URL path (no base URL)"
|
|
71
|
+
headers: "Optional request headers (omit auth tokens — use placeholder)"
|
|
72
|
+
body: "Optional request body (JSON)"
|
|
73
|
+
response:
|
|
74
|
+
status: "HTTP status code (integer)"
|
|
75
|
+
body: "Response body (JSON object)"
|
|
76
|
+
when_to_use: "Feature is triggered by HTTP request and returns HTTP response"
|
|
77
|
+
|
|
78
|
+
cli:
|
|
79
|
+
description: CLI tool adapter — for command-line tools, scripts, and batch processors
|
|
80
|
+
fields:
|
|
81
|
+
args: "Command arguments array (excluding the program name itself)"
|
|
82
|
+
stdin: "Standard input string (null if the command reads no stdin)"
|
|
83
|
+
stdout: "Expected standard output string"
|
|
84
|
+
stderr: "Expected standard error string (empty string if none expected)"
|
|
85
|
+
exit_code: "Expected exit code (integer: 0 = success)"
|
|
86
|
+
when_to_use: "Feature is invoked via command-line arguments and produces stdout/stderr output"
|
|
87
|
+
example: |
|
|
88
|
+
{
|
|
89
|
+
"adapter": "cli",
|
|
90
|
+
"feature_id": "FM-012",
|
|
91
|
+
"scenario": "convert_csv_to_json",
|
|
92
|
+
"args": ["convert", "--input", "data.csv", "--format", "json"],
|
|
93
|
+
"stdin": null,
|
|
94
|
+
"stdout": "{\"rows\": 42, \"status\": \"ok\"}",
|
|
95
|
+
"stderr": "",
|
|
96
|
+
"exit_code": 0,
|
|
97
|
+
"ignore_fields": []
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
file:
|
|
101
|
+
description: File I/O adapter — for batch processors, report generators, and data pipelines
|
|
102
|
+
fields:
|
|
103
|
+
input_files: "List of input file descriptors: {path, content_hash}"
|
|
104
|
+
output_files: "List of expected output file descriptors: {path, content_hash}"
|
|
105
|
+
content_hash_format: "sha256:<hex> — use fixtures for deterministic input; capture hash from reference run for expected output"
|
|
106
|
+
when_to_use: "Feature reads input files and produces output files (no HTTP or CLI interaction)"
|
|
107
|
+
example: |
|
|
108
|
+
{
|
|
109
|
+
"adapter": "file",
|
|
110
|
+
"feature_id": "FM-015",
|
|
111
|
+
"scenario": "generate_monthly_report",
|
|
112
|
+
"input_files": [
|
|
113
|
+
{ "path": "fixtures/sales_2026_04.csv", "content_hash": "sha256:abc123" }
|
|
114
|
+
],
|
|
115
|
+
"output_files": [
|
|
116
|
+
{ "path": "output/report_2026_04.pdf", "content_hash": "sha256:def456" }
|
|
117
|
+
],
|
|
118
|
+
"ignore_fields": []
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
event:
|
|
122
|
+
description: Event/message adapter — for event-driven systems, message queues, and daemons
|
|
123
|
+
fields:
|
|
124
|
+
trigger: "The triggering event or message: {type, queue/topic, payload}"
|
|
125
|
+
expected_state_changes: "List of expected database/state changes: {entity, field, from, to}"
|
|
126
|
+
expected_side_effects: "List of expected side effects using standard labels: EMAIL_SENT, QUEUE_MESSAGE_PUBLISHED, FILE_WRITTEN, HTTP_CALL_MADE"
|
|
127
|
+
when_to_use: "Feature is triggered by an event/message and produces state changes or side effects"
|
|
128
|
+
example: |
|
|
129
|
+
{
|
|
130
|
+
"adapter": "event",
|
|
131
|
+
"feature_id": "FM-020",
|
|
132
|
+
"scenario": "order_placed_triggers_inventory_deduction",
|
|
133
|
+
"trigger": {
|
|
134
|
+
"type": "message",
|
|
135
|
+
"queue": "orders.placed",
|
|
136
|
+
"payload": { "order_id": "ORD-001", "product_id": "PROD-007", "quantity": 1 }
|
|
137
|
+
},
|
|
138
|
+
"expected_state_changes": [
|
|
139
|
+
{ "entity": "inventory", "field": "quantity", "from": 10, "to": 9 }
|
|
140
|
+
],
|
|
141
|
+
"expected_side_effects": ["EMAIL_SENT", "QUEUE_MESSAGE_PUBLISHED"],
|
|
142
|
+
"ignore_fields": ["processed_at", "message_id"]
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
directory_structure:
|
|
146
|
+
root: ".snapshots/"
|
|
147
|
+
layout: ".snapshots/<feature-id>/<scenario>.json"
|
|
148
|
+
example: |
|
|
149
|
+
.snapshots/
|
|
150
|
+
FM-001-UserLogin/ ← http adapter
|
|
151
|
+
happy_path.json
|
|
152
|
+
invalid_credentials.json
|
|
153
|
+
FM-007-OrderCancellation/ ← http adapter
|
|
154
|
+
happy_path.json
|
|
155
|
+
order_not_found.json
|
|
156
|
+
MANUAL-refund_webhook.json
|
|
157
|
+
FM-012-ConvertCsv/ ← cli adapter
|
|
158
|
+
convert_csv_to_json.json
|
|
159
|
+
missing_input_file.json
|
|
160
|
+
FM-015-MonthlyReport/ ← file adapter
|
|
161
|
+
generate_monthly_report.json
|
|
162
|
+
FM-020-InventoryDeduction/ ← event adapter
|
|
163
|
+
order_placed_triggers_inventory_deduction.json
|
|
164
|
+
manual_prefix:
|
|
165
|
+
description: "Files prefixed MANUAL- contain manually authored snapshots (cannot be auto-recorded)"
|
|
166
|
+
examples:
|
|
167
|
+
- webhook endpoints triggered by third parties
|
|
168
|
+
- scenarios requiring specific database state
|
|
169
|
+
- background job/queue-triggered flows
|
|
170
|
+
|
|
171
|
+
ignore_fields_guidance:
|
|
172
|
+
always_ignore:
|
|
173
|
+
- created_at, updated_at, timestamp, recorded_at
|
|
174
|
+
- token, session_id, csrf_token, access_token, refresh_token
|
|
175
|
+
- request_id, trace_id, correlation_id
|
|
176
|
+
always_compare:
|
|
177
|
+
- status, code, message, error_code
|
|
178
|
+
- user_id, order_id (when using fixed test data)
|
|
179
|
+
- amount, quantity, price (business calculation results)
|
|
180
|
+
- "success, refunded, cancelled (boolean business outcomes)"
|
|
181
|
+
|
|
182
|
+
parity_gate:
|
|
183
|
+
description: CI gate comparing new system responses against recorded snapshots
|
|
184
|
+
tool: "npx tsx scripts/parity-check.ts --url <target-url> --snapshots .snapshots [--env <uat|staging>]"
|
|
185
|
+
pass_criteria: "100% of non-MANUAL snapshots must match (status + non-ignored body fields)"
|
|
186
|
+
failure_behavior:
|
|
187
|
+
uat_or_production: "Exit 1 — deployment blocked with [PARITY-BLOCK] message"
|
|
188
|
+
staging: "Exit 2 — warning only with [PARITY-WARN] message"
|
|
189
|
+
report_format: |
|
|
190
|
+
Parity Results: <passed>/<total> passed (<pct>%)
|
|
191
|
+
✅ FM-001 / happy_path
|
|
192
|
+
✅ FM-001 / invalid_credentials
|
|
193
|
+
❌ [PARITY-FAIL] FM-007 / happy_path
|
|
194
|
+
body.order_status: expected "cancelled", got "pending"
|
|
195
|
+
|
|
196
|
+
gate_zero_protocol:
|
|
197
|
+
description: Characterization test gate for refactoring (XSPEC-201 Phase 1)
|
|
198
|
+
when: "--variant refactor in /vo-pipeline"
|
|
199
|
+
requirement: |
|
|
200
|
+
Characterization tests must exist and ALL pass before refactoring begins.
|
|
201
|
+
Characterization tests lock existing behavior — they do not test correctness,
|
|
202
|
+
they test that the behavior does not change during refactoring.
|
|
203
|
+
test_annotation: "@characterization or describe('characterization')"
|
|
204
|
+
enforcement: |
|
|
205
|
+
Gate 0: Run characterization tests before first refactoring commit.
|
|
206
|
+
Any failure during refactoring triggers immediate warning.
|
|
207
|
+
Gate 2: All characterization tests must pass before refactoring is considered complete.
|
|
208
|
+
anti_pattern: "Do NOT start refactoring without Gate 0 — behavior drift becomes undetectable"
|
|
209
|
+
|
|
210
|
+
rules:
|
|
211
|
+
- id: snapshot-before-migration
|
|
212
|
+
trigger: starting --variant migration pipeline
|
|
213
|
+
instruction: |
|
|
214
|
+
.snapshots/ must exist with at least one snapshot per feature before pipeline starts.
|
|
215
|
+
This is Gate 1b in the pre-flight check.
|
|
216
|
+
priority: required
|
|
217
|
+
|
|
218
|
+
- id: characterization-before-refactor
|
|
219
|
+
trigger: starting --variant refactor pipeline
|
|
220
|
+
instruction: |
|
|
221
|
+
Characterization tests must exist and pass before any refactoring begins.
|
|
222
|
+
If characterization tests don't exist, halt and prompt developer to write them.
|
|
223
|
+
priority: required
|
|
224
|
+
|
|
225
|
+
- id: ignore-fields-discipline
|
|
226
|
+
trigger: creating or reviewing snapshot ignore_fields
|
|
227
|
+
instruction: |
|
|
228
|
+
Only add fields to ignore_fields if they are legitimately non-deterministic
|
|
229
|
+
(timestamps, tokens, random IDs). Business logic fields must always be compared.
|
|
230
|
+
Overuse of ignore_fields defeats the purpose of parity testing.
|
|
231
|
+
priority: required
|
|
232
|
+
|
|
233
|
+
- id: manual-snapshots
|
|
234
|
+
trigger: snapshot cannot be auto-recorded
|
|
235
|
+
instruction: |
|
|
236
|
+
Prefix filename with MANUAL- and note why auto-recording is not possible.
|
|
237
|
+
MANUAL- snapshots must be authored by a human with full business knowledge.
|
|
238
|
+
They are excluded from auto-replay but count toward coverage reporting.
|
|
239
|
+
priority: recommended
|
|
240
|
+
|
|
241
|
+
- id: parity-100-before-uat
|
|
242
|
+
trigger: before UAT deployment in migration pipeline
|
|
243
|
+
instruction: |
|
|
244
|
+
Run parity check against all non-MANUAL snapshots.
|
|
245
|
+
100% pass rate required. Any failure blocks UAT deployment.
|
|
246
|
+
Fix parity failures before promoting — they represent behavioral divergence.
|
|
247
|
+
priority: required
|
|
248
|
+
|
|
249
|
+
- id: adapter-selection
|
|
250
|
+
trigger: creating a behavior snapshot
|
|
251
|
+
instruction: |
|
|
252
|
+
Select the adapter matching the feature's interaction type.
|
|
253
|
+
Use http ONLY for actual HTTP endpoint features.
|
|
254
|
+
Use cli for command-line tool features.
|
|
255
|
+
Use file for batch I/O and report generation features.
|
|
256
|
+
Use event for message-driven and daemon features.
|
|
257
|
+
When in doubt about which adapter to use, refer to the adapters section's when_to_use fields.
|
|
258
|
+
priority: required
|
|
259
|
+
|
|
260
|
+
- id: backward-compatibility
|
|
261
|
+
trigger: reading existing snapshot files without adapter field
|
|
262
|
+
instruction: |
|
|
263
|
+
Treat snapshot files missing the adapter field as adapter=http.
|
|
264
|
+
Do NOT require migration of existing snapshot files to add adapter field.
|
|
265
|
+
New snapshots should always include the adapter field explicitly.
|
|
266
|
+
priority: required
|
|
267
|
+
|
|
268
|
+
related_standards:
|
|
269
|
+
- feature-manifest-standard.ai.yaml
|
|
270
|
+
- acceptance-criteria-traceability.ai.yaml
|
|
271
|
+
- refactoring-standards.ai.yaml
|
|
272
|
+
- testing.ai.yaml
|
|
@@ -12,10 +12,13 @@ standard:
|
|
|
12
12
|
- "Automate build, test, deploy, and rollback"
|
|
13
13
|
|
|
14
14
|
meta:
|
|
15
|
-
version: "1.
|
|
16
|
-
updated: "2026-
|
|
15
|
+
version: "1.1.0"
|
|
16
|
+
updated: "2026-05-13"
|
|
17
17
|
source: core/deployment-standards.md
|
|
18
|
-
description:
|
|
18
|
+
description: >
|
|
19
|
+
Safe deployment strategies, feature flags, rollback, environment parity, and DORA metrics.
|
|
20
|
+
v1.1.0: Added environment stratification responsibility matrix and stub server CI/CD
|
|
21
|
+
lifecycle rules (XSPEC-204).
|
|
19
22
|
|
|
20
23
|
principles:
|
|
21
24
|
core:
|
|
@@ -125,6 +128,108 @@ checklist:
|
|
|
125
128
|
medium_term_24hr: ["Batch jobs successful", "Data consistency verified", "No memory leaks"]
|
|
126
129
|
long_term_1wk: ["Flag cleanup scheduled", "Retrospective completed", "Docs updated"]
|
|
127
130
|
|
|
131
|
+
# ─────────────────────────────────────────────────────────
|
|
132
|
+
# Environment Stratification Responsibility Matrix (v1.1.0)
|
|
133
|
+
# ─────────────────────────────────────────────────────────
|
|
134
|
+
environment_stratification_matrix:
|
|
135
|
+
rule: >
|
|
136
|
+
Projects with external dependencies MUST build an environment stratification
|
|
137
|
+
responsibility matrix at test-planning time (not at release candidate review).
|
|
138
|
+
This matrix answers: "Which test flows can be fully verified in which environment?"
|
|
139
|
+
when_required: "Any project with external service dependencies (SMS, payment, IdP, messaging, etc.)"
|
|
140
|
+
where: "docs/testing/environment-stratification-matrix.md or in the test plan"
|
|
141
|
+
|
|
142
|
+
template: |
|
|
143
|
+
## Environment Stratification Responsibility Matrix
|
|
144
|
+
|
|
145
|
+
| Flow / Feature | local UAT | Remote UAT | PRD |
|
|
146
|
+
|------------------------|:----------------:|:----------------:|:------------------:|
|
|
147
|
+
| Auth / Login | ✅ stub IdP | ✅ Keycloak/AD | ✅ Enterprise IdP |
|
|
148
|
+
| SMS Sending | ⚠️ L2-stub | ❌ / ⚠️ | ✅ Real + billing |
|
|
149
|
+
| Payment / Purchase | ⚠️ L2-stub | ⚠️ network-dep | ✅ Real + reconcile|
|
|
150
|
+
| User / Dept Management | ✅ | ✅ cross-machine | ✅ |
|
|
151
|
+
| Background Jobs | ✅ in-process | ✅ | ✅ |
|
|
152
|
+
|
|
153
|
+
Legend:
|
|
154
|
+
✅ Full E2E verification possible
|
|
155
|
+
⚠️ Flow passes through stub/mock — real-world dimensions NOT verified
|
|
156
|
+
❌ Cannot test in this environment layer
|
|
157
|
+
|
|
158
|
+
### PRD-only verification items (must plan PRD smoke test coverage)
|
|
159
|
+
- SMS billing correctness
|
|
160
|
+
- Payment real debit + bank reconciliation
|
|
161
|
+
- Enterprise AD group sync behavior
|
|
162
|
+
|
|
163
|
+
mandatory_rule: >
|
|
164
|
+
This matrix MUST be reviewed at test planning stage alongside
|
|
165
|
+
acceptance-criteria-traceability. It is NOT acceptable to discover
|
|
166
|
+
PRD-only verification items for the first time during release candidate review.
|
|
167
|
+
|
|
168
|
+
# ─────────────────────────────────────────────────────────
|
|
169
|
+
# Stub Server CI/CD Lifecycle Rules (v1.1.0)
|
|
170
|
+
# ─────────────────────────────────────────────────────────
|
|
171
|
+
stub_server_cicd_rules:
|
|
172
|
+
rationale: >
|
|
173
|
+
Production CI/CD artifacts commonly exclude stub server directories for valid
|
|
174
|
+
security reasons (e.g., MockSoap/, tests/stub-server/ excluded from build.ps1).
|
|
175
|
+
Without explicit rules, this creates an undocumented "UAT cannot test X" situation
|
|
176
|
+
that is discovered too late in the release cycle.
|
|
177
|
+
|
|
178
|
+
build_time:
|
|
179
|
+
rules:
|
|
180
|
+
- "Production artifact MUST exclude all stub server code directories"
|
|
181
|
+
- "Exclusion rule MUST be documented in docs/uat/STUB-EXCLUSION-RATIONALE.md"
|
|
182
|
+
- "CI build verification step MUST confirm stub directories are absent from artifact"
|
|
183
|
+
example_ps1: |
|
|
184
|
+
# build.ps1 — explicit exclusion with documentation comment
|
|
185
|
+
# Stub server excluded from production artifact (see docs/uat/STUB-EXCLUSION-RATIONALE.md)
|
|
186
|
+
# Consequence: UAT machine cannot run SMS/MMS flow without sidecar deployment (see Option A below)
|
|
187
|
+
$exclude = @("MockSoap", "tests/stub-server", "test-fixtures")
|
|
188
|
+
|
|
189
|
+
uat_deployment:
|
|
190
|
+
rule: "Choose Option A or Option B; document the choice; do NOT leave it undocumented"
|
|
191
|
+
options:
|
|
192
|
+
option_a_sidecar_deploy:
|
|
193
|
+
name: "Sidecar Deployment (Recommended)"
|
|
194
|
+
description: >
|
|
195
|
+
Stub server deployed as separate process to UAT machine;
|
|
196
|
+
application configured via env var to reach the stub endpoint.
|
|
197
|
+
benefit: "Decoupled from app artifact; independently updatable"
|
|
198
|
+
example_github_actions: |
|
|
199
|
+
deploy-stub-server:
|
|
200
|
+
environment: uat
|
|
201
|
+
steps:
|
|
202
|
+
- name: Deploy stub server to UAT
|
|
203
|
+
run: |
|
|
204
|
+
ssh uat-machine "cd /opt/stub-server && pm2 start server.js --name stub-server"
|
|
205
|
+
- name: Configure app to use stub
|
|
206
|
+
run: echo "SMS_ENDPOINT=http://uat-machine:9999/soap" >> $GITHUB_ENV
|
|
207
|
+
example_gitlab_ci: |
|
|
208
|
+
deploy-stub-server:
|
|
209
|
+
stage: deploy
|
|
210
|
+
environment: uat
|
|
211
|
+
script:
|
|
212
|
+
- ssh uat-machine "pm2 start tests/stub-server/server.js --name stub-server"
|
|
213
|
+
only: [uat-branch, tags]
|
|
214
|
+
|
|
215
|
+
option_b_prd_smoke_deferral:
|
|
216
|
+
name: "PRD Smoke Deferral"
|
|
217
|
+
description: >
|
|
218
|
+
Document which flows cannot be tested in UAT; explicitly mark them as
|
|
219
|
+
PRD-smoke-only items. These items must appear in the environment stratification matrix.
|
|
220
|
+
requirement: "Must be reflected as ❌ in environment stratification matrix with PRD smoke plan"
|
|
221
|
+
|
|
222
|
+
prd_prohibitions:
|
|
223
|
+
- "MUST NOT deploy or run stub servers in PRD environment"
|
|
224
|
+
- "MUST NOT include stub server code in PRD artifact"
|
|
225
|
+
- "MUST NOT allow network access to stub server endpoints from PRD"
|
|
226
|
+
|
|
227
|
+
forbidden_state: >
|
|
228
|
+
It is NEVER acceptable to have "no stub server AND no real service AND no documented
|
|
229
|
+
deferral" for a testable flow. Every flow must be either:
|
|
230
|
+
(a) fully testable in UAT via real service or Level 2 stub server, OR
|
|
231
|
+
(b) explicitly documented as PRD-smoke-only with a smoke test plan.
|
|
232
|
+
|
|
128
233
|
physical_spec:
|
|
129
234
|
type: custom_script
|
|
130
235
|
validator:
|