@sun-asterisk/sungen 3.2.10-beta.6 → 3.2.10

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 (45) hide show
  1. package/dist/capabilities/discover.d.ts.map +1 -1
  2. package/dist/capabilities/discover.js +2 -5
  3. package/dist/capabilities/discover.js.map +1 -1
  4. package/dist/cli/commands/capability.d.ts.map +1 -1
  5. package/dist/cli/commands/capability.js +2 -44
  6. package/dist/cli/commands/capability.js.map +1 -1
  7. package/dist/harness/capability.d.ts +0 -1
  8. package/dist/harness/capability.d.ts.map +1 -1
  9. package/dist/harness/capability.js.map +1 -1
  10. package/dist/harness/catalog/drivers.yaml +1 -2
  11. package/dist/harness/query-catalog.d.ts +2 -32
  12. package/dist/harness/query-catalog.d.ts.map +1 -1
  13. package/dist/harness/query-catalog.js +0 -0
  14. package/dist/harness/query-catalog.js.map +1 -1
  15. package/dist/index.d.ts +2 -2
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +1 -3
  18. package/dist/index.js.map +1 -1
  19. package/dist/orchestrator/templates/ai-src/commands/run-test.md +0 -1
  20. package/dist/orchestrator/templates/ai-src/config/claude.md +1 -3
  21. package/dist/orchestrator/templates/ai-src/config/copilot.md +1 -3
  22. package/dist/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +5 -15
  23. package/dist/orchestrator/templates/specs-db.d.ts +11 -201
  24. package/dist/orchestrator/templates/specs-db.d.ts.map +1 -1
  25. package/dist/orchestrator/templates/specs-db.js +91 -440
  26. package/dist/orchestrator/templates/specs-db.js.map +1 -1
  27. package/dist/orchestrator/templates/specs-db.ts +79 -463
  28. package/dist/orchestrator/templates/specs-test-data.ts +3 -39
  29. package/package.json +4 -8
  30. package/src/capabilities/discover.ts +2 -5
  31. package/src/cli/commands/capability.ts +2 -40
  32. package/src/harness/capability.ts +0 -1
  33. package/src/harness/catalog/drivers.yaml +1 -2
  34. package/src/harness/query-catalog.ts +0 -0
  35. package/src/index.ts +2 -2
  36. package/src/orchestrator/templates/ai-src/commands/run-test.md +0 -1
  37. package/src/orchestrator/templates/ai-src/config/claude.md +1 -3
  38. package/src/orchestrator/templates/ai-src/config/copilot.md +1 -3
  39. package/src/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +5 -15
  40. package/src/orchestrator/templates/specs-db.ts +79 -463
  41. package/src/orchestrator/templates/specs-test-data.ts +3 -39
  42. package/dist/orchestrator/templates/ai-src/commands/create-data-test.md +0 -85
  43. package/dist/orchestrator/templates/ai-src/skills/sungen-data-factory/SKILL.md +0 -101
  44. package/src/orchestrator/templates/ai-src/commands/create-data-test.md +0 -85
  45. package/src/orchestrator/templates/ai-src/skills/sungen-data-factory/SKILL.md +0 -101
@@ -48,27 +48,9 @@ export class TestDataLoader {
48
48
  if (value === undefined || value === null) {
49
49
  throw new Error(`Test data key not found: ${key}`);
50
50
  }
51
- // A projected array (e.g. `{{q.rows[*].name}}`) serializes as a JSON list so the full
52
- // ordered set is preserved for the assert-compare — String([...]) would flatten it to a
53
- // lossy comma-join that can't be distinguished from a scalar containing commas.
54
- if (Array.isArray(value)) return this.interpolate(JSON.stringify(value));
55
51
  return this.interpolate(String(value));
56
52
  }
57
53
 
