@esthernandez/vibe-doc 0.1.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.
Files changed (95) hide show
  1. package/dist/checker/index.d.ts +34 -0
  2. package/dist/checker/index.d.ts.map +1 -0
  3. package/dist/checker/index.js +154 -0
  4. package/dist/checker/staleness.d.ts +26 -0
  5. package/dist/checker/staleness.d.ts.map +1 -0
  6. package/dist/checker/staleness.js +56 -0
  7. package/dist/classifier/index.d.ts +26 -0
  8. package/dist/classifier/index.d.ts.map +1 -0
  9. package/dist/classifier/index.js +146 -0
  10. package/dist/classifier/llm-prompt.d.ts +12 -0
  11. package/dist/classifier/llm-prompt.d.ts.map +1 -0
  12. package/dist/classifier/llm-prompt.js +123 -0
  13. package/dist/classifier/scoring-engine.d.ts +41 -0
  14. package/dist/classifier/scoring-engine.d.ts.map +1 -0
  15. package/dist/classifier/scoring-engine.js +197 -0
  16. package/dist/classifier/signals.d.ts +16 -0
  17. package/dist/classifier/signals.d.ts.map +1 -0
  18. package/dist/classifier/signals.js +305 -0
  19. package/dist/gap-analyzer/breadcrumbs.d.ts +18 -0
  20. package/dist/gap-analyzer/breadcrumbs.d.ts.map +1 -0
  21. package/dist/gap-analyzer/breadcrumbs.js +314 -0
  22. package/dist/gap-analyzer/index.d.ts +13 -0
  23. package/dist/gap-analyzer/index.d.ts.map +1 -0
  24. package/dist/gap-analyzer/index.js +88 -0
  25. package/dist/gap-analyzer/matrix.d.ts +29 -0
  26. package/dist/gap-analyzer/matrix.d.ts.map +1 -0
  27. package/dist/gap-analyzer/matrix.js +137 -0
  28. package/dist/gap-analyzer/tier-assigner.d.ts +22 -0
  29. package/dist/gap-analyzer/tier-assigner.d.ts.map +1 -0
  30. package/dist/gap-analyzer/tier-assigner.js +112 -0
  31. package/dist/generator/docx-writer.d.ts +15 -0
  32. package/dist/generator/docx-writer.d.ts.map +1 -0
  33. package/dist/generator/docx-writer.js +271 -0
  34. package/dist/generator/extractor.d.ts +11 -0
  35. package/dist/generator/extractor.d.ts.map +1 -0
  36. package/dist/generator/extractor.js +459 -0
  37. package/dist/generator/index.d.ts +25 -0
  38. package/dist/generator/index.d.ts.map +1 -0
  39. package/dist/generator/index.js +106 -0
  40. package/dist/generator/markdown-writer.d.ts +27 -0
  41. package/dist/generator/markdown-writer.d.ts.map +1 -0
  42. package/dist/generator/markdown-writer.js +85 -0
  43. package/dist/index.d.ts +7 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +372 -0
  46. package/dist/scanner/artifact-scanner.d.ts +16 -0
  47. package/dist/scanner/artifact-scanner.d.ts.map +1 -0
  48. package/dist/scanner/artifact-scanner.js +189 -0
  49. package/dist/scanner/code-scanner.d.ts +17 -0
  50. package/dist/scanner/code-scanner.d.ts.map +1 -0
  51. package/dist/scanner/code-scanner.js +69 -0
  52. package/dist/scanner/file-scanner.d.ts +16 -0
  53. package/dist/scanner/file-scanner.d.ts.map +1 -0
  54. package/dist/scanner/file-scanner.js +119 -0
  55. package/dist/scanner/git-scanner.d.ts +10 -0
  56. package/dist/scanner/git-scanner.d.ts.map +1 -0
  57. package/dist/scanner/git-scanner.js +120 -0
  58. package/dist/scanner/index.d.ts +15 -0
  59. package/dist/scanner/index.d.ts.map +1 -0
  60. package/dist/scanner/index.js +106 -0
  61. package/dist/state/index.d.ts +20 -0
  62. package/dist/state/index.d.ts.map +1 -0
  63. package/dist/state/index.js +141 -0
  64. package/dist/state/schema.d.ts +101 -0
  65. package/dist/state/schema.d.ts.map +1 -0
  66. package/dist/state/schema.js +6 -0
  67. package/dist/templates/embedded/adr.md +45 -0
  68. package/dist/templates/embedded/api-spec.md +55 -0
  69. package/dist/templates/embedded/data-model.md +55 -0
  70. package/dist/templates/embedded/deployment-procedure.md +63 -0
  71. package/dist/templates/embedded/runbook.md +55 -0
  72. package/dist/templates/embedded/test-plan.md +55 -0
  73. package/dist/templates/embedded/threat-model.md +47 -0
  74. package/dist/templates/index.d.ts +20 -0
  75. package/dist/templates/index.d.ts.map +1 -0
  76. package/dist/templates/index.js +106 -0
  77. package/dist/templates/registry.d.ts +31 -0
  78. package/dist/templates/registry.d.ts.map +1 -0
  79. package/dist/templates/registry.js +172 -0
  80. package/dist/templates/renderer.d.ts +26 -0
  81. package/dist/templates/renderer.d.ts.map +1 -0
  82. package/dist/templates/renderer.js +145 -0
  83. package/dist/utils/language-detect.d.ts +14 -0
  84. package/dist/utils/language-detect.d.ts.map +1 -0
  85. package/dist/utils/language-detect.js +58 -0
  86. package/dist/utils/logger.d.ts +16 -0
  87. package/dist/utils/logger.d.ts.map +1 -0
  88. package/dist/utils/logger.js +35 -0
  89. package/dist/versioning/differ.d.ts +20 -0
  90. package/dist/versioning/differ.d.ts.map +1 -0
  91. package/dist/versioning/differ.js +160 -0
  92. package/dist/versioning/index.d.ts +44 -0
  93. package/dist/versioning/index.d.ts.map +1 -0
  94. package/dist/versioning/index.js +165 -0
  95. package/package.json +40 -0
