@mcp-graph-workflow/mcp-graph 5.1.5 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/analyzer/ac-parser.d.ts +7 -0
- package/dist/core/analyzer/ac-parser.d.ts.map +1 -0
- package/dist/core/analyzer/ac-parser.js +67 -0
- package/dist/core/analyzer/ac-parser.js.map +1 -0
- package/dist/core/analyzer/ac-validator.d.ts +15 -0
- package/dist/core/analyzer/ac-validator.d.ts.map +1 -0
- package/dist/core/analyzer/ac-validator.js +142 -0
- package/dist/core/analyzer/ac-validator.js.map +1 -0
- package/dist/core/analyzer/definition-of-ready.d.ts +16 -0
- package/dist/core/analyzer/definition-of-ready.d.ts.map +1 -0
- package/dist/core/analyzer/definition-of-ready.js +107 -0
- package/dist/core/analyzer/definition-of-ready.js.map +1 -0
- package/dist/core/analyzer/prd-quality.d.ts +14 -0
- package/dist/core/analyzer/prd-quality.d.ts.map +1 -0
- package/dist/core/analyzer/prd-quality.js +156 -0
- package/dist/core/analyzer/prd-quality.js.map +1 -0
- package/dist/core/analyzer/risk-assessment.d.ts +11 -0
- package/dist/core/analyzer/risk-assessment.d.ts.map +1 -0
- package/dist/core/analyzer/risk-assessment.js +97 -0
- package/dist/core/analyzer/risk-assessment.js.map +1 -0
- package/dist/core/analyzer/scope-analyzer.d.ts +7 -0
- package/dist/core/analyzer/scope-analyzer.d.ts.map +1 -0
- package/dist/core/analyzer/scope-analyzer.js +99 -0
- package/dist/core/analyzer/scope-analyzer.js.map +1 -0
- package/dist/core/config/ai-memory-generator.d.ts.map +1 -1
- package/dist/core/config/ai-memory-generator.js +8 -11
- package/dist/core/config/ai-memory-generator.js.map +1 -1
- package/dist/core/context/context-assembler.d.ts +3 -0
- package/dist/core/context/context-assembler.d.ts.map +1 -1
- package/dist/core/context/context-assembler.js +5 -2
- package/dist/core/context/context-assembler.js.map +1 -1
- package/dist/core/context/rag-context.d.ts +4 -2
- package/dist/core/context/rag-context.d.ts.map +1 -1
- package/dist/core/context/rag-context.js +8 -5
- package/dist/core/context/rag-context.js.map +1 -1
- package/dist/core/designer/adr-validator.d.ts +8 -0
- package/dist/core/designer/adr-validator.d.ts.map +1 -0
- package/dist/core/designer/adr-validator.js +61 -0
- package/dist/core/designer/adr-validator.js.map +1 -0
- package/dist/core/designer/coupling-analyzer.d.ts +7 -0
- package/dist/core/designer/coupling-analyzer.d.ts.map +1 -0
- package/dist/core/designer/coupling-analyzer.js +59 -0
- package/dist/core/designer/coupling-analyzer.js.map +1 -0
- package/dist/core/designer/definition-of-ready.d.ts +8 -0
- package/dist/core/designer/definition-of-ready.d.ts.map +1 -0
- package/dist/core/designer/definition-of-ready.js +146 -0
- package/dist/core/designer/definition-of-ready.js.map +1 -0
- package/dist/core/designer/interface-checker.d.ts +7 -0
- package/dist/core/designer/interface-checker.d.ts.map +1 -0
- package/dist/core/designer/interface-checker.js +53 -0
- package/dist/core/designer/interface-checker.js.map +1 -0
- package/dist/core/designer/tech-risk-assessor.d.ts +7 -0
- package/dist/core/designer/tech-risk-assessor.d.ts.map +1 -0
- package/dist/core/designer/tech-risk-assessor.js +95 -0
- package/dist/core/designer/tech-risk-assessor.js.map +1 -0
- package/dist/core/designer/traceability-matrix.d.ts +8 -0
- package/dist/core/designer/traceability-matrix.d.ts.map +1 -0
- package/dist/core/designer/traceability-matrix.js +67 -0
- package/dist/core/designer/traceability-matrix.js.map +1 -0
- package/dist/core/events/event-types.d.ts +11 -1
- package/dist/core/events/event-types.d.ts.map +1 -1
- package/dist/core/handoff/delivery-checklist.d.ts +10 -0
- package/dist/core/handoff/delivery-checklist.d.ts.map +1 -0
- package/dist/core/handoff/delivery-checklist.js +148 -0
- package/dist/core/handoff/delivery-checklist.js.map +1 -0
- package/dist/core/handoff/doc-completeness.d.ts +7 -0
- package/dist/core/handoff/doc-completeness.d.ts.map +1 -0
- package/dist/core/handoff/doc-completeness.js +19 -0
- package/dist/core/handoff/doc-completeness.js.map +1 -0
- package/dist/core/implementer/definition-of-done.d.ts +11 -0
- package/dist/core/implementer/definition-of-done.d.ts.map +1 -0
- package/dist/core/implementer/definition-of-done.js +158 -0
- package/dist/core/implementer/definition-of-done.js.map +1 -0
- package/dist/core/implementer/sprint-progress.d.ts +11 -0
- package/dist/core/implementer/sprint-progress.d.ts.map +1 -0
- package/dist/core/implementer/sprint-progress.js +80 -0
- package/dist/core/implementer/sprint-progress.js.map +1 -0
- package/dist/core/implementer/tdd-checker.d.ts +15 -0
- package/dist/core/implementer/tdd-checker.d.ts.map +1 -0
- package/dist/core/implementer/tdd-checker.js +132 -0
- package/dist/core/implementer/tdd-checker.js.map +1 -0
- package/dist/core/listener/backlog-health.d.ts +7 -0
- package/dist/core/listener/backlog-health.d.ts.map +1 -0
- package/dist/core/listener/backlog-health.js +64 -0
- package/dist/core/listener/backlog-health.js.map +1 -0
- package/dist/core/listener/feedback-readiness.d.ts +11 -0
- package/dist/core/listener/feedback-readiness.d.ts.map +1 -0
- package/dist/core/listener/feedback-readiness.js +124 -0
- package/dist/core/listener/feedback-readiness.js.map +1 -0
- package/dist/core/planner/lifecycle-phase.d.ts.map +1 -1
- package/dist/core/planner/lifecycle-phase.js +78 -50
- package/dist/core/planner/lifecycle-phase.js.map +1 -1
- package/dist/core/rag/phase-metadata.d.ts +23 -0
- package/dist/core/rag/phase-metadata.d.ts.map +1 -0
- package/dist/core/rag/phase-metadata.js +72 -0
- package/dist/core/rag/phase-metadata.js.map +1 -0
- package/dist/core/rag/phase-summary.d.ts +17 -0
- package/dist/core/rag/phase-summary.d.ts.map +1 -0
- package/dist/core/rag/phase-summary.js +104 -0
- package/dist/core/rag/phase-summary.js.map +1 -0
- package/dist/core/rag/prd-indexer.d.ts +16 -0
- package/dist/core/rag/prd-indexer.d.ts.map +1 -0
- package/dist/core/rag/prd-indexer.js +37 -0
- package/dist/core/rag/prd-indexer.js.map +1 -0
- package/dist/core/reviewer/review-readiness.d.ts +8 -0
- package/dist/core/reviewer/review-readiness.d.ts.map +1 -0
- package/dist/core/reviewer/review-readiness.js +159 -0
- package/dist/core/reviewer/review-readiness.js.map +1 -0
- package/dist/core/store/knowledge-store.d.ts +9 -0
- package/dist/core/store/knowledge-store.d.ts.map +1 -1
- package/dist/core/store/knowledge-store.js +22 -0
- package/dist/core/store/knowledge-store.js.map +1 -1
- package/dist/core/validator/definition-of-ready.d.ts +8 -0
- package/dist/core/validator/definition-of-ready.d.ts.map +1 -0
- package/dist/core/validator/definition-of-ready.js +155 -0
- package/dist/core/validator/definition-of-ready.js.map +1 -0
- package/dist/core/validator/done-integrity-checker.d.ts +7 -0
- package/dist/core/validator/done-integrity-checker.d.ts.map +1 -0
- package/dist/core/validator/done-integrity-checker.js +38 -0
- package/dist/core/validator/done-integrity-checker.js.map +1 -0
- package/dist/core/validator/status-flow-checker.d.ts +7 -0
- package/dist/core/validator/status-flow-checker.d.ts.map +1 -0
- package/dist/core/validator/status-flow-checker.js +26 -0
- package/dist/core/validator/status-flow-checker.js.map +1 -0
- package/dist/mcp/lifecycle-wrapper.d.ts +9 -0
- package/dist/mcp/lifecycle-wrapper.d.ts.map +1 -1
- package/dist/mcp/lifecycle-wrapper.js +27 -2
- package/dist/mcp/lifecycle-wrapper.js.map +1 -1
- package/dist/mcp/tools/{stats.d.ts → analyze.d.ts} +2 -2
- package/dist/mcp/tools/analyze.d.ts.map +1 -0
- package/dist/mcp/tools/analyze.js +272 -0
- package/dist/mcp/tools/analyze.js.map +1 -0
- package/dist/mcp/tools/import-prd.d.ts.map +1 -1
- package/dist/mcp/tools/import-prd.js +15 -1
- package/dist/mcp/tools/import-prd.js.map +1 -1
- package/dist/mcp/tools/index.d.ts.map +1 -1
- package/dist/mcp/tools/index.js +6 -10
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/{velocity.d.ts → metrics.d.ts} +2 -2
- package/dist/mcp/tools/metrics.d.ts.map +1 -0
- package/dist/mcp/tools/metrics.js +69 -0
- package/dist/mcp/tools/metrics.js.map +1 -0
- package/dist/mcp/tools/next.d.ts.map +1 -1
- package/dist/mcp/tools/next.js +19 -5
- package/dist/mcp/tools/next.js.map +1 -1
- package/dist/mcp/tools/plan-sprint.d.ts.map +1 -1
- package/dist/mcp/tools/plan-sprint.js +20 -0
- package/dist/mcp/tools/plan-sprint.js.map +1 -1
- package/dist/mcp/tools/rag-context.d.ts.map +1 -1
- package/dist/mcp/tools/rag-context.js +20 -5
- package/dist/mcp/tools/rag-context.js.map +1 -1
- package/dist/mcp/tools/set-phase.d.ts.map +1 -1
- package/dist/mcp/tools/set-phase.js +16 -1
- package/dist/mcp/tools/set-phase.js.map +1 -1
- package/dist/mcp/tools/update-status.d.ts.map +1 -1
- package/dist/mcp/tools/update-status.js +21 -6
- package/dist/mcp/tools/update-status.js.map +1 -1
- package/dist/mcp/tools/{decompose.d.ts → validate-ac.d.ts} +2 -2
- package/dist/mcp/tools/validate-ac.d.ts.map +1 -0
- package/dist/mcp/tools/validate-ac.js +23 -0
- package/dist/mcp/tools/validate-ac.js.map +1 -0
- package/dist/schemas/ac-quality-schema.d.ts +90 -0
- package/dist/schemas/ac-quality-schema.d.ts.map +1 -0
- package/dist/schemas/ac-quality-schema.js +34 -0
- package/dist/schemas/ac-quality-schema.js.map +1 -0
- package/dist/schemas/analyzer-schema.d.ts +160 -0
- package/dist/schemas/analyzer-schema.d.ts.map +1 -0
- package/dist/schemas/analyzer-schema.js +74 -0
- package/dist/schemas/analyzer-schema.js.map +1 -0
- package/dist/schemas/designer-schema.d.ts +259 -0
- package/dist/schemas/designer-schema.d.ts.map +1 -0
- package/dist/schemas/designer-schema.js +102 -0
- package/dist/schemas/designer-schema.js.map +1 -0
- package/dist/schemas/handoff-schema.d.ts +49 -0
- package/dist/schemas/handoff-schema.d.ts.map +1 -0
- package/dist/schemas/handoff-schema.js +28 -0
- package/dist/schemas/handoff-schema.js.map +1 -0
- package/dist/schemas/implementer-schema.d.ts +187 -0
- package/dist/schemas/implementer-schema.d.ts.map +1 -0
- package/dist/schemas/implementer-schema.js +80 -0
- package/dist/schemas/implementer-schema.js.map +1 -0
- package/dist/schemas/knowledge.schema.d.ts +8 -0
- package/dist/schemas/knowledge.schema.d.ts.map +1 -1
- package/dist/schemas/knowledge.schema.js +1 -1
- package/dist/schemas/knowledge.schema.js.map +1 -1
- package/dist/schemas/listener-schema.d.ts +62 -0
- package/dist/schemas/listener-schema.d.ts.map +1 -0
- package/dist/schemas/listener-schema.js +35 -0
- package/dist/schemas/listener-schema.js.map +1 -0
- package/dist/schemas/reviewer-schema.d.ts +34 -0
- package/dist/schemas/reviewer-schema.d.ts.map +1 -0
- package/dist/schemas/reviewer-schema.js +17 -0
- package/dist/schemas/reviewer-schema.js.map +1 -0
- package/dist/schemas/validator-schema.d.ts +79 -0
- package/dist/schemas/validator-schema.d.ts.map +1 -0
- package/dist/schemas/validator-schema.js +43 -0
- package/dist/schemas/validator-schema.js.map +1 -0
- package/dist/web/dashboard/dist/assets/{benchmark-tab-DzYj_lJO.js → benchmark-tab-DE6hAHVG.js} +1 -1
- package/dist/web/dashboard/dist/assets/{gitnexus-tab-B16kDpcc.js → gitnexus-tab-DsBjJHx8.js} +1 -1
- package/dist/web/dashboard/dist/assets/graph-tab-C09DzeZ_.js +1 -0
- package/dist/web/dashboard/dist/assets/{graph-utils-CETPf3Qj.js → graph-utils-D4LFspTf.js} +5 -5
- package/dist/web/dashboard/dist/assets/{index-DLehETrJ.js → index-B2fTJ4AS.js} +2 -2
- package/dist/web/dashboard/dist/assets/index-CkqEqKiH.css +1 -0
- package/dist/web/dashboard/dist/assets/{insights-tab-MkpvetqF.js → insights-tab-Bm7CDckb.js} +1 -1
- package/dist/web/dashboard/dist/assets/{logs-tab-BPDyVj2B.js → logs-tab-Cxpcv_ni.js} +1 -1
- package/dist/web/dashboard/dist/assets/{prd-backlog-tab-DbnFo6Ve.js → prd-backlog-tab-X84Rj-IB.js} +1 -1
- package/dist/web/dashboard/dist/assets/{serena-tab-CLJOpG5i.js → serena-tab-BunULNvw.js} +1 -1
- package/dist/web/dashboard/dist/index.html +2 -2
- package/package.json +1 -1
- package/dist/mcp/tools/bulk-update-status.d.ts +0 -4
- package/dist/mcp/tools/bulk-update-status.d.ts.map +0 -1
- package/dist/mcp/tools/bulk-update-status.js +0 -22
- package/dist/mcp/tools/bulk-update-status.js.map +0 -1
- package/dist/mcp/tools/decompose.d.ts.map +0 -1
- package/dist/mcp/tools/decompose.js +0 -25
- package/dist/mcp/tools/decompose.js.map +0 -1
- package/dist/mcp/tools/dependencies.d.ts +0 -4
- package/dist/mcp/tools/dependencies.d.ts.map +0 -1
- package/dist/mcp/tools/dependencies.js +0 -47
- package/dist/mcp/tools/dependencies.js.map +0 -1
- package/dist/mcp/tools/stats.d.ts.map +0 -1
- package/dist/mcp/tools/stats.js +0 -46
- package/dist/mcp/tools/stats.js.map +0 -1
- package/dist/mcp/tools/velocity.d.ts.map +0 -1
- package/dist/mcp/tools/velocity.js +0 -25
- package/dist/mcp/tools/velocity.js.map +0 -1
- package/dist/web/dashboard/dist/assets/graph-tab-bgRao3Qi.js +0 -1
- package/dist/web/dashboard/dist/assets/index-D4nxPvv8.css +0 -1
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Acceptance Criteria Parser — detects GWT (Given/When/Then), checklist, and free-text formats.
|
|
3
|
+
* Supports both English and Portuguese keywords.
|
|
4
|
+
*/
|
|
5
|
+
import type { ParsedAc } from "../../schemas/ac-quality-schema.js";
|
|
6
|
+
export declare function parseAc(text: string): ParsedAc;
|
|
7
|
+
//# sourceMappingURL=ac-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ac-parser.d.ts","sourceRoot":"","sources":["../../../src/core/analyzer/ac-parser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAqB,MAAM,oCAAoC,CAAC;AAqBtF,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAgB9C"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Acceptance Criteria Parser — detects GWT (Given/When/Then), checklist, and free-text formats.
|
|
3
|
+
* Supports both English and Portuguese keywords.
|
|
4
|
+
*/
|
|
5
|
+
const GWT_KEYWORDS_EN = /^(given|when|then|and|but)\s/i;
|
|
6
|
+
const GWT_KEYWORDS_PT = /^(dado|quando|então|entao|e|mas)\s/i;
|
|
7
|
+
const CHECKLIST_PATTERN = /^[-*[\]✓✗☐☑]\s/;
|
|
8
|
+
const TESTABLE_VERBS = [
|
|
9
|
+
"deve", "should", "must", "returns", "retorna", "exibe", "displays",
|
|
10
|
+
"cria", "creates", "valida", "validates", "rejeita", "rejects",
|
|
11
|
+
"redireciona", "redirects", "envia", "sends", "salva", "saves",
|
|
12
|
+
"mostra", "shows", "permite", "allows", "bloqueia", "blocks",
|
|
13
|
+
];
|
|
14
|
+
const MEASURABLE_PATTERNS = [
|
|
15
|
+
/\d+\s*(ms|s|seg|min|%|px|kb|mb)/i,
|
|
16
|
+
/\b(menor|maior|less|more|under|over|within|antes|depois)\s+(?:que\s+)?\d+/i,
|
|
17
|
+
/\b(exatamente|exactly|igual|equals?)\s+/i,
|
|
18
|
+
/\b(status\s+\d{3}|código?\s+\d{3})/i,
|
|
19
|
+
/\b(vazio|empty|null|undefined|true|false)\b/i,
|
|
20
|
+
];
|
|
21
|
+
export function parseAc(text) {
|
|
22
|
+
const trimmed = text.trim();
|
|
23
|
+
const lines = trimmed.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
24
|
+
const format = detectFormat(lines);
|
|
25
|
+
const steps = format === "gwt" ? extractGwtSteps(lines) : undefined;
|
|
26
|
+
const isTestable = checkTestable(trimmed);
|
|
27
|
+
const isMeasurable = checkMeasurable(trimmed);
|
|
28
|
+
return {
|
|
29
|
+
raw: trimmed,
|
|
30
|
+
format,
|
|
31
|
+
steps,
|
|
32
|
+
isTestable,
|
|
33
|
+
isMeasurable,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function detectFormat(lines) {
|
|
37
|
+
const hasGwt = lines.some((l) => GWT_KEYWORDS_EN.test(l) || GWT_KEYWORDS_PT.test(l));
|
|
38
|
+
if (hasGwt)
|
|
39
|
+
return "gwt";
|
|
40
|
+
const hasChecklist = lines.some((l) => CHECKLIST_PATTERN.test(l));
|
|
41
|
+
if (hasChecklist)
|
|
42
|
+
return "checklist";
|
|
43
|
+
return "free_text";
|
|
44
|
+
}
|
|
45
|
+
function extractGwtSteps(lines) {
|
|
46
|
+
const steps = [];
|
|
47
|
+
for (const line of lines) {
|
|
48
|
+
const matchEn = line.match(/^(given|when|then|and|but)\s+(.+)$/i);
|
|
49
|
+
const matchPt = line.match(/^(dado|quando|então|entao|e|mas)\s+(.+)$/i);
|
|
50
|
+
const match = matchEn ?? matchPt;
|
|
51
|
+
if (match) {
|
|
52
|
+
steps.push({
|
|
53
|
+
keyword: match[1].toLowerCase(),
|
|
54
|
+
text: match[2].trim(),
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return steps;
|
|
59
|
+
}
|
|
60
|
+
function checkTestable(text) {
|
|
61
|
+
const lower = text.toLowerCase();
|
|
62
|
+
return TESTABLE_VERBS.some((v) => lower.includes(v));
|
|
63
|
+
}
|
|
64
|
+
function checkMeasurable(text) {
|
|
65
|
+
return MEASURABLE_PATTERNS.some((p) => p.test(text));
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=ac-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ac-parser.js","sourceRoot":"","sources":["../../../src/core/analyzer/ac-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AC Validator — INVEST check for acceptance criteria quality.
|
|
3
|
+
*
|
|
4
|
+
* Checks:
|
|
5
|
+
* - I: Independent — AC doesn't reference other ACs
|
|
6
|
+
* - N: Negotiable — not overly prescriptive (implementation details)
|
|
7
|
+
* - V: Valuable — has a clear outcome/benefit
|
|
8
|
+
* - E: Estimable — can be estimated (not too vague)
|
|
9
|
+
* - S: Small — not too many steps
|
|
10
|
+
* - T: Testable — has concrete assertions
|
|
11
|
+
*/
|
|
12
|
+
import type { GraphDocument } from "../graph/graph-types.js";
|
|
13
|
+
import type { AcQualityReport } from "../../schemas/ac-quality-schema.js";
|
|
14
|
+
export declare function validateAcQuality(doc: GraphDocument, nodeId?: string, all?: boolean): AcQualityReport;
|
|
15
|
+
//# sourceMappingURL=ac-validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ac-validator.d.ts","sourceRoot":"","sources":["../../../src/core/analyzer/ac-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAa,MAAM,yBAAyB,CAAC;AACxE,OAAO,KAAK,EAAE,eAAe,EAA6B,MAAM,oCAAoC,CAAC;AAoBrG,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,GAAG,eAAe,CAuCrG"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AC Validator — INVEST check for acceptance criteria quality.
|
|
3
|
+
*
|
|
4
|
+
* Checks:
|
|
5
|
+
* - I: Independent — AC doesn't reference other ACs
|
|
6
|
+
* - N: Negotiable — not overly prescriptive (implementation details)
|
|
7
|
+
* - V: Valuable — has a clear outcome/benefit
|
|
8
|
+
* - E: Estimable — can be estimated (not too vague)
|
|
9
|
+
* - S: Small — not too many steps
|
|
10
|
+
* - T: Testable — has concrete assertions
|
|
11
|
+
*/
|
|
12
|
+
import { parseAc } from "./ac-parser.js";
|
|
13
|
+
import { logger } from "../utils/logger.js";
|
|
14
|
+
const VAGUE_TERMS = [
|
|
15
|
+
"apropriado", "appropriate", "adequado", "adequate",
|
|
16
|
+
"rápido", "fast", "bom", "good", "bonito", "nice",
|
|
17
|
+
"eficiente", "efficient", "robusto", "robust",
|
|
18
|
+
"escalável", "scalable", "intuitivo", "intuitive",
|
|
19
|
+
"fácil", "easy", "simples", "simple",
|
|
20
|
+
"melhor", "better", "ótimo", "great",
|
|
21
|
+
"etc", "e outros", "and more",
|
|
22
|
+
];
|
|
23
|
+
const IMPLEMENTATION_KEYWORDS = [
|
|
24
|
+
"sql", "query", "endpoint", "api call", "function",
|
|
25
|
+
"class", "method", "variable", "database", "table",
|
|
26
|
+
"column", "redis", "queue", "cron",
|
|
27
|
+
];
|
|
28
|
+
export function validateAcQuality(doc, nodeId, all) {
|
|
29
|
+
const { nodes } = doc;
|
|
30
|
+
const targetNodes = selectTargetNodes(nodes, nodeId, all);
|
|
31
|
+
const reports = [];
|
|
32
|
+
for (const node of targetNodes) {
|
|
33
|
+
const acs = node.acceptanceCriteria ?? [];
|
|
34
|
+
if (acs.length === 0)
|
|
35
|
+
continue;
|
|
36
|
+
const parsedAcs = acs.map((ac) => parseAc(ac));
|
|
37
|
+
const investChecks = runInvestChecks(node, parsedAcs);
|
|
38
|
+
const vagueTerms = detectVagueTerms(acs);
|
|
39
|
+
const passedChecks = investChecks.filter((c) => c.passed).length;
|
|
40
|
+
const score = investChecks.length > 0
|
|
41
|
+
? Math.round((passedChecks / investChecks.length) * 100)
|
|
42
|
+
: 0;
|
|
43
|
+
reports.push({
|
|
44
|
+
nodeId: node.id,
|
|
45
|
+
title: node.title,
|
|
46
|
+
score,
|
|
47
|
+
parsedAcs,
|
|
48
|
+
investChecks,
|
|
49
|
+
vagueTerms,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
const overallScore = reports.length > 0
|
|
53
|
+
? Math.round(reports.reduce((sum, r) => sum + r.score, 0) / reports.length)
|
|
54
|
+
: 0;
|
|
55
|
+
const summary = reports.length > 0
|
|
56
|
+
? `AC Quality: ${overallScore}/100 across ${reports.length} nodes. ${reports.filter((r) => r.score >= 80).length} nodes with good AC quality.`
|
|
57
|
+
: "Nenhum node com acceptance criteria encontrado.";
|
|
58
|
+
logger.info("ac-validator", { nodeCount: reports.length, overallScore });
|
|
59
|
+
return { nodes: reports, overallScore, summary };
|
|
60
|
+
}
|
|
61
|
+
function selectTargetNodes(nodes, nodeId, all) {
|
|
62
|
+
if (nodeId) {
|
|
63
|
+
const node = nodes.find((n) => n.id === nodeId);
|
|
64
|
+
return node ? [node] : [];
|
|
65
|
+
}
|
|
66
|
+
if (all) {
|
|
67
|
+
return nodes.filter((n) => (n.type === "task" || n.type === "subtask") &&
|
|
68
|
+
n.acceptanceCriteria &&
|
|
69
|
+
n.acceptanceCriteria.length > 0);
|
|
70
|
+
}
|
|
71
|
+
// Default: all tasks with AC
|
|
72
|
+
return nodes.filter((n) => (n.type === "task" || n.type === "subtask") &&
|
|
73
|
+
n.acceptanceCriteria &&
|
|
74
|
+
n.acceptanceCriteria.length > 0);
|
|
75
|
+
}
|
|
76
|
+
function runInvestChecks(node, parsedAcs) {
|
|
77
|
+
const checks = [];
|
|
78
|
+
const allText = (node.acceptanceCriteria ?? []).join(" ").toLowerCase();
|
|
79
|
+
// I — Independent
|
|
80
|
+
const hasInternalRefs = /ac\s*\d|critério\s*\d|criterion\s*\d/i.test(allText);
|
|
81
|
+
checks.push({
|
|
82
|
+
criterion: "Independent",
|
|
83
|
+
passed: !hasInternalRefs,
|
|
84
|
+
details: hasInternalRefs
|
|
85
|
+
? "AC referencia outros critérios — deve ser independente"
|
|
86
|
+
: "AC é independente",
|
|
87
|
+
});
|
|
88
|
+
// N — Negotiable (not implementation-specific)
|
|
89
|
+
const hasImpl = IMPLEMENTATION_KEYWORDS.some((k) => allText.includes(k));
|
|
90
|
+
checks.push({
|
|
91
|
+
criterion: "Negotiable",
|
|
92
|
+
passed: !hasImpl,
|
|
93
|
+
details: hasImpl
|
|
94
|
+
? "AC contém detalhes de implementação — deve descrever comportamento, não solução"
|
|
95
|
+
: "AC descreve comportamento, não implementação",
|
|
96
|
+
});
|
|
97
|
+
// V — Valuable (has clear outcome)
|
|
98
|
+
const hasOutcome = parsedAcs.some((p) => p.isTestable);
|
|
99
|
+
checks.push({
|
|
100
|
+
criterion: "Valuable",
|
|
101
|
+
passed: hasOutcome,
|
|
102
|
+
details: hasOutcome
|
|
103
|
+
? "AC descreve resultado observável"
|
|
104
|
+
: "AC não descreve resultado claro — adicionar verbo de ação concreto",
|
|
105
|
+
});
|
|
106
|
+
// E — Estimable (not too vague)
|
|
107
|
+
const vagueCount = detectVagueTerms(node.acceptanceCriteria ?? []).length;
|
|
108
|
+
const isEstimable = vagueCount <= 1;
|
|
109
|
+
checks.push({
|
|
110
|
+
criterion: "Estimable",
|
|
111
|
+
passed: isEstimable,
|
|
112
|
+
details: isEstimable
|
|
113
|
+
? "AC é específico o suficiente para estimar"
|
|
114
|
+
: `AC contém ${vagueCount} termos vagos — quantificar critérios`,
|
|
115
|
+
});
|
|
116
|
+
// S — Small (not too many steps)
|
|
117
|
+
const totalSteps = parsedAcs.reduce((sum, p) => sum + (p.steps?.length ?? 1), 0);
|
|
118
|
+
const isSmall = totalSteps <= 10;
|
|
119
|
+
checks.push({
|
|
120
|
+
criterion: "Small",
|
|
121
|
+
passed: isSmall,
|
|
122
|
+
details: isSmall
|
|
123
|
+
? `${totalSteps} steps — tamanho adequado`
|
|
124
|
+
: `${totalSteps} steps — considerar dividir em ACs menores`,
|
|
125
|
+
});
|
|
126
|
+
// T — Testable
|
|
127
|
+
const testableCount = parsedAcs.filter((p) => p.isTestable).length;
|
|
128
|
+
const isTestable = testableCount > 0 && testableCount >= parsedAcs.length * 0.5;
|
|
129
|
+
checks.push({
|
|
130
|
+
criterion: "Testable",
|
|
131
|
+
passed: isTestable,
|
|
132
|
+
details: isTestable
|
|
133
|
+
? `${testableCount}/${parsedAcs.length} ACs testáveis`
|
|
134
|
+
: `Apenas ${testableCount}/${parsedAcs.length} ACs são testáveis — adicionar assertions concretas`,
|
|
135
|
+
});
|
|
136
|
+
return checks;
|
|
137
|
+
}
|
|
138
|
+
function detectVagueTerms(acs) {
|
|
139
|
+
const allText = acs.join(" ").toLowerCase();
|
|
140
|
+
return VAGUE_TERMS.filter((term) => allText.includes(term));
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=ac-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ac-validator.js","sourceRoot":"","sources":["../../../src/core/analyzer/ac-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Definition of Ready — gate checklist for ANALYZE → DESIGN transition.
|
|
3
|
+
*
|
|
4
|
+
* Checks:
|
|
5
|
+
* 1. ≥1 epic or requirement
|
|
6
|
+
* 2. Tasks with acceptance criteria
|
|
7
|
+
* 3. No orphan nodes
|
|
8
|
+
* 4. No dependency cycles
|
|
9
|
+
* 5. ≥1 constraint
|
|
10
|
+
* 6. ≥1 risk identified
|
|
11
|
+
* 7. PRD quality score ≥ 60
|
|
12
|
+
*/
|
|
13
|
+
import type { GraphDocument } from "../graph/graph-types.js";
|
|
14
|
+
import type { ReadinessReport } from "../../schemas/analyzer-schema.js";
|
|
15
|
+
export declare function checkDefinitionOfReady(doc: GraphDocument): ReadinessReport;
|
|
16
|
+
//# sourceMappingURL=definition-of-ready.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definition-of-ready.d.ts","sourceRoot":"","sources":["../../../src/core/analyzer/definition-of-ready.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAkB,MAAM,kCAAkC,CAAC;AAKxF,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,aAAa,GAAG,eAAe,CA8F1E"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Definition of Ready — gate checklist for ANALYZE → DESIGN transition.
|
|
3
|
+
*
|
|
4
|
+
* Checks:
|
|
5
|
+
* 1. ≥1 epic or requirement
|
|
6
|
+
* 2. Tasks with acceptance criteria
|
|
7
|
+
* 3. No orphan nodes
|
|
8
|
+
* 4. No dependency cycles
|
|
9
|
+
* 5. ≥1 constraint
|
|
10
|
+
* 6. ≥1 risk identified
|
|
11
|
+
* 7. PRD quality score ≥ 60
|
|
12
|
+
*/
|
|
13
|
+
import { analyzeScope } from "./scope-analyzer.js";
|
|
14
|
+
import { analyzePrdQuality } from "./prd-quality.js";
|
|
15
|
+
import { logger } from "../utils/logger.js";
|
|
16
|
+
export function checkDefinitionOfReady(doc) {
|
|
17
|
+
const { nodes } = doc;
|
|
18
|
+
const checks = [];
|
|
19
|
+
const blockers = [];
|
|
20
|
+
const warnings = [];
|
|
21
|
+
// 1. Has epics or requirements
|
|
22
|
+
const hasEpicOrReq = nodes.some((n) => n.type === "epic" || n.type === "requirement");
|
|
23
|
+
checks.push({
|
|
24
|
+
name: "has_requirements",
|
|
25
|
+
passed: hasEpicOrReq,
|
|
26
|
+
details: hasEpicOrReq
|
|
27
|
+
? `${nodes.filter((n) => n.type === "epic" || n.type === "requirement").length} requirements/epics encontrados`
|
|
28
|
+
: "Nenhum epic ou requirement definido",
|
|
29
|
+
});
|
|
30
|
+
if (!hasEpicOrReq)
|
|
31
|
+
blockers.push("Criar pelo menos 1 epic ou requirement");
|
|
32
|
+
// 2. Tasks with AC
|
|
33
|
+
const tasks = nodes.filter((n) => n.type === "task" || n.type === "subtask");
|
|
34
|
+
const acNodes = nodes.filter((n) => n.type === "acceptance_criteria");
|
|
35
|
+
const tasksWithAc = tasks.filter((n) => n.acceptanceCriteria && n.acceptanceCriteria.length > 0);
|
|
36
|
+
const hasAc = tasksWithAc.length > 0 || acNodes.length > 0;
|
|
37
|
+
checks.push({
|
|
38
|
+
name: "has_acceptance_criteria",
|
|
39
|
+
passed: hasAc,
|
|
40
|
+
details: hasAc
|
|
41
|
+
? `${tasksWithAc.length} tasks com AC, ${acNodes.length} AC nodes`
|
|
42
|
+
: "Nenhum acceptance criteria definido",
|
|
43
|
+
});
|
|
44
|
+
if (!hasAc && tasks.length > 0)
|
|
45
|
+
warnings.push("Definir acceptance criteria para as tasks");
|
|
46
|
+
// 3. No orphans
|
|
47
|
+
const scope = analyzeScope(doc);
|
|
48
|
+
const noOrphans = scope.orphans.length === 0;
|
|
49
|
+
checks.push({
|
|
50
|
+
name: "no_orphans",
|
|
51
|
+
passed: noOrphans,
|
|
52
|
+
details: noOrphans
|
|
53
|
+
? "Nenhum nó órfão detectado"
|
|
54
|
+
: `${scope.orphans.length} nós órfãos: ${scope.orphans.map((o) => o.id).join(", ")}`,
|
|
55
|
+
});
|
|
56
|
+
if (!noOrphans)
|
|
57
|
+
warnings.push(`Resolver ${scope.orphans.length} nós órfãos`);
|
|
58
|
+
// 4. No cycles
|
|
59
|
+
const noCycles = scope.cycles.length === 0;
|
|
60
|
+
checks.push({
|
|
61
|
+
name: "no_cycles",
|
|
62
|
+
passed: noCycles,
|
|
63
|
+
details: noCycles
|
|
64
|
+
? "Nenhum ciclo de dependência"
|
|
65
|
+
: `${scope.cycles.length} ciclos detectados`,
|
|
66
|
+
});
|
|
67
|
+
if (!noCycles)
|
|
68
|
+
blockers.push("Resolver ciclos de dependência");
|
|
69
|
+
// 5. Has constraints
|
|
70
|
+
const hasConstraints = nodes.some((n) => n.type === "constraint");
|
|
71
|
+
checks.push({
|
|
72
|
+
name: "has_constraints",
|
|
73
|
+
passed: hasConstraints,
|
|
74
|
+
details: hasConstraints
|
|
75
|
+
? `${nodes.filter((n) => n.type === "constraint").length} constraints definidas`
|
|
76
|
+
: "Nenhuma constraint definida",
|
|
77
|
+
});
|
|
78
|
+
if (!hasConstraints)
|
|
79
|
+
warnings.push("Definir restrições técnicas/negócio");
|
|
80
|
+
// 6. Has risks
|
|
81
|
+
const hasRisks = nodes.some((n) => n.type === "risk");
|
|
82
|
+
checks.push({
|
|
83
|
+
name: "has_risks",
|
|
84
|
+
passed: hasRisks,
|
|
85
|
+
details: hasRisks
|
|
86
|
+
? `${nodes.filter((n) => n.type === "risk").length} riscos identificados`
|
|
87
|
+
: "Nenhum risco identificado",
|
|
88
|
+
});
|
|
89
|
+
if (!hasRisks)
|
|
90
|
+
warnings.push("Identificar riscos do projeto");
|
|
91
|
+
// 7. PRD quality score
|
|
92
|
+
const prdQuality = analyzePrdQuality(doc);
|
|
93
|
+
const qualityPass = prdQuality.score >= 60;
|
|
94
|
+
checks.push({
|
|
95
|
+
name: "prd_quality_score",
|
|
96
|
+
passed: qualityPass,
|
|
97
|
+
details: `PRD score: ${prdQuality.score}/100 (${prdQuality.grade}) — mínimo: 60`,
|
|
98
|
+
});
|
|
99
|
+
if (!qualityPass)
|
|
100
|
+
blockers.push(`PRD quality score ${prdQuality.score} < 60 mínimo`);
|
|
101
|
+
const readyForNextPhase = blockers.length === 0 && checks.filter((c) => !c.passed).length <= 2;
|
|
102
|
+
const passedCount = checks.filter((c) => c.passed).length;
|
|
103
|
+
const summary = `Definition of Ready: ${passedCount}/${checks.length} checks passed. ${readyForNextPhase ? "Ready para DESIGN." : "Não atende os critérios."}`;
|
|
104
|
+
logger.info("definition-of-ready", { passedCount, total: checks.length, ready: readyForNextPhase });
|
|
105
|
+
return { readyForNextPhase, checks, blockers, warnings, summary };
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=definition-of-ready.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definition-of-ready.js","sourceRoot":"","sources":["../../../src/core/analyzer/definition-of-ready.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRD Quality Analyzer — scores a project graph for completeness and quality.
|
|
3
|
+
*
|
|
4
|
+
* Scoring weights:
|
|
5
|
+
* - Requirements: 25% (epics + requirements present and with descriptions)
|
|
6
|
+
* - Acceptance Criteria: 25% (tasks have AC defined)
|
|
7
|
+
* - Tasks: 20% (tasks exist, are decomposed, have estimates)
|
|
8
|
+
* - Risks: 15% (risk nodes present and assessed)
|
|
9
|
+
* - Constraints: 15% (constraint nodes defined)
|
|
10
|
+
*/
|
|
11
|
+
import type { GraphDocument } from "../graph/graph-types.js";
|
|
12
|
+
import type { PrdQualityReport } from "../../schemas/analyzer-schema.js";
|
|
13
|
+
export declare function analyzePrdQuality(doc: GraphDocument): PrdQualityReport;
|
|
14
|
+
//# sourceMappingURL=prd-quality.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prd-quality.d.ts","sourceRoot":"","sources":["../../../src/core/analyzer/prd-quality.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAsD,MAAM,kCAAkC,CAAC;AA0B7H,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,aAAa,GAAG,gBAAgB,CAwItE"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PRD Quality Analyzer — scores a project graph for completeness and quality.
|
|
3
|
+
*
|
|
4
|
+
* Scoring weights:
|
|
5
|
+
* - Requirements: 25% (epics + requirements present and with descriptions)
|
|
6
|
+
* - Acceptance Criteria: 25% (tasks have AC defined)
|
|
7
|
+
* - Tasks: 20% (tasks exist, are decomposed, have estimates)
|
|
8
|
+
* - Risks: 15% (risk nodes present and assessed)
|
|
9
|
+
* - Constraints: 15% (constraint nodes defined)
|
|
10
|
+
*/
|
|
11
|
+
import { logger } from "../utils/logger.js";
|
|
12
|
+
const SECTION_WEIGHTS = {
|
|
13
|
+
requirements: 25,
|
|
14
|
+
acceptanceCriteria: 25,
|
|
15
|
+
tasks: 20,
|
|
16
|
+
risks: 15,
|
|
17
|
+
constraints: 15,
|
|
18
|
+
};
|
|
19
|
+
function scoreToGrade(score) {
|
|
20
|
+
if (score >= 90)
|
|
21
|
+
return "A";
|
|
22
|
+
if (score >= 75)
|
|
23
|
+
return "B";
|
|
24
|
+
if (score >= 60)
|
|
25
|
+
return "C";
|
|
26
|
+
if (score >= 40)
|
|
27
|
+
return "D";
|
|
28
|
+
return "F";
|
|
29
|
+
}
|
|
30
|
+
function assessQuality(ratio) {
|
|
31
|
+
if (ratio <= 0)
|
|
32
|
+
return "missing";
|
|
33
|
+
if (ratio < 0.4)
|
|
34
|
+
return "weak";
|
|
35
|
+
if (ratio < 0.7)
|
|
36
|
+
return "adequate";
|
|
37
|
+
return "strong";
|
|
38
|
+
}
|
|
39
|
+
export function analyzePrdQuality(doc) {
|
|
40
|
+
const { nodes } = doc;
|
|
41
|
+
const sections = [];
|
|
42
|
+
// ── Requirements (epics + requirements) ──
|
|
43
|
+
const reqNodes = nodes.filter((n) => n.type === "epic" || n.type === "requirement");
|
|
44
|
+
const reqWithDesc = reqNodes.filter((n) => n.description && n.description.trim().length > 0);
|
|
45
|
+
const reqRatio = reqNodes.length > 0 ? reqWithDesc.length / reqNodes.length : 0;
|
|
46
|
+
const reqQuality = assessQuality(reqNodes.length > 0 ? (reqNodes.length >= 1 ? Math.min(1, reqRatio + 0.3) : 0) : 0);
|
|
47
|
+
const reqIssues = [];
|
|
48
|
+
const reqSuggestions = [];
|
|
49
|
+
if (reqNodes.length === 0) {
|
|
50
|
+
reqIssues.push("Nenhum epic ou requirement definido");
|
|
51
|
+
reqSuggestions.push("Criar pelo menos 1 epic descrevendo o escopo do projeto");
|
|
52
|
+
}
|
|
53
|
+
if (reqNodes.length > 0 && reqWithDesc.length < reqNodes.length) {
|
|
54
|
+
reqIssues.push(`${reqNodes.length - reqWithDesc.length} requirements sem descrição`);
|
|
55
|
+
reqSuggestions.push("Adicionar descrição a todos os requirements para clareza");
|
|
56
|
+
}
|
|
57
|
+
sections.push({
|
|
58
|
+
name: "requirements",
|
|
59
|
+
quality: reqQuality,
|
|
60
|
+
issues: reqIssues,
|
|
61
|
+
suggestions: reqSuggestions,
|
|
62
|
+
});
|
|
63
|
+
// ── Acceptance Criteria ──
|
|
64
|
+
const tasks = nodes.filter((n) => n.type === "task" || n.type === "subtask");
|
|
65
|
+
const acNodes = nodes.filter((n) => n.type === "acceptance_criteria");
|
|
66
|
+
const tasksWithAc = tasks.filter((n) => n.acceptanceCriteria && n.acceptanceCriteria.length > 0);
|
|
67
|
+
const acTotal = tasksWithAc.length + acNodes.length;
|
|
68
|
+
const acRatio = tasks.length > 0 ? Math.min(1, acTotal / tasks.length) : (acNodes.length > 0 ? 0.5 : 0);
|
|
69
|
+
const acQuality = assessQuality(acRatio);
|
|
70
|
+
const acIssues = [];
|
|
71
|
+
const acSuggestions = [];
|
|
72
|
+
if (acTotal === 0) {
|
|
73
|
+
acIssues.push("Nenhum critério de aceitação definido");
|
|
74
|
+
acSuggestions.push("Definir AC para cada task (Given/When/Then ou checklist)");
|
|
75
|
+
}
|
|
76
|
+
else if (tasks.length > 0 && tasksWithAc.length < tasks.length && acNodes.length === 0) {
|
|
77
|
+
acIssues.push(`${tasks.length - tasksWithAc.length} tasks sem acceptance criteria`);
|
|
78
|
+
acSuggestions.push("Garantir que toda task tenha AC testável");
|
|
79
|
+
}
|
|
80
|
+
sections.push({
|
|
81
|
+
name: "acceptanceCriteria",
|
|
82
|
+
quality: acQuality,
|
|
83
|
+
issues: acIssues,
|
|
84
|
+
suggestions: acSuggestions,
|
|
85
|
+
});
|
|
86
|
+
// ── Tasks ──
|
|
87
|
+
const tasksWithEstimate = tasks.filter((n) => n.estimateMinutes || n.xpSize);
|
|
88
|
+
const taskRatio = tasks.length > 0 ? Math.min(1, tasksWithEstimate.length / tasks.length) : 0;
|
|
89
|
+
const taskQuality = assessQuality(tasks.length > 0 ? Math.min(1, (tasks.length >= 1 ? 0.5 : 0) + taskRatio * 0.5) : 0);
|
|
90
|
+
const taskIssues = [];
|
|
91
|
+
const taskSuggestions = [];
|
|
92
|
+
if (tasks.length === 0) {
|
|
93
|
+
taskIssues.push("Nenhuma task definida");
|
|
94
|
+
taskSuggestions.push("Decompor requirements em tasks executáveis");
|
|
95
|
+
}
|
|
96
|
+
if (tasks.length > 0 && tasksWithEstimate.length < tasks.length) {
|
|
97
|
+
taskIssues.push(`${tasks.length - tasksWithEstimate.length} tasks sem estimativa`);
|
|
98
|
+
taskSuggestions.push("Adicionar xpSize ou estimateMinutes a todas as tasks");
|
|
99
|
+
}
|
|
100
|
+
sections.push({
|
|
101
|
+
name: "tasks",
|
|
102
|
+
quality: taskQuality,
|
|
103
|
+
issues: taskIssues,
|
|
104
|
+
suggestions: taskSuggestions,
|
|
105
|
+
});
|
|
106
|
+
// ── Risks ──
|
|
107
|
+
const riskNodes = nodes.filter((n) => n.type === "risk");
|
|
108
|
+
const riskQuality = assessQuality(riskNodes.length > 0 ? Math.min(1, riskNodes.length / 2) : 0);
|
|
109
|
+
const riskIssues = [];
|
|
110
|
+
const riskSuggestions = [];
|
|
111
|
+
if (riskNodes.length === 0) {
|
|
112
|
+
riskIssues.push("Nenhum risco identificado");
|
|
113
|
+
riskSuggestions.push("Identificar pelo menos 1-2 riscos técnicos ou de negócio");
|
|
114
|
+
}
|
|
115
|
+
sections.push({
|
|
116
|
+
name: "risks",
|
|
117
|
+
quality: riskQuality,
|
|
118
|
+
issues: riskIssues,
|
|
119
|
+
suggestions: riskSuggestions,
|
|
120
|
+
});
|
|
121
|
+
// ── Constraints ──
|
|
122
|
+
const constraintNodes = nodes.filter((n) => n.type === "constraint");
|
|
123
|
+
const constraintQuality = assessQuality(constraintNodes.length > 0 ? Math.min(1, constraintNodes.length / 2) : 0);
|
|
124
|
+
const constraintIssues = [];
|
|
125
|
+
const constraintSuggestions = [];
|
|
126
|
+
if (constraintNodes.length === 0) {
|
|
127
|
+
constraintIssues.push("Nenhuma restrição definida");
|
|
128
|
+
constraintSuggestions.push("Definir restrições técnicas (stack, performance, compatibilidade)");
|
|
129
|
+
}
|
|
130
|
+
sections.push({
|
|
131
|
+
name: "constraints",
|
|
132
|
+
quality: constraintQuality,
|
|
133
|
+
issues: constraintIssues,
|
|
134
|
+
suggestions: constraintSuggestions,
|
|
135
|
+
});
|
|
136
|
+
// ── Final score ──
|
|
137
|
+
const qualityToScore = {
|
|
138
|
+
missing: 0,
|
|
139
|
+
weak: 33,
|
|
140
|
+
adequate: 66,
|
|
141
|
+
strong: 100,
|
|
142
|
+
};
|
|
143
|
+
let totalScore = 0;
|
|
144
|
+
for (const section of sections) {
|
|
145
|
+
const weight = SECTION_WEIGHTS[section.name] ?? 0;
|
|
146
|
+
totalScore += (qualityToScore[section.quality] * weight) / 100;
|
|
147
|
+
}
|
|
148
|
+
const score = Math.round(totalScore);
|
|
149
|
+
const grade = scoreToGrade(score);
|
|
150
|
+
const hasCriticalMissing = sections.some((s) => s.quality === "missing" && (s.name === "requirements" || s.name === "acceptanceCriteria"));
|
|
151
|
+
const readyForDesign = score >= 60 && !hasCriticalMissing;
|
|
152
|
+
const summary = `PRD Quality: ${grade} (${score}/100). ${readyForDesign ? "Pronto para DESIGN." : "Não atende os critérios mínimos para avançar."}`;
|
|
153
|
+
logger.info("prd-quality", { score, grade, readyForDesign });
|
|
154
|
+
return { score, grade, sections, readyForDesign, summary };
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=prd-quality.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prd-quality.js","sourceRoot":"","sources":["../../../src/core/analyzer/prd-quality.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Risk Assessment — evaluates risk nodes using probability × impact scoring.
|
|
3
|
+
*
|
|
4
|
+
* Heuristics:
|
|
5
|
+
* - Keywords in title/description drive automatic probability/impact scoring
|
|
6
|
+
* - Mitigation status: mitigated if child task is done, partial if in_progress
|
|
7
|
+
*/
|
|
8
|
+
import type { GraphDocument } from "../graph/graph-types.js";
|
|
9
|
+
import type { RiskMatrix } from "../../schemas/analyzer-schema.js";
|
|
10
|
+
export declare function assessRisks(doc: GraphDocument): RiskMatrix;
|
|
11
|
+
//# sourceMappingURL=risk-assessment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"risk-assessment.d.ts","sourceRoot":"","sources":["../../../src/core/analyzer/risk-assessment.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAwB,MAAM,kCAAkC,CAAC;AA2BzF,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,UAAU,CAsD1D"}
|