58
- /**
59
- * Resolve a key to its RAW, uncoerced value (array/object/number kept as-is) — for binding
60
- * DB query parameters, where type-strict stores (MySQL numeric columns, MongoDB) require the
61
- * native type. get() stringifies for Gherkin text; raw() must not. Throws on missing, mirroring
62
- * get()'s guard.
63
- */
64
- raw(key: string): any {
65
- const value = this.resolve(key);
66
- if (value === undefined || value === null) {
67
- throw new Error(`Test data key not found: ${key}`);
68
- }
69
- return value;
70
- }
71
-
72
54
  /**
73
55
  * Substitute embedded `{{ref}}` cross-references inside a resolved string value.
74
56
  * Each ref is looked up via resolve() (flat key, @cases row column, or dotted path),
@@ -96,7 +78,6 @@ export class TestDataLoader {
96
78
  * `q.count` / `q.length` → number of rows
97
79
  * `q.first.col` / `q.last.col` / `q[2].col` → a specific row's column
98
80
  * `q.col` → shorthand for the first row's column
99
- * `q.rows[*].col` → the `col` of EVERY row, projected to an ordered array
100
81
  */
101
82
  private resolve(key: string): any {
102
83
  // 1. Exact flat key — captured vars (set()) live under a literal, possibly dotted, key.
@@ -107,26 +88,9 @@ export class TestDataLoader {
107
88
  return this.data[key];
108
89
  }
109
90
  // 2. Structured path: head from the row (cases) or shared data, then walk segments.
110
- // `[n]` `.n` (numeric index); `[*]` → `.*` (project the rest of the path over each element).
111
- const tokens = String(key).replace(/\[(\d+)\]/g, '.$1').replace(/\[\*\]/g, '.*').split('.');
112
- const cur: any = (this.row && tokens[0] in this.row) ? this.row[tokens[0]] : this.data[tokens[0]];
113
- return TestDataLoader.walk(cur, tokens, 1);
114
- }
115
-
116
- /**
117
- * Walk the remaining path tokens from `i`. A `*` token on an array projects: the rest of the
118
- * path is mapped over every element and the collected array returned (recurses for nested `[*]`).
119
- * Non-`*` tokens use the linear single-step navigation, so numeric/first/last/object access is
120
- * unchanged.
121
- */
122
- private static walk(cur: any, tokens: string[], i: number): any {
123
- for (; i < tokens.length && cur != null; i++) {
124
- if (tokens[i] === '*' && Array.isArray(cur)) {
125
- const rest = tokens.slice(i + 1);
126
- return cur.map((el) => TestDataLoader.walk(el, rest, 0));
127
- }
128
- cur = TestDataLoader.step(cur, tokens[i]);
129
- }
91
+ const tokens = String(key).replace(/\[(\d+)\]/g, '.$1').split('.');
92
+ let cur: any = (this.row && tokens[0] in this.row) ? this.row[tokens[0]] : this.data[tokens[0]];
93
+ for (let i = 1; i < tokens.length && cur != null; i++) cur = TestDataLoader.step(cur, tokens[i]);
130
94
  return cur;
131
95
  }
132
96
 
