projex-cli 0.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/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +321 -0
- package/dist/cli.js.map +1 -0
- package/dist/event-bus.d.ts +35 -0
- package/dist/event-bus.d.ts.map +1 -0
- package/dist/event-bus.js +71 -0
- package/dist/event-bus.js.map +1 -0
- package/dist/events/event-bus.d.ts +35 -0
- package/dist/events/event-bus.d.ts.map +1 -0
- package/dist/events/event-bus.js +71 -0
- package/dist/events/event-bus.js.map +1 -0
- package/dist/events/index.d.ts +3 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +3 -0
- package/dist/events/index.js.map +1 -0
- package/dist/events/types.d.ts +143 -0
- package/dist/events/types.d.ts.map +1 -0
- package/dist/events/types.js +6 -0
- package/dist/events/types.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/inference/enricher.d.ts +18 -0
- package/dist/inference/enricher.d.ts.map +1 -0
- package/dist/inference/enricher.js +290 -0
- package/dist/inference/enricher.js.map +1 -0
- package/dist/inference/index.d.ts +5 -0
- package/dist/inference/index.d.ts.map +1 -0
- package/dist/inference/index.js +5 -0
- package/dist/inference/index.js.map +1 -0
- package/dist/inference/lifecycle-tracker.d.ts +40 -0
- package/dist/inference/lifecycle-tracker.d.ts.map +1 -0
- package/dist/inference/lifecycle-tracker.js +132 -0
- package/dist/inference/lifecycle-tracker.js.map +1 -0
- package/dist/inference/portfolio-generator.d.ts +44 -0
- package/dist/inference/portfolio-generator.d.ts.map +1 -0
- package/dist/inference/portfolio-generator.js +239 -0
- package/dist/inference/portfolio-generator.js.map +1 -0
- package/dist/inference/project-detector.d.ts +17 -0
- package/dist/inference/project-detector.d.ts.map +1 -0
- package/dist/inference/project-detector.js +127 -0
- package/dist/inference/project-detector.js.map +1 -0
- package/dist/ingestion/github-client.d.ts +56 -0
- package/dist/ingestion/github-client.d.ts.map +1 -0
- package/dist/ingestion/github-client.js +213 -0
- package/dist/ingestion/github-client.js.map +1 -0
- package/dist/ingestion/github-poller.d.ts +41 -0
- package/dist/ingestion/github-poller.d.ts.map +1 -0
- package/dist/ingestion/github-poller.js +121 -0
- package/dist/ingestion/github-poller.js.map +1 -0
- package/dist/ingestion/normalizer.d.ts +41 -0
- package/dist/ingestion/normalizer.d.ts.map +1 -0
- package/dist/ingestion/normalizer.js +173 -0
- package/dist/ingestion/normalizer.js.map +1 -0
- package/dist/integrations/analyzer.d.ts +74 -0
- package/dist/integrations/analyzer.d.ts.map +1 -0
- package/dist/integrations/analyzer.js +287 -0
- package/dist/integrations/analyzer.js.map +1 -0
- package/dist/integrations/index.d.ts +4 -0
- package/dist/integrations/index.d.ts.map +1 -0
- package/dist/integrations/index.js +5 -0
- package/dist/integrations/index.js.map +1 -0
- package/dist/integrations/injectors.d.ts +60 -0
- package/dist/integrations/injectors.d.ts.map +1 -0
- package/dist/integrations/injectors.js +361 -0
- package/dist/integrations/injectors.js.map +1 -0
- package/dist/integrations/template-generator.d.ts +45 -0
- package/dist/integrations/template-generator.d.ts.map +1 -0
- package/dist/integrations/template-generator.js +187 -0
- package/dist/integrations/template-generator.js.map +1 -0
- package/dist/storage/index.d.ts +2 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +2 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/project-store.d.ts +23 -0
- package/dist/storage/project-store.d.ts.map +1 -0
- package/dist/storage/project-store.js +107 -0
- package/dist/storage/project-store.js.map +1 -0
- package/dist/types.d.ts +143 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lifecycle Tracker - Rule 4: Project completion detection
|
|
3
|
+
* Detects when projects become inactive or are explicitly archived.
|
|
4
|
+
*/
|
|
5
|
+
export class LifecycleTracker {
|
|
6
|
+
store;
|
|
7
|
+
eventBus;
|
|
8
|
+
completionThresholdDays;
|
|
9
|
+
minCommitsForCompletion;
|
|
10
|
+
constructor(store, eventBus, config) {
|
|
11
|
+
this.store = store;
|
|
12
|
+
this.eventBus = eventBus;
|
|
13
|
+
this.completionThresholdDays = config.inference.completionThresholdDays;
|
|
14
|
+
this.minCommitsForCompletion = config.inference.minCommitsForCompletion;
|
|
15
|
+
// Subscribe to archived events
|
|
16
|
+
this.eventBus.subscribe(['repo.archived'], (event) => this.handleArchived(event));
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Handle explicit archive events - high confidence completion
|
|
20
|
+
*/
|
|
21
|
+
async handleArchived(event) {
|
|
22
|
+
const project = this.store.getProject(event.repo.id);
|
|
23
|
+
if (!project) {
|
|
24
|
+
console.log(`[LifecycleTracker] Project not found for archive: ${event.repo.id}`);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
console.log(`[LifecycleTracker] Project archived: ${event.repo.id}`);
|
|
28
|
+
project.status = 'ARCHIVED';
|
|
29
|
+
project.completionDate = event.payload.archivedAt;
|
|
30
|
+
project.confidence.completion = 1.0; // Explicit archive = certain
|
|
31
|
+
project.updatedAt = new Date();
|
|
32
|
+
this.store.saveProject(project);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Check all projects for inactivity-based completion
|
|
36
|
+
* Should be called periodically (e.g., after each poll)
|
|
37
|
+
*/
|
|
38
|
+
checkForCompletedProjects() {
|
|
39
|
+
const now = new Date();
|
|
40
|
+
const thresholdMs = this.completionThresholdDays * 24 * 60 * 60 * 1000;
|
|
41
|
+
const completedProjects = [];
|
|
42
|
+
for (const project of this.store.getAllProjects()) {
|
|
43
|
+
// Skip already completed/archived/ignored projects
|
|
44
|
+
if (project.status !== 'ACTIVE')
|
|
45
|
+
continue;
|
|
46
|
+
const daysSinceActivity = (now.getTime() - project.lastActivityDate.getTime()) / (24 * 60 * 60 * 1000);
|
|
47
|
+
// Check completion criteria
|
|
48
|
+
if (daysSinceActivity >= this.completionThresholdDays) {
|
|
49
|
+
const hasSubstantialContent = this.hasSubstantialContent(project);
|
|
50
|
+
if (hasSubstantialContent) {
|
|
51
|
+
console.log(`[LifecycleTracker] Marking as likely completed (${daysSinceActivity.toFixed(0)} days inactive): ${project.id}`);
|
|
52
|
+
project.status = 'LIKELY_COMPLETED';
|
|
53
|
+
project.completionDate = project.lastActivityDate;
|
|
54
|
+
project.confidence.completion = this.calculateCompletionConfidence(project, daysSinceActivity);
|
|
55
|
+
project.updatedAt = now;
|
|
56
|
+
this.store.saveProject(project);
|
|
57
|
+
completedProjects.push(project);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return completedProjects;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Check if project has enough content to be considered a real project
|
|
65
|
+
*/
|
|
66
|
+
hasSubstantialContent(project) {
|
|
67
|
+
// Must have a README
|
|
68
|
+
if (!project.rawData.readme)
|
|
69
|
+
return false;
|
|
70
|
+
// Must have detected tech stack (indicates code exists)
|
|
71
|
+
if (project.techStack.length === 0)
|
|
72
|
+
return false;
|
|
73
|
+
// Must have some languages detected
|
|
74
|
+
const languageCount = Object.keys(project.rawData.languages).length;
|
|
75
|
+
if (languageCount === 0)
|
|
76
|
+
return false;
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Calculate confidence in completion status
|
|
81
|
+
*/
|
|
82
|
+
calculateCompletionConfidence(project, daysSinceActivity) {
|
|
83
|
+
let confidence = 0.5; // Base confidence for inactivity threshold
|
|
84
|
+
// More days = more confident it's complete
|
|
85
|
+
if (daysSinceActivity > 180)
|
|
86
|
+
confidence += 0.2;
|
|
87
|
+
else if (daysSinceActivity > 120)
|
|
88
|
+
confidence += 0.1;
|
|
89
|
+
// Has README = more likely a finished project
|
|
90
|
+
if (project.rawData.readme)
|
|
91
|
+
confidence += 0.1;
|
|
92
|
+
// Has description = intentionally created
|
|
93
|
+
if (project.rawData.description)
|
|
94
|
+
confidence += 0.05;
|
|
95
|
+
// Has substantial code (multiple languages or large files)
|
|
96
|
+
const totalBytes = Object.values(project.rawData.languages).reduce((a, b) => a + b, 0);
|
|
97
|
+
if (totalBytes > 10000)
|
|
98
|
+
confidence += 0.1;
|
|
99
|
+
// Has topics = organized project
|
|
100
|
+
if (project.topics.length > 0)
|
|
101
|
+
confidence += 0.05;
|
|
102
|
+
return Math.min(confidence, 0.95); // Cap at 0.95 for inactivity detection
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Manually mark a project as completed
|
|
106
|
+
*/
|
|
107
|
+
markAsCompleted(projectId) {
|
|
108
|
+
const project = this.store.getProject(projectId);
|
|
109
|
+
if (!project)
|
|
110
|
+
return false;
|
|
111
|
+
project.status = 'COMPLETED';
|
|
112
|
+
project.completionDate = new Date();
|
|
113
|
+
project.confidence.completion = 1.0;
|
|
114
|
+
project.updatedAt = new Date();
|
|
115
|
+
this.store.saveProject(project);
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Manually mark a project to be ignored (not a portfolio candidate)
|
|
120
|
+
*/
|
|
121
|
+
ignoreProject(projectId) {
|
|
122
|
+
const project = this.store.getProject(projectId);
|
|
123
|
+
if (!project)
|
|
124
|
+
return false;
|
|
125
|
+
project.status = 'IGNORED';
|
|
126
|
+
project.portfolioStatus = 'REJECTED';
|
|
127
|
+
project.updatedAt = new Date();
|
|
128
|
+
this.store.saveProject(project);
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=lifecycle-tracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle-tracker.js","sourceRoot":"","sources":["../../src/inference/lifecycle-tracker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portfolio Generator - Rule 5: Creates portfolio drafts from completed projects
|
|
3
|
+
*/
|
|
4
|
+
import type { Project, PortfolioDraft } from '../events/types.js';
|
|
5
|
+
import type { ProjectStore } from '../storage/project-store.js';
|
|
6
|
+
export declare class PortfolioGenerator {
|
|
7
|
+
private store;
|
|
8
|
+
constructor(store: ProjectStore);
|
|
9
|
+
/**
|
|
10
|
+
* Generate portfolio drafts for all completed projects that don't have one
|
|
11
|
+
*/
|
|
12
|
+
generatePendingDrafts(): PortfolioDraft[];
|
|
13
|
+
/**
|
|
14
|
+
* Generate a single portfolio draft for a project
|
|
15
|
+
*/
|
|
16
|
+
generateDraft(project: Project): PortfolioDraft;
|
|
17
|
+
/**
|
|
18
|
+
* Regenerate draft for a specific project
|
|
19
|
+
*/
|
|
20
|
+
regenerateDraft(projectId: string): PortfolioDraft | null;
|
|
21
|
+
/**
|
|
22
|
+
* Apply user edits to a draft
|
|
23
|
+
*/
|
|
24
|
+
applyUserEdits(projectId: string, edits: Partial<PortfolioDraft>): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Approve a portfolio draft
|
|
27
|
+
*/
|
|
28
|
+
approveDraft(projectId: string): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Reject a portfolio draft
|
|
31
|
+
*/
|
|
32
|
+
rejectDraft(projectId: string): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Get the final portfolio entry (with user edits applied)
|
|
35
|
+
*/
|
|
36
|
+
getFinalPortfolioEntry(projectId: string): PortfolioDraft | null;
|
|
37
|
+
private shouldGenerateDraft;
|
|
38
|
+
private generateTagline;
|
|
39
|
+
private generateDescription;
|
|
40
|
+
private formatTechStack;
|
|
41
|
+
private extractHighlights;
|
|
42
|
+
private extractFeaturesFromReadme;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=portfolio-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portfolio-generator.d.ts","sourceRoot":"","sources":["../../src/inference/portfolio-generator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACR,OAAO,EACP,cAAc,EAEjB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE,qBAAa,kBAAkB;IACf,OAAO,CAAC,KAAK;gBAAL,KAAK,EAAE,YAAY;IAEvC;;OAEG;IACH,qBAAqB,IAAI,cAAc,EAAE;IAmBzC;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,cAAc;IAkB/C;;OAEG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAazD;;OAEG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO;IAc1E;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAaxC;;OAEG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAWvC;;OAEG;IACH,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAchE,OAAO,CAAC,mBAAmB;IAe3B,OAAO,CAAC,eAAe;IAsBvB,OAAO,CAAC,mBAAmB;IAuB3B,OAAO,CAAC,eAAe;IA+BvB,OAAO,CAAC,iBAAiB;IA+BzB,OAAO,CAAC,yBAAyB;CA6BpC"}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portfolio Generator - Rule 5: Creates portfolio drafts from completed projects
|
|
3
|
+
*/
|
|
4
|
+
export class PortfolioGenerator {
|
|
5
|
+
store;
|
|
6
|
+
constructor(store) {
|
|
7
|
+
this.store = store;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Generate portfolio drafts for all completed projects that don't have one
|
|
11
|
+
*/
|
|
12
|
+
generatePendingDrafts() {
|
|
13
|
+
const generated = [];
|
|
14
|
+
for (const project of this.store.getAllProjects()) {
|
|
15
|
+
if (this.shouldGenerateDraft(project)) {
|
|
16
|
+
const draft = this.generateDraft(project);
|
|
17
|
+
project.portfolioDraft = draft;
|
|
18
|
+
project.portfolioStatus = 'PENDING_REVIEW';
|
|
19
|
+
project.updatedAt = new Date();
|
|
20
|
+
this.store.saveProject(project);
|
|
21
|
+
generated.push(draft);
|
|
22
|
+
console.log(`[PortfolioGenerator] Generated draft for: ${project.id}`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return generated;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Generate a single portfolio draft for a project
|
|
29
|
+
*/
|
|
30
|
+
generateDraft(project) {
|
|
31
|
+
return {
|
|
32
|
+
title: project.displayName,
|
|
33
|
+
tagline: this.generateTagline(project),
|
|
34
|
+
description: this.generateDescription(project),
|
|
35
|
+
techStack: this.formatTechStack(project.techStack),
|
|
36
|
+
timelineStart: project.startDate,
|
|
37
|
+
timelineEnd: project.completionDate,
|
|
38
|
+
highlights: this.extractHighlights(project),
|
|
39
|
+
githubUrl: project.url,
|
|
40
|
+
liveUrl: null,
|
|
41
|
+
userEdits: {},
|
|
42
|
+
approved: false,
|
|
43
|
+
approvedAt: null,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Regenerate draft for a specific project
|
|
48
|
+
*/
|
|
49
|
+
regenerateDraft(projectId) {
|
|
50
|
+
const project = this.store.getProject(projectId);
|
|
51
|
+
if (!project)
|
|
52
|
+
return null;
|
|
53
|
+
const draft = this.generateDraft(project);
|
|
54
|
+
project.portfolioDraft = draft;
|
|
55
|
+
project.portfolioStatus = 'PENDING_REVIEW';
|
|
56
|
+
project.updatedAt = new Date();
|
|
57
|
+
this.store.saveProject(project);
|
|
58
|
+
return draft;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Apply user edits to a draft
|
|
62
|
+
*/
|
|
63
|
+
applyUserEdits(projectId, edits) {
|
|
64
|
+
const project = this.store.getProject(projectId);
|
|
65
|
+
if (!project?.portfolioDraft)
|
|
66
|
+
return false;
|
|
67
|
+
project.portfolioDraft.userEdits = {
|
|
68
|
+
...project.portfolioDraft.userEdits,
|
|
69
|
+
...edits,
|
|
70
|
+
};
|
|
71
|
+
project.updatedAt = new Date();
|
|
72
|
+
this.store.saveProject(project);
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Approve a portfolio draft
|
|
77
|
+
*/
|
|
78
|
+
approveDraft(projectId) {
|
|
79
|
+
const project = this.store.getProject(projectId);
|
|
80
|
+
if (!project?.portfolioDraft)
|
|
81
|
+
return false;
|
|
82
|
+
project.portfolioDraft.approved = true;
|
|
83
|
+
project.portfolioDraft.approvedAt = new Date();
|
|
84
|
+
project.portfolioStatus = 'APPROVED';
|
|
85
|
+
project.updatedAt = new Date();
|
|
86
|
+
this.store.saveProject(project);
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Reject a portfolio draft
|
|
91
|
+
*/
|
|
92
|
+
rejectDraft(projectId) {
|
|
93
|
+
const project = this.store.getProject(projectId);
|
|
94
|
+
if (!project)
|
|
95
|
+
return false;
|
|
96
|
+
project.portfolioStatus = 'REJECTED';
|
|
97
|
+
project.updatedAt = new Date();
|
|
98
|
+
this.store.saveProject(project);
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get the final portfolio entry (with user edits applied)
|
|
103
|
+
*/
|
|
104
|
+
getFinalPortfolioEntry(projectId) {
|
|
105
|
+
const project = this.store.getProject(projectId);
|
|
106
|
+
if (!project?.portfolioDraft)
|
|
107
|
+
return null;
|
|
108
|
+
// Merge user edits on top of generated draft
|
|
109
|
+
return {
|
|
110
|
+
...project.portfolioDraft,
|
|
111
|
+
...project.portfolioDraft.userEdits,
|
|
112
|
+
userEdits: project.portfolioDraft.userEdits,
|
|
113
|
+
approved: project.portfolioDraft.approved,
|
|
114
|
+
approvedAt: project.portfolioDraft.approvedAt,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
shouldGenerateDraft(project) {
|
|
118
|
+
// Generate for completed/likely completed projects without a draft
|
|
119
|
+
if (!['COMPLETED', 'LIKELY_COMPLETED'].includes(project.status))
|
|
120
|
+
return false;
|
|
121
|
+
if (project.portfolioStatus !== 'NONE')
|
|
122
|
+
return false;
|
|
123
|
+
if (project.portfolioDraft)
|
|
124
|
+
return false;
|
|
125
|
+
// Skip private repos by default
|
|
126
|
+
if (project.isPrivate)
|
|
127
|
+
return false;
|
|
128
|
+
// Must have some content
|
|
129
|
+
if (!project.purpose && project.techStack.length === 0)
|
|
130
|
+
return false;
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
generateTagline(project) {
|
|
134
|
+
const frameworks = project.techStack
|
|
135
|
+
.filter(t => t.category === 'framework')
|
|
136
|
+
.slice(0, 2)
|
|
137
|
+
.map(t => t.name);
|
|
138
|
+
const languages = project.techStack
|
|
139
|
+
.filter(t => t.category === 'language')
|
|
140
|
+
.slice(0, 2)
|
|
141
|
+
.map(t => t.name);
|
|
142
|
+
if (frameworks.length > 0) {
|
|
143
|
+
return `Built with ${frameworks.join(' and ')}`;
|
|
144
|
+
}
|
|
145
|
+
if (languages.length > 0) {
|
|
146
|
+
return `${languages.join('/')} project`;
|
|
147
|
+
}
|
|
148
|
+
return 'Software project';
|
|
149
|
+
}
|
|
150
|
+
generateDescription(project) {
|
|
151
|
+
if (project.purpose && project.purpose !== 'Purpose not detected') {
|
|
152
|
+
return project.purpose;
|
|
153
|
+
}
|
|
154
|
+
// Generate from available info
|
|
155
|
+
const parts = [];
|
|
156
|
+
if (project.topics.length > 0) {
|
|
157
|
+
parts.push(`A project focused on ${project.topics.slice(0, 3).join(', ')}.`);
|
|
158
|
+
}
|
|
159
|
+
const frameworks = project.techStack
|
|
160
|
+
.filter(t => t.category === 'framework')
|
|
161
|
+
.map(t => t.name);
|
|
162
|
+
if (frameworks.length > 0) {
|
|
163
|
+
parts.push(`Built using ${frameworks.join(', ')}.`);
|
|
164
|
+
}
|
|
165
|
+
return parts.join(' ') || `${project.displayName} project.`;
|
|
166
|
+
}
|
|
167
|
+
formatTechStack(techStack) {
|
|
168
|
+
// Group by category and take top items
|
|
169
|
+
const byCategory = new Map();
|
|
170
|
+
for (const item of techStack) {
|
|
171
|
+
const existing = byCategory.get(item.category) ?? [];
|
|
172
|
+
existing.push(item);
|
|
173
|
+
byCategory.set(item.category, existing);
|
|
174
|
+
}
|
|
175
|
+
const result = [];
|
|
176
|
+
// Languages first
|
|
177
|
+
const languages = byCategory.get('language') ?? [];
|
|
178
|
+
result.push(...languages.slice(0, 3).map(l => l.name));
|
|
179
|
+
// Then frameworks
|
|
180
|
+
const frameworks = byCategory.get('framework') ?? [];
|
|
181
|
+
result.push(...frameworks.slice(0, 3).map(f => f.name));
|
|
182
|
+
// Then key libraries
|
|
183
|
+
const libraries = byCategory.get('library') ?? [];
|
|
184
|
+
result.push(...libraries.slice(0, 2).map(l => l.name));
|
|
185
|
+
// Platforms
|
|
186
|
+
const platforms = byCategory.get('platform') ?? [];
|
|
187
|
+
result.push(...platforms.slice(0, 2).map(p => p.name));
|
|
188
|
+
return result;
|
|
189
|
+
}
|
|
190
|
+
extractHighlights(project) {
|
|
191
|
+
const highlights = [];
|
|
192
|
+
// Extract from README if available
|
|
193
|
+
if (project.rawData.readme) {
|
|
194
|
+
const features = this.extractFeaturesFromReadme(project.rawData.readme);
|
|
195
|
+
highlights.push(...features.slice(0, 5));
|
|
196
|
+
}
|
|
197
|
+
// Add tech-based highlights if no features found
|
|
198
|
+
if (highlights.length === 0) {
|
|
199
|
+
const frameworks = project.techStack
|
|
200
|
+
.filter(t => t.category === 'framework')
|
|
201
|
+
.map(t => t.name);
|
|
202
|
+
if (frameworks.length > 0) {
|
|
203
|
+
highlights.push(`Built with ${frameworks[0]}`);
|
|
204
|
+
}
|
|
205
|
+
const platforms = project.techStack
|
|
206
|
+
.filter(t => t.category === 'platform')
|
|
207
|
+
.map(t => t.name);
|
|
208
|
+
if (platforms.includes('Docker')) {
|
|
209
|
+
highlights.push('Containerized with Docker');
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return highlights;
|
|
213
|
+
}
|
|
214
|
+
extractFeaturesFromReadme(readme) {
|
|
215
|
+
const features = [];
|
|
216
|
+
// Look for Features/Highlights section
|
|
217
|
+
const featureMatch = readme.match(/##?\s*(Features|Highlights|Key Features)[^\n]*\n([\s\S]*?)(?=\n##|\n$|$)/i);
|
|
218
|
+
if (featureMatch) {
|
|
219
|
+
const section = featureMatch[2];
|
|
220
|
+
// Extract bullet points
|
|
221
|
+
const bullets = section.match(/^[\s]*[-*]\s+(.+)$/gm);
|
|
222
|
+
if (bullets) {
|
|
223
|
+
for (const bullet of bullets.slice(0, 5)) {
|
|
224
|
+
const text = bullet.replace(/^[\s]*[-*]\s+/, '').trim();
|
|
225
|
+
// Clean up markdown formatting
|
|
226
|
+
const cleaned = text
|
|
227
|
+
.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
|
|
228
|
+
.replace(/`([^`]+)`/g, '$1')
|
|
229
|
+
.replace(/\*\*([^*]+)\*\*/g, '$1');
|
|
230
|
+
if (cleaned.length > 10 && cleaned.length < 100) {
|
|
231
|
+
features.push(cleaned);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return features;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=portfolio-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portfolio-generator.js","sourceRoot":"","sources":["../../src/inference/portfolio-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project Detector - Rule 1: Creates draft projects from repo events
|
|
3
|
+
*/
|
|
4
|
+
import type { ProjectStore } from '../storage/project-store.js';
|
|
5
|
+
import { EventBus } from '../events/event-bus.js';
|
|
6
|
+
export declare class ProjectDetector {
|
|
7
|
+
private store;
|
|
8
|
+
private eventBus;
|
|
9
|
+
constructor(store: ProjectStore, eventBus: EventBus);
|
|
10
|
+
private handleEvent;
|
|
11
|
+
private handleRepoCreated;
|
|
12
|
+
private handleRepoPushed;
|
|
13
|
+
private createDraftProject;
|
|
14
|
+
private createProjectFromPush;
|
|
15
|
+
private humanizeName;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=project-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-detector.d.ts","sourceRoot":"","sources":["../../src/inference/project-detector.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAElD,qBAAa,eAAe;IAEpB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,QAAQ;gBADR,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,QAAQ;YAQhB,WAAW;YAQX,iBAAiB;YAcjB,gBAAgB;IAuB9B,OAAO,CAAC,kBAAkB;IA0C1B,OAAO,CAAC,qBAAqB;IA0C7B,OAAO,CAAC,YAAY;CASvB"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project Detector - Rule 1: Creates draft projects from repo events
|
|
3
|
+
*/
|
|
4
|
+
export class ProjectDetector {
|
|
5
|
+
store;
|
|
6
|
+
eventBus;
|
|
7
|
+
constructor(store, eventBus) {
|
|
8
|
+
this.store = store;
|
|
9
|
+
this.eventBus = eventBus;
|
|
10
|
+
// Subscribe to relevant events
|
|
11
|
+
this.eventBus.subscribe(['repo.created', 'repo.pushed'], (event) => this.handleEvent(event));
|
|
12
|
+
}
|
|
13
|
+
async handleEvent(event) {
|
|
14
|
+
if (event.eventType === 'repo.created') {
|
|
15
|
+
await this.handleRepoCreated(event);
|
|
16
|
+
}
|
|
17
|
+
else if (event.eventType === 'repo.pushed') {
|
|
18
|
+
await this.handleRepoPushed(event);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
async handleRepoCreated(event) {
|
|
22
|
+
const existingProject = this.store.getProject(event.repo.id);
|
|
23
|
+
if (existingProject) {
|
|
24
|
+
console.log(`[ProjectDetector] Project already exists: ${event.repo.id}`);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
console.log(`[ProjectDetector] Creating new project: ${event.repo.id}`);
|
|
28
|
+
const project = this.createDraftProject(event);
|
|
29
|
+
this.store.saveProject(project);
|
|
30
|
+
}
|
|
31
|
+
async handleRepoPushed(event) {
|
|
32
|
+
const existingProject = this.store.getProject(event.repo.id);
|
|
33
|
+
if (existingProject) {
|
|
34
|
+
// Update last activity date
|
|
35
|
+
existingProject.lastActivityDate = event.timestamp;
|
|
36
|
+
existingProject.updatedAt = new Date();
|
|
37
|
+
// If it was marked as likely completed, reactivate it
|
|
38
|
+
if (existingProject.status === 'LIKELY_COMPLETED') {
|
|
39
|
+
existingProject.status = 'ACTIVE';
|
|
40
|
+
console.log(`[ProjectDetector] Reactivated project: ${event.repo.id}`);
|
|
41
|
+
}
|
|
42
|
+
this.store.saveProject(existingProject);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
// Unknown repo with push activity - create project
|
|
46
|
+
console.log(`[ProjectDetector] Creating project from push: ${event.repo.id}`);
|
|
47
|
+
const project = this.createProjectFromPush(event);
|
|
48
|
+
this.store.saveProject(project);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
createDraftProject(event) {
|
|
52
|
+
const now = new Date();
|
|
53
|
+
return {
|
|
54
|
+
id: event.repo.id,
|
|
55
|
+
name: event.repo.name,
|
|
56
|
+
displayName: this.humanizeName(event.repo.name),
|
|
57
|
+
owner: event.repo.owner,
|
|
58
|
+
url: event.repo.url,
|
|
59
|
+
status: 'ACTIVE',
|
|
60
|
+
isPrivate: event.payload.isPrivate,
|
|
61
|
+
purpose: event.payload.description,
|
|
62
|
+
techStack: [],
|
|
63
|
+
topics: event.payload.topics,
|
|
64
|
+
startDate: event.timestamp,
|
|
65
|
+
lastActivityDate: event.timestamp,
|
|
66
|
+
completionDate: null,
|
|
67
|
+
confidence: {
|
|
68
|
+
purpose: event.payload.description ? 0.3 : 0,
|
|
69
|
+
techStack: 0,
|
|
70
|
+
completion: 0,
|
|
71
|
+
},
|
|
72
|
+
rawData: {
|
|
73
|
+
description: event.payload.description,
|
|
74
|
+
readme: null,
|
|
75
|
+
languages: {},
|
|
76
|
+
packageFiles: [],
|
|
77
|
+
},
|
|
78
|
+
portfolioStatus: 'NONE',
|
|
79
|
+
portfolioDraft: null,
|
|
80
|
+
createdAt: now,
|
|
81
|
+
updatedAt: now,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
createProjectFromPush(event) {
|
|
85
|
+
const now = new Date();
|
|
86
|
+
return {
|
|
87
|
+
id: event.repo.id,
|
|
88
|
+
name: event.repo.name,
|
|
89
|
+
displayName: this.humanizeName(event.repo.name),
|
|
90
|
+
owner: event.repo.owner,
|
|
91
|
+
url: event.repo.url,
|
|
92
|
+
status: 'ACTIVE',
|
|
93
|
+
isPrivate: false,
|
|
94
|
+
purpose: null,
|
|
95
|
+
techStack: [],
|
|
96
|
+
topics: [],
|
|
97
|
+
startDate: event.timestamp,
|
|
98
|
+
lastActivityDate: event.timestamp,
|
|
99
|
+
completionDate: null,
|
|
100
|
+
confidence: {
|
|
101
|
+
purpose: 0,
|
|
102
|
+
techStack: 0,
|
|
103
|
+
completion: 0,
|
|
104
|
+
},
|
|
105
|
+
rawData: {
|
|
106
|
+
description: null,
|
|
107
|
+
readme: null,
|
|
108
|
+
languages: {},
|
|
109
|
+
packageFiles: [],
|
|
110
|
+
},
|
|
111
|
+
portfolioStatus: 'NONE',
|
|
112
|
+
portfolioDraft: null,
|
|
113
|
+
createdAt: now,
|
|
114
|
+
updatedAt: now,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
humanizeName(name) {
|
|
118
|
+
// Convert kebab-case or snake_case to Title Case
|
|
119
|
+
return name
|
|
120
|
+
.replace(/[-_]/g, ' ')
|
|
121
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
122
|
+
.split(' ')
|
|
123
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
124
|
+
.join(' ');
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=project-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-detector.js","sourceRoot":"","sources":["../../src/inference/project-detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub API client wrapper using Octokit.
|
|
3
|
+
* Provides typed access to repository data and events.
|
|
4
|
+
*/
|
|
5
|
+
import type { PackageFileInfo } from '../events/types.js';
|
|
6
|
+
export interface GitHubRepoData {
|
|
7
|
+
id: number;
|
|
8
|
+
name: string;
|
|
9
|
+
fullName: string;
|
|
10
|
+
owner: string;
|
|
11
|
+
url: string;
|
|
12
|
+
description: string | null;
|
|
13
|
+
topics: string[];
|
|
14
|
+
isPrivate: boolean;
|
|
15
|
+
isArchived: boolean;
|
|
16
|
+
defaultBranch: string;
|
|
17
|
+
createdAt: Date;
|
|
18
|
+
updatedAt: Date;
|
|
19
|
+
pushedAt: Date | null;
|
|
20
|
+
starCount: number;
|
|
21
|
+
forkCount: number;
|
|
22
|
+
}
|
|
23
|
+
export interface GitHubEnrichmentData {
|
|
24
|
+
languages: Record<string, number>;
|
|
25
|
+
readme: string | null;
|
|
26
|
+
packageFiles: PackageFileInfo[];
|
|
27
|
+
}
|
|
28
|
+
export declare class GitHubClient {
|
|
29
|
+
private octokit;
|
|
30
|
+
private username;
|
|
31
|
+
constructor(token: string, username: string);
|
|
32
|
+
/**
|
|
33
|
+
* Fetch all repositories for the configured user
|
|
34
|
+
*/
|
|
35
|
+
listUserRepos(): Promise<GitHubRepoData[]>;
|
|
36
|
+
/**
|
|
37
|
+
* Get detailed repo info including topics
|
|
38
|
+
*/
|
|
39
|
+
getRepo(owner: string, repo: string): Promise<GitHubRepoData>;
|
|
40
|
+
/**
|
|
41
|
+
* Fetch enrichment data: languages, readme, package files
|
|
42
|
+
*/
|
|
43
|
+
getEnrichmentData(owner: string, repo: string): Promise<GitHubEnrichmentData>;
|
|
44
|
+
private getLanguages;
|
|
45
|
+
private getReadme;
|
|
46
|
+
private getPackageFiles;
|
|
47
|
+
private parsePackageFile;
|
|
48
|
+
/**
|
|
49
|
+
* Get recent commits for activity tracking
|
|
50
|
+
*/
|
|
51
|
+
getRecentCommits(owner: string, repo: string, since?: Date): Promise<{
|
|
52
|
+
sha: string;
|
|
53
|
+
date: Date;
|
|
54
|
+
}[]>;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=github-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-client.d.ts","sourceRoot":"","sources":["../../src/ingestion/github-client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D,MAAM,WAAW,cAAc;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACjC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,YAAY,EAAE,eAAe,EAAE,CAAC;CACnC;AAED,qBAAa,YAAY;IACrB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,QAAQ,CAAS;gBAEb,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAK3C;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAgChD;;OAEG;IACG,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAsBnE;;OAEG;IACG,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;YAUrE,YAAY;YASZ,SAAS;YAWT,eAAe;IA0C7B,OAAO,CAAC,gBAAgB;IAqDxB;;OAEG;IACG,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,IAAI,CAAA;KAAE,EAAE,CAAC;CAqB5G"}
|