cc-devflow 4.5.1 → 4.5.2
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/.claude/skills/cc-act/CHANGELOG.md +14 -0
- package/.claude/skills/cc-act/PLAYBOOK.md +26 -1
- package/.claude/skills/cc-act/SKILL.md +36 -7
- package/.claude/skills/cc-act/assets/PR_BRIEF_TEMPLATE.md +20 -0
- package/.claude/skills/cc-act/references/closure-contract.md +8 -0
- package/.claude/skills/cc-act/scripts/cc-act-common.sh +6 -1
- package/.claude/skills/cc-act/scripts/render-pr-brief.sh +99 -0
- package/.claude/skills/cc-act/scripts/verify-act-gate.sh +17 -1
- package/.claude/skills/cc-check/CHANGELOG.md +14 -0
- package/.claude/skills/cc-check/PLAYBOOK.md +101 -1
- package/.claude/skills/cc-check/SKILL.md +128 -7
- package/.claude/skills/cc-check/assets/REPORT_CARD_TEMPLATE.json +121 -1
- package/.claude/skills/cc-check/references/review-contract.md +88 -0
- package/.claude/skills/cc-check/scripts/render-report-card.js +172 -5
- package/.claude/skills/cc-check/scripts/verify-gate.sh +21 -0
- package/.claude/skills/cc-investigate/CHANGELOG.md +13 -0
- package/.claude/skills/cc-investigate/PLAYBOOK.md +105 -4
- package/.claude/skills/cc-investigate/SKILL.md +185 -8
- package/.claude/skills/cc-investigate/assets/ANALYSIS_TEMPLATE.md +77 -3
- package/.claude/skills/cc-investigate/assets/TASKS_TEMPLATE.md +10 -3
- package/.claude/skills/cc-investigate/assets/TASK_MANIFEST_TEMPLATE.json +102 -1
- package/.claude/skills/cc-investigate/references/investigation-contract.md +146 -0
- package/.claude/skills/cc-simplify/CHANGELOG.md +15 -0
- package/.claude/skills/cc-simplify/SKILL.md +255 -35
- package/CHANGELOG.md +16 -0
- package/docs/examples/example-bindings.json +3 -3
- package/docs/examples/full-design-blocked/README.md +1 -1
- package/docs/examples/full-design-blocked/changes/REQ-002-bulk-invite-import/review/report-card.json +140 -3
- package/docs/examples/local-handoff/README.md +1 -1
- package/docs/examples/local-handoff/changes/REQ-003-audit-log-export/review/report-card.json +92 -0
- package/docs/examples/pdca-loop/README.md +1 -1
- package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/handoff/pr-brief.md +20 -0
- package/docs/examples/pdca-loop/changes/REQ-001-copy-invite-link/review/report-card.json +92 -0
- package/lib/skill-runtime/review.js +64 -1
- package/lib/skill-runtime/schemas.js +150 -3
- package/package.json +1 -1
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
- Example version: `1.0.0`
|
|
6
6
|
- Last reviewed: `2026-04-17`
|
|
7
|
-
- Bound skills: `cc-roadmap@4.3.4`, `cc-plan@3.5.6`, `cc-do@1.5.2`, `cc-check@1.8.
|
|
7
|
+
- Bound skills: `cc-roadmap@4.3.4`, `cc-plan@3.5.6`, `cc-do@1.5.2`, `cc-check@1.8.4`, `cc-act@1.6.4`
|
|
8
8
|
|
|
9
9
|
This folder shows one minimal but complete `cc-roadmap -> cc-plan -> cc-do -> cc-check -> cc-act` loop.
|
|
10
10
|
|
|
@@ -20,6 +20,25 @@
|
|
|
20
20
|
- Base branch: `main`
|
|
21
21
|
- PR / MR: not created yet
|
|
22
22
|
|
|
23
|
+
## Review Range
|
|
24
|
+
|
|
25
|
+
- Reviewed base SHA: `example-base`
|
|
26
|
+
- Reviewed head SHA: `example-head`
|
|
27
|
+
- Review packet: `planning/tasks.md#T001-T003`; `planning/design.md`
|
|
28
|
+
- Finding triage: no findings
|
|
29
|
+
- QA / claim evidence: `qa=pass`, `tests-pass=pass`, `requirements-met=pass`
|
|
30
|
+
|
|
31
|
+
## Readiness Dashboard
|
|
32
|
+
|
|
33
|
+
- Review freshness: `fresh`, reviewed `example-head`, current `example-head`
|
|
34
|
+
- Review quality: `qualityScore=9`
|
|
35
|
+
- Specialist review facets: `testing:pass`
|
|
36
|
+
- QA coverage: `status=pass`, gaps `0`, e2eRequired `false`
|
|
37
|
+
- Browser QA: `skipped`, example fixture uses targeted component evidence instead of a live browser
|
|
38
|
+
- Failure ownership: no open failures recorded
|
|
39
|
+
- Documentation release: README and CLAUDE unchanged for this scoped example
|
|
40
|
+
- PR body accuracy: regenerate the PR body from this brief, current report-card, and current diff
|
|
41
|
+
|
|
23
42
|
## Summary
|
|
24
43
|
|
|
25
44
|
- removes a small but visible sharing friction in the beta flow
|
|
@@ -35,6 +54,7 @@
|
|
|
35
54
|
## Verification Evidence
|
|
36
55
|
|
|
37
56
|
- `report-card.json` verdict: `pass`
|
|
57
|
+
- Merged-result verification: not applicable before merge
|
|
38
58
|
- Fresh evidence:
|
|
39
59
|
- `npm test -- src/features/share/ShareDialog.test.tsx`
|
|
40
60
|
- `npm run lint -- src/features/share/ShareDialog.tsx`
|
|
@@ -3,6 +3,65 @@
|
|
|
3
3
|
"verdict": "pass",
|
|
4
4
|
"overall": "pass",
|
|
5
5
|
"summary": "verdict=pass quick=2/2 strict=0/0 review=pass",
|
|
6
|
+
"specAlignment": "pass",
|
|
7
|
+
"specDeltaVerified": true,
|
|
8
|
+
"specSyncReady": true,
|
|
9
|
+
"runtime": {
|
|
10
|
+
"status": "pass",
|
|
11
|
+
"failureOwnership": []
|
|
12
|
+
},
|
|
13
|
+
"claimEvidence": [
|
|
14
|
+
{
|
|
15
|
+
"claim": "tests-pass",
|
|
16
|
+
"requiredProof": "fresh targeted test command with exit 0",
|
|
17
|
+
"commandOrArtifact": "npm test -- src/features/share/ShareDialog.test.tsx",
|
|
18
|
+
"exitStatus": 0,
|
|
19
|
+
"keyObservation": "share dialog targeted tests passed",
|
|
20
|
+
"status": "pass"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"claim": "requirements-met",
|
|
24
|
+
"requiredProof": "line-by-line planning/tasks.md and task-manifest.json checklist",
|
|
25
|
+
"commandOrArtifact": "planning/tasks.md + planning/task-manifest.json",
|
|
26
|
+
"exitStatus": null,
|
|
27
|
+
"keyObservation": "T001-T003 complete with spec/code review proof",
|
|
28
|
+
"status": "pass"
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"qa": {
|
|
32
|
+
"status": "pass",
|
|
33
|
+
"regressionProof": [],
|
|
34
|
+
"testQuality": [
|
|
35
|
+
{
|
|
36
|
+
"area": "share-dialog",
|
|
37
|
+
"checksRealBehavior": true,
|
|
38
|
+
"mockBoundary": "none",
|
|
39
|
+
"testOnlyProductionApi": false,
|
|
40
|
+
"status": "pass"
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
"coverageAudit": {
|
|
44
|
+
"status": "pass",
|
|
45
|
+
"coveragePct": 80,
|
|
46
|
+
"pathMap": ["copy invite link success path", "clipboard fallback error path"],
|
|
47
|
+
"gaps": [],
|
|
48
|
+
"testsAdded": ["src/features/share/ShareDialog.test.tsx"],
|
|
49
|
+
"e2eRequired": false,
|
|
50
|
+
"evalRequired": false,
|
|
51
|
+
"qualityStars": "★★"
|
|
52
|
+
},
|
|
53
|
+
"browserEvidence": {
|
|
54
|
+
"status": "skipped",
|
|
55
|
+
"mode": "not-applicable",
|
|
56
|
+
"affectedRoutes": [],
|
|
57
|
+
"screenshots": [],
|
|
58
|
+
"consoleErrors": [],
|
|
59
|
+
"healthScore": null,
|
|
60
|
+
"issues": [],
|
|
61
|
+
"skipReason": "example fixture uses targeted component evidence instead of a live browser"
|
|
62
|
+
},
|
|
63
|
+
"tddException": null
|
|
64
|
+
},
|
|
6
65
|
"quickGates": [
|
|
7
66
|
{
|
|
8
67
|
"name": "targeted-tests",
|
|
@@ -22,10 +81,35 @@
|
|
|
22
81
|
"status": "pass",
|
|
23
82
|
"summary": "Task review proof and requirement-level diff review both passed",
|
|
24
83
|
"details": "T001-T003 have matching spec/code review proof and the diff stays inside the approved tiny-design boundary.",
|
|
84
|
+
"freshness": {
|
|
85
|
+
"status": "fresh",
|
|
86
|
+
"reviewedCommit": "example-head",
|
|
87
|
+
"currentCommit": "example-head",
|
|
88
|
+
"commitsSinceReview": 0,
|
|
89
|
+
"staleReason": ""
|
|
90
|
+
},
|
|
91
|
+
"qualityScore": 9,
|
|
92
|
+
"specialistReviews": [
|
|
93
|
+
{
|
|
94
|
+
"name": "testing",
|
|
95
|
+
"status": "pass",
|
|
96
|
+
"required": true,
|
|
97
|
+
"summary": "targeted tests cover the share dialog behavior for this example",
|
|
98
|
+
"skipReason": "",
|
|
99
|
+
"findings": []
|
|
100
|
+
}
|
|
101
|
+
],
|
|
25
102
|
"taskReviews": {
|
|
26
103
|
"status": "pass",
|
|
27
104
|
"required": true,
|
|
28
105
|
"summary": "All completed tasks carry spec/code proof",
|
|
106
|
+
"reviewPacket": {
|
|
107
|
+
"baseSha": "example-base",
|
|
108
|
+
"headSha": "example-head",
|
|
109
|
+
"requirements": "planning/tasks.md#T001-T003",
|
|
110
|
+
"implemented": "copy invite link workflow",
|
|
111
|
+
"reviewerContext": "task manifest plus changed share dialog files"
|
|
112
|
+
},
|
|
29
113
|
"reviewers": [],
|
|
30
114
|
"findings": []
|
|
31
115
|
},
|
|
@@ -33,12 +117,20 @@
|
|
|
33
117
|
"status": "pass",
|
|
34
118
|
"required": false,
|
|
35
119
|
"summary": "No blocking requirement-level findings",
|
|
120
|
+
"reviewPacket": {
|
|
121
|
+
"baseSha": "example-base",
|
|
122
|
+
"headSha": "example-head",
|
|
123
|
+
"requirements": "planning/design.md",
|
|
124
|
+
"implemented": "copy invite link workflow",
|
|
125
|
+
"reviewerContext": "requirement diff, plan completion, scope drift, docs staleness"
|
|
126
|
+
},
|
|
36
127
|
"reviewers": [],
|
|
37
128
|
"findings": []
|
|
38
129
|
},
|
|
39
130
|
"findings": []
|
|
40
131
|
},
|
|
41
132
|
"blockingFindings": [],
|
|
133
|
+
"gaps": [],
|
|
42
134
|
"reroute": "none",
|
|
43
135
|
"timestamp": "2026-04-15T11:20:00.000Z"
|
|
44
136
|
}
|
|
@@ -79,6 +79,7 @@ function makeFinding({
|
|
|
79
79
|
status = 'open',
|
|
80
80
|
fingerprint
|
|
81
81
|
}) {
|
|
82
|
+
const confidenceScore = severityRank(severity) >= severityRank('important') ? 8 : 6;
|
|
82
83
|
return {
|
|
83
84
|
id,
|
|
84
85
|
source,
|
|
@@ -91,7 +92,12 @@ function makeFinding({
|
|
|
91
92
|
...(typeof line === 'number' ? { line } : {}),
|
|
92
93
|
action,
|
|
93
94
|
status,
|
|
94
|
-
|
|
95
|
+
confidenceScore,
|
|
96
|
+
fingerprint: fingerprint || `${source}:${category}:${id}`,
|
|
97
|
+
displayTier: status === 'informational'
|
|
98
|
+
? 'info'
|
|
99
|
+
: (severityRank(severity) >= severityRank('important') ? 'blocking' : 'warning'),
|
|
100
|
+
suppressionReason: null
|
|
95
101
|
};
|
|
96
102
|
}
|
|
97
103
|
|
|
@@ -231,6 +237,14 @@ async function detectBaseRef(repoRoot) {
|
|
|
231
237
|
return 'HEAD~1';
|
|
232
238
|
}
|
|
233
239
|
|
|
240
|
+
async function detectCurrentCommit(repoRoot) {
|
|
241
|
+
const result = await runCommand('git rev-parse --short HEAD', { cwd: repoRoot });
|
|
242
|
+
if (result.code === 0 && result.stdout.trim()) {
|
|
243
|
+
return result.stdout.trim();
|
|
244
|
+
}
|
|
245
|
+
return 'working-tree';
|
|
246
|
+
}
|
|
247
|
+
|
|
234
248
|
async function runCodexStructuredReview({ repoRoot, baseRef }) {
|
|
235
249
|
const command = [
|
|
236
250
|
'codex review',
|
|
@@ -530,6 +544,7 @@ async function runReviewSuite({ repoRoot, changeId, manifest, strict, skipReview
|
|
|
530
544
|
const diffReview = await runDiffReviewSection({ repoRoot, strict, skipReview });
|
|
531
545
|
const findings = flattenFindings(taskReviews, diffReview);
|
|
532
546
|
const status = deriveReviewStatus(taskReviews, diffReview);
|
|
547
|
+
const currentCommit = await detectCurrentCommit(repoRoot);
|
|
533
548
|
const details = [
|
|
534
549
|
taskReviews.summary,
|
|
535
550
|
diffReview.summary
|
|
@@ -539,6 +554,54 @@ async function runReviewSuite({ repoRoot, changeId, manifest, strict, skipReview
|
|
|
539
554
|
status,
|
|
540
555
|
summary: `Task review: ${taskReviews.status}. Diff review: ${diffReview.status}.`,
|
|
541
556
|
details,
|
|
557
|
+
freshness: {
|
|
558
|
+
status: 'fresh',
|
|
559
|
+
reviewedCommit: currentCommit,
|
|
560
|
+
currentCommit,
|
|
561
|
+
commitsSinceReview: 0,
|
|
562
|
+
staleReason: ''
|
|
563
|
+
},
|
|
564
|
+
qualityScore: status === 'pass' ? 9 : (status === 'blocked' ? 5 : 3),
|
|
565
|
+
specialistReviews: [
|
|
566
|
+
{
|
|
567
|
+
name: 'testing',
|
|
568
|
+
status: taskReviews.status,
|
|
569
|
+
required: true,
|
|
570
|
+
summary: taskReviews.summary,
|
|
571
|
+
skipReason: '',
|
|
572
|
+
findings: []
|
|
573
|
+
}
|
|
574
|
+
],
|
|
575
|
+
runtime: {
|
|
576
|
+
status: status === 'pass' ? 'pass' : (status === 'fail' ? 'fail' : 'blocked'),
|
|
577
|
+
failureOwnership: []
|
|
578
|
+
},
|
|
579
|
+
qa: {
|
|
580
|
+
status: 'pass',
|
|
581
|
+
regressionProof: [],
|
|
582
|
+
testQuality: [],
|
|
583
|
+
coverageAudit: {
|
|
584
|
+
status: 'pass',
|
|
585
|
+
coveragePct: null,
|
|
586
|
+
pathMap: [],
|
|
587
|
+
gaps: [],
|
|
588
|
+
testsAdded: [],
|
|
589
|
+
e2eRequired: false,
|
|
590
|
+
evalRequired: false,
|
|
591
|
+
qualityStars: ''
|
|
592
|
+
},
|
|
593
|
+
browserEvidence: {
|
|
594
|
+
status: 'skipped',
|
|
595
|
+
mode: 'not-applicable',
|
|
596
|
+
affectedRoutes: [],
|
|
597
|
+
screenshots: [],
|
|
598
|
+
consoleErrors: [],
|
|
599
|
+
healthScore: null,
|
|
600
|
+
issues: [],
|
|
601
|
+
skipReason: 'runtime verify did not identify a UI browser QA target'
|
|
602
|
+
},
|
|
603
|
+
tddException: null
|
|
604
|
+
},
|
|
542
605
|
taskReviews,
|
|
543
606
|
diffReview,
|
|
544
607
|
findings
|
|
@@ -269,8 +269,26 @@ const GateResultSchema = z.object({
|
|
|
269
269
|
});
|
|
270
270
|
|
|
271
271
|
const ReviewSeveritySchema = z.enum(['critical', 'important', 'minor', 'info']);
|
|
272
|
-
const ReviewActionSchema = z.enum([
|
|
273
|
-
|
|
272
|
+
const ReviewActionSchema = z.enum([
|
|
273
|
+
'fix_now',
|
|
274
|
+
'follow_up',
|
|
275
|
+
'cc-investigate',
|
|
276
|
+
'reroute-cc-do',
|
|
277
|
+
'reroute-cc-plan',
|
|
278
|
+
'reroute-cc-investigate',
|
|
279
|
+
'document-follow-up',
|
|
280
|
+
'none'
|
|
281
|
+
]);
|
|
282
|
+
const ReviewFindingStatusSchema = z.enum([
|
|
283
|
+
'open',
|
|
284
|
+
'resolved',
|
|
285
|
+
'accepted',
|
|
286
|
+
'informational',
|
|
287
|
+
'accepted-fixed',
|
|
288
|
+
'rejected-with-evidence',
|
|
289
|
+
'deferred-minor',
|
|
290
|
+
'clarification-needed'
|
|
291
|
+
]);
|
|
274
292
|
|
|
275
293
|
const ReviewEvidenceSchema = z.object({
|
|
276
294
|
kind: z.enum(['command', 'file', 'note']),
|
|
@@ -291,7 +309,11 @@ const ReviewFindingSchema = z.object({
|
|
|
291
309
|
line: z.number().int().min(1).optional(),
|
|
292
310
|
action: ReviewActionSchema.default('none'),
|
|
293
311
|
status: ReviewFindingStatusSchema.default('open'),
|
|
294
|
-
fingerprint: z.string().optional()
|
|
312
|
+
fingerprint: z.string().optional(),
|
|
313
|
+
confidence: z.enum(['high', 'medium', 'low']).optional(),
|
|
314
|
+
confidenceScore: z.number().min(1).max(10).optional(),
|
|
315
|
+
displayTier: z.enum(['blocking', 'warning', 'info', 'suppressed']).optional(),
|
|
316
|
+
suppressionReason: z.string().nullable().optional()
|
|
295
317
|
});
|
|
296
318
|
|
|
297
319
|
const ReviewerResultSchema = z.object({
|
|
@@ -317,6 +339,28 @@ const ReportReviewSchema = z.object({
|
|
|
317
339
|
status: ReviewDecisionStatusSchema.default('skipped'),
|
|
318
340
|
summary: z.string().default(''),
|
|
319
341
|
details: z.string().default(''),
|
|
342
|
+
freshness: z.object({
|
|
343
|
+
status: z.enum(['fresh', 'stale', 'unknown', 'not-applicable']).default('unknown'),
|
|
344
|
+
reviewedCommit: z.string().default(''),
|
|
345
|
+
currentCommit: z.string().default(''),
|
|
346
|
+
commitsSinceReview: z.number().int().min(0).nullable().default(null),
|
|
347
|
+
staleReason: z.string().default('')
|
|
348
|
+
}).default({
|
|
349
|
+
status: 'unknown',
|
|
350
|
+
reviewedCommit: '',
|
|
351
|
+
currentCommit: '',
|
|
352
|
+
commitsSinceReview: null,
|
|
353
|
+
staleReason: ''
|
|
354
|
+
}),
|
|
355
|
+
qualityScore: z.number().min(0).max(10).nullable().default(null),
|
|
356
|
+
specialistReviews: z.array(z.object({
|
|
357
|
+
name: z.string().min(1),
|
|
358
|
+
status: ReviewDecisionStatusSchema,
|
|
359
|
+
required: z.boolean().default(false),
|
|
360
|
+
summary: z.string().default(''),
|
|
361
|
+
skipReason: z.string().default(''),
|
|
362
|
+
findings: z.array(ReviewFindingSchema).default([])
|
|
363
|
+
})).default([]),
|
|
320
364
|
taskReviews: ReviewSectionSchema.default({
|
|
321
365
|
status: 'skipped',
|
|
322
366
|
required: false,
|
|
@@ -334,15 +378,118 @@ const ReportReviewSchema = z.object({
|
|
|
334
378
|
findings: z.array(ReviewFindingSchema).default([])
|
|
335
379
|
});
|
|
336
380
|
|
|
381
|
+
const ClaimEvidenceSchema = z.object({
|
|
382
|
+
claim: z.string().min(1),
|
|
383
|
+
requiredProof: z.string().min(1),
|
|
384
|
+
commandOrArtifact: z.string().min(1),
|
|
385
|
+
exitStatus: z.number().int().nullable().optional(),
|
|
386
|
+
keyObservation: z.string().default(''),
|
|
387
|
+
status: ReviewDecisionStatusSchema
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
const RuntimeFailureOwnershipSchema = z.object({
|
|
391
|
+
failure: z.string().min(1),
|
|
392
|
+
classification: z.enum(['in-branch', 'pre-existing', 'environment', 'ambiguous']),
|
|
393
|
+
touchedByDiff: z.boolean().optional(),
|
|
394
|
+
evidence: z.string().default(''),
|
|
395
|
+
action: z.string().default(''),
|
|
396
|
+
status: z.string().default('open')
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
const ReportRuntimeSchema = z.object({
|
|
400
|
+
status: ReviewDecisionStatusSchema.default('skipped'),
|
|
401
|
+
failureOwnership: z.array(RuntimeFailureOwnershipSchema).default([])
|
|
402
|
+
}).default({
|
|
403
|
+
status: 'skipped',
|
|
404
|
+
failureOwnership: []
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
const QaSchema = z.object({
|
|
408
|
+
status: ReviewDecisionStatusSchema.default('skipped'),
|
|
409
|
+
regressionProof: z.array(z.record(z.any())).default([]),
|
|
410
|
+
testQuality: z.array(z.record(z.any())).default([]),
|
|
411
|
+
coverageAudit: z.object({
|
|
412
|
+
status: ReviewDecisionStatusSchema.default('skipped'),
|
|
413
|
+
coveragePct: z.number().nullable().default(null),
|
|
414
|
+
pathMap: z.array(z.string()).default([]),
|
|
415
|
+
gaps: z.array(z.string()).default([]),
|
|
416
|
+
testsAdded: z.array(z.string()).default([]),
|
|
417
|
+
e2eRequired: z.boolean().default(false),
|
|
418
|
+
evalRequired: z.boolean().default(false),
|
|
419
|
+
qualityStars: z.string().default('')
|
|
420
|
+
}).default({
|
|
421
|
+
status: 'skipped',
|
|
422
|
+
coveragePct: null,
|
|
423
|
+
pathMap: [],
|
|
424
|
+
gaps: [],
|
|
425
|
+
testsAdded: [],
|
|
426
|
+
e2eRequired: false,
|
|
427
|
+
evalRequired: false,
|
|
428
|
+
qualityStars: ''
|
|
429
|
+
}),
|
|
430
|
+
browserEvidence: z.object({
|
|
431
|
+
status: ReviewDecisionStatusSchema.default('skipped'),
|
|
432
|
+
mode: z.string().default('not-applicable'),
|
|
433
|
+
affectedRoutes: z.array(z.string()).default([]),
|
|
434
|
+
screenshots: z.array(z.string()).default([]),
|
|
435
|
+
consoleErrors: z.array(z.string()).default([]),
|
|
436
|
+
healthScore: z.number().nullable().default(null),
|
|
437
|
+
issues: z.array(z.record(z.any())).default([]),
|
|
438
|
+
skipReason: z.string().default('')
|
|
439
|
+
}).default({
|
|
440
|
+
status: 'skipped',
|
|
441
|
+
mode: 'not-applicable',
|
|
442
|
+
affectedRoutes: [],
|
|
443
|
+
screenshots: [],
|
|
444
|
+
consoleErrors: [],
|
|
445
|
+
healthScore: null,
|
|
446
|
+
issues: [],
|
|
447
|
+
skipReason: ''
|
|
448
|
+
}),
|
|
449
|
+
tddException: z.string().nullable().default(null)
|
|
450
|
+
}).default({
|
|
451
|
+
status: 'skipped',
|
|
452
|
+
regressionProof: [],
|
|
453
|
+
testQuality: [],
|
|
454
|
+
coverageAudit: {
|
|
455
|
+
status: 'skipped',
|
|
456
|
+
coveragePct: null,
|
|
457
|
+
pathMap: [],
|
|
458
|
+
gaps: [],
|
|
459
|
+
testsAdded: [],
|
|
460
|
+
e2eRequired: false,
|
|
461
|
+
evalRequired: false,
|
|
462
|
+
qualityStars: ''
|
|
463
|
+
},
|
|
464
|
+
browserEvidence: {
|
|
465
|
+
status: 'skipped',
|
|
466
|
+
mode: 'not-applicable',
|
|
467
|
+
affectedRoutes: [],
|
|
468
|
+
screenshots: [],
|
|
469
|
+
consoleErrors: [],
|
|
470
|
+
healthScore: null,
|
|
471
|
+
issues: [],
|
|
472
|
+
skipReason: ''
|
|
473
|
+
},
|
|
474
|
+
tddException: null
|
|
475
|
+
});
|
|
476
|
+
|
|
337
477
|
const ReportCardSchema = z.object({
|
|
338
478
|
changeId: ChangeIdSchema,
|
|
339
479
|
verdict: z.enum(['pass', 'fail', 'blocked']).optional(),
|
|
340
480
|
overall: z.enum(['pass', 'fail']),
|
|
341
481
|
summary: z.string().default(''),
|
|
482
|
+
specAlignment: z.enum(['pass', 'fail', 'blocked']).default('blocked'),
|
|
483
|
+
specDeltaVerified: z.boolean().default(false),
|
|
484
|
+
specSyncReady: z.boolean().default(false),
|
|
485
|
+
runtime: ReportRuntimeSchema,
|
|
486
|
+
claimEvidence: z.array(ClaimEvidenceSchema).default([]),
|
|
487
|
+
qa: QaSchema,
|
|
342
488
|
quickGates: z.array(GateResultSchema),
|
|
343
489
|
strictGates: z.array(GateResultSchema),
|
|
344
490
|
review: ReportReviewSchema,
|
|
345
491
|
blockingFindings: z.array(z.string()),
|
|
492
|
+
gaps: z.array(z.string()).default([]),
|
|
346
493
|
reroute: z.enum(['none', 'cc-do', 'cc-investigate', 'cc-plan']).default('none'),
|
|
347
494
|
timestamp: z.string().datetime()
|
|
348
495
|
});
|