@@ -1,85 +0,0 @@
1
- ---
2
- name: create-data-test
3
- description: "Generate standardized test-data for a screen/flow from the Data Factory catalog — valid/boundary/invalid values with CHK-* traceability (no free-form guessing)"
4
- argument-hint: [screen-or-flow-name]
5
- order: 25
6
- claude-tools: "Read, Grep, Bash, Glob, Write, Edit, AskUserQuestion, Skill"
7
- copilot-tools: "[vscode, execute, read, agent, edit, search, todo]"
8
- codex-trigger: "Run when the user asks to CREATE, generate, or standardize TEST DATA / test values for a screen or flow (valid/boundary/invalid, boundary values, negative data). Uses the Data Factory driver. Not for generating the .feature scenarios themselves (that is create-test)."
9
- ---
10
-
11
- **Input**: A screen or flow name (e.g., `/sungen:create-data-test login`), OR **no name** to do every unit (with a confirmation — see ALL mode). Load the `sungen-data-factory` skill for the full method.
12
-
13
- ## Role
14
-
15
- You are a **Senior QA Engineer** producing **test data to a standard**, not by guessing. You do NOT invent values field-by-field. You follow the 4-source method (spec rules → field-type catalog → design technique → DB mapping), driven by the **Data Factory** capability driver. Values come from the catalog (`common/` + the project's `.overwrite`), each tagged with a `CHK-*` id that traces back to the spec. Where the catalog cannot cover a project-specific field, you **ask the QA** — you never fabricate domain data.
16
-
17
- ## Preconditions
18
-
19
- 1. **Availability** — Data Factory is **bundled with core** (no `capability add` needed); its CLI (`sungen data …`) is available out of the box. Just continue.
20
- 2. Determine mode from `$ARGUMENTS`:
21
- - A **name** given → single-unit mode (that screen/flow only).
22
- - **No name** → **ALL mode** (see below — always confirm first).
23
-
24
- ## ALL mode (no name) — confirm before doing everything
25
-
26
- If no name was given, the user wants **all** screens/flows — but this is wide, and a missing name is often a typo (they meant `create-data-test home`). So:
27
-
28
- 1. List every unit under `qa/screens/*` and `qa/flows/*`, and classify each as **new** (no `test-data/<name>.yaml` yet) vs **would-overwrite**.
29
- 2. Show the list and use `AskUserQuestion` to confirm: *"Generate test-data for ALL N units? (X new · Y would overwrite)"* — default to **No**.
30
- 3. Only proceed when the user confirms. Then run the per-unit flow below for each (the CLI `sungen data gen --all` also enforces this confirm; `--yes` after the user agrees).
31
-
32
- ## Per-unit flow (single unit, or each unit in ALL mode)
33
-
34
- Auto-detect: `qa/flows/<name>/` → flow; else `qa/screens/<name>/` → screen. (API units carry their contract in `apis.yaml` — data there is `@cases` in create-test, not this command.)
35
-
36
- ### 1. Read the sources (Nguồn 1 + 4)
37
-
38
- Read `qa/<screens|flows>/<name>/requirements/spec.md` and `test-viewpoint.md`. For **each input field / parameter**, extract:
39
- - data **type** (map to a catalog field-type: email · password · phone · string · number-integer · number-float · currency · postcode · katakana …),
40
- - `required`, format, **min/max** length or value,
41
- - the real **error/message code** the spec shows when a rule is violated,
42
- - any **DB mapping** (unique, cross-entity dependency) noted in the spec.
43
-
44
- Viewpoint tells you which fields are high-priority → give them the fullest data.
45
-
46
- **No input fields → nothing to generate.** If the unit is a pure navigation / listing / capture-compare flow (e.g. a home-shopping browse flow) with **no user-input fields or parameters**, Data Factory has nothing to standardize. Report *"`<name>`: no input fields → nothing to generate"* and stop for this unit — do **not** write an empty `qa/data-factory/<name>.fields.yaml`. (Its scenarios are covered by create-test's data, not by field-level test data.)
47
-
48
- ### 2. Write the field-map — `qa/data-factory/<name>.fields.yaml`
49
-
50
- This is the input the deterministic generator expands. One entry per field:
51
-
52
- ```yaml
53
- screen: <name> # or: flow: <name>
54
- fields:
55
- - name: email
56
- type: email
57
- required: true
58
- constraints: { maxLocal: 64, maxTotal: 254 } # project's real limits
59
- errorMap: { M13: E1042, M02: E1001 } # catalog placeholder → project's real code
60
- - name: password
61
- type: password
62
- constraints: { minLength: 8, maxLength: 32 }
63
- ```
64
-
65
- Map every placeholder error code you can (`errorMap`) to the spec's real code. Leave a code unmapped only if the spec truly has none — the lint will flag it as an open point to confirm with BA/Dev.
66
-
67
- ### 3. Blind spots — ask, do not invent
68
-
69
- If a field's type is **not** in the catalog (a business enum, a cross-entity constraint, a project data model), **stop and ask the QA** with `AskUserQuestion` for: (1) the valid set, (2) invalid / non-existent values, (3) the error code when wrong, (4) dependencies on other fields. Record the answer in `qa/data-factory/project/<entity>.yaml` for reuse. Never fabricate domain values.
70
-
71
- ### 4. Lint the coverage
72
-
73
- Run (local-first): `[ -x ./bin/sungen.js ] && ./bin/sungen.js data lint --screen <name> || npx sungen data lint --screen <name>`. Fix what it reports: add missing boundary values, resolve `UNRESOLVED` items (supply the constraint), map `OPEN_ERRORREF` codes. The bar is the phuong-phap §6 checklist — every required field has valid + boundary + invalid, one invalid per rule.
74
-
75
- ### 5. Generate the test-data
76
-
77
- Run (local-first): `[ -x ./bin/sungen.js ] && ./bin/sungen.js data gen --screen <name> || npx sungen data gen --screen <name>`. If `test-data/<name>.yaml` already exists it **asks before overwriting** — respect the user's choice (in ALL mode after they confirmed, add `--yes`; use `--force` only when the user explicitly wants an unconditional overwrite). The output is standardized `valid/boundary/invalid` values with `CHK-*` traceability.
78
-
79
- ### 6. Weave into scenarios (if create-test already ran)
80
-
81
- If the `.feature` exists, turn the generated invalid/boundary sets into data-driven `Scenario Outline` + `Examples` (`@cases`) referencing the values — following `sungen-gherkin-syntax`. Otherwise leave the standardized `test-data/<name>.yaml` for `/sungen:run-test` to consume.
82
-
83
- ## After running
84
-
85
- Use `AskUserQuestion` to offer the next step: review the generated data, run `/sungen:create-test <name>` (if scenarios don't exist yet), or `/sungen:run-test <name>`.
@@ -1,101 +0,0 @@
1
- ---
2
- name: sungen-data-factory
3
- description: 'Use when create-data-test (or create-test) needs standardized TEST DATA — valid/boundary/invalid values for input fields with CHK-* traceability. Drives the Data Factory catalog + the 4-source method. Invoke after reading spec.md, when authoring the field-map or filling test-data.'
4
- user-invocable: false
5
- ---
6
-
7
- ## What this skill does
8
-
9
- Turn a screen/flow's fields into **standardized test data** — not guessed values. You author a
10
- **field-map**; the deterministic `sungen data gen` expands it from the Data Factory **catalog**
11
- (field-type + security + technique library) into valid / boundary / invalid values, each carrying a
12
- `CHK-*` id that traces to the spec. Your judgment goes into *reading the spec correctly* and
13
- *answering blind spots* — never into inventing values the catalog or the QA should own.
14
-
15
- Data Factory is **bundled with core** (runtime-free) — no `capability add` needed; the `sungen data …`
16
- CLI is available out of the box.
17
-
18
- ## The 4-source method (phuong-phap-tao-test-data.md)
19
-
20
- Never invent values from memory. Cross-reference four sources — each covers the previous one's gap:
21
-
22
- 1. **Spec validate rules** — required, format, min/max, business rules, and the **error/message code**
23
- per rule. Defines the legal/illegal boundary. (Says the *law*, not every way to *break* it.)
24
- 2. **Field-type catalog** — the accumulated "how this type breaks" knowledge (email/password/phone/
25
- number/…). This is the Data Factory `common/` — it fills the "spec doesn't list every break" gap.
26
- 3. **Design technique** — Boundary Value Analysis / Equivalence Partitioning / Decision Table / State
27
- Transition — reduces the rule + candidates to a *minimal-but-sufficient* representative set.
28
- 4. **DB mapping** — unique constraints, cross-entity dependency, real backend limits → precondition
29
- data, not just a single input value.
30
-
31
- Then classify every value into **Valid / Boundary / Invalid** (each invalid tagged with its error
32
- code) and give it a `CHK-*` id for traceability.
33
-
34
- ## The field-map — `qa/data-factory/<name>.fields.yaml`
35
-
36
- Your main artifact. One entry per input field; the generator expands it:
37
-
38
- ```yaml
39
- screen: login # or flow: <name>
40
- fields:
41
- - name: email
42
- type: email # a catalog field-type (see list below)
43
- required: true
44
- constraints: { maxLocal: 64, maxTotal: 254 } # the project's REAL limits from spec
45
- errorMap: { M13: E1042, M02: E1001 } # catalog placeholder code → project's real code
46
- - name: password
47
- type: password
48
- constraints: { minLength: 8, maxLength: 32 }
49
- ```
50
-
51
- **Catalog field-types** (P1): `email` · `password` · `phone` · `string` · `number-integer` ·
52
- `number-float` · `currency` · `postcode` · `katakana` (JP). Security payload banks auto-append to a
53
- field's invalid group via the type's `uses_security` (`sqli`, `xss`, `idor`, `broken-auth`, `upload`,
54
- `input-validation`).
55
-
56
- Rules:
57
- - Pick the closest `type`; put the project's real numbers in `constraints` (they override the
58
- catalog defaults).
59
- - Map every `errorRef` placeholder (`M13`, `M39`, …) to the spec's real code via `errorMap`. Leave
60
- one unmapped **only** if the spec has none — the lint flags it as an open point to confirm.
61
-
62
- ## No input fields → nothing to generate
63
-
64
- Data Factory standardizes **field-level input data**. If a unit has no user-input fields or
65
- parameters — a pure navigation, listing, or capture-compare flow — there is nothing to generate.
66
- Report *"no input fields → nothing to generate"* and skip it; do **not** write an empty field-map.
67
- Those scenarios are covered by the data create-test already produced, not by field-level test data.
68
- (This is a correct outcome, not a gap — don't force a field-map to make the unit "processed".)
69
-
70
- ## Blind spots — ask, never fabricate
71
-
72
- If a field's type is **not** in the catalog — a business enum, a cross-entity constraint, a
73
- project-specific data model — do **not** guess. Ask the QA (via `AskUserQuestion`) for: (1) the valid
74
- set, (2) invalid / non-existent values, (3) the error code when wrong, (4) dependencies on other
75
- fields. Record it in `qa/data-factory/project/<entity>.yaml` so it becomes reusable project catalog.
76
- This is the core discipline: *common is never enough; when blind, think and ask — don't invent.*
77
-
78
- ## Customizing the catalog — `.overwrite` (survives `sungen update`)
79
-
80
- The shipped `common/` is a floor. Project rules go in `qa/data-factory/common.overwrite.yaml`,
81
- deep-merged over the common (**later-wins**, keyed by `type` + data-point `id`): same `id` replaces,
82
- new `id` appends, `constraints` merge key-by-key. `sungen update` refreshes `common/` but never
83
- touches your overlay. If an update makes an overlay entry stale (references a bank/constraint that no
84
- longer exists), the loader **warns you to prune it** — it never edits your file. Prefer a targeted
85
- `errorMap`/`constraints` in the field-map for per-screen tweaks; use `.overwrite` only for rules that
86
- apply project-wide.
87
-
88
- ## Verify before done — the phuong-phap §6 checklist
89
-
90
- Run `sungen data lint` and clear it: every required field has **≥1 valid**, **boundary present**
91
- (exact min/max, not only over-boundary) for bounded types, **≥1 invalid per rule** (not one generic
92
- "wrong" value for many rules), no `UNRESOLVED` values, error codes mapped or explicitly left open.
93
- Then `sungen data gen` writes the standardized `test-data/<name>.yaml`. Do not hand-edit the
94
- generated values — change the field-map or `.overwrite` and re-run (determinism: same input → same
95
- data).
96
-
97
- ## Weaving into scenarios
98
-
99
- When a `.feature` exists, express invalid/boundary sets as data-driven `Scenario Outline` + `Examples`
100
- (`@cases`) referencing the values — see `sungen-gherkin-syntax`. This keeps one logic + many values
101
- instead of copy-pasted scenarios, and each row carries its `CHK-*` id for traceability.
@@ -1,85 +0,0 @@
1
- ---
2
- name: create-data-test
3
- description: "Generate standardized test-data for a screen/flow from the Data Factory catalog — valid/boundary/invalid values with CHK-* traceability (no free-form guessing)"
4
- argument-hint: [screen-or-flow-name]
5
- order: 25
6
- claude-tools: "Read, Grep, Bash, Glob, Write, Edit, AskUserQuestion, Skill"
7
- copilot-tools: "[vscode, execute, read, agent, edit, search, todo]"
8
- codex-trigger: "Run when the user asks to CREATE, generate, or standardize TEST DATA / test values for a screen or flow (valid/boundary/invalid, boundary values, negative data). Uses the Data Factory driver. Not for generating the .feature scenarios themselves (that is create-test)."
9
- ---
10
-
11
- **Input**: A screen or flow name (e.g., `/sungen:create-data-test login`), OR **no name** to do every unit (with a confirmation — see ALL mode). Load the `sungen-data-factory` skill for the full method.
12
-
13
- ## Role
14
-
15
- You are a **Senior QA Engineer** producing **test data to a standard**, not by guessing. You do NOT invent values field-by-field. You follow the 4-source method (spec rules → field-type catalog → design technique → DB mapping), driven by the **Data Factory** capability driver. Values come from the catalog (`common/` + the project's `.overwrite`), each tagged with a `CHK-*` id that traces back to the spec. Where the catalog cannot cover a project-specific field, you **ask the QA** — you never fabricate domain data.
16
-
17
- ## Preconditions
18
-
19
- 1. **Availability** — Data Factory is **bundled with core** (no `capability add` needed); its CLI (`sungen data …`) is available out of the box. Just continue.
20
- 2. Determine mode from `$ARGUMENTS`:
21
- - A **name** given → single-unit mode (that screen/flow only).
22
- - **No name** → **ALL mode** (see below — always confirm first).
23
-
24
- ## ALL mode (no name) — confirm before doing everything
25
-
26
- If no name was given, the user wants **all** screens/flows — but this is wide, and a missing name is often a typo (they meant `create-data-test home`). So:
27
-
28
- 1. List every unit under `qa/screens/*` and `qa/flows/*`, and classify each as **new** (no `test-data/<name>.yaml` yet) vs **would-overwrite**.
29
- 2. Show the list and use `AskUserQuestion` to confirm: *"Generate test-data for ALL N units? (X new · Y would overwrite)"* — default to **No**.
30
- 3. Only proceed when the user confirms. Then run the per-unit flow below for each (the CLI `sungen data gen --all` also enforces this confirm; `--yes` after the user agrees).
31
-
32
- ## Per-unit flow (single unit, or each unit in ALL mode)
33
-
34
- Auto-detect: `qa/flows/<name>/` → flow; else `qa/screens/<name>/` → screen. (API units carry their contract in `apis.yaml` — data there is `@cases` in create-test, not this command.)
35
-
36
- ### 1. Read the sources (Nguồn 1 + 4)
37
-
38
- Read `qa/<screens|flows>/<name>/requirements/spec.md` and `test-viewpoint.md`. For **each input field / parameter**, extract:
39
- - data **type** (map to a catalog field-type: email · password · phone · string · number-integer · number-float · currency · postcode · katakana …),
40
- - `required`, format, **min/max** length or value,
41
- - the real **error/message code** the spec shows when a rule is violated,
42
- - any **DB mapping** (unique, cross-entity dependency) noted in the spec.
43
-
44
- Viewpoint tells you which fields are high-priority → give them the fullest data.
45
-
46
- **No input fields → nothing to generate.** If the unit is a pure navigation / listing / capture-compare flow (e.g. a home-shopping browse flow) with **no user-input fields or parameters**, Data Factory has nothing to standardize. Report *"`<name>`: no input fields → nothing to generate"* and stop for this unit — do **not** write an empty `qa/data-factory/<name>.fields.yaml`. (Its scenarios are covered by create-test's data, not by field-level test data.)
47
-
48
- ### 2. Write the field-map — `qa/data-factory/<name>.fields.yaml`
49
-
50
- This is the input the deterministic generator expands. One entry per field:
51
-
52
- ```yaml
53
- screen: <name> # or: flow: <name>
54
- fields:
55
- - name: email
56
- type: email
57
- required: true
58
- constraints: { maxLocal: 64, maxTotal: 254 } # project's real limits
59
- errorMap: { M13: E1042, M02: E1001 } # catalog placeholder → project's real code
60
- - name: password
61
- type: password
62
- constraints: { minLength: 8, maxLength: 32 }
63
- ```
64
-
65
- Map every placeholder error code you can (`errorMap`) to the spec's real code. Leave a code unmapped only if the spec truly has none — the lint will flag it as an open point to confirm with BA/Dev.
66
-
67
- ### 3. Blind spots — ask, do not invent
68
-
69
- If a field's type is **not** in the catalog (a business enum, a cross-entity constraint, a project data model), **stop and ask the QA** with `AskUserQuestion` for: (1) the valid set, (2) invalid / non-existent values, (3) the error code when wrong, (4) dependencies on other fields. Record the answer in `qa/data-factory/project/<entity>.yaml` for reuse. Never fabricate domain values.
70
-
71
- ### 4. Lint the coverage
72
-
73
- Run (local-first): `[ -x ./bin/sungen.js ] && ./bin/sungen.js data lint --screen <name> || npx sungen data lint --screen <name>`. Fix what it reports: add missing boundary values, resolve `UNRESOLVED` items (supply the constraint), map `OPEN_ERRORREF` codes. The bar is the phuong-phap §6 checklist — every required field has valid + boundary + invalid, one invalid per rule.
74
-
75
- ### 5. Generate the test-data
76
-
77
- Run (local-first): `[ -x ./bin/sungen.js ] && ./bin/sungen.js data gen --screen <name> || npx sungen data gen --screen <name>`. If `test-data/<name>.yaml` already exists it **asks before overwriting** — respect the user's choice (in ALL mode after they confirmed, add `--yes`; use `--force` only when the user explicitly wants an unconditional overwrite). The output is standardized `valid/boundary/invalid` values with `CHK-*` traceability.
78
-
79
- ### 6. Weave into scenarios (if create-test already ran)
80
-
81
- If the `.feature` exists, turn the generated invalid/boundary sets into data-driven `Scenario Outline` + `Examples` (`@cases`) referencing the values — following `sungen-gherkin-syntax`. Otherwise leave the standardized `test-data/<name>.yaml` for `/sungen:run-test` to consume.
82
-
83
- ## After running
84
-
85
- Use `AskUserQuestion` to offer the next step: review the generated data, run `/sungen:create-test <name>` (if scenarios don't exist yet), or `/sungen:run-test <name>`.
@@ -1,101 +0,0 @@
1
- ---
2
- name: sungen-data-factory
3
- description: 'Use when create-data-test (or create-test) needs standardized TEST DATA — valid/boundary/invalid values for input fields with CHK-* traceability. Drives the Data Factory catalog + the 4-source method. Invoke after reading spec.md, when authoring the field-map or filling test-data.'
4
- user-invocable: false
5
- ---
6
-
7
- ## What this skill does
8
-
9
- Turn a screen/flow's fields into **standardized test data** — not guessed values. You author a
10
- **field-map**; the deterministic `sungen data gen` expands it from the Data Factory **catalog**
11
- (field-type + security + technique library) into valid / boundary / invalid values, each carrying a
12
- `CHK-*` id that traces to the spec. Your judgment goes into *reading the spec correctly* and
13
- *answering blind spots* — never into inventing values the catalog or the QA should own.
14
-
15
- Data Factory is **bundled with core** (runtime-free) — no `capability add` needed; the `sungen data …`
16
- CLI is available out of the box.
17
-
18
- ## The 4-source method (phuong-phap-tao-test-data.md)
19
-
20
- Never invent values from memory. Cross-reference four sources — each covers the previous one's gap:
21
-
22
- 1. **Spec validate rules** — required, format, min/max, business rules, and the **error/message code**
23
- per rule. Defines the legal/illegal boundary. (Says the *law*, not every way to *break* it.)
24
- 2. **Field-type catalog** — the accumulated "how this type breaks" knowledge (email/password/phone/
25
- number/…). This is the Data Factory `common/` — it fills the "spec doesn't list every break" gap.
26
- 3. **Design technique** — Boundary Value Analysis / Equivalence Partitioning / Decision Table / State
27
- Transition — reduces the rule + candidates to a *minimal-but-sufficient* representative set.
28
- 4. **DB mapping** — unique constraints, cross-entity dependency, real backend limits → precondition
29
- data, not just a single input value.
30
-
31
- Then classify every value into **Valid / Boundary / Invalid** (each invalid tagged with its error
32
- code) and give it a `CHK-*` id for traceability.
33
-
34
- ## The field-map — `qa/data-factory/<name>.fields.yaml`
35
-
36
- Your main artifact. One entry per input field; the generator expands it:
37
-
38
- ```yaml
39
- screen: login # or flow: <name>
40
- fields:
41
- - name: email
42
- type: email # a catalog field-type (see list below)
43
- required: true
44
- constraints: { maxLocal: 64, maxTotal: 254 } # the project's REAL limits from spec
45
- errorMap: { M13: E1042, M02: E1001 } # catalog placeholder code → project's real code
46
- - name: password
47
- type: password
48
- constraints: { minLength: 8, maxLength: 32 }
49
- ```
50
-
51
- **Catalog field-types** (P1): `email` · `password` · `phone` · `string` · `number-integer` ·
52
- `number-float` · `currency` · `postcode` · `katakana` (JP). Security payload banks auto-append to a
53
- field's invalid group via the type's `uses_security` (`sqli`, `xss`, `idor`, `broken-auth`, `upload`,
54
- `input-validation`).
55
-
56
- Rules:
57
- - Pick the closest `type`; put the project's real numbers in `constraints` (they override the
58
- catalog defaults).
59
- - Map every `errorRef` placeholder (`M13`, `M39`, …) to the spec's real code via `errorMap`. Leave
60
- one unmapped **only** if the spec has none — the lint flags it as an open point to confirm.
61
-
62
- ## No input fields → nothing to generate
63
-
64
- Data Factory standardizes **field-level input data**. If a unit has no user-input fields or
65
- parameters — a pure navigation, listing, or capture-compare flow — there is nothing to generate.
66
- Report *"no input fields → nothing to generate"* and skip it; do **not** write an empty field-map.
67
- Those scenarios are covered by the data create-test already produced, not by field-level test data.
68
- (This is a correct outcome, not a gap — don't force a field-map to make the unit "processed".)
69
-
70
- ## Blind spots — ask, never fabricate
71
-
72
- If a field's type is **not** in the catalog — a business enum, a cross-entity constraint, a
73
- project-specific data model — do **not** guess. Ask the QA (via `AskUserQuestion`) for: (1) the valid
74
- set, (2) invalid / non-existent values, (3) the error code when wrong, (4) dependencies on other
75
- fields. Record it in `qa/data-factory/project/<entity>.yaml` so it becomes reusable project catalog.
76
- This is the core discipline: *common is never enough; when blind, think and ask — don't invent.*
77
-
78
- ## Customizing the catalog — `.overwrite` (survives `sungen update`)
79
-
80
- The shipped `common/` is a floor. Project rules go in `qa/data-factory/common.overwrite.yaml`,
81
- deep-merged over the common (**later-wins**, keyed by `type` + data-point `id`): same `id` replaces,
82
- new `id` appends, `constraints` merge key-by-key. `sungen update` refreshes `common/` but never
83
- touches your overlay. If an update makes an overlay entry stale (references a bank/constraint that no
84
- longer exists), the loader **warns you to prune it** — it never edits your file. Prefer a targeted
85
- `errorMap`/`constraints` in the field-map for per-screen tweaks; use `.overwrite` only for rules that
86
- apply project-wide.
87
-
88
- ## Verify before done — the phuong-phap §6 checklist
89
-
90
- Run `sungen data lint` and clear it: every required field has **≥1 valid**, **boundary present**
91
- (exact min/max, not only over-boundary) for bounded types, **≥1 invalid per rule** (not one generic
92
- "wrong" value for many rules), no `UNRESOLVED` values, error codes mapped or explicitly left open.
93
- Then `sungen data gen` writes the standardized `test-data/<name>.yaml`. Do not hand-edit the
94
- generated values — change the field-map or `.overwrite` and re-run (determinism: same input → same
95
- data).
96
-
97
- ## Weaving into scenarios
98
-
99
- When a `.feature` exists, express invalid/boundary sets as data-driven `Scenario Outline` + `Examples`
100
- (`@cases`) referencing the values — see `sungen-gherkin-syntax`. This keeps one logic + many values
101
- instead of copy-pasted scenarios, and each row carries its `CHK-*` id for traceability.