@sun-asterisk/sungen 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/dist/cli/commands/audit.d.ts.map +1 -1
  2. package/dist/cli/commands/audit.js +24 -0
  3. package/dist/cli/commands/audit.js.map +1 -1
  4. package/dist/cli/commands/delivery.d.ts.map +1 -1
  5. package/dist/cli/commands/delivery.js +30 -14
  6. package/dist/cli/commands/delivery.js.map +1 -1
  7. package/dist/cli/commands/eval.d.ts +3 -0
  8. package/dist/cli/commands/eval.d.ts.map +1 -0
  9. package/dist/cli/commands/eval.js +37 -0
  10. package/dist/cli/commands/eval.js.map +1 -0
  11. package/dist/cli/commands/ingest.d.ts +3 -0
  12. package/dist/cli/commands/ingest.d.ts.map +1 -0
  13. package/dist/cli/commands/ingest.js +179 -0
  14. package/dist/cli/commands/ingest.js.map +1 -0
  15. package/dist/cli/index.js +4 -0
  16. package/dist/cli/index.js.map +1 -1
  17. package/dist/dashboard/templates/index.html +108 -194
  18. package/dist/generators/test-generator/adapters/adapter-interface.d.ts +1 -0
  19. package/dist/generators/test-generator/adapters/adapter-interface.d.ts.map +1 -1
  20. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.d.ts +1 -0
  21. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.d.ts.map +1 -1
  22. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.js.map +1 -1
  23. package/dist/generators/test-generator/adapters/playwright/templates/imports.hbs +3 -0
  24. package/dist/generators/test-generator/code-generator.d.ts +4 -0
  25. package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
  26. package/dist/generators/test-generator/code-generator.js +31 -2
  27. package/dist/generators/test-generator/code-generator.js.map +1 -1
  28. package/dist/generators/test-generator/patterns/database-patterns.d.ts +5 -0
  29. package/dist/generators/test-generator/patterns/database-patterns.d.ts.map +1 -0
  30. package/dist/generators/test-generator/patterns/database-patterns.js +94 -0
  31. package/dist/generators/test-generator/patterns/database-patterns.js.map +1 -0
  32. package/dist/generators/test-generator/patterns/index.d.ts +1 -0
  33. package/dist/generators/test-generator/patterns/index.d.ts.map +1 -1
  34. package/dist/generators/test-generator/patterns/index.js +6 -1
  35. package/dist/generators/test-generator/patterns/index.js.map +1 -1
  36. package/dist/generators/test-generator/template-engine.d.ts +1 -0
  37. package/dist/generators/test-generator/template-engine.d.ts.map +1 -1
  38. package/dist/generators/test-generator/template-engine.js +1 -1
  39. package/dist/generators/test-generator/template-engine.js.map +1 -1
  40. package/dist/harness/audit.d.ts +16 -0
  41. package/dist/harness/audit.d.ts.map +1 -1
  42. package/dist/harness/audit.js +69 -5
  43. package/dist/harness/audit.js.map +1 -1
  44. package/dist/harness/capability-plan.d.ts +6 -0
  45. package/dist/harness/capability-plan.d.ts.map +1 -1
  46. package/dist/harness/capability-plan.js +14 -1
  47. package/dist/harness/capability-plan.js.map +1 -1
  48. package/dist/harness/catalog/drivers.yaml +1 -1
  49. package/dist/harness/catalog/universal-viewpoints.yaml +1 -1
  50. package/dist/harness/eval/skill-lint.d.ts +16 -0
  51. package/dist/harness/eval/skill-lint.d.ts.map +1 -0
  52. package/dist/harness/eval/skill-lint.js +129 -0
  53. package/dist/harness/eval/skill-lint.js.map +1 -0
  54. package/dist/harness/flow-plan.js +1 -1
  55. package/dist/harness/parse.d.ts +6 -0
  56. package/dist/harness/parse.d.ts.map +1 -1
  57. package/dist/harness/parse.js +18 -3
  58. package/dist/harness/parse.js.map +1 -1
  59. package/dist/harness/quality-gates.d.ts +29 -0
  60. package/dist/harness/quality-gates.d.ts.map +1 -0
  61. package/dist/harness/quality-gates.js +183 -0
  62. package/dist/harness/quality-gates.js.map +1 -0
  63. package/dist/harness/script-check.d.ts.map +1 -1
  64. package/dist/harness/script-check.js +4 -1
  65. package/dist/harness/script-check.js.map +1 -1
  66. package/dist/harness/sensors.d.ts.map +1 -1
  67. package/dist/harness/sensors.js +85 -6
  68. package/dist/harness/sensors.js.map +1 -1
  69. package/dist/harness/spec-coverage.d.ts +37 -0
  70. package/dist/harness/spec-coverage.d.ts.map +1 -0
  71. package/dist/harness/spec-coverage.js +159 -0
  72. package/dist/harness/spec-coverage.js.map +1 -0
  73. package/dist/harness/viewpoint-ledger.d.ts +23 -0
  74. package/dist/harness/viewpoint-ledger.d.ts.map +1 -0
  75. package/dist/harness/viewpoint-ledger.js +118 -0
  76. package/dist/harness/viewpoint-ledger.js.map +1 -0
  77. package/dist/ingest/baseline-audit.d.ts +38 -0
  78. package/dist/ingest/baseline-audit.d.ts.map +1 -0
  79. package/dist/ingest/baseline-audit.js +85 -0
  80. package/dist/ingest/baseline-audit.js.map +1 -0
  81. package/dist/ingest/gsheet-fetch.d.ts +9 -0
  82. package/dist/ingest/gsheet-fetch.d.ts.map +1 -0
  83. package/dist/ingest/gsheet-fetch.js +180 -0
  84. package/dist/ingest/gsheet-fetch.js.map +1 -0
  85. package/dist/ingest/index.d.ts +6 -0
  86. package/dist/ingest/index.d.ts.map +1 -0
  87. package/dist/ingest/index.js +22 -0
  88. package/dist/ingest/index.js.map +1 -0
  89. package/dist/ingest/legacy-parser.d.ts +39 -0
  90. package/dist/ingest/legacy-parser.d.ts.map +1 -0
  91. package/dist/ingest/legacy-parser.js +218 -0
  92. package/dist/ingest/legacy-parser.js.map +1 -0
  93. package/dist/ingest/reconcile.d.ts +30 -0
  94. package/dist/ingest/reconcile.d.ts.map +1 -0
  95. package/dist/ingest/reconcile.js +65 -0
  96. package/dist/ingest/reconcile.js.map +1 -0
  97. package/dist/ingest/to-gherkin.d.ts +33 -0
  98. package/dist/ingest/to-gherkin.d.ts.map +1 -0
  99. package/dist/ingest/to-gherkin.js +93 -0
  100. package/dist/ingest/to-gherkin.js.map +1 -0
  101. package/dist/orchestrator/ai-rules-updater.d.ts.map +1 -1
  102. package/dist/orchestrator/ai-rules-updater.js +2 -0
  103. package/dist/orchestrator/ai-rules-updater.js.map +1 -1
  104. package/dist/orchestrator/templates/ai-instructions/claude-agent-reviewer.md +1 -0
  105. package/dist/orchestrator/templates/ai-instructions/claude-skill-delivery.md +10 -0
  106. package/dist/orchestrator/templates/ai-instructions/claude-skill-harness-audit.md +1 -1
  107. package/dist/orchestrator/templates/ai-instructions/claude-skill-ingest-legacy.md +79 -0
  108. package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +25 -1
  109. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-delivery.md +10 -0
  110. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-harness-audit.md +1 -1
  111. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-ingest-legacy.md +79 -0
  112. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +44 -7
  113. package/dist/orchestrator/templates/specs-db.d.ts +18 -0
  114. package/dist/orchestrator/templates/specs-db.d.ts.map +1 -0
  115. package/dist/orchestrator/templates/specs-db.js +171 -0
  116. package/dist/orchestrator/templates/specs-db.js.map +1 -0
  117. package/dist/orchestrator/templates/specs-db.ts +147 -0
  118. package/docs/orchestration-spec.md +3 -3
  119. package/package.json +4 -4
  120. package/src/cli/commands/audit.ts +19 -0
  121. package/src/cli/commands/delivery.ts +31 -15
  122. package/src/cli/commands/eval.ts +28 -0
  123. package/src/cli/commands/ingest.ts +141 -0
  124. package/src/cli/index.ts +4 -0
  125. package/src/dashboard/templates/index.html +108 -194
  126. package/src/generators/test-generator/adapters/adapter-interface.ts +1 -1
  127. package/src/generators/test-generator/adapters/playwright/playwright-adapter.ts +1 -1
  128. package/src/generators/test-generator/adapters/playwright/templates/imports.hbs +3 -0
  129. package/src/generators/test-generator/code-generator.ts +29 -2
  130. package/src/generators/test-generator/patterns/database-patterns.ts +95 -0
  131. package/src/generators/test-generator/patterns/index.ts +3 -0
  132. package/src/generators/test-generator/template-engine.ts +2 -2
  133. package/src/harness/audit.ts +82 -5
  134. package/src/harness/capability-plan.ts +12 -1
  135. package/src/harness/catalog/drivers.yaml +1 -1
  136. package/src/harness/catalog/universal-viewpoints.yaml +1 -1
  137. package/src/harness/eval/skill-lint.ts +87 -0
  138. package/src/harness/flow-plan.ts +1 -1
  139. package/src/harness/parse.ts +19 -3
  140. package/src/harness/quality-gates.ts +152 -0
  141. package/src/harness/script-check.ts +4 -1
  142. package/src/harness/sensors.ts +84 -7
  143. package/src/harness/spec-coverage.ts +139 -0
  144. package/src/harness/viewpoint-ledger.ts +80 -0
  145. package/src/ingest/baseline-audit.ts +100 -0
  146. package/src/ingest/gsheet-fetch.ts +152 -0
  147. package/src/ingest/index.ts +5 -0
  148. package/src/ingest/legacy-parser.ts +184 -0
  149. package/src/ingest/reconcile.ts +80 -0
  150. package/src/ingest/to-gherkin.ts +108 -0
  151. package/src/orchestrator/ai-rules-updater.ts +2 -0
  152. package/src/orchestrator/templates/ai-instructions/claude-agent-reviewer.md +1 -0
  153. package/src/orchestrator/templates/ai-instructions/claude-skill-delivery.md +10 -0
  154. package/src/orchestrator/templates/ai-instructions/claude-skill-harness-audit.md +1 -1
  155. package/src/orchestrator/templates/ai-instructions/claude-skill-ingest-legacy.md +79 -0
  156. package/src/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +25 -1
  157. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-delivery.md +10 -0
  158. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-harness-audit.md +1 -1
  159. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-ingest-legacy.md +79 -0
  160. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +44 -7
  161. package/src/orchestrator/templates/specs-db.ts +147 -0
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.parseSpecClauses = parseSpecClauses;
37
+ exports.specCoverage = specCoverage;
38
+ /**
39
+ * Spec-clause coverage (harness G2) — the spec-layer faithfulness check.
40
+ *
41
+ * Parses the structured parts of a screen `spec.md` (Functional Requirements + the
42
+ * Validation Rules table) and verifies (a) every MUST FR is covered by a scenario and
43
+ * (b) for EACH validation constraint, every trigger the spec mandates is actually
44
+ * exercised. The trigger check is PER-CONSTRAINT — so "validate format on blur AND on
45
+ * submit" tested only on blur is caught even when other constraints do use submit.
46
+ * Generic: no project data.
47
+ */
48
+ const fs = __importStar(require("fs"));
49
+ // Parsing the spec's Trigger CELL: loose word match ("blur, submit").
50
+ const SPEC_TRIGGER = [
51
+ { trigger: 'blur', re: /\b(blur|on blur|focus[- ]?out)\b/i },
52
+ { trigger: 'submit', re: /\b(submit|on submit)\b/i },
53
+ ];
54
+ // Detecting the trigger ACTION in a scenario: must be an actual action, NOT the word
55
+ // "submit" in a "[Submit] button is disabled" assertion.
56
+ const ACTION_TRIGGER = [
57
+ { trigger: 'blur', re: /\b(press tab|blur|focus[- ]?out|loses? focus|tab away|tab out)\b/i },
58
+ { trigger: 'submit', re: /(click \[submit\]|press enter|\benter key\b|送信する)/i },
59
+ ];
60
+ function modalityOf(text) {
61
+ if (/\bMUST\b/.test(text))
62
+ return 'MUST';
63
+ if (/\bSHOULD\b/.test(text))
64
+ return 'SHOULD';
65
+ return 'MAY';
66
+ }
67
+ function specTriggersIn(text) {
68
+ return SPEC_TRIGGER.filter((t) => t.re.test(text)).map((t) => t.trigger);
69
+ }
70
+ function actionTriggersIn(text) {
71
+ return ACTION_TRIGGER.filter((t) => t.re.test(text)).map((t) => t.trigger);
72
+ }
73
+ function parseSpecClauses(specPath) {
74
+ if (!fs.existsSync(specPath))
75
+ return { frs: [], valRows: [] };
76
+ const lines = fs.readFileSync(specPath, 'utf-8').split('\n');
77
+ const frs = [];
78
+ for (const line of lines) {
79
+ const m = line.match(/\*\*FR-(\d+)\*\*\s*:\s*(.+)$/);
80
+ if (m)
81
+ frs.push({ id: `FR-${m[1]}`, text: m[2].replace(/\*\*/g, '').trim(), modality: modalityOf(m[2]) });
82
+ }
83
+ // Validation Rules table: a row carries a Constraint, a Trigger cell, and (often) a code.
84
+ const valRows = [];
85
+ let cTrigger = -1, cConstraint = -1, cCode = -1, inTable = false;
86
+ for (const raw of lines) {
87
+ const line = raw.trim();
88
+ if (line.startsWith('|') && /\btrigger\b/i.test(line) && cTrigger < 0) {
89
+ const cells = line.split('|').map((c) => c.trim());
90
+ cTrigger = cells.findIndex((c) => /^trigger$/i.test(c));
91
+ cConstraint = cells.findIndex((c) => /constraint/i.test(c));
92
+ cCode = cells.findIndex((c) => /code/i.test(c));
93
+ inTable = cTrigger >= 0;
94
+ continue;
95
+ }
96
+ if (inTable) {
97
+ if (!line.startsWith('|')) {
98
+ inTable = false;
99
+ cTrigger = -1;
100
+ continue;
101
+ }
102
+ if (/^\|[\s|:-]+\|?$/.test(line))
103
+ continue;
104
+ const cells = line.split('|').map((c) => c.trim());
105
+ const triggers = [...new Set((cells[cTrigger] || '').split(/,|\band\b/i).flatMap((p) => specTriggersIn(p)))];
106
+ if (!triggers.length)
107
+ continue; // server-only rows etc.
108
+ const constraint = (cConstraint >= 0 ? cells[cConstraint] : '').replace(/`/g, '') || 'validation';
109
+ const codeM = (cCode >= 0 ? cells[cCode] : line).match(/M\d+/);
110
+ valRows.push({ constraint, code: codeM ? codeM[0] : '', triggers });
111
+ }
112
+ }
113
+ return { frs, valRows };
114
+ }
115
+ /** Split a feature file into per-scenario blocks (tags + comments + steps), keyed by blank lines. */
116
+ function scenarioBlocks(featureText) {
117
+ return featureText.split(/\n\s*\n/).filter((b) => /\bScenario:/.test(b)).map((b) => b.toLowerCase());
118
+ }
119
+ function specCoverage(specPath, scenarios, featureText) {
120
+ const { frs, valRows } = parseSpecClauses(specPath);
121
+ if (!fs.existsSync(specPath) || (frs.length === 0 && valRows.length === 0)) {
122
+ return { hasSpec: fs.existsSync(specPath), frTotal: 0, frCovered: 0, uncoveredMust: [], triggerGaps: [], verdict: 'pass' };
123
+ }
124
+ const featLower = featureText.toLowerCase();
125
+ // FR coverage: explicit @spec:FR / literal FR-id citation, else keyword fallback.
126
+ const uncoveredMust = [];
127
+ let frCovered = 0;
128
+ for (const fr of frs) {
129
+ const idLower = fr.id.toLowerCase();
130
+ const cited = featLower.includes(idLower);
131
+ const words = [...new Set((fr.text.toLowerCase().match(/[a-z][a-z-]{4,}/g) || []))]
132
+ .filter((w) => !/must|should|system|screen|users?|value|input|field/.test(w));
133
+ const kwHit = words.length > 0 && scenarios.some((s) => words.filter((w) => s.haystack.includes(w)).length >= Math.min(2, words.length));
134
+ if (cited || kwHit)
135
+ frCovered++;
136
+ else if (fr.modality === 'MUST')
137
+ uncoveredMust.push({ id: fr.id, text: fr.text.slice(0, 90) });
138
+ }
139
+ // Per-constraint trigger coverage — the matrix-collapse catch.
140
+ // generic words that don't identify a constraint (would over-match happy-path scenarios)
141
+ const GENERIC = new Set(['valid', 'local', 'part', 'domain', 'email', 'address', 'must', 'exist', 'store', 'field', 'input', 'value', 'formed', 'well', 'character', 'characters']);
142
+ const blocks = scenarioBlocks(featureText);
143
+ const triggerGaps = [];
144
+ for (const row of valRows) {
145
+ const kw = (row.constraint.toLowerCase().match(/[a-z]{4,}/g) || []).filter((w) => !GENERIC.has(w));
146
+ // blocks that belong to this constraint: cite its msg code (primary), or mention a
147
+ // DISTINCTIVE constraint word (generic words filtered to avoid matching happy paths).
148
+ const own = blocks.filter((b) => (row.code && b.includes(row.code.toLowerCase())) || kw.some((w) => b.includes(w)));
149
+ if (!own.length)
150
+ continue; // constraint has no scenarios at all — FR/viewpoint gate covers that
151
+ const found = [...new Set(own.flatMap((b) => actionTriggersIn(b)))];
152
+ const missing = row.triggers.filter((t) => !found.includes(t));
153
+ if (missing.length)
154
+ triggerGaps.push({ constraint: row.constraint, code: row.code, required: row.triggers, found, missing });
155
+ }
156
+ const verdict = uncoveredMust.length > 0 || triggerGaps.length > 0 ? 'fail' : 'pass';
157
+ return { hasSpec: true, frTotal: frs.length, frCovered, uncoveredMust, triggerGaps, verdict };
158
+ }
159
+ //# sourceMappingURL=spec-coverage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec-coverage.js","sourceRoot":"","sources":["../../src/harness/spec-coverage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { ScenarioInfo } from './parse';
2
+ export interface LedgerItem {
3
+ id?: string;
4
+ text: string;
5
+ covered: boolean;
6
+ }
7
+ export interface LedgerResult {
8
+ hasViewpoint: boolean;
9
+ total: number;
10
+ covered: number;
11
+ ratio: number;
12
+ missing: {
13
+ id?: string;
14
+ text: string;
15
+ }[];
16
+ }
17
+ /** Extract atomic checklist items from a viewpoint file (format-tolerant). */
18
+ export declare function parseViewpointItems(viewpointPath: string): {
19
+ id?: string;
20
+ text: string;
21
+ }[];
22
+ export declare function viewpointLedger(viewpointPath: string, scenarios: ScenarioInfo[], featureText: string): LedgerResult;
23
+ //# sourceMappingURL=viewpoint-ledger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewpoint-ledger.d.ts","sourceRoot":"","sources":["../../src/harness/viewpoint-ledger.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,MAAM,WAAW,UAAU;IAAG,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE;AAE3E,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC1C;AAKD,8EAA8E;AAC9E,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CA4B1F;AAED,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,YAAY,CAsBnH"}
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.parseViewpointItems = parseViewpointItems;
37
+ exports.viewpointLedger = viewpointLedger;
38
+ /**
39
+ * Viewpoint Atomic Coverage Ledger (harness #2).
40
+ *
41
+ * The project's `test-viewpoint.md` IS the coverage contract. This parses it into ATOMIC
42
+ * items (each bullet / table row / ID-prefixed line) and reports the status of EACH —
43
+ * covered / missing — instead of the coarse "viewpoint mentioned" signal. It is fully
44
+ * project-driven (works on any project's viewpoint file, any domain), which is why it
45
+ * scales where a hardcoded domain catalog does not. Advisory: it surfaces the per-item
46
+ * gaps that inflate a "looks-covered" score; it does not fail the gate.
47
+ */
48
+ const fs = __importStar(require("fs"));
49
+ const ID_RE = /\b([A-Z]{1,5}\d{0,2}(?:[.\-][A-Za-z0-9]+)*-?\d{0,3})\b/; // VP0.Title, VP7-002, MS-HP-001, TV-01
50
+ const GENERIC = new Set(['display', 'shown', 'value', 'field', 'input', 'page', 'screen', 'button', 'link', 'text', 'check', 'verify', 'should', 'with', 'when', 'then', 'user', 'this', 'that', 'each', 'item', 'items']);
51
+ /** Extract atomic checklist items from a viewpoint file (format-tolerant). */
52
+ function parseViewpointItems(viewpointPath) {
53
+ if (!fs.existsSync(viewpointPath))
54
+ return [];
55
+ const lines = fs.readFileSync(viewpointPath, 'utf-8').split('\n');
56
+ const items = [];
57
+ let inFence = false;
58
+ for (const raw of lines) {
59
+ const line = raw.trim();
60
+ if (line.startsWith('```')) {
61
+ inFence = !inFence;
62
+ continue;
63
+ }
64
+ if (inFence || !line)
65
+ continue;
66
+ if (/^#{1,6}\s/.test(line))
67
+ continue; // markdown heading
68
+ let text = '';
69
+ const bullet = line.match(/^(?:[-*+]|\d+[.)])\s+(.*)$/);
70
+ if (bullet)
71
+ text = bullet[1];
72
+ else if (line.startsWith('|')) { // table data row
73
+ if (/^\|[\s|:-]+\|?$/.test(line))
74
+ continue; // separator
75
+ const cells = line.split('|').map((c) => c.trim()).filter(Boolean);
76
+ if (/^(vp|id|viewpoint|priority|reason|no\.?|category|item|trigger|#|pattern|applicable|notes|field|constraint|code|description|status)$/i.test(cells[0] || ''))
77
+ continue; // header
78
+ text = cells.join(' — ');
79
+ }
80
+ else
81
+ continue;
82
+ text = text.replace(/[*`]/g, '').trim();
83
+ if (!text)
84
+ continue;
85
+ const idM = text.match(ID_RE);
86
+ const id = idM && /\d/.test(idM[1]) ? idM[1] : undefined; // require a digit so prose words aren't IDs
87
+ const words = (text.toLowerCase().match(/[a-z][a-z-]{3,}/g) || []).filter((w) => !GENERIC.has(w));
88
+ if (!id && words.length < 2)
89
+ continue; // not substantive enough to track
90
+ items.push({ id, text: text.slice(0, 100) });
91
+ }
92
+ return items;
93
+ }
94
+ function viewpointLedger(viewpointPath, scenarios, featureText) {
95
+ const items = parseViewpointItems(viewpointPath);
96
+ if (!fs.existsSync(viewpointPath) || items.length === 0) {
97
+ return { hasViewpoint: fs.existsSync(viewpointPath), total: 0, covered: 0, ratio: 1, missing: [] };
98
+ }
99
+ const featLower = featureText.toLowerCase();
100
+ const missing = [];
101
+ let covered = 0;
102
+ for (const item of items) {
103
+ let isCovered = false;
104
+ if (item.id && featLower.includes(item.id.toLowerCase()))
105
+ isCovered = true;
106
+ else {
107
+ const words = [...new Set((item.text.toLowerCase().match(/[a-z][a-z-]{3,}/g) || []).filter((w) => !GENERIC.has(w)))];
108
+ const need = Math.min(2, words.length);
109
+ isCovered = words.length > 0 && scenarios.some((s) => words.filter((w) => s.haystack.includes(w)).length >= need);
110
+ }
111
+ if (isCovered)
112
+ covered++;
113
+ else
114
+ missing.push({ id: item.id, text: item.text });
115
+ }
116
+ return { hasViewpoint: true, total: items.length, covered, ratio: items.length ? covered / items.length : 1, missing };
117
+ }
118
+ //# sourceMappingURL=viewpoint-ledger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"viewpoint-ledger.js","sourceRoot":"","sources":["../../src/harness/viewpoint-ledger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * QA baseline audit over a legacy testcase inventory (P-A). Reuses the harness
3
+ * duplicate sensor + the capability-plan reason classifier so the legacy view and
4
+ * the Gherkin view agree. Advisory — evaluates the *existing* manual suite and the
5
+ * automation/driver opportunity; it does not gate anything.
6
+ */
7
+ import { LegacyInventory, LegacyTestcase } from './legacy-parser';
8
+ import { ScenarioInfo } from '../harness/parse';
9
+ export interface BaselineReport {
10
+ total: number;
11
+ sheets: {
12
+ name: string;
13
+ type: string;
14
+ rows: number;
15
+ }[];
16
+ byCategory: Record<string, number>;
17
+ byPriority: Record<string, number>;
18
+ byResult: Record<string, number>;
19
+ depthRatio: number;
20
+ deepCount: number;
21
+ duplicateClusters: number;
22
+ exactDuplicates: number;
23
+ reasons: {
24
+ ui: number;
25
+ crossScreen: number;
26
+ capabilityManual: number;
27
+ keepManual: number;
28
+ byCode: Record<string, number>;
29
+ driverCandidates: {
30
+ driver: string;
31
+ count: number;
32
+ }[];
33
+ };
34
+ }
35
+ /** Synthesize a ScenarioInfo-lite so we can reuse harness sensors on the inventory. */
36
+ export declare function legacyToScenarioInfo(tc: LegacyTestcase): ScenarioInfo;
37
+ export declare function baselineAudit(inv: LegacyInventory): BaselineReport;
38
+ //# sourceMappingURL=baseline-audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"baseline-audit.d.ts","sourceRoot":"","sources":["../../src/ingest/baseline-audit.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAElE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGhD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACvD,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE;QACP,EAAE,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAC9E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/B,gBAAgB,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;KACvD,CAAC;CACH;AAWD,uFAAuF;AACvF,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,cAAc,GAAG,YAAY,CAgBrE;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,eAAe,GAAG,cAAc,CA2ClE"}
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.legacyToScenarioInfo = legacyToScenarioInfo;
4
+ exports.baselineAudit = baselineAudit;
5
+ const sensors_1 = require("../harness/sensors");
6
+ const capability_plan_1 = require("../harness/capability-plan");
7
+ /** An Expected that asserts a concrete value (not just "displayed/visible"). */
8
+ function isDeep(tc) {
9
+ const e = (tc.expected || '').trim().toLowerCase();
10
+ if (!e)
11
+ return false;
12
+ const shallowOnly = /^(.{0,40})(表示される|hiển thị|displayed|shown|is visible|表示)$/.test(e);
13
+ const hasValue = /(=|equals?|bằng|giá trị|\bvalue\b|"|「|\bmessage\b|エラー|error|\bcount\b|số lượng|\bformat\b|định dạng)/.test(e);
14
+ return hasValue || (!shallowOnly && e.length > 30);
15
+ }
16
+ /** Synthesize a ScenarioInfo-lite so we can reuse harness sensors on the inventory. */
17
+ function legacyToScenarioInfo(tc) {
18
+ const skeleton = (tc.steps || '')
19
+ .replace(/\{\{[^}]*\}\}/g, '{}').replace(/"[^"]*"/g, '""')
20
+ .replace(/\d+/g, 'N').replace(/\s+/g, ' ').trim().toLowerCase();
21
+ const hay = `${tc.category} ${tc.steps} ${tc.expected}`.toLowerCase();
22
+ return {
23
+ name: `${tc.category}: ${tc.id}`,
24
+ category: (tc.category || '').toUpperCase().replace(/[^A-Z0-9]+/g, '-').slice(0, 16),
25
+ priority: tc.priority,
26
+ manual: true,
27
+ thenCount: tc.expected ? 1 : 0,
28
+ hasDataAssertion: isDeep(tc),
29
+ shallow: !isDeep(tc),
30
+ stepSkeleton: skeleton,
31
+ haystack: hay,
32
+ };
33
+ }
34
+ function baselineAudit(inv) {
35
+ const tcs = inv.testcases;
36
+ const inc = (m, k) => { m[k] = (m[k] || 0) + 1; };
37
+ const byCategory = {};
38
+ const byPriority = {};
39
+ const byResult = {};
40
+ let deepCount = 0;
41
+ const byCode = {};
42
+ let ui = 0, crossScreen = 0, capabilityManual = 0, keepManual = 0;
43
+ const driverHits = {};
44
+ for (const tc of tcs) {
45
+ inc(byCategory, tc.category || '(uncategorized)');
46
+ inc(byPriority, tc.priority);
47
+ inc(byResult, (tc.result || '(not-run)').trim() || '(not-run)');
48
+ if (isDeep(tc))
49
+ deepCount++;
50
+ const code = (0, capability_plan_1.classifyReason)(`${tc.precondition || ''} ${tc.steps} ${tc.expected} ${tc.testData || ''}`);
51
+ if (!code) {
52
+ ui++;
53
+ continue;
54
+ }
55
+ inc(byCode, code);
56
+ if (code === 'XS') {
57
+ crossScreen++;
58
+ continue;
59
+ }
60
+ const def = capability_plan_1.MANUAL_REASONS[code];
61
+ if (def?.cls === 'keep')
62
+ keepManual++;
63
+ else {
64
+ capabilityManual++;
65
+ for (const d of def?.drivers || [])
66
+ driverHits[d] = (driverHits[d] || 0) + 1;
67
+ }
68
+ }
69
+ const dup = (0, sensors_1.duplicateClusters)(tcs.map(legacyToScenarioInfo));
70
+ return {
71
+ total: tcs.length,
72
+ sheets: inv.sheets,
73
+ byCategory, byPriority, byResult,
74
+ depthRatio: tcs.length ? deepCount / tcs.length : 0,
75
+ deepCount,
76
+ duplicateClusters: dup.clusters.length,
77
+ exactDuplicates: dup.exactDuplicateCount,
78
+ reasons: {
79
+ ui, crossScreen, capabilityManual, keepManual, byCode,
80
+ driverCandidates: Object.entries(driverHits).map(([driver, count]) => ({ driver, count }))
81
+ .sort((a, b) => b.count - a.count),
82
+ },
83
+ };
84
+ }
85
+ //# sourceMappingURL=baseline-audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"baseline-audit.js","sourceRoot":"","sources":["../../src/ingest/baseline-audit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { RawSheet } from './legacy-parser';
2
+ export interface SheetBundle {
3
+ source: string;
4
+ sheets: RawSheet[];
5
+ }
6
+ /** Accept a full Sheets URL or a bare spreadsheet ID. */
7
+ export declare function parseSpreadsheetId(idOrUrl: string): string;
8
+ export declare function fetchGoogleSheet(idOrUrl: string): Promise<SheetBundle>;
9
+ //# sourceMappingURL=gsheet-fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gsheet-fetch.d.ts","sourceRoot":"","sources":["../../src/ingest/gsheet-fetch.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,MAAM,WAAW,WAAW;IAAG,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,QAAQ,EAAE,CAAA;CAAE;AAInE,yDAAyD;AACzD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAG1D;AAiED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA+D5E"}