@nebulacomponents/citable 1.16.0 → 1.18.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/CHANGELOG.md +47 -0
- package/README.md +16 -3
- package/dist/universal/.agents/skills/citable/SKILL.md +66 -1
- package/dist/universal/.agents/skills/citable/VERSION +1 -1
- package/dist/universal/.agents/skills/citable/manifest.json +9 -6
- package/dist/universal/.agents/skills/citable/schemas/cli-output-envelope.schema.json +30 -0
- package/dist/universal/.agents/skills/citable/schemas/finding.schema.json +69 -0
- package/dist/universal/.agents/skills/citable/schemas/remediation-verification.schema.json +98 -0
- package/dist/universal/.agents/skills/citable/schemas/sow.schema.json +92 -0
- package/dist/universal/.claude/agents/citable/manifest.json +2 -2
- package/dist/universal/.claude/skills/citable/SKILL.md +66 -1
- package/dist/universal/.claude/skills/citable/VERSION +1 -1
- package/dist/universal/.claude/skills/citable/manifest.json +9 -6
- package/dist/universal/.claude/skills/citable/schemas/cli-output-envelope.schema.json +30 -0
- package/dist/universal/.claude/skills/citable/schemas/finding.schema.json +69 -0
- package/dist/universal/.claude/skills/citable/schemas/remediation-verification.schema.json +98 -0
- package/dist/universal/.claude/skills/citable/schemas/sow.schema.json +92 -0
- package/dist/universal/.cursor/skills/citable/SKILL.md +66 -1
- package/dist/universal/.cursor/skills/citable/VERSION +1 -1
- package/dist/universal/.cursor/skills/citable/manifest.json +9 -6
- package/dist/universal/.cursor/skills/citable/schemas/cli-output-envelope.schema.json +30 -0
- package/dist/universal/.cursor/skills/citable/schemas/finding.schema.json +69 -0
- package/dist/universal/.cursor/skills/citable/schemas/remediation-verification.schema.json +98 -0
- package/dist/universal/.cursor/skills/citable/schemas/sow.schema.json +92 -0
- package/dist/universal/.gemini/skills/citable/SKILL.md +66 -1
- package/dist/universal/.gemini/skills/citable/VERSION +1 -1
- package/dist/universal/.gemini/skills/citable/manifest.json +9 -6
- package/dist/universal/.gemini/skills/citable/schemas/cli-output-envelope.schema.json +30 -0
- package/dist/universal/.gemini/skills/citable/schemas/finding.schema.json +69 -0
- package/dist/universal/.gemini/skills/citable/schemas/remediation-verification.schema.json +98 -0
- package/dist/universal/.gemini/skills/citable/schemas/sow.schema.json +92 -0
- package/dist/universal/.github/skills/citable/SKILL.md +66 -1
- package/dist/universal/.github/skills/citable/VERSION +1 -1
- package/dist/universal/.github/skills/citable/manifest.json +9 -6
- package/dist/universal/.github/skills/citable/schemas/cli-output-envelope.schema.json +30 -0
- package/dist/universal/.github/skills/citable/schemas/finding.schema.json +69 -0
- package/dist/universal/.github/skills/citable/schemas/remediation-verification.schema.json +98 -0
- package/dist/universal/.github/skills/citable/schemas/sow.schema.json +92 -0
- package/dist/universal/.kiro/skills/citable/SKILL.md +66 -1
- package/dist/universal/.kiro/skills/citable/VERSION +1 -1
- package/dist/universal/.kiro/skills/citable/manifest.json +9 -6
- package/dist/universal/.kiro/skills/citable/schemas/cli-output-envelope.schema.json +30 -0
- package/dist/universal/.kiro/skills/citable/schemas/finding.schema.json +69 -0
- package/dist/universal/.kiro/skills/citable/schemas/remediation-verification.schema.json +98 -0
- package/dist/universal/.kiro/skills/citable/schemas/sow.schema.json +92 -0
- package/dist/universal/.opencode/skills/citable/SKILL.md +66 -1
- package/dist/universal/.opencode/skills/citable/VERSION +1 -1
- package/dist/universal/.opencode/skills/citable/manifest.json +9 -6
- package/dist/universal/.opencode/skills/citable/schemas/cli-output-envelope.schema.json +30 -0
- package/dist/universal/.opencode/skills/citable/schemas/finding.schema.json +69 -0
- package/dist/universal/.opencode/skills/citable/schemas/remediation-verification.schema.json +98 -0
- package/dist/universal/.opencode/skills/citable/schemas/sow.schema.json +92 -0
- package/dist/universal/.pi/agent/skills/citable/SKILL.md +66 -1
- package/dist/universal/.pi/agent/skills/citable/VERSION +1 -1
- package/dist/universal/.pi/agent/skills/citable/manifest.json +9 -6
- package/dist/universal/.pi/agent/skills/citable/schemas/cli-output-envelope.schema.json +30 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/finding.schema.json +69 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/remediation-verification.schema.json +98 -0
- package/dist/universal/.pi/agent/skills/citable/schemas/sow.schema.json +92 -0
- package/dist/universal/.qoder/skills/citable/SKILL.md +66 -1
- package/dist/universal/.qoder/skills/citable/VERSION +1 -1
- package/dist/universal/.qoder/skills/citable/manifest.json +9 -6
- package/dist/universal/.qoder/skills/citable/schemas/cli-output-envelope.schema.json +30 -0
- package/dist/universal/.qoder/skills/citable/schemas/finding.schema.json +69 -0
- package/dist/universal/.qoder/skills/citable/schemas/remediation-verification.schema.json +98 -0
- package/dist/universal/.qoder/skills/citable/schemas/sow.schema.json +92 -0
- package/dist/universal/.rovodev/skills/citable/SKILL.md +66 -1
- package/dist/universal/.rovodev/skills/citable/VERSION +1 -1
- package/dist/universal/.rovodev/skills/citable/manifest.json +9 -6
- package/dist/universal/.rovodev/skills/citable/schemas/cli-output-envelope.schema.json +30 -0
- package/dist/universal/.rovodev/skills/citable/schemas/finding.schema.json +69 -0
- package/dist/universal/.rovodev/skills/citable/schemas/remediation-verification.schema.json +98 -0
- package/dist/universal/.rovodev/skills/citable/schemas/sow.schema.json +92 -0
- package/dist/universal/.trae/skills/citable/SKILL.md +66 -1
- package/dist/universal/.trae/skills/citable/VERSION +1 -1
- package/dist/universal/.trae/skills/citable/manifest.json +9 -6
- package/dist/universal/.trae/skills/citable/schemas/cli-output-envelope.schema.json +30 -0
- package/dist/universal/.trae/skills/citable/schemas/finding.schema.json +69 -0
- package/dist/universal/.trae/skills/citable/schemas/remediation-verification.schema.json +98 -0
- package/dist/universal/.trae/skills/citable/schemas/sow.schema.json +92 -0
- package/dist/universal/.trae-cn/skills/citable/SKILL.md +66 -1
- package/dist/universal/.trae-cn/skills/citable/VERSION +1 -1
- package/dist/universal/.trae-cn/skills/citable/manifest.json +9 -6
- package/dist/universal/.trae-cn/skills/citable/schemas/cli-output-envelope.schema.json +30 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/finding.schema.json +69 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/remediation-verification.schema.json +98 -0
- package/dist/universal/.trae-cn/skills/citable/schemas/sow.schema.json +92 -0
- package/dist/universal/manifest.json +112 -76
- package/package.json +1 -1
- package/schemas/cli-output-envelope.schema.json +30 -0
- package/schemas/finding.schema.json +69 -0
- package/schemas/remediation-verification.schema.json +98 -0
- package/schemas/sow.schema.json +92 -0
- package/skill/SKILL.md +66 -1
- package/src/analysis/behavioral.js +126 -0
- package/src/analysis/croAudit.js +302 -0
- package/src/analysis/croRoadmap.js +121 -0
- package/src/analysis/eeat.js +300 -0
- package/src/analysis/funnelAnalysis.js +171 -0
- package/src/analysis/iceMatrix.js +205 -0
- package/src/analysis/offpage.js +228 -0
- package/src/analysis/readiness.js +253 -0
- package/src/analysis/saliency.js +119 -0
- package/src/analysis/schemaRecommendations.js +173 -0
- package/src/analysis/strategicRoadmap.js +148 -0
- package/src/cli/index.js +418 -9
- package/src/commands/answerEngineReadiness.js +48 -0
- package/src/commands/audit.js +2 -2
- package/src/commands/auditBacklinks.js +79 -0
- package/src/commands/ciWorkflow.js +63 -0
- package/src/commands/compatibility.js +205 -0
- package/src/commands/context.js +2 -1
- package/src/commands/croBacklog.js +182 -0
- package/src/commands/croSuite.js +156 -0
- package/src/commands/edgeRules.js +80 -4
- package/src/commands/edgeSecurity.js +192 -0
- package/src/commands/executive.js +6 -0
- package/src/commands/executiveCro.js +30 -0
- package/src/commands/executiveSearch.js +28 -0
- package/src/commands/experimentGuardrails.js +213 -0
- package/src/commands/goldenCorpus.js +155 -0
- package/src/commands/implementationKit.js +202 -0
- package/src/commands/inspectCro.js +67 -0
- package/src/commands/inspectEeat.js +53 -0
- package/src/commands/planExperiment.js +52 -0
- package/src/commands/previewCro.js +241 -0
- package/src/commands/prioritize.js +42 -6
- package/src/commands/remediate.js +461 -0
- package/src/commands/roadmapCmd.js +69 -0
- package/src/commands/schemaCmd.js +10 -2
- package/src/commands/sowCmd.js +67 -0
- package/src/commands/sweep.js +357 -0
- package/src/commands/verifyRemediation.js +204 -0
- package/src/commands/visualRegression.js +165 -0
- package/src/components/index.js +556 -0
- package/src/detectors/cro.js +48 -0
- package/src/detectors/framework.js +31 -1
- package/src/reporting/executiveCroReport.js +731 -0
- package/src/reporting/executiveExport.js +175 -1
- package/src/reporting/executiveSearchReport.js +704 -0
- package/src/sow/admissibilityGate.js +194 -0
- package/src/sow/generateSow.js +762 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { execFileSync } from 'node:child_process';
|
|
4
|
+
import { nowIso } from '../shared/io.js';
|
|
5
|
+
|
|
6
|
+
const PKG_VERSION = JSON.parse(
|
|
7
|
+
fs.readFileSync(new URL('../../package.json', import.meta.url), 'utf8')
|
|
8
|
+
).version;
|
|
9
|
+
|
|
10
|
+
export const VIEWPORT_CLASSES = [
|
|
11
|
+
{ id: 'mobile', width: 375, height: 667 },
|
|
12
|
+
{ id: 'tablet', width: 768, height: 1024 },
|
|
13
|
+
{ id: 'desktop', width: 1280, height: 800 },
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
export const VARIANT_CLASSES = [
|
|
17
|
+
{ id: 'default' },
|
|
18
|
+
{ id: 'keyboard-focus', note: 'tab to first interactive element; visible focus indicator required' },
|
|
19
|
+
{ id: 'reduced-motion', note: 'emulate prefers-reduced-motion: reduce; no animation may run' },
|
|
20
|
+
{ id: 'text-zoom-200', note: 'browser text zoom 200%; layout must wrap, not clip' },
|
|
21
|
+
{ id: 'long-translation', note: 'substitute longest German strings; layout must wrap, not overflow' },
|
|
22
|
+
{ id: 'narrow-mobile', viewport: 'mobile', width: 320, note: '320px width; split view must collapse to one column' },
|
|
23
|
+
{ id: 'dark', note: 'emulate prefers-color-scheme: dark' },
|
|
24
|
+
{ id: 'light', note: 'emulate prefers-color-scheme: light' },
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Deterministic layout-contract checks over the preview HTML (or any exported
|
|
29
|
+
* preview artifact). These always run — no browser required — and lock in the
|
|
30
|
+
* properties the screenshot matrix would otherwise only observe.
|
|
31
|
+
*/
|
|
32
|
+
export function visualContractChecks(html) {
|
|
33
|
+
const checks = [];
|
|
34
|
+
const push = (check_id, passed, detail) => checks.push({ check_id, passed, detail });
|
|
35
|
+
|
|
36
|
+
push('viewport-meta', /<meta[^>]*name="viewport"[^>]*>/i.test(html), 'mobile viewport meta present');
|
|
37
|
+
push(
|
|
38
|
+
'three-viewport-classes',
|
|
39
|
+
/375px/.test(html) && /768px/.test(html) && /Desktop/i.test(html),
|
|
40
|
+
'Mobile (375px), Tablet (768px), and Desktop toggles declared'
|
|
41
|
+
);
|
|
42
|
+
push('keyboard-focus-visible', /:focus-visible/i.test(html), 'visible :focus-visible outline defined for interactive elements');
|
|
43
|
+
push('reduced-motion', /prefers-reduced-motion\s*:\s*reduce/i.test(html), 'prefers-reduced-motion: reduce disables transitions and animations');
|
|
44
|
+
push('narrow-mobile-collapse', /max-width:\s*480px[^}]*\{[^}]*grid-template-columns:\s*1fr/i.test(html) || /max-width:\s*480px[\s\S]{0,200}1fr/.test(html), 'split view collapses to one column at narrow mobile widths');
|
|
45
|
+
push('text-zoom-wrap', /overflow-wrap\s*:\s*break-word/.test(html), 'long words wrap instead of clipping (text zoom / translations)');
|
|
46
|
+
push('touch-targets', /min-height:\s*48px/.test(html), 'remediated side declares >= 48px touch targets');
|
|
47
|
+
push('dark-light-preference', /prefers-color-scheme/i.test(html), 'preview chrome adapts to prefers-color-scheme');
|
|
48
|
+
push('viewport-buttons-labelled', /aria-pressed/.test(html), 'viewport toggle state exposed via aria-pressed');
|
|
49
|
+
push('font-size-legible', !/font-size:\s*(?:[0-9]|1[01])px\s*;?\s*[^}]*background:\s*#16a34a/.test(html) && /font-size:\s*16px/.test(html), 'remediated CTAs use 16px baseline');
|
|
50
|
+
|
|
51
|
+
return { ok: checks.every((c) => c.passed), checks };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function playwrightImportable() {
|
|
55
|
+
try {
|
|
56
|
+
execFileSync(process.execPath, ['--input-type=module', '-e', "await import('playwright')"], {
|
|
57
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
58
|
+
timeout: 20000,
|
|
59
|
+
env: { ...process.env, NODE_OPTIONS: '' },
|
|
60
|
+
});
|
|
61
|
+
return true;
|
|
62
|
+
} catch {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Visual regression runner over the preview artifact.
|
|
69
|
+
*
|
|
70
|
+
* The deterministic contract checks always run. Screenshots run only when
|
|
71
|
+
* playwright is importable AND a browser launches; otherwise the run is
|
|
72
|
+
* recorded as `skipped` with the exact required input — never silently
|
|
73
|
+
* skipped. Screenshots are recorded (hash + bytes); cross-platform pixel
|
|
74
|
+
* comparison is intentionally NOT claimed because rendering is not
|
|
75
|
+
* byte-deterministic across machines.
|
|
76
|
+
*/
|
|
77
|
+
export async function runVisualRegression(root, { previewHtml = null, output = null } = {}) {
|
|
78
|
+
let html = previewHtml;
|
|
79
|
+
if (!html) {
|
|
80
|
+
const { generateCroPreviewHtml } = await import('./previewCro.js');
|
|
81
|
+
html = generateCroPreviewHtml({});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const contract = visualContractChecks(html);
|
|
85
|
+
const cells = [];
|
|
86
|
+
for (const vp of VIEWPORT_CLASSES) {
|
|
87
|
+
for (const variant of VARIANT_CLASSES) {
|
|
88
|
+
if (variant.viewport && variant.viewport !== vp.id) continue;
|
|
89
|
+
cells.push({ viewport: vp.id, width: vp.width, height: vp.height, variant: variant.id, note: variant.note || null });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const result = {
|
|
94
|
+
timestamp: nowIso(),
|
|
95
|
+
tool_version: PKG_VERSION,
|
|
96
|
+
contract,
|
|
97
|
+
matrix_cells: cells,
|
|
98
|
+
screenshots: { status: 'skipped', captured: [], required_input: null },
|
|
99
|
+
limitations: [
|
|
100
|
+
'Layout-contract checks are deterministic string checks; they do not observe actual rendering.',
|
|
101
|
+
'Screenshots are recorded per cell with hashes; no cross-machine pixel comparison is claimed.',
|
|
102
|
+
'A skipped screenshot run is an explicit, recorded state — it never implies the matrix passed.',
|
|
103
|
+
],
|
|
104
|
+
output_dir: null,
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
if (!playwrightImportable()) {
|
|
108
|
+
result.screenshots.required_input = 'optional peer dependency playwright >= 1.50 with a Chromium install';
|
|
109
|
+
if (output) writeReport(root, output, result);
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const outDir = output ? path.resolve(root, output) : path.join(root, '.citable', 'visual', nowIso().replace(/\D/g, '').slice(0, 14));
|
|
114
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
115
|
+
try {
|
|
116
|
+
const pw = await import('playwright');
|
|
117
|
+
const browser = await pw.chromium.launch({ headless: true });
|
|
118
|
+
try {
|
|
119
|
+
const tmp = path.join(outDir, 'preview.html');
|
|
120
|
+
fs.writeFileSync(tmp, html, 'utf8');
|
|
121
|
+
for (const cell of cells) {
|
|
122
|
+
const context = await browser.newContext({
|
|
123
|
+
viewport: { width: cell.width, height: cell.height },
|
|
124
|
+
reducedMotion: cell.variant === 'reduced-motion' ? 'reduce' : 'no-preference',
|
|
125
|
+
colorScheme: cell.variant === 'dark' ? 'dark' : cell.variant === 'light' ? 'light' : 'no-preference',
|
|
126
|
+
});
|
|
127
|
+
const page = await context.newPage();
|
|
128
|
+
await page.goto(`file://${tmp}`);
|
|
129
|
+
if (cell.variant === 'keyboard-focus') await page.keyboard.press('Tab');
|
|
130
|
+
if (cell.variant === 'text-zoom-200') {
|
|
131
|
+
await page.addStyleTag({ content: 'html { font-size: 200%; }' });
|
|
132
|
+
}
|
|
133
|
+
if (cell.variant === 'long-translation') {
|
|
134
|
+
await page.evaluate(() => {
|
|
135
|
+
const apply = (el, t) => { if (el) el.textContent = t; };
|
|
136
|
+
apply(document.querySelector('h2'), 'Skalieren Sie Ihre Unternehmensarchitektur mit unprecedented Geschwindigkeit');
|
|
137
|
+
const btn = document.querySelector('.btn-mock.btn-nebula');
|
|
138
|
+
if (btn) btn.textContent = 'Jetzt kostenlos testen und sofort durchstarten';
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
if (cell.variant === 'narrow-mobile') await page.setViewportSize({ width: 320, height: 667 });
|
|
142
|
+
const file = path.join(outDir, `${cell.viewport}-${cell.variant}.png`);
|
|
143
|
+
await page.screenshot({ path: file, fullPage: true });
|
|
144
|
+
const { sha256File } = await import('../shared/io.js');
|
|
145
|
+
result.screenshots.captured.push({ cell: `${cell.viewport}/${cell.variant}`, file: path.relative(root, file), sha256: sha256File(file), bytes: fs.statSync(file).size });
|
|
146
|
+
await context.close();
|
|
147
|
+
}
|
|
148
|
+
result.screenshots.status = 'captured';
|
|
149
|
+
} finally {
|
|
150
|
+
await browser.close();
|
|
151
|
+
}
|
|
152
|
+
} catch (err) {
|
|
153
|
+
result.screenshots.status = 'skipped';
|
|
154
|
+
result.screenshots.required_input = `browser launch failed: ${err.message}`;
|
|
155
|
+
}
|
|
156
|
+
if (output || result.screenshots.status === 'captured') writeReport(root, output || path.relative(root, outDir), result);
|
|
157
|
+
return result;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function writeReport(root, output, result) {
|
|
161
|
+
const outFull = path.resolve(root, output, 'visual-regression.json');
|
|
162
|
+
fs.mkdirSync(path.dirname(outFull), { recursive: true });
|
|
163
|
+
fs.writeFileSync(outFull, JSON.stringify(result, null, 2) + '\n', 'utf8');
|
|
164
|
+
result.output_dir = path.dirname(outFull);
|
|
165
|
+
}
|