specforge-mcp 0.9.0 → 0.11.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/engine/actuals/backfill.d.ts +14 -0
- package/dist/engine/actuals/backfill.d.ts.map +1 -0
- package/dist/engine/actuals/backfill.js +62 -0
- package/dist/engine/actuals/backfill.js.map +1 -0
- package/dist/engine/actuals/consolidator.d.ts +12 -0
- package/dist/engine/actuals/consolidator.d.ts.map +1 -0
- package/dist/engine/actuals/consolidator.js +54 -0
- package/dist/engine/actuals/consolidator.js.map +1 -0
- package/dist/engine/actuals/git-analyzer.d.ts +23 -0
- package/dist/engine/actuals/git-analyzer.d.ts.map +1 -0
- package/dist/engine/actuals/git-analyzer.js +169 -0
- package/dist/engine/actuals/git-analyzer.js.map +1 -0
- package/dist/engine/actuals/index.d.ts +5 -0
- package/dist/engine/actuals/index.d.ts.map +1 -0
- package/dist/engine/actuals/index.js +7 -0
- package/dist/engine/actuals/index.js.map +1 -0
- package/dist/engine/actuals/wip-tracker.d.ts +25 -0
- package/dist/engine/actuals/wip-tracker.d.ts.map +1 -0
- package/dist/engine/actuals/wip-tracker.js +71 -0
- package/dist/engine/actuals/wip-tracker.js.map +1 -0
- package/dist/engine/doc-generator/executive-summary/data-extractors.d.ts +12 -0
- package/dist/engine/doc-generator/executive-summary/data-extractors.d.ts.map +1 -0
- package/dist/engine/doc-generator/executive-summary/data-extractors.js +96 -0
- package/dist/engine/doc-generator/executive-summary/data-extractors.js.map +1 -0
- package/dist/engine/doc-generator/executive-summary/executive-summary-generator.d.ts +7 -0
- package/dist/engine/doc-generator/executive-summary/executive-summary-generator.d.ts.map +1 -0
- package/dist/engine/doc-generator/executive-summary/executive-summary-generator.js +38 -0
- package/dist/engine/doc-generator/executive-summary/executive-summary-generator.js.map +1 -0
- package/dist/engine/doc-generator/executive-summary/html-template.d.ts +3 -0
- package/dist/engine/doc-generator/executive-summary/html-template.d.ts.map +1 -0
- package/dist/engine/doc-generator/executive-summary/html-template.js +53 -0
- package/dist/engine/doc-generator/executive-summary/html-template.js.map +1 -0
- package/dist/engine/doc-generator/executive-summary/index.d.ts +2 -0
- package/dist/engine/doc-generator/executive-summary/index.d.ts.map +1 -0
- package/dist/engine/doc-generator/executive-summary/index.js +3 -0
- package/dist/engine/doc-generator/executive-summary/index.js.map +1 -0
- package/dist/engine/doc-generator/executive-summary/section-builders.d.ts +18 -0
- package/dist/engine/doc-generator/executive-summary/section-builders.d.ts.map +1 -0
- package/dist/engine/doc-generator/executive-summary/section-builders.js +152 -0
- package/dist/engine/doc-generator/executive-summary/section-builders.js.map +1 -0
- package/dist/engine/doc-generator/executive-summary/svg-diagrams.d.ts +8 -0
- package/dist/engine/doc-generator/executive-summary/svg-diagrams.d.ts.map +1 -0
- package/dist/engine/doc-generator/executive-summary/svg-diagrams.js +124 -0
- package/dist/engine/doc-generator/executive-summary/svg-diagrams.js.map +1 -0
- package/dist/engine/doc-generator.d.ts.map +1 -1
- package/dist/engine/doc-generator.js +2 -0
- package/dist/engine/doc-generator.js.map +1 -1
- package/dist/engine/risk-analyzer/approach-analyzer.d.ts +6 -0
- package/dist/engine/risk-analyzer/approach-analyzer.d.ts.map +1 -0
- package/dist/engine/risk-analyzer/approach-analyzer.js +86 -0
- package/dist/engine/risk-analyzer/approach-analyzer.js.map +1 -0
- package/dist/engine/risk-analyzer/complexity-calculator.d.ts +6 -0
- package/dist/engine/risk-analyzer/complexity-calculator.d.ts.map +1 -0
- package/dist/engine/risk-analyzer/complexity-calculator.js +110 -0
- package/dist/engine/risk-analyzer/complexity-calculator.js.map +1 -0
- package/dist/engine/risk-analyzer/confidence-scorer.d.ts +7 -0
- package/dist/engine/risk-analyzer/confidence-scorer.d.ts.map +1 -0
- package/dist/engine/risk-analyzer/confidence-scorer.js +113 -0
- package/dist/engine/risk-analyzer/confidence-scorer.js.map +1 -0
- package/dist/engine/risk-analyzer/index.d.ts +6 -0
- package/dist/engine/risk-analyzer/index.d.ts.map +1 -0
- package/dist/engine/risk-analyzer/index.js +7 -0
- package/dist/engine/risk-analyzer/index.js.map +1 -0
- package/dist/engine/risk-analyzer/risk-generator.d.ts +6 -0
- package/dist/engine/risk-analyzer/risk-generator.d.ts.map +1 -0
- package/dist/engine/risk-analyzer/risk-generator.js +94 -0
- package/dist/engine/risk-analyzer/risk-generator.js.map +1 -0
- package/dist/engine/risk-analyzer/tradeoff-detector.d.ts +6 -0
- package/dist/engine/risk-analyzer/tradeoff-detector.d.ts.map +1 -0
- package/dist/engine/risk-analyzer/tradeoff-detector.js +128 -0
- package/dist/engine/risk-analyzer/tradeoff-detector.js.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/storage/risk-store.d.ts +16 -0
- package/dist/storage/risk-store.d.ts.map +1 -0
- package/dist/storage/risk-store.js +53 -0
- package/dist/storage/risk-store.js.map +1 -0
- package/dist/tools/schemas/lifecycle.d.ts +2 -0
- package/dist/tools/schemas/lifecycle.d.ts.map +1 -1
- package/dist/tools/schemas/lifecycle.js +3 -1
- package/dist/tools/schemas/lifecycle.js.map +1 -1
- package/dist/types/actuals-tracking.d.ts +51 -0
- package/dist/types/actuals-tracking.d.ts.map +1 -0
- package/dist/types/actuals-tracking.js +2 -0
- package/dist/types/actuals-tracking.js.map +1 -0
- package/dist/types/common/tech-enums.d.ts +1 -1
- package/dist/types/common/tech-enums.d.ts.map +1 -1
- package/dist/types/docs.d.ts +44 -1
- package/dist/types/docs.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/risk.d.ts +90 -0
- package/dist/types/risk.d.ts.map +1 -0
- package/dist/types/risk.js +2 -0
- package/dist/types/risk.js.map +1 -0
- package/package.json +1 -1
- package/src/i18n/messages/en.json +3 -3
- package/src/i18n/messages/es.json +3 -3
- package/src/i18n/messages/pt.json +3 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"complexity-calculator.d.ts","sourceRoot":"","sources":["../../../src/engine/risk-analyzer/complexity-calculator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,mBAAmB,EACnB,gBAAgB,EAGjB,MAAM,sBAAsB,CAAC;AAiG9B;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,mBAAmB,GAAG,gBAAgB,CAiBpF"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
function technicalScore(ctx) {
|
|
2
|
+
const score = ctx.difficulty;
|
|
3
|
+
return {
|
|
4
|
+
dimension: 'technical',
|
|
5
|
+
score,
|
|
6
|
+
justification: `Difficulty level ${score}/5 maps directly to technical complexity`,
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
function integrationScore(ctx) {
|
|
10
|
+
let base;
|
|
11
|
+
const f = ctx.fileCount;
|
|
12
|
+
if (f <= 3) {
|
|
13
|
+
base = 1;
|
|
14
|
+
}
|
|
15
|
+
else if (f <= 6) {
|
|
16
|
+
base = 2;
|
|
17
|
+
}
|
|
18
|
+
else if (f <= 10) {
|
|
19
|
+
base = 3;
|
|
20
|
+
}
|
|
21
|
+
else if (f <= 15) {
|
|
22
|
+
base = 4;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
base = 5;
|
|
26
|
+
}
|
|
27
|
+
const depFactor = ctx.dependencyCount > 5 ? 1 : 0;
|
|
28
|
+
const score = Math.min(base + depFactor, 5);
|
|
29
|
+
return {
|
|
30
|
+
dimension: 'integration',
|
|
31
|
+
score,
|
|
32
|
+
justification: `${f} files (base ${base}) + dependency factor ${depFactor}`,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function testingScore(ctx) {
|
|
36
|
+
const scopeMap = {
|
|
37
|
+
trivial: 1,
|
|
38
|
+
feature: 2,
|
|
39
|
+
'cross-module': 4,
|
|
40
|
+
architectural: 5,
|
|
41
|
+
};
|
|
42
|
+
const score = scopeMap[ctx.scope] ?? 2;
|
|
43
|
+
return {
|
|
44
|
+
dimension: 'testing',
|
|
45
|
+
score,
|
|
46
|
+
justification: `Scope "${ctx.scope}" requires testing at level ${score}/5`,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function organizationalScore(ctx) {
|
|
50
|
+
const hasBreaking = ctx.tags.includes('breaking-change') || ctx.tags.includes('migration');
|
|
51
|
+
const score = hasBreaking ? 4 : 2;
|
|
52
|
+
return {
|
|
53
|
+
dimension: 'organizational',
|
|
54
|
+
score,
|
|
55
|
+
justification: hasBreaking
|
|
56
|
+
? 'Contains breaking-change or migration tags requiring coordination'
|
|
57
|
+
: 'No breaking changes detected',
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function uncertaintyScore(ctx) {
|
|
61
|
+
let score = 2;
|
|
62
|
+
if (ctx.framework === null) {
|
|
63
|
+
score += 2;
|
|
64
|
+
}
|
|
65
|
+
// High difficulty without a known framework indicates exploratory/spike-like work
|
|
66
|
+
if (ctx.difficulty >= 4 && ctx.framework === null) {
|
|
67
|
+
score = Math.min(score + 1, 5);
|
|
68
|
+
}
|
|
69
|
+
score = Math.min(score, 5);
|
|
70
|
+
return {
|
|
71
|
+
dimension: 'uncertainty',
|
|
72
|
+
score,
|
|
73
|
+
justification: ctx.framework === null
|
|
74
|
+
? 'Unknown framework increases estimation uncertainty'
|
|
75
|
+
: 'Framework known, moderate uncertainty',
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function weightedAverage(scores) {
|
|
79
|
+
const weights = {
|
|
80
|
+
technical: 0.3,
|
|
81
|
+
integration: 0.25,
|
|
82
|
+
testing: 0.2,
|
|
83
|
+
organizational: 0.15,
|
|
84
|
+
uncertainty: 0.1,
|
|
85
|
+
};
|
|
86
|
+
return scores.reduce((acc, s) => {
|
|
87
|
+
const weight = weights[s.dimension];
|
|
88
|
+
return acc + s.score * weight;
|
|
89
|
+
}, 0);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Calculate the full complexity matrix for a spec.
|
|
93
|
+
*/
|
|
94
|
+
export function calculateComplexityMatrix(ctx) {
|
|
95
|
+
const scores = [
|
|
96
|
+
technicalScore(ctx),
|
|
97
|
+
integrationScore(ctx),
|
|
98
|
+
testingScore(ctx),
|
|
99
|
+
organizationalScore(ctx),
|
|
100
|
+
uncertaintyScore(ctx),
|
|
101
|
+
];
|
|
102
|
+
const overallComplexity = weightedAverage(scores);
|
|
103
|
+
return {
|
|
104
|
+
specId: ctx.specId,
|
|
105
|
+
scores,
|
|
106
|
+
overallComplexity,
|
|
107
|
+
generatedAt: new Date().toISOString(),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=complexity-calculator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"complexity-calculator.js","sourceRoot":"","sources":["../../../src/engine/risk-analyzer/complexity-calculator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RiskAnalysisContext, EstimationConfidence } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Calculate the estimation confidence for a spec.
|
|
4
|
+
* @param historicalAccuracy - optional 0-1 ratio from past estimates (1 = perfect accuracy)
|
|
5
|
+
*/
|
|
6
|
+
export declare function calculateConfidence(ctx: RiskAnalysisContext, historicalAccuracy?: number): EstimationConfidence;
|
|
7
|
+
//# sourceMappingURL=confidence-scorer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confidence-scorer.d.ts","sourceRoot":"","sources":["../../../src/engine/risk-analyzer/confidence-scorer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EAErB,MAAM,sBAAsB,CAAC;AA0H9B;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,mBAAmB,EACxB,kBAAkB,CAAC,EAAE,MAAM,GAC1B,oBAAoB,CAYtB"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
const BASE_SCORE = 50;
|
|
2
|
+
const HISTORICAL_ADJUSTMENT = 20;
|
|
3
|
+
function buildPositiveFactors(ctx) {
|
|
4
|
+
const factors = [];
|
|
5
|
+
if (ctx.scope !== 'architectural') {
|
|
6
|
+
factors.push({
|
|
7
|
+
name: 'Well-defined scope',
|
|
8
|
+
impact: 'positive',
|
|
9
|
+
weight: 0.2,
|
|
10
|
+
description: `Scope "${ctx.scope}" is clearly bounded`,
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
if (ctx.framework !== null) {
|
|
14
|
+
factors.push({
|
|
15
|
+
name: 'Known framework',
|
|
16
|
+
impact: 'positive',
|
|
17
|
+
weight: 0.15,
|
|
18
|
+
description: `Framework "${ctx.framework}" is established and well-understood`,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
if (ctx.dependencyCount < 3) {
|
|
22
|
+
factors.push({
|
|
23
|
+
name: 'Low dependency count',
|
|
24
|
+
impact: 'positive',
|
|
25
|
+
weight: 0.1,
|
|
26
|
+
description: `Only ${ctx.dependencyCount} dependencies reduces integration risk`,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
if (ctx.difficulty <= 2) {
|
|
30
|
+
factors.push({
|
|
31
|
+
name: 'Low difficulty',
|
|
32
|
+
impact: 'positive',
|
|
33
|
+
weight: 0.15,
|
|
34
|
+
description: `Difficulty level ${ctx.difficulty}/5 is well within team capability`,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return factors;
|
|
38
|
+
}
|
|
39
|
+
function buildNegativeFactors(ctx) {
|
|
40
|
+
const factors = [];
|
|
41
|
+
if (ctx.framework === null) {
|
|
42
|
+
factors.push({
|
|
43
|
+
name: 'Unknown framework',
|
|
44
|
+
impact: 'negative',
|
|
45
|
+
weight: 0.2,
|
|
46
|
+
description: 'No framework specified increases estimation uncertainty',
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
if (ctx.dependencyCount > 5) {
|
|
50
|
+
factors.push({
|
|
51
|
+
name: 'Many dependencies',
|
|
52
|
+
impact: 'negative',
|
|
53
|
+
weight: 0.15,
|
|
54
|
+
description: `${ctx.dependencyCount} dependencies increase coordination risk`,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
if (ctx.scope === 'cross-module' || ctx.scope === 'architectural') {
|
|
58
|
+
factors.push({
|
|
59
|
+
name: 'Broad scope',
|
|
60
|
+
impact: 'negative',
|
|
61
|
+
weight: 0.2,
|
|
62
|
+
description: `Scope "${ctx.scope}" spans multiple areas making estimation harder`,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
if (ctx.risk === 'high' || ctx.risk === 'critical') {
|
|
66
|
+
factors.push({
|
|
67
|
+
name: 'High risk level',
|
|
68
|
+
impact: 'negative',
|
|
69
|
+
weight: 0.15,
|
|
70
|
+
description: `Risk level "${ctx.risk}" signals higher uncertainty`,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return factors;
|
|
74
|
+
}
|
|
75
|
+
function computeScore(positiveFactors, negativeFactors, historicalAccuracy) {
|
|
76
|
+
let score = BASE_SCORE;
|
|
77
|
+
for (const f of positiveFactors) {
|
|
78
|
+
score += f.weight * 100;
|
|
79
|
+
}
|
|
80
|
+
for (const f of negativeFactors) {
|
|
81
|
+
score -= f.weight * 100;
|
|
82
|
+
}
|
|
83
|
+
if (historicalAccuracy !== undefined) {
|
|
84
|
+
const adjustment = (historicalAccuracy - 0.5) * 2 * HISTORICAL_ADJUSTMENT;
|
|
85
|
+
score += adjustment;
|
|
86
|
+
}
|
|
87
|
+
return Math.min(Math.max(score, 0), 100);
|
|
88
|
+
}
|
|
89
|
+
function scoreToLevel(score) {
|
|
90
|
+
if (score < 35) {
|
|
91
|
+
return 'low';
|
|
92
|
+
}
|
|
93
|
+
if (score <= 65) {
|
|
94
|
+
return 'medium';
|
|
95
|
+
}
|
|
96
|
+
return 'high';
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Calculate the estimation confidence for a spec.
|
|
100
|
+
* @param historicalAccuracy - optional 0-1 ratio from past estimates (1 = perfect accuracy)
|
|
101
|
+
*/
|
|
102
|
+
export function calculateConfidence(ctx, historicalAccuracy) {
|
|
103
|
+
const positiveFactors = buildPositiveFactors(ctx);
|
|
104
|
+
const negativeFactors = buildNegativeFactors(ctx);
|
|
105
|
+
const allFactors = [...positiveFactors, ...negativeFactors];
|
|
106
|
+
const score = computeScore(positiveFactors, negativeFactors, historicalAccuracy);
|
|
107
|
+
return {
|
|
108
|
+
level: scoreToLevel(score),
|
|
109
|
+
score,
|
|
110
|
+
factors: allFactors,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=confidence-scorer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confidence-scorer.js","sourceRoot":"","sources":["../../../src/engine/risk-analyzer/confidence-scorer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { generateRiskRegister } from './risk-generator.js';
|
|
2
|
+
export { calculateComplexityMatrix } from './complexity-calculator.js';
|
|
3
|
+
export { detectTradeOffs } from './tradeoff-detector.js';
|
|
4
|
+
export { analyzeApproach } from './approach-analyzer.js';
|
|
5
|
+
export { calculateConfidence } from './confidence-scorer.js';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/engine/risk-analyzer/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// risk-analyzer — Barrel exports
|
|
2
|
+
export { generateRiskRegister } from './risk-generator.js';
|
|
3
|
+
export { calculateComplexityMatrix } from './complexity-calculator.js';
|
|
4
|
+
export { detectTradeOffs } from './tradeoff-detector.js';
|
|
5
|
+
export { analyzeApproach } from './approach-analyzer.js';
|
|
6
|
+
export { calculateConfidence } from './confidence-scorer.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/engine/risk-analyzer/index.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { RiskAnalysisContext, RiskRegister } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Generate an initial risk register from spec metadata.
|
|
4
|
+
*/
|
|
5
|
+
export declare function generateRiskRegister(ctx: RiskAnalysisContext, totalBudget?: number): RiskRegister;
|
|
6
|
+
//# sourceMappingURL=risk-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"risk-generator.d.ts","sourceRoot":"","sources":["../../../src/engine/risk-analyzer/risk-generator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,mBAAmB,EACnB,YAAY,EAGb,MAAM,sBAAsB,CAAC;AA0F9B;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,mBAAmB,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,YAAY,CAYjG"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
function buildRiskTemplates(ctx) {
|
|
2
|
+
const templates = [];
|
|
3
|
+
if (ctx.difficulty >= 4) {
|
|
4
|
+
templates.push({
|
|
5
|
+
description: 'High complexity may lead to estimation overrun',
|
|
6
|
+
category: 'technical',
|
|
7
|
+
probability: 40,
|
|
8
|
+
impactDays: 3,
|
|
9
|
+
mitigationPlan: 'Break down into smaller tasks and reassess estimates',
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
if (ctx.scope === 'cross-module' || ctx.scope === 'architectural') {
|
|
13
|
+
templates.push({
|
|
14
|
+
description: 'Cross-module changes risk breaking existing integrations',
|
|
15
|
+
category: 'integration',
|
|
16
|
+
probability: 35,
|
|
17
|
+
impactDays: 2,
|
|
18
|
+
mitigationPlan: 'Add integration tests covering all affected modules before merging',
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
if (ctx.dependencyCount > 3) {
|
|
22
|
+
templates.push({
|
|
23
|
+
description: 'Multiple dependencies increase coordination overhead',
|
|
24
|
+
category: 'dependency',
|
|
25
|
+
probability: 30,
|
|
26
|
+
impactDays: 2,
|
|
27
|
+
mitigationPlan: 'Establish dependency contracts early and monitor for version conflicts',
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
if (ctx.risk === 'high' || ctx.risk === 'critical') {
|
|
31
|
+
templates.push({
|
|
32
|
+
description: 'Spec flagged as high-risk requires extra review',
|
|
33
|
+
category: 'organizational',
|
|
34
|
+
probability: 50,
|
|
35
|
+
impactDays: 3,
|
|
36
|
+
mitigationPlan: 'Schedule mandatory peer review and add approval gates before deployment',
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
if (ctx.tags.includes('security')) {
|
|
40
|
+
templates.push({
|
|
41
|
+
description: 'Security-sensitive changes require audit',
|
|
42
|
+
category: 'security',
|
|
43
|
+
probability: 25,
|
|
44
|
+
impactDays: 4,
|
|
45
|
+
mitigationPlan: 'Engage security team for review and run SAST/DAST tools',
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
if (ctx.fileCount > 10) {
|
|
49
|
+
templates.push({
|
|
50
|
+
description: 'Large number of files increases merge conflict risk',
|
|
51
|
+
category: 'technical',
|
|
52
|
+
probability: 30,
|
|
53
|
+
impactDays: 1,
|
|
54
|
+
mitigationPlan: 'Use feature flags and incremental PRs to reduce merge surface',
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return templates;
|
|
58
|
+
}
|
|
59
|
+
function buildRisks(ctx, templates) {
|
|
60
|
+
return templates.map((t, index) => ({
|
|
61
|
+
id: `R${index + 1}`,
|
|
62
|
+
description: t.description,
|
|
63
|
+
category: t.category,
|
|
64
|
+
probability: t.probability,
|
|
65
|
+
impactUsd: 0,
|
|
66
|
+
impactDays: t.impactDays,
|
|
67
|
+
owner: '',
|
|
68
|
+
status: 'identified',
|
|
69
|
+
mitigationPlan: t.mitigationPlan,
|
|
70
|
+
specId: ctx.specId,
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
73
|
+
function computeAggregateScore(risks, totalBudgetDays) {
|
|
74
|
+
const rawScore = risks.reduce((acc, r) => acc + (r.probability / 100) * r.impactDays, 0);
|
|
75
|
+
const denominator = Math.max(totalBudgetDays, 1);
|
|
76
|
+
const score = (rawScore / denominator) * 100;
|
|
77
|
+
return Math.min(score, 100);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Generate an initial risk register from spec metadata.
|
|
81
|
+
*/
|
|
82
|
+
export function generateRiskRegister(ctx, totalBudget) {
|
|
83
|
+
const budgetDays = totalBudget ?? 30;
|
|
84
|
+
const templates = buildRiskTemplates(ctx);
|
|
85
|
+
const risks = buildRisks(ctx, templates);
|
|
86
|
+
const aggregateRiskScore = computeAggregateScore(risks, budgetDays);
|
|
87
|
+
return {
|
|
88
|
+
specId: ctx.specId,
|
|
89
|
+
risks,
|
|
90
|
+
aggregateRiskScore,
|
|
91
|
+
generatedAt: new Date().toISOString(),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=risk-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"risk-generator.js","sourceRoot":"","sources":["../../../src/engine/risk-analyzer/risk-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { RiskAnalysisContext, TradeOff } from '../../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Detect applicable trade-offs based on spec context patterns.
|
|
4
|
+
*/
|
|
5
|
+
export declare function detectTradeOffs(ctx: RiskAnalysisContext): TradeOff[];
|
|
6
|
+
//# sourceMappingURL=tradeoff-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tradeoff-detector.d.ts","sourceRoot":"","sources":["../../../src/engine/risk-analyzer/tradeoff-detector.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAkB,MAAM,sBAAsB,CAAC;AAsH1F;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,mBAAmB,GAAG,QAAQ,EAAE,CAoBpE"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
function architecturalTradeOff() {
|
|
2
|
+
const options = [
|
|
3
|
+
{
|
|
4
|
+
name: 'Monolithic implementation',
|
|
5
|
+
pros: ['Simpler to develop', 'Faster initial delivery', 'Easier to debug'],
|
|
6
|
+
cons: ['Harder to scale', 'Tightly coupled components', 'Difficult to maintain long-term'],
|
|
7
|
+
riskIfChosen: 'Technical debt accumulates, refactoring will be costly later',
|
|
8
|
+
riskIfNotChosen: 'Over-engineering for current scope',
|
|
9
|
+
estimatedCostDelta: -8,
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
name: 'Modular implementation',
|
|
13
|
+
pros: ['Better separation of concerns', 'Easier to test in isolation', 'Scalable by design'],
|
|
14
|
+
cons: ['Higher upfront complexity', 'More files and boilerplate', 'Steeper learning curve'],
|
|
15
|
+
riskIfChosen: 'Over-engineering if scope does not expand',
|
|
16
|
+
riskIfNotChosen: 'Hard to scale or refactor once monolithic approach is established',
|
|
17
|
+
estimatedCostDelta: 8,
|
|
18
|
+
},
|
|
19
|
+
];
|
|
20
|
+
return {
|
|
21
|
+
id: 'TO-1',
|
|
22
|
+
description: 'Monolithic vs modular implementation approach',
|
|
23
|
+
options,
|
|
24
|
+
chosenOption: '',
|
|
25
|
+
rationale: '',
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function incrementalPrTradeOff() {
|
|
29
|
+
const options = [
|
|
30
|
+
{
|
|
31
|
+
name: 'Single large PR',
|
|
32
|
+
pros: ['All changes in one review', 'No partial states in main branch'],
|
|
33
|
+
cons: ['Large PR harder to review', 'Higher merge conflict risk', 'Blocks other work longer'],
|
|
34
|
+
riskIfChosen: 'Reviewers miss issues due to PR fatigue',
|
|
35
|
+
riskIfNotChosen: 'Parallel work may depend on partial changes',
|
|
36
|
+
estimatedCostDelta: -4,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'Incremental PRs',
|
|
40
|
+
pros: ['Smaller, reviewable chunks', 'Earlier feedback', 'Reduces merge conflicts'],
|
|
41
|
+
cons: ['More coordination overhead', 'Partial features may be live temporarily'],
|
|
42
|
+
riskIfChosen: 'Partial states may cause confusion without feature flags',
|
|
43
|
+
riskIfNotChosen: 'Large PR increases review errors',
|
|
44
|
+
estimatedCostDelta: 4,
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
return {
|
|
48
|
+
id: 'TO-2',
|
|
49
|
+
description: 'Single PR vs incremental PRs for large changeset',
|
|
50
|
+
options,
|
|
51
|
+
chosenOption: '',
|
|
52
|
+
rationale: '',
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function performanceTradeOff() {
|
|
56
|
+
const options = [
|
|
57
|
+
{
|
|
58
|
+
name: 'Optimize now',
|
|
59
|
+
pros: ['Performance built-in from the start', 'Avoids costly rewrites later'],
|
|
60
|
+
cons: ['Premature optimization risk', 'Adds complexity before problems are confirmed'],
|
|
61
|
+
riskIfChosen: 'Optimizing the wrong bottleneck without profiling data',
|
|
62
|
+
riskIfNotChosen: 'Performance issues at scale require expensive retrofitting',
|
|
63
|
+
estimatedCostDelta: 12,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: 'Defer optimization',
|
|
67
|
+
pros: ['Faster initial delivery', 'Optimize based on real profiling data'],
|
|
68
|
+
cons: ['May need rework later', 'Performance issues may reach production'],
|
|
69
|
+
riskIfChosen: 'Technical debt if optimization is never prioritized',
|
|
70
|
+
riskIfNotChosen: 'Early optimization may be unnecessary',
|
|
71
|
+
estimatedCostDelta: -12,
|
|
72
|
+
},
|
|
73
|
+
];
|
|
74
|
+
return {
|
|
75
|
+
id: 'TO-3',
|
|
76
|
+
description: 'Optimize now vs defer optimization',
|
|
77
|
+
options,
|
|
78
|
+
chosenOption: '',
|
|
79
|
+
rationale: '',
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function dependencyTradeOff() {
|
|
83
|
+
const options = [
|
|
84
|
+
{
|
|
85
|
+
name: 'Use external dependency',
|
|
86
|
+
pros: ['Faster delivery', 'Battle-tested solution', 'Community support'],
|
|
87
|
+
cons: ['Version lock-in risk', 'Security surface increases', 'License constraints possible'],
|
|
88
|
+
riskIfChosen: 'Dependency may be abandoned or introduce breaking changes',
|
|
89
|
+
riskIfNotChosen: 'Custom solution may lack features or have bugs',
|
|
90
|
+
estimatedCostDelta: -16,
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: 'Custom implementation',
|
|
94
|
+
pros: ['Full control', 'No external lock-in', 'Tailored to exact needs'],
|
|
95
|
+
cons: ['High development cost', 'Maintenance burden', 'Re-inventing the wheel risk'],
|
|
96
|
+
riskIfChosen: 'Under-resourced maintenance leads to accumulating bugs',
|
|
97
|
+
riskIfNotChosen: 'Dependency risks (abandonment, licensing) remain',
|
|
98
|
+
estimatedCostDelta: 16,
|
|
99
|
+
},
|
|
100
|
+
];
|
|
101
|
+
return {
|
|
102
|
+
id: 'TO-4',
|
|
103
|
+
description: 'External dependency vs custom implementation',
|
|
104
|
+
options,
|
|
105
|
+
chosenOption: '',
|
|
106
|
+
rationale: '',
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Detect applicable trade-offs based on spec context patterns.
|
|
111
|
+
*/
|
|
112
|
+
export function detectTradeOffs(ctx) {
|
|
113
|
+
const tradeoffs = [];
|
|
114
|
+
if (ctx.scope === 'architectural') {
|
|
115
|
+
tradeoffs.push(architecturalTradeOff());
|
|
116
|
+
}
|
|
117
|
+
if (ctx.fileCount > 8) {
|
|
118
|
+
tradeoffs.push(incrementalPrTradeOff());
|
|
119
|
+
}
|
|
120
|
+
if (ctx.tags.includes('performance')) {
|
|
121
|
+
tradeoffs.push(performanceTradeOff());
|
|
122
|
+
}
|
|
123
|
+
if (ctx.dependencyCount > 5) {
|
|
124
|
+
tradeoffs.push(dependencyTradeOff());
|
|
125
|
+
}
|
|
126
|
+
return tradeoffs;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=tradeoff-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tradeoff-detector.js","sourceRoot":"","sources":["../../../src/engine/risk-analyzer/tradeoff-detector.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -61,6 +61,13 @@ const server = new McpServer({
|
|
|
61
61
|
'4. When presenting lists or results, use plain language headers — not jargon.',
|
|
62
62
|
'5. If the user seems confused, offer to explain further. Never assume knowledge.',
|
|
63
63
|
"6. Adapt your language to the user's locale (English, Spanish, or Portuguese).",
|
|
64
|
+
'',
|
|
65
|
+
'GIT WORKFLOW — suggest branches at key moments:',
|
|
66
|
+
'- After creating spec(s): suggest creating a feature branch (e.g., "git checkout -b feat/SPEC-XXX-feature-name").',
|
|
67
|
+
'- When a spec moves to "implementing": remind the user to work in a dedicated branch, not directly on main or develop.',
|
|
68
|
+
'- Use manage_git to create branches, generate PR descriptions, and link them to specs.',
|
|
69
|
+
'- Branch naming convention: feat/SPEC-XXX-short-name for features, fix/SPEC-XXX-short-name for fixes.',
|
|
70
|
+
'- Explain why: "Working in a separate branch keeps your main code safe while you build this feature. When it is ready, you merge it back."',
|
|
64
71
|
].join('\n'),
|
|
65
72
|
});
|
|
66
73
|
// ---------------------------------------------------------------------------
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,mDAAmD;AACnD,mFAAmF;AAEnF,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAC/E,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAC;AACjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,6BAA6B,EAAE,MAAM,gCAAgC,CAAC;AAC/E,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,8EAA8E;AAC9E,eAAe;AACf,8EAA8E;AAE9E,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B;IACE,IAAI,EAAE,WAAW;IACjB,OAAO,EAAE,iBAAiB;CAC3B,EACD;IACE,YAAY,EAAE;QACZ,iGAAiG;QACjG,EAAE;QACF,wDAAwD;QACxD,EAAE;QACF,wFAAwF;QACxF,0FAA0F;QAC1F,qFAAqF;QACrF,8EAA8E;QAC9E,yEAAyE;QACzE,6EAA6E;QAC7E,6EAA6E;QAC7E,+HAA+H;QAC/H,oGAAoG;QACpG,qFAAqF;QACrF,2FAA2F;QAC3F,oGAAoG;QACpG,gHAAgH;QAChH,0FAA0F;QAC1F,qFAAqF;QACrF,gGAAgG;QAChG,yEAAyE;QACzE,kGAAkG;QAClG,sHAAsH;QACtH,yFAAyF;QACzF,yEAAyE;QACzE,qFAAqF;QACrF,EAAE;QACF,6DAA6D;QAC7D,sEAAsE;QACtE,+EAA+E;QAC/E,kFAAkF;QAClF,gFAAgF;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { RiskRegister } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Load the risk register for a given spec.
|
|
4
|
+
* Returns null when no register has been saved yet.
|
|
5
|
+
*/
|
|
6
|
+
export declare function loadRiskRegister(projectDataDir: string, specId: string): Promise<RiskRegister | null>;
|
|
7
|
+
/**
|
|
8
|
+
* Persist a risk register for a spec.
|
|
9
|
+
*/
|
|
10
|
+
export declare function saveRiskRegister(projectDataDir: string, register: RiskRegister): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Load all risk registers for a project.
|
|
13
|
+
* Returns an empty array when the risks directory does not exist.
|
|
14
|
+
*/
|
|
15
|
+
export declare function loadAllRiskRegisters(projectDataDir: string): Promise<RiskRegister[]>;
|
|
16
|
+
//# sourceMappingURL=risk-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"risk-store.d.ts","sourceRoot":"","sources":["../../src/storage/risk-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAa,MAAM,mBAAmB,CAAC;AAiBjE;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAE9B;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,YAAY,GACrB,OAAO,CAAC,IAAI,CAAC,CAEf;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAsB1F"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { readJson, writeJson } from './base-store.js';
|
|
2
|
+
import { readdir } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
// --- internal helpers ---
|
|
5
|
+
function risksDir(projectDataDir) {
|
|
6
|
+
return join(projectDataDir, 'risks');
|
|
7
|
+
}
|
|
8
|
+
function riskFile(projectDataDir, specId) {
|
|
9
|
+
return join(risksDir(projectDataDir), `${specId}.json`);
|
|
10
|
+
}
|
|
11
|
+
// --- public API ---
|
|
12
|
+
/**
|
|
13
|
+
* Load the risk register for a given spec.
|
|
14
|
+
* Returns null when no register has been saved yet.
|
|
15
|
+
*/
|
|
16
|
+
export async function loadRiskRegister(projectDataDir, specId) {
|
|
17
|
+
return readJson(riskFile(projectDataDir, specId), null);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Persist a risk register for a spec.
|
|
21
|
+
*/
|
|
22
|
+
export async function saveRiskRegister(projectDataDir, register) {
|
|
23
|
+
await writeJson(riskFile(projectDataDir, register.specId), register);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Load all risk registers for a project.
|
|
27
|
+
* Returns an empty array when the risks directory does not exist.
|
|
28
|
+
*/
|
|
29
|
+
export async function loadAllRiskRegisters(projectDataDir) {
|
|
30
|
+
const dir = risksDir(projectDataDir);
|
|
31
|
+
let files;
|
|
32
|
+
try {
|
|
33
|
+
files = await readdir(dir);
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
if (isNodeError(err) && err.code === 'ENOENT') {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
/* v8 ignore next */
|
|
40
|
+
throw err;
|
|
41
|
+
}
|
|
42
|
+
const jsonFiles = files.filter((f) => f.endsWith('.json'));
|
|
43
|
+
const registers = await Promise.all(jsonFiles.map(async (file) => {
|
|
44
|
+
const specId = file.replace(/\.json$/, '');
|
|
45
|
+
return loadRiskRegister(projectDataDir, specId);
|
|
46
|
+
}));
|
|
47
|
+
return registers.filter((r) => r !== null);
|
|
48
|
+
}
|
|
49
|
+
// --- internal helpers ---
|
|
50
|
+
function isNodeError(err) {
|
|
51
|
+
return err instanceof Error && 'code' in err;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=risk-store.js.map
|