@epoint-testtech/ep-stage-skill 0.0.15 → 0.0.17
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/codex-skill/ep-stage/code-list-generate/SKILL.md +1 -1
- package/codex-skill/ep-stage/glue-create-project/SKILL.md +1 -1
- package/codex-skill/ep-stage/glue-generate-testcase/SKILL.md +7 -6
- package/codex-skill/ep-stage/glue-run-test/SKILL.md +100 -38
- package/codex-skill/ep-stage/glue-run-test/references/ai-runtime-loop.md +15 -9
- package/codex-skill/ep-stage/glue-run-test/references/crud-pipeline.md +10 -3
- package/codex-skill/ep-stage/glue-run-test/references/gap-review-protocol.md +11 -0
- package/codex-skill/ep-stage/glue-run-test/references/playwright-cli-odav.md +13 -2
- package/codex-skill/ep-stage/page-element-scan/SKILL.md +92 -91
- package/codex-skill/ep-stage/scripts/validate-skill.mjs +4 -1
- package/dist/src/cli/calibrate.d.ts +75 -0
- package/dist/src/cli/calibrate.d.ts.map +1 -0
- package/dist/src/cli/calibrate.js +318 -0
- package/dist/src/cli/demote.d.ts +53 -0
- package/dist/src/cli/demote.d.ts.map +1 -0
- package/dist/src/cli/demote.js +111 -0
- package/dist/src/cli/index.d.ts +5 -3
- package/dist/src/cli/index.d.ts.map +1 -1
- package/dist/src/cli/index.js +45 -6
- package/dist/src/cli/run-report.d.ts +6 -0
- package/dist/src/cli/run-report.d.ts.map +1 -1
- package/dist/src/cli/run-report.js +161 -147
- package/dist/src/cli/run.d.ts +51 -0
- package/dist/src/cli/run.d.ts.map +1 -1
- package/dist/src/cli/run.js +233 -31
- package/dist/src/contracts/glue-contract-v1.d.ts +37 -1
- package/dist/src/contracts/glue-contract-v1.d.ts.map +1 -1
- package/dist/src/extractors/code-list-json5.d.ts +29 -0
- package/dist/src/extractors/code-list-json5.d.ts.map +1 -1
- package/dist/src/generators/stage-skeleton-script.d.ts +30 -1
- package/dist/src/generators/stage-skeleton-script.d.ts.map +1 -1
- package/dist/src/generators/stage-skeleton-script.js +74 -11
- package/dist/src/runtime/ai-runtime-trace.d.ts +6 -0
- package/dist/src/runtime/ai-runtime-trace.d.ts.map +1 -1
- package/dist/src/testcase/contract-testcase-assembler.d.ts +23 -4
- package/dist/src/testcase/contract-testcase-assembler.d.ts.map +1 -1
- package/dist/src/testcase/contract-testcase-assembler.js +204 -27
- package/dist/src/testcase/query-component-map.d.ts +51 -0
- package/dist/src/testcase/query-component-map.d.ts.map +1 -0
- package/dist/src/testcase/query-component-map.js +64 -0
- package/dist/src/validation/contract.d.ts.map +1 -1
- package/dist/src/validation/contract.js +45 -3
- package/package.json +1 -1
package/dist/src/cli/run.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { spawnSync } from 'node:child_process';
|
|
2
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import JSON5 from 'json5';
|
|
5
5
|
import { validateTestcase } from '../validation/testcase.js';
|
|
6
|
+
import { validateCredentials } from '../validation/credentials.js';
|
|
6
7
|
import { classifyRunFailure, createInitialAiRuntimeTrace, nextRepairRound, writeAiRuntimeTrace, writeRepairReport, } from '../runtime/ai-runtime-trace.js';
|
|
7
8
|
import { runSpec } from './spec.js';
|
|
8
9
|
import { parsePlaywrightJsonResults, renderRunReportHtml } from './run-report.js';
|
|
@@ -37,6 +38,7 @@ export function parseRunArgs(argv) {
|
|
|
37
38
|
// headless 默认 true;--headless false 时关闭无头。
|
|
38
39
|
headless: result.headless !== 'false',
|
|
39
40
|
aiSnippets: result.aiSnippets,
|
|
41
|
+
strictAi: result.strictAi === 'true',
|
|
40
42
|
};
|
|
41
43
|
}
|
|
42
44
|
/**
|
|
@@ -169,14 +171,15 @@ function defaultAiSnippetsPath(caseDir) {
|
|
|
169
171
|
return path.join(caseDir, '.ep-stage', 'ai-snippets.json5');
|
|
170
172
|
}
|
|
171
173
|
/**
|
|
172
|
-
* 读取并校验 Agent
|
|
174
|
+
* 读取并校验 ai-snippets.json5,返回全部 result(含 resolved 与 Agent 自评 needs_review)。
|
|
173
175
|
*
|
|
174
|
-
*
|
|
176
|
+
* 文件缺失时返回空数组;schema / testcasePath / caseId 归属校验失败时抛错。
|
|
177
|
+
* 本函数是 loadAiSnippets 与 loadAiSnippetReviewResults 的共用解析层。
|
|
175
178
|
*
|
|
176
179
|
* @param input - snippets 路径、testcase 路径和当前 AI tasks。
|
|
177
|
-
* @returns
|
|
180
|
+
* @returns 校验通过的 AiRuntimeResult 全量列表。
|
|
178
181
|
*/
|
|
179
|
-
|
|
182
|
+
function parseAiSnippetsFile(input) {
|
|
180
183
|
if (!existsSync(input.snippetsPath)) {
|
|
181
184
|
return [];
|
|
182
185
|
}
|
|
@@ -195,11 +198,35 @@ export function loadAiSnippets(input) {
|
|
|
195
198
|
if (!taskIds.has(result.caseId)) {
|
|
196
199
|
throw new Error(`ai-snippets.json5 包含未知 caseId: ${result.caseId}`);
|
|
197
200
|
}
|
|
198
|
-
return
|
|
199
|
-
typeof result.specSnippet === 'string' &&
|
|
200
|
-
result.specSnippet.trim().length > 0);
|
|
201
|
+
return true;
|
|
201
202
|
});
|
|
202
203
|
}
|
|
204
|
+
/**
|
|
205
|
+
* 读取并校验 Agent O-D-A-V 产出的 snippets。
|
|
206
|
+
*
|
|
207
|
+
* 只有 testcasePath 匹配、caseId 属于当前任务、status=resolved 且 specSnippet 非空时才可合并。
|
|
208
|
+
*
|
|
209
|
+
* @param input - snippets 路径、testcase 路径和当前 AI tasks。
|
|
210
|
+
* @returns 可合并的 AiRuntimeResult 列表。
|
|
211
|
+
*/
|
|
212
|
+
export function loadAiSnippets(input) {
|
|
213
|
+
return parseAiSnippetsFile(input).filter((result) => result.status === 'resolved' &&
|
|
214
|
+
typeof result.specSnippet === 'string' &&
|
|
215
|
+
result.specSnippet.trim().length > 0);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* 读取 Agent 在 ai-snippets.json5 中自评的 needs_review 结论。
|
|
219
|
+
*
|
|
220
|
+
* 与 loadAiSnippets 互补:resolved 走 spec 合并,needs_review 走 trace/报告透传——
|
|
221
|
+
* Agent 的差异化复审证据(reviewReason / observation / evidence)必须保留,
|
|
222
|
+
* 不得被 CLI 占位文本覆盖。
|
|
223
|
+
*
|
|
224
|
+
* @param input - snippets 路径、testcase 路径和当前 AI tasks。
|
|
225
|
+
* @returns Agent 自评 needs_review 的 AiRuntimeResult 列表。
|
|
226
|
+
*/
|
|
227
|
+
export function loadAiSnippetReviewResults(input) {
|
|
228
|
+
return parseAiSnippetsFile(input).filter((result) => result.status === 'needs_review');
|
|
229
|
+
}
|
|
203
230
|
/**
|
|
204
231
|
* 截断现有 spec 的 AI 追加段(用于重跑覆盖,幂等)。
|
|
205
232
|
*
|
|
@@ -348,6 +375,7 @@ export function prepareAiRuntimeTasks(testcasePath) {
|
|
|
348
375
|
if (!existsSync(paths.specPath)) {
|
|
349
376
|
runSpec({ testcase: paths.testcasePath, out: paths.specPath });
|
|
350
377
|
}
|
|
378
|
+
warnIfSpecStale(paths);
|
|
351
379
|
const testcaseRaw = JSON5.parse(readFileSync(paths.testcasePath, 'utf8'));
|
|
352
380
|
const testcase = validateTestcase(testcaseRaw);
|
|
353
381
|
const tasks = buildAiRuntimeTasks(testcase, paths);
|
|
@@ -365,6 +393,28 @@ export function prepareAiRuntimeTasks(testcasePath) {
|
|
|
365
393
|
blockedCount,
|
|
366
394
|
};
|
|
367
395
|
}
|
|
396
|
+
/**
|
|
397
|
+
* spec 滞后警告:spec 是生成产物,prepare-tasks/run 的 existsSync 守卫不会自动重生成。
|
|
398
|
+
* 当 spec 旧于 testcase.json5 或 contract.json5 时打印警告,提示用 calibrate/demote/spec
|
|
399
|
+
* 子命令显式重生成(不自动改写,保持显式性)。
|
|
400
|
+
*
|
|
401
|
+
* @param paths - run 阶段路径。
|
|
402
|
+
*/
|
|
403
|
+
function warnIfSpecStale(paths) {
|
|
404
|
+
try {
|
|
405
|
+
if (!existsSync(paths.specPath))
|
|
406
|
+
return;
|
|
407
|
+
const specMtime = statSync(paths.specPath).mtimeMs;
|
|
408
|
+
const staleSources = [paths.testcasePath, paths.contractPath].filter((sourcePath) => existsSync(sourcePath) && statSync(sourcePath).mtimeMs > specMtime);
|
|
409
|
+
if (staleSources.length > 0) {
|
|
410
|
+
console.warn(`警告:spec 可能滞后于 ${staleSources.map((s) => path.basename(s)).join('、')},` +
|
|
411
|
+
'请用 calibrate/demote 子命令或手动重跑 spec 子命令刷新。');
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
catch {
|
|
415
|
+
// 警告级探测失败不影响主流程
|
|
416
|
+
}
|
|
417
|
+
}
|
|
368
418
|
/**
|
|
369
419
|
* 为缺少 resolved snippet 的 AI tasks 生成 needs_review 结果。
|
|
370
420
|
*
|
|
@@ -372,24 +422,33 @@ export function prepareAiRuntimeTasks(testcasePath) {
|
|
|
372
422
|
* @param resolvedResults - 已由 Agent 解决的结果。
|
|
373
423
|
* @returns 未解决任务的 needs_review 结果。
|
|
374
424
|
*/
|
|
375
|
-
function buildNeedsReviewResults(tasks, resolvedResults) {
|
|
425
|
+
function buildNeedsReviewResults(tasks, resolvedResults, agentReviewResults = []) {
|
|
376
426
|
const resolvedIds = new Set(resolvedResults.map((result) => result.caseId));
|
|
427
|
+
const agentReviewById = new Map(agentReviewResults.map((result) => [result.caseId, result]));
|
|
377
428
|
return tasks
|
|
378
429
|
.filter((task) => !resolvedIds.has(task.caseId))
|
|
379
|
-
.map((task) =>
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
430
|
+
.map((task) => {
|
|
431
|
+
// Agent 在 ai-snippets.json5 自评的 needs_review 结论(含差异化复审证据)优先透传,
|
|
432
|
+
// 只有 Agent 未产出结论时才落 CLI 占位文本。
|
|
433
|
+
const agentReview = agentReviewById.get(task.caseId);
|
|
434
|
+
if (agentReview) {
|
|
435
|
+
return { ...agentReview, status: 'needs_review' };
|
|
436
|
+
}
|
|
437
|
+
return {
|
|
438
|
+
caseId: task.caseId,
|
|
439
|
+
status: 'needs_review',
|
|
440
|
+
observation: {
|
|
441
|
+
summary: '未找到 Agent O-D-A-V 产出的 resolved snippet,等待人工或 Agent 继续推理。',
|
|
442
|
+
},
|
|
443
|
+
decision: {
|
|
444
|
+
action: 'skip merge and execution',
|
|
445
|
+
},
|
|
446
|
+
verification: {
|
|
447
|
+
assertionExpectation: task.assertionExpectation,
|
|
448
|
+
},
|
|
449
|
+
evidence: [{ source: 'ep-stage-cli', note: 'CLI 不生成占位 snippet,避免假通过' }],
|
|
450
|
+
};
|
|
451
|
+
});
|
|
393
452
|
}
|
|
394
453
|
/**
|
|
395
454
|
* 生成器在 test.describe 闭包内输出的 in-place 定位 marker(` // @stage-gap-append`)。
|
|
@@ -438,6 +497,31 @@ function appendAiSnippets(specPath, tasks, results) {
|
|
|
438
497
|
const section = ` ${AI_APPEND_MARKER}\n${snippets.join('\n\n')}\n\n`;
|
|
439
498
|
writeFileSync(specPath, `${before}${section}${after}`, 'utf8');
|
|
440
499
|
}
|
|
500
|
+
/**
|
|
501
|
+
* run 执行前置凭据门禁。
|
|
502
|
+
*
|
|
503
|
+
* 背景:glue 骨架运行时(stage-core loadCredentials / spec 内 `credential.url`)只读
|
|
504
|
+
* `url / username / password`;credentials.json5 只写 loginUrl 时 CLI 侧宽松校验能过,
|
|
505
|
+
* 却要等到骨架 `page.goto(undefined)` 才爆。这里在执行 Playwright 前显式拦截:
|
|
506
|
+
* 文件存在则每条必须 url / username / password 非空(validateCredentials 先保证结构
|
|
507
|
+
* 与 username/password,本门禁再强制 url 字段本身存在)。
|
|
508
|
+
* 文件缺失仍走 credentialsNotice 软提示(保持既有行为,由 skill Step 3 引导补齐)。
|
|
509
|
+
*
|
|
510
|
+
* @param testcase - 已校验 testcase。
|
|
511
|
+
* @param testcasePath - testcase.json5 绝对路径。
|
|
512
|
+
*/
|
|
513
|
+
export function assertRunCredentialsReady(testcase, testcasePath) {
|
|
514
|
+
const credPath = resolveCredentialPath(testcase, testcasePath);
|
|
515
|
+
if (!existsSync(credPath))
|
|
516
|
+
return;
|
|
517
|
+
const entries = validateCredentials(JSON5.parse(readFileSync(credPath, 'utf8')));
|
|
518
|
+
entries.forEach((entry, index) => {
|
|
519
|
+
if (!entry.url || !entry.url.trim()) {
|
|
520
|
+
throw new Error(`credentials.json5 第 ${index + 1} 条(角色:${entry.role || '未标注'})缺 url 字段(登录页地址)。` +
|
|
521
|
+
'glue 骨架登录只读 url,不识别 loginUrl;请把 loginUrl 的值同步到 url 字段后重跑。');
|
|
522
|
+
}
|
|
523
|
+
});
|
|
524
|
+
}
|
|
441
525
|
/**
|
|
442
526
|
* 读取并声明消费 credentials.json5(消费边界声明)。
|
|
443
527
|
*
|
|
@@ -456,6 +540,92 @@ function loadCredentialsNotice(testcase, testcasePath) {
|
|
|
456
540
|
JSON5.parse(readFileSync(credPath, 'utf8'));
|
|
457
541
|
return undefined;
|
|
458
542
|
}
|
|
543
|
+
/**
|
|
544
|
+
* 从项目 glue-report 下最新的 stage-glue 执行记录 JSON 提取复核结论映射。
|
|
545
|
+
*
|
|
546
|
+
* 与 run 的关系:recorder 由 spec 内 afterAll 在 Playwright 进程内写出
|
|
547
|
+
* (glue-report/<执行时间戳>/stage-glue-<时间戳>.json),本函数在 Playwright 结束后调用。
|
|
548
|
+
*
|
|
549
|
+
* 串轮防线:只消费「本轮执行」产生的记录。最新目录的 JSON startedAt 早于
|
|
550
|
+
* executionStartedAt(含 30s 时钟容差)时说明本轮 recorder 未落盘(如执行在
|
|
551
|
+
* afterAll 前崩溃),直接返回空 Map——严禁回退到上一轮目录,否则历史复核结论
|
|
552
|
+
* (如「搜索前后数据量相同」)会贴到本轮已通过用例的卡片上。
|
|
553
|
+
*
|
|
554
|
+
* 任一环节缺失(目录/文件/结构不符)返回空 Map——综合报告退化为仅 Playwright 视角,不阻断。
|
|
555
|
+
*
|
|
556
|
+
* @param projectDir - glue 项目根目录。
|
|
557
|
+
* @param executionStartedAt - 本轮 Playwright 启动时刻(早于 executor 调用采集)。
|
|
558
|
+
* @returns playwrightTestTitle → 复核原因(仅 needs_review 工作流)。
|
|
559
|
+
*/
|
|
560
|
+
export function loadRecorderReviewNotes(projectDir, executionStartedAt) {
|
|
561
|
+
const notes = new Map();
|
|
562
|
+
// 30s 时钟容差:recorder 进程与 CLI 进程计时基准可能存在微小偏移。
|
|
563
|
+
const SKEW_MS = 30_000;
|
|
564
|
+
try {
|
|
565
|
+
const glueReportRoot = path.join(projectDir, 'glue-report');
|
|
566
|
+
if (!existsSync(glueReportRoot))
|
|
567
|
+
return notes;
|
|
568
|
+
const runDirs = readdirSync(glueReportRoot)
|
|
569
|
+
.filter((name) => /^\d{14}$/.test(name))
|
|
570
|
+
.sort()
|
|
571
|
+
.reverse();
|
|
572
|
+
for (const runDir of runDirs) {
|
|
573
|
+
const dirPath = path.join(glueReportRoot, runDir);
|
|
574
|
+
const jsonFile = readdirSync(dirPath).find((name) => name.startsWith('stage-glue-') && name.endsWith('.json'));
|
|
575
|
+
if (!jsonFile)
|
|
576
|
+
continue;
|
|
577
|
+
const parsed = JSON.parse(readFileSync(path.join(dirPath, jsonFile), 'utf8'));
|
|
578
|
+
const recorderStartedAt = Date.parse(parsed.startedAt ?? '');
|
|
579
|
+
if (Number.isNaN(recorderStartedAt))
|
|
580
|
+
return notes;
|
|
581
|
+
// 目录按时间戳倒序:首个含 JSON 的目录即最新一轮记录;它若比本轮启动还早,
|
|
582
|
+
// 说明本轮没有 recorder 产物,更旧的目录只会更 stale,直接停。
|
|
583
|
+
if (recorderStartedAt < executionStartedAt.getTime() - SKEW_MS)
|
|
584
|
+
return notes;
|
|
585
|
+
for (const workflow of parsed.workflows ?? []) {
|
|
586
|
+
if (workflow.status === 'needs_review' && workflow.playwrightTestTitle && workflow.reviewReason) {
|
|
587
|
+
notes.set(workflow.playwrightTestTitle, workflow.reviewReason);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
return notes; // 本轮记录已消费(即使无复核结论),不再触碰历史目录
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
catch {
|
|
594
|
+
// 复核结论合并失败不阻断综合报告
|
|
595
|
+
}
|
|
596
|
+
return notes;
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* 把 recorder 的复核结论按标题合并进综合报告条目(就地修改 items)。
|
|
600
|
+
*
|
|
601
|
+
* @param items - 综合报告用例条目。
|
|
602
|
+
* @param reviewNotes - playwrightTestTitle → 复核原因。
|
|
603
|
+
*/
|
|
604
|
+
function mergeReviewNotesIntoItems(items, reviewNotes) {
|
|
605
|
+
for (const item of items) {
|
|
606
|
+
const note = reviewNotes.get(item.title);
|
|
607
|
+
if (note) {
|
|
608
|
+
item.reviewNote = note;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* 提取待审任务在报告中的审阅原因:优先 Agent 自评 reviewReason(差异化复审证据),
|
|
614
|
+
* 其次 observation.summary,最后回退通用占位文本。
|
|
615
|
+
*
|
|
616
|
+
* @param result - needs_review 的 AiRuntimeResult。
|
|
617
|
+
* @returns 报告卡片呈现的审阅原因。
|
|
618
|
+
*/
|
|
619
|
+
function resolveReviewNoteText(result) {
|
|
620
|
+
if (typeof result.reviewReason === 'string' && result.reviewReason.trim().length > 0) {
|
|
621
|
+
return result.reviewReason;
|
|
622
|
+
}
|
|
623
|
+
const summary = result.observation?.summary;
|
|
624
|
+
if (typeof summary === 'string' && summary.trim().length > 0) {
|
|
625
|
+
return summary;
|
|
626
|
+
}
|
|
627
|
+
return '缺 resolved snippet,本轮未执行,等待人工复审。';
|
|
628
|
+
}
|
|
459
629
|
/**
|
|
460
630
|
* run 子命令主体(REQ-CHAIN-02 / REQ-SPEC-01,新协议 v1-draft)。
|
|
461
631
|
*
|
|
@@ -478,8 +648,10 @@ export async function runRun(args, deps) {
|
|
|
478
648
|
if (!existsSync(paths.specPath)) {
|
|
479
649
|
runSpec({ testcase: paths.testcasePath, out: paths.specPath });
|
|
480
650
|
}
|
|
651
|
+
warnIfSpecStale(paths);
|
|
481
652
|
const testcaseRaw = JSON5.parse(readFileSync(paths.testcasePath, 'utf8'));
|
|
482
653
|
const testcase = validateTestcase(testcaseRaw);
|
|
654
|
+
assertRunCredentialsReady(testcase, paths.testcasePath);
|
|
483
655
|
const tracePath = path.join(paths.caseDir, '.ep-stage', 'ai-runtime-trace.json5');
|
|
484
656
|
const aiRuntimeTasks = buildAiRuntimeTasks(testcase, paths);
|
|
485
657
|
const trace = createInitialAiRuntimeTrace({
|
|
@@ -493,11 +665,19 @@ export async function runRun(args, deps) {
|
|
|
493
665
|
testcasePath: paths.testcasePath,
|
|
494
666
|
tasks: aiRuntimeTasks,
|
|
495
667
|
});
|
|
496
|
-
const
|
|
668
|
+
const agentReviewResults = loadAiSnippetReviewResults({
|
|
669
|
+
snippetsPath,
|
|
670
|
+
testcasePath: paths.testcasePath,
|
|
671
|
+
tasks: aiRuntimeTasks,
|
|
672
|
+
});
|
|
673
|
+
const needsReviewResults = buildNeedsReviewResults(aiRuntimeTasks, resolvedResults, agentReviewResults);
|
|
497
674
|
trace.results = [...resolvedResults, ...needsReviewResults];
|
|
498
|
-
|
|
675
|
+
// --strict-ai 恢复旧语义:任一 AI 任务缺 resolved snippet → 整体短路不执行。
|
|
676
|
+
// 默认(false)为部分执行:needs_review 只记 trace,glue 与已 resolved 用例照常执行,
|
|
677
|
+
// 报告显式列出待审任务(不构成假通过),未决任务可在修补回路中补齐后重跑。
|
|
678
|
+
if (needsReviewResults.length > 0 && args.strictAi) {
|
|
499
679
|
writeAiRuntimeTrace(tracePath, trace);
|
|
500
|
-
const reportDir = path.join(paths.projectDir, '
|
|
680
|
+
const reportDir = path.join(paths.projectDir, 'glue-report', new Date().toISOString().replace(/[:.]/g, '-'));
|
|
501
681
|
mkdirSync(reportDir, { recursive: true });
|
|
502
682
|
return {
|
|
503
683
|
specPath: paths.specPath,
|
|
@@ -505,15 +685,20 @@ export async function runRun(args, deps) {
|
|
|
505
685
|
credentialsNotice: loadCredentialsNotice(testcase, paths.testcasePath),
|
|
506
686
|
version: 'v1',
|
|
507
687
|
aiRuntimeTracePath: tracePath,
|
|
688
|
+
needsReviewCount: needsReviewResults.length,
|
|
508
689
|
};
|
|
509
690
|
}
|
|
691
|
+
if (needsReviewResults.length > 0) {
|
|
692
|
+
console.warn(`提示:${needsReviewResults.length} 条 AI 任务缺 resolved snippet,本轮不执行(trace 已记 needs_review),其余用例照常执行。`);
|
|
693
|
+
}
|
|
510
694
|
appendAiSnippets(paths.specPath, aiRuntimeTasks, resolvedResults);
|
|
511
695
|
writeAiRuntimeTrace(tracePath, trace);
|
|
512
696
|
// 报告目录先于执行创建:json reporter 结果文件落这里,供 glue 风格综合报告渲染。
|
|
513
|
-
const reportDir = path.join(paths.projectDir, '
|
|
697
|
+
const reportDir = path.join(paths.projectDir, 'glue-report', new Date().toISOString().replace(/[:.]/g, '-'));
|
|
514
698
|
mkdirSync(reportDir, { recursive: true });
|
|
515
699
|
const resultsJsonPath = path.join(reportDir, 'playwright-results.json');
|
|
516
|
-
// 执行完整 spec
|
|
700
|
+
// 执行完整 spec。启动时刻先采集:recorder 复核结论合并以此为「本轮」时间闸。
|
|
701
|
+
const executionStartedAt = new Date();
|
|
517
702
|
const executor = deps?.executeFullSpec ?? defaultExecuteFullSpec;
|
|
518
703
|
const execution = await executor({
|
|
519
704
|
projectDir: paths.projectDir,
|
|
@@ -559,15 +744,31 @@ export async function runRun(args, deps) {
|
|
|
559
744
|
try {
|
|
560
745
|
if (existsSync(resultsJsonPath)) {
|
|
561
746
|
const parsedResults = parsePlaywrightJsonResults(readFileSync(resultsJsonPath, 'utf8'));
|
|
747
|
+
// 合并骨架运行时复核结论(stage-glue 执行记录):搜索前后数据量无变化 /
|
|
748
|
+
// 查询字段不在列表列等场景在报告标「待审阅」,避免 Playwright 层全绿掩盖语义未验证。
|
|
749
|
+
// 只消费本轮执行产生的记录,历史轮次的结论不回退合并。
|
|
750
|
+
mergeReviewNotesIntoItems(parsedResults.items, loadRecorderReviewNotes(paths.projectDir, executionStartedAt));
|
|
751
|
+
// 未执行的待审 AI 任务补卡:Playwright JSON 只覆盖已执行用例,
|
|
752
|
+
// needs_review 任务(缺 resolved snippet 未进 spec)必须显式呈现,
|
|
753
|
+
// 审阅原因取 Agent 自评结论(差异化证据),不用首轮 glue 的历史结论。
|
|
754
|
+
const taskTitleById = new Map(aiRuntimeTasks.map((task) => [task.caseId, task.title]));
|
|
755
|
+
const unexecutedReviewItems = needsReviewResults.map((result) => ({
|
|
756
|
+
title: `${result.caseId} ${taskTitleById.get(result.caseId) ?? ''}`.trim(),
|
|
757
|
+
suitePath: `${parsedResults.suiteTitle} › (未执行:待审阅)`,
|
|
758
|
+
projectName: '-',
|
|
759
|
+
status: 'skipped',
|
|
760
|
+
durationMs: 0,
|
|
761
|
+
reviewNote: resolveReviewNoteText(result),
|
|
762
|
+
}));
|
|
562
763
|
const html = renderRunReportHtml({
|
|
563
764
|
suiteTitle: parsedResults.suiteTitle,
|
|
564
765
|
startedAt: parsedResults.startedAt,
|
|
565
766
|
durationMs: parsedResults.durationMs,
|
|
566
767
|
specFile: paths.specPath,
|
|
567
|
-
items: parsedResults.items,
|
|
768
|
+
items: [...parsedResults.items, ...unexecutedReviewItems],
|
|
568
769
|
aiTasks: aiRuntimeTasks.map((task) => ({ title: task.title, caseId: task.caseId })),
|
|
569
|
-
playwrightReportHref: '
|
|
570
|
-
stageReportHref: '
|
|
770
|
+
playwrightReportHref: '../../playwright-report/index.html',
|
|
771
|
+
stageReportHref: '../../stage-report/report.pdf',
|
|
571
772
|
});
|
|
572
773
|
comprehensiveReportPath = path.join(reportDir, 'index.html');
|
|
573
774
|
writeFileSync(comprehensiveReportPath, html);
|
|
@@ -586,5 +787,6 @@ export async function runRun(args, deps) {
|
|
|
586
787
|
aiRuntimeTracePath: tracePath,
|
|
587
788
|
repairReportPath,
|
|
588
789
|
comprehensiveReportPath,
|
|
790
|
+
...(needsReviewResults.length > 0 ? { needsReviewCount: needsReviewResults.length } : {}),
|
|
589
791
|
};
|
|
590
792
|
}
|
|
@@ -46,6 +46,31 @@ export type ChildGridFlowSlot = {
|
|
|
46
46
|
cellValueByIndexAndField: string;
|
|
47
47
|
};
|
|
48
48
|
};
|
|
49
|
+
/**
|
|
50
|
+
* 未决槽位记录(unresolvedSlots 条目)。
|
|
51
|
+
*
|
|
52
|
+
* 契约可观测性 gate 的落地:无法静态/运行时确认的槽位显式登记在此,
|
|
53
|
+
* 禁止以猜测值写入正式槽位。
|
|
54
|
+
*/
|
|
55
|
+
export type UnresolvedSlotRecord = {
|
|
56
|
+
/** 槽位路径,如 'scenario.skeletonSlots.crud.searchConditions[科室]' */
|
|
57
|
+
slotPath: string;
|
|
58
|
+
/** 未决类别 */
|
|
59
|
+
kind: 'unsupported_query_component' | 'query_field_not_found' | 'multi_list_page' | 'export_button_unverified' | 'search_submit_unverified';
|
|
60
|
+
/** 原始组件名(unsupported_query_component 时填) */
|
|
61
|
+
rawComponent?: string;
|
|
62
|
+
/** 原因说明 */
|
|
63
|
+
reason: string;
|
|
64
|
+
/** 建议处理动作 */
|
|
65
|
+
suggestedAction: 'ai_runtime' | 'extend_component_library' | 'manual_split' | 'human_review';
|
|
66
|
+
/** 发现时机:assemble=装配期 / calibrate=校准期 */
|
|
67
|
+
detectedAt: 'assemble' | 'calibrate';
|
|
68
|
+
/** 证据引用 */
|
|
69
|
+
evidence?: {
|
|
70
|
+
source: 'code_list' | 'elementmap';
|
|
71
|
+
ref: string;
|
|
72
|
+
};
|
|
73
|
+
};
|
|
49
74
|
/**
|
|
50
75
|
* contract.json5 v1-draft 顶层类型。
|
|
51
76
|
*
|
|
@@ -75,6 +100,12 @@ export type EpStageContractV1Draft = {
|
|
|
75
100
|
searchFields: Array<{
|
|
76
101
|
field: string;
|
|
77
102
|
label: string;
|
|
103
|
+
/**
|
|
104
|
+
* 组件类型。白名单值(input/listbox/datepicker/tree,见 query-component-map.ts)= glue 承载,
|
|
105
|
+
* 必须存在于 skeletonSlots.crud.searchConditions;其余为上游 MiniUI 原名(如 mini-spinner),
|
|
106
|
+
* 用例走 AI 通道(gapCandidates/unresolvedCandidates),不在 searchConditions 出现。
|
|
107
|
+
* 故意保持 string 不收窄枚举:未识别组件须能合法穿过契约到达 AI 通道。
|
|
108
|
+
*/
|
|
78
109
|
component: string;
|
|
79
110
|
caseExpansion?: string[];
|
|
80
111
|
}>;
|
|
@@ -84,6 +115,11 @@ export type EpStageContractV1Draft = {
|
|
|
84
115
|
moduleId: string;
|
|
85
116
|
label: string;
|
|
86
117
|
mode: string;
|
|
118
|
+
/** 可选:导出按钮/容器定位器覆盖;缺失时 spec 生成回退框架默认 */
|
|
119
|
+
locators?: {
|
|
120
|
+
exportButton?: string;
|
|
121
|
+
exportContainer?: string;
|
|
122
|
+
};
|
|
87
123
|
};
|
|
88
124
|
childGrids?: ChildGridFlowSlot[];
|
|
89
125
|
};
|
|
@@ -93,6 +129,6 @@ export type EpStageContractV1Draft = {
|
|
|
93
129
|
generationStrategy: GenerationStrategy;
|
|
94
130
|
}>;
|
|
95
131
|
};
|
|
96
|
-
unresolvedSlots:
|
|
132
|
+
unresolvedSlots: UnresolvedSlotRecord[];
|
|
97
133
|
};
|
|
98
134
|
//# sourceMappingURL=glue-contract-v1.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glue-contract-v1.d.ts","sourceRoot":"","sources":["../../../src/contracts/glue-contract-v1.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,IAAI,CAAC;AAE/C;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,KAAK,GAAG,MAAM,CAAC;IACzB,QAAQ,EAAE,WAAW,GAAG,mBAAmB,GAAG,MAAM,CAAC;IACrD,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,EAAE;QACR,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,IAAI,EAAE,MAAM,CAAC;QACb,aAAa,EAAE,MAAM,CAAC;QACtB,sBAAsB,EAAE,MAAM,CAAC;QAC/B,oBAAoB,EAAE,MAAM,CAAC;QAC7B,kBAAkB,EAAE,MAAM,CAAC;QAC3B,mBAAmB,EAAE,MAAM,CAAC;QAC5B,wBAAwB,EAAE,MAAM,CAAC;KAClC,CAAC;CACH,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,aAAa,EAAE,4BAA4B,CAAC;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE;QACJ,MAAM,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;QACtC,UAAU,EAAE;YAAE,SAAS,EAAE,WAAW,GAAG,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;YAAC,SAAS,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACvF,WAAW,EAAE;YAAE,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;KACjC,CAAC;IACF,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,KAAK,CAAC;YAClB,KAAK,EAAE,MAAM,CAAC;YACd,KAAK,EAAE,MAAM,CAAC;YACd,SAAS,EAAE,MAAM,CAAC;YAClB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;SAC1B,CAAC,CAAC;QACH,aAAa,EAAE;YAEb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAC9B,MAAM,EAAE;
|
|
1
|
+
{"version":3,"file":"glue-contract-v1.d.ts","sourceRoot":"","sources":["../../../src/contracts/glue-contract-v1.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,7 @@ export type QueryField = {
|
|
|
13
13
|
component?: string;
|
|
14
14
|
modelRef?: string;
|
|
15
15
|
bind?: string;
|
|
16
|
+
elementHints?: ElementHint[];
|
|
16
17
|
};
|
|
17
18
|
/** 按钮/操作 */
|
|
18
19
|
export type ButtonAction = {
|
|
@@ -21,6 +22,20 @@ export type ButtonAction = {
|
|
|
21
22
|
backendMethod: string | null;
|
|
22
23
|
customAction?: string;
|
|
23
24
|
};
|
|
25
|
+
/** 元素线索(attr/value 对,供推导定位符,非最终 locator) */
|
|
26
|
+
export type ElementHint = {
|
|
27
|
+
attr: string;
|
|
28
|
+
value: string;
|
|
29
|
+
};
|
|
30
|
+
/** 工具栏按钮完整事实(code_list pages[].toolbarActions[]) */
|
|
31
|
+
export type ToolbarAction = {
|
|
32
|
+
label: string;
|
|
33
|
+
actionName?: string;
|
|
34
|
+
component?: string;
|
|
35
|
+
backendMethod?: string;
|
|
36
|
+
opens?: string;
|
|
37
|
+
elementHints?: ElementHint[];
|
|
38
|
+
};
|
|
24
39
|
/** 行级操作 */
|
|
25
40
|
export type RowAction = {
|
|
26
41
|
label: string;
|
|
@@ -59,11 +74,25 @@ export type PageItem = {
|
|
|
59
74
|
description: string;
|
|
60
75
|
pageId?: string;
|
|
61
76
|
title?: string;
|
|
77
|
+
/** 页面初始化的 restController 名(装配器据此推导查询请求断言关键字:FUI 查询走 /rest/<controller>/page_Refresh) */
|
|
78
|
+
initAction?: string;
|
|
62
79
|
directUrl?: string;
|
|
63
80
|
queryFields?: QueryField[];
|
|
64
81
|
formFields?: QueryField[] | string[];
|
|
65
82
|
buttons: ButtonAction[];
|
|
66
83
|
rowActions: RowAction[];
|
|
84
|
+
toolbarActions?: ToolbarAction[];
|
|
85
|
+
/** 列表页数据表格事实(装配器用 backendMethod 推导查询请求断言关键字) */
|
|
86
|
+
dataGrid?: {
|
|
87
|
+
id?: string;
|
|
88
|
+
idField?: string;
|
|
89
|
+
backendMethod?: string;
|
|
90
|
+
columns?: Array<{
|
|
91
|
+
field: string;
|
|
92
|
+
label: string;
|
|
93
|
+
renderer?: string;
|
|
94
|
+
}>;
|
|
95
|
+
};
|
|
67
96
|
usedDataModels?: string[];
|
|
68
97
|
dataLoadingMethods?: DataLoadingMethod[];
|
|
69
98
|
childGrids?: ChildGridItem[] | string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code-list-json5.d.ts","sourceRoot":"","sources":["../../../src/extractors/code-list-json5.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,4BAA4B,CAAC;AAIpC,WAAW;AACX,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"code-list-json5.d.ts","sourceRoot":"","sources":["../../../src/extractors/code-list-json5.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,4BAA4B,CAAC;AAIpC,WAAW;AACX,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;CAC9B,CAAC;AAEF,YAAY;AACZ,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,4CAA4C;AAC5C,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,oDAAoD;AACpD,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;CAC9B,CAAC;AAEF,WAAW;AACX,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,aAAa;AACb,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG,mBAAmB,GAAG,MAAM,CAAC;AAE3E,YAAY;AACZ,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACjC,CAAC;AAEF,WAAW;AACX,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvD,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC9B,CAAC;AAEF,WAAW;AACX,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wFAAwF;IACxF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,UAAU,EAAE,GAAG,MAAM,EAAE,CAAC;IACrC,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;IACjC,gDAAgD;IAChD,QAAQ,CAAC,EAAE;QACT,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,OAAO,CAAC,EAAE,KAAK,CAAC;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACtE,CAAC;IACF,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,kBAAkB,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACzC,UAAU,CAAC,EAAE,aAAa,EAAE,GAAG,MAAM,EAAE,CAAC;CACzC,CAAC;AAEF,WAAW;AACX,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,SAAS;AACT,MAAM,MAAM,QAAQ,GAAG;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,aAAa;AACb,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,WAAW;AACX,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,WAAW;AACX,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,WAAW,EAAE,CAAC;CACvB,CAAC;AAEF,WAAW;AACX,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;4CACwC;IACxC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,aAAa;AACb,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B,CAAC;AAEF,aAAa;AACb,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACpC,CAAC;AAEF,0CAA0C;AAC1C,MAAM,MAAM,gBAAgB,GAAG;IAC7B,gBAAgB;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,wBAAwB,CAAC,EAAE,MAAM,CAAC;CACnC,CAAC;AAEF,mCAAmC;AACnC,MAAM,MAAM,sBAAsB,GAAG;IACnC,aAAa;IACb,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW;IACX,MAAM,EAAE,MAAM,CAAC;IACf,aAAa;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB;IACjB,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,kBAAkB;IAClB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,aAAa;IACb,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,WAAW;IACX,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,aAAa;IACb,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,iBAAiB;IACjB,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;IAC7B,eAAe;IACf,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC;IACxB,eAAe;IACf,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,qBAAqB;IACrB,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B,CAAC;AAIF;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAI9D;AAID;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC,sBAAsB,EAAE,MAAM,GAAG,gBAAgB,CAAC,CAoChH;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,sBAAsB,CAiB7E"}
|
|
@@ -41,7 +41,27 @@ export type StageSkeletonCrudListboxSearchConditionSlot = {
|
|
|
41
41
|
searchAssertion?: StageSkeletonCrudListboxSearchAssertion;
|
|
42
42
|
createSelections?: StageSkeletonCrudListboxSelectionSlot[];
|
|
43
43
|
};
|
|
44
|
-
|
|
44
|
+
/** 日期/日期范围查询条件槽位(与骨架 CrudDatepickerSearchConditionSlot 结构一致)。 */
|
|
45
|
+
export type StageSkeletonCrudDatepickerSearchConditionSlot = {
|
|
46
|
+
component: 'datepicker';
|
|
47
|
+
field: string;
|
|
48
|
+
label: string;
|
|
49
|
+
listLocator?: string;
|
|
50
|
+
searchText?: string;
|
|
51
|
+
triggerSearch?: boolean;
|
|
52
|
+
searchAssertion?: 'none';
|
|
53
|
+
};
|
|
54
|
+
/** 过滤树查询条件槽位(与骨架 CrudTreeSearchConditionSlot 结构一致)。 */
|
|
55
|
+
export type StageSkeletonCrudTreeSearchConditionSlot = {
|
|
56
|
+
component: 'tree';
|
|
57
|
+
field: string;
|
|
58
|
+
label: string;
|
|
59
|
+
treeLocator?: string;
|
|
60
|
+
nodeStrategy?: 'first_leaf' | 'root';
|
|
61
|
+
searchOnSelect?: boolean;
|
|
62
|
+
searchAssertion?: 'none';
|
|
63
|
+
};
|
|
64
|
+
export type StageSkeletonCrudSearchConditionSlot = StageSkeletonCrudInputSearchConditionSlot | StageSkeletonCrudListboxSearchConditionSlot | StageSkeletonCrudDatepickerSearchConditionSlot | StageSkeletonCrudTreeSearchConditionSlot;
|
|
45
65
|
/**
|
|
46
66
|
* 子表列槽位(生成器层形态,与 skeleton ChildGridColumnSlot 保持一致)。
|
|
47
67
|
*/
|
|
@@ -105,7 +125,11 @@ export type StageSkeletonCrudFlowSlots = {
|
|
|
105
125
|
blockedDeleteMessage?: string;
|
|
106
126
|
/** 条件性删除(如"草稿可删、在用不可删"):骨架 runDeleteWorkflow 运行时按记录是否仍存在分流断言 */
|
|
107
127
|
conditionalDelete?: boolean;
|
|
128
|
+
/** 查询请求级断言关键字(骨架触发查询动作前 arm waitForResponse);与骨架 CrudFlowSlots.assertions 对齐 */
|
|
129
|
+
searchResponseUrlKeyword?: string;
|
|
108
130
|
};
|
|
131
|
+
/** 列表页列头标签清单(装配器从 dataGrid.columns 推导;骨架据此判定查询字段列可见性,不在列则标需人工复核) */
|
|
132
|
+
gridColumns?: string[];
|
|
109
133
|
};
|
|
110
134
|
/**
|
|
111
135
|
* 将 CRUD 业务模块契约映射为 stage-skeleton 的 CrudFlowSlots。
|
|
@@ -156,6 +180,11 @@ export type GenerateStageSkeletonCrudSpecFromSlotsOptions = {
|
|
|
156
180
|
moduleId: string;
|
|
157
181
|
label: string;
|
|
158
182
|
mode: string;
|
|
183
|
+
/** 可选:导出按钮/容器定位器覆盖(calibrate 运行时实据注入) */
|
|
184
|
+
locators?: {
|
|
185
|
+
exportButton?: string;
|
|
186
|
+
exportContainer?: string;
|
|
187
|
+
};
|
|
159
188
|
};
|
|
160
189
|
childGridSlots?: StageSkeletonChildGridFlowSlots[];
|
|
161
190
|
/** glue 用例清单(来自 testcase.json5 cases[]):一用例一脚本,标题带 caseId 前缀。 */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stage-skeleton-script.d.ts","sourceRoot":"","sources":["../../../src/generators/stage-skeleton-script.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,0BAA0B,EAAiF,MAAM,sCAAsC,CAAC;AAEtK,MAAM,MAAM,6BAA6B,GAAG,gBAAgB,GAAG,0BAA0B,CAAC;AAC1F,MAAM,MAAM,kCAAkC,GAAG,kBAAkB,GAAG,aAAa,CAAC;AAEpF,MAAM,MAAM,qCAAqC,GAAG,UAAU,GAAG,uBAAuB,CAAC;AACzF,MAAM,MAAM,uCAAuC,GAAG,qBAAqB,GAAG,MAAM,CAAC;AAErF,MAAM,MAAM,qCAAqC,GAAG;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,qCAAqC,CAAC;IACtD,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,yCAAyC,GAAG;IACtD,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,kCAAkC,CAAC;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,2CAA2C,GAAG;IACxD,SAAS,EAAE,SAAS,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,qCAAqC,CAAC;IACtD,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe,CAAC,EAAE,uCAAuC,CAAC;IAC1D,gBAAgB,CAAC,EAAE,qCAAqC,EAAE,CAAC;CAC5D,CAAC;AAEF,MAAM,MAAM,oCAAoC,GAC5C,yCAAyC,GACzC,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"stage-skeleton-script.d.ts","sourceRoot":"","sources":["../../../src/generators/stage-skeleton-script.ts"],"names":[],"mappings":"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"}
|