@@ -0,0 +1,34 @@
1
+ /**
2
+ * CI Check Logic
3
+ * Validates that all required documentation exists and is not stale
4
+ */
5
+ export interface CheckOptions {
6
+ threshold?: number;
7
+ }
8
+ export interface CheckResult {
9
+ pass: boolean;
10
+ missing: string[];
11
+ stale: string[];
12
+ details: string;
13
+ exitCode: 0 | 1;
14
+ }
15
+ /**
16
+ * Run CI checks on the project
17
+ * Verifies that all required docs exist and are not stale
18
+ * @param projectPath - Root path of the project
19
+ * @param options - Check options (threshold in commits)
20
+ * @returns CheckResult with pass/fail status and details
21
+ */
22
+ export declare function runCheck(projectPath: string, options?: CheckOptions): Promise<CheckResult>;
23
+ /**
24
+ * Get detailed staleness info for a specific doc type
25
+ * Useful for debugging/verbose output
26
+ */
27
+ export declare function getDocStalenessDetails(projectPath: string, docType: string): Promise<{
28
+ docType: string;
29
+ commitsSince: number;
30
+ daysSince: number;
31
+ generatedAt: string;
32
+ exists: boolean;
33
+ } | null>;
34
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/checker/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;CACjB;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAC5B,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,WAAW,CAAC,CAyDtB;AAqCD;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IACT,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;CACjB,GAAG,IAAI,CAAC,CA0BR"}
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ /**
3
+ * CI Check Logic
4
+ * Validates that all required documentation exists and is not stale
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.runCheck = runCheck;
41
+ exports.getDocStalenessDetails = getDocStalenessDetails;
42
+ const path = __importStar(require("path"));
43
+ const fs = __importStar(require("fs"));
44
+ const state_1 = require("../state");
45
+ const staleness_1 = require("./staleness");
46
+ /**
47
+ * Run CI checks on the project
48
+ * Verifies that all required docs exist and are not stale
49
+ * @param projectPath - Root path of the project
50
+ * @param options - Check options (threshold in commits)
51
+ * @returns CheckResult with pass/fail status and details
52
+ */
53
+ async function runCheck(projectPath, options = {}) {
54
+ const threshold = options.threshold ?? 20;
55
+ const missing = [];
56
+ const stale = [];
57
+ // Read state
58
+ const state = (0, state_1.readState)(projectPath);
59
+ if (!state) {
60
+ return {
61
+ pass: false,
62
+ missing: [],
63
+ stale: [],
64
+ details: 'No vibe-doc state found. Run `vibe-doc scan` first.',
65
+ exitCode: 1,
66
+ };
67
+ }
68
+ // Get all required gaps (tier === 'required')
69
+ const requiredGaps = state.gapReport.gaps.filter((gap) => gap.tier === 'required');
70
+ // Check each required gap
71
+ for (const gap of requiredGaps) {
72
+ const docPath = path.join(projectPath, 'docs', 'generated', `${gap.docType}.md`);
73
+ // Check if doc exists
74
+ if (!fs.existsSync(docPath)) {
75
+ missing.push(gap.docType);
76
+ continue;
77
+ }
78
+ // Find the generated doc in state
79
+ const generatedDoc = state.generatedDocs.find((d) => d.docType === gap.docType);
80
+ if (!generatedDoc) {
81
+ missing.push(gap.docType);
82
+ continue;
83
+ }
84
+ // Check staleness
85
+ const docIsStale = await (0, staleness_1.isStale)(generatedDoc, projectPath, threshold);
86
+ if (docIsStale) {
87
+ stale.push(gap.docType);
88
+ }
89
+ }
90
+ // Determine pass/fail
91
+ const pass = missing.length === 0 && stale.length === 0;
92
+ // Build details message
93
+ const details = buildDetailsMessage(requiredGaps.length, missing, stale, threshold);
94
+ return {
95
+ pass,
96
+ missing,
97
+ stale,
98
+ details,
99
+ exitCode: pass ? 0 : 1,
100
+ };
101
+ }
102
+ /**
103
+ * Build a human-readable details message
104
+ */
105
+ function buildDetailsMessage(totalRequired, missing, stale, threshold) {
106
+ const lines = [];
107
+ lines.push(`Documentation Check Results`);
108
+ lines.push(`Required docs: ${totalRequired}`);
109
+ if (missing.length > 0) {
110
+ lines.push(`\nMissing (${missing.length}):`);
111
+ for (const doc of missing) {
112
+ lines.push(` - ${doc}`);
113
+ }
114
+ }
115
+ if (stale.length > 0) {
116
+ lines.push(`\nStale - more than ${threshold} commits since generation (${stale.length}):`);
117
+ for (const doc of stale) {
118
+ lines.push(` - ${doc}`);
119
+ }
120
+ }
121
+ if (missing.length === 0 && stale.length === 0) {
122
+ lines.push(`\n✓ All required documentation is present and current`);
123
+ }
124
+ return lines.join('\n');
125
+ }
126
+ /**
127
+ * Get detailed staleness info for a specific doc type
128
+ * Useful for debugging/verbose output
129
+ */
130
+ async function getDocStalenessDetails(projectPath, docType) {
131
+ const state = (0, state_1.readState)(projectPath);
132
+ if (!state) {
133
+ return null;
134
+ }
135
+ const generatedDoc = state.generatedDocs.find((d) => d.docType === docType);
136
+ if (!generatedDoc) {
137
+ return null;
138
+ }
139
+ const docPath = path.join(projectPath, 'docs', 'generated', `${docType}.md`);
140
+ const exists = fs.existsSync(docPath);
141
+ try {
142
+ const staleness = await (0, staleness_1.getStalenessInfo)(generatedDoc, projectPath);
143
+ return {
144
+ docType,
145
+ commitsSince: staleness.commitsSince,
146
+ daysSince: staleness.daysSince,
147
+ generatedAt: generatedDoc.generatedAt,
148
+ exists,
149
+ };
150
+ }
151
+ catch {
152
+ return null;
153
+ }
154
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Staleness Detection
3
+ * Determines if generated documentation is stale based on git commit history
4
+ */
5
+ import { GeneratedDoc } from '../state/schema';
6
+ export interface StalenessInfo {
7
+ commitsSince: number;
8
+ daysSince: number;
9
+ isStale: boolean;
10
+ }
11
+ /**
12
+ * Check if a document is stale based on commit count since generation
13
+ * @param doc - The generated document
14
+ * @param projectPath - Root path of the project
15
+ * @param threshold - Number of commits before doc is considered stale (default: 20)
16
+ * @returns true if commits since generation >= threshold
17
+ */
18
+ export declare function isStale(doc: GeneratedDoc, projectPath: string, threshold?: number): Promise<boolean>;
19
+ /**
20
+ * Get detailed staleness information for a document
21
+ * @param doc - The generated document
22
+ * @param projectPath - Root path of the project
23
+ * @returns Staleness info including commit count and days since generation
24
+ */
25
+ export declare function getStalenessInfo(doc: GeneratedDoc, projectPath: string): Promise<StalenessInfo>;
26
+ //# sourceMappingURL=staleness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staleness.d.ts","sourceRoot":"","sources":["../../src/checker/staleness.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAsB,OAAO,CAC3B,GAAG,EAAE,YAAY,EACjB,WAAW,EAAE,MAAM,EACnB,SAAS,GAAE,MAAW,GACrB,OAAO,CAAC,OAAO,CAAC,CAWlB;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,YAAY,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,aAAa,CAAC,CAsBxB"}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ /**
3
+ * Staleness Detection
4
+ * Determines if generated documentation is stale based on git commit history
5
+ */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.isStale = isStale;
11
+ exports.getStalenessInfo = getStalenessInfo;
12
+ const simple_git_1 = __importDefault(require("simple-git"));
13
+ /**
14
+ * Check if a document is stale based on commit count since generation
15
+ * @param doc - The generated document
16
+ * @param projectPath - Root path of the project
17
+ * @param threshold - Number of commits before doc is considered stale (default: 20)
18
+ * @returns true if commits since generation >= threshold
19
+ */
20
+ async function isStale(doc, projectPath, threshold = 20) {
21
+ try {
22
+ const staleness = await getStalenessInfo(doc, projectPath);
23
+ return staleness.commitsSince >= threshold;
24
+ }
25
+ catch (error) {
26
+ // If we can't determine staleness, conservatively assume stale to prevent deploying with outdated docs
27
+ console.warn(`Failed to check staleness for ${doc.docType}: ${error}. Assuming stale for safety.`);
28
+ return true;
29
+ }
30
+ }
31
+ /**
32
+ * Get detailed staleness information for a document
33
+ * @param doc - The generated document
34
+ * @param projectPath - Root path of the project
35
+ * @returns Staleness info including commit count and days since generation
36
+ */
37
+ async function getStalenessInfo(doc, projectPath) {
38
+ try {
39
+ const git = (0, simple_git_1.default)(projectPath);
40
+ // Get the timestamp of the document generation
41
+ const docDate = new Date(doc.generatedAt);
42
+ // Get all commits since that time
43
+ const log = await git.log({ from: doc.generatedAt });
44
+ // Calculate days since generation
45
+ const now = new Date();
46
+ const daysSince = Math.floor((now.getTime() - docDate.getTime()) / (1000 * 60 * 60 * 24));
47
+ return {
48
+ commitsSince: log.total,
49
+ daysSince,
50
+ isStale: false, // Will be set by isStale() function
51
+ };
52
+ }
53
+ catch (error) {
54
+ throw new Error(`Failed to get staleness info for ${doc.docType}: ${error}`);
55
+ }
56
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Classifier Orchestrator
3
+ * Main entry point for hybrid classification
4
+ */
5
+ import { ArtifactInventory, Classification } from '../state/schema';
6
+ export interface ClassificationOptions {
7
+ confidenceThreshold?: number;
8
+ }
9
+ export interface ClassificationResult {
10
+ resolved: boolean;
11
+ classification?: Classification;
12
+ llmPrompt?: string;
13
+ candidates?: Array<{
14
+ category: string;
15
+ score: number;
16
+ }>;
17
+ contexts?: string[];
18
+ }
19
+ /**
20
+ * Classify a project based on artifact inventory
21
+ * Returns either a high-confidence classification or a prompt for LLM fallback
22
+ * @param inventory - Artifact inventory from scanner
23
+ * @param options - Classification options (confidenceThreshold, etc.)
24
+ */
25
+ export declare function classify(inventory: ArtifactInventory, options?: ClassificationOptions): ClassificationResult;
26
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/classifier/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAqB,MAAM,iBAAiB,CAAC;AAMvF,MAAM,WAAW,qBAAqB;IACpC,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CACtB,SAAS,EAAE,iBAAiB,EAC5B,OAAO,CAAC,EAAE,qBAAqB,GAC9B,oBAAoB,CAkDtB"}
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ /**
3
+ * Classifier Orchestrator
4
+ * Main entry point for hybrid classification
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.classify = classify;
8
+ const logger_1 = require("../utils/logger");
9
+ const signals_1 = require("./signals");
10
+ const scoring_engine_1 = require("./scoring-engine");
11
+ const llm_prompt_1 = require("./llm-prompt");
12
+ /**
13
+ * Classify a project based on artifact inventory
14
+ * Returns either a high-confidence classification or a prompt for LLM fallback
15
+ * @param inventory - Artifact inventory from scanner
16
+ * @param options - Classification options (confidenceThreshold, etc.)
17
+ */
18
+ function classify(inventory, options) {
19
+ const confidenceThreshold = options?.confidenceThreshold ?? 0.85;
20
+ logger_1.logger.info('Starting hybrid classification', { confidenceThreshold });
21
+ // Step 1: Extract signals from inventory
22
+ const signals = (0, signals_1.extractSignals)(inventory);
23
+ logger_1.logger.info('Signals extracted', { count: signals.length });
24
+ // Step 2: Run scoring engine
25
+ const ruleResults = (0, scoring_engine_1.scoreClassification)(signals, confidenceThreshold);
26
+ logger_1.logger.info('Rule-based scoring complete', {
27
+ confidence: ruleResults.confidence,
28
+ topCategory: ruleResults.categories[0],
29
+ });
30
+ // Step 3: Check confidence threshold
31
+ if (ruleResults.confidence >= confidenceThreshold) {
32
+ // High confidence - return classification directly
33
+ const classification = buildClassification(ruleResults, inventory);
34
+ logger_1.logger.info('Classification resolved with high confidence', {
35
+ category: classification.primaryCategory,
36
+ confidence: classification.confidence,
37
+ });
38
+ return {
39
+ resolved: true,
40
+ classification,
41
+ };
42
+ }
43
+ // Low confidence - build classification from best candidate and prepare LLM prompt
44
+ logger_1.logger.info('Classification confidence too low, building from best candidate', {
45
+ confidence: ruleResults.confidence,
46
+ topCandidate: ruleResults.categories[0]?.category,
47
+ });
48
+ const llmPrompt = (0, llm_prompt_1.buildClassificationPrompt)(inventory, ruleResults);
49
+ const classification = buildLowConfidenceClassification(ruleResults, inventory);
50
+ return {
51
+ resolved: false,
52
+ classification,
53
+ llmPrompt,
54
+ candidates: ruleResults.categories.map((c) => ({
55
+ category: c.category,
56
+ score: c.score,
57
+ })),
58
+ contexts: ruleResults.contexts.map((c) => c.context),
59
+ };
60
+ }
61
+ /**
62
+ * Build a Classification object from scoring results
63
+ */
64
+ function buildClassification(ruleResults, inventory) {
65
+ const topCategory = ruleResults.categories[0];
66
+ const secondaryCategory = ruleResults.categories.length > 1 ? ruleResults.categories[1] : null;
67
+ const contexts = ruleResults.contexts.map((c) => c.context);
68
+ // Map category to deployment context
69
+ const deploymentContext = mapCategoryToDeploymentContext(topCategory.category, contexts);
70
+ return {
71
+ primaryCategory: topCategory.category,
72
+ secondaryCategory: secondaryCategory?.category || '',
73
+ deploymentContext,
74
+ contextModifiers: contexts,
75
+ confidence: ruleResults.confidence,
76
+ rationale: buildRationale(topCategory.category, contexts),
77
+ userConfirmed: false,
78
+ };
79
+ }
80
+ /**
81
+ * Build a Classification object from low-confidence scoring results
82
+ * Uses the best candidate with actual confidence score and contexts
83
+ */
84
+ function buildLowConfidenceClassification(ruleResults, inventory) {
85
+ const topCategory = ruleResults.categories[0];
86
+ const secondaryCategory = ruleResults.categories.length > 1 ? ruleResults.categories[1] : null;
87
+ const contexts = ruleResults.contexts.map((c) => c.context);
88
+ // Map category to deployment context
89
+ const deploymentContext = mapCategoryToDeploymentContext(topCategory.category, contexts);
90
+ // Build rationale noting that LLM review is available
91
+ const baseRationale = buildRationale(topCategory.category, contexts);
92
+ const reviewNote = ' [LLM review available to increase confidence]';
93
+ return {
94
+ primaryCategory: topCategory.category,
95
+ secondaryCategory: secondaryCategory?.category || '',
96
+ deploymentContext,
97
+ contextModifiers: contexts,
98
+ confidence: ruleResults.confidence,
99
+ rationale: baseRationale + reviewNote,
100
+ userConfirmed: false,
101
+ };
102
+ }
103
+ /**
104
+ * Map category and contexts to deployment context
105
+ */
106
+ function mapCategoryToDeploymentContext(category, contexts) {
107
+ const result = [];
108
+ // Determine platform based on category
109
+ let platform = 'cloud';
110
+ if (category === scoring_engine_1.Category.MobileApplication) {
111
+ platform = 'mobile';
112
+ }
113
+ else if (category === scoring_engine_1.Category.InfrastructurePlatform) {
114
+ platform = 'kubernetes';
115
+ }
116
+ // Check for EdgeEmbedded context
117
+ if (contexts.includes(scoring_engine_1.Context.EdgeEmbedded)) {
118
+ platform = 'edge';
119
+ }
120
+ // Determine environment based on contexts
121
+ let environment = 'production';
122
+ if (contexts.includes(scoring_engine_1.Context.InternalTooling)) {
123
+ environment = 'staging';
124
+ }
125
+ // Determine scale based on contexts
126
+ let scale = 'small';
127
+ if (contexts.includes(scoring_engine_1.Context.CustomerFacing)) {
128
+ scale = 'large';
129
+ }
130
+ else if (contexts.includes(scoring_engine_1.Context.MultiTenant)) {
131
+ scale = 'large';
132
+ }
133
+ result.push({ platform, environment, scale });
134
+ return result;
135
+ }
136
+ /**
137
+ * Build a rationale string for the classification
138
+ */
139
+ function buildRationale(category, contexts) {
140
+ const parts = [];
141
+ parts.push(`Primary category: ${category}`);
142
+ if (contexts.length > 0) {
143
+ parts.push(`Contexts: ${contexts.join(', ')}`);
144
+ }
145
+ return parts.join('. ');
146
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * LLM Prompt Builder
3
+ * Generates structured prompts for LLM-based classification fallback
4
+ */
5
+ import { ArtifactInventory } from '../state/schema';
6
+ import { ScoringResult } from './scoring-engine';
7
+ /**
8
+ * Build a structured prompt for LLM classification
9
+ * Used when rule-based confidence is < 0.85
10
+ */
11
+ export declare function buildClassificationPrompt(inventory: ArtifactInventory, ruleResults: ScoringResult): string;
12
+ //# sourceMappingURL=llm-prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-prompt.d.ts","sourceRoot":"","sources":["../../src/classifier/llm-prompt.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAA+B,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAE9E;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,iBAAiB,EAC5B,WAAW,EAAE,aAAa,GACzB,MAAM,CA0DR"}
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ /**
3
+ * LLM Prompt Builder
4
+ * Generates structured prompts for LLM-based classification fallback
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.buildClassificationPrompt = buildClassificationPrompt;
8
+ /**
9
+ * Build a structured prompt for LLM classification
10
+ * Used when rule-based confidence is < 0.85
11
+ */
12
+ function buildClassificationPrompt(inventory, ruleResults) {
13
+ const topCategories = ruleResults.categories.slice(0, 3);
14
+ const detectedContexts = ruleResults.contexts.slice(0, 3);
15
+ const projectSummary = buildProjectSummary(inventory);
16
+ const candidateSummary = buildCandidateSummary(topCategories, detectedContexts);
17
+ return `# Project Classification Task
18
+
19
+ You are an expert software architect reviewing a codebase to determine its primary category and operational contexts.
20
+
21
+ ## Project Scan Summary
22
+
23
+ ${projectSummary}
24
+
25
+ ## Rule Engine Candidates
26
+
27
+ The rule-based classifier generated these candidates with confidence ${(ruleResults.confidence * 100).toFixed(0)}%:
28
+
29
+ ${candidateSummary}
30
+
31
+ ## Classification Categories
32
+
33
+ Choose ONE primary category that best describes this project:
34
+
35
+ - **WebApplication**: A user-facing web application (SPA, server-rendered, etc.)
36
+ - **APIMicroservice**: A REST API, GraphQL service, or microservice
37
+ - **DataPipeline**: ETL pipelines, data warehouses, batch processors
38
+ - **InfrastructurePlatform**: Infrastructure-as-code, deployment systems, cloud platforms
39
+ - **MobileApplication**: Native or cross-platform mobile apps
40
+ - **AIMLSystem**: ML/AI-focused projects with models, training, inference
41
+ - **IntegrationConnector**: Adapters, SDKs, connectors for third-party services
42
+
43
+ ## Operational Contexts
44
+
45
+ Identify applicable contexts (can select multiple):
46
+
47
+ - **Regulated**: Subject to compliance requirements (HIPAA, SOX, PCI, etc.)
48
+ - **CustomerFacing**: Public-facing or customer-critical service
49
+ - **InternalTooling**: Internal tools, admin dashboards, support systems
50
+ - **MultiTenant**: Serves multiple independent customers/tenants
51
+ - **EdgeEmbedded**: Runs on edge devices, embedded systems, or IoT
52
+
53
+ ## Your Response
54
+
55
+ Return a JSON object with this exact structure:
56
+ \`\`\`json
57
+ {
58
+ "primaryCategory": "string (one of the categories above)",
59
+ "secondaryCategory": "string (optional, for ambiguous cases)",
60
+ "contexts": ["string", "string"],
61
+ "confidence": 0.75,
62
+ "rationale": "Explain your classification in 2-3 sentences"
63
+ }
64
+ \`\`\`
65
+
66
+ Focus on the strongest signals in the codebase. If multiple categories are equally plausible, explain the tie-breaker in rationale.
67
+ `;
68
+ }
69
+ function buildProjectSummary(inventory) {
70
+ const sc = inventory.categories.sourceCode;
71
+ const conf = inventory.categories.configuration;
72
+ const doc = inventory.categories.documentation;
73
+ const tests = inventory.categories.tests;
74
+ const arch = inventory.categories.architecture;
75
+ const infra = inventory.categories.infrastructure;
76
+ const languages = inventory.gitStats.mainLanguages.slice(0, 5).join(', ') || 'Unknown';
77
+ return `
78
+ ### File Distribution
79
+ - Source code: ${sc.count} files (${languages})
80
+ - Configuration: ${conf.count} files
81
+ - Documentation: ${doc.count} files
82
+ - Tests: ${tests.count} files
83
+ - Architecture artifacts: ${arch.count} files
84
+ - Infrastructure: ${infra.count} files
85
+ - **Total artifacts: ${inventory.totalArtifacts}**
86
+
87
+ ### Git Activity
88
+ - Total commits: ${inventory.gitStats.totalCommits}
89
+ - Contributors: ${inventory.gitStats.contributors}
90
+ - Last commit: ${inventory.gitStats.lastCommitDate}
91
+
92
+ ### Top Source Files (Sample)
93
+ \`\`\`
94
+ ${sc.files.slice(0, 5).join('\n')}
95
+ ${sc.files.length > 5 ? `... and ${sc.files.length - 5} more source files` : ''}
96
+ \`\`\`
97
+
98
+ ### Configuration Files (Sample)
99
+ \`\`\`
100
+ ${conf.files.slice(0, 5).join('\n')}
101
+ ${conf.files.length > 5 ? `... and ${conf.files.length - 5} more config files` : ''}
102
+ \`\`\`
103
+
104
+ ### Infrastructure Files (Sample)
105
+ \`\`\`
106
+ ${infra.files.slice(0, 5).join('\n')}
107
+ ${infra.files.length > 5 ? `... and ${infra.files.length - 5} more infrastructure files` : ''}
108
+ \`\`\`
109
+ `;
110
+ }
111
+ function buildCandidateSummary(categories, contexts) {
112
+ let summary = '### Categories (Rule Score)\n';
113
+ for (const cat of categories) {
114
+ summary += `- ${cat.category}: ${cat.score.toFixed(1)}\n`;
115
+ }
116
+ if (contexts.length > 0) {
117
+ summary += '\n### Detected Contexts (Rule Score)\n';
118
+ for (const ctx of contexts) {
119
+ summary += `- ${ctx.context}: ${ctx.score.toFixed(1)}\n`;
120
+ }
121
+ }
122
+ return summary;
123
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Scoring Engine Module
3
+ * Rule-based matrix for categorizing projects and contexts
4
+ */
5
+ import { Signal } from './signals';
6
+ export declare enum Category {
7
+ WebApplication = "WebApplication",
8
+ APIMicroservice = "APIMicroservice",
9
+ DataPipeline = "DataPipeline",
10
+ InfrastructurePlatform = "InfrastructurePlatform",
11
+ MobileApplication = "MobileApplication",
12
+ AIMLSystem = "AIMLSystem",
13
+ IntegrationConnector = "IntegrationConnector"
14
+ }
15
+ export declare enum Context {
16
+ Regulated = "Regulated",
17
+ CustomerFacing = "CustomerFacing",
18
+ InternalTooling = "InternalTooling",
19
+ MultiTenant = "MultiTenant",
20
+ EdgeEmbedded = "EdgeEmbedded"
21
+ }
22
+ export interface CategoryScore {
23
+ category: Category;
24
+ score: number;
25
+ }
26
+ export interface ContextScore {
27
+ context: Context;
28
+ score: number;
29
+ }
30
+ export interface ScoringResult {
31
+ categories: CategoryScore[];
32
+ contexts: ContextScore[];
33
+ confidence: number;
34
+ }
35
+ /**
36
+ * Score classification based on signals
37
+ * @param signals - Array of detected signals
38
+ * @param confidenceThreshold - Threshold for high confidence classification (default: 0.85)
39
+ */
40
+ export declare function scoreClassification(signals: Signal[], confidenceThreshold?: number): ScoringResult;
41
+ //# sourceMappingURL=scoring-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scoring-engine.d.ts","sourceRoot":"","sources":["../../src/classifier/scoring-engine.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAGnC,oBAAY,QAAQ;IAClB,cAAc,mBAAmB;IACjC,eAAe,oBAAoB;IACnC,YAAY,iBAAiB;IAC7B,sBAAsB,2BAA2B;IACjD,iBAAiB,sBAAsB;IACvC,UAAU,eAAe;IACzB,oBAAoB,yBAAyB;CAC9C;AAED,oBAAY,OAAO;IACjB,SAAS,cAAc;IACvB,cAAc,mBAAmB;IACjC,eAAe,oBAAoB;IACnC,WAAW,gBAAgB;IAC3B,YAAY,iBAAiB;CAC9B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EAAE,EACjB,mBAAmB,GAAE,MAAa,GACjC,aAAa,CAuMf"}