@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.
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/audit.js +24 -0
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/cli/commands/delivery.d.ts.map +1 -1
- package/dist/cli/commands/delivery.js +30 -14
- package/dist/cli/commands/delivery.js.map +1 -1
- package/dist/cli/commands/eval.d.ts +3 -0
- package/dist/cli/commands/eval.d.ts.map +1 -0
- package/dist/cli/commands/eval.js +37 -0
- package/dist/cli/commands/eval.js.map +1 -0
- package/dist/cli/commands/ingest.d.ts +3 -0
- package/dist/cli/commands/ingest.d.ts.map +1 -0
- package/dist/cli/commands/ingest.js +179 -0
- package/dist/cli/commands/ingest.js.map +1 -0
- package/dist/cli/index.js +4 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/dashboard/templates/index.html +108 -194
- package/dist/generators/test-generator/adapters/adapter-interface.d.ts +1 -0
- package/dist/generators/test-generator/adapters/adapter-interface.d.ts.map +1 -1
- package/dist/generators/test-generator/adapters/playwright/playwright-adapter.d.ts +1 -0
- package/dist/generators/test-generator/adapters/playwright/playwright-adapter.d.ts.map +1 -1
- package/dist/generators/test-generator/adapters/playwright/playwright-adapter.js.map +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/imports.hbs +3 -0
- package/dist/generators/test-generator/code-generator.d.ts +4 -0
- package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
- package/dist/generators/test-generator/code-generator.js +31 -2
- package/dist/generators/test-generator/code-generator.js.map +1 -1
- package/dist/generators/test-generator/patterns/database-patterns.d.ts +5 -0
- package/dist/generators/test-generator/patterns/database-patterns.d.ts.map +1 -0
- package/dist/generators/test-generator/patterns/database-patterns.js +94 -0
- package/dist/generators/test-generator/patterns/database-patterns.js.map +1 -0
- package/dist/generators/test-generator/patterns/index.d.ts +1 -0
- package/dist/generators/test-generator/patterns/index.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/index.js +6 -1
- package/dist/generators/test-generator/patterns/index.js.map +1 -1
- package/dist/generators/test-generator/template-engine.d.ts +1 -0
- package/dist/generators/test-generator/template-engine.d.ts.map +1 -1
- package/dist/generators/test-generator/template-engine.js +1 -1
- package/dist/generators/test-generator/template-engine.js.map +1 -1
- package/dist/harness/audit.d.ts +16 -0
- package/dist/harness/audit.d.ts.map +1 -1
- package/dist/harness/audit.js +69 -5
- package/dist/harness/audit.js.map +1 -1
- package/dist/harness/capability-plan.d.ts +6 -0
- package/dist/harness/capability-plan.d.ts.map +1 -1
- package/dist/harness/capability-plan.js +14 -1
- package/dist/harness/capability-plan.js.map +1 -1
- package/dist/harness/catalog/drivers.yaml +1 -1
- package/dist/harness/catalog/universal-viewpoints.yaml +1 -1
- package/dist/harness/eval/skill-lint.d.ts +16 -0
- package/dist/harness/eval/skill-lint.d.ts.map +1 -0
- package/dist/harness/eval/skill-lint.js +129 -0
- package/dist/harness/eval/skill-lint.js.map +1 -0
- package/dist/harness/flow-plan.js +1 -1
- package/dist/harness/parse.d.ts +6 -0
- package/dist/harness/parse.d.ts.map +1 -1
- package/dist/harness/parse.js +18 -3
- package/dist/harness/parse.js.map +1 -1
- package/dist/harness/quality-gates.d.ts +29 -0
- package/dist/harness/quality-gates.d.ts.map +1 -0
- package/dist/harness/quality-gates.js +183 -0
- package/dist/harness/quality-gates.js.map +1 -0
- package/dist/harness/script-check.d.ts.map +1 -1
- package/dist/harness/script-check.js +4 -1
- package/dist/harness/script-check.js.map +1 -1
- package/dist/harness/sensors.d.ts.map +1 -1
- package/dist/harness/sensors.js +85 -6
- package/dist/harness/sensors.js.map +1 -1
- package/dist/harness/spec-coverage.d.ts +37 -0
- package/dist/harness/spec-coverage.d.ts.map +1 -0
- package/dist/harness/spec-coverage.js +159 -0
- package/dist/harness/spec-coverage.js.map +1 -0
- package/dist/harness/viewpoint-ledger.d.ts +23 -0
- package/dist/harness/viewpoint-ledger.d.ts.map +1 -0
- package/dist/harness/viewpoint-ledger.js +118 -0
- package/dist/harness/viewpoint-ledger.js.map +1 -0
- package/dist/ingest/baseline-audit.d.ts +38 -0
- package/dist/ingest/baseline-audit.d.ts.map +1 -0
- package/dist/ingest/baseline-audit.js +85 -0
- package/dist/ingest/baseline-audit.js.map +1 -0
- package/dist/ingest/gsheet-fetch.d.ts +9 -0
- package/dist/ingest/gsheet-fetch.d.ts.map +1 -0
- package/dist/ingest/gsheet-fetch.js +180 -0
- package/dist/ingest/gsheet-fetch.js.map +1 -0
- package/dist/ingest/index.d.ts +6 -0
- package/dist/ingest/index.d.ts.map +1 -0
- package/dist/ingest/index.js +22 -0
- package/dist/ingest/index.js.map +1 -0
- package/dist/ingest/legacy-parser.d.ts +39 -0
- package/dist/ingest/legacy-parser.d.ts.map +1 -0
- package/dist/ingest/legacy-parser.js +218 -0
- package/dist/ingest/legacy-parser.js.map +1 -0
- package/dist/ingest/reconcile.d.ts +30 -0
- package/dist/ingest/reconcile.d.ts.map +1 -0
- package/dist/ingest/reconcile.js +65 -0
- package/dist/ingest/reconcile.js.map +1 -0
- package/dist/ingest/to-gherkin.d.ts +33 -0
- package/dist/ingest/to-gherkin.d.ts.map +1 -0
- package/dist/ingest/to-gherkin.js +93 -0
- package/dist/ingest/to-gherkin.js.map +1 -0
- package/dist/orchestrator/ai-rules-updater.d.ts.map +1 -1
- package/dist/orchestrator/ai-rules-updater.js +2 -0
- package/dist/orchestrator/ai-rules-updater.js.map +1 -1
- package/dist/orchestrator/templates/ai-instructions/claude-agent-reviewer.md +1 -0
- package/dist/orchestrator/templates/ai-instructions/claude-skill-delivery.md +10 -0
- package/dist/orchestrator/templates/ai-instructions/claude-skill-harness-audit.md +1 -1
- package/dist/orchestrator/templates/ai-instructions/claude-skill-ingest-legacy.md +79 -0
- package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +25 -1
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-delivery.md +10 -0
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-harness-audit.md +1 -1
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-ingest-legacy.md +79 -0
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +44 -7
- package/dist/orchestrator/templates/specs-db.d.ts +18 -0
- package/dist/orchestrator/templates/specs-db.d.ts.map +1 -0
- package/dist/orchestrator/templates/specs-db.js +171 -0
- package/dist/orchestrator/templates/specs-db.js.map +1 -0
- package/dist/orchestrator/templates/specs-db.ts +147 -0
- package/docs/orchestration-spec.md +3 -3
- package/package.json +4 -4
- package/src/cli/commands/audit.ts +19 -0
- package/src/cli/commands/delivery.ts +31 -15
- package/src/cli/commands/eval.ts +28 -0
- package/src/cli/commands/ingest.ts +141 -0
- package/src/cli/index.ts +4 -0
- package/src/dashboard/templates/index.html +108 -194
- package/src/generators/test-generator/adapters/adapter-interface.ts +1 -1
- package/src/generators/test-generator/adapters/playwright/playwright-adapter.ts +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/imports.hbs +3 -0
- package/src/generators/test-generator/code-generator.ts +29 -2
- package/src/generators/test-generator/patterns/database-patterns.ts +95 -0
- package/src/generators/test-generator/patterns/index.ts +3 -0
- package/src/generators/test-generator/template-engine.ts +2 -2
- package/src/harness/audit.ts +82 -5
- package/src/harness/capability-plan.ts +12 -1
- package/src/harness/catalog/drivers.yaml +1 -1
- package/src/harness/catalog/universal-viewpoints.yaml +1 -1
- package/src/harness/eval/skill-lint.ts +87 -0
- package/src/harness/flow-plan.ts +1 -1
- package/src/harness/parse.ts +19 -3
- package/src/harness/quality-gates.ts +152 -0
- package/src/harness/script-check.ts +4 -1
- package/src/harness/sensors.ts +84 -7
- package/src/harness/spec-coverage.ts +139 -0
- package/src/harness/viewpoint-ledger.ts +80 -0
- package/src/ingest/baseline-audit.ts +100 -0
- package/src/ingest/gsheet-fetch.ts +152 -0
- package/src/ingest/index.ts +5 -0
- package/src/ingest/legacy-parser.ts +184 -0
- package/src/ingest/reconcile.ts +80 -0
- package/src/ingest/to-gherkin.ts +108 -0
- package/src/orchestrator/ai-rules-updater.ts +2 -0
- package/src/orchestrator/templates/ai-instructions/claude-agent-reviewer.md +1 -0
- package/src/orchestrator/templates/ai-instructions/claude-skill-delivery.md +10 -0
- package/src/orchestrator/templates/ai-instructions/claude-skill-harness-audit.md +1 -1
- package/src/orchestrator/templates/ai-instructions/claude-skill-ingest-legacy.md +79 -0
- package/src/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +25 -1
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-delivery.md +10 -0
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-harness-audit.md +1 -1
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-ingest-legacy.md +79 -0
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +44 -7
- package/src/orchestrator/templates/specs-db.ts +147 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
import { parseLegacyFile, listSheets, baselineAudit, BaselineReport, LegacyInventory, inventoryToGherkin, reconcileViewpoints, renderViewpointOverview, fetchGoogleSheet } from '../../ingest';
|
|
5
|
+
|
|
6
|
+
function renderInventoryMd(inv: LegacyInventory, r: BaselineReport): string {
|
|
7
|
+
const lines: string[] = [];
|
|
8
|
+
lines.push(`# Legacy Testcase Inventory — ${inv.source.file}`, '');
|
|
9
|
+
lines.push(`Total testcases: **${r.total}**`, '');
|
|
10
|
+
lines.push('## Sheets', '', '| Sheet | Type | Rows |', '|---|---|---|');
|
|
11
|
+
for (const s of r.sheets) lines.push(`| ${s.name} | ${s.type} | ${s.rows} |`);
|
|
12
|
+
lines.push('', '## By category', '');
|
|
13
|
+
for (const [k, v] of Object.entries(r.byCategory).sort((a, b) => b[1] - a[1])) lines.push(`- ${k}: ${v}`);
|
|
14
|
+
lines.push('', `Depth: **${(r.depthRatio * 100).toFixed(0)}%** (${r.deepCount}/${r.total} assert a concrete expected value)`, '');
|
|
15
|
+
return lines.join('\n');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function render(inv: LegacyInventory, r: BaselineReport): void {
|
|
19
|
+
const L = console.log;
|
|
20
|
+
const pct = (x: number) => (r.total ? Math.round((x / r.total) * 100) : 0);
|
|
21
|
+
L('');
|
|
22
|
+
L(`━━━ Legacy Ingest — ${inv.source.file} ━━━`);
|
|
23
|
+
L('');
|
|
24
|
+
L(` Sheets:`);
|
|
25
|
+
for (const s of r.sheets) L(` • ${s.name} — ${s.type} (${s.rows})`);
|
|
26
|
+
L('');
|
|
27
|
+
L(` TOTAL testcases: ${r.total}`);
|
|
28
|
+
L('');
|
|
29
|
+
L(' ── QA baseline ──');
|
|
30
|
+
L(` By category: ${Object.entries(r.byCategory).sort((a, b) => b[1] - a[1]).slice(0, 12).map(([k, v]) => `${k}=${v}`).join(' ')}`);
|
|
31
|
+
L(` By priority: ${Object.entries(r.byPriority).map(([k, v]) => `${k}=${v}`).join(' ')}`);
|
|
32
|
+
L(` By result: ${Object.entries(r.byResult).map(([k, v]) => `${k}=${v}`).join(' ')}`);
|
|
33
|
+
L(` Depth: ${r.deepCount}/${r.total} (${(r.depthRatio * 100).toFixed(0)}%) assert a concrete expected value → convert to DEEP Gherkin`);
|
|
34
|
+
L(` Duplicates: ${r.duplicateClusters} same-shape cluster(s), ${r.exactDuplicates} likely exact`);
|
|
35
|
+
L('');
|
|
36
|
+
L(' ── Capability Plan (which driver, if any) ──');
|
|
37
|
+
L(` UI automatable : ${r.reasons.ui} (${pct(r.reasons.ui)}%)`);
|
|
38
|
+
L(` cross-screen → flow : ${r.reasons.crossScreen} (${pct(r.reasons.crossScreen)}%)`);
|
|
39
|
+
L(` capability-manual : ${r.reasons.capabilityManual} (${pct(r.reasons.capabilityManual)}%)`);
|
|
40
|
+
L(` keep-manual : ${r.reasons.keepManual} (${pct(r.reasons.keepManual)}%)`);
|
|
41
|
+
if (r.reasons.driverCandidates.length)
|
|
42
|
+
L(` driver candidates : ${r.reasons.driverCandidates.map((d) => `${d.driver}×${d.count}`).join(' ')}`);
|
|
43
|
+
else
|
|
44
|
+
L(` driver candidates : none (no capability-manual at scale → no driver justified)`);
|
|
45
|
+
L('');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function registerIngestCommand(program: Command): void {
|
|
49
|
+
program
|
|
50
|
+
.command('ingest')
|
|
51
|
+
.description('Ingest a legacy manual testcase workbook (CSV/XLSX/JSON-bundle) → normalized inventory + QA baseline audit')
|
|
52
|
+
.option('--legacy <file...>', 'Path(s) to the legacy testcase file(s): .csv, .xlsx, or a .json sheet-bundle')
|
|
53
|
+
.option('--gsheet <urlOrId>', 'Fetch a Google Sheet (all tabs) under YOUR Google identity (ADC, read-only) → bundle. Needs: npm i googleapis + gcloud auth application-default login')
|
|
54
|
+
.option('-s, --screen <name>', 'Screen name (output goes under qa/screens/<name>/requirements/legacy/)')
|
|
55
|
+
.option('--out <dir>', 'Output directory (overrides the default screen path)')
|
|
56
|
+
.option('--sheets <names>', 'Comma-separated tab names to ingest (default: all). Workbooks carry many tabs.')
|
|
57
|
+
.option('--list-sheets', 'List the tabs + detected type (testcase/viewpoint-matrix/ui-checklist) and exit')
|
|
58
|
+
.option('--emit-gherkin', 'Also emit a traceable Gherkin DRAFT (.legacy-draft.feature) + trace map (P-B)')
|
|
59
|
+
.option('--json', 'Print the raw inventory + baseline JSON')
|
|
60
|
+
.action(async (options) => {
|
|
61
|
+
try {
|
|
62
|
+
if (!options.legacy && !options.gsheet) throw new Error('Provide --legacy <file...> or --gsheet <url|id>');
|
|
63
|
+
|
|
64
|
+
const outDir = options.out
|
|
65
|
+
? path.resolve(process.cwd(), options.out)
|
|
66
|
+
: options.screen
|
|
67
|
+
? path.join(process.cwd(), 'qa', 'screens', options.screen, 'requirements', 'legacy')
|
|
68
|
+
: path.join(process.cwd(), '.sungen', 'legacy');
|
|
69
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
70
|
+
|
|
71
|
+
let files: string[];
|
|
72
|
+
if (options.gsheet) {
|
|
73
|
+
// Fetch as the user (not AI) — bypasses the AI-context DLP legitimately.
|
|
74
|
+
const bundle = await fetchGoogleSheet(String(options.gsheet));
|
|
75
|
+
const bundlePath = path.join(outDir, 'bundle.json');
|
|
76
|
+
fs.writeFileSync(bundlePath, JSON.stringify(bundle, null, 0));
|
|
77
|
+
console.log(` Fetched Google Sheet "${bundle.source}" → ${bundle.sheets.length} tab(s) → ${path.relative(process.cwd(), bundlePath)}`);
|
|
78
|
+
files = [bundlePath];
|
|
79
|
+
} else {
|
|
80
|
+
files = (Array.isArray(options.legacy) ? options.legacy : [options.legacy])
|
|
81
|
+
.map((f: string) => path.resolve(process.cwd(), f));
|
|
82
|
+
for (const f of files) if (!fs.existsSync(f)) throw new Error(`File not found: ${f}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (options.listSheets) {
|
|
86
|
+
const sheets = await listSheets(files);
|
|
87
|
+
console.log('');
|
|
88
|
+
console.log(' Tabs found:');
|
|
89
|
+
for (const s of sheets) console.log(` • ${s.name} — ${s.type} (${s.rows} rows)`);
|
|
90
|
+
console.log('');
|
|
91
|
+
console.log(` Ingest the testcase tab(s) with: --sheets "${sheets.filter((s) => s.type === 'testcase').map((s) => s.name).join(',')}"`);
|
|
92
|
+
console.log('');
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const onlySheets: string[] | undefined = options.sheets ? String(options.sheets).split(',') : undefined;
|
|
97
|
+
const inv = await parseLegacyFile(files, onlySheets);
|
|
98
|
+
const report = baselineAudit(inv);
|
|
99
|
+
fs.writeFileSync(path.join(outDir, 'inventory.json'), JSON.stringify({ inventory: inv, baseline: report }, null, 2));
|
|
100
|
+
fs.writeFileSync(path.join(outDir, 'inventory.md'), renderInventoryMd(inv, report));
|
|
101
|
+
|
|
102
|
+
let convert;
|
|
103
|
+
let recon;
|
|
104
|
+
if (options.emitGherkin) {
|
|
105
|
+
const featureName = options.screen || (files.length === 1 ? path.basename(files[0]).replace(/\.[^.]+$/, '') : 'legacy');
|
|
106
|
+
convert = inventoryToGherkin(inv, featureName);
|
|
107
|
+
fs.writeFileSync(path.join(outDir, `${featureName}.legacy-draft.feature`), convert.feature);
|
|
108
|
+
fs.writeFileSync(path.join(outDir, 'legacy-trace.json'), JSON.stringify(convert.trace, null, 2));
|
|
109
|
+
// Viewpoint reconciliation: legacy coverage vs catalog → blind-spots (P-C)
|
|
110
|
+
recon = reconcileViewpoints(inv);
|
|
111
|
+
fs.writeFileSync(path.join(outDir, 'test-viewpoint.draft.md'), renderViewpointOverview(featureName, recon));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (options.json) console.log(JSON.stringify({ inventory: inv, baseline: report, convert, reconciliation: recon }, null, 2));
|
|
115
|
+
else {
|
|
116
|
+
render(inv, report);
|
|
117
|
+
if (convert) {
|
|
118
|
+
const g = convert.gap;
|
|
119
|
+
console.log(' ── Gherkin draft (P-B) ──');
|
|
120
|
+
console.log(` ${g.total} scenario(s) drafted → ui=${g.ui} · cross-screen=${g.crossScreen} · @manual(capability)=${g.manualCapability} · @manual(keep)=${g.manualKeep}`);
|
|
121
|
+
if (g.noExpected) console.log(` ⚠ ${g.noExpected} testcase(s) without an Expected → needs review`);
|
|
122
|
+
console.log(` Draft: ${path.relative(process.cwd(), outDir)}/*.legacy-draft.feature (refine via /sungen:create-test)`);
|
|
123
|
+
}
|
|
124
|
+
if (recon) {
|
|
125
|
+
console.log(' ── Viewpoint reconciliation (legacy vs catalog) ──');
|
|
126
|
+
console.log(` page-type: ${recon.pageType ?? 'unknown'} · legacy covers ${recon.themesCovered}/${recon.themesTotal} catalog themes (${(recon.coverageRatio * 100).toFixed(0)}%)`);
|
|
127
|
+
if (recon.blindSpots.length)
|
|
128
|
+
console.log(` ⚠ BLIND-SPOTS (catalog expects, legacy lacks): ${recon.blindSpots.map((b) => `${b.theme}[${b.status}]`).join(', ')}`);
|
|
129
|
+
else
|
|
130
|
+
console.log(` ✓ no catalog blind-spots — legacy covers the expected themes`);
|
|
131
|
+
console.log(` Draft viewpoint: ${path.relative(process.cwd(), outDir)}/test-viewpoint.draft.md → seed /sungen:create-test`);
|
|
132
|
+
}
|
|
133
|
+
console.log(` Inventory: ${path.relative(process.cwd(), outDir)}/inventory.json`);
|
|
134
|
+
console.log('');
|
|
135
|
+
}
|
|
136
|
+
} catch (error) {
|
|
137
|
+
console.error('Error:', error instanceof Error ? error.message : error);
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
package/src/cli/index.ts
CHANGED
|
@@ -15,6 +15,8 @@ import { registerFigmaCommand } from './commands/figma';
|
|
|
15
15
|
import { registerAddFlowCommand } from './commands/add-flow';
|
|
16
16
|
import { registerDashboardCommand } from './commands/dashboard';
|
|
17
17
|
import { registerAuditCommand } from './commands/audit';
|
|
18
|
+
import { registerIngestCommand } from './commands/ingest';
|
|
19
|
+
import { registerEvalCommand } from './commands/eval';
|
|
18
20
|
import { registerManifestCommand } from './commands/manifest';
|
|
19
21
|
import { registerLedgerCommand } from './commands/ledger';
|
|
20
22
|
import { registerFeedbackCommand } from './commands/feedback';
|
|
@@ -60,6 +62,8 @@ async function main() {
|
|
|
60
62
|
registerBlindspotCommand(program);
|
|
61
63
|
registerCapabilityCommand(program);
|
|
62
64
|
registerFlowCheckCommand(program);
|
|
65
|
+
registerIngestCommand(program);
|
|
66
|
+
registerEvalCommand(program);
|
|
63
67
|
|
|
64
68
|
await program.parseAsync(process.argv);
|
|
65
69
|
}
|