@taodigital/agents 0.0.0-stage → 1.2.1
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/README.md +99 -2
- package/dist/api-test-agent.d.ts +126 -0
- package/dist/api-test-agent.js +267 -0
- package/dist/artifact-intel-agent.d.ts +11 -0
- package/dist/artifact-intel-agent.js +152 -0
- package/dist/coverage-gap-agent.d.ts +25 -0
- package/dist/coverage-gap-agent.js +269 -0
- package/dist/coverage-map-agent.d.ts +15 -0
- package/dist/coverage-map-agent.js +255 -0
- package/dist/crawl-diff-agent.d.ts +27 -0
- package/dist/crawl-diff-agent.js +412 -0
- package/dist/data-agent.d.ts +101 -0
- package/dist/data-agent.js +2284 -0
- package/dist/document-agent.d.ts +10 -0
- package/dist/document-agent.js +32 -0
- package/dist/enhancement-agent.d.ts +48 -0
- package/dist/enhancement-agent.js +342 -0
- package/dist/field-detector-agent.d.ts +35 -0
- package/dist/field-detector-agent.js +220 -0
- package/dist/flow-agent.d.ts +130 -0
- package/dist/flow-agent.js +169 -0
- package/dist/github-agent.d.ts +18 -0
- package/dist/github-agent.js +39 -0
- package/dist/github-write-agent.d.ts +67 -0
- package/dist/github-write-agent.js +249 -0
- package/dist/grouping-agent.d.ts +18 -0
- package/dist/grouping-agent.js +338 -0
- package/dist/healing-agent.d.ts +73 -0
- package/dist/healing-agent.js +137 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.js +67 -0
- package/dist/integration-test-agent.d.ts +118 -0
- package/dist/integration-test-agent.js +165 -0
- package/dist/label-assignment-agent.d.ts +15 -0
- package/dist/label-assignment-agent.js +97 -0
- package/dist/llm-config.d.ts +38 -0
- package/dist/llm-config.js +287 -0
- package/dist/llm-mock.d.ts +77 -0
- package/dist/llm-mock.js +192 -0
- package/dist/llm.d.ts +58 -0
- package/dist/llm.js +438 -0
- package/dist/nlp-agent.d.ts +208 -0
- package/dist/nlp-agent.js +340 -0
- package/dist/orchestrator.d.ts +285 -0
- package/dist/orchestrator.js +141 -0
- package/dist/plan-agent.d.ts +4 -0
- package/dist/plan-agent.js +200 -0
- package/dist/repo-scan-agent.d.ts +189 -0
- package/dist/repo-scan-agent.js +2032 -0
- package/dist/requirements-agent.d.ts +59 -0
- package/dist/requirements-agent.js +641 -0
- package/dist/scenario-agent.d.ts +20 -0
- package/dist/scenario-agent.js +123 -0
- package/dist/script-agent.d.ts +447 -0
- package/dist/script-agent.js +11813 -0
- package/dist/security-test-agent.d.ts +111 -0
- package/dist/security-test-agent.js +141 -0
- package/dist/skill-file-agent.d.ts +264 -0
- package/dist/skill-file-agent.js +3470 -0
- package/dist/step-coverage.d.ts +46 -0
- package/dist/step-coverage.js +288 -0
- package/dist/step-utils.d.ts +2 -0
- package/dist/step-utils.js +62 -0
- package/dist/test-case-agent.d.ts +206 -0
- package/dist/test-case-agent.js +2141 -0
- package/dist/test-import-agent.d.ts +148 -0
- package/dist/test-import-agent.js +3235 -0
- package/dist/test-script-agent.d.ts +16 -0
- package/dist/test-script-agent.js +48 -0
- package/dist/token-pricing.d.ts +14 -0
- package/dist/token-pricing.js +62 -0
- package/dist/types.d.ts +232 -0
- package/dist/types.js +7 -0
- package/dist/visual-agent.d.ts +114 -0
- package/dist/visual-agent.js +261 -0
- package/package.json +26 -4
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Test Agent — OWASP DAST Coverage Generator
|
|
3
|
+
*
|
|
4
|
+
* Maps the attack surface discovered during crawl (all form inputs,
|
|
5
|
+
* API endpoints) to OWASP Top 10 test scenarios.
|
|
6
|
+
*
|
|
7
|
+
* Uses: ERROR_CATALOGUE, API_CONTRACT, AUTH_SESSION, INTERACTION_PATTERNS
|
|
8
|
+
* Test kinds: SECURITY, NEGATIVE, EDGE
|
|
9
|
+
*/
|
|
10
|
+
export interface SecurityTestCase {
|
|
11
|
+
title: string;
|
|
12
|
+
kind: 'SECURITY' | 'NEGATIVE' | 'EDGE';
|
|
13
|
+
priority: 'CRITICAL' | 'HIGH' | 'MEDIUM';
|
|
14
|
+
owaspCategory: string;
|
|
15
|
+
preconditions: string;
|
|
16
|
+
steps: string[];
|
|
17
|
+
expectedResult: string;
|
|
18
|
+
groundedOn: string[];
|
|
19
|
+
tags: string[];
|
|
20
|
+
}
|
|
21
|
+
export declare function generateSecurityTests(opts: {
|
|
22
|
+
tenantId: string;
|
|
23
|
+
projectId: string;
|
|
24
|
+
apiEndpoints?: Array<{
|
|
25
|
+
method: string;
|
|
26
|
+
urlPattern: string;
|
|
27
|
+
}>;
|
|
28
|
+
}): Promise<{
|
|
29
|
+
status: string;
|
|
30
|
+
cases: never[];
|
|
31
|
+
saved: null;
|
|
32
|
+
suiteName?: undefined;
|
|
33
|
+
} | {
|
|
34
|
+
status: string;
|
|
35
|
+
cases: SecurityTestCase[];
|
|
36
|
+
saved: {
|
|
37
|
+
suite: {
|
|
38
|
+
tenantId: string;
|
|
39
|
+
id: string;
|
|
40
|
+
projectId: string;
|
|
41
|
+
name: string;
|
|
42
|
+
createdAt: Date;
|
|
43
|
+
genModel: string | null;
|
|
44
|
+
category: import(".prisma/client").$Enums.SuiteCategory | null;
|
|
45
|
+
parentId: string | null;
|
|
46
|
+
ownerUserId: string | null;
|
|
47
|
+
genTotalTokens: number | null;
|
|
48
|
+
genTotalCostUsd: number | null;
|
|
49
|
+
genAt: Date | null;
|
|
50
|
+
genScreenCount: number | null;
|
|
51
|
+
coverageReport: import("@prisma/client/runtime/library").JsonValue | null;
|
|
52
|
+
};
|
|
53
|
+
testCases: {
|
|
54
|
+
tenantId: string;
|
|
55
|
+
screenId: string | null;
|
|
56
|
+
id: string;
|
|
57
|
+
projectId: string;
|
|
58
|
+
source: string;
|
|
59
|
+
status: string;
|
|
60
|
+
createdAt: Date;
|
|
61
|
+
updatedAt: Date;
|
|
62
|
+
steps: import("@prisma/client/runtime/library").JsonValue;
|
|
63
|
+
kind: string;
|
|
64
|
+
tags: import("@prisma/client/runtime/library").JsonValue;
|
|
65
|
+
approvedBy: string | null;
|
|
66
|
+
suiteId: string;
|
|
67
|
+
ref: string | null;
|
|
68
|
+
title: string;
|
|
69
|
+
priority: string;
|
|
70
|
+
preconditions: string | null;
|
|
71
|
+
expectedResult: string | null;
|
|
72
|
+
gherkin: string | null;
|
|
73
|
+
approvedAt: Date | null;
|
|
74
|
+
groundedOn: import("@prisma/client/runtime/library").JsonValue;
|
|
75
|
+
caseRefs: import("@prisma/client/runtime/library").JsonValue;
|
|
76
|
+
viewports: import("@prisma/client/runtime/library").JsonValue;
|
|
77
|
+
viewportConstraint: string;
|
|
78
|
+
techniqueOfRecord: string | null;
|
|
79
|
+
traceTo: string | null;
|
|
80
|
+
traceToExtra: import("@prisma/client/runtime/library").JsonValue;
|
|
81
|
+
testDataInline: import("@prisma/client/runtime/library").JsonValue | null;
|
|
82
|
+
dataNote: string | null;
|
|
83
|
+
scriptNote: string | null;
|
|
84
|
+
structuredSteps: import("@prisma/client/runtime/library").JsonValue | null;
|
|
85
|
+
artifactId: string | null;
|
|
86
|
+
scenarioId: string | null;
|
|
87
|
+
suspect: boolean;
|
|
88
|
+
suspectReason: string | null;
|
|
89
|
+
flakyScore: number;
|
|
90
|
+
consecutiveFlakes: number;
|
|
91
|
+
lastFlakyAt: Date | null;
|
|
92
|
+
quarantined: boolean;
|
|
93
|
+
quarantinedAt: Date | null;
|
|
94
|
+
quarantineReason: string | null;
|
|
95
|
+
genPromptTokens: number | null;
|
|
96
|
+
genCompletionTokens: number | null;
|
|
97
|
+
genCostUsd: number | null;
|
|
98
|
+
genModel: string | null;
|
|
99
|
+
dataSetId: string | null;
|
|
100
|
+
repoTargetPath: string | null;
|
|
101
|
+
stepsKey: string | null;
|
|
102
|
+
gherkinKey: string | null;
|
|
103
|
+
contentHash: string | null;
|
|
104
|
+
groundingHash: string | null;
|
|
105
|
+
locatorsJson: import("@prisma/client/runtime/library").JsonValue | null;
|
|
106
|
+
locatorsExtractedAt: Date | null;
|
|
107
|
+
captureStepScreenshots: import("@prisma/client/runtime/library").JsonValue | null;
|
|
108
|
+
}[];
|
|
109
|
+
};
|
|
110
|
+
suiteName: string;
|
|
111
|
+
}>;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Security Test Agent — OWASP DAST Coverage Generator
|
|
4
|
+
*
|
|
5
|
+
* Maps the attack surface discovered during crawl (all form inputs,
|
|
6
|
+
* API endpoints) to OWASP Top 10 test scenarios.
|
|
7
|
+
*
|
|
8
|
+
* Uses: ERROR_CATALOGUE, API_CONTRACT, AUTH_SESSION, INTERACTION_PATTERNS
|
|
9
|
+
* Test kinds: SECURITY, NEGATIVE, EDGE
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.generateSecurityTests = generateSecurityTests;
|
|
13
|
+
const app_brain_1 = require("@taodigital/app-brain");
|
|
14
|
+
const core_1 = require("@taodigital/core");
|
|
15
|
+
const llm_js_1 = require("./llm.js");
|
|
16
|
+
const llm_config_js_1 = require("./llm-config.js");
|
|
17
|
+
async function generateSecurityTests(opts) {
|
|
18
|
+
const llmCfg = await (0, llm_config_js_1.getTaskAgentLLMConfig)(opts.tenantId, 'testGeneration');
|
|
19
|
+
const project = await app_brain_1.AppBrain.getProjectMap(opts.tenantId, opts.projectId);
|
|
20
|
+
if (!project)
|
|
21
|
+
return { status: 'NO_PROJECT', cases: [], saved: null };
|
|
22
|
+
const screens = project.screens ?? [];
|
|
23
|
+
// Collect input elements (the attack surface)
|
|
24
|
+
const SCREEN_LIMIT = parseInt(process.env.SECURITY_AGENT_SCREEN_LIMIT ?? '20', 10);
|
|
25
|
+
const inputElements = [];
|
|
26
|
+
for (const screen of screens.slice(0, SCREEN_LIMIT)) {
|
|
27
|
+
for (const el of (screen.elements ?? [])) {
|
|
28
|
+
const roleLC = (el.role ?? '').toLowerCase();
|
|
29
|
+
if (['input', 'form', 'search', 'text', 'password', 'email', 'textarea', 'field'].some((r) => roleLC.includes(r))) {
|
|
30
|
+
inputElements.push({ screenName: screen.name, meaning: el.meaning, role: el.role, expectedData: el.expectedData });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const skillFiles = await app_brain_1.AppBrain.listSkillFiles(opts.tenantId, opts.projectId, ['ERROR_CATALOGUE', 'API_CONTRACT', 'AUTH_SESSION', 'INTERACTION_PATTERNS']);
|
|
35
|
+
const skillCtx = skillFiles.map((sf) => `### ${sf.kind}\n${sf.content}`).join('\n\n');
|
|
36
|
+
const inputSummary = inputElements.slice(0, 30)
|
|
37
|
+
.map((e) => ` - [${e.screenName}] ${e.role}: "${e.meaning}"${e.expectedData ? ` (expected: ${e.expectedData})` : ''}`)
|
|
38
|
+
.join('\n');
|
|
39
|
+
const endpointSummary = (opts.apiEndpoints ?? []).slice(0, 30)
|
|
40
|
+
.map((e) => ` ${e.method} ${e.urlPattern}`)
|
|
41
|
+
.join('\n');
|
|
42
|
+
const SYSTEM_DEFAULT = `You are an expert security QA engineer generating DAST test cases covering OWASP Top 10.
|
|
43
|
+
|
|
44
|
+
OWASP CATEGORIES TO COVER:
|
|
45
|
+
- A01: Broken Access Control (auth bypass, IDOR, privilege escalation)
|
|
46
|
+
- A02: Cryptographic Failures (sensitive data in URLs, weak tokens)
|
|
47
|
+
- A03: Injection (XSS, SQLi, command injection via inputs)
|
|
48
|
+
- A04: Insecure Design (business logic bypass, missing rate limiting)
|
|
49
|
+
- A05: Security Misconfiguration (verbose errors, debug info)
|
|
50
|
+
- A07: Authentication Failures (weak passwords, no lockout)
|
|
51
|
+
- A08: Integrity Failures (CSRF, unvalidated redirects)
|
|
52
|
+
|
|
53
|
+
GROUNDING RULES:
|
|
54
|
+
- Only inject payloads into INPUT FIELDS listed
|
|
55
|
+
- Only test auth bypass on endpoints/screens listed
|
|
56
|
+
- Never invent inputs or endpoints not documented
|
|
57
|
+
- Steps: "On [ScreenName]: [action]" or "API [METHOD] [path]: [action]"
|
|
58
|
+
- expectedResult: what the app MUST do — reject, sanitize, block
|
|
59
|
+
|
|
60
|
+
OUTPUT FORMAT — valid JSON array only, no markdown:
|
|
61
|
+
[
|
|
62
|
+
{
|
|
63
|
+
"title": "string",
|
|
64
|
+
"kind": "SECURITY|NEGATIVE|EDGE",
|
|
65
|
+
"priority": "CRITICAL|HIGH|MEDIUM",
|
|
66
|
+
"owaspCategory": "A01|A02|A03|A04|A05|A07|A08",
|
|
67
|
+
"preconditions": "string",
|
|
68
|
+
"steps": ["step1", "step2"],
|
|
69
|
+
"expectedResult": "string",
|
|
70
|
+
"groundedOn": ["ScreenName.ElementMeaning or endpoint:METHOD /path"],
|
|
71
|
+
"tags": ["security", "owasp"]
|
|
72
|
+
}
|
|
73
|
+
]`;
|
|
74
|
+
const user = `Generate OWASP DAST security test cases for this application.
|
|
75
|
+
|
|
76
|
+
ATTACK SURFACE — INPUT FIELDS:
|
|
77
|
+
${inputSummary || ' (No input fields found — run a crawl first)'}
|
|
78
|
+
|
|
79
|
+
ATTACK SURFACE — API ENDPOINTS:
|
|
80
|
+
${endpointSummary || ' (No endpoints captured — check API_CONTRACT skill file)'}
|
|
81
|
+
|
|
82
|
+
SKILL FILE CONTEXT:
|
|
83
|
+
${skillCtx.slice(0, 5000)}
|
|
84
|
+
|
|
85
|
+
Generate tests:
|
|
86
|
+
1. XSS stored (A03): <script>alert('XSS')</script> in text inputs → DOM must not reflect unescaped
|
|
87
|
+
2. XSS reflected (A03): Payload in URL query params → response must not reflect
|
|
88
|
+
3. SQL injection (A03): ' OR 1=1 -- in login/search fields → no data leak, proper error
|
|
89
|
+
4. Auth bypass (A01): Navigate to protected screen without session cookie → redirect to login
|
|
90
|
+
5. IDOR (A01): Change resource ID in API call to another user's ID → 403 or 404
|
|
91
|
+
6. Brute force (A07): 10+ wrong password attempts → rate limiting or lockout
|
|
92
|
+
7. CSRF (A08): Submit form without CSRF token → request rejected
|
|
93
|
+
8. Verbose error (A05): Trigger 500 → no stack trace or internal path in response
|
|
94
|
+
9. Expired JWT (A02): Request with expired token → 401, not 200
|
|
95
|
+
10. Open redirect (A08): redirect_to=https://evil.com in params → only own domain allowed
|
|
96
|
+
|
|
97
|
+
Min 1-2 tests per OWASP category. Reference ACTUAL field names and endpoints from lists above.`;
|
|
98
|
+
const seed = (0, llm_js_1.deterministicSeed)(`${opts.tenantId}:${opts.projectId}:security:${inputSummary.slice(0, 300)}:${endpointSummary.slice(0, 200)}`);
|
|
99
|
+
const system = await (0, core_1.getAgentPrompt)('security-test-generation', undefined, opts.tenantId) ?? SYSTEM_DEFAULT;
|
|
100
|
+
let parsed = [];
|
|
101
|
+
const t0 = Date.now();
|
|
102
|
+
try {
|
|
103
|
+
const { text: raw, usage } = await (0, llm_js_1.askTracked)(system, user, llmCfg, undefined, undefined, { temperature: 0, seed });
|
|
104
|
+
const latencyMs = Date.now() - t0;
|
|
105
|
+
(0, app_brain_1.recordLLMCall)({
|
|
106
|
+
tenantId: opts.tenantId, projectId: opts.projectId,
|
|
107
|
+
agentType: 'security_test', label: 'security_test_generation', usage, latencyMs,
|
|
108
|
+
}).catch(console.error);
|
|
109
|
+
const jsonMatch = raw.match(/\[[\s\S]*\]/);
|
|
110
|
+
if (jsonMatch) {
|
|
111
|
+
const items = JSON.parse(jsonMatch[0]);
|
|
112
|
+
parsed = items
|
|
113
|
+
.filter((tc) => tc.title && Array.isArray(tc.steps) && tc.steps.length >= 1)
|
|
114
|
+
.map((tc) => ({
|
|
115
|
+
title: String(tc.title).slice(0, 200),
|
|
116
|
+
kind: (['SECURITY', 'NEGATIVE', 'EDGE'].includes(tc.kind) ? tc.kind : 'SECURITY'),
|
|
117
|
+
priority: (['CRITICAL', 'HIGH', 'MEDIUM'].includes(tc.priority) ? tc.priority : 'HIGH'),
|
|
118
|
+
owaspCategory: String(tc.owaspCategory || 'A03').slice(0, 10),
|
|
119
|
+
preconditions: String(tc.preconditions || '').slice(0, 300),
|
|
120
|
+
steps: tc.steps.map((s) => String(s).slice(0, 400)),
|
|
121
|
+
expectedResult: String(tc.expectedResult || '').slice(0, 500),
|
|
122
|
+
groundedOn: Array.isArray(tc.groundedOn) ? tc.groundedOn.map(String) : [],
|
|
123
|
+
tags: ['security', 'owasp', tc.owaspCategory || 'A03', ...(Array.isArray(tc.tags) ? tc.tags.map(String) : [])],
|
|
124
|
+
}));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch (e) {
|
|
128
|
+
console.error('[security-test-agent] parse error:', e?.message);
|
|
129
|
+
}
|
|
130
|
+
if (parsed.length === 0)
|
|
131
|
+
return { status: 'LLM_EMPTY', cases: [], saved: null };
|
|
132
|
+
const suiteName = 'Security Tests: OWASP Top 10';
|
|
133
|
+
const saved = await app_brain_1.AppBrain.saveGeneratedTestCases(opts.tenantId, opts.projectId, suiteName, parsed.map((tc) => ({
|
|
134
|
+
title: tc.title, kind: tc.kind, priority: tc.priority,
|
|
135
|
+
preconditions: tc.preconditions, steps: tc.steps,
|
|
136
|
+
expectedResult: tc.expectedResult, groundedOn: tc.groundedOn,
|
|
137
|
+
tags: tc.tags, source: 'AI_GENERATED',
|
|
138
|
+
})));
|
|
139
|
+
console.log(`[security-test-agent] ${parsed.length} OWASP test cases saved`);
|
|
140
|
+
return { status: 'GENERATED', cases: parsed, saved, suiteName };
|
|
141
|
+
}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill File Agent — 14-Dimension Application Intelligence Generator
|
|
3
|
+
*
|
|
4
|
+
* After each crawl, generates 14 taxonomy-level skill files in the Zeta Core:
|
|
5
|
+
*
|
|
6
|
+
* TIER 1 — Platform Intelligence (zero-cost DOM/network extraction, no LLM):
|
|
7
|
+
* 1. TECH_STACK — framework, CSS lib, API style, build tool
|
|
8
|
+
* 2. AUTH_SESSION — auth type, token storage, 2FA, protected routes
|
|
9
|
+
* 3. API_CONTRACT — captured endpoints, base URL, error format
|
|
10
|
+
*
|
|
11
|
+
* TIER 2 — Domain Intelligence (LLM, uses DOM data):
|
|
12
|
+
* 4. BUSINESS_DOMAIN — domain, user roles, core journeys, business rules
|
|
13
|
+
* 5. DATA_MODEL — entities and field constraints from HTML5 attrs
|
|
14
|
+
*
|
|
15
|
+
* TIER 3 — Behavioral Intelligence (LLM + vision):
|
|
16
|
+
* 6. INTERACTION_PATTERNS — error display, loading states, submit flow
|
|
17
|
+
* 7. ERROR_CATALOGUE — exact error messages per field and API error map
|
|
18
|
+
*
|
|
19
|
+
* TIER 4 — Structural Intelligence (LLM + vision):
|
|
20
|
+
* 8. VISUAL_BASELINE — colors (hex), typography, layout, contrast ratios
|
|
21
|
+
* 9. COMPONENT_LIBRARY — reusable components, where they appear, edge cases
|
|
22
|
+
* 10. ELEMENT_BEHAVIORS — per-element: type, required, min/max, pattern, states
|
|
23
|
+
*
|
|
24
|
+
* TIER 5 — Quality Intelligence (structured data, no LLM):
|
|
25
|
+
* 11. NAVIGATION_MAP — route inventory, auth guards, flow graph
|
|
26
|
+
* 12. LOCATOR_STRATEGY — data-testid coverage, role-based locators, fragile selectors
|
|
27
|
+
* 13. PERFORMANCE_BASELINE — LCP/FCP/TTFB per screen, CWV status
|
|
28
|
+
* 14. COVERAGE_MATRIX — TC counts per screen×type, coverage gaps
|
|
29
|
+
*
|
|
30
|
+
* QUALITY PROJECTION: 42/100 (old 6-file) → 87/100 (new 14-file)
|
|
31
|
+
*
|
|
32
|
+
* COST: Tiers 1, 5 = ZERO extra LLM tokens (pure DOM/network data).
|
|
33
|
+
* Tiers 2–4 = LLM calls, same as before but higher-quality prompts.
|
|
34
|
+
*/
|
|
35
|
+
export interface CrawledScreen {
|
|
36
|
+
id: string;
|
|
37
|
+
name: string;
|
|
38
|
+
url?: string | null;
|
|
39
|
+
elements: Array<{
|
|
40
|
+
meaning: string;
|
|
41
|
+
role: string;
|
|
42
|
+
expectedData?: string | null;
|
|
43
|
+
notes?: string | null;
|
|
44
|
+
transitionsToScreenId?: string | null;
|
|
45
|
+
}>;
|
|
46
|
+
screenshots?: Array<{
|
|
47
|
+
storagePath: string;
|
|
48
|
+
}> | null;
|
|
49
|
+
}
|
|
50
|
+
export interface ApiEndpoint {
|
|
51
|
+
method: string;
|
|
52
|
+
urlPattern: string;
|
|
53
|
+
}
|
|
54
|
+
export interface PerformanceMetric {
|
|
55
|
+
url: string;
|
|
56
|
+
screenName: string;
|
|
57
|
+
lcp?: number;
|
|
58
|
+
fcp?: number;
|
|
59
|
+
ttfb?: number;
|
|
60
|
+
cls?: number;
|
|
61
|
+
}
|
|
62
|
+
interface SkillFileResult {
|
|
63
|
+
content: string;
|
|
64
|
+
summary: string;
|
|
65
|
+
tags: string[];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Generate all 14 taxonomy skill files for a project after a crawl.
|
|
69
|
+
* Dependency-aware execution in 3 phases:
|
|
70
|
+
* Phase A: Zero-cost structured data (no LLM)
|
|
71
|
+
* Phase B: LLM domain + behavioral (uses Phase A data)
|
|
72
|
+
* Phase C: LLM structural + quality (uses Phase A+B data)
|
|
73
|
+
*/
|
|
74
|
+
export declare function generateTaxonomySkillFiles(tenantId: string, projectId: string, screens: CrawledScreen[], apiEndpoints?: ApiEndpoint[], performanceMetrics?: PerformanceMetric[]): Promise<void>;
|
|
75
|
+
/** TECH_STACK — purely from DOM data extracted during crawl */
|
|
76
|
+
export declare function generateTechStackFile(screens: CrawledScreen[], apiEndpoints?: ApiEndpoint[]): SkillFileResult;
|
|
77
|
+
/** AUTH_SESSION — from network request patterns + redirect behavior */
|
|
78
|
+
export declare function generateAuthSessionFile(screens: CrawledScreen[], apiEndpoints?: ApiEndpoint[]): SkillFileResult;
|
|
79
|
+
/** API_CONTRACT — from HAR-style endpoint capture during crawl */
|
|
80
|
+
export declare function generateApiContractFile(apiEndpoints?: ApiEndpoint[]): SkillFileResult;
|
|
81
|
+
/** NAVIGATION_MAP — from screen URLs + flow graph */
|
|
82
|
+
export declare function generateNavigationMapFile(screens: CrawledScreen[]): SkillFileResult;
|
|
83
|
+
/** LOCATOR_STRATEGY — from data-testid presence + ARIA attribute analysis */
|
|
84
|
+
export declare function generateLocatorStrategyFile(screens: CrawledScreen[]): SkillFileResult;
|
|
85
|
+
/** PERFORMANCE_BASELINE — from Playwright performance metrics during crawl */
|
|
86
|
+
export declare function generatePerformanceBaselineFile(screens: CrawledScreen[], metrics?: PerformanceMetric[]): SkillFileResult;
|
|
87
|
+
/** One probe observation captured by the interactive probe during a crawl. */
|
|
88
|
+
export interface ProbeObservationLite {
|
|
89
|
+
elementMeaning: string;
|
|
90
|
+
observationType: string;
|
|
91
|
+
observedText: string;
|
|
92
|
+
triggeredBy: string;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Derive concrete valid/invalid example values and state descriptions from
|
|
96
|
+
* HTML5 constraint attributes — deterministic, no LLM. This is what fills the
|
|
97
|
+
* Valid/Invalid Example columns that used to come back as "-".
|
|
98
|
+
*/
|
|
99
|
+
export declare function deriveConstraintExamples(role: string, expectedData: string | null | undefined, attrs: Record<string, string>): {
|
|
100
|
+
constraints: string;
|
|
101
|
+
valid: string;
|
|
102
|
+
invalid: string;
|
|
103
|
+
states: string;
|
|
104
|
+
};
|
|
105
|
+
export interface CoverageScreenRow {
|
|
106
|
+
id: string | null;
|
|
107
|
+
name: string;
|
|
108
|
+
url?: string | null;
|
|
109
|
+
elementCount: number;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Render the Coverage Matrix from live screen + TestCase-count data. Reuses
|
|
113
|
+
* the same URL-dedup and generic-title (deriveScreenLabel) logic as the
|
|
114
|
+
* crawl-time baseline above so screens are named consistently either way.
|
|
115
|
+
*/
|
|
116
|
+
export declare function renderCoverageMatrix(screens: CoverageScreenRow[], counts: Array<{
|
|
117
|
+
screenId: string | null;
|
|
118
|
+
kind: string;
|
|
119
|
+
count: number;
|
|
120
|
+
}>): SkillFileResult;
|
|
121
|
+
/**
|
|
122
|
+
* Recompute the COVERAGE_MATRIX skill file from live TestCase data.
|
|
123
|
+
* Called after every test generation run (and after crawls, as the baseline).
|
|
124
|
+
* Skips human-approved or manually written files so edits are never clobbered.
|
|
125
|
+
*/
|
|
126
|
+
export declare function refreshCoverageMatrix(tenantId: string, projectId: string): Promise<void>;
|
|
127
|
+
/**
|
|
128
|
+
* Recompute the TEST_CASES skill file.
|
|
129
|
+
* Emits testing strategy (persona registry, risk matrix, title conventions, exclusion list)
|
|
130
|
+
* drawn from BUSINESS_DOMAIN, then appends a live inventory of generated test cases.
|
|
131
|
+
* Runs even when no cases exist so new projects get actionable guidance immediately.
|
|
132
|
+
*/
|
|
133
|
+
export declare function refreshTestCaseInventory(tenantId: string, projectId: string): Promise<void>;
|
|
134
|
+
/**
|
|
135
|
+
* Recompute the TEST_SCRIPT skill file.
|
|
136
|
+
* Emits authoring standards (framework, auth strategy, selector priority, CI constraints, k6 config)
|
|
137
|
+
* drawn from TECH_STACK, AUTH_SESSION, and LOCATOR_STRATEGY skill files, then appends an
|
|
138
|
+
* inventory of existing scripts. Runs even when no scripts exist so new projects get
|
|
139
|
+
* actionable standards before first generation.
|
|
140
|
+
*/
|
|
141
|
+
export declare function refreshScriptInventory(tenantId: string, projectId: string): Promise<void>;
|
|
142
|
+
export declare function refineSkillFile(opts: {
|
|
143
|
+
tenantId: string;
|
|
144
|
+
projectId: string;
|
|
145
|
+
kind: string;
|
|
146
|
+
currentContent: string;
|
|
147
|
+
feedback: string;
|
|
148
|
+
}): Promise<SkillFileResult>;
|
|
149
|
+
export interface RepoSkillFileOpts {
|
|
150
|
+
repoFullName: string;
|
|
151
|
+
framework: string;
|
|
152
|
+
language: string;
|
|
153
|
+
testGlob: string;
|
|
154
|
+
styleProfile: Record<string, any> | null;
|
|
155
|
+
pageObjectInventory: Array<{
|
|
156
|
+
className: string;
|
|
157
|
+
filePath: string;
|
|
158
|
+
methods?: Array<{
|
|
159
|
+
name: string;
|
|
160
|
+
params?: string;
|
|
161
|
+
returnType?: string;
|
|
162
|
+
}>;
|
|
163
|
+
}>;
|
|
164
|
+
testPaths: string[];
|
|
165
|
+
extractedTestCount: number;
|
|
166
|
+
treeWasTruncated?: boolean;
|
|
167
|
+
extractedTests?: Array<{
|
|
168
|
+
name: string;
|
|
169
|
+
normalizedName: string;
|
|
170
|
+
filePath: string;
|
|
171
|
+
lineNumber: number;
|
|
172
|
+
describeBlock?: string;
|
|
173
|
+
framework: string;
|
|
174
|
+
dynamic: boolean;
|
|
175
|
+
}>;
|
|
176
|
+
}
|
|
177
|
+
export declare function generateRepoSkillFiles(tenantId: string, projectId: string, opts: RepoSkillFileOpts): Promise<void>;
|
|
178
|
+
/**
|
|
179
|
+
* Generates a `REPO_ZETA_OVERLAY` skill file containing repo-specific overrides
|
|
180
|
+
* derived deterministically from the `styleProfile` produced by repo scan.
|
|
181
|
+
* This overlay is injected AFTER the base `ZETA_FRAMEWORK_STANDARD` in generation
|
|
182
|
+
* prompts so repo-specific paths/conventions override generic ZeTa defaults.
|
|
183
|
+
*/
|
|
184
|
+
export declare function alignSkillFile(tenantId: string, projectId: string, opts: {
|
|
185
|
+
framework: string;
|
|
186
|
+
language: string;
|
|
187
|
+
styleProfile: Record<string, unknown> | null;
|
|
188
|
+
repoFullName: string;
|
|
189
|
+
}): Promise<void>;
|
|
190
|
+
/**
|
|
191
|
+
* Upserts one ZETA_FRAMEWORK_{FRAMEWORK} skill file per supported framework.
|
|
192
|
+
* Called once on project creation so every project has the framework standards
|
|
193
|
+
* available to script-generation agents from day one.
|
|
194
|
+
*/
|
|
195
|
+
export declare function generateZetaFrameworkSkillFiles(tenantId: string, projectId: string): Promise<void>;
|
|
196
|
+
/**
|
|
197
|
+
* Refresh BUSINESS_DOMAIN from uploaded/imported artifacts.
|
|
198
|
+
*
|
|
199
|
+
* Crawl-generated BUSINESS_DOMAIN is useful, but uploaded BRDs/specs often arrive
|
|
200
|
+
* before a crawl or test import. This live DB refresh makes those documents visible
|
|
201
|
+
* as project memory immediately without an LLM call. Approved/manual domain files
|
|
202
|
+
* remain locked.
|
|
203
|
+
*/
|
|
204
|
+
export declare function refreshArtifactKnowledgeSkillFile(tenantId: string, projectId: string): Promise<void>;
|
|
205
|
+
/**
|
|
206
|
+
* Refresh the TEST_CASES skill file from live TestCase data.
|
|
207
|
+
* Groups test cases by suite, caps at 200 rows, and summarises approval status.
|
|
208
|
+
*/
|
|
209
|
+
export declare function refreshTestCasesSkillFile(tenantId: string, projectId: string): Promise<void>;
|
|
210
|
+
/**
|
|
211
|
+
* Refresh the TEST_DATA skill file.
|
|
212
|
+
* Emits authoring guidance (personas, field constraints, equivalence classes, forbidden patterns)
|
|
213
|
+
* drawn from DATA_MODEL and BUSINESS_DOMAIN skill files, then appends an inventory of
|
|
214
|
+
* existing TestData records below a separator. Runs even when no data exists yet so new
|
|
215
|
+
* projects start with useful guidance immediately.
|
|
216
|
+
*/
|
|
217
|
+
export declare function refreshTestDataSkillFile(tenantId: string, projectId: string): Promise<void>;
|
|
218
|
+
/**
|
|
219
|
+
* Refresh the TEST_SCRIPT skill file from live TestScript records.
|
|
220
|
+
* Emits authoring standards (framework, auth, selector priority, CI constraints, k6 config)
|
|
221
|
+
* drawn from TECH_STACK, AUTH_SESSION, and LOCATOR_STRATEGY skill files, then appends an
|
|
222
|
+
* inventory of existing scripts with code samples. Runs even when no scripts exist yet.
|
|
223
|
+
*/
|
|
224
|
+
export declare function refreshTestScriptSkillFile(tenantId: string, projectId: string): Promise<void>;
|
|
225
|
+
/**
|
|
226
|
+
* Refresh the REQUIREMENTS_COVERAGE skill file from live requirements and test case data.
|
|
227
|
+
* Queries requirements, approved test cases, and traces coverage via LLM matching.
|
|
228
|
+
* No-ops when the skill file has been manually approved or edited.
|
|
229
|
+
*/
|
|
230
|
+
export declare function refreshRequirementsCoverageSkillFile(tenantId: string, projectId: string): Promise<void>;
|
|
231
|
+
/**
|
|
232
|
+
* GAP-SF-17: TEST_EXECUTION_HISTORY — top recently failed tests with error type + frequency.
|
|
233
|
+
* Refreshed after each test run completes.
|
|
234
|
+
*/
|
|
235
|
+
export declare function refreshTestExecutionHistorySkillFile(tenantId: string, projectId: string): Promise<void>;
|
|
236
|
+
/**
|
|
237
|
+
* GAP-SF-18: VISUAL_REGRESSION_HISTORY — screens with recent diffs, change types, stable vs unstable zones.
|
|
238
|
+
* Refreshed after visual diff generation.
|
|
239
|
+
*/
|
|
240
|
+
export declare function refreshVisualRegressionHistorySkillFile(tenantId: string, projectId: string): Promise<void>;
|
|
241
|
+
/**
|
|
242
|
+
* GAP-SF-19: Append self-healing history to LOCATOR_STRATEGY — elements with healCount > 2 are high-fragility.
|
|
243
|
+
* Refreshed after self-healing events.
|
|
244
|
+
*/
|
|
245
|
+
export declare function refreshLocatorStrategyWithHealingData(tenantId: string, projectId: string): Promise<void>;
|
|
246
|
+
/**
|
|
247
|
+
* GAP-SF-20: FIELD_CATALOG — deterministic ground-truth field inventory from AppField table.
|
|
248
|
+
* Refreshed after crawl when AppField catalog is populated.
|
|
249
|
+
*/
|
|
250
|
+
export declare function refreshFieldCatalogSkillFile(tenantId: string, projectId: string): Promise<void>;
|
|
251
|
+
/**
|
|
252
|
+
* GAP-SF-21: HEALING_LOG — dedicated skill file tracking healing events (element breaks + auto-fixes).
|
|
253
|
+
* Separates healing telemetry from LOCATOR_STRATEGY so it can be queried independently.
|
|
254
|
+
* Refreshed after self-healing events.
|
|
255
|
+
*/
|
|
256
|
+
export declare function refreshHealingLogSkillFile(tenantId: string, projectId: string): Promise<void>;
|
|
257
|
+
/**
|
|
258
|
+
* GAP-SF-22: LOCATOR_INVENTORY — per-screen map of actual extracted locators.
|
|
259
|
+
* Sourced from TestScript rows where language ends in ':locators'.
|
|
260
|
+
* Different from LOCATOR_STRATEGY which contains strategy guidance only.
|
|
261
|
+
* Refreshed after locator extraction runs.
|
|
262
|
+
*/
|
|
263
|
+
export declare function refreshLocatorInventorySkillFile(tenantId: string, projectId: string): Promise<void>;
|
|
264
|
+
export {